diff options
32 files changed, 4632 insertions, 877 deletions
| @@ -118,6 +118,7 @@ LIBS += disk/libdisk.a  LIBS += rtc/librtc.a  LIBS += dtt/libdtt.a  LIBS += drivers/libdrivers.a +LIBS += drivers/nand/libnand.a  LIBS += drivers/sk98lin/libsk98lin.a  LIBS += post/libpost.a post/cpu/libcpu.a  LIBS += common/libcommon.a @@ -1391,6 +1392,17 @@ mx1ads_config	:	unconfig  mx1fs2_config	:	unconfig  	@./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  	@./mkconfig $(@:_config=) arm arm925t omap1510inn diff --git a/board/netstar/Makefile b/board/netstar/Makefile new file mode 100644 index 000000000..8ef21893e --- /dev/null +++ b/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 + +######################################################################### diff --git a/board/netstar/config.mk b/board/netstar/config.mk new file mode 100644 index 000000000..8b73e9759 --- /dev/null +++ b/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 diff --git a/board/netstar/crcek.S b/board/netstar/crcek.S new file mode 100644 index 000000000..6ca4d11df --- /dev/null +++ b/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 diff --git a/board/netstar/crcek.h b/board/netstar/crcek.h new file mode 100644 index 000000000..30c08602f --- /dev/null +++ b/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) diff --git a/board/netstar/crcit.c b/board/netstar/crcit.c new file mode 100644 index 000000000..f6d3066c1 --- /dev/null +++ b/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; +} diff --git a/board/netstar/eeprom.c b/board/netstar/eeprom.c new file mode 100644 index 000000000..fef3822aa --- /dev/null +++ b/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; +} diff --git a/board/netstar/eeprom.lds b/board/netstar/eeprom.lds new file mode 100644 index 000000000..317550dba --- /dev/null +++ b/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 = .; +} diff --git a/board/netstar/eeprom_start.S b/board/netstar/eeprom_start.S new file mode 100644 index 000000000..75d9f0558 --- /dev/null +++ b/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 diff --git a/board/netstar/flash.c b/board/netstar/flash.c new file mode 100644 index 000000000..f555c0c00 --- /dev/null +++ b/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 diff --git a/board/netstar/nand.c b/board/netstar/nand.c new file mode 100644 index 000000000..e5b7f3346 --- /dev/null +++ b/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 diff --git a/board/netstar/netstar.c b/board/netstar/netstar.c new file mode 100644 index 000000000..62615e5c5 --- /dev/null +++ b/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; +} diff --git a/board/netstar/setup.S b/board/netstar/setup.S new file mode 100644 index 000000000..82c034235 --- /dev/null +++ b/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 diff --git a/board/netstar/u-boot.lds b/board/netstar/u-boot.lds new file mode 100644 index 000000000..8317f72d0 --- /dev/null +++ b/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 = .; +} diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 7ab6e9ca7..bc63f0c49 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -99,6 +99,10 @@  #include <cramfs/cramfs_fs.h> +#ifdef CONFIG_NEW_NAND_CODE +#include <nand.h> +#endif +  /* enable/disable debugging messages */  #define	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)  	/* 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) {  		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); +#endif  	list_del(&part->link);  	free(part);  	dev->num_parts--; @@ -445,7 +449,9 @@ static void part_delall(struct list_head *head)  	list_for_each_safe(entry, n, head) {  		part_tmp = list_entry(entry, struct part_info, link); +#ifndef CONFIG_NEW_NAND_CODE  		jffs2_free_cache(part_tmp); +#endif  		list_del(entry);  		free(part_tmp);  	} @@ -661,6 +667,7 @@ static int device_validate(u8 type, u8 num, u32 *size)  		if (num < CFG_MAX_FLASH_BANKS) {  			extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];  			*size = flash_info[num].size; +  			return 0;  		} @@ -672,8 +679,12 @@ static int device_validate(u8 type, u8 num, u32 *size)  	} else if (type == MTD_DEV_TYPE_NAND) {  #if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)  		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];  			*size = nand_dev_desc[num].totlen; +#endif  			return 0;  		} diff --git a/common/cmd_nand.c b/common/cmd_nand.c index ae4c68ac1..0c0525585 100644 --- a/common/cmd_nand.c +++ b/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> - -#if (CONFIG_COMMANDS & CFG_CMD_NAND) -  #include <command.h> -#include <watchdog.h>  #include <malloc.h> -#include <asm/byteorder.h> +#include <asm/io.h> +#include <watchdog.h>  #ifdef CONFIG_SHOW_BOOT_PROGRESS  # include <status_led.h> @@ -18,311 +21,290 @@  # 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; -} +#if (CONFIG_COMMANDS & CFG_CMD_NAND) && !defined CONFIG_NEW_NAND_CODE -static int nand_dump(nand_info_t *nand, ulong off) -{ -	int i; -	u_char *buf, *p; +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ids.h> +#include <jffs2/jffs2.h> -	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); +#ifdef CONFIG_OMAP1510 +void archflashwp(void *archdata, int wp); +#endif -	return 0; -} +#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1))) -/* ------------------------------------------------------------------------- */ +/* + * 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}; -static void -arg_off_size(int argc, char *argv[], ulong *off, ulong *size, ulong totsize) -{ -	*off = 0; -	*size = 0; +#undef	NAND_DEBUG +#undef	PSYCHO_DEBUG -#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; +/* ****************** 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 (argc >= 2) -			partstr = argv[1]; -		else -			partstr = getenv("partition"); +#define CONFIG_MTD_NAND_ECC  /* enable ECC */ +#define CONFIG_MTD_NAND_ECC_JFFS2 -		if (partstr) -			part_num = (int)simple_strtoul(partstr, NULL, 10); -		else -			part_num = 0; +/* 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 -		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 -	{ -		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; - -	/* at least two arguments please */ -	if (argc < 2) -		goto usage; +    int rcode = 0; -	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; -	} -	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;  		} -		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; -	} - -	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; -	} -	if (strcmp(cmd, "erase") == 0 -#ifdef CONFIG_MTD_NAND_UNSAFE -	    || strcmp(cmd, "scrub") == 0 -#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); -#ifdef CONFIG_MTD_NAND_UNSAFE -		i = strcmp(cmd, "scrub") == 0;	/* 1 scrub, 0 = erase */ -#endif +		printf ("\nDevice %d: ", dev); +		if (dev >= CFG_MAX_NAND_DEVICE) { +			puts ("unknown device\n"); +			return 1; +		} +		nand_print(&nand_dev_desc[dev]); +		/*nand_print (dev);*/ -		arg_off_size(argc - 2, argv + 2, &off, &size, nand->size); -		if (off == 0 && size == 0) +		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {  			return 1; +		} -		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); +		curr_device = dev; -#ifdef CONFIG_MTD_NAND_UNSAFE -		if (i) -			ret = nand_scrub(nand, off, size); -		else -#endif -			ret = nand_erase(nand, off, size); - -		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); +	printf ("Usage:\n%s\n", cmdtp->usage); +	return 1; +    default: +	/* at least 4 args */ -		arg_off_size(argc - 3, argv + 3, &off, &size, nand->size); -		if (off == 0 && size == 0) +	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; +		} -		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", -	"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"  	"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"); +	"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 *ep;  	int dev; -	int r; -	ulong addr, cnt, offset = 0; +	ulong cnt; +	ulong addr; +	ulong offset = 0;  	image_header_t *hdr; -	nand_info_t *nand; - +	int rcode = 0;  	switch (argc) {  	case 1:  		addr = CFG_LOAD_ADDR; -		boot_device = getenv("bootdevice"); +		boot_device = getenv ("bootdevice");  		break;  	case 2:  		addr = simple_strtoul(argv[1], NULL, 16); -		boot_device = getenv("bootdevice"); +		boot_device = getenv ("bootdevice");  		break;  	case 3:  		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);  		break;  	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;  	}  	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;  	}  	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;  	} -	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;  	} -	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;  	} @@ -389,24 +373,1526 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	load_addr = addr;  	/* 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]; -		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[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; + +	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;  } -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) */ diff --git a/common/cmd_nand_new.c b/common/cmd_nand_new.c new file mode 100644 index 000000000..3ff2ebaf6 --- /dev/null +++ b/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) */ diff --git a/cpu/arm925t/config.mk b/cpu/arm925t/config.mk index cef7d26f1..960df4c98 100644 --- a/cpu/arm925t/config.mk +++ b/cpu/arm925t/config.mk @@ -22,6 +22,6 @@  #  PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \ -	-mshort-load-bytes -msoft-float +	-msoft-float  PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4 diff --git a/drivers/nand/Makefile b/drivers/nand/Makefile index 3906bf951..96f67dfca 100644 --- a/drivers/nand/Makefile +++ b/drivers/nand/Makefile @@ -14,4 +14,3 @@ $(LIB):	$(OBJS)  		$(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@  sinclude .depend - diff --git a/drivers/nand/diskonchip.c b/drivers/nand/diskonchip.c index 02135c3ac..b421d4c1c 100644 --- a/drivers/nand/diskonchip.c +++ b/drivers/nand/diskonchip.c @@ -1,4 +1,4 @@ -/*  +/*   * drivers/mtd/nand/diskonchip.c   *   * (C) 2003 Red Hat, Inc. @@ -8,12 +8,12 @@   * Author: David Woodhouse <dwmw2@infradead.org>   * Additional Diskonchip 2000 and Millennium support by Dan Brown <dan_brown@ieee.org>   * Diskonchip Millennium Plus support by Kalev Lember <kalev@smartlink.ee> - *  + *   * 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.   * converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de> - *   + *   * Interface to generic NAND code for M-Systems DiskOnChip devices   *   * $Id: diskonchip.c,v 1.45 2005/01/05 18:05:14 dwmw2 Exp $ @@ -42,25 +42,25 @@  static unsigned long __initdata doc_locations[] = {  #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__)  #ifdef CONFIG_MTD_DISKONCHIP_PROBE_HIGH -	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,  +	0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000,  	0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, -	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000,  -	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,  +	0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, +	0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000,  	0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000,  #else /*  CONFIG_MTD_DOCPROBE_HIGH */ -	0xc8000, 0xca000, 0xcc000, 0xce000,  +	0xc8000, 0xca000, 0xcc000, 0xce000,  	0xd0000, 0xd2000, 0xd4000, 0xd6000, -	0xd8000, 0xda000, 0xdc000, 0xde000,  -	0xe0000, 0xe2000, 0xe4000, 0xe6000,  +	0xd8000, 0xda000, 0xdc000, 0xde000, +	0xe0000, 0xe2000, 0xe4000, 0xe6000,  	0xe8000, 0xea000, 0xec000, 0xee000,  #endif /*  CONFIG_MTD_DOCPROBE_HIGH */  #elif defined(__PPC__)  	0xe4000000,  #elif defined(CONFIG_MOMENCO_OCELOT)  	0x2f000000, -        0xff000000, +	0xff000000,  #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) -        0xff000000, +	0xff000000,  ##else  #warning Unknown architecture for DiskOnChip. No default probe locations defined  #endif @@ -142,7 +142,7 @@ MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe  /* the Reed Solomon control structure */  static struct rs_control *rs_decoder; -/*  +/*   * 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   * 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 */  	for (i = 0; i < NROOTS; i++)  		s[i] = ds[0]; -	/*  -	 *  Evaluate  +	/* +	 *  Evaluate  	 *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]  	 *  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)  		return nerr; -	/*  +	/*  	 * Correct the errors. The bitpositions are a bit of magic,  	 * but they are given by the design of the de/encoder circuit  	 * 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 */  			index = (pos >> 3) ^ 1;  			bitpos = pos & 7; -			if ((index >= 0 && index < SECTOR_SIZE) ||  +			if ((index >= 0 && index < SECTOR_SIZE) ||  			    index == (SECTOR_SIZE + 1)) {  				val = (uint8_t) (errval[i] >> (2 + bitpos));  				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;  			if (bitpos == 0)  				bitpos = 8; -			if ((index >= 0 && index < SECTOR_SIZE) ||  +			if ((index >= 0 && index < SECTOR_SIZE) ||  			    index == (SECTOR_SIZE + 1)) {  				val = (uint8_t)(errval[i] << (8 - bitpos));  				parity ^= val; @@ -237,7 +237,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)  {  	volatile char dummy;  	int i; -	 +  	for (i = 0; i < cycles; i++) {  		if (DoC_is_Millennium(doc))  			dummy = ReadDOC(doc->virtadr, NOP); @@ -246,7 +246,7 @@ static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)  		else  			dummy = ReadDOC(doc->virtadr, DOCStatus);  	} -	 +  }  #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 */  static int _DoC_WaitReady(struct doc_priv *doc)  { -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	unsigned long timeo = jiffies + (HZ * 10);  	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)  { -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int ret = 0;  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	if(debug)printk("write_byte %02x\n", datum);  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	u_char ret;  	ReadDOC(docptr, CDSNSlowIO); @@ -331,12 +331,12 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)  	return ret;  } -static void doc2000_writebuf(struct mtd_info *mtd,  +static void doc2000_writebuf(struct mtd_info *mtd,  			     const u_char *buf, int len)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	if (debug)printk("writebuf of %d bytes: ", len);  	for (i=0; i < len; i++) { @@ -347,12 +347,12 @@ static void doc2000_writebuf(struct mtd_info *mtd,  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;   	int i;  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;   	int i;  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int 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;  		}  	} -		 +  	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;  	int status; -	 +  	DoC_WaitReady(doc);  	this->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	WriteDOC(datum, docptr, CDSNSlowIO);  	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 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 */  	DoC_Delay(doc, 2);  	ReadDOC(docptr, ReadPipeInit); -	//return ReadDOC(docptr, Mil_CDSN_IO); +	/*return ReadDOC(docptr, Mil_CDSN_IO); */  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	for (i=0; i < len; i++) @@ -514,12 +514,12 @@ static void doc2001_writebuf(struct mtd_info *mtd,  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	/* Start read pipeline */ @@ -532,12 +532,12 @@ static void doc2001_readbuf(struct mtd_info *mtd,  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	/* Start read pipeline */ @@ -557,22 +557,22 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	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);  	return ret;  } -static void doc2001plus_writebuf(struct mtd_info *mtd,  +static void doc2001plus_writebuf(struct mtd_info *mtd,  			     const u_char *buf, int len)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	if (debug)printk("writebuf of %d bytes: ", len); @@ -584,12 +584,12 @@ static void doc2001plus_writebuf(struct mtd_info *mtd,  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	if (debug)printk("readbuf of %d bytes: ", len); @@ -614,12 +614,12 @@ static void doc2001plus_readbuf(struct mtd_info *mtd,  	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)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int floor = 0;  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int floor = 0;  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	switch(cmd) {  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	/*  	 * 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);  	} -	/*  +	/*  	 * program and erase have their own busy handlers  	 * 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 */  	default: -		/*  +		/*  		 * If we don't have access to the busy pin, we apply the given  		 * command delay  		*/ @@ -840,7 +840,7 @@ static int doc200x_dev_ready(struct mtd_info *mtd)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	if (DoC_is_MillenniumPlus(doc)) {  		/* 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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	/* Prime the ECC engine */  	switch(mode) { @@ -897,7 +897,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)  {  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	/* Prime the ECC engine */  	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 doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	int i;  	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++) {  		if (DoC_is_MillenniumPlus(doc))  			ecc_code[i] = ReadDOC_(docptr, DoC_Mplus_ECCSyndrome0 + i); -		else  +		else  			ecc_code[i] = ReadDOC_(docptr, DoC_ECCSyndrome0 + i);  		if (ecc_code[i] != empty_write_ecc[i])  			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;  	struct nand_chip *this = mtd->priv;  	struct doc_priv *doc = this->priv; -        void __iomem *docptr = doc->virtadr; +	void __iomem *docptr = doc->virtadr;  	volatile u_char dummy;  	int emptymatch = 1; -	 +  	/* flush the pipeline */  	if (DoC_is_2000(doc)) {  		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);  	} -	 +  	/* Error occured ? */  	if (dummy & 0x80) {  		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 (ret > 0)  			printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret); -	}	 +	}  	if (DoC_is_MillenniumPlus(doc))  		WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);  	else @@ -1043,16 +1043,16 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_  	}  	return ret;  } -		 -//u_char mydatabuf[528]; + +/*u_char mydatabuf[528]; */  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.     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 @@ -1068,7 +1068,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,  	int ret;  	size_t retlen; -	end = min(end, mtd->size); // paranoia +	end = min(end, mtd->size); /* paranoia */  	for (offs = 0; offs < end; offs += mtd->erasesize) {  		ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);  		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;  	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"  			 "    NumEraseUnits    = %d\n"  			 "    FirstPhysicalEUN = %d\n" @@ -1132,7 +1132,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,  		mh->DataOrgID, mh->NumEraseUnits,  		mh->FirstPhysicalEUN, mh->FormattedSize,  		mh->UnitSizeFactor); -//#endif +/*#endif */  	blocks = mtd->size >> this->phys_erase_shift;  	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 += 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].offset = offs; @@ -1232,9 +1232,9 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,  	mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);  	mh->FormatFlags = le32_to_cpu(mh->FormatFlags);  	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"  			 "    NoOfBootImageBlocks   = %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)[3] & 0xf,  		mh->PercentUsed); -//#endif +/*#endif */  	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->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"  			"        virtualUnits    = %d\n"  			"        firstUnit       = %d\n" @@ -1289,7 +1289,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd,  			i, ip->virtualUnits, ip->firstUnit,  			ip->lastUnit, ip->flags,  			ip->spareUnits); -//#endif +/*#endif */  /*  		if ((i == 0) && (ip->firstUnit > 0)) { @@ -1456,7 +1456,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd)  	ReadDOC(doc->virtadr, ChipID);  	if (ReadDOC(doc->virtadr, ChipID) != DOC_ChipID_DocMil) {  		/* 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  		   can have multiple chips. */  		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  	 * 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 -	 * found it.  +	 * found it.  	 */  	save_control = ReadDOC(virtadr, DOCControl);  	/* 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); -	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,  +	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,  		 virtadr, DOCControl);  	/* 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); -	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,  +	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,  		 virtadr, DOCControl);  	ChipID = ReadDOC(virtadr, ChipID); @@ -1614,11 +1614,11 @@ static inline int __init doc_probe(unsigned long physadr)  		if (ChipID == DOC_ChipID_DocMilPlus16) {  			WriteDOC(~newval, virtadr, Mplus_AliasResolution);  			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution); -			WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it +			WriteDOC(newval, virtadr, Mplus_AliasResolution); /* restore it */  		} else {  			WriteDOC(~newval, virtadr, AliasResolution);  			oldval = ReadDOC(doc->virtadr, AliasResolution); -			WriteDOC(newval, virtadr, AliasResolution); // restore it +			WriteDOC(newval, virtadr, AliasResolution); /* restore it */  		}  		newval = ~newval;  		if (oldval == newval) { @@ -1726,7 +1726,7 @@ static int __init init_nanddoc(void)  	int i, ret = 0;  	/* 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)  	 * Primitve polynomial is x^10+x^3+1 diff --git a/drivers/nand/nand_base.c b/drivers/nand/nand_base.c index c423512f1..a7ab8c27a 100644 --- a/drivers/nand/nand_base.c +++ b/drivers/nand/nand_base.c @@ -5,14 +5,14 @@   *   This is the generic MTD driver for NAND flash devices. It should be   *   capable of working with almost all NAND chips currently available.   *   Basic support for AG-AND chips is provided. - *    + *   *	Additional technical information is available on   *	http://www.linux-mtd.infradead.org/tech/nand.html - *	 + *   *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)   * 		  2002 Thomas Gleixner (tglx@linutronix.de)   * - *  02-08-2004  tglx: support for strange chips, which cannot auto increment  + *  02-08-2004  tglx: support for strange chips, which cannot auto increment   *		pages on read / read_oob   *   *  03-17-2004  tglx: Check ready before auto increment check. Simon Bayes @@ -21,7 +21,7 @@   *		Make reads over block boundaries work too   *   *  04-14-2004	tglx: first working version for 2k page size chips - *   + *   *  05-19-2004  tglx: Basic support for Renesas AG-AND chips   *   *  09-24-2004  tglx: add support for hardware controllers (e.g. ECC) shared @@ -29,8 +29,8 @@   *		from Ben Dooks <ben-mtd@fluff.org>   *   * Credits: - *	David Woodhouse for adding multichip support   - *	 + *	David Woodhouse for adding multichip support + *   *	Aleph One Ltd. and Toby Churchill Ltd. for supporting the   *	rework for 2K page size chips   * @@ -68,7 +68,7 @@  #include <linux/mtd/partitions.h>  #endif -#else +#endif  #include <common.h> @@ -88,8 +88,6 @@  #include <jffs2/jffs2.h>  #endif -#endif -  /* Define default oob placement schemes for large and small page devices */  static struct nand_oobinfo nand_oob_8 = {  	.useecc = MTD_NANDECC_AUTOPLACE, @@ -109,8 +107,8 @@ static struct nand_oobinfo nand_oob_64 = {  	.useecc = MTD_NANDECC_AUTOPLACE,  	.eccbytes = 24,  	.eccpos = { -		40, 41, 42, 43, 44, 45, 46, 47,  -		48, 49, 50, 51, 52, 53, 54, 55,  +		40, 41, 42, 43, 44, 45, 46, 47, +		48, 49, 50, 51, 52, 53, 54, 55,  		56, 57, 58, 59, 60, 61, 62, 63},  	.oobfree = { {2, 38} }  }; @@ -156,19 +154,19 @@ static void nand_sync (struct mtd_info *mtd);  static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,  		struct nand_oobinfo *oobsel, int mode);  #ifdef CONFIG_MTD_NAND_VERIFY_WRITE -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,  +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,  	u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode);  #else  #define nand_verify_pages(...) (0)  #endif -		 +  static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state);  /**   * nand_release_device - [GENERIC] release chip   * @mtd:	MTD device structure - *  - * Deselect, release chip lock and wake up anyone waiting on the device  + * + * Deselect, release chip lock and wake up anyone waiting on the device   */  /* XXX U-BOOT XXX */  #if 0 @@ -223,7 +221,7 @@ static void nand_write_byte(struct mtd_info *mtd, u_char byte)   * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip   * @mtd:	MTD device structure   * - * Default read function for 16bit buswith with  + * Default read function for 16bit buswith with   * endianess conversion   */  static u_char nand_read_byte16(struct mtd_info *mtd) @@ -250,7 +248,7 @@ static void nand_write_byte16(struct mtd_info *mtd, u_char byte)   * nand_read_word - [DEFAULT] read one word from the chip   * @mtd:	MTD device structure   * - * Default read function for 16bit buswith without  + * Default read function for 16bit buswith without   * endianess conversion   */  static u16 nand_read_word(struct mtd_info *mtd) @@ -264,7 +262,7 @@ static u16 nand_read_word(struct mtd_info *mtd)   * @mtd:	MTD device structure   * @word:	data word to write   * - * Default write function for 16bit buswith without  + * Default write function for 16bit buswith without   * endianess conversion   */  static void nand_write_word(struct mtd_info *mtd, u16 word) @@ -285,7 +283,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chip)  	struct nand_chip *this = mtd->priv;  	switch(chip) {  	case -1: -		this->hwcontrol(mtd, NAND_CTL_CLRNCE);	 +		this->hwcontrol(mtd, NAND_CTL_CLRNCE);  		break;  	case 0:  		this->hwcontrol(mtd, NAND_CTL_SETNCE); @@ -314,7 +312,7 @@ static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)  }  /** - * nand_read_buf - [DEFAULT] read chip data into buffer  + * nand_read_buf - [DEFAULT] read chip data into buffer   * @mtd:	MTD device structure   * @buf:	buffer to store date   * @len:	number of bytes to read @@ -331,7 +329,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)  }  /** - * nand_verify_buf - [DEFAULT] Verify chip data against buffer  + * nand_verify_buf - [DEFAULT] Verify chip data against buffer   * @mtd:	MTD device structure   * @buf:	buffer containing the data to compare   * @len:	number of bytes to compare @@ -364,14 +362,14 @@ static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)  	struct nand_chip *this = mtd->priv;  	u16 *p = (u16 *) buf;  	len >>= 1; -	 +  	for (i=0; i<len; i++)  		writew(p[i], this->IO_ADDR_W); -		 +  }  /** - * nand_read_buf16 - [DEFAULT] read chip data into buffer  + * nand_read_buf16 - [DEFAULT] read chip data into buffer   * @mtd:	MTD device structure   * @buf:	buffer to store date   * @len:	number of bytes to read @@ -390,7 +388,7 @@ static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)  }  /** - * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer  + * nand_verify_buf16 - [DEFAULT] Verify chip data against buffer   * @mtd:	MTD device structure   * @buf:	buffer containing the data to compare   * @len:	number of bytes to compare @@ -417,7 +415,7 @@ static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)   * @ofs:	offset from device start   * @getchip:	0, if the chip is already selected   * - * Check, if the block is bad.  + * Check, if the block is bad.   */  static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  { @@ -434,8 +432,8 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  		/* Select the NAND device */  		this->select_chip(mtd, chipnr); -	} else  -		page = (int) ofs;	 +	} else +		page = (int) ofs;  	if (this->options & NAND_BUSWIDTH_16) {  		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask); @@ -449,12 +447,12 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)  		if (this->read_byte(mtd) != 0xff)  			res = 1;  	} -		 +  	if (getchip) {  		/* Deselect and wake up anyone waiting on the device */  		nand_release_device(mtd); -	}	 -	 +	} +  	return res;  } @@ -472,7 +470,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)  	u_char buf[2] = {0, 0};  	size_t	retlen;  	int block; -	 +  	/* Get block number */  	block = ((int) ofs) >> this->bbt_erase_shift;  	this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); @@ -480,25 +478,25 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)  	/* Do we have a flash based bad block table ? */  	if (this->options & NAND_USE_FLASH_BBT)  		return nand_update_bbt (mtd, ofs); -		 +  	/* We write two bytes, so we dont have to mess with 16 bit access */  	ofs += mtd->oobsize + (this->badblockpos & ~0x01);  	return nand_write_oob (mtd, ofs , 2, &retlen, buf);  } -/**  +/**   * nand_check_wp - [GENERIC] check if the chip is write protected   * @mtd:	MTD device structure - * Check, if the device is write protected  + * Check, if the device is write protected   * - * The function expects, that the device is already selected  + * The function expects, that the device is already selected   */  static int nand_check_wp (struct mtd_info *mtd)  {  	struct nand_chip *this = mtd->priv;  	/* Check the WP bit */  	this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -	return (this->read_byte(mtd) & 0x80) ? 0 : 1;  +	return (this->read_byte(mtd) & 0x80) ? 0 : 1;  }  /** @@ -514,10 +512,10 @@ static int nand_check_wp (struct mtd_info *mtd)  static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)  {  	struct nand_chip *this = mtd->priv; -	 +  	if (!this->bbt)  		return this->block_bad(mtd, ofs, getchip); -	 +  	/* Return info from the table */  	return nand_isbad_bbt (mtd, ofs, allowbbt);  } @@ -582,13 +580,13 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in  		/* Latch in address */  		this->hwcontrol(mtd, NAND_CTL_CLRALE);  	} -	 -	/*  -	 * program and erase have their own busy handlers  + +	/* +	 * program and erase have their own busy handlers  	 * status and sequential in needs no delay  	*/  	switch (command) { -			 +  	case NAND_CMD_PAGEPROG:  	case NAND_CMD_ERASE1:  	case NAND_CMD_ERASE2: @@ -597,7 +595,7 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in  		return;  	case NAND_CMD_RESET: -		if (this->dev_ready)	 +		if (this->dev_ready)  			break;  		udelay(this->chip_delay);  		this->hwcontrol(mtd, NAND_CTL_SETCLE); @@ -606,18 +604,18 @@ static void nand_command (struct mtd_info *mtd, unsigned command, int column, in  		while ( !(this->read_byte(mtd) & 0x40));  		return; -	/* This applies to read commands */	 +	/* This applies to read commands */  	default: -		/*  +		/*  		 * If we don't have access to the busy pin, we apply the given  		 * command delay  		*/  		if (!this->dev_ready) {  			udelay (this->chip_delay);  			return; -		}	 +		}  	} -	 +  	/* Apply this short delay always to ensure that we do wait tWB in  	 * any case on any machine. */  	ndelay (100); @@ -646,8 +644,8 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,  		column += mtd->oobblock;  		command = NAND_CMD_READ0;  	} -	 -		 + +  	/* Begin command latch cycle */  	this->hwcontrol(mtd, NAND_CTL_SETCLE);  	/* Write out the command to the device. */ @@ -665,7 +663,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,  				column >>= 1;  			this->write_byte(mtd, column & 0xff);  			this->write_byte(mtd, column >> 8); -		}	 +		}  		if (page_addr != -1) {  			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));  			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); @@ -676,13 +674,13 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,  		/* Latch in address */  		this->hwcontrol(mtd, NAND_CTL_CLRALE);  	} -	 -	/*  -	 * program and erase have their own busy handlers  + +	/* +	 * program and erase have their own busy handlers  	 * status and sequential in needs no delay  	*/  	switch (command) { -			 +  	case NAND_CMD_CACHEDPROG:  	case NAND_CMD_PAGEPROG:  	case NAND_CMD_ERASE1: @@ -693,7 +691,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,  	case NAND_CMD_RESET: -		if (this->dev_ready)	 +		if (this->dev_ready)  			break;  		udelay(this->chip_delay);  		this->hwcontrol(mtd, NAND_CTL_SETCLE); @@ -710,19 +708,19 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,  		/* End command latch cycle */  		this->hwcontrol(mtd, NAND_CTL_CLRCLE);  		/* Fall through into ready check */ -		 -	/* This applies to read commands */	 + +	/* This applies to read commands */  	default: -		/*  +		/*  		 * If we don't have access to the busy pin, we apply the given  		 * command delay  		*/  		if (!this->dev_ready) {  			udelay (this->chip_delay);  			return; -		}	 +		}  	} -	 +  	/* Apply this short delay always to ensure that we do wait tWB in  	 * any case on any machine. */  	ndelay (100); @@ -734,7 +732,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column,   * nand_get_device - [GENERIC] Get chip for selected access   * @this:	the nand chip descriptor   * @mtd:	MTD device structure - * @new_state:	the state which is requested  + * @new_state:	the state which is requested   *   * Get the device and lock it for exclusive access   */ @@ -746,8 +744,8 @@ static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int n  	DECLARE_WAITQUEUE (wait, current); -	/*  -	 * Grab the lock and see if the device is available  +	/* +	 * Grab the lock and see if the device is available  	*/  retry:  	/* Hardware controller shared among independend devices */ @@ -759,7 +757,7 @@ retry:  			this->controller->active = this;  		spin_unlock (&this->controller->lock);  	} -	 +  	if (active == this) {  		spin_lock (&this->chip_lock);  		if (this->state == FL_READY) { @@ -767,7 +765,7 @@ retry:  			spin_unlock (&this->chip_lock);  			return;  		} -	}	 +	}  	set_current_state (TASK_UNINTERRUPTIBLE);  	add_wait_queue (&active->wq, &wait);  	spin_unlock (&active->chip_lock); @@ -786,7 +784,7 @@ static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int n   * @state:	state to select the max. timeout value   *   * Wait for command done. This applies to erase and program only - * Erase can take up to 400ms and program up to 20ms according to  + * Erase can take up to 400ms and program up to 20ms according to   * general NAND and SmartMedia specs   *  */ @@ -796,7 +794,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)  {  	unsigned long	timeo = jiffies;  	int	status; -	 +  	if (state == FL_ERASING)  		 timeo += (HZ * 400) / 1000;  	else @@ -808,17 +806,17 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)  	if ((state == FL_ERASING) && (this->options & NAND_IS_AND))  		this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); -	else	 +	else  		this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); -	while (time_before(jiffies, timeo)) {		 +	while (time_before(jiffies, timeo)) {  		/* Check, if we were interrupted */  		if (this->state != state)  			return 0;  		if (this->dev_ready) {  			if (this->dev_ready(mtd)) -				break;	 +				break;  		} else {  			if (this->read_byte(mtd) & NAND_STATUS_READY)  				break; @@ -853,7 +851,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)   *   * Cached programming is not supported yet.   */ -static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,  +static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,  	u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached)  {  	int 	i, status; @@ -862,10 +860,10 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa  	int  	*oob_config = oobsel->eccpos;  	int	datidx = 0, eccidx = 0, eccsteps = this->eccsteps;  	int	eccbytes = 0; -	 +  	/* FIXME: Enable cached programming */  	cached = 0; -	 +  	/* Send command to begin auto page programming */  	this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); @@ -876,7 +874,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa  		printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");  		this->write_buf(mtd, this->data_poi, mtd->oobblock);  		break; -		 +  	/* Software ecc 3/256, write all */  	case NAND_ECC_SOFT:  		for (; eccsteps; eccsteps--) { @@ -905,11 +903,11 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa  		}  		break;  	} -										 +  	/* Write out OOB data */  	if (this->options & NAND_HWECC_SYNDROME)  		this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes); -	else  +	else  		this->write_buf(mtd, oob_buf, mtd->oobsize);  	/* Send command to actually program the data */ @@ -926,9 +924,9 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa  	} else {  		/* FIXME: Implement cached programming ! */  		/* wait until cache is ready*/ -		// status = this->waitfunc (mtd, this, FL_CACHEDRPG); +		/* status = this->waitfunc (mtd, this, FL_CACHEDRPG); */  	} -	return 0;	 +	return 0;  }  #ifdef CONFIG_MTD_NAND_VERIFY_WRITE @@ -944,19 +942,19 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa   * @oobmode:	1 = full buffer verify, 0 = ecc only   *   * 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  + * 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  + * 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.   */ -static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,  +static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,  	u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)  {  	int 	i, j, datidx = 0, oobofs = 0, res = -EIO;  	int	eccsteps = this->eccsteps; -	int	hweccbytes;  +	int	hweccbytes;  	u_char 	oobdata[64];  	hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0; @@ -996,7 +994,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int  			if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {  				int ecccnt = oobsel->eccbytes; -		 +  				for (i = 0; i < ecccnt; i++) {  					int idx = oobsel->eccpos[i];  					if (oobdata[idx] != oob_buf[oobofs + idx] ) { @@ -1006,38 +1004,38 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int  						goto out;  					}  				} -			}	 +			}  		}  		oobofs += mtd->oobsize - hweccbytes * eccsteps;  		page++;  		numpages--; -		/* Apply delay or wait for ready/busy pin  +		/* Apply delay or wait for ready/busy pin  		 * Do this before the AUTOINCR check, so no problems  		 * arise if a chip which does auto increment  		 * is marked as NOAUTOINCR by the board driver.  		 * Do this also before returning, so the chip is  		 * ready for the next command.  		*/ -		if (!this->dev_ready)  +		if (!this->dev_ready)  			udelay (this->chip_delay);  		else -			while (!this->dev_ready(mtd));	 +			while (!this->dev_ready(mtd));  		/* All done, return happy */  		if (!numpages)  			return 0; -		 -			 -		/* Check, if the chip supports auto page increment */  + + +		/* Check, if the chip supports auto page increment */  		if (!NAND_CANAUTOINCR(this))  			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);  	} -	/*  +	/*  	 * Terminate the read command. We come here in case of an error  	 * So we must issue a reset command.  	 */ -out:	  +out:  	this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);  	return res;  } @@ -1056,7 +1054,7 @@ out:  static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)  {  	return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL); -}			    +}  /** @@ -1080,7 +1078,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  	u_char *data_poi, *oob_data = oob_buf;  	u_char ecc_calc[32];  	u_char ecc_code[32]; -        int eccmode, eccsteps; +	int eccmode, eccsteps;  	int	*oob_config, datidx;  	int	blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;  	int	eccbytes; @@ -1103,11 +1101,11 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  	/* use userspace supplied oobinfo, if zero */  	if (oobsel == NULL)  		oobsel = &mtd->oobinfo; -	 +  	/* Autoplace of oob data ? Use the default placement scheme */  	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)  		oobsel = this->autooob; -		 +  	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;  	oob_config = oobsel->eccpos; @@ -1125,28 +1123,28 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  	end = mtd->oobblock;  	ecc = this->eccsize;  	eccbytes = this->eccbytes; -	 +  	if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))  		compareecc = 0;  	oobreadlen = mtd->oobsize; -	if (this->options & NAND_HWECC_SYNDROME)  +	if (this->options & NAND_HWECC_SYNDROME)  		oobreadlen -= oobsel->eccbytes;  	/* Loop until all data read */  	while (read < len) { -		 +  		int aligned = (!col && (len - read) >= end); -		/*  +		/*  		 * If the read is not page aligned, we have to read into data buffer  		 * due to ecc, else we read into return buffer direct  		 */  		if (aligned)  			data_poi = &buf[read]; -		else  +		else  			data_poi = this->data_buf; -		 -		/* Check, if we have this page in the buffer  + +		/* Check, if we have this page in the buffer  		 *  		 * FIXME: Make it work when we must provide oob data too,  		 * check the usage of data_buf oob field @@ -1162,7 +1160,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  		if (sndcmd) {  			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);  			sndcmd = 0; -		}	 +		}  		/* get oob area, if we have no oob buffer from fs-driver */  		if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE || @@ -1170,7 +1168,7 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  			oob_data = &this->data_buf[end];  		eccsteps = this->eccsteps; -		 +  		switch (eccmode) {  		case NAND_ECC_NONE: {	/* No ECC, Read in a page */  /* XXX U-BOOT XXX */ @@ -1186,12 +1184,12 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  			this->read_buf(mtd, data_poi, end);  			break;  		} -			 +  		case NAND_ECC_SOFT:	/* Software ECC 3/256: Read in a page + oob data */  			this->read_buf(mtd, data_poi, end); -			for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)  +			for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)  				this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); -			break;	 +			break;  		default:  			for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { @@ -1209,15 +1207,15 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  					 * generator for an error, reads back the syndrome and  					 * does the error correction on the fly */  					if (this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]) == -1) { -						DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "  +						DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "  							"Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);  						ecc_failed++;  					}  				} else {  					this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); -				}	 +				}  			} -			break;						 +			break;  		}  		/* read oobdata */ @@ -1225,8 +1223,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  		/* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */  		if (!compareecc) -			goto readoob;	 -		 +			goto readoob; +  		/* Pick the ECC bytes out of the oob data */  		for (j = 0; j < oobsel->eccbytes; j++)  			ecc_code[j] = oob_data[oob_config[j]]; @@ -1234,24 +1232,24 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  		/* correct data, if neccecary */  		for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {  			ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]); -			 +  			/* Get next chunk of ecc bytes */  			j += eccbytes; -			 -			/* Check, if we have a fs supplied oob-buffer,  + +			/* Check, if we have a fs supplied oob-buffer,  			 * This is the legacy mode. Used by YAFFS1  			 * Should go away some day  			 */ -			if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {  +			if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {  				int *p = (int *)(&oob_data[mtd->oobsize]);  				p[i] = ecc_status;  			} -			 -			if (ecc_status == -1) {	 + +			if (ecc_status == -1) {  				DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);  				ecc_failed++;  			} -		}		 +		}  	readoob:  		/* check, if we have a fs supplied oob-buffer */ @@ -1278,25 +1276,25 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  		}  	readdata:  		/* Partial page read, transfer data into fs buffer */ -		if (!aligned) {  +		if (!aligned) {  			for (j = col; j < end && read < len; j++)  				buf[read++] = data_poi[j]; -			this->pagebuf = realpage;	 -		} else		 +			this->pagebuf = realpage; +		} else  			read += mtd->oobblock; -		/* Apply delay or wait for ready/busy pin  +		/* Apply delay or wait for ready/busy pin  		 * Do this before the AUTOINCR check, so no problems  		 * arise if a chip which does auto increment  		 * is marked as NOAUTOINCR by the board driver.  		*/ -		if (!this->dev_ready)  +		if (!this->dev_ready)  			udelay (this->chip_delay);  		else -			while (!this->dev_ready(mtd));	 -			 +			while (!this->dev_ready(mtd)); +  		if (read == len) -			break;	 +			break;  		/* For subsequent reads align to page boundary. */  		col = 0; @@ -1310,11 +1308,11 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,  			this->select_chip(mtd, -1);  			this->select_chip(mtd, chipnr);  		} -		/* Check, if the chip supports auto page increment  -		 * or if we have hit a block boundary.  -		*/  +		/* Check, if the chip supports auto page increment +		 * or if we have hit a block boundary. +		*/  		if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) -			sndcmd = 1;				 +			sndcmd = 1;  	}  	/* Deselect and wake up anyone waiting on the device */ @@ -1350,7 +1348,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t  	/* Shift to get page */  	page = (int)(from >> this->page_shift);  	chipnr = (int)(from >> this->chip_shift); -	 +  	/* Mask to get column */  	col = from & (mtd->oobsize - 1); @@ -1372,7 +1370,7 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t  	/* Send the read command */  	this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask); -	/*  +	/*  	 * Read the data, if we read more than one page  	 * oob data, let the device transfer the data !  	 */ @@ -1382,16 +1380,16 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t  		thislen = min_t(int, thislen, len);  		this->read_buf(mtd, &buf[i], thislen);  		i += thislen; -		 -		/* Apply delay or wait for ready/busy pin  + +		/* Apply delay or wait for ready/busy pin  		 * Do this before the AUTOINCR check, so no problems  		 * arise if a chip which does auto increment  		 * is marked as NOAUTOINCR by the board driver.  		*/ -		if (!this->dev_ready)  +		if (!this->dev_ready)  			udelay (this->chip_delay);  		else -			while (!this->dev_ready(mtd));	 +			while (!this->dev_ready(mtd));  		/* Read more ? */  		if (i < len) { @@ -1404,13 +1402,13 @@ static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t  				this->select_chip(mtd, -1);  				this->select_chip(mtd, chipnr);  			} -				 -			/* Check, if the chip supports auto page increment  -			 * or if we have hit a block boundary.  -			*/  + +			/* Check, if the chip supports auto page increment +			 * or if we have hit a block boundary. +			*/  			if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {  				/* For subsequent page reads set offset to 0 */ -			        this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask); +				this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);  			}  		}  	} @@ -1453,27 +1451,27 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,  	nand_get_device (this, mtd , FL_READING);  	this->select_chip (mtd, chip); -	 +  	/* Add requested oob length */  	len += ooblen; -	 +  	while (len) {  		if (sndcmd)  			this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask); -		sndcmd = 0;	 +		sndcmd = 0;  		this->read_buf (mtd, &buf[cnt], pagesize);  		len -= pagesize;  		cnt += pagesize;  		page++; -		 -		if (!this->dev_ready)  + +		if (!this->dev_ready)  			udelay (this->chip_delay);  		else -			while (!this->dev_ready(mtd));	 -			 -		/* Check, if the chip supports auto page increment */  +			while (!this->dev_ready(mtd)); + +		/* Check, if the chip supports auto page increment */  		if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))  			sndcmd = 1;  	} @@ -1484,8 +1482,8 @@ int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len,  } -/**  - * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer  +/** + * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer   * @mtd:	MTD device structure   * @fsbuf:	buffer given by fs driver   * @oobsel:	out of band selection structre @@ -1514,20 +1512,20 @@ static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct  	int i, len, ofs;  	/* Zero copy fs supplied buffer */ -	if (fsbuf && !autoplace)  +	if (fsbuf && !autoplace)  		return fsbuf;  	/* Check, if the buffer must be filled with ff again */ -	if (this->oobdirty) {	 -		memset (this->oob_buf, 0xff,  +	if (this->oobdirty) { +		memset (this->oob_buf, 0xff,  			mtd->oobsize << (this->phys_erase_shift - this->page_shift));  		this->oobdirty = 0; -	}	 -	 +	} +  	/* If we have no autoplacement or no fs buffer use the internal one */  	if (!autoplace || !fsbuf)  		return this->oob_buf; -	 +  	/* Walk through the pages and place the data */  	this->oobdirty = 1;  	ofs = 0; @@ -1561,7 +1559,7 @@ static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * ret  {  	return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));  } -			    +  /**   * nand_write_ecc - [MTD Interface] NAND write with ECC   * @mtd:	MTD device structure @@ -1594,7 +1592,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  		return -EINVAL;  	} -	/* reject writes, which are not page aligned */	 +	/* reject writes, which are not page aligned */  	if (NOTALIGNED (to) || NOTALIGNED(len)) {  		printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");  		return -EINVAL; @@ -1613,14 +1611,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  		goto out;  	/* if oobsel is NULL, use chip defaults */ -	if (oobsel == NULL)  -		oobsel = &mtd->oobinfo;		 -		 +	if (oobsel == NULL) +		oobsel = &mtd->oobinfo; +  	/* Autoplace of oob data ? Use the default placement scheme */  	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {  		oobsel = this->autooob;  		autoplace = 1; -	}	 +	}  	if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)  		autoplace = 1; @@ -1628,9 +1626,9 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  	totalpages = len >> this->page_shift;  	page = (int) (to >> this->page_shift);  	/* Invalidate the page cache, if we write to the cached page */ -	if (page <= this->pagebuf && this->pagebuf < (page + totalpages))   +	if (page <= this->pagebuf && this->pagebuf < (page + totalpages))  		this->pagebuf = -1; -	 +  	/* Set it relative to chip */  	page &= this->pagemask;  	startpage = page; @@ -1652,14 +1650,14 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  		if (ret) {  			DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);  			goto out; -		}	 +		}  		/* Next oob page */  		oob += mtd->oobsize;  		/* Update written bytes count */  		written += mtd->oobblock; -		if (written == len)  +		if (written == len)  			goto cmp; -		 +  		/* Increment page address */  		page++; @@ -1670,13 +1668,13 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  		if (!(page & (ppblock - 1))){  			int ofs;  			this->data_poi = bufstart; -			ret = nand_verify_pages (mtd, this, startpage,  +			ret = nand_verify_pages (mtd, this, startpage,  				page - startpage,  				oobbuf, oobsel, chipnr, (eccbuf != NULL));  			if (ret) {  				DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);  				goto out; -			}	 +			}  			*retlen = written;  			ofs = autoplace ? mtd->oobavail : mtd->oobsize; @@ -1686,7 +1684,7 @@ static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,  			numpages = min (totalpages, ppblock);  			page &= this->pagemask;  			startpage = page; -			oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,  +			oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,  					autoplace, numpages);  			/* Check, if we cross a chip boundary */  			if (!page) { @@ -1703,7 +1701,7 @@ cmp:  		oobbuf, oobsel, chipnr, (eccbuf != NULL));  	if (!ret)  		*retlen = written; -	else	 +	else  		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);  out: @@ -1763,7 +1761,7 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t *  	/* Check, if it is write protected */  	if (nand_check_wp(mtd))  		goto out; -	 +  	/* Invalidate the page cache, if we write to the cached page */  	if (page == this->pagebuf)  		this->pagebuf = -1; @@ -1827,10 +1825,10 @@ out:   *   * NAND write with kvec. This just calls the ecc function   */ -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,  +static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,  		loff_t to, size_t * retlen)  { -	return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));	 +	return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));  }  /** @@ -1845,7 +1843,7 @@ static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned   *   * NAND write with iovec with ecc   */ -static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,  +static int nand_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)  {  	int i, page, len, total_len, ret = -EIO, written = 0, chipnr; @@ -1871,7 +1869,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  		return -EINVAL;  	} -	/* reject writes, which are not page aligned */	 +	/* reject writes, which are not page aligned */  	if (NOTALIGNED (to) || NOTALIGNED(total_len)) {  		printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");  		return -EINVAL; @@ -1890,21 +1888,21 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  		goto out;  	/* if oobsel is NULL, use chip defaults */ -	if (oobsel == NULL)  -		oobsel = &mtd->oobinfo;		 +	if (oobsel == NULL) +		oobsel = &mtd->oobinfo;  	/* Autoplace of oob data ? Use the default placement scheme */  	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {  		oobsel = this->autooob;  		autoplace = 1; -	}	 +	}  	if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)  		autoplace = 1;  	/* Setup start page */  	page = (int) (to >> this->page_shift);  	/* Invalidate the page cache, if we write to the cached page */ -	if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))   +	if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))  		this->pagebuf = -1;  	startpage = page & this->pagemask; @@ -1928,10 +1926,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  			oob = 0;  			for (i = 1; i <= numpages; i++) {  				/* Write one page. If this is the last page to write -				 * then use the real pageprogram command, else select  +				 * then use the real pageprogram command, else select  				 * cached programming if supported by the chip.  				 */ -				ret = nand_write_page (mtd, this, page & this->pagemask,  +				ret = nand_write_page (mtd, this, page & this->pagemask,  					&oobbuf[oob], oobsel, i != numpages);  				if (ret)  					goto out; @@ -1947,12 +1945,12 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  				count--;  			}  		} else { -			/* We must use the internal buffer, read data out of each  +			/* We must use the internal buffer, read data out of each  			 * tuple until we have a full page to write  			 */  			int cnt = 0;  			while (cnt < mtd->oobblock) { -				if (vecs->iov_base != NULL && vecs->iov_len)  +				if (vecs->iov_base != NULL && vecs->iov_len)  					this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];  				/* Check, if we have to switch to the next tuple */  				if (len >= (int) vecs->iov_len) { @@ -1961,10 +1959,10 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  					count--;  				}  			} -			this->pagebuf = page;	 -			this->data_poi = this->data_buf;	 +			this->pagebuf = page; +			this->data_poi = this->data_buf;  			bufstart = this->data_poi; -			numpages = 1;		 +			numpages = 1;  			oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);  			ret = nand_write_page (mtd, this, page & this->pagemask,  				oobbuf, oobsel, 0); @@ -1977,7 +1975,7 @@ static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsig  		ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);  		if (ret)  			goto out; -			 +  		written += mtd->oobblock * numpages;  		/* All done ? */  		if (!count) @@ -2046,7 +2044,7 @@ static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)  {  	return nand_erase_nand (mtd, instr, 0);  } -  +  /**   * nand_erase_intern - [NAND Interface] erase block(s)   * @mtd:	MTD device structure @@ -2116,14 +2114,14 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb  			instr->state = MTD_ERASE_FAILED;  			goto erase_exit;  		} -		 -		/* Invalidate the page cache, if we erase the block which contains  + +		/* Invalidate the page cache, if we erase the block which contains  		   the current cached page */  		if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))  			this->pagebuf = -1;  		this->erase_cmd (mtd, page & this->pagemask); -		 +  		status = this->waitfunc (mtd, this, FL_ERASING);  		/* See if block erase succeeded */ @@ -2133,7 +2131,7 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb  			instr->fail_addr = (page << this->page_shift);  			goto erase_exit;  		} -		 +  		/* Increment page address and decrement length */  		len -= (1 << this->phys_erase_shift);  		page += pages_per_block; @@ -2188,9 +2186,9 @@ static void nand_sync (struct mtd_info *mtd)  static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)  {  	/* Check for invalid offset */ -	if (ofs > mtd->size)  +	if (ofs > mtd->size)  		return -EINVAL; -	 +  	return nand_block_checkbad (mtd, ofs, 1, 0);  } @@ -2204,12 +2202,12 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)  	struct nand_chip *this = mtd->priv;  	int ret; -        if ((ret = nand_block_isbad(mtd, ofs))) { -        	/* If it was bad already, return success and do nothing. */ +	if ((ret = nand_block_isbad(mtd, ofs))) { +		/* If it was bad already, return success and do nothing. */  		if (ret > 0)  			return 0; -        	return ret; -        } +		return ret; +	}  	return this->block_markbad(mtd, ofs);  } @@ -2281,13 +2279,13 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  	/* Print and store flash device information */  	for (i = 0; nand_flash_ids[i].name != NULL; i++) { -				 -		if (nand_dev_id != nand_flash_ids[i].id)  + +		if (nand_dev_id != nand_flash_ids[i].id)  			continue;  		if (!mtd->name) mtd->name = nand_flash_ids[i].name;  		this->chipsize = nand_flash_ids[i].chipsize << 20; -		 +  		/* New devices have all the information in additional id bytes */  		if (!nand_flash_ids[i].pagesize) {  			int extid; @@ -2306,7 +2304,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  			extid >>= 2;  			/* Get buswidth information */  			busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; -		 +  		} else {  			/* Old devices have this data hardcoded in the  			 * device id table */ @@ -2320,23 +2318,23 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  		 * this correct ! */  		if (busw != (this->options & NAND_BUSWIDTH_16)) {  			printk (KERN_INFO "NAND device: Manufacturer ID:" -				" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,  +				" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,  				nand_manuf_ids[i].name , mtd->name); -			printk (KERN_WARNING  -				"NAND bus width %d instead %d bit\n",  +			printk (KERN_WARNING +				"NAND bus width %d instead %d bit\n",  					(this->options & NAND_BUSWIDTH_16) ? 16 : 8,  					busw ? 16 : 8);  			this->select_chip(mtd, -1); -			return 1;	 +			return 1;  		} -		 -		/* Calculate the address shift from the page size */	 + +		/* Calculate the address shift from the page size */  		this->page_shift = ffs(mtd->oobblock) - 1;  		this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;  		this->chip_shift = ffs(this->chipsize) - 1;  		/* Set the bad block position */ -		this->badblockpos = mtd->oobblock > 512 ?  +		this->badblockpos = mtd->oobblock > 512 ?  			NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;  		/* Get chip options, preserve non chip based options */ @@ -2346,10 +2344,10 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  		this->options |= NAND_NO_AUTOINCR;  		/* Check if this is a not a samsung device. Do not clear the options  		 * for chips which are not having an extended id. -		 */	 +		 */  		if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)  			this->options &= ~NAND_SAMSUNG_LP_OPTIONS; -		 +  		/* Check for AND chips with 4 page planes */  		if (this->options & NAND_4PAGE_ARRAY)  			this->erase_cmd = multi_erase_cmd; @@ -2359,14 +2357,14 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  		/* Do not replace user supplied command function ! */  		if (mtd->oobblock > 512 && this->cmdfunc == nand_command)  			this->cmdfunc = nand_command_lp; -				 +  		/* Try to identify manufacturer */  		for (j = 0; nand_manuf_ids[j].id != 0x0; j++) {  			if (nand_manuf_ids[j].id == nand_maf_id)  				break;  		}  		printk (KERN_INFO "NAND device: Manufacturer ID:" -			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,  +			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,  			nand_manuf_ids[j].name , nand_flash_ids[i].name);  		break;  	} @@ -2390,7 +2388,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  	}  	if (i > 1)  		printk(KERN_INFO "%d NAND chips detected\n", i); -	 +  	/* Allocate buffers, if neccecary */  	if (!this->oob_buf) {  		size_t len; @@ -2402,7 +2400,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  		}  		this->options |= NAND_OOBBUF_ALLOC;  	} -	 +  	if (!this->data_buf) {  		size_t len;  		len = mtd->oobblock + mtd->oobsize; @@ -2429,7 +2427,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  	if (!this->autooob) {  		/* Select the appropriate default oob placement scheme for  		 * placement agnostic filesystems */ -		switch (mtd->oobsize) {  +		switch (mtd->oobsize) {  		case 8:  			this->autooob = &nand_oob_8;  			break; @@ -2445,7 +2443,7 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  /*			BUG(); */  		}  	} -	 +  	/* The number of bytes available for the filesystem to place fs dependend  	 * oob data */  	if (this->options & NAND_BUSWIDTH_16) { @@ -2455,12 +2453,12 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  	} else  		mtd->oobavail = mtd->oobsize - (this->autooob->eccbytes + 1); -	/*  +	/*  	 * check ECC mode, default to software  	 * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize -	 * fallback to software ECC  +	 * fallback to software ECC  	*/ -	this->eccsize = 256;	/* set default eccsize */	 +	this->eccsize = 256;	/* set default eccsize */  	this->eccbytes = 3;  	switch (this->eccmode) { @@ -2475,27 +2473,27 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  			this->eccsize = 2048;  		break; -	case NAND_ECC_HW3_512:  -	case NAND_ECC_HW6_512:  -	case NAND_ECC_HW8_512:  +	case NAND_ECC_HW3_512: +	case NAND_ECC_HW6_512: +	case NAND_ECC_HW8_512:  		if (mtd->oobblock == 256) {  			printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");  			this->eccmode = NAND_ECC_SOFT;  			this->calculate_ecc = nand_calculate_ecc;  			this->correct_data = nand_correct_data; -		} else  +		} else  			this->eccsize = 512; /* set eccsize to 512 */  		break; -			 +  	case NAND_ECC_HW3_256:  		break; -		 -	case NAND_ECC_NONE:  + +	case NAND_ECC_NONE:  		printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");  		this->eccmode = NAND_ECC_NONE;  		break; -	case NAND_ECC_SOFT:	 +	case NAND_ECC_SOFT:  		this->calculate_ecc = nand_calculate_ecc;  		this->correct_data = nand_correct_data;  		break; @@ -2503,28 +2501,28 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  	default:  		printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);  /*		BUG(); */ -	}	 +	} -	/* Check hardware ecc function availability and adjust number of ecc bytes per  +	/* Check hardware ecc function availability and adjust number of ecc bytes per  	 * calculation step  	*/  	switch (this->eccmode) {  	case NAND_ECC_HW12_2048:  		this->eccbytes += 4; -	case NAND_ECC_HW8_512:  +	case NAND_ECC_HW8_512:  		this->eccbytes += 2; -	case NAND_ECC_HW6_512:  +	case NAND_ECC_HW6_512:  		this->eccbytes += 3; -	case NAND_ECC_HW3_512:  +	case NAND_ECC_HW3_512:  	case NAND_ECC_HW3_256:  		if (this->calculate_ecc && this->correct_data && this->enable_hwecc)  			break;  		printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");  /*		BUG();	*/  	} -		 +  	mtd->eccsize = this->eccsize; -	 +  	/* Set the number of read / write steps for one page to ensure ECC generation */  	switch (this->eccmode) {  	case NAND_ECC_HW12_2048: @@ -2536,17 +2534,17 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  		this->eccsteps = mtd->oobblock / 512;  		break;  	case NAND_ECC_HW3_256: -	case NAND_ECC_SOFT:	 +	case NAND_ECC_SOFT:  		this->eccsteps = mtd->oobblock / 256;  		break; -		 -	case NAND_ECC_NONE:  + +	case NAND_ECC_NONE:  		this->eccsteps = 1;  		break;  	}  /* XXX U-BOOT XXX */ -#if 0	 +#if 0  	/* Initialize state, waitqueue and spinlock */  	this->state = FL_READY;  	init_waitqueue_head (&this->wq); @@ -2600,9 +2598,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips)  }  /** - * nand_release - [NAND Interface] Free resources held by the NAND device  + * nand_release - [NAND Interface] Free resources held by the NAND device   * @mtd:	MTD device structure -*/ + */  void nand_release (struct mtd_info *mtd)  {  	struct nand_chip *this = mtd->priv; diff --git a/drivers/nand/nand_bbt.c b/drivers/nand/nand_bbt.c index 6f7e05b7e..dfa88a3af 100644 --- a/drivers/nand/nand_bbt.c +++ b/drivers/nand/nand_bbt.c @@ -3,7 +3,7 @@   *   *  Overview:   *   Bad block table support for the NAND driver - *    + *   *  Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)   *   * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $ @@ -14,23 +14,23 @@   *   * 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 - * 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.   * 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 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.   *   * The table uses 2 bits per block @@ -43,13 +43,13 @@   * 01b:		block is marked bad due to wear   * 10b:		block is reserved (to protect the bbt area)   * 11b:		block is factory marked bad - *  + *   * Multichip devices like DOC store the bad block info per floor.   *   * Following assumptions are made:   * - 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 - *  + *   */  #include <common.h> @@ -63,7 +63,7 @@  #include <asm/errno.h> -/**  +/**   * check_pattern - [GENERIC] check if a pattern is in the buffer   * @buf:	the 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)  				return -1;  		} -	}	 +	}  	p += end; -	 +  	/* Compare the pattern */  	for (i = 0; i < td->len; 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.   *   */ -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 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;  	from = ((loff_t)page) << this->page_shift; -	 +  	while (totlen) {  		len = min (totlen, (size_t) (1 << this->bbt_erase_shift));  		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;  			}  			printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n"); -		}	 +		}  		/* Analyse data */  		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 */  				printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",  					((offs << 2) + (act >> 1)) << this->bbt_erase_shift); -				/* Factory marked bad or worn out ? */	 +				/* Factory marked bad or worn out ? */  				if (tmp == 0)  					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);  				else  					this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06); -			}	 +			}  		}  		totlen -= 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   * @mtd:	MTD device structure   * @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.   *		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   * @mtd:	MTD device structure   * @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   *   * 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; -	/* Read the primary version, if available */	 +	/* Read the primary version, if available */  	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];  		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)) { -		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];  		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 {  		if (bd->options & NAND_BBT_SCAN2NDPAGE)  			len = 2; -		else	 +		else  			len = 1;  	}  	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) {  			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",  				chip + 1, this->numchips); -			return;	 +			return;  		}  		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);  		startblock = chip * numblocks;  		numblocks += startblock;  		from = startblock << (this->bbt_erase_shift - 1);  	} -	 +  	for (i = startblock; i < numblocks;) {  		nand_read_raw (mtd, buf, from, readlen, ooblen);  		for (j = 0; j < len; j++) {  			if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {  				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);  				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   *   * 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   * 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.   * 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)  { @@ -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;  		dir = -1;  	} else { -		startblock = 0;	 +		startblock = 0;  		dir = 1; -	}	 -	 +	} +  	/* Do we have a bbt per chip ? */  	if (td->options & NAND_BBT_PERCHIP) {  		chips = this->numchips; @@ -351,19 +351,19 @@ static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr  		chips = 1;  		bbtblocks = mtd->size >> this->bbt_erase_shift;  	} -	 +  	/* Number of bits for each erase block in the bbt */  	bits = td->options & NAND_BBT_NRBITS_MSK; -	 +  	for (i = 0; i < chips; i++) {  		/* Reset version information */ -		td->version[i] = 0;	 +		td->version[i] = 0;  		td->pages[i] = -1;  		/* Scan the maximum number of blocks */  		for (block = 0; block < td->maxblocks; block++) {  			int actblock = startblock + dir * block;  			/* 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)) {  				td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);  				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  			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)   * @mtd:	MTD device structure   * @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   *   * 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)  {  	/* Search the primary table */  	search_bbt (mtd, buf, td); -		 +  	/* Search the mirror table */  	if (md)  		search_bbt (mtd, buf, md); -	 +  	/* Force result check */ -	return 1;	 +	return 1;  } -	 -/**  + +/**   * write_bbt - [GENERIC] (Re)write the bad block table   *   * @mtd:	MTD device structure   * @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   * @chipsel:	selector for a specific chip, -1 for all   *   * (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_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 ? */  	if (td->options & NAND_BBT_PERCHIP) {  		numblocks = (int) (this->chipsize >> this->bbt_erase_shift); -		/* Full device write or specific chip ? */	 +		/* Full device write or specific chip ? */  		if (chipsel == -1) {  			nrchips = this->numchips;  		} else { @@ -449,19 +449,19 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,  	} else {  		numblocks = (int) (mtd->size >> this->bbt_erase_shift);  		nrchips = 1; -	}	 -	 +	} +  	/* Loop through the chips */  	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.  		 */  		if (td->pages[chip] != -1) {  			page = td->pages[chip];  			goto write; -		}	 +		}  		/* Automatic placement of the bad block table */  		/* Search direction top -> down ? */ @@ -471,7 +471,7 @@ static int write_bbt (struct mtd_info *mtd, uint8_t *buf,  		} else {  			startblock = chip * numblocks;  			dir = 1; -		}	 +		}  		for (i = 0; i < td->maxblocks; 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");  		return -ENOSPC; -write:	 +write:  		/* Set up shift count and masks for the flash table */  		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;  		default: return -EINVAL;  		} -		 +  		bbtoffs = chip * (numblocks >> 2); -		 +  		to = ((loff_t) page) << this->page_shift;  		memcpy (&oobinfo, this->autooob, sizeof(oobinfo));  		oobinfo.useecc = MTD_NANDECC_PLACEONLY; -		 +  		/* Must we save the block contents ? */  		if (td->options & NAND_BBT_SAVECONTENT) {  			/* Make it block aligned */ @@ -545,7 +545,7 @@ write:  				buf[len + td->veroffs] = td->version[chip];  			}  		} -	 +  		/* walk through the memory table */  		for (i = 0; i < numblocks; ) {  			uint8_t dat; @@ -557,7 +557,7 @@ write:  				dat >>= 2;  			}  		} -		 +  		memset (&einfo, 0, sizeof (einfo));  		einfo.mtd = mtd;  		einfo.addr = (unsigned long) to; @@ -567,18 +567,18 @@ write:  			printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);  			return res;  		} -	 +  		res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);  		if (res < 0) {  			printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", 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]); -	 +  		/* Mark it as used */  		td->pages[chip] = page; -	}	 +	}  	return 0;  } @@ -587,7 +587,7 @@ write:   * @mtd:	MTD device structure   * @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  */  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;  	/* Do we have a bbt per chip ? */ -	if (td->options & NAND_BBT_PERCHIP)  +	if (td->options & NAND_BBT_PERCHIP)  		chips = this->numchips; -	else  +	else  		chips = 1; -	 +  	for (i = 0; i < chips; i++) {  		writeops = 0;  		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) { -				rd = md;				 +				rd = md;  				td->version[i] = md->version[i];  				writeops = 1;  				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))  					rd2 = md;  				goto writecheck; -			}	 +			}  			if (((int8_t) (td->version[i] - md->version[i])) > 0) {  				rd = td; @@ -683,15 +683,15 @@ static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_des  create:  		/* Create the bad block table by scanning the device ? */  		if (!(td->options & NAND_BBT_CREATE)) -			continue;	 -		 +			continue; +  		/* Create the table in memory by scanning the chip(s) */  		create_bbt (mtd, buf, bd, chipsel); -		 +  		td->version[i] = 1;  		if (md) -			md->version[i] = 1;	 -writecheck:	 +			md->version[i] = 1; +writecheck:  		/* read back first ? */  		if (rd)  			read_abs_bbt (mtd, buf, rd, chipsel); @@ -705,7 +705,7 @@ writecheck:  			if (res < 0)  				return res;  		} -		 +  		/* Write the mirror bad block table to the device ? */  		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {  			res = write_bbt (mtd, buf, md, td, chipsel); @@ -713,11 +713,11 @@ writecheck:  				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   * @td:		bad block table descriptor   * @@ -738,14 +738,14 @@ static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)  	} else {  		chips = 1;  		nrblocks = (int)(mtd->size >> this->bbt_erase_shift); -	}	 -	 +	} +  	for (i = 0; i < chips; i++) {  		if ((td->options & NAND_BBT_ABSPAGE) ||  		    !(td->options & NAND_BBT_WRITE)) {  		    	if (td->pages[i] == -1) continue;  			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); -			block <<= 1;		 +			block <<= 1;  			oldval = this->bbt[(block >> 3)];  			newval = oldval | (0x2 << (block & 0x06));  			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;  		if (td->options & NAND_BBT_LASTBLOCK)  			block = ((i + 1) * nrblocks) - td->maxblocks; -		else	 +		else  			block = i * nrblocks; -		block <<= 1;	 +		block <<= 1;  		for (j = 0; j < td->maxblocks; j++) {  			oldval = this->bbt[(block >> 3)];  			newval = oldval | (0x2 << (block & 0x06));  			this->bbt[(block >> 3)] = newval;  			if (oldval != newval) update = 1;  			block += 2; -		}	 +		}  		/* If we want reserved blocks to be recorded to flash, and some  		   new ones have been marked, then we need to update the stored  		   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   * @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   * marked good / bad blocks and writes the bad block table(s) to   * the selected place. @@ -822,30 +822,30 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)  		this->bbt = NULL;  		return -ENOMEM;  	} -	 +  	/* Is the bbt at a given page ? */  	if (td->options & NAND_BBT_ABSPAGE) {  		res = read_abs_bbts (mtd, buf, td, md); -	} else {	 +	} else {  		/* Search the bad block table using a pattern in oob */  		res = search_read_bbts (mtd, buf, td, md); -	}	 +	} -	if (res)  +	if (res)  		res = check_create (mtd, buf, bd); -	 +  	/* Prevent the bbt regions from erasing / writing */  	mark_bbt_region (mtd, td);  	if (md)  		mark_bbt_region (mtd, md); -	 +  	kfree (buf);  	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   * @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");  		return -ENOMEM;  	} -	 +  	writeops = md != NULL ? 0x03 : 0x01;  	/* 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]++;  	if (md) -		md->version[chip]++;	 +		md->version[chip]++;  	/* Write the bad block table to the device ? */  	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);  	} -out:	 +out:  	kfree (buf);  	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 - *  - * The memory based patterns just  + * + * The memory based patterns just   */  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 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,  	.offs =	8,  	.len = 4, @@ -964,7 +964,7 @@ static struct nand_bbt_descr bbt_main_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,  	.offs =	8,  	.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   *   * 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)  {  	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  	 * _good_ blocks. Erasing those blocks leads to loss  	 * 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  	*/  	if (this->options & NAND_IS_AND) {  		/* Use the default pattern descriptors */ -		if (!this->bbt_td) {	 +		if (!this->bbt_td) {  			this->bbt_td = &bbt_main_descr;  			this->bbt_md = &bbt_mirror_descr; -		}	 +		}  		this->options |= NAND_USE_FLASH_BBT;  		return nand_scan_bbt (mtd, &agand_flashbased);  	} -	 -	 + +  	/* Is a flash based bad block table requested ? */  	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_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   * @offs:	offset in the device   * @allowbbt:	allow access to bad block table region   * -*/ + */  int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)  {  	struct nand_chip *this = mtd->priv;  	int block;  	uint8_t	res; -	 +  	/* Get block number * 2 */  	block = (int) (offs >> (this->bbt_erase_shift - 1));  	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);  	switch ((int)res) { diff --git a/drivers/nand/nand_ecc.c b/drivers/nand/nand_ecc.c index dc9db4b48..6e11c2285 100644 --- a/drivers/nand/nand_ecc.c +++ b/drivers/nand/nand_ecc.c @@ -13,16 +13,16 @@   * under the terms of the GNU General Public License as published by the   * Free Software Foundation; either version 2 or (at your option) any   * later version. - *  + *   * This file 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 file; if not, write to the Free Software Foundation, Inc.,   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - *  + *   * As a special exception, if other files instantiate templates or use   * 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 @@ -30,7 +30,7 @@   * covered by the GNU General Public License. However the source code for   * these files must still be made available in accordance with section (3)   * of the GNU General Public License. - *  + *   * This exception does not invalidate any other reasons why a work based on   * 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   * @reg2:	line parity reg 2   * @reg3:	line parity reg 3 - * @ecc_code:	ecc  + * @ecc_code:	ecc   *   * 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 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] */ @@ -89,7 +89,7 @@ static void nand_trans_result(u_char reg2, u_char reg3,  		b >>= 1;  		a >>= 1;  	} -	 +  	/* Calculate second ECC byte */  	b = 0x80;  	for (i = 0; i < 4; i++) { @@ -101,7 +101,7 @@ static void nand_trans_result(u_char reg2, u_char reg3,  		b >>= 1;  		a >>= 1;  	} -	 +  	/* Store two of the ECC bytes */  	ecc_code[0] = tmp1;  	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;  	int j; -	 +  	/* Initialize variables */  	reg1 = reg2 = reg3 = 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++) { -		 +  		/* Get CP0 - CP5 from table */  		idx = nand_ecc_precalc_table[dat[j]];  		reg1 ^= (idx & 0x3f); -		 +  		/* All bit XOR = 1 ? */  		if (idx & 0x40) {  			reg3 ^= (u_char) j;  			reg2 ^= ~((u_char) j);  		}  	} -	 +  	/* Create non-inverted ECC code from line parity */  	nand_trans_result(reg2, reg3, ecc_code); -	 +  	/* Calculate final ECC code */  	ecc_code[0] = ~ecc_code[0];  	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)  {  	u_char a, b, c, d1, d2, d3, add, bit, i; -	 -	/* Do error detection */  + +	/* 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; @@ -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;  		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; @@ -205,8 +205,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_cha  			a ^= (b << bit);  			dat[add] = a;  			return 1; -		} -		else { +		} else {  			i = 0;  			while (d1) {  				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 */  	return -1;  } diff --git a/drivers/nand/nand_ids.c b/drivers/nand/nand_ids.c index 5df1e8971..39882cc76 100644 --- a/drivers/nand/nand_ids.c +++ b/drivers/nand/nand_ids.c @@ -18,14 +18,14 @@  /*  *	Chip ID list -*	 +*  *	Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,  *	options -*  +*  * 	Pagesize; 0, 256, 512  *	0 	get this information from the extended chip ID  +	256	256 Byte page size -*	512	512 Byte page size	 +*	512	512 Byte page size  */  struct nand_flash_dev nand_flash_ids[] = {  	{"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", 	0xe5, 512, 4, 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 3,3V 8-bit", 	0xe6, 512, 8, 0x2000, 0},  	{"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 16MiB 1,8V 8-bit", 	0x33, 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 3,3V 16-bit", 	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, -	 +  	{"NAND 32MiB 1,8V 8-bit", 	0x35, 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 3,3V 16-bit", 	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, -	 +  	{"NAND 64MiB 1,8V 8-bit", 	0x36, 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 3,3V 16-bit", 	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, -	 +  	{"NAND 128MiB 1,8V 8-bit", 	0x78, 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 3,3V 16-bit", 	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, -	 +  	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},  	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0}, -	 +  	/* These are the new chips with large page size. The pagesize  	* 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 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}, -	 +  	/* 4 Gigabit */  	{"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 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}, -	 +  	/* 8 Gigabit */  	{"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}, @@ -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 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  	 * 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 -	 * 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}, diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index e53aa31ef..6658512b2 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -143,7 +143,7 @@  /* keeps pointer to currentlu processed partition */  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   * @@ -290,7 +290,7 @@ static inline void *get_fl_mem(u32 off, u32 size, void *ext_buf)  		return get_fl_mem_nor(off);  #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)  		return get_fl_mem_nand(off, size, ext_buf);  #endif @@ -308,7 +308,7 @@ static inline void *get_node_mem(u32 off)  		return get_node_mem_nor(off);  #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)  		return get_node_mem_nand(off);  #endif @@ -319,7 +319,7 @@ static inline void *get_node_mem(u32 off)  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;  	if (id->type == MTD_DEV_TYPE_NAND) diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c index ce80a43fa..e5c2a7dd4 100644 --- a/fs/jffs2/jffs2_nand_1pass.c +++ b/fs/jffs2/jffs2_nand_1pass.c @@ -1,6 +1,6 @@  #include <common.h> -#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) +#if defined(CONFIG_NEW_NAND_CODE) && (CONFIG_COMMANDS & CFG_CMD_JFFS2)  #include <malloc.h>  #include <linux/stat.h> @@ -12,12 +12,12 @@  #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 */  #undef	DEBUG_DIRENTS		/* print directory entry list after scan */  #undef	DEBUG_FRAGMENTS		/* print fragment list after scan */ -#undef	DEBUG  			/* enable debugging messages */ +#undef	DEBUG			/* enable debugging messages */  #ifdef  DEBUG  # define DEBUGF(fmt,args...)	printf(fmt ,##args) @@ -25,7 +25,6 @@  # define DEBUGF(fmt,args...)  #endif -static int nanddev = -1; /* nand device of current partition */  static nand_info_t *nand;  /* Compression names */ @@ -385,10 +384,10 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)  				continue;  			if (jDir->version == version && inode != 0) { -			    	/* I'm pretty sure this isn't legal */ +				/* I'm pretty sure this isn't legal */  				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;  			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 */  	for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {  		if (ino == jDir->ino) { -		    	if (jDir->version < version) +			if (jDir->version < version)  				continue;  			if (jDir->version == version && jDirFoundType) { -			    	/* I'm pretty sure this isn't legal */ +				/* I'm pretty sure this isn't legal */  				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; @@ -686,12 +685,6 @@ jffs2_1pass_rescan_needed(struct part_info *part)  		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 */  #if 0  	/* 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 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. */  	jffs_init_1pass_list(part); @@ -993,7 +984,7 @@ jffs2_1pass_load(char *dest, struct part_info * part, const char *fname)  	long ret = 0;  	u32 inode; -	if (! (pl  = jffs2_get_list(part, "load"))) +	if (! (pl = jffs2_get_list(part, "load")))  		return 0;  	if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) { @@ -1025,7 +1016,7 @@ jffs2_1pass_info(struct part_info * part)  	struct b_lists *pl;  	int i; -	if (! (pl  = jffs2_get_list(part, "info"))) +	if (! (pl = jffs2_get_list(part, "info")))  		return 0;  	jffs2_1pass_fill_info(pl, &info); diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index c2b69fb2d..648a10dd9 100644 --- a/include/asm-arm/io.h +++ b/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_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   * properly.  Spell it out to the compiler in some cases. diff --git a/include/configs/netstar.h b/include/configs/netstar.h new file mode 100644 index 000000000..30d265473 --- /dev/null +++ b/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 */ diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index afe96b59c..3d1d41681 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/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 $   * - * 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__ @@ -27,17 +27,17 @@ struct mtd_oob_buf {  #define MTD_OTHER		14  #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_RAM		(MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)  #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) -// 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 */ -#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 {  	uint8_t type;  	uint32_t flags; -	uint32_t size;	 // Total size of the MTD +	uint32_t size;	 /* Total size of the MTD */  	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 eccsize;  };  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 */  	uint32_t erasesize;		/* For this region */  	uint32_t numblocks;		/* Number of blocks in this region */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 9ef4cced5..13e90803a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,4 +1,4 @@ -/*  +/*   * $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. @@ -46,7 +46,7 @@ struct mtd_erase_region_info {  struct mtd_info {  	u_char type;  	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  	 * 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 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 eccsize; -	 -	// Kernel-only stuff starts here. + +	/* Kernel-only stuff starts here. */  	char *name;  	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;  	/* 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; -	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 */  	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 (*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 -	 * 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); @@ -109,14 +109,14 @@ struct mtd_info {  #if 0  	/* kvec-based read/write methods. We need these especially for NAND flash,  	   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.  	*/  	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);  	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);  #endif  	/* 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_READOOB(mtd, args...) (*(mtd->read_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 diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 9a0108f78..065e1cb4e 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -24,7 +24,7 @@   *			bat later if I did something naughty.   *   10-11-2000 SJH     Added private NAND flash structure for driver   *   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   *   02-21-2002 TG	added support for different read/write adress and   *			ready/busy line access function @@ -36,14 +36,14 @@   *			CONFIG_MTD_NAND_ECC_JFFS2 is not set   *   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   *			support for 6byte/512byte hardware ECC   *			read_ecc, write_ecc extended for different oob-layout   *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,   *			NAND_YAFFS_OOB   *  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   *  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_WP		0x80 -/*  +/*   * 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  /* Chip has copy back function */  #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 */  #define NAND_IS_AND		0x00000020  /* Chip has a array of 4 pages which can be read without   * additional ready /busy waits */ -#define NAND_4PAGE_ARRAY	0x00000040  +#define NAND_4PAGE_ARRAY	0x00000040  /* Options valid for Samsung large page devices */  #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   * default bad block table function. */  #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 */  #define NAND_HWECC_SYNDROME	0x00020000 @@ -218,7 +218,7 @@ struct nand_chip;  #if 0  /**   * 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   */  struct nand_hw_control { @@ -229,8 +229,8 @@ struct nand_hw_control {  /**   * 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   * @write_byte:		[REPLACEABLE] write one byte to 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   * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support   * @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   * @eccbytes: 		[INTERN] number of ecc bytes per ecc-calculation step   * @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   * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry   * @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   * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized   * @data_poi:		[INTERN] pointer to a data buffer @@ -280,20 +280,20 @@ struct nand_hw_control {   * @bbt:		[INTERN] bad block table pointer   * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup   * @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   * @priv:		[OPTIONAL] pointer to private chip date   */ -  +  struct nand_chip {  	void  __iomem	*IO_ADDR_R;  	void  __iomem 	*IO_ADDR_W; -	 +  	u_char		(*read_byte)(struct mtd_info *mtd);  	void		(*write_byte)(struct mtd_info *mtd, u_char byte);  	u16		(*read_word)(struct mtd_info *mtd);  	void		(*write_word)(struct mtd_info *mtd, u16 word); -	 +  	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);  	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   * @id:   	device ID code   * @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   *		extended id bytes in the chip   * @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_manufacturers nand_manuf_ids[]; -/**  +/**   * struct nand_bbt_descr - bad block table descriptor   * @options:	options for this descriptor   * @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   * @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 - *		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.   * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than   *              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   * - * 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   * that the pattern and the version count are always located in the oob area   * of the first block. diff --git a/include/nand.h b/include/nand.h index 29580da4f..6dbaa4240 100644 --- a/include/nand.h +++ b/include/nand.h @@ -24,7 +24,7 @@  #ifndef _NAND_H_  #define _NAND_H_ -#include <linux_compat.h> +#include <linux/mtd/compat.h>  #include <linux/mtd/mtd.h>  #include <linux/mtd/nand.h> |