diff options
55 files changed, 6600 insertions, 419 deletions
| @@ -2,6 +2,29 @@  Changes since U-Boot 0.2.2:  ====================================================================== +* Patch by Rick Bronson, 16 Mar 2003: +  Add support for Atmel AT91RM9200DK w/NAND + +* Patches by Robert Schwebel, 19 Mar 2003: +  - use arm-linux-gcc as default compiler for ARM +  - fix i2c fixup code +  - fix missing baudrate setting +  - added $loadaddr / CFG_LOAD_ADDR support to loadb +  - moved "ignoring trailing characters" _before_ u-boot wants to +    print out diagnostics messages; removes bogus characters at the +    end of transmission + +* Patch by John Zhan, 18 Mar 2003: +  Add support for SinoVee Microsystems SC8xx boards + +* Patch by Rolf Offermanns, 21 Mar 2003: +  ported the dnp1110 related changes from the current armboot cvs to +  current u-boot cvs. smc91111 does not work. problem marked in +  smc91111.c, grep for "FIXME". + +* Patch by Brian Auld, 25 Mar 2003: +  Add support for STM flash chips on ebony board +  * Add PCI support for MPC8250 Boards (PM825 module)  * Patch by Stefan Roese, 25 Mar 2003: @@ -46,6 +46,10 @@ N: Raphael Bossek  E: raphael.bossek@solutions4linux.de  D: 8xxrom-0.3.0 +N: Rick Bronson +E: rick@efn.org +D: Atmel AT91RM9200DK w/NAND support +  N: David Brown  E: DBrown03@harris.com  D: Extensions to 8xxrom-0.3.0 @@ -262,6 +266,10 @@ N: Christian Vejlbo  E: christian.vejlbo@tellabs.com  D: FADS860T ethernet support +N: John Zhan +E: zhanz@sinovee.com +D: Support for SinoVee Microsystems SC8xx SBC +  N: Alex Zuepke  E: azu@sysgo.de  D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM diff --git a/MAINTAINERS b/MAINTAINERS index 292a29097..56f296d72 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -32,6 +32,10 @@ Jerry Van Baren <vanbaren_gerald@si.com>  	sacsng			MPC8260 +Rick Bronson <rick@efn.org> + +	AT91RM9200DK		at91rm9200 +  Oliver Brown <obrown@adventnetworks.com>  	gw8260			MPC8260 @@ -197,6 +201,10 @@ Rune Torgersen <runet@innovsys.com>  	MPC8266ADS		MPC8266 +John Zhan <zhanz@sinovee.com> + +	svm_sc8xx		MPC8xx +  -------------------------------------------------------------------------  Unknown / orphaned boards: @@ -25,9 +25,10 @@ LIST_8xx="	\  	lwmon   	MBX		MBX860T		MHPC		\  	MVS1		NETVIA		NX823		pcu_e		\  	R360MPI		RPXClassic	RPXlite		RRvision	\ -	SM850		SPD823TS	SXNI855T	TOP860		\ -	TQM823L		TQM823L_LCD	TQM850L		TQM855L		\ -	TQM860L		TQM860L_FEC	TTTech		v37		\ +	SM850		SPD823TS	svm_sc8xx	SXNI855T	\ +	TOP860		TQM823L		TQM823L_LCD	TQM850L		\ +	TQM855L		TQM860L		TQM860L_FEC	TTTech		\ +	v37								\  "  ######################################################################### @@ -83,13 +84,13 @@ LIST_ppc="${LIST_8xx} ${LIST_824x} ${LIST_8260} \  ## StrongARM Systems  ######################################################################### -LIST_SA="lart shannon dnp1110" +LIST_SA="at91rm9200dk dnp1110 lart shannon"  #########################################################################  ## ARM7 Systems  ######################################################################### -LIST_ARM7="impa7 ep7312" +LIST_ARM7="ep7312 impa7"  #########################################################################  ## ARM9 Systems @@ -101,7 +102,7 @@ LIST_ARM9="smdk2400 smdk2410 trab VCMA9"  ## Xscale Systems  ######################################################################### -LIST_xscale="lubbock cradle csb226 innokom" +LIST_xscale="cradle csb226 innokom lubbock"  LIST_arm="${LIST_SA} ${LIST_ARM7} ${LIST_ARM9} ${LIST_xscale}" @@ -57,7 +57,7 @@ ifeq ($(ARCH),ppc)  CROSS_COMPILE = ppc_8xx-  endif  ifeq ($(ARCH),arm) -CROSS_COMPILE = arm_920TDI- +CROSS_COMPILE = arm-linux-  endif  ifeq ($(ARCH),i386)  #CROSS_COMPILE = i386-elf- @@ -314,6 +314,10 @@ SM850_config	:	unconfig  SPD823TS_config:	unconfig  	@./mkconfig $(@:_config=) ppc mpc8xx spd8xx +svm_sc8xx_config:	unconfig +	@ >include/config.h +	@./mkconfig $(@:_config=) ppc mpc8xx svm_sc8xx +  SXNI855T_config:	unconfig  	@./mkconfig $(@:_config=) ppc mpc8xx sixnet @@ -624,6 +628,9 @@ ELPPC_config: unconfig  ## StrongARM Systems  ######################################################################### +at91rm9200dk_config	:	unconfig +	@./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk +  lart_config	:	unconfig  	@./mkconfig $(@:_config=) arm sa1100 lart @@ -1549,6 +1549,7 @@ configuration.  Low Level (hardware related) configuration options: +---------------------------------------------------  - CFG_CACHELINE_SIZE:  		Cache Line Size of the CPU. @@ -1928,7 +1929,7 @@ Some configuration options can be set using Environment Variables:    ipaddr	- IP address; needed for tftpboot command    loadaddr	- Default load address for commands like "bootp", -		  "rarpboot", "tftpboot" or "diskboot" +		  "rarpboot", "tftpboot", "loadb" or "diskboot"    loads_echo	- see CONFIG_LOADS_ECHO diff --git a/board/at91rm9200dk/Makefile b/board/at91rm9200dk/Makefile new file mode 100644 index 000000000..d925d3329 --- /dev/null +++ b/board/at91rm9200dk/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(BOARD).a + +OBJS	:= at91rm9200dk.o flash.o +SOBJS	:= + +$(LIB):	$(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +clean: +	rm -f $(SOBJS) $(OBJS) + +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/at91rm9200dk/at91rm9200dk.c b/board/at91rm9200dk/at91rm9200dk.c new file mode 100644 index 000000000..7c3670bdf --- /dev/null +++ b/board/at91rm9200dk/at91rm9200dk.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.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 + */ + +#include <common.h> +#include <AT91RM9200.h> + +/* ------------------------------------------------------------------------- */ +/* + * Miscelaneous platform dependent initialisations + */ + +int board_init(void) +  { +  DECLARE_GLOBAL_DATA_PTR; + +    /* memory and cpu-speed are setup before relocation */ +    /* so we do _nothing_ here */ + +    /* arch number of AT91RM9200DK-Board */ +    gd->bd->bi_arch_number = 251; +    /* adress of boot parameters */ +    gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + +    return 0; +} + +int dram_init(void) +{ +  DECLARE_GLOBAL_DATA_PTR; + +  gd->bd->bi_dram[0].start = PHYS_SDRAM; +  gd->bd->bi_dram[0].size  = PHYS_SDRAM_SIZE; +  return 0; +} + +/* + * Disk On Chip (NAND) Millenium initialization. + * The NAND lives in the CS2* space + */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +extern void +nand_probe(ulong physadr); + +#define AT91_SMARTMEDIA_BASE 0x40000000  /* physical address to access memory on NCS3 */ +void +nand_init(void) +{ +	/* Setup Smart Media, fitst enable the address range of CS3 */ +        *AT91C_EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia; +        /* set the bus interface characteristics based on +           tDS Data Set up Time 30 - ns +           tDH Data Hold Time 20 - ns +           tALS ALE Set up Time 20 - ns +           16ns at 60 MHz ~= 3  */ +/*memory mapping structures */ +#define SM_ID_RWH	(5 << 28) +#define SM_RWH		(1 << 28) +#define SM_RWS		(0 << 24) +#define SM_TDF		(1 << 8) +#define SM_NWS		(3) +        AT91C_BASE_SMC2->SMC2_CSR[3] = ( SM_RWH|SM_RWS | AT91C_SMC2_ACSS_STANDARD | +                                         AT91C_SMC2_DBW_8 | SM_TDF | +                                         AT91C_SMC2_WSEN | SM_NWS); + +        /* enable the SMOE line PC0=SMCE, A21=CLE, A22=ALE */ +        *AT91C_PIOC_ASR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE; +        *AT91C_PIOC_PDR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE; + +	/* Configure PC2 as input (signal READY of the SmartMedia) */ +        *AT91C_PIOC_PER = AT91C_PC2_BFAVD;  /* enable direct output enable */ +        *AT91C_PIOC_ODR = AT91C_PC2_BFAVD;  /* disable output */ + +	/* Configure PB1 as input (signal Card Detect of the SmartMedia) */ +        *AT91C_PIOB_PER = AT91C_PIO_PB1;  /* enable direct output enable */ +        *AT91C_PIOB_ODR = AT91C_PIO_PB1;  /* disable output */ + +        if (*AT91C_PIOB_PDSR & AT91C_PIO_PB1) +          printf ("No "); +        printf ("SmartMedia card inserted\n"); + +	printf("Probing at 0x%.8x\n", AT91_SMARTMEDIA_BASE); +	nand_probe(AT91_SMARTMEDIA_BASE); +} +#endif diff --git a/board/at91rm9200dk/config.mk b/board/at91rm9200dk/config.mk new file mode 100644 index 000000000..a682451eb --- /dev/null +++ b/board/at91rm9200dk/config.mk @@ -0,0 +1,2 @@ +TEXT_BASE = 0x21fa0000 + diff --git a/board/at91rm9200dk/flash.c b/board/at91rm9200dk/flash.c new file mode 100644 index 000000000..6497f11ca --- /dev/null +++ b/board/at91rm9200dk/flash.c @@ -0,0 +1,397 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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 + */ + +#include <common.h> + +ulong myflush(void); + + +#define FLASH_BANK_SIZE 0x200000	/* 2 MB */ +#define MAIN_SECT_SIZE  0x10000		/* 64 KB */ + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; + + +#define CMD_READ_ARRAY		0x00F0 +#define CMD_UNLOCK1		0x00AA +#define CMD_UNLOCK2		0x0055 +#define CMD_ERASE_SETUP		0x0080 +#define CMD_ERASE_CONFIRM	0x0030 +#define CMD_PROGRAM		0x00A0 +#define CMD_UNLOCK_BYPASS	0x0020 + +#define MEM_FLASH_ADDR1		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1))) +#define MEM_FLASH_ADDR2		(*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1))) + +#define BIT_ERASE_DONE		0x0080 +#define BIT_RDY_MASK		0x0080 +#define BIT_PROGRAM_ERROR	0x0020 +#define BIT_TIMEOUT		0x80000000 /* our flag */ + +#define READY 1 +#define ERR   2 +#define TMO   4 + +/*----------------------------------------------------------------------- + */ + +ulong flash_init(void) +{ +    int i, j; +    ulong size = 0; + +    for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) +    { +	ulong flashbase = 0; +	flash_info[i].flash_id = +	  (ATM_MANUFACT & FLASH_VENDMASK) | +	  (ATM_ID_BV1614 & FLASH_TYPEMASK); +	flash_info[i].size = FLASH_BANK_SIZE; +	flash_info[i].sector_count = CFG_MAX_FLASH_SECT; +	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); +	if (i == 0) +	  flashbase = PHYS_FLASH_1; +	else +	  panic("configured to many flash banks!\n"); +	for (j = 0; j < flash_info[i].sector_count; j++) +	{ + +	    if (j <= 9) +	    { +		/* 1st to 8th are 8 KB */ +		if (j <= 7) +		{ +		    flash_info[i].start[j] = flashbase + j*0x2000; +		} + +		/* 9th and 10th are both 32 KB */ +		if ((j == 8) || (j == 9)) +		{ +			flash_info[i].start[j] = flashbase + 0x10000 + (j-8)*0x8000; +		} +	    } +	    else +	    { +		flash_info[i].start[j] = flashbase + (j-8)*MAIN_SECT_SIZE; +	    } +	} +	size += flash_info[i].size; +    } + +    flash_protect(FLAG_PROTECT_SET, +		  CFG_FLASH_BASE, +		  CFG_ENV_ADDR - 1, +		  &flash_info[0]); + +    flash_protect(FLAG_PROTECT_SET, +		  CFG_ENV_ADDR, +		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1, +		  &flash_info[0]); + +    return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +    int i; + +    switch (info->flash_id & FLASH_VENDMASK) +    { +    case (ATM_MANUFACT & FLASH_VENDMASK): +	printf("Atmel: "); +	break; +    default: +	printf("Unknown Vendor "); +	break; +    } + +    switch (info->flash_id & FLASH_TYPEMASK) +    { +    case (ATM_ID_BV1614 & FLASH_TYPEMASK): +	printf("AT49BV1614 (16Mbit)\n"); +	break; +    default: +	printf("Unknown Chip Type\n"); +	goto Done; +	break; +    } + +    printf("  Size: %ld MB in %d Sectors\n", +	   info->size >> 20, info->sector_count); + +    printf("  Sector Start Addresses:"); +    for (i = 0; i < info->sector_count; i++) +    { +	if ((i % 5) == 0) +	{ +	    printf ("\n   "); +	} +	printf (" %08lX%s", info->start[i], +		info->protect[i] ? " (RO)" : "     "); +    } +    printf ("\n"); + +Done: +} + +/*----------------------------------------------------------------------- + */ + +int	flash_erase (flash_info_t *info, int s_first, int s_last) +{ +    ulong result; +    int iflag, cflag, prot, sect; +    int rc = ERR_OK; +    int chip1; + +    /* 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) != +	(ATM_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) +	return ERR_PROTECTED; + +    /* +     * Disable interrupts which might cause a timeout +     * here. Remember that our exception vectors are +     * at address 0 in the flash, and we don't want a +     * (ticker) exception to happen while the flash +     * chip is in programming mode. +     */ +    cflag = icache_status(); +    icache_disable(); +    iflag = disable_interrupts(); + +    /* Start erase on unprotected sectors */ +    for (sect = s_first; sect<=s_last && !ctrlc(); sect++) +    { +	printf("Erasing sector %2d ... ", sect); + +	/* arm simple, non interrupt dependent timer */ +	reset_timer_masked(); + +	if (info->protect[sect] == 0) +	{	/* not protected */ +	    volatile u16 *addr = (volatile u16 *)(info->start[sect]); + +	    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 */ +	    chip1 = 0; + +	    do +	    { +		result = *addr; + +		/* check timeout */ +		if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) +		{ +		    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; +		    chip1 = TMO; +		    break; +		} + +		if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) +			chip1 = READY; + +	    }  while (!chip1); + +	    MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + +	    if (chip1 == ERR) +	    { +		rc = ERR_PROG_ERROR; +		goto outahere; +	    } +	    if (chip1 == TMO) +	    { +		rc = ERR_TIMOUT; +		goto outahere; +	    } + +	    printf("ok.\n"); +	} +	else /* it was protected */ +	{ +	    printf("protected!\n"); +	} +    } + +    if (ctrlc()) +      printf("User Interrupt!\n"); + +outahere: +    /* allow flash to settle - wait 10 ms */ +    udelay_masked(10000); + +    if (iflag) +      enable_interrupts(); + +    if (cflag) +      icache_enable(); + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +volatile static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +    volatile u16 *addr = (volatile u16 *)dest; +    ulong result; +    int rc = ERR_OK; +    int cflag, iflag; +    int chip1; + +    /* +     * Check if Flash is (sufficiently) erased +     */ +    result = *addr; +    if ((result & data) != data) +        return ERR_NOT_ERASED; + + +    /* +     * Disable interrupts which might cause a timeout +     * here. Remember that our exception vectors are +     * at address 0 in the flash, and we don't want a +     * (ticker) exception to happen while the flash +     * chip is in programming mode. +     */ +    cflag = icache_status(); +    icache_disable(); +    iflag = disable_interrupts(); + +    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 */ +    chip1 = 0; +    do +    { +	result = *addr; + +	/* check timeout */ +	if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) +	{ +	    chip1 = ERR | TMO; +	    break; +	} +	if (!chip1 && ((result & 0x80) == (data & 0x80))) +		chip1 = READY; + +    }  while (!chip1); + +    *addr = CMD_READ_ARRAY; + +    if (chip1 == ERR || *addr != data) +        rc = ERR_PROG_ERROR; + +    if (iflag) +      enable_interrupts(); + +    if (cflag) +      icache_enable(); + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +    ulong wp, data; +    int rc; + +    if(addr & 1) { +      printf("unaligned destination not supported\n"); +      return ERR_ALIGN; +    }; + +    if((int)src & 1) { +      printf("unaligned source not supported\n"); +      return ERR_ALIGN; +    }; + +    wp = addr; + +    while (cnt >= 2) { +	data = *((volatile u16*)src); +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	src += 2; +	wp  += 2; +	cnt -= 2; +    } + +    if(cnt == 1) { +      data =  (*((volatile u8*)src)) | (*((volatile u8*)(wp+1)) << 8); +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	src += 1; +	wp  += 1; +	cnt -= 1; +    }; + +    return ERR_OK; +} diff --git a/board/at91rm9200dk/u-boot.lds b/board/at91rm9200dk/u-boot.lds new file mode 100644 index 000000000..2447bcad0 --- /dev/null +++ b/board/at91rm9200dk/u-boot.lds @@ -0,0 +1,54 @@ +/* + * (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_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ +        . = 0x00000000; + +        . = ALIGN(4); +	.text      : +	{ +	  cpu/at91rm9200/start.o	(.text) +	  *(.text) +	} + +        . = ALIGN(4); +        .rodata : { *(.rodata) } + +        . = ALIGN(4); +        .data : { *(.data) } + +        . = ALIGN(4); +        .got : { *(.got) } + +	armboot_end_data = .; + +        . = ALIGN(4); +        .bss : { *(.bss) } + +	armboot_end = .; +} diff --git a/board/dnp1110/dnp1110.c b/board/dnp1110/dnp1110.c index d6b181534..4a2b44e0e 100644 --- a/board/dnp1110/dnp1110.c +++ b/board/dnp1110/dnp1110.c @@ -23,7 +23,7 @@   */  #include <common.h> - +#include <SA-1100.h>  /* ------------------------------------------------------------------------- */ @@ -41,8 +41,9 @@ int board_init (void)  	/* arch number of DNP1110-Board */  	gd->bd->bi_arch_number = 255; -	/* adress of boot parameters */ -	gd->bd->bi_boot_params = 0xc0000100; +    /* flash vpp on */ +    PPDR |= 0x80;	/* assumes LCD controller is off */ +    PPSR |= 0x80;  	return 0;  } diff --git a/board/dnp1110/flash.c b/board/dnp1110/flash.c index ca9aff957..bb6d2e799 100644 --- a/board/dnp1110/flash.c +++ b/board/dnp1110/flash.c @@ -1,7 +1,9 @@  /* - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Rolf Offermanns <rof@sysgo.de> + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   *   * See file CREDITS for list of people who contributed to this   * project. @@ -23,81 +25,58 @@   */  #include <common.h> - -ulong myflush(void); +#include <linux/byteorder/swab.h> -#define FLASH_BANK_SIZE 0x800000 -#define MAIN_SECT_SIZE  0x20000 -#define PARAM_SECT_SIZE 0x4000 - -/* puzzle magic for lart - * data_*_flash are def'd in flashasm.S - */ +flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ -extern u32 data_from_flash(u32); -extern u32 data_to_flash(u32); +/* Board support for 1 or 2 flash devices */ +#undef FLASH_PORT_WIDTH32 +#define FLASH_PORT_WIDTH16 -#define PUZZLE_FROM_FLASH(x)	(x) -#define PUZZLE_TO_FLASH(x)	(x) +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH		ushort +#define FLASH_PORT_WIDTHV		vu_short +#define SWAP(x)               __swab16(x) +#else +#define FLASH_PORT_WIDTH		ulong +#define FLASH_PORT_WIDTHV		vu_long +#define SWAP(x)               __swab32(x) +#endif -flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; +#define FPW	   FLASH_PORT_WIDTH +#define FPWV   FLASH_PORT_WIDTHV +#define mb() __asm__ __volatile__ ("" : : : "memory") -#define CMD_READ_ARRAY		0x00FF00FF -#define CMD_IDENTIFY		0x00900090 -#define CMD_ERASE_SETUP		0x00200020 -#define CMD_ERASE_CONFIRM	0x00D000D0 -#define CMD_PROGRAM		0x00400040 -#define CMD_RESUME		0x00D000D0 -#define CMD_SUSPEND		0x00B000B0 -#define CMD_STATUS_READ		0x00700070 -#define CMD_STATUS_RESET	0x00500050 - -#define BIT_BUSY		0x00800080 -#define BIT_ERASE_SUSPEND	0x00400040 -#define BIT_ERASE_ERROR		0x00200020 -#define BIT_PROGRAM_ERROR	0x00100010 -#define BIT_VPP_RANGE_ERROR	0x00080008 -#define BIT_PROGRAM_SUSPEND	0x00040004 -#define BIT_PROTECT_ERROR	0x00020002 -#define BIT_UNDEFINED		0x00010001 - -#define BIT_SEQUENCE_ERROR	0x00300030 -#define BIT_TIMEOUT		0x80000000 +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (FPW *addr, flash_info_t *info); +static int   write_data (flash_info_t *info, ulong dest, FPW data); +static void  flash_get_offsets (ulong base, flash_info_t *info); +void inline  spin_wheel(void);  /*-----------------------------------------------------------------------   */ -ulong flash_init(void) +unsigned long flash_init (void)  { -    int i, j; +   int i;      ulong size = 0;      for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)      { -	ulong flashbase = 0; -	flash_info[i].flash_id = -	  (INTEL_MANUFACT & FLASH_VENDMASK) | -	  (INTEL_ID_28F160F3B & FLASH_TYPEMASK); -	flash_info[i].size = FLASH_BANK_SIZE; -	flash_info[i].sector_count = CFG_MAX_FLASH_SECT; -	memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); -	if (i == 0) -	  flashbase = PHYS_FLASH_1; -	else -	  panic("configured to many flash banks!\n"); -	for (j = 0; j < flash_info[i].sector_count; j++) -	{ -	    if (j <= 7) -	    { -		flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE; -	    } -	    else -	    { -		flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE; -	    } -	} +        switch (i) +        { +           case 0: +            flash_get_size((FPW *)PHYS_FLASH_1, &flash_info[i]); +	         flash_get_offsets(PHYS_FLASH_1, &flash_info[i]); +                break; +           default: +	        panic("configured to many flash banks!\n"); +                break; +        }  	size += flash_info[i].size;      } @@ -118,150 +97,138 @@ ulong flash_init(void)  /*-----------------------------------------------------------------------   */ -void flash_print_info  (flash_info_t *info) +static void flash_get_offsets (ulong base, flash_info_t *info)  { -    int i; +	int i; -    switch (info->flash_id & FLASH_VENDMASK) -    { -    case (INTEL_MANUFACT & FLASH_VENDMASK): -	printf("Intel: "); -	break; -    default: -	printf("Unknown Vendor "); -	break; -    } - -    switch (info->flash_id & FLASH_TYPEMASK) -    { -    case (INTEL_ID_28F160F3B & FLASH_TYPEMASK): -	printf("2x 28F160F3B (16Mbit)\n"); -	break; -    default: -	printf("Unknown Chip Type\n"); -	goto Done; -	break; -    } - -    printf("  Size: %ld MB in %d Sectors\n", -	   info->size >> 20, info->sector_count); - -    printf("  Sector Start Addresses:"); -    for (i = 0; i < info->sector_count; i++) -    { -	if ((i % 5) == 0) -	{ -	    printf ("\n   "); +	if (info->flash_id == FLASH_UNKNOWN) { +		return;  	} -	printf (" %08lX%s", info->start[i], -		info->protect[i] ? " (RO)" : "     "); -    } -    printf ("\n"); -Done: +	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { +		for (i = 0; i < info->sector_count; i++) { +			info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE); +			info->protect[i] = 0; +		} +	}  }  /*-----------------------------------------------------------------------   */ - -int flash_error (ulong code) +void flash_print_info  (flash_info_t *info)  { -	/* Check bit patterns */ -	/* SR.7=0 is busy, SR.7=1 is ready */ -	/* all other flags indicate error on 1 */ -	/* SR.0 is undefined */ -	/* Timeout is our faked flag */ +	int i; -	/* sequence is described in Intel 290644-005 document */ +	if (info->flash_id == FLASH_UNKNOWN) { +		printf ("missing or unknown FLASH type\n"); +		return; +        } -	/* check Timeout */ -	if (code & BIT_TIMEOUT) -	{ -		printf ("Timeout\n"); -		return ERR_TIMOUT; +	switch (info->flash_id & FLASH_VENDMASK) { +		case FLASH_MAN_INTEL:	printf ("INTEL ");		break; +		default:		printf ("Unknown Vendor ");	break;  	} -	/* check Busy, SR.7 */ -	if (~code & BIT_BUSY) -	{ -		printf ("Busy\n"); -		return ERR_PROG_ERROR; -	} +	switch (info->flash_id & FLASH_TYPEMASK) { +   case FLASH_28F128J3A: +				printf ("28F128J3A\n"); break; +	default:		printf ("Unknown Chip Type\n"); break; +        } -	/* check Vpp low, SR.3 */ -	if (code & BIT_VPP_RANGE_ERROR) -	{ -		printf ("Vpp range error\n"); -		return ERR_PROG_ERROR; -	} +	printf ("  Size: %ld MB in %d Sectors\n", +	        info->size >> 20, info->sector_count); -	/* check Device Protect Error, SR.1 */ -	if (code & BIT_PROTECT_ERROR) -	{ -		printf ("Device protect error\n"); -		return ERR_PROG_ERROR; -	} +	printf ("  Sector Start Addresses:"); +	for (i=0; i<info->sector_count; ++i) { +	        if ((i % 5) == 0) +	        printf ("\n   "); +		printf (" %08lX%s", +			info->start[i], +			info->protect[i] ? " (RO)" : "     " +		); +        } +        printf ("\n"); +	return; +} -	/* check Command Seq Error, SR.4 & SR.5 */ -	if (code & BIT_SEQUENCE_ERROR) -	{ -		printf ("Command seqence error\n"); -		return ERR_PROG_ERROR; -	} +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW *addr, flash_info_t *info) +{ +	volatile FPW value; +	/* Write auto select command: read Manufacturer ID */ +	addr[0x5555] = (FPW)0x00AA00AA; +	addr[0x2AAA] = (FPW)0x00550055; +	addr[0x5555] = (FPW)0x00900090; -	/* check Block Erase Error, SR.5 */ -	if (code & BIT_ERASE_ERROR) -	{ -		printf ("Block erase error\n"); -		return ERR_PROG_ERROR; -	} +   mb(); +	value = addr[0]; +	 +   switch (value) { -	/* check Program Error, SR.4 */ -	if (code & BIT_PROGRAM_ERROR) -	{ -		printf ("Program error\n"); -		return ERR_PROG_ERROR; -	} +   case (FPW)INTEL_MANUFACT: +      info->flash_id = FLASH_MAN_INTEL; +      break; -	/* check Block Erase Suspended, SR.6 */ -	if (code & BIT_ERASE_SUSPEND) -	{ -		printf ("Block erase suspended\n"); -		return ERR_PROG_ERROR; +	default: +		info->flash_id = FLASH_UNKNOWN; +		info->sector_count = 0; +		info->size = 0; +		addr[0] = (FPW)0x00FF00FF;      /* restore read mode */ +		return (0);			/* no or unknown flash	*/  	} -	/* check Program Suspended, SR.2 */ -	if (code & BIT_PROGRAM_SUSPEND) -	{ -		printf ("Program suspended\n"); -		return ERR_PROG_ERROR; +   mb(); +	value = addr[1];			/* device ID		*/ +   switch (value) { + +   case (FPW)INTEL_ID_28F128J3A: +      info->flash_id += FLASH_28F128J3A; +      info->sector_count = 128; +      info->size = 0x02000000; +      break;            /* => 16 MB     */ + +	default: +		info->flash_id = FLASH_UNKNOWN; +		break;  	} -	/* OK, no error */ -	return ERR_OK; +	if (info->sector_count > CFG_MAX_FLASH_SECT) { +		printf ("** ERROR: sector count %d > max (%d) **\n", +			info->sector_count, CFG_MAX_FLASH_SECT); +		info->sector_count = CFG_MAX_FLASH_SECT; +    } + +	addr[0] = (FPW)0x00FF00FF;      /* restore read mode */ + +	return (info->size);  } +  /*-----------------------------------------------------------------------   */  int	flash_erase (flash_info_t *info, int s_first, int s_last)  { -    ulong result; -    int iflag, cflag, prot, sect; -    int rc = ERR_OK; - -    /* first look for protection bits */ - -    if (info->flash_id == FLASH_UNKNOWN) -	return ERR_UNKNOWN_FLASH_TYPE; +    int flag, prot, sect; +	ulong type, start, last; +	int rcode = 0;      if ((s_first < 0) || (s_first > s_last)) { -	return ERR_INVAL; +		if (info->flash_id == FLASH_UNKNOWN) { +			printf ("- missing\n"); +		} else { +			printf ("- no sectors to erase\n"); +		} +		return 1;      } -    if ((info->flash_id & FLASH_VENDMASK) != -	(INTEL_MANUFACT & FLASH_VENDMASK)) { -	return ERR_UNKNOWN_FLASH_VENDOR; +	type = (info->flash_id & FLASH_VENDMASK); +	if ((type != FLASH_MAN_INTEL)) { +		printf ("Can't erase unknown flash type %08lx - aborted\n", +			info->flash_id); +		return 1;      }      prot = 0; @@ -270,152 +237,79 @@ int	flash_erase (flash_info_t *info, int s_first, int s_last)  	    prot++;  	}      } -    if (prot) -	return ERR_PROTECTED; -    /* -     * Disable interrupts which might cause a timeout -     * here. Remember that our exception vectors are -     * at address 0 in the flash, and we don't want a -     * (ticker) exception to happen while the flash -     * chip is in programming mode. -     */ -    cflag = icache_status(); -    icache_disable(); -    iflag = disable_interrupts(); +	if (prot) { +		printf ("- Warning: %d protected sectors will not be erased!\n", +			prot); +	} else { +		printf ("\n"); +	} + +	start = get_timer (0); +	last  = start; + +   /* Disable interrupts which might cause a timeout here */ +    flag = disable_interrupts();      /* Start erase on unprotected sectors */ -    for (sect = s_first; sect<=s_last && !ctrlc(); sect++) -    { +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) {	/* not protected */ +			FPWV *addr = (FPWV *)(info->start[sect]); +			FPW status; +  	printf("Erasing sector %2d ... ", sect);  	/* arm simple, non interrupt dependent timer */  	reset_timer_masked(); -	if (info->protect[sect] == 0) -	{	/* not protected */ -	    vu_long *addr = (vu_long *)(info->start[sect]); - -	    *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET); -	    *addr = PUZZLE_TO_FLASH(CMD_ERASE_SETUP); -	    *addr = PUZZLE_TO_FLASH(CMD_ERASE_CONFIRM); - -	    /* wait until flash is ready */ -	    do -	    { -		/* check timeout */ -		if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) -		{ -		    *addr = PUZZLE_TO_FLASH(CMD_SUSPEND); -		    result = BIT_TIMEOUT; -		    break; -		} - -		result = PUZZLE_FROM_FLASH(*addr); -	    }  while (~result & BIT_BUSY); +			*addr = (FPW)0x00500050;	/* clear status register */ +			*addr = (FPW)0x00200020;	/* erase setup */ +			*addr = (FPW)0x00D000D0;	/* erase confirm */ -	    *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY); - -	    if ((rc = flash_error(result)) != ERR_OK) -	    	goto outahere; - -	    printf("ok.\n"); -	} -	else /* it was protected */ -	{ -	    printf("protected!\n"); +			while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) { +		if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) { +					printf ("Timeout\n"); +					*addr = (FPW)0x00B000B0; /* suspend erase	  */ +					*addr = (FPW)0x00FF00FF; /* reset to read mode */ +					rcode = 1; +					break;  	}      } -    if (ctrlc()) -      printf("User Interrupt!\n"); - -outahere: -    /* allow flash to settle - wait 10 ms */ -    udelay_masked(10000); +			*addr = (FPW)0x00500050; /* clear status register cmd.   */ +			*addr = (FPW)0x00FF00FF; /* resest to read mode          */ -    if (iflag) -      enable_interrupts(); - -    if (cflag) -      icache_enable(); - -    return rc; +			printf (" done\n"); +        } +        } +	return rcode;  }  /*----------------------------------------------------------------------- - * Copy memory to flash - */ - -volatile static int write_word (flash_info_t *info, ulong dest, ulong data) -{ -    vu_long *addr = (vu_long *)dest; -    ulong result; -    int rc = ERR_OK; -    int cflag, iflag; - -    /* Check if Flash is (sufficiently) erased -     */ -    result = PUZZLE_FROM_FLASH(*addr); -    if ((result & data) != data) -        return ERR_NOT_ERASED; - -    /* -     * Disable interrupts which might cause a timeout -     * here. Remember that our exception vectors are -     * at address 0 in the flash, and we don't want a -     * (ticker) exception to happen while the flash -     * chip is in programming mode. -     */ -    cflag = icache_status(); -    icache_disable(); -    iflag = disable_interrupts(); - -    *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET); -    *addr = PUZZLE_TO_FLASH(CMD_PROGRAM); -    *addr = data; - -    /* arm simple, non interrupt dependent timer */ -    reset_timer_masked(); - -    /* wait until flash is ready */ -    do -    { -	/* check timeout */ -	if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) -	{ -	    *addr = PUZZLE_TO_FLASH(CMD_SUSPEND); -	    result = BIT_TIMEOUT; -	    break; -	} - -	result = PUZZLE_FROM_FLASH(*addr); -    }  while (~result & BIT_BUSY); - -    *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY); - -    rc = flash_error(result); - -    if (iflag) -      enable_interrupts(); - -    if (cflag) -      icache_enable(); - -    return rc; -} - -/*----------------------------------------------------------------------- - * Copy memory to flash. + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified   */  int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)  { -    ulong cp, wp, data; -    int l; -    int i, rc; +    ulong cp, wp; +	FPW data; +	int count, i, l, rc, port_width; -    wp = (addr & ~3);	/* get lower word aligned address */ +	if (info->flash_id == FLASH_UNKNOWN) { +		return 4; +	} +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 +	wp = (addr & ~1); +	port_width = 2; +#else +	wp = (addr & ~3); +	port_width = 4; +#endif      /*       * handle unaligned start bytes @@ -423,51 +317,109 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)      if ((l = addr - wp) != 0) {  	data = 0;  	for (i=0, cp=wp; i<l; ++i, ++cp) { -	    data = (data >> 8) | (*(uchar *)cp << 24); +			data = (data << 8) | (*(uchar *)cp);  	} -	for (; i<4 && cnt>0; ++i) { -	    data = (data >> 8) | (*src++ << 24); +		for (; i<port_width && cnt>0; ++i) { +			data = (data << 8) | *src++;  	    --cnt;  	    ++cp;  	} -	for (; cnt==0 && i<4; ++i, ++cp) { -	    data = (data >> 8) | (*(uchar *)cp << 24); +		for (; cnt==0 && i<port_width; ++i, ++cp) { +			data = (data << 8) | (*(uchar *)cp);  	} -	if ((rc = write_word(info, wp, data)) != 0) { +		if ((rc = write_data(info, wp, SWAP(data))) != 0) {  	    return (rc);  	} -	wp += 4; +		wp += port_width;      }      /*       * handle word aligned part       */ -    while (cnt >= 4) { -	data = *((vu_long*)src); -	if ((rc = write_word(info, wp, data)) != 0) { +	count = 0; +	while (cnt >= port_width) { +		data = 0; +		for (i=0; i<port_width; ++i) { +			data = (data << 8) | *src++; +		} +		if ((rc = write_data(info, wp, SWAP(data))) != 0) {  	    return (rc);  	} -	src += 4; -	wp  += 4; -	cnt -= 4; +		wp  += port_width; +		cnt -= port_width; +		if (count++ > 0x800) +		{ +         spin_wheel(); +			count = 0; +		}      }      if (cnt == 0) { -	return ERR_OK; +		return (0);      }      /*       * handle unaligned tail bytes       */      data = 0; -    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { -	data = (data >> 8) | (*src++ << 24); +	for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) { +		data = (data << 8) | *src++;  	--cnt;      } -    for (; i<4; ++i, ++cp) { -	data = (data >> 8) | (*(uchar *)cp << 24); +	for (; i<port_width; ++i, ++cp) { +		data = (data << 8) | (*(uchar *)cp); +	} + +	return (write_data(info, wp, SWAP(data))); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t *info, ulong dest, FPW data) +{ +	FPWV *addr = (FPWV *)dest; +	ulong status; +	int flag; + +	/* Check if Flash is (sufficiently) erased */ +	if ((*addr & data) != data) { +		printf("not erased at %08lx (%x)\n",(ulong)addr,*addr); +		return (2); +	} +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); + +	*addr = (FPW)0x00400040;		/* write setup */ +	*addr = data; + +	/* arm simple, non interrupt dependent timer */ +	reset_timer_masked(); + +	/* wait while polling the status register */ +	while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) { +		if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) { +			*addr = (FPW)0x00FF00FF;	/* restore read mode */ +			return (1); +		}      } -    return write_word(info, wp, data); +	*addr = (FPW)0x00FF00FF;	/* restore read mode */ + +	return (0); +} + +void inline +spin_wheel(void) +{ +   static int p=0; +   static char w[] = "\\/-"; + +   printf("\010%c", w[p]); +   (++p == 3) ? (p = 0) : 0;  } + diff --git a/board/dnp1110/memsetup.S b/board/dnp1110/memsetup.S index bebd697a8..6539c2082 100644 --- a/board/dnp1110/memsetup.S +++ b/board/dnp1110/memsetup.S @@ -25,8 +25,8 @@ -#include <config.h> -#include <version.h> +#include "config.h" +#include "version.h"  /* some parameters for the board */ @@ -34,63 +34,103 @@  MEM_BASE:	.long	0xa0000000  MEM_START:	.long	0xc0000000 -#define	MDCNFG	0x00 -#define MDCAS0	0x04 -#define MDCAS1	0x08 -#define MDCAS2	0x0c -#define MSC0	0x10 -#define MSC1	0x14 -#define MECR	0x18 +#define MDCNFG		0x00 +#define MDCAS00		0x04		/* CAS waveform rotate reg 0       */ +#define MDCAS01		0x08		/* CAS waveform rotate reg 1 bank  */ +#define MDCAS02		0x0C		/* CAS waveform rotate reg 2 bank  */ +#define MDREFR		0x1C		/* DRAM refresh control reg        */ +#define MDCAS20		0x20		/* CAS waveform rotate reg 0 bank  */  +#define MDCAS21		0x24		/* CAS waveform rotate reg 1 bank  */ +#define MDCAS22		0x28		/* CAS waveform rotate reg 2 bank  */ +#define MECR		0x18		/* Expansion memory (PCMCIA) bus configuration  register */ +#define MSC0		0x10		/* static memory control reg 0     */ +#define MSC1		0x14		/* static memory control reg 1     */ +#define MSC2		0x2C		/* static memory control reg 2     */ +#define SMCNFG		0x30		/* SMROM configuration reg         */ -mdcas0:		.long	0xc71c703f -mdcas1:		.long	0xffc71c71 -mdcas2:		.long	0xffffffff -/* mdcnfg:		.long   0x0bb2bcbf */ -mdcnfg:		.long	0x0334b22f	@ alt -/* mcs0:		.long   0xfff8fff8 */ -msc0:		.long	0xad8c4888	@ alt -mecr:		.long	0x00060006 -/* mecr:		.long	0x994a994a	@ alt */ +mdcas00:	.long	0x5555557F +mdcas01:	.long	0x55555555 +mdcas02:	.long	0x55555555 +mdcas20:	.long	0x5555557F +mdcas21:	.long	0x55555555 +mdcas22:	.long	0x55555555 +mdcnfg:		.long	0x0000B25C +mdrefr:		.long	0x007000C1 +mecr:		.long	0x10841084 +msc0:		.long	0x00004774 +msc1:		.long	0x00000000 +msc2:		.long	0x00000000 +smcnfg:		.long	0x00000000  /* setting up the memory */  .globl memsetup  memsetup: -	ldr	r0, MEM_BASE -	/* Setup the flash memory */ -	ldr	r1, msc0 -	str	r1, [r0, #MSC0] +	ldr	r0, MEM_BASE  	/* Set up the DRAM */ -	/* MDCAS0 */ -	ldr	r1, mdcas0 -	str	r1, [r0, #MDCAS0] +	/* MDCAS00 */ +	ldr	r1, mdcas00 +	str	r1, [r0, #MDCAS00] -	/* MDCAS1 */ -	ldr	r1, mdcas1 -	str	r1, [r0, #MDCAS1] +	/* MDCAS01 */ +	ldr	r1, mdcas01 +	str	r1, [r0, #MDCAS01] -	/* MDCAS2 */ -	ldr	r1, mdcas2 -	str	r1, [r0, #MDCAS2] +	/* MDCAS02 */ +	ldr	r1, mdcas02 +	str	r1, [r0, #MDCAS02] -	/* MDCNFG */ -	ldr	r1, mdcnfg -	str	r1, [r0, #MDCNFG] +	/* MDCAS20 */ +	ldr	r1, mdcas20 +	str	r1, [r0, #MDCAS20] + +	/* MDCAS21 */ +	ldr	r1, mdcas21 +	str	r1, [r0, #MDCAS21] + +	/* MDCAS22 */ +	ldr	r1, mdcas22 +	str	r1, [r0, #MDCAS22] + +	/* MDREFR */ +	ldr	r1, mdrefr +	str	r1, [r0, #MDREFR]  	/* Set up PCMCIA space */  	ldr	r1, mecr  	str	r1, [r0, #MECR] -	/* Load something to activate bank */ -	ldr	r1, MEM_START +	/* Setup the flash memory and other */ +	ldr	r1, msc0 +	str	r1, [r0, #MSC0] +	ldr	r1, msc1 +	str	r1, [r0, #MSC1] + +	ldr	r1, msc2 +	str	r1, [r0, #MSC2] + +	ldr	r1, smcnfg +	str	r1, [r0, #SMCNFG] + +	/* MDCNFG */ +	ldr	r1, mdcnfg +	bic	r1, r1, #0x00000001 +	str	r1, [r0, #MDCNFG] + +	/* Load something to activate bank */ +	ldr	r2, MEM_START  .rept	8 -	ldr	r0, [r1] +	ldr	r1, [r2]  .endr +	/* MDCNFG */ +	ldr	r1, mdcnfg +	orr	r1, r1, #0x00000001 +	str	r1, [r0, #MDCNFG] +  	/* everything is fine now */  	mov	pc, lr - diff --git a/board/ebony/flash.c b/board/ebony/flash.c index 6efd566e8..961c61656 100644 --- a/board/ebony/flash.c +++ b/board/ebony/flash.c @@ -327,6 +327,9 @@ void flash_print_info  (flash_info_t *info)  			case (FLASH_WORD_SIZE)SST_MANUFACT:  				info->flash_id = FLASH_MAN_SST;  				break; +			case (FLASH_WORD_SIZE)STM_MANUFACT: +				info->flash_id = FLASH_MAN_STM; +				break;  			default:  				info->flash_id = FLASH_UNKNOWN;  				info->sector_count = 0; @@ -349,6 +352,11 @@ void flash_print_info  (flash_info_t *info)  				info->sector_count = 32;  				info->size = 0x00200000;  				break;				/* => 2 MB		*/ +                        case (FLASH_WORD_SIZE)STM_ID_F040B: +                                info->flash_id += FLASH_AM040; +                                info->sector_count = 8; +                                info->size = 0x0080000; /* => 512 ko */ +                                break;				  			case (FLASH_WORD_SIZE)AMD_ID_F040B:  				info->flash_id += FLASH_AM040;  				info->sector_count = 8; diff --git a/board/innokom/flash.c b/board/innokom/flash.c index b56707d23..32c57d8d9 100644 --- a/board/innokom/flash.c +++ b/board/innokom/flash.c @@ -9,6 +9,9 @@   * (C) Copyright 2002   * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>   * + * (C) Copyright 2002 + * Kai-Uwe Bloem, GDS, <kai-uwe.bloem@auerswald.de> + *   * See file CREDITS for list of people who contributed to this   * project.   * diff --git a/board/innokom/innokom.c b/board/innokom/innokom.c index 0176d9c2c..5ee511764 100644 --- a/board/innokom/innokom.c +++ b/board/innokom/innokom.c @@ -39,20 +39,28 @@   * The Innokom board has GPIO70 connected to SCLK which can be toggled   * until all chips think that their current cycles are finished.   */ -void i2c_init_board(void) +int i2c_init_board(void)  { -	int i; +	int i, icr; -	/* set gpio pin to output */ -        GPDR(70) |= GPIO_bit(70); -	for (i = 0; i < 11; i++) { +	/* disable I2C controller first, otherwhise it thinks we want to    */ +	/* talk to the slave port...                                        */ +	icr = ICR; ICR &= ~(ICR_SCLE | ICR_IUE); +	 +	/* set gpio pin low _before_ we change direction to output          */  		GPCR(70) = GPIO_bit(70); +	 +	/* now toggle between output=low and high-impedance                 */ +	for (i = 0; i < 20; i++) { +		GPDR(70) |= GPIO_bit(70);  /* output */  		udelay(10); -		GPSR(70)  = GPIO_bit(70); +		GPDR(70) &= ~GPIO_bit(70); /* input  */  		udelay(10);  	} -        /* set gpio pin to input */ -        GPDR(70) &= ~GPIO_bit(70); + +	ICR = icr; + +	return 0;  } @@ -98,6 +106,9 @@ int board_init (void)  	/* adress of boot parameters */  	gd->bd->bi_boot_params = 0xa0000100; +	/* baud rate */ +	gd->bd->bi_baudrate = CONFIG_BAUDRATE; +  	return 0;  } diff --git a/board/svm_sc8xx/Makefile b/board/svm_sc8xx/Makefile new file mode 100644 index 000000000..ef173d036 --- /dev/null +++ b/board/svm_sc8xx/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(BOARD).a + +OBJS	= $(BOARD).o flash.o + +$(LIB):	.depend $(OBJS) +	$(AR) crv $@ $^ + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/svm_sc8xx/config.mk b/board/svm_sc8xx/config.mk new file mode 100644 index 000000000..4bec9cbe8 --- /dev/null +++ b/board/svm_sc8xx/config.mk @@ -0,0 +1,24 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +TEXT_BASE = 0x40000000 diff --git a/board/svm_sc8xx/flash.c b/board/svm_sc8xx/flash.c new file mode 100644 index 000000000..8c0e22913 --- /dev/null +++ b/board/svm_sc8xx/flash.c @@ -0,0 +1,801 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@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 + */ + +#include <common.h> +#include <mpc8xx.h> + +#ifndef	CFG_ENV_ADDR +#define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET) +#endif + +flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ + +/*----------------------------------------------------------------------- + * Functions + */ +static int write_word (flash_info_t *info, ulong dest, ulong data); +#if 0 +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static void flash_get_offsets (ulong base, flash_info_t *info); +#endif +#ifdef  CONFIG_BOOT_8B +static int my_in_8( unsigned char *addr); +static  void my_out_8( unsigned char *addr, int val); +#endif +#ifdef  CONFIG_BOOT_16B +static  int my_in_be16( unsigned short *addr); +static  void my_out_be16( unsigned short *addr, int val); +#endif +#ifdef  CONFIG_BOOT_32B +static  unsigned my_in_be32( unsigned *addr); +static  void my_out_be32( unsigned *addr, int val); +#endif +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ +	volatile immap_t     *immap  = (immap_t *)CFG_IMMR; +	volatile memctl8xx_t *memctl = &immap->im_memctl; +	unsigned long size_b0, size_b1; +	int i; + +	size_b0=0; +	size_b1=0; +	/* Init: no FLASHes known */ +	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { +		flash_info[i].flash_id = FLASH_UNKNOWN; +	} +#ifdef CFG_DOC_BASE +#ifndef CONFIG_FEL8xx_AT +        memctl->memc_or5 = (0xffff8000 | CFG_OR_TIMING_DOC ); /* 32k bytes */ +        memctl->memc_br5 = CFG_DOC_BASE | 0x401; +#else +        memctl->memc_or3 = (0xffff8000 | CFG_OR_TIMING_DOC ); /* 32k bytes */ +        memctl->memc_br3 = CFG_DOC_BASE | 0x401; +#endif +#endif +#if defined( CONFIG_BOOT_8B) +//        memctl->memc_or0 = 0xfff80ff4; /* 4MB bytes */ +//        memctl->memc_br0 = 0x40000401; +        size_b0 = 0x80000;  /* 512 K */ +        flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM040; +        flash_info[0].sector_count = 8; +        flash_info[0].size = 0x00080000; +        /* set up sector start address table */ +        for (i = 0; i < flash_info[0].sector_count; i++) +        flash_info[0].start[i] = 0x40000000 + (i * 0x10000); +        /* protect all sectors */ +        for (i = 0; i < flash_info[0].sector_count; i++) +        flash_info[0].protect[i] = 0x1; +#elif defined (CONFIG_BOOT_16B) +//        memctl->memc_or0 = 0xfff80ff4; /* 4MB bytes */ +//        memctl->memc_br0 = 0x40000401; +        size_b0 = 0x400000;  /* 4MB , assume AMD29LV320B */ +        flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM320B; +        flash_info[0].sector_count = 67; +        flash_info[0].size = 0x00400000; +        /* set up sector start address table */ +        flash_info[0].start[0] = 0x40000000  ; +        flash_info[0].start[1] = 0x40000000 + 0x4000; +        flash_info[0].start[2] = 0x40000000 + 0x6000; +        flash_info[0].start[3] = 0x40000000 + 0x8000; +        for (i = 4; i < flash_info[0].sector_count; i++) +        flash_info[0].start[i] = 0x40000000 + 0x10000 + ((i-4) * 0x10000); +        /* protect all sectors */ +        for (i = 0; i < flash_info[0].sector_count; i++) +        flash_info[0].protect[i] = 0x1; +#endif									 + + +#ifdef CONFIG_BOOT_32B + +	/* Static FLASH Bank configuration here - FIXME XXX */ + +	size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + +	if (flash_info[0].flash_id == FLASH_UNKNOWN) { +		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", +			size_b0, size_b0<<20); +	} + +	size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + +	if (size_b1 > size_b0) { +		printf ("## ERROR: " +			"Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", +			size_b1, size_b1<<20, +			size_b0, size_b0<<20 +		); +		flash_info[0].flash_id	= FLASH_UNKNOWN; +		flash_info[1].flash_id	= FLASH_UNKNOWN; +		flash_info[0].sector_count	= -1; +		flash_info[1].sector_count	= -1; +		flash_info[0].size		= 0; +		flash_info[1].size		= 0; +		return (0); +	} + +	/* Remap FLASH according to real size */ +	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK); +	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; + +	/* Re-do sizing to get full correct info */ +	size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + +	flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +	/* monitor protection ON by default */ +	flash_protect(FLAG_PROTECT_SET, +		      CFG_MONITOR_BASE, +		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, +		      &flash_info[0]); +#endif + +#ifdef	CFG_ENV_IS_IN_FLASH +	/* ENV protection ON by default */ +	flash_protect(FLAG_PROTECT_SET, +		      CFG_ENV_ADDR, +		      CFG_ENV_ADDR+CFG_ENV_SIZE-1, +		      &flash_info[0]); +#endif + +	if (size_b1) { +		memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000); +		memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | +				    BR_MS_GPCM | BR_V; + +		/* Re-do sizing to get full correct info */ +		size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0), +					  &flash_info[1]); + +		flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +		/* monitor protection ON by default */ +		flash_protect(FLAG_PROTECT_SET, +			      CFG_MONITOR_BASE, +			      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, +			      &flash_info[1]); +#endif + +#ifdef	CFG_ENV_IS_IN_FLASH +		/* ENV protection ON by default */ +		flash_protect(FLAG_PROTECT_SET, +			      CFG_ENV_ADDR, +			      CFG_ENV_ADDR+CFG_ENV_SIZE-1, +			      &flash_info[1]); +#endif +	} else { +		memctl->memc_br1 = 0;		/* invalidate bank */ + +		flash_info[1].flash_id = FLASH_UNKNOWN; +		flash_info[1].sector_count = -1; +	} + +	flash_info[0].size = size_b0; +	flash_info[1].size = size_b1; + + +#endif  /* CONFIG_BOOT_32B */ + +	return (size_b0 + size_b1); +} +#if 0 +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ +	int i; + +	/* set up sector start address table */ +	if (info->flash_id & FLASH_BTYPE) { +		/* set sector offsets for bottom boot block type	*/ +		info->start[0] = base + 0x00000000; +		info->start[1] = base + 0x00008000; +		info->start[2] = base + 0x0000C000; +		info->start[3] = base + 0x00010000; +		for (i = 4; i < info->sector_count; i++) { +			info->start[i] = base + (i * 0x00020000) - 0x00060000; +		} +	} else { +		/* set sector offsets for top boot block type		*/ +		i = info->sector_count - 1; +		info->start[i--] = base + info->size - 0x00008000; +		info->start[i--] = base + info->size - 0x0000C000; +		info->start[i--] = base + info->size - 0x00010000; +		for (; i >= 0; i--) { +			info->start[i] = base + i * 0x00020000; +		} +	} +} +#endif +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +	int i; + +	if (info->flash_id == FLASH_UNKNOWN) { +		printf ("missing or unknown FLASH type\n"); +		return; +	} + +	switch (info->flash_id & FLASH_VENDMASK) { +	case FLASH_MAN_AMD:	printf ("AMD ");		break; +	case FLASH_MAN_FUJ:	printf ("FUJITSU ");		break; +	default:		printf ("Unknown Vendor ");	break; +	} + +	switch (info->flash_id & FLASH_TYPEMASK) { +	case FLASH_AM400B:	printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM400T:	printf ("AM29LV400T (4 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM800B:	printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM800T:	printf ("AM29LV800T (8 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM160B:	printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM160T:	printf ("AM29LV160T (16 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM320B:	printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM320T:	printf ("AM29LV320T (32 Mbit, top boot sector)\n"); +				break; +	default:		printf ("Unknown Chip Type\n"); +				break; +	} + +	printf ("  Size: %ld MB in %d Sectors\n", +		info->size >> 20, info->sector_count); + +	printf ("  Sector Start Addresses:"); +	for (i=0; i<info->sector_count; ++i) { +		if ((i % 5) == 0) +			printf ("\n   "); +		printf (" %08lX%s", +			info->start[i], +			info->protect[i] ? " (RO)" : "     " +		); +	} +	printf ("\n"); +	return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ +#if 0 +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ +	short i; +	ulong value; +	ulong base = (ulong)addr; + +	/* Write auto select command: read Manufacturer ID */ +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; +	addr[0x0555] = 0x00900090; + +	value = addr[0]; + +	switch (value) { +	case AMD_MANUFACT: +		info->flash_id = FLASH_MAN_AMD; +		break; +	case FUJ_MANUFACT: +		info->flash_id = FLASH_MAN_FUJ; +		break; +	default: +		info->flash_id = FLASH_UNKNOWN; +		info->sector_count = 0; +		info->size = 0; +		return (0);			/* no or unknown flash	*/ +	} + +	value = addr[1];			/* device ID		*/ + +	switch (value) { +	case AMD_ID_LV400T: +		info->flash_id += FLASH_AM400T; +		info->sector_count = 11; +		info->size = 0x00100000; +		break;				/* => 1 MB		*/ + +	case AMD_ID_LV400B: +		info->flash_id += FLASH_AM400B; +		info->sector_count = 11; +		info->size = 0x00100000; +		break;				/* => 1 MB		*/ + +	case AMD_ID_LV800T: +		info->flash_id += FLASH_AM800T; +		info->sector_count = 19; +		info->size = 0x00200000; +		break;				/* => 2 MB		*/ + +	case AMD_ID_LV800B: +		info->flash_id += FLASH_AM800B; +		info->sector_count = 19; +		info->size = 0x00200000; +		break;				/* => 2 MB		*/ + +	case AMD_ID_LV160T: +		info->flash_id += FLASH_AM160T; +		info->sector_count = 35; +		info->size = 0x00400000; +		break;				/* => 4 MB		*/ + +	case AMD_ID_LV160B: +		info->flash_id += FLASH_AM160B; +		info->sector_count = 35; +		info->size = 0x00400000; +		break;				/* => 4 MB		*/ +#if 0	/* enable when device IDs are available */ +	case AMD_ID_LV320T: +		info->flash_id += FLASH_AM320T; +		info->sector_count = 67; +		info->size = 0x00800000; +		break;				/* => 8 MB		*/ + +	case AMD_ID_LV320B: +		info->flash_id += FLASH_AM320B; +		info->sector_count = 67; +		info->size = 0x00800000; +		break;				/* => 8 MB		*/ +#endif +	default: +		info->flash_id = FLASH_UNKNOWN; +		return (0);			/* => no or unknown flash */ +	} + +	/* set up sector start address table */ +	if (info->flash_id & FLASH_BTYPE) { +		/* set sector offsets for bottom boot block type	*/ +		info->start[0] = base + 0x00000000; +		info->start[1] = base + 0x00008000; +		info->start[2] = base + 0x0000C000; +		info->start[3] = base + 0x00010000; +		for (i = 4; i < info->sector_count; i++) { +			info->start[i] = base + (i * 0x00020000) - 0x00060000; +		} +	} else { +		/* set sector offsets for top boot block type		*/ +		i = info->sector_count - 1; +		info->start[i--] = base + info->size - 0x00008000; +		info->start[i--] = base + info->size - 0x0000C000; +		info->start[i--] = base + info->size - 0x00010000; +		for (; i >= 0; i--) { +			info->start[i] = base + i * 0x00020000; +		} +	} + +	/* check for protected sectors */ +	for (i = 0; i < info->sector_count; i++) { +		/* read sector protection at sector address, (A7 .. A0) = 0x02 */ +		/* D0 = 1 if protected */ +		addr = (volatile unsigned long *)(info->start[i]); +		info->protect[i] = addr[2] & 1; +	} + +	/* +	 * Prevent writes to uninitialized FLASH. +	 */ +	if (info->flash_id != FLASH_UNKNOWN) { +		addr = (volatile unsigned long *)info->start[0]; + +		*addr = 0x00F000F0;	/* reset bank */ +	} + +	return (info->size); +} +#endif + +/*----------------------------------------------------------------------- + */ + +int	flash_erase (flash_info_t *info, int s_first, int s_last) +{ +	vu_long *addr = (vu_long*)(info->start[0]); +	int flag, prot, sect, l_sect,in_mid,in_did; +	ulong start, now, last; + +	if ((s_first < 0) || (s_first > s_last)) { +		if (info->flash_id == FLASH_UNKNOWN) { +			printf ("- missing\n"); +		} else { +			printf ("- no sectors to erase\n"); +		} +		return 1; +	} + +	if ((info->flash_id == FLASH_UNKNOWN) || +	    (info->flash_id > FLASH_AMD_COMP)) { +		printf ("Can't erase unknown flash type %08lx - aborted\n", +			info->flash_id); +		return 1; +	} + +	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 { +		printf ("\n"); +	} + +	l_sect = -1; + +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); +#if defined (CONFIG_BOOT_8B ) +	my_out_8( (unsigned char * )  ((ulong)addr+0x555) , 0xaa ); +	my_out_8( (unsigned char * )  ((ulong)addr+0x2aa) , 0x55 ); +	my_out_8( (unsigned char * )  ((ulong)addr+0x555) , 0x90 ); +	in_mid=my_in_8( (unsigned char * ) addr ); +	in_did=my_in_8( (unsigned char * ) ((ulong)addr+1) ); +	printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); +	my_out_8( (unsigned char *)addr, 0xf0); +	udelay(1); +	my_out_8(     (unsigned char *) ((ulong)addr+0x555),0xaa ); +	my_out_8(     (unsigned char *) ((ulong)addr+0x2aa),0x55 ); +	my_out_8(     (unsigned char *) ((ulong)addr+0x555),0x80 ); +	my_out_8(     (unsigned char *) ((ulong)addr+0x555),0xaa ); +	my_out_8(     (unsigned char *) ((ulong)addr+0x2aa),0x55 ); +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) {	/* not protected */ +			addr = (vu_long*)(info->start[sect]); +			//addr[0] = 0x00300030; +			my_out_8(     (unsigned char *) ((ulong)addr),0x30 ); +			l_sect = sect; +		} +	} +#elif defined(CONFIG_BOOT_16B ) +	my_out_be16( (unsigned short * )  ((ulong)addr+ (0xaaa)) , 0xaa ); +	my_out_be16( (unsigned short * )  ((ulong)addr+ (0x554)) , 0x55 ); +	my_out_be16( (unsigned short * )  ((ulong)addr+ (0xaaa)) , 0x90 ); +	in_mid=my_in_be16( (unsigned short * ) addr ); +	in_did=my_in_be16 ( (unsigned short * ) ((ulong)addr+2) ); +	printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); +	my_out_be16( (unsigned short *)addr, 0xf0); +	udelay(1); +	my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xaa ); +	my_out_be16(     (unsigned short *) ((ulong)addr+0x554),0x55 ); +	my_out_be16(     (unsigned short *) ((ulong)addr+0xaaa),0x80 ); +	my_out_be16(     (unsigned short *) ((ulong)addr+0xaaa),0xaa ); +	my_out_be16(     (unsigned short *) ((ulong)addr+0x554),0x55 ); +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) {	/* not protected */ +			addr = (vu_long*)(info->start[sect]); +			my_out_be16(     (unsigned short *) ((ulong)addr),0x30 ); +			l_sect = sect; +		} +	} + +#elif defined(CONFIG_BOOT_32B) +	my_out_be32( (unsigned * )  ((ulong)addr+0x1554) , 0xaa ); +	my_out_be32( (unsigned * )  ((ulong)addr+0xaa8) , 0x55 ); +	my_out_be32( (unsigned  *)  ((ulong)addr+0x1554) , 0x90 ); +	in_mid=my_in_be32( (unsigned  * ) addr ); +	in_did=my_in_be32( (unsigned  * ) ((ulong)addr+4) ); +	printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); +	my_out_be32( (unsigned *)addr, 0xf0); +	udelay(1); +	my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0xaa ); +	my_out_be32(     (unsigned  *) ((ulong)addr+0xaa8),0x55 ); +	my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0x80 ); +	my_out_be32(     (unsigned  *) ((ulong)addr+0x1554),0xaa ); +	my_out_be32(     (unsigned  *) ((ulong)addr+0xaa8),0x55 ); +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) {	/* not protected */ +			addr = (vu_long*)(info->start[sect]); +			my_out_be32(     (unsigned *) ((ulong)addr),0x00300030 ); +			l_sect = sect; +		} +	} + +#else +# error CONFIG_BOOT_(size)B missing. +#endif +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +	/* wait at least 80us - let's wait 1 ms */ +	udelay (1000); + +	/* +	 * We wait for the last triggered sector +	 */ +	if (l_sect < 0) +		goto DONE; + +	start = get_timer (0); +	last  = start; +	addr = (vu_long*)(info->start[l_sect]); +#if defined (CONFIG_BOOT_8B) +	while (  (my_in_8((unsigned char *)addr) & 0x80) != 0x80 )  +#elif defined(CONFIG_BOOT_16B ) +	while (  (my_in_be16((unsigned short *)addr) & 0x0080) != 0x0080 )  +#elif defined(CONFIG_BOOT_32B) +	while (  (my_in_be32((unsigned  *)addr) & 0x00800080) != 0x00800080 )  +#else +# error CONFIG_BOOT_(size)B missing. +#endif +	{ +		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { +			printf ("Timeout\n"); +			return 1; +		} +		/* show that we're waiting */ +		if ((now - last) > 1000) {	/* every second */ +			putc ('.'); +			last = now; +		} +	} +DONE: +	/* reset to read mode */ +	addr = (volatile unsigned long *)info->start[0]; +#if defined (CONFIG_BOOT_8B) +	my_out_8( (unsigned char *)addr, 0xf0); +#elif defined(CONFIG_BOOT_16B ) +	my_out_be16( (unsigned short * ) addr , 0x00f0 ); +#elif defined(CONFIG_BOOT_32B) +	my_out_be32 ( (unsigned *)addr,  0x00F000F0 );	/* reset bank */ +#else +# error CONFIG_BOOT_(size)B missing. +#endif +	printf (" done\n"); +	return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +	ulong cp, wp, data; +	int i, l, rc; + +	wp = (addr & ~3);	/* 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); +		} +		for (; i<4 && cnt>0; ++i) { +			data = (data << 8) | *src++; +			--cnt; +			++cp; +		} +		for (; cnt==0 && i<4; ++i, ++cp) { +			data = (data << 8) | (*(uchar *)cp); +		} + +		if ((rc = write_word(info, wp, data)) != 0) { +			return (rc); +		} +		wp += 4; +	} + +	/* +	 * handle word aligned part +	 */ +	while (cnt >= 4) { +		data = 0; +		for (i=0; i<4; ++i) { +			data = (data << 8) | *src++; +		} +		if ((rc = write_word(info, wp, data)) != 0) { +			return (rc); +		} +		wp  += 4; +		cnt -= 4; +	} + +	if (cnt == 0) { +		return (0); +	} + +	/* +	 * handle unaligned tail bytes +	 */ +	data = 0; +	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +		data = (data << 8) | *src++; +		--cnt; +	} +	for (; i<4; ++i, ++cp) { +		data = (data << 8) | (*(uchar *)cp); +	} + +	return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +	ulong addr = (ulong)(info->start[0]); +	ulong start,last; +	int flag; +	ulong i; +	int  data_short[2]; + +	/* Check if Flash is (sufficiently) erased */ +	if ( ((ulong)  *(ulong *)dest & data) != data ) { +		return (2); +	} +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); +#if defined(CONFIG_BOOT_8B) +#ifdef DEBUG +	{ +	int in_mid,in_did; +	my_out_8( (unsigned char * )  (addr+0x555) , 0xaa ); +	my_out_8( (unsigned char * )  (addr+0x2aa) , 0x55 ); +	my_out_8( (unsigned char * )  (addr+0x555) , 0x90 ); +	in_mid=my_in_8( (unsigned char * ) addr ); +	in_did=my_in_8( (unsigned char * ) (addr+1) ); +  	printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); +	my_out_8( (unsigned char *)addr, 0xf0); +	udelay(1); +	} +#endif +      { +	int  data_ch[4]; +	data_ch[0]=(int ) ((data>>24) & 0xff); +	data_ch[1]=(int ) ((data>>16) &0xff );  +	data_ch[2]=(int ) ((data >>8) & 0xff); +	data_ch[3]=(int ) (data & 0xff); +	for (i=0;i<4;i++ ){ +	  my_out_8( (unsigned char *) (addr+0x555),0xaa); +	  my_out_8((unsigned char *) (addr+0x2aa),0x55); +	  my_out_8( (unsigned char *)  (addr+0x555),0xa0); +	  my_out_8((unsigned char *)  (dest+i) ,data_ch[i]); +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +  	  start = get_timer (0); +	last  = start; +	  while(  ( my_in_8((unsigned char *) (dest+i)) ) != ( data_ch[i]  ) ) { +		  if (get_timer(start) > CFG_FLASH_WRITE_TOUT ) { +			  return 1; +		  } +	  } +	}/* for */ +     } +#elif defined( CONFIG_BOOT_16B) +	data_short[0]=(int) (data>>16) & 0xffff; +	data_short[1]=(int ) data & 0xffff ;  +	for (i=0;i<2;i++ ){ +	my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xaa ); +	my_out_be16(     (unsigned short *) ((ulong)addr+ 0x554),0x55 ); +	my_out_be16(     (unsigned short *) ((ulong)addr+ 0xaaa),0xa0 ); +	my_out_be16(  (unsigned short *) (dest+(i*2)) ,data_short[i]); +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); +  	  start = get_timer (0); +	last  = start; +	  while(  ( my_in_be16((unsigned short *) (dest+(i*2))) ) != ( data_short[i]  ) ) { +		  if (get_timer(start) > CFG_FLASH_WRITE_TOUT ) { +			  return 1; +		  } +	  } +	} +#elif defined( CONFIG_BOOT_32B) +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; +	addr[0x0555] = 0x00A000A0; + +	*((vu_long *)dest) = data; + +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +	/* data polling for D7 */ +	start = get_timer (0); +	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) { +		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { +			return (1); +		} +	} +#endif +	 +	 +	return (0); +} +#ifdef  CONFIG_BOOT_8B +static int my_in_8  ( unsigned char *addr) +{ +       int ret; +       __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); +       return ret; +} + +static void my_out_8  ( unsigned char *addr, int val) +{ +       __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif +#ifdef  CONFIG_BOOT_16B +static int my_in_be16( unsigned short *addr) +{ +       int ret; +        __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); +			        return ret; +} +static void my_out_be16( unsigned short *addr, int val) +{ +       __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif +#ifdef  CONFIG_BOOT_32B +static  unsigned my_in_be32( unsigned *addr) +{ +        unsigned ret; +        __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); +			        return ret; +} +static  void my_out_be32( unsigned *addr, int val) +{ +       __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif + + + diff --git a/board/svm_sc8xx/ppcboot.lds b/board/svm_sc8xx/ppcboot.lds new file mode 100644 index 000000000..5f5e2e428 --- /dev/null +++ b/board/svm_sc8xx/ppcboot.lds @@ -0,0 +1,133 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@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_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    cpu/mpc8xx/start.o	(.text) +    common/dlmalloc.o	(.text) +    ppc/ppcstring.o	(.text) +    ppc/vsprintf.o	(.text) +    ppc/crc32.o		(.text) +    ppc/zlib.o		(.text) + +    . = env_offset; +    common/environment.o(.text) + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x00FF) & 0xFFFFFF00; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(256); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(256); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} + diff --git a/board/svm_sc8xx/ppcboot.lds.debug b/board/svm_sc8xx/ppcboot.lds.debug new file mode 100644 index 000000000..f230a6b49 --- /dev/null +++ b/board/svm_sc8xx/ppcboot.lds.debug @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@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_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    cpu/mpc8xx/start.o	(.text) +    common/dlmalloc.o	(.text) +    ppc/vsprintf.o	(.text) +    ppc/crc32.o		(.text) + +    . = env_offset; +    common/environment.o(.text) + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} + diff --git a/board/svm_sc8xx/svm_sc8xx.c b/board/svm_sc8xx/svm_sc8xx.c new file mode 100644 index 000000000..db3162a0e --- /dev/null +++ b/board/svm_sc8xx/svm_sc8xx.c @@ -0,0 +1,163 @@ +/* + * (C) Copyright 2000, 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@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 + */ + +#include <common.h> +#include <mpc8xx.h> + +/* ------------------------------------------------------------------------- */ +const uint sdram_table[] = +{ +/*----------------- + UPM A contents: +----------------- */ +/*--------------------------------------------------- + Read Single Beat Cycle. Offset 0 in the RAM array. +---------------------------------------------------- */ +0x1f07fc04,  0xeeaefc04,  0x11adfc04,  0xefbbbc00 , +0x1ff77c47,  0x1ff77c35,  0xefeabc34,  0x1fb57c35 , +/*------------------------------------------------ + Read Burst Cycle. Offset 0x8 in the RAM array. +------------------------------------------------ */ +0x1f07fc04,  0xeeaefc04,  0x10adfc04,  0xf0affc00, +0xf0affc00,  0xf1affc00,  0xefbbbc00,  0x1ff77c47, +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff, +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff, +/*------------------------------------------------------- + Write Single Beat Cycle. Offset 0x18 in the RAM array +------------------------------------------------------- */ +0x1f27fc04,  0xeeaebc00,  0x01b93c04,  0x1ff77c47 , +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff , +/*------------------------------------------------- + Write Burst Cycle. Offset 0x20 in the RAM array +------------------------------------------------- */ +0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00, +0xf0affc00, 0xe1bbbc04, 0x1ff77c47, 0xffffffff, +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff , +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff , +/*------------------------------------------------------------------------ + Periodic Timer Expired. For DRAM refresh. Offset 0x30 in the RAM array +------------------------------------------------------------------------ */ +0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04, +0xfffffc84, 0xfffffc07, 0xffffffff, 0xffffffff, +0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff , +/*----------- +*  Exception: +*  ----------- */ +0x7ffefc07,  0xffffffff,  0xffffffff,  0xffffffff , +}; + +/* ------------------------------------------------------------------------- */ +/* + * Check Board Identity: + * + * Test ID string (SVM8...) + * + * Return 1 for "SC8xx" type, 0 else. + */ + +int checkboard (void) +{ +    unsigned char *s = getenv("serial#"); +    int board_type; + +    if (!s || strncmp(s, "SVM8", 4)) { +	printf ("### No HW ID - assuming SVM SC8xx\n"); +	return (0); +    } + +    board_type = 1; + +    for (; *s; ++s) { +	if (*s == ' ') +	    break; +	putc (*s); +    } + +    putc ('\n'); + +    return (0); +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{     +	volatile immap_t     *immap  = (immap_t *)CFG_IMMR; +	volatile memctl8xx_t *memctl = &immap->im_memctl; +	long int size_b0 = 0; + +	upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + +	memctl->memc_mptpr = CFG_MPTPR; +#if defined (CONFIG_SDRAM_16M) +	memctl->memc_mamr = 0x00802114 | CFG_MxMR_PTx; +	memctl->memc_mcr  = 0x80002105;     /* SDRAM bank 0 */ +	udelay(1); +	memctl->memc_mcr  = 0x80002830; +	udelay(1); +	memctl->memc_mar  = 0x00000088; +	udelay(1); +	memctl->memc_mcr  = 0x80002106; +	udelay(1); +	memctl->memc_or1 =  0xff000a00; +	size_b0 = 0x01000000; +#elif defined (CONFIG_SDRAM_32M) +	memctl->memc_mamr = 0x00904114 | CFG_MxMR_PTx; +	memctl->memc_mcr  = 0x80002105;     /* SDRAM bank 0 */ +	udelay(1); +	memctl->memc_mcr  = 0x80002830; +	udelay(1); +	memctl->memc_mar  = 0x00000088; +	udelay(1); +	memctl->memc_mcr  = 0x80002106; +	udelay(1); +	memctl->memc_or1 =  0xfe000a00; +	size_b0 = 0x02000000; +#elif defined (CONFIG_SDRAM_64M) +	memctl->memc_mamr = 0x00a04114 | CFG_MxMR_PTx; +	memctl->memc_mcr  = 0x80002105;     /* SDRAM bank 0 */ +	udelay(1); +	memctl->memc_mcr  = 0x80002830; +	udelay(1); +	memctl->memc_mar  = 0x00000088; +	udelay(1); +	memctl->memc_mcr  = 0x80002106; +	udelay(1); +	memctl->memc_or1 =  0xfc000a00; +	size_b0 = 0x04000000; +#else  +#error SDRAM size configuration missing. +#endif +	memctl->memc_br1 =  0x00000081; +	udelay(200); +	return (size_b0 ); +} + +#if (CONFIG_COMMANDS & CFG_CMD_DOC) +extern void doc_probe (ulong physadr); +void doc_init (void) +{ +	        doc_probe (CFG_DOC_BASE); +} +#endif + diff --git a/board/svm_sc8xx/u-boot.lds b/board/svm_sc8xx/u-boot.lds new file mode 100644 index 000000000..17fea2e6c --- /dev/null +++ b/board/svm_sc8xx/u-boot.lds @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@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_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)	} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)	} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)	} +  .rela.got      : { *(.rela.got)	} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)	} +  .rela.bss      : { *(.rela.bss)	} +  .rel.plt       : { *(.rel.plt)	} +  .rela.plt      : { *(.rela.plt)	} +  .init          : { *(.init)		} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    cpu/mpc8xx/start.o		(.text) +    cpu/mpc8xx/traps.o		(.text) +    common/dlmalloc.o		(.text) +    lib_ppc/ppcstring.o		(.text) +    lib_generic/vsprintf.o	(.text) +    lib_generic/crc32.o		(.text) +    lib_generic/zlib.o		(.text) +    lib_ppc/cache.o		(.text) +    lib_ppc/time.o		(.text) + +    . = env_offset; +    common/environment.o	(.ppcenv) + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x00FF) & 0xFFFFFF00; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(256); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(256); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} + diff --git a/board/svm_sc8xx/u-boot.lds.debug b/board/svm_sc8xx/u-boot.lds.debug new file mode 100644 index 000000000..22138f8aa --- /dev/null +++ b/board/svm_sc8xx/u-boot.lds.debug @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@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_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    cpu/mpc8xx/start.o	(.text) +    common/dlmalloc.o	(.text) +    lib_generic/vsprintf.o	(.text) +    lib_generic/crc32.o		(.text) + +    . = env_offset; +    common/environment.o(.text) + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x0FFF) & 0xFFFFF000; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(4096); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(4096); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} + diff --git a/common/Makefile b/common/Makefile index 67387ef64..123871cf2 100644 --- a/common/Makefile +++ b/common/Makefile @@ -30,7 +30,7 @@ AOBJS	=  COBJS	= main.o altera.o bedbug.o \  	  cmd_autoscript.o cmd_bedbug.o cmd_boot.o \  	  cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o \ -	  cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o \ +	  cmd_dcr.o cmd_diag.o cmd_doc.o cmd_nand.o cmd_dtt.o \  	  cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_fdos.o cmd_flash.o \  	  cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \  	  cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \ diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 2604e41bf..1c9a41d8e 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -153,10 +153,9 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	print_num ("boot_params",	(ulong)bd->bi_boot_params);  	for (i=0; i<CONFIG_NR_DRAM_BANKS; ++i) { -		printf ("DRAM:%02d.start = %08lX\n", -			i, bd->bi_dram[i].start); -		printf ("DRAM:%02d.size  = %08lX\n", -			i, bd->bi_dram[i].size); +		print_num("DRAM bank",	i); +		print_num("-> start",	bd->bi_dram[i].start); +		print_num("-> size",	bd->bi_dram[i].size);  	}  	printf ("ethaddr     ="); @@ -200,7 +199,7 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	addr = simple_strtoul(argv[1], NULL, 16); -	printf ("## Starting application at 0x%08lx ...\n", addr); +	printf ("## Starting application at 0x%08lX ...\n", addr);  	/*  	 * pass address parameter as argv[0] (aka command name), @@ -209,7 +208,7 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);  	if (rc != 0) rcode = 1; -	printf ("## Application terminated, rc = 0x%lx\n", rc); +	printf ("## Application terminated, rc = 0x%lX\n", rc);  	return rcode;  } @@ -285,7 +284,7 @@ int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		printf ("## S-Record download aborted\n");  		rcode = 1;  	} else { -		printf ("## Start Addr      = 0x%08lx\n", addr); +		printf ("## Start Addr      = 0x%08lX\n", addr);  		load_addr = addr;  	} @@ -345,9 +344,9 @@ load_serial (ulong offset)  			memcpy ((char *)(store_addr), binbuf, binlen);  		    }  		    if ((store_addr) < start_addr) -		    	start_addr = store_addr; +			start_addr = store_addr;  		    if ((store_addr + binlen - 1) > end_addr) -		    	end_addr = store_addr + binlen - 1; +			end_addr = store_addr + binlen - 1;  		    break;  		case SREC_END2:  		case SREC_END3: @@ -606,9 +605,17 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	ulong offset = 0;  	ulong addr; -	int i;  	int load_baudrate, current_baudrate;  	int rcode = 0; +	char *s; + +	/* pre-set offset from CFG_LOAD_ADDR */ +	offset = CFG_LOAD_ADDR; + +	/* pre-set offset from $loadaddr */ +	if ((s = getenv("loadaddr")) != NULL) { +		offset = simple_strtoul(s, NULL, 16); +	}  	load_baudrate = current_baudrate = gd->baudrate; @@ -635,28 +642,19 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  				break;  		}  	} -	printf ("## Ready for binary (kermit) download ...\n"); +	printf ("## Ready for binary (kermit) download " +		"to 0x%08lX at %d bps...\n", +		offset, +		current_baudrate);  	addr = load_serial_bin (offset); -	/* -	 * Gather any trailing characters (for instance, the ^D which -	 * is sent by 'cu' after sending a file), and give the -	 * box some time (100 * 1 ms) -	 */ -	for (i=0; i<100; ++i) { -		if (serial_tstc()) { -			(void) serial_getc(); -		} -		udelay(1000); -	} -  	if (addr == ~0) {  		load_addr = 0;  		printf ("## Binary (kermit) download aborted\n");  		rcode = 1;  	} else { -		printf ("## Start Addr      = 0x%08lx\n", addr); +		printf ("## Start Addr      = 0x%08lX\n", addr);  		load_addr = addr;  	} diff --git a/common/cmd_nand.c b/common/cmd_nand.c new file mode 100644 index 000000000..356b592d5 --- /dev/null +++ b/common/cmd_nand.c @@ -0,0 +1,1545 @@ +/* + * Driver for NAND support, Rick Bronson + * borrowed heavily from: + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> + * + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <malloc.h> +#include <asm/io.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 + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <linux/mtd/nftl.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ids.h> + +/* + * 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}; + +#define	NAND_DEBUG +#undef	ECC_DEBUG +#undef	PSYCHO_DEBUG +#undef	NFTL_DEBUG + +#define CONFIG_MTD_NAND_ECC  /* enable ECC */ +/* #define CONFIG_MTD_NAND_ECC_JFFS2 */ + +/* + * Function Prototypes + */ +static void nand_print(struct nand_chip *nand); +static int nand_rw (struct nand_chip* nand, int cmd, +	    size_t start, size_t len, +	    size_t * retlen, u_char * buf); +static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len); +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); +#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 + +static 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 rcode = 0; + +    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; + +		putc ('\n'); + +		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; + +	} 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 ("\nDevice %d: ", curr_device); +		nand_print(&nand_dev_desc[curr_device]); +		return 0; +	} +	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); + +		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);*/ + +		if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { +			return 1; +		} + +		curr_device = dev; + +		puts ("... is now current device\n"); + +		return 0; +	} + +	printf ("Usage:\n%s\n", cmdtp->usage); +	return 1; +    default: +	/* at least 4 args */ + +	if (strcmp(argv[1],"read") == 0 || strcmp(argv[1],"write") == 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    = (strcmp(argv[1],"read") == 0); +		int ret, total; + +		printf ("\nNAND %s: device %d offset %ld, size %ld ... ", +			cmd ? "read" : "write", curr_device, off, size); + +		ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size, +			     &total, (u_char*)addr); + +		printf ("%d bytes %s: %s\n", total, cmd ? "read" : "write", +			ret ? "ERROR" : "OK"); + +		return ret; +	} else if (strcmp(argv[1],"erase") == 0) { +		ulong off = simple_strtoul(argv[2], NULL, 16); +		ulong size = simple_strtoul(argv[3], NULL, 16); +		int ret; + +		printf ("\nNAND erase: device %d offset %ld, size %ld ... ", +			curr_device, off, size); + +		ret = nand_erase (nand_dev_desc + curr_device, off, size); + +		printf("%s\n", ret ? "ERROR" : "OK"); + +		return ret; +	} else { +		printf ("Usage:\n%s\n", cmdtp->usage); +		rcode = 1; +	} + +	return rcode; +    } +} + +int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	char *boot_device = NULL; +	char *ep; +	int dev; +	ulong cnt; +	ulong addr; +	ulong offset = 0; +	image_header_t *hdr; +	int rcode = 0; +	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 >= 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; +	} + +	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); + +	if (nand_rw (nand_dev_desc + dev, 1, offset, +		    SECTORSIZE, NULL, (u_char *)addr)) { +		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) { + +		print_image_hdr (hdr); + +		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; +	} + +	if (nand_rw (nand_dev_desc + dev, 1, offset + SECTORSIZE, cnt, +		    NULL, (u_char *)(addr+SECTORSIZE))) { +		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); +		rcode = 1; +	} +	return rcode; +} + +static int nand_rw (struct nand_chip* nand, int cmd, +	    size_t start, size_t len, +	    size_t * retlen, u_char * buf) +{ +	int noecc, ret = 0, n, total = 0; +	char eccbuf[6]; + +	while(len) { +		/* The ECC will not be calculated correctly if +		   less than 512 is written or read */ +		noecc = (start != (start | 0x1ff) + 1) ||	(len < 0x200); +		if (cmd) +			ret = nand_read_ecc(nand, start, len, +					   &n, (u_char*)buf, +					   noecc ? NULL : eccbuf); +		else +			ret = nand_write_ecc(nand, start, len, +					    &n, (u_char*)buf, +					    noecc ? NULL : 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) + { +	printf("%s at 0x%lX,\n" +	       "\t  %d chip%s %s, size %d MB, \n" +	       "\t  total size %ld MB, sector size %ld kB\n", +	       nand->name, nand->IO_ADDR, nand->numchips, +	       nand->numchips>1 ? "s" : "", nand->chips_name, +	       1 << (nand->chipshift - 20), +	       nand->totlen >> 20, nand->erasesize >> 10); + +	if (nand->nftl_found) { +		struct NFTLrecord *nftl = &nand->nftl; +		unsigned long bin_size, flash_size; + +		bin_size = nftl->nb_boot_blocks * nand->erasesize; +		flash_size = (nftl->nb_blocks - nftl->nb_boot_blocks) * nand->erasesize; + +		printf("\t  NFTL boot record:\n" +		       "\t    Binary partition: size %ld%s\n" +		       "\t    Flash disk partition: size %ld%s, offset 0x%lx\n", +		       bin_size > (1 << 20) ? bin_size >> 20 : bin_size >> 10, +		       bin_size > (1 << 20) ? "MB" : "kB", +		       flash_size > (1 << 20) ? flash_size >> 20 : flash_size >> 10, +		       flash_size > (1 << 20) ? "MB" : "kB", bin_size); +	} else { +		puts ("\t  No NFTL boot record found.\n"); +	} +} + +/* ------------------------------------------------------------------------- */ + +/* This function is needed to avoid calls of the __ashrdi3 function. */ +static int shr(int val, int shift) + { +	return val >> shift; +} + +static int NanD_WaitReady(struct nand_chip *nand) +{ +	/* This is inline, to optimise the common case, where it's ready instantly */ +	int ret = 0; +        NAND_WAIT_READY(nand); + +	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); + +	return NanD_WaitReady(nand); +} + +/* 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); +  } + +/* 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); +} + +/* 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 */ +	/* No response - return failure */ +	if (mfr == 0xff || mfr == 0) +          { +          printf("NanD_Command (ReadID) got %d %d\n", mfr, id); +          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; +				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; +				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) { +		puts ("No flash chips recognised.\n"); +		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 +} +#ifdef CONFIG_MTD_NAND_ECC +/* we need to be fast here, 1 us per read translates to 1 second per meg */ +static void nand_fast_copy (unsigned char *source, unsigned char *dest, long cntr) +  { +  while (cntr > 16) +    { +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    *dest++ = *source++; +    cntr -= 16; +    } +  while (cntr > 0) +    { +    *dest++ = *source++; +    cntr--; +    } +  } +#endif +/* we need to be fast here, 1 us per read translates to 1 second per meg */ +static void nand_fast_read(unsigned char *data_buf, int cntr, unsigned long nandptr) +  { +  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--; +    } +  } + +/* This routine is made available to other mtd code via + * inter_module_register.  It must only be accessed through + * inter_module_get which will bump the use count of this module.  The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000. + */ + +/* + * 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 +	unsigned long nandptr = nand->IO_ADDR; + +	/* Do not allow reads past end of device */ +	if ((start + len) > nand->totlen) { +		printf ("nand_read_ecc: Attempt read beyond end of device %x %x %x\n", (uint) start, (uint) len, (uint) nand->totlen); +		*retlen = 0; +		return -1; +	} + +	/* First we calculate the starting page */ +	page = shr(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); +                NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); +		/* Read in a page + oob data */ +		nand_fast_read(nand->data_buf, nand->oobblock + nand->oobsize, nandptr); + +		/* 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 ("nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); +				ecc_failed++; +				break; +			case 1: +			case 2:	/* transfer ECC corrected data to 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 ("nand_read_ecc: " "Failed ECC read, page 0x%08x\n", 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) { +			nand_fast_copy (data_poi, buf + *retlen, len - *retlen); +			*retlen = len; +		} else { +			nand_fast_copy (data_poi, buf + *retlen, 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); +                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_fast_read(buf + *retlen, len - *retlen, nandptr); +			*retlen = len; +			/* We're done */ +			continue; +		} else { +			nand_fast_read(buf + *retlen, nand->oobblock - col, nandptr); +			*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; +#ifdef CONFIG_MTD_NAND_ECC +	unsigned long nandptr = nand->IO_ADDR; +#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); +                NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); +		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_SEQIN); +	NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + +	/* Write out complete page of data */ +	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); + +	/* See if device thinks it succeeded */ +	if (READ_NAND(nand->IO_ADDR) & 0x01) { +		printf ("nand_write_ecc: " "Failed write, page 0x%08x, ", 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); +        NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + +	/* Loop through and verify the data */ +	for (i = col; i < last; i++) { +		if (nand->data_buf[i] != readb (nand->IO_ADDR)) { +			printf ("nand_write_ecc: " "Failed write verify, page 0x%08x ", 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); +	NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); +	for (i = 0; i < nand->oobsize; i++) +		nand->data_buf[i] = readb (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 ("nand_write_ecc: Failed ECC write " +			       "verify, page 0x%08x, " "%6i bytes were succesful\n", page, i); +			return -1; +		} +	} +#endif +#endif +	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 ("nand_write_oob: Attempt to write past end of page\n"); +		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 */ +      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; +	} + +	/* 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 */ + +	return ret; +} + +#if 0 /* not used */ +/* Read a buffer from NanD */ +static void NanD_ReadBuf(struct nand_chip *nand, u_char * buf, int len) +{ +	unsigned long nandptr; + +	nandptr = nand->IO_ADDR; + +	for (; len > 0; len--) +		*buf++ = READ_NAND(nandptr); + +} +/* Write a buffer to NanD */ +static void NanD_WriteBuf(struct nand_chip *nand, const u_char * buf, int len) +{ +	unsigned long nandptr; +	int i; + +	nandptr = nand->IO_ADDR; + +	if (len <= 0) +		return; + +	for (i = 0; i < len; i++) +		WRITE_NAND(buf[i], nandptr); + +} + +/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the + *	various device information of the NFTL partition and Bad Unit Table. Update + *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] + *	is used for management of Erase Unit in other routines in nftl.c and nftlmount.c + */ +static int find_boot_record(struct NFTLrecord *nftl) +{ +	struct nftl_uci1 h1; +	struct nftl_oob oob; +	unsigned int block, boot_record_count = 0; +	int retlen; +	u8 buf[SECTORSIZE]; +	struct NFTLMediaHeader *mh = &nftl->MediaHdr; +	unsigned int i; + +	nftl->MediaUnit = BLOCK_NIL; +	nftl->SpareMediaUnit = BLOCK_NIL; + +	/* search for a valid boot record */ +	for (block = 0; block < nftl->nb_blocks; block++) { +		int ret; + +		/* Check for ANAND header first. Then can whinge if it's found but later +		   checks fail */ +		if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, +					&retlen, buf, NULL))) { +			static int warncount = 5; + +			if (warncount) { +				printf("Block read at 0x%x failed\n", block * nftl->EraseSize); +				if (!--warncount) +					puts ("Further failures for this block will not be printed\n"); +			} +			continue; +		} + +		if (retlen < 6 || memcmp(buf, "ANAND", 6)) { +			/* ANAND\0 not found. Continue */ +#ifdef PSYCHO_DEBUG +			printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize); +#endif +			continue; +		} + +#ifdef NFTL_DEBUG +		printf("ANAND header found at 0x%x\n", block * nftl->EraseSize); +#endif + +		/* To be safer with BIOS, also use erase mark as discriminant */ +		if ((ret = nand_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, +				8, &retlen, (char *)&h1) < 0)) { +#ifdef NFTL_DEBUG +			printf("ANAND header found at 0x%x, but OOB data read failed\n", +			       block * nftl->EraseSize); +#endif +			continue; +		} + +		/* OK, we like it. */ + +		if (boot_record_count) { +			/* We've already processed one. So we just check if +			   this one is the same as the first one we found */ +			if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) { +#ifdef NFTL_DEBUG +				printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n", +				       nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize); +#endif +				/* if (debug) Print both side by side */ +				return -1; +			} +			if (boot_record_count == 1) +				nftl->SpareMediaUnit = block; + +			boot_record_count++; +			continue; +		} + +		/* This is the first we've seen. Copy the media header structure into place */ +		memcpy(mh, buf, sizeof(struct NFTLMediaHeader)); + +		/* Do some sanity checks on it */ +		if (mh->UnitSizeFactor != 0xff) { +			puts ("Sorry, we don't support UnitSizeFactor " +			      "of != 1 yet.\n"); +			return -1; +		} + +		nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); +		if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { +			printf ("NFTL Media Header sanity check failed:\n" +				"nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", +				nftl->nb_boot_blocks, nftl->nb_blocks); +			return -1; +		} + +		nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize; +		if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) { +			printf ("NFTL Media Header sanity check failed:\n" +				"numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n", +				nftl->numvunits, +				nftl->nb_blocks, +				nftl->nb_boot_blocks); +			return -1; +		} + +		nftl->nr_sects  = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); + +		/* If we're not using the last sectors in the device for some reason, +		   reduce nb_blocks accordingly so we forget they're there */ +		nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN); + +		/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */ +		for (i = 0; i < nftl->nb_blocks; i++) { +			if ((i & (SECTORSIZE - 1)) == 0) { +				/* read one sector for every SECTORSIZE of blocks */ +				if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize + +						       i + SECTORSIZE, SECTORSIZE, +						       &retlen, buf, (char *)&oob)) < 0) { +					puts ("Read of bad sector table failed\n"); +					return -1; +				} +			} +			/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */ +			if (buf[i & (SECTORSIZE - 1)] != 0xff) +				nftl->ReplUnitTable[i] = BLOCK_RESERVED; +		} + +		nftl->MediaUnit = block; +		boot_record_count++; + +	} /* foreach (block) */ + +	return boot_record_count?0:-1; +} +static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, +		 size_t * retlen, u_char * buf) +{ +	int len256 = 0, ret; +	unsigned long nandptr; +	struct Nand *mychip; + +	nandptr = nand->IO_ADDR; + +	mychip = &nand->chips[shr(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_Command(nand, NAND_CMD_READOOB); +	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); + +	return ret; + +} +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; +	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 + +	/* 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); +	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); +	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_WriteBuf(nand, buf, len256); + +		NanD_Command(nand, NAND_CMD_PAGEPROG); +		NanD_Command(nand, NAND_CMD_STATUS); +		/* NanD_WaitReady() is implicit in NanD_Command */ + +		if (READ_NAND(nandptr) & 1) { +			puts ("Error programming oob data\n"); +			/* There was an error */ +			*retlen = 0; +			return -1; +		} +		NanD_Command(nand, NAND_CMD_SEQIN); +		NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff)); +	} + +	NanD_WriteBuf(nand, &buf[len256], len - len256); + +	NanD_Command(nand, NAND_CMD_PAGEPROG); +	NanD_Command(nand, NAND_CMD_STATUS); +	/* NanD_WaitReady() is implicit in NanD_Command */ + +	if (READ_NAND(nandptr) & 1) { +		puts ("Error programming oob data\n"); +		/* There was an error */ +		*retlen = 0; +		return -1; +	} + +	*retlen = len; +	return 0; + +} +#endif + +static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len) +{ +	unsigned long nandptr; +	struct Nand *mychip; + +	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; + +	/* FIXME: Do nand in the background. Use timers or schedule_task() */ +	while(len) { +		mychip = &nand->chips[shr(ofs, nand->chipshift)]; + +		NanD_Command(nand, NAND_CMD_ERASE1); +		NanD_Address(nand, ADDR_PAGE, ofs); +		NanD_Command(nand, NAND_CMD_ERASE2); + +		NanD_Command(nand, NAND_CMD_STATUS); + +		if (READ_NAND(nandptr) & 1) { +			printf("Error erasing at 0x%lx\n", (long)ofs); +			/* There was an error */ +			goto callback; +		} +		ofs += nand->erasesize; +		len -= nand->erasesize; +	} + + callback: +	return 0; +} + +static inline int nandcheck(unsigned long potential, unsigned long physadr) +{ + + +	return 0; +} + +void 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.badblock_pos = 5; +	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.badblock_pos = NAND_NOOB_BADBPOS; +	oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS; +#endif + +	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 (curr_device == -1) +			curr_device = i; + +		memset((char *)nand, 0, sizeof(struct nand_chip)); + +		nand->cache_page = -1;  /* init the cache page */ +		nand->IO_ADDR = physadr; +		nand->ChipID = ChipID; +                NanD_ScanChips(nand); +                nand->data_buf = malloc (nand->oobblock + nand->oobsize); +		if (!nand->data_buf) { +			puts ("Cannot allocate memory for data structures.\n"); +			return; +		} +} + +#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, reg2, reg3; +	int j; + +	/* Initialize variables */ +	reg1 = reg2 = 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 & 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]; +	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 +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index 31abbaf72..c009156af 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -514,12 +514,17 @@ static int hardware_disable(int slot)  /* -------------------------------------------------------------------- */  /* TQM8xxL Boards by TQ Components					*/ +/* SC8xx   Boards by SinoVee Microsystems				*/  /* -------------------------------------------------------------------- */ -#if defined(CONFIG_TQM8xxL) +#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx) +#if defined(CONFIG_TQM8xxL)  #define PCMCIA_BOARD_MSG "TQM8xxL" - +#endif +#if defined(CONFIG_SVM_SC8xx) +#define PCMCIA_BOARD_MSG "SC8xx" +#endif  static int hardware_enable(int slot)  { diff --git a/common/command.c b/common/command.c index 2304d7a9b..1008925c7 100644 --- a/common/command.c +++ b/common/command.c @@ -58,6 +58,7 @@  #include <cmd_mii.h>  #include <cmd_dcr.h>		/* 4xx DCR register access */  #include <cmd_doc.h> +#include <cmd_nand.h>  #include <cmd_jffs2.h>  #include <cmd_fpga.h> @@ -307,6 +308,8 @@ cmd_tbl_t cmd_tbl[] = {  	CMD_TBL_MTEST  	CMD_TBL_MUXINFO  	CMD_TBL_MW +	CMD_TBL_NAND +	CMD_TBL_NANDBOOT  	CMD_TBL_NEXT  	CMD_TBL_NM  	CMD_TBL_PCI diff --git a/cpu/at91rm9200/Makefile b/cpu/at91rm9200/Makefile new file mode 100644 index 000000000..0953c9f11 --- /dev/null +++ b/cpu/at91rm9200/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(CPU).a + +START	= start.o +OBJS	= serial.o interrupts.o cpu.o + +all:	.depend $(START) $(LIB) + +$(LIB):	$(OBJS) +	$(AR) crv $@ $(OBJS) + +######################################################################### + +.depend:	Makefile $(START:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/at91rm9200/config.mk b/cpu/at91rm9200/config.mk new file mode 100644 index 000000000..deb7f8760 --- /dev/null +++ b/cpu/at91rm9200/config.mk @@ -0,0 +1,27 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.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 +# +PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \ +	-mshort-load-bytes -msoft-float + +PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4 -mtune=arm7tdmi diff --git a/cpu/at91rm9200/cpu.c b/cpu/at91rm9200/cpu.c new file mode 100644 index 000000000..f41210b54 --- /dev/null +++ b/cpu/at91rm9200/cpu.c @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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 + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <AT91RM9200.h> + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1(void) +{ +    unsigned long value; + +    __asm__ __volatile__( +	"mrc     p15, 0, %0, c1, c0, 0   @ read control reg\n" +	: "=r" (value) +	: +	: "memory"); +    /*printf("p15/c1 is = %08lx\n", value); */ +    return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1(unsigned long value) +{ +    /*printf("write %08lx to p15/c1\n", value); */ +    __asm__ __volatile__( +        "mcr     p15, 0, %0, c1, c0, 0   @ write it back\n" +	: "=r" (value) +	: +	: "memory"); + +    read_p15_c1(); +} + +static void cp_delay(void) +{ +    volatile int i; + +    /* copro seems to need some delay between reading and writing */ +    for (i=0; i<100; i++); +} +/* See also ARM Ref. Man. */ +#define C1_MMU		(1<<0)	/* mmu off/on */ +#define C1_ALIGN	(1<<1)	/* alignment faults off/on */ +#define C1_IDC		(1<<2)	/* icache and/or dcache off/on */ +#define C1_WRITE_BUFFER	(1<<3)	/* write buffer off/on */ +#define C1_BIG_ENDIAN	(1<<7)	/* big endian off/on */ +#define C1_SYS_PROT	(1<<8)	/* system protection */ +#define C1_ROM_PROT	(1<<9)	/* ROM protection */ +#define C1_HIGH_VECTORS	(1<<13)	/* location of vectors: low/high addresses */ + +int cpu_init(void) +{ +    /* +     * setup up stack if necessary +     */ +#ifdef CONFIG_USE_IRQ +    IRQ_STACK_START = _armboot_end + +      			CONFIG_STACKSIZE + CONFIG_STACKSIZE_IRQ - 4; +    FIQ_STACK_START = IRQ_STACK_START + CONFIG_STACKSIZE_FIQ; +    _armboot_real_end = FIQ_STACK_START + 4; +#else +    _armboot_real_end = _armboot_end + CONFIG_STACKSIZE; +#endif +    return 0; +} + +int cleanup_before_linux(void) +{ +    /* +     * this function is called just before we call linux +     * it prepares the processor for linux +     * +     * we turn off caches etc ... +     * and we set the CPU-speed to 73 MHz - see start.S for details +     */ + +    disable_interrupts(); +    return 0; +} + +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + +#ifdef CFG_SOFT_RESET +    extern void reset_cpu(ulong addr); + +    disable_interrupts(); +    reset_cpu(0); +#else +   AT91PS_USART us = AT91C_BASE_US1; +   AT91PS_PIO pio = AT91C_BASE_PIOA; + +   /*shutdown the console to avoid strange chars during reset */ +   us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); + +   /* Clear PA19 to trigger the hard reset */ +   pio->PIO_CODR = 0x00080000; +   pio->PIO_OER  = 0x00080000; +   pio->PIO_PER  = 0x00080000; +   /* Never reached */ +#endif +   return 0; +} + +void icache_enable(void) +{ +    ulong reg; +    reg = read_p15_c1(); +    cp_delay(); +    write_p15_c1(reg | C1_IDC); +} + +void icache_disable(void) +{ +    ulong reg; +    reg = read_p15_c1(); +    cp_delay(); +    write_p15_c1(reg & ~C1_IDC); +} + +int icache_status(void) +{ +    return (read_p15_c1() & C1_IDC) != 0; +    return 0; +} + +void dcache_enable(void) +{ +    ulong reg; +    reg = read_p15_c1(); +    cp_delay(); +    write_p15_c1(reg | C1_IDC); +} + +void dcache_disable(void) +{ +    ulong reg; +    reg = read_p15_c1(); +    cp_delay(); +    write_p15_c1(reg & ~C1_IDC); +} + +int dcache_status(void) +{ +    return (read_p15_c1() & C1_IDC) != 0; +    return 0; +} diff --git a/cpu/at91rm9200/interrupts.c b/cpu/at91rm9200/interrupts.c new file mode 100644 index 000000000..a14ef81d0 --- /dev/null +++ b/cpu/at91rm9200/interrupts.c @@ -0,0 +1,236 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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 + */ + +#include <common.h> +#include <AT91RM9200.h> +#include <asm/proc-armv/ptrace.h> + +extern void reset_cpu(ulong addr); + +/* we always count down the max. */ +#define TIMER_LOAD_VAL 0xffff + +/* macro to read the 16 bit timer */ +#define READ_TIMER (tmr->TC_CV) +AT91PS_TC tmr; + + + +void enable_interrupts (void) +{ +    return; +} +int disable_interrupts (void) +{ +    return 0; +} + + +void bad_mode(void) +{ +    panic("Resetting CPU ...\n"); +    reset_cpu(0); +} + +void show_regs(struct pt_regs * regs) +{ +    unsigned long flags; +const char *processor_modes[]= +{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , +  "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", +  "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , +  "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" +}; + +    flags = condition_codes(regs); + +    printf("pc : [<%08lx>]    lr : [<%08lx>]\n" +	   "sp : %08lx  ip : %08lx  fp : %08lx\n", +	   instruction_pointer(regs), +	   regs->ARM_lr, regs->ARM_sp, +	   regs->ARM_ip, regs->ARM_fp); +    printf("r10: %08lx  r9 : %08lx  r8 : %08lx\n", +	   regs->ARM_r10, regs->ARM_r9, +	   regs->ARM_r8); +    printf("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n", +	   regs->ARM_r7, regs->ARM_r6, +	   regs->ARM_r5, regs->ARM_r4); +    printf("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n", +	   regs->ARM_r3, regs->ARM_r2, +	   regs->ARM_r1, regs->ARM_r0); +    printf("Flags: %c%c%c%c", +	   flags & CC_N_BIT ? 'N' : 'n', +	   flags & CC_Z_BIT ? 'Z' : 'z', +	   flags & CC_C_BIT ? 'C' : 'c', +	   flags & CC_V_BIT ? 'V' : 'v'); +    printf("  IRQs %s  FIQs %s  Mode %s%s\n", +	   interrupts_enabled(regs) ? "on" : "off", +	   fast_interrupts_enabled(regs) ? "on" : "off", +	   processor_modes[processor_mode(regs)], +	   thumb_mode(regs) ? " (T)" : ""); +} + +void do_undefined_instruction(struct pt_regs *pt_regs) +{ +    printf("undefined instruction\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_software_interrupt(struct pt_regs *pt_regs) +{ +    printf("software interrupt\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_prefetch_abort(struct pt_regs *pt_regs) +{ +    printf("prefetch abort\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_data_abort(struct pt_regs *pt_regs) +{ +    printf("data abort\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_not_used(struct pt_regs *pt_regs) +{ +    printf("not used\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_fiq(struct pt_regs *pt_regs) +{ +    printf("fast interrupt request\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +void do_irq(struct pt_regs *pt_regs) +{ +    printf("interrupt request\n"); +    show_regs(pt_regs); +    bad_mode(); +} + +static ulong timestamp; +static ulong lastinc; + +int interrupt_init (void) +{ + +    tmr = AT91C_BASE_TC0; + +    /* enables TC1.0 clock */ +    *AT91C_PMC_PCER = 1 << AT91C_ID_TC0;  /* enable clock */ + +    *AT91C_TCB0_BCR = 0; +    *AT91C_TCB0_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_NONE | AT91C_TCB_TC2XC2S_NONE; +    tmr->TC_CCR = AT91C_TC_CLKDIS; +    tmr->TC_CMR = AT91C_TC_TIMER_DIV1_CLOCK;  /* set to MCLK/2 */ + +    tmr->TC_IDR = ~0ul; +    tmr->TC_RC = TIMER_LOAD_VAL; +    lastinc = TIMER_LOAD_VAL; +    tmr->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; +    timestamp = 0; +    return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer(void) +{ +    reset_timer_masked(); +} + +ulong get_timer (ulong base) +{ +    return get_timer_masked() - base; +} + +void set_timer (ulong t) +{ +    timestamp = t; +} + +void udelay(unsigned long usec) +{ +    udelay_masked(usec); +} + +void reset_timer_masked(void) +{ +    /* reset time */ +    lastinc = READ_TIMER; +    timestamp = 0; +} + +ulong get_timer_masked(void) +{ +    ulong now = READ_TIMER; +    if (now >= lastinc) +    { +        /* normal mode */ +        timestamp += now - lastinc; +    } else { +        /* we have an overflow ... */ +        timestamp += now + TIMER_LOAD_VAL - lastinc; +    } +    lastinc = now; + +    return timestamp; +} + +void udelay_masked(unsigned long usec) +{ +    ulong tmo; + +    tmo = usec / 1000; +    tmo *= CFG_HZ; +    tmo /= 1000; + +    reset_timer_masked(); + +    while(get_timer_masked() < tmo); +      /*NOP*/; +} + + diff --git a/cpu/at91rm9200/serial.c b/cpu/at91rm9200/serial.c new file mode 100644 index 000000000..565cd3da8 --- /dev/null +++ b/cpu/at91rm9200/serial.c @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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> +#include <AT91RM9200.h> + +/* ggi thunder */ +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; + +void serial_setbrg(void) +  { +  DECLARE_GLOBAL_DATA_PTR; +  int baudrate; + +  if ((baudrate = gd->bd->bi_baudrate) <= 0) +    baudrate = CONFIG_BAUDRATE; +  us->US_BRGR = 33 /* AT91C_MASTER_CLOCK / baudrate / 16 */; /* hardcode so no __divsi3 */ +  } + +int serial_init(void) +  { +  /* make any port initializations specific to this port */ +  *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD;  /* PA 31 & 30 */ +  *AT91C_PMC_PCER = 1 << AT91C_ID_SYS;  /* enable clock */ +  serial_setbrg(); + +  us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; +  us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; +  us->US_MR = ( AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT ); +  us->US_IMR = ~0ul; +  return (0); +  } + +void serial_putc(const char c) +  { +  if (c == '\n') +    serial_putc('\r'); +  while( (us->US_CSR & AT91C_US_TXRDY) == 0 ) +    ; +  us->US_THR=c; +  } + +void +serial_puts (const char *s) +  { +  while (*s) +    { +    serial_putc (*s++); +    } +  } + +int serial_getc(void) +  { +  while( (us->US_CSR & AT91C_US_RXRDY) == 0 ); +  return us->US_RHR; +  } + +int serial_tstc(void) +  { +  return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY); +  } diff --git a/cpu/at91rm9200/start.S b/cpu/at91rm9200/start.S new file mode 100644 index 000000000..9b3e7aa0f --- /dev/null +++ b/cpu/at91rm9200/start.S @@ -0,0 +1,347 @@ +/* + *  armboot - Startup Code for ARM720 CPU-core + * + *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de> + *  Copyright (c) 2002	Alex Züpke <azu@sysgo.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 + */ + + + +#include "config.h" +#include "version.h" + + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start:	b       reset +	ldr	pc, _undefined_instruction +	ldr	pc, _software_interrupt +	ldr	pc, _prefetch_abort +	ldr	pc, _data_abort +	ldr	pc, _not_used +	ldr	pc, _irq +	ldr	pc, _fiq + +_undefined_instruction:	.word undefined_instruction +_software_interrupt:	.word software_interrupt +_prefetch_abort:	.word prefetch_abort +_data_abort:		.word data_abort +_not_used:		.word not_used +_irq:			.word irq +_fiq:			.word fiq + +	.balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +/* + * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h) + */ +_TEXT_BASE: +	.word	TEXT_BASE + +.globl _armboot_start +_armboot_start: +	.word _start + +/* + * Note: _armboot_end_data and _armboot_end are defined + * by the (board-dependent) linker script. + * _armboot_end_data is the first usable FLASH address after armboot + */ +.globl _armboot_end_data +_armboot_end_data: +	.word armboot_end_data +/* + * Note: armboot_end is defined by the (board-dependent) linker script + */ +.globl _armboot_end +_armboot_end: +	.word armboot_end + +/* + * _armboot_real_end is the first usable RAM address behind armboot + * and the various stacks + */ +.globl _armboot_real_end +_armboot_real_end: +	.word 0x0badc0de + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: +	.word	0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: +	.word 0x0badc0de +#endif + + +/* + * the actual reset code + */ + +reset: +	/* +         * set the cpu to SVC32 mode +         */ +        mrs     r0,cpsr +        bic     r0,r0,#0x1f +        orr     r0,r0,#0x13 +        msr     cpsr,r0 + +	/* +	 * relocate exeception table +	 */ +	ldr	r0, =_start +	ldr	r1, =0x0 +	mov	r2, #16 +copyex: +	subs	r2, r2, #1 +	ldr	r3, [r0], #4 +	str	r3, [r1], #4 +	bne	copyex + +	/* +         * we do sys-critical inits only at reboot, +         * not when booting from ram! +         */ +#ifdef CONFIG_INIT_CRITICAL +        bl      cpu_init_crit +#endif + +        /* set up the stack */ +        ldr     r0, _armboot_end +        add     r0, r0, #CONFIG_STACKSIZE +        sub     sp, r0, #12             /* leave 3 words for abort-stack */ +        ldr pc,_start_armboot + +_start_armboot: .word start_armboot + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + ************************************************************************* + */ + +cpu_init_crit: +	# actually do nothing for now! +	mov	pc, lr + + + + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE	72 + +#define S_OLD_R0	68 +#define S_PSR		64 +#define S_PC		60 +#define S_LR		56 +#define S_SP		52 + +#define S_IP		48 +#define S_FP		44 +#define S_R10		40 +#define S_R9		36 +#define S_R8		32 +#define S_R7		28 +#define S_R6		24 +#define S_R5		20 +#define S_R4		16 +#define S_R3		12 +#define S_R2		8 +#define S_R1		4 +#define S_R0		0 + +#define MODE_SVC 0x13 +#define I_BIT	 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + +	.macro	bad_save_user_regs +	sub	sp, sp, #S_FRAME_SIZE +	stmia	sp, {r0 - r12}			@ Calling r0-r12 +	add     r8, sp, #S_PC + +	ldr	r2, _armboot_end +	add	r2, r2, #CONFIG_STACKSIZE +	sub	r2, r2, #8 +	ldmia	r2, {r2 - r4}                   @ get pc, cpsr, old_r0 +	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC + +	add	r5, sp, #S_SP +	mov	r1, lr +	stmia	r5, {r0 - r4}                   @ save sp_SVC, lr_SVC, pc, cpsr, old_r +	mov	r0, sp +	.endm + +	.macro	irq_save_user_regs +	sub	sp, sp, #S_FRAME_SIZE +	stmia	sp, {r0 - r12}			@ Calling r0-r12 +	add     r8, sp, #S_PC +	stmdb   r8, {sp, lr}^                   @ Calling SP, LR +	str     lr, [r8, #0]                    @ Save calling PC +	mrs     r6, spsr +	str     r6, [r8, #4]                    @ Save CPSR +	str     r0, [r8, #8]                    @ Save OLD_R0 +	mov	r0, sp +	.endm + +	.macro	irq_restore_user_regs +	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr +	mov	r0, r0 +	ldr	lr, [sp, #S_PC]			@ Get PC +	add	sp, sp, #S_FRAME_SIZE +	subs	pc, lr, #4			@ return & move spsr_svc into cpsr +	.endm + +	.macro get_bad_stack +	ldr	r13, _armboot_end		@ setup our mode stack +	add	r13, r13, #CONFIG_STACKSIZE	@ resides at top of normal stack +	sub	r13, r13, #8 + +	str	lr, [r13]			@ save caller lr / spsr +	mrs	lr, spsr +	str     lr, [r13, #4] + +	mov	r13, #MODE_SVC			@ prepare SVC-Mode +	msr	spsr_c, r13 +	mov	lr, pc +	movs	pc, lr +	.endm + +	.macro get_irq_stack			@ setup IRQ stack +	ldr	sp, IRQ_STACK_START +	.endm + +	.macro get_fiq_stack			@ setup FIQ stack +	ldr	sp, FIQ_STACK_START +	.endm + +/* + * exception handlers + */ +	.align  5 +undefined_instruction: +	get_bad_stack +	bad_save_user_regs +	bl 	do_undefined_instruction + +	.align	5 +software_interrupt: +	get_bad_stack +	bad_save_user_regs +	bl 	do_software_interrupt + +	.align	5 +prefetch_abort: +	get_bad_stack +	bad_save_user_regs +	bl 	do_prefetch_abort + +	.align	5 +data_abort: +	get_bad_stack +	bad_save_user_regs +	bl 	do_data_abort + +	.align	5 +not_used: +	get_bad_stack +	bad_save_user_regs +	bl 	do_not_used + +#ifdef CONFIG_USE_IRQ + +	.align	5 +irq: +	get_irq_stack +	irq_save_user_regs +	bl 	do_irq +	irq_restore_user_regs + +	.align	5 +fiq: +	get_fiq_stack +	/* someone ought to write a more effiction fiq_save_user_regs */ +	irq_save_user_regs +	bl 	do_fiq +	irq_restore_user_regs + +#else + +	.align	5 +irq: +	get_bad_stack +	bad_save_user_regs +	bl 	do_irq + +	.align	5 +fiq: +	get_bad_stack +	bad_save_user_regs +	bl 	do_fiq + +#endif + +	.align	5 +.globl reset_cpu +reset_cpu: +	mov     pc, r0 diff --git a/cpu/mpc8xx/cpu_init.c b/cpu/mpc8xx/cpu_init.c index 4bd91f98c..83ff66a48 100644 --- a/cpu/mpc8xx/cpu_init.c +++ b/cpu/mpc8xx/cpu_init.c @@ -54,9 +54,11 @@ void cpu_init_f (volatile immap_t * immr)  #endif /* CONFIG_WATCHDOG */  	/* SIUMCR - contains debug pin configuration (11-6) */ - +#ifndef CONFIG_SVM_SC8xx  	immr->im_siu_conf.sc_siumcr |= CFG_SIUMCR; - +#else +	immr->im_siu_conf.sc_siumcr = CFG_SIUMCR; +#endif  	/* initialize timebase status and control register (11-26) */  	/* unlock TBSCRK */ diff --git a/cpu/sa1100/serial.c b/cpu/sa1100/serial.c index 68bcd1f2a..d3b862824 100644 --- a/cpu/sa1100/serial.c +++ b/cpu/sa1100/serial.c @@ -53,17 +53,19 @@ void serial_setbrg (void)  		hang ();  #ifdef CONFIG_SERIAL1 +	/* SA1110 uart function */ +	Ser1SDCR0 |= SDCR0_SUS; +  	/* Wait until port is ready ... */ -	while (Ser1UTSR1 & UTSR1_TBY) { -	} +	while(Ser1UTSR1 & UTSR1_TBY) {}  	/* init serial serial 1 */  	Ser1UTCR3 = 0x00;  	Ser1UTSR0 = 0xff; -	Ser1UTCR0 = (UTCR0_1StpBit | UTCR0_8BitData); +	Ser1UTCR0 = ( UTCR0_1StpBit | UTCR0_8BitData );  	Ser1UTCR1 = 0; -	Ser1UTCR2 = (u32) reg; -	Ser1UTCR3 = (UTCR3_RXE | UTCR3_TXE); +	Ser1UTCR2 = (u32)reg; +	Ser1UTCR3 = ( UTCR3_RXE | UTCR3_TXE );  #elif CONFIG_SERIAL3  	/* Wait until port is ready ... */  	while (Ser3UTSR1 & UTSR1_TBY) { diff --git a/drivers/Makefile b/drivers/Makefile index 3278cec03..59d753ee4 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -27,7 +27,8 @@ include $(TOPDIR)/config.mk  LIB	= libdrivers.a -OBJS	= 3c589.o 5701rls.o bcm570x.o bcm570x_autoneg.o \ +OBJS	= 3c589.o 5701rls.o at91rm9200_ether.o \ +	  bcm570x.o bcm570x_autoneg.o \  	  cfb_console.o cs8900.o ct69000.o dc2114x.o \  	  eepro100.o i8042.o inca-ip_sw.o \  	  natsemi.o ns16550.o ns8382x.o ns87308.o \ diff --git a/drivers/at91rm9200_ether.c b/drivers/at91rm9200_ether.c new file mode 100644 index 000000000..1b3e87f39 --- /dev/null +++ b/drivers/at91rm9200_ether.c @@ -0,0 +1,251 @@ + +#include <common.h> +#include <command.h> +#include <AT91RM9200.h> +#include <net.h> + +/* ----- Ethernet Buffer definitions ----- */ + +typedef struct { +  unsigned long addr,size; +} rbf_t; + +#define RBF_ADDR      0xfffffffc +#define RBF_OWNER     (1<<0) +#define RBF_WRAP      (1<<1) +#define RBF_BROADCAST (1<<31) +#define RBF_MULTICAST (1<<30) +#define RBF_UNICAST   (1<<29) +#define RBF_EXTERNAL  (1<<28) +#define RBF_UNKOWN    (1<<27) +#define RBF_SIZE      0x07ff +#define RBF_LOCAL4    (1<<26) +#define RBF_LOCAL3    (1<<25) +#define RBF_LOCAL2    (1<<24) +#define RBF_LOCAL1    (1<<23) + +#define RBF_FRAMEMAX 10 +#define RBF_FRAMEMEM 0x200000 +#define RBF_FRAMELEN 0x600 + +#define RBF_FRAMEBTD RBF_FRAMEMEM +#define RBF_FRAMEBUF (RBF_FRAMEMEM + RBF_FRAMEMAX*sizeof(rbf_t)) + +/* stolen from mii.h */ +/* Generic MII registers. */ + +#define MII_BMCR            0x00        /* Basic mode control register */ +#define MII_BMSR            0x01        /* Basic mode status register  */ +#define BMSR_JCD                0x0002  /* Jabber detected             */ +#define BMSR_LSTATUS            0x0004  /* Link status                 */ +#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */ +#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */ +#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */ +#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */ + +#define MII_STS2_REG	17  /* Davicom specific */ +#define MII_MDINTR_REG	21  /* Davicom specific */ + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +AT91PS_EMAC p_mac; + +int MII_ReadPhy(unsigned char addr, unsigned short *ret) +  { + +  p_mac->EMAC_MAN = 0x60020000 | (addr << 18); +  udelay(10000); +  *ret = (unsigned short)p_mac->EMAC_MAN; +  return 1; +  } + + +int MII_GetLinkSpeed(void) +  { +  unsigned short stat1, stat2; +  int ret; + +  if (!(ret = MII_ReadPhy(MII_BMSR, &stat1))) +    return 0; + +  if (stat1 & BMSR_JCD) +    { +#ifdef DEBUG +    printf("MII: jabber condition detected\n"); +#endif      /*jabber detected re-read the register*/ +    } +  if (!(ret = MII_ReadPhy(MII_BMSR, &stat1))) +    return 0; +  if (!(stat1 & BMSR_LSTATUS))  /* link status up? */ +    { +    printf("MII: no Link\n"); +    return 0; +    } + +  if (!(ret = MII_ReadPhy(MII_STS2_REG, &stat2))) +    return 0; + +  if ((stat1 & BMSR_100FULL) && (stat2 & 0x8000) ) +    { +    /* set MII for 100BaseTX and Full Duplex */ +    p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; +#ifdef DEBUG +    printf("MII: 100BaseTX and Full Duplex detected\n"); +#endif +    return 1; +    } + +  else +    if ((stat1 & BMSR_10FULL) && (stat2 & 0x2000)) +      { +      /* set MII for 10BaseT and Full Duplex */ +      p_mac->EMAC_CFG = (p_mac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)); +#ifdef DEBUG +        printf("MII: 10BaseT and Full Duplex detected\n"); +#endif +      return 1; +      } +    else +      if ((stat1 & BMSR_100HALF) && (stat2 & 0x4000)) +        { +        /* set MII for 100BaseTX and Half Duplex */ +        p_mac->EMAC_CFG = (p_mac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)); +#ifdef DEBUG +          printf("MII: 100BaseTX and Hall Duplex detected\n"); +#endif +        return 1; +        } +      else +        if ((stat1 & BMSR_10HALF) && (stat2 & 0x1000)) +          { +          /*set MII for 10BaseT and Half Duplex */ +          p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); +#ifdef DEBUG +          printf("MII: 10BaseT and Hall Duplex detected\n"); +#endif +          return 1; +          } + +  return 0; +  } + + +int MDIO_StartupPhy(void) +  { +  int ret; + +  if(p_mac->EMAC_SR & AT91C_EMAC_LINK) +    { +    printf("MDIO_StartupPhy: no link\n"); +    return 0; +    }; + +  p_mac->EMAC_CTL |= AT91C_EMAC_MPE; + +  ret = MII_GetLinkSpeed(); +  if (ret == 0) +    { +    printf("MDIO_StartupPhy: MII_GetLinkSpeed failed\n"); +    ret = 0; +    } +  else +    { +    ret = 1; +    } + +  p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; +  return ret; + +  } + + +rbf_t* rbfdt; +rbf_t* rbfp; + +int eth_init( bd_t *bd ) +  { +  int ret; +  int i; +  p_mac = AT91C_BASE_EMAC; + +  *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | +    AT91C_PA15_EMDC | AT91C_PA14_ERXER | AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | +    AT91C_PA11_ECRS_ECRSDV | AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | +    AT91C_PA7_ETXCK_EREFCK; 	/* PIO Disable Register */ + +  *AT91C_PIOB_PDR = AT91C_PB25_EF100 | +    AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | +    AT91C_PB15_ERX2 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; + +  *AT91C_PIOB_BSR = AT91C_PB25_EF100 | +    AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | +    AT91C_PB15_ERX2 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2;  /* Select B Register */ +  *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC;  /* Peripheral Clock Enable Register */ +  p_mac->EMAC_CFG |= AT91C_EMAC_CSR;  /* Clear statistics */ + +  rbfdt=(rbf_t *)RBF_FRAMEBTD; +  for(i = 0; i < RBF_FRAMEMAX; i++) +    { +    rbfdt[i].addr=RBF_FRAMEBUF+RBF_FRAMELEN*i; +    rbfdt[i].size=0; +    } +  rbfdt[RBF_FRAMEMAX-1].addr|=RBF_WRAP; +  rbfp=&rbfdt[0]; + +  if (!(ret = MDIO_StartupPhy())) +    { +    printf("MAC: error during MII initialization\n"); +    return 0; +    } + +  p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) +    | (bd->bi_enetaddr[1] <<  8) | (bd->bi_enetaddr[0]); +  p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] <<  8) | (bd->bi_enetaddr[4]); + +  p_mac->EMAC_RBQP = (long)(&rbfdt[0]); +  p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); +  p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_RMII) & ~AT91C_EMAC_CLK; +  p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE ; + +  return 0; +  } + +int eth_send(volatile void *packet, int length) +  { +  while(!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)) +    ; +  p_mac->EMAC_TAR = (long)packet; +  p_mac->EMAC_TCR = length; +  while(p_mac->EMAC_TCR & 0x7ff) +    ; +  p_mac->EMAC_TSR |= AT91C_EMAC_COMP; +  return 0; +  } + +int eth_rx(void) +  { +  int size; + +  if(!(rbfp->addr & RBF_OWNER)) +    return 0; + +  size=rbfp->size & RBF_SIZE; +  NetReceive((volatile uchar *) (rbfp->addr & RBF_ADDR), size); + +  rbfp->addr &= ~RBF_OWNER; +  if(rbfp->addr & RBF_WRAP) +    rbfp = &rbfdt[0]; +  else +    rbfp++; + +  p_mac->EMAC_RSR |= AT91C_EMAC_REC; + +  return size; +  } + +void eth_halt( void ) + {}; +#endif +#endif diff --git a/drivers/smc91111.c b/drivers/smc91111.c index 6244b4eb2..652d859dc 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -493,6 +493,13 @@ static int smc_send_packet(volatile void *packet, int packet_length)  	SMC_SELECT_BANK( 2 );  	SMC_outw( MC_ALLOC | numPages, MMU_CMD_REG ); +	/* FIXME: the ALLOC_INT bit never gets set * +	 * so the following will always give a     * +	 * memory allocation error.                * +	 * same code works in armboot though       * +	 * -ro +	 */ +  again:  	try++;  	time_out = MEMORY_WAIT_TIME; diff --git a/examples/Makefile b/examples/Makefile index e6a302391..2897ba163 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -26,6 +26,7 @@ LOAD_ADDR = 0x40000  include $(TOPDIR)/config.mk  SREC	= hello_world.srec +BIN	= hello_world.bin  ifeq ($(CPU),mips)  SREC = @@ -50,7 +51,7 @@ LIBOBJS	= $(LIBAOBJS) $(LIBCOBJS)  CPPFLAGS += -I.. -all:	.depend $(LIB) $(SREC) +all:	.depend $(LIB) $(SREC) $(BIN)  #########################################################################  $(LIB): .depend $(LIBOBJS) @@ -60,6 +61,9 @@ $(LIB): .depend $(LIBOBJS)  	$(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e $(<:.o=) $< $(LIB)  	$(OBJCOPY) -O srec $(<:.o=) $@ +%.bin:	%.srec +	$(OBJCOPY) -O binary $< $@ +  #########################################################################  .depend:	Makefile $(OBJS:.o=.c) $(LIBCOBJS:.o=.c) $(LIBAOBJS:.o=.S) diff --git a/include/AT91RM9200.h b/include/AT91RM9200.h new file mode 100644 index 000000000..f65328fe9 --- /dev/null +++ b/include/AT91RM9200.h @@ -0,0 +1,349 @@ +/*  ---------------------------------------------------------------------------- */ +/*           ATMEL Microcontroller Software Support  -  ROUSSET  - */ +/*  ---------------------------------------------------------------------------- */ +/*   The software is delivered "AS IS" without warranty or condition of any */ +/*   kind, either express, implied or statutory. This includes without */ +/*   limitation any warranty or condition with respect to merchantability or */ +/*   fitness for any particular purpose, or against the infringements of */ +/*   intellectual property rights of others. */ +/*  ---------------------------------------------------------------------------- */ +/*  File Name           : AT91RM9200.h */ +/*  Object              : AT91RM9200 definitions */ +/*  Generated           : AT91 SW Application Group  10/29/2002 (16:10:51) */ +#ifndef AT91RM9200_H +#define AT91RM9200_H + +typedef volatile unsigned int AT91_REG;/*  Hardware register definition */ + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Timer Counter Channel Interface */ +/*  ***************************************************************************** */ +typedef struct _AT91S_TC { +	AT91_REG	 TC_CCR; 	/*  Channel Control Register */ +	AT91_REG	 TC_CMR; 	/*  Channel Mode Register */ +	AT91_REG	 Reserved0[2]; 	/*   */ +	AT91_REG	 TC_CV; 	/*  Counter Value */ +	AT91_REG	 TC_RA; 	/*  Register A */ +	AT91_REG	 TC_RB; 	/*  Register B */ +	AT91_REG	 TC_RC; 	/*  Register C */ +	AT91_REG	 TC_SR; 	/*  Status Register */ +	AT91_REG	 TC_IER; 	/*  Interrupt Enable Register */ +	AT91_REG	 TC_IDR; 	/*  Interrupt Disable Register */ +	AT91_REG	 TC_IMR; 	/*  Interrupt Mask Register */ +} AT91S_TC, *AT91PS_TC; + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Usart */ +/*  ***************************************************************************** */ +typedef struct _AT91S_USART { +	AT91_REG	 US_CR; 	/*  Control Register */ +	AT91_REG	 US_MR; 	/*  Mode Register */ +	AT91_REG	 US_IER; 	/*  Interrupt Enable Register */ +	AT91_REG	 US_IDR; 	/*  Interrupt Disable Register */ +	AT91_REG	 US_IMR; 	/*  Interrupt Mask Register */ +	AT91_REG	 US_CSR; 	/*  Channel Status Register */ +	AT91_REG	 US_RHR; 	/*  Receiver Holding Register */ +	AT91_REG	 US_THR; 	/*  Transmitter Holding Register */ +	AT91_REG	 US_BRGR; 	/*  Baud Rate Generator Register */ +	AT91_REG	 US_RTOR; 	/*  Receiver Time-out Register */ +	AT91_REG	 US_TTGR; 	/*  Transmitter Time-guard Register */ +	AT91_REG	 Reserved0[5]; 	/*   */ +	AT91_REG	 US_FIDI; 	/*  FI_DI_Ratio Register */ +	AT91_REG	 US_NER; 	/*  Nb Errors Register */ +	AT91_REG	 US_XXR; 	/*  XON_XOFF Register */ +	AT91_REG	 US_IF; 	/*  IRDA_FILTER Register */ +	AT91_REG	 Reserved1[44]; 	/*   */ +	AT91_REG	 US_RPR; 	/*  Receive Pointer Register */ +	AT91_REG	 US_RCR; 	/*  Receive Counter Register */ +	AT91_REG	 US_TPR; 	/*  Transmit Pointer Register */ +	AT91_REG	 US_TCR; 	/*  Transmit Counter Register */ +	AT91_REG	 US_RNPR; 	/*  Receive Next Pointer Register */ +	AT91_REG	 US_RNCR; 	/*  Receive Next Counter Register */ +	AT91_REG	 US_TNPR; 	/*  Transmit Next Pointer Register */ +	AT91_REG	 US_TNCR; 	/*  Transmit Next Counter Register */ +	AT91_REG	 US_PTCR; 	/*  PDC Transfer Control Register */ +	AT91_REG	 US_PTSR; 	/*  PDC Transfer Status Register */ +} AT91S_USART, *AT91PS_USART; + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Parallel Input Output Controler */ +/*  ***************************************************************************** */ +typedef struct _AT91S_PIO { +	AT91_REG	 PIO_PER; 	/*  PIO Enable Register */ +	AT91_REG	 PIO_PDR; 	/*  PIO Disable Register */ +	AT91_REG	 PIO_PSR; 	/*  PIO Status Register */ +	AT91_REG	 Reserved0[1]; 	/*   */ +	AT91_REG	 PIO_OER; 	/*  Output Enable Register */ +	AT91_REG	 PIO_ODR; 	/*  Output Disable Registerr */ +	AT91_REG	 PIO_OSR; 	/*  Output Status Register */ +	AT91_REG	 Reserved1[1]; 	/*   */ +	AT91_REG	 PIO_IFER; 	/*  Input Filter Enable Register */ +	AT91_REG	 PIO_IFDR; 	/*  Input Filter Disable Register */ +	AT91_REG	 PIO_IFSR; 	/*  Input Filter Status Register */ +	AT91_REG	 Reserved2[1]; 	/*   */ +	AT91_REG	 PIO_SODR; 	/*  Set Output Data Register */ +	AT91_REG	 PIO_CODR; 	/*  Clear Output Data Register */ +	AT91_REG	 PIO_ODSR; 	/*  Output Data Status Register */ +	AT91_REG	 PIO_PDSR; 	/*  Pin Data Status Register */ +	AT91_REG	 PIO_IER; 	/*  Interrupt Enable Register */ +	AT91_REG	 PIO_IDR; 	/*  Interrupt Disable Register */ +	AT91_REG	 PIO_IMR; 	/*  Interrupt Mask Register */ +	AT91_REG	 PIO_ISR; 	/*  Interrupt Status Register */ +	AT91_REG	 PIO_MDER; 	/*  Multi-driver Enable Register */ +	AT91_REG	 PIO_MDDR; 	/*  Multi-driver Disable Register */ +	AT91_REG	 PIO_MDSR; 	/*  Multi-driver Status Register */ +	AT91_REG	 Reserved3[1]; 	/*   */ +	AT91_REG	 PIO_PPUDR; 	/*  Pull-up Disable Register */ +	AT91_REG	 PIO_PPUER; 	/*  Pull-up Enable Register */ +	AT91_REG	 PIO_PPUSR; 	/*  Pad Pull-up Status Register */ +	AT91_REG	 Reserved4[1]; 	/*   */ +	AT91_REG	 PIO_ASR; 	/*  Select A Register */ +	AT91_REG	 PIO_BSR; 	/*  Select B Register */ +	AT91_REG	 PIO_ABSR; 	/*  AB Select Status Register */ +	AT91_REG	 Reserved5[9]; 	/*   */ +	AT91_REG	 PIO_OWER; 	/*  Output Write Enable Register */ +	AT91_REG	 PIO_OWDR; 	/*  Output Write Disable Register */ +	AT91_REG	 PIO_OWSR; 	/*  Output Write Status Register */ +} AT91S_PIO, *AT91PS_PIO; + + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Debug Unit */ +/*  ***************************************************************************** */ +typedef struct _AT91S_DBGU { +	AT91_REG	 DBGU_CR; 	/*  Control Register */ +	AT91_REG	 DBGU_MR; 	/*  Mode Register */ +	AT91_REG	 DBGU_IER; 	/*  Interrupt Enable Register */ +	AT91_REG	 DBGU_IDR; 	/*  Interrupt Disable Register */ +	AT91_REG	 DBGU_IMR; 	/*  Interrupt Mask Register */ +	AT91_REG	 DBGU_CSR; 	/*  Channel Status Register */ +	AT91_REG	 DBGU_RHR; 	/*  Receiver Holding Register */ +	AT91_REG	 DBGU_THR; 	/*  Transmitter Holding Register */ +	AT91_REG	 DBGU_BRGR; 	/*  Baud Rate Generator Register */ +	AT91_REG	 Reserved0[7]; 	/*   */ +	AT91_REG	 DBGU_C1R; 	/*  Chip ID1 Register */ +	AT91_REG	 DBGU_C2R; 	/*  Chip ID2 Register */ +	AT91_REG	 DBGU_FNTR; 	/*  Force NTRST Register */ +	AT91_REG	 Reserved1[45]; 	/*   */ +	AT91_REG	 DBGU_RPR; 	/*  Receive Pointer Register */ +	AT91_REG	 DBGU_RCR; 	/*  Receive Counter Register */ +	AT91_REG	 DBGU_TPR; 	/*  Transmit Pointer Register */ +	AT91_REG	 DBGU_TCR; 	/*  Transmit Counter Register */ +	AT91_REG	 DBGU_RNPR; 	/*  Receive Next Pointer Register */ +	AT91_REG	 DBGU_RNCR; 	/*  Receive Next Counter Register */ +	AT91_REG	 DBGU_TNPR; 	/*  Transmit Next Pointer Register */ +	AT91_REG	 DBGU_TNCR; 	/*  Transmit Next Counter Register */ +	AT91_REG	 DBGU_PTCR; 	/*  PDC Transfer Control Register */ +	AT91_REG	 DBGU_PTSR; 	/*  PDC Transfer Status Register */ +} AT91S_DBGU, *AT91PS_DBGU; + + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Static Memory Controller 2 Interface */ +/*  ***************************************************************************** */ +typedef struct _AT91S_SMC2 { +	AT91_REG	 SMC2_CSR[8]; 	/*  SMC2 Chip Select Register */ +} AT91S_SMC2, *AT91PS_SMC2; + +/*  ***************************************************************************** */ +/*               SOFTWARE API DEFINITION  FOR Ethernet MAC */ +/*  ***************************************************************************** */ +typedef struct _AT91S_EMAC { +	AT91_REG	 EMAC_CTL; 	/*  Network Control Register */ +	AT91_REG	 EMAC_CFG; 	/*  Network Configuration Register */ +	AT91_REG	 EMAC_SR; 	/*  Network Status Register */ +	AT91_REG	 EMAC_TAR; 	/*  Transmit Address Register */ +	AT91_REG	 EMAC_TCR; 	/*  Transmit Control Register */ +	AT91_REG	 EMAC_TSR; 	/*  Transmit Status Register */ +	AT91_REG	 EMAC_RBQP; 	/*  Receive Buffer Queue Pointer */ +	AT91_REG	 Reserved0[1]; 	/*   */ +	AT91_REG	 EMAC_RSR; 	/*  Receive Status Register */ +	AT91_REG	 EMAC_ISR; 	/*  Interrupt Status Register */ +	AT91_REG	 EMAC_IER; 	/*  Interrupt Enable Register */ +	AT91_REG	 EMAC_IDR; 	/*  Interrupt Disable Register */ +	AT91_REG	 EMAC_IMR; 	/*  Interrupt Mask Register */ +	AT91_REG	 EMAC_MAN; 	/*  PHY Maintenance Register */ +	AT91_REG	 Reserved1[2]; 	/*   */ +	AT91_REG	 EMAC_FRA; 	/*  Frames Transmitted OK Register */ +	AT91_REG	 EMAC_SCOL; 	/*  Single Collision Frame Register */ +	AT91_REG	 EMAC_MCOL; 	/*  Multiple Collision Frame Register */ +	AT91_REG	 EMAC_OK; 	/*  Frames Received OK Register */ +	AT91_REG	 EMAC_SEQE; 	/*  Frame Check Sequence Error Register */ +	AT91_REG	 EMAC_ALE; 	/*  Alignment Error Register */ +	AT91_REG	 EMAC_DTE; 	/*  Deferred Transmission Frame Register */ +	AT91_REG	 EMAC_LCOL; 	/*  Late Collision Register */ +	AT91_REG	 EMAC_ECOL; 	/*  Excessive Collision Register */ +	AT91_REG	 EMAC_CSE; 	/*  Carrier Sense Error Register */ +	AT91_REG	 EMAC_TUE; 	/*  Transmit Underrun Error Register */ +	AT91_REG	 EMAC_CDE; 	/*  Code Error Register */ +	AT91_REG	 EMAC_ELR; 	/*  Excessive Length Error Register */ +	AT91_REG	 EMAC_RJB; 	/*  Receive Jabber Register */ +	AT91_REG	 EMAC_USF; 	/*  Undersize Frame Register */ +	AT91_REG	 EMAC_SQEE; 	/*  SQE Test Error Register */ +	AT91_REG	 EMAC_DRFC; 	/*  Discarded RX Frame Register */ +	AT91_REG	 Reserved2[3]; 	/*   */ +	AT91_REG	 EMAC_HSH; 	/*  Hash Address High[63:32] */ +	AT91_REG	 EMAC_HSL; 	/*  Hash Address Low[31:0] */ +	AT91_REG	 EMAC_SA1L; 	/*  Specific Address 1 Low, First 4 bytes */ +	AT91_REG	 EMAC_SA1H; 	/*  Specific Address 1 High, Last 2 bytes */ +	AT91_REG	 EMAC_SA2L; 	/*  Specific Address 2 Low, First 4 bytes */ +	AT91_REG	 EMAC_SA2H; 	/*  Specific Address 2 High, Last 2 bytes */ +	AT91_REG	 EMAC_SA3L; 	/*  Specific Address 3 Low, First 4 bytes */ +	AT91_REG	 EMAC_SA3H; 	/*  Specific Address 3 High, Last 2 bytes */ +	AT91_REG	 EMAC_SA4L; 	/*  Specific Address 4 Low, First 4 bytes */ +	AT91_REG	 EMAC_SA4H; 	/*  Specific Address 4 High, Last 2 bytesr */ +} AT91S_EMAC, *AT91PS_EMAC; + +/*  -------- DBGU_IER : (DBGU Offset: 0x8) Debug Unit Interrupt Enable Register --------  */ +#define AT91C_US_RXRDY        ((unsigned int) 0x1 <<  0) /*  (DBGU) RXRDY Interrupt */ +#define AT91C_US_TXRDY        ((unsigned int) 0x1 <<  1) /*  (DBGU) TXRDY Interrupt */ +#define AT91C_US_ENDRX        ((unsigned int) 0x1 <<  3) /*  (DBGU) End of Receive Transfer Interrupt */ +#define AT91C_US_ENDTX        ((unsigned int) 0x1 <<  4) /*  (DBGU) End of Transmit Interrupt */ +#define AT91C_US_OVRE         ((unsigned int) 0x1 <<  5) /*  (DBGU) Overrun Interrupt */ +#define AT91C_US_FRAME        ((unsigned int) 0x1 <<  6) /*  (DBGU) Framing Error Interrupt */ +#define AT91C_US_PARE         ((unsigned int) 0x1 <<  7) /*  (DBGU) Parity Error Interrupt */ +#define AT91C_US_TXEMPTY      ((unsigned int) 0x1 <<  9) /*  (DBGU) TXEMPTY Interrupt */ +#define AT91C_US_TXBUFE       ((unsigned int) 0x1 << 11) /*  (DBGU) TXBUFE Interrupt */ +#define AT91C_US_RXBUFF       ((unsigned int) 0x1 << 12) /*  (DBGU) RXBUFF Interrupt */ +#define AT91C_US_COMM_TX      ((unsigned int) 0x1 << 30) /*  (DBGU) COMM_TX Interrupt */ +#define AT91C_US_COMM_RX      ((unsigned int) 0x1 << 31) /*  (DBGU) COMM_RX Interrupt */ + +/*  -------- DBGU_CR : (DBGU Offset: 0x0) Debug Unit Control Register --------  */ +#define AT91C_US_RSTRX        ((unsigned int) 0x1 <<  2) /*  (DBGU) Reset Receiver */ +#define AT91C_US_RSTTX        ((unsigned int) 0x1 <<  3) /*  (DBGU) Reset Transmitter */ +#define AT91C_US_RXEN         ((unsigned int) 0x1 <<  4) /*  (DBGU) Receiver Enable */ +#define AT91C_US_RXDIS        ((unsigned int) 0x1 <<  5) /*  (DBGU) Receiver Disable */ +#define AT91C_US_TXEN         ((unsigned int) 0x1 <<  6) /*  (DBGU) Transmitter Enable */ +#define AT91C_US_TXDIS        ((unsigned int) 0x1 <<  7) /*  (DBGU) Transmitter Disable */ + +#define 	AT91C_US_CLKS_CLOCK                ((unsigned int) 0x0 <<  4) /*  (USART) Clock */ +#define 	AT91C_US_CHRL_8_BITS               ((unsigned int) 0x3 <<  6) /*  (USART) Character Length: 8 bits */ +#define 	AT91C_US_PAR_NONE                 ((unsigned int) 0x4 <<  9) /*  (DBGU) No Parity */ +#define 	AT91C_US_NBSTOP_1_BIT                ((unsigned int) 0x0 << 12) /*  (USART) 1 stop bit */ + +#define AT91C_PMC_PCER  ((AT91_REG *) 	0xFFFFFC10) /*  (PMC) Peripheral Clock Enable Register */ +#define AT91C_PIOA_PDR  ((AT91_REG *) 	0xFFFFF404) /*  (PIOA) PIO Disable Register */ +#define AT91C_PIO_PA30       ((unsigned int) 1 << 30) /*  Pin Controlled by PA30 */ +#define AT91C_PIO_PC0        ((unsigned int) 1 <<  0) /*  Pin Controlled by PC0 */ +#define AT91C_PC0_BFCK     ((unsigned int) AT91C_PIO_PC0) /*   Burst Flash Clock */ +#define AT91C_PA30_DRXD     ((unsigned int) AT91C_PIO_PA30) /*   DBGU Debug Receive Data */ +#define AT91C_PIO_PA31       ((unsigned int) 1 << 31) /*  Pin Controlled by PA31 */ +#define AT91C_PA31_DTXD     ((unsigned int) AT91C_PIO_PA31) /*   DBGU Debug Transmit Data */ + +#define AT91C_ID_SYS    ((unsigned int)  1) /*  System Peripheral */ +#define AT91C_ID_TC0    ((unsigned int) 17) /*  Timer Counter 0 */ +#define AT91C_ID_EMAC   ((unsigned int) 24) /*  Ethernet MAC */ + +#define AT91C_PIO_PC1        ((unsigned int) 1 <<  1) /*  Pin Controlled by PC1 */ +#define AT91C_PC1_BFRDY_SMOE ((unsigned int) AT91C_PIO_PC1) /*   Burst Flash Ready */ +#define AT91C_PIO_PC3        ((unsigned int) 1 <<  3) /*  Pin Controlled by PC3 */ +#define AT91C_PC3_BFBAA_SMWE ((unsigned int) AT91C_PIO_PC3) /*   Burst Flash Address Advance / SmartMedia Write Enable */ +#define AT91C_PIO_PC2        ((unsigned int) 1 <<  2) /*  Pin Controlled by PC2 */ +#define AT91C_PC2_BFAVD    ((unsigned int) AT91C_PIO_PC2) /*   Burst Flash Address Valid */ +#define AT91C_PIO_PB1        ((unsigned int) 1 <<  1) /*  Pin Controlled by PB1 */ + +#define AT91C_TC_TIMER_DIV1_CLOCK      ((unsigned int) 0x0 <<  0) /*  (TC) MCK/2 */ +#define AT91C_TC_TIMER_DIV2_CLOCK      ((unsigned int) 0x1 <<  0) /*  (TC) MCK/8 */ +#define AT91C_TC_TIMER_DIV3_CLOCK      ((unsigned int) 0x2 <<  0) /*  (TC) MCK/32 */ +#define AT91C_TC_TIMER_DIV4_CLOCK      ((unsigned int) 0x3 <<  0) /*  (TC) MCK/128 */ +#define AT91C_TC_SLOW_CLOCK            ((unsigned int) 0x4 <<  0) /*  (TC) SLOW CLK */ +#define AT91C_TC_XC0_CLOCK             ((unsigned int) 0x5 <<  0) /*  (TC) XC0 */ +#define AT91C_TC_XC1_CLOCK             ((unsigned int) 0x6 <<  0) /*  (TC) XC1 */ +#define AT91C_TC_XC2_CLOCK             ((unsigned int) 0x7 <<  0) /*  (TC) XC2 */ +#define 	AT91C_TCB_TC0XC0S_NONE                 ((unsigned int) 0x1) /*  (TCB) None signal connected to XC0 */ +#define 	AT91C_TCB_TC1XC1S_NONE                 ((unsigned int) 0x1 <<  2) /*  (TCB) None signal connected to XC1 */ +#define 	AT91C_TCB_TC2XC2S_NONE                 ((unsigned int) 0x1 <<  4) /*  (TCB) None signal connected to XC2 */ +#define AT91C_TC_CLKDIS       ((unsigned int) 0x1 <<  1) /*  (TC) Counter Clock Disable Command */ +#define AT91C_TC_SWTRG        ((unsigned int) 0x1 <<  2) /*  (TC) Software Trigger Command */ +#define AT91C_TC_CLKEN        ((unsigned int) 0x1 <<  0) /*  (TC) Counter Clock Enable Command */ + +#define AT91C_EMAC_BNQ        ((unsigned int) 0x1 <<  4) /*  (EMAC)  */ +#define AT91C_EMAC_COMP       ((unsigned int) 0x1 <<  5) /*  (EMAC)  */ +#define AT91C_EMAC_REC        ((unsigned int) 0x1 <<  1) /*  (EMAC)  */ +#define AT91C_EMAC_RE         ((unsigned int) 0x1 <<  2) /*  (EMAC) Receive enable.  */ +#define AT91C_EMAC_TE         ((unsigned int) 0x1 <<  3) /*  (EMAC) Transmit enable.  */ +#define AT91C_EMAC_CLK        ((unsigned int) 0x3 << 10) /*  (EMAC)  */ +#define AT91C_EMAC_RMII       ((unsigned int) 0x1 << 13) /*  (EMAC)  */ +#define AT91C_EMAC_NBC        ((unsigned int) 0x1 <<  5) /*  (EMAC) No broadcast.  */ +#define AT91C_EMAC_CAF        ((unsigned int) 0x1 <<  4) /*  (EMAC) Copy all frames.  */ +#define AT91C_EMAC_BNA        ((unsigned int) 0x1 <<  0) /*  (EMAC)  */ +#define AT91C_EMAC_REC        ((unsigned int) 0x1 <<  1) /*  (EMAC)  */ +#define AT91C_EMAC_RSR_OVR    ((unsigned int) 0x1 <<  2) /*  (EMAC)  */ +#define AT91C_EMAC_CSR        ((unsigned int) 0x1 <<  5) /*  (EMAC) Clear statistics registers.  */ +#define AT91C_EMAC_SPD        ((unsigned int) 0x1 <<  0) /*  (EMAC) Speed.  */ +#define AT91C_EMAC_FD         ((unsigned int) 0x1 <<  1) /*  (EMAC) Full duplex.  */ +#define AT91C_EMAC_LINK       ((unsigned int) 0x1 <<  0) /*  (EMAC)  */ +#define AT91C_EMAC_MPE        ((unsigned int) 0x1 <<  4) /*  (EMAC) Management port enable.  */ +#define AT91C_PIO_PA16       ((unsigned int) 1 << 16) /*  Pin Controlled by PA16 */ +#define AT91C_PA16_EMDIO    ((unsigned int) AT91C_PIO_PA16) /*   Ethernet MAC Management Data Input/Output */ +#define AT91C_PIO_PA15       ((unsigned int) 1 << 15) /*  Pin Controlled by PA15 */ +#define AT91C_PA15_EMDC     ((unsigned int) AT91C_PIO_PA15) /*   Ethernet MAC Management Data Clock */ +#define AT91C_PIO_PA14       ((unsigned int) 1 << 14) /*  Pin Controlled by PA14 */ +#define AT91C_PA14_ERXER    ((unsigned int) AT91C_PIO_PA14) /*   Ethernet MAC Receive Error */ +#define AT91C_PIO_PA13       ((unsigned int) 1 << 13) /*  Pin Controlled by PA13 */ +#define AT91C_PA13_ERX1     ((unsigned int) AT91C_PIO_PA13) /*   Ethernet MAC Receive Data 1 */ +#define AT91C_PIO_PA12       ((unsigned int) 1 << 12) /*  Pin Controlled by PA12 */ +#define AT91C_PA12_ERX0     ((unsigned int) AT91C_PIO_PA12) /*   Ethernet MAC Receive Data 0 */ +#define AT91C_PIO_PA11       ((unsigned int) 1 << 11) /*  Pin Controlled by PA11 */ +#define AT91C_PA11_ECRS_ECRSDV ((unsigned int) AT91C_PIO_PA11) /*   Ethernet MAC Carrier Sense/Carrier Sense and Data Valid */ +#define AT91C_PIO_PA10       ((unsigned int) 1 << 10) /*  Pin Controlled by PA10 */ +#define AT91C_PA10_ETX1     ((unsigned int) AT91C_PIO_PA10) /*   Ethernet MAC Transmit Data 1 */ +#define AT91C_PIO_PA9        ((unsigned int) 1 <<  9) /*  Pin Controlled by PA9 */ +#define AT91C_PA9_ETX0     ((unsigned int) AT91C_PIO_PA9) /*   Ethernet MAC Transmit Data 0 */ +#define AT91C_PIO_PA8        ((unsigned int) 1 <<  8) /*  Pin Controlled by PA8 */ +#define AT91C_PA8_ETXEN    ((unsigned int) AT91C_PIO_PA8) /*   Ethernet MAC Transmit Enable */ +#define AT91C_PIO_PA7        ((unsigned int) 1 <<  7) /*  Pin Controlled by PA7 */ +#define AT91C_PA7_ETXCK_EREFCK ((unsigned int) AT91C_PIO_PA7) /*   Ethernet MAC Transmit Clock/Reference Clock */ +#define AT91C_PIO_PB25       ((unsigned int) 1 << 25) /*  Pin Controlled by PB25 */ +#define AT91C_PB25_DSR1     ((unsigned int) AT91C_PIO_PB25) /*   USART 1 Data Set ready */ +#define AT91C_PB25_EF100    ((unsigned int) AT91C_PIO_PB25) /*   Ethernet MAC Force 100 Mbits */ +#define AT91C_PIO_PB19       ((unsigned int) 1 << 19) /*  Pin Controlled by PB19 */ +#define AT91C_PB19_DTR1     ((unsigned int) AT91C_PIO_PB19) /*   USART 1 Data Terminal ready */ +#define AT91C_PB19_ERXCK    ((unsigned int) AT91C_PIO_PB19) /*   Ethernet MAC Receive Clock */ +#define AT91C_PIO_PB18       ((unsigned int) 1 << 18) /*  Pin Controlled by PB18 */ +#define AT91C_PB18_RI1      ((unsigned int) AT91C_PIO_PB18) /*   USART 1 Ring Indicator */ +#define AT91C_PB18_ECOL     ((unsigned int) AT91C_PIO_PB18) /*   Ethernet MAC Collision Detected */ +#define AT91C_PIO_PB17       ((unsigned int) 1 << 17) /*  Pin Controlled by PB17 */ +#define AT91C_PB17_RF2      ((unsigned int) AT91C_PIO_PB17) /*   SSC Receive Frame Sync 2 */ +#define AT91C_PB17_ERXDV    ((unsigned int) AT91C_PIO_PB17) /*   Ethernet MAC Receive Data Valid */ +#define AT91C_PIO_PB16       ((unsigned int) 1 << 16) /*  Pin Controlled by PB16 */ +#define AT91C_PB16_RK2      ((unsigned int) AT91C_PIO_PB16) /*   SSC Receive Clock 2 */ +#define AT91C_PB16_ERX3     ((unsigned int) AT91C_PIO_PB16) /*   Ethernet MAC Receive Data 3 */ +#define AT91C_PIO_PB15       ((unsigned int) 1 << 15) /*  Pin Controlled by PB15 */ +#define AT91C_PB15_RD2      ((unsigned int) AT91C_PIO_PB15) /*   SSC Receive Data 2 */ +#define AT91C_PB15_ERX2     ((unsigned int) AT91C_PIO_PB15) /*   Ethernet MAC Receive Data 2 */ +#define AT91C_PIO_PB14       ((unsigned int) 1 << 14) /*  Pin Controlled by PB14 */ +#define AT91C_PB14_TD2      ((unsigned int) AT91C_PIO_PB14) /*   SSC Transmit Data 2 */ +#define AT91C_PB14_ETXER    ((unsigned int) AT91C_PIO_PB14) /*   Ethernet MAC Transmikt Coding Error */ +#define AT91C_PIO_PB13       ((unsigned int) 1 << 13) /*  Pin Controlled by PB13 */ +#define AT91C_PB13_TK2      ((unsigned int) AT91C_PIO_PB13) /*   SSC Transmit Clock 2 */ +#define AT91C_PB13_ETX3     ((unsigned int) AT91C_PIO_PB13) /*   Ethernet MAC Transmit Data 3 */ +#define AT91C_PIO_PB12       ((unsigned int) 1 << 12) /*  Pin Controlled by PB12 */ +#define AT91C_PB12_TF2      ((unsigned int) AT91C_PIO_PB12) /*   SSC Transmit Frame Sync 2 */ +#define AT91C_PB12_ETX2     ((unsigned int) AT91C_PIO_PB12) /*   Ethernet MAC Transmit Data 2 */ + +#define AT91C_PIOB_BSR  ((AT91_REG *) 	0xFFFFF674) /*  (PIOB) Select B Register */ +#define AT91C_BASE_EMAC      ((AT91PS_EMAC) 	0xFFFBC000) /*  (EMAC) Base Address */ +#define AT91C_PIOB_PDR  ((AT91_REG *) 	0xFFFFF604) /*  (PIOB) PIO Disable Register */ + +#define 	AT91C_EBI_CS3A_SMC_SmartMedia       ((unsigned int) 0x1 <<  3) /*  (EBI) Chip Select 3 is assigned to the Static Memory Controller and the SmartMedia Logic is activated. */ +#define	AT91C_SMC2_ACSS_STANDARD ((unsigned int) 0x0 << 16) /*  (SMC2) Standard, asserted at the beginning of the access and deasserted at the end. */ +#define AT91C_SMC2_DBW_8      ((unsigned int) 0x2 << 13) /*  (SMC2) 8-bit. */ +#define AT91C_SMC2_WSEN       ((unsigned int) 0x1 <<  7) /*  (SMC2) Wait State Enable */ +#define AT91C_PIOC_ASR  ((AT91_REG *) 	0xFFFFF870) /*  (PIOC) Select A Register */ + +#define AT91C_BASE_TC0       ((AT91PS_TC) 	0xFFFA0000) /*  (TC0) Base Address */ +#define AT91C_BASE_DBGU      ((AT91PS_DBGU) 	0xFFFFF200) /*  (DBGU) Base Address */ +#define AT91C_BASE_PIOA      ((AT91PS_PIO) 	0xFFFFF400) /*  (PIOA) Base Address */ +#define AT91C_EBI_CSA   ((AT91_REG *) 	0xFFFFFF60) /*  (EBI) Chip Select Assignment Register */ +#define AT91C_BASE_SMC2      ((AT91PS_SMC2) 	0xFFFFFF70) /*  (SMC2) Base Address */ +#define AT91C_BASE_US1       ((AT91PS_USART) 	0xFFFC4000) /*  (US1) Base Address */ +#define AT91C_TCB0_BMR  ((AT91_REG *) 	0xFFFA00C4) /*  (TCB0) TC Block Mode Register */ +#define AT91C_TCB0_BCR  ((AT91_REG *) 	0xFFFA00C0) /*  (TCB0) TC Block Control Register */ +#define AT91C_PIOC_PDR  ((AT91_REG *) 	0xFFFFF804) /*  (PIOC) PIO Disable Register */ +#define AT91C_PIOC_PER  ((AT91_REG *) 	0xFFFFF800) /*  (PIOC) PIO Enable Register */ +#define AT91C_PIOC_ODR  ((AT91_REG *) 	0xFFFFF814) /*  (PIOC) Output Disable Registerr */ +#define AT91C_PIOB_PER  ((AT91_REG *) 	0xFFFFF600) /*  (PIOB) PIO Enable Register */ +#define AT91C_PIOB_ODR  ((AT91_REG *) 	0xFFFFF614) /*  (PIOB) Output Disable Registerr */ +#define AT91C_PIOB_PDSR ((AT91_REG *) 	0xFFFFF63C) /*  (PIOB) Pin Data Status Register */ +#endif diff --git a/include/asm-ppc/u-boot.h b/include/asm-ppc/u-boot.h index eea9c7c1e..e417e0d30 100644 --- a/include/asm-ppc/u-boot.h +++ b/include/asm-ppc/u-boot.h @@ -68,11 +68,11 @@ typedef struct bd_info {  #if defined(CONFIG_HYMOD)  	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */  #endif -#if defined(CONFIG_EVB64260) || defined(CONFIG_PN62) +#if defined(CONFIG_EVB64260) || defined(CONFIG_PN62) || defined(CONFIG_SVM_SC8xx)  	/* second onboard ethernet port */  	unsigned char   bi_enet1addr[6];  #endif -#if defined(CONFIG_EVB64260) +#if defined(CONFIG_EVB64260) || defined(CONFIG_SVM_SC8xx)  	/* third onboard ethernet port */  	unsigned char	bi_enet2addr[6];  #endif diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index c462c3f42..4e7ab9be4 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -78,6 +78,7 @@  #define CFG_CMD_SPI	0x0000100000000000	/* SPI utility			*/  #define CFG_CMD_FDOS	0x0000200000000000	/* Floppy DOS support		*/  #define CFG_CMD_VFD	0x0000400000000000	/* VFD support (TRAB)		*/ +#define CFG_CMD_NAND	0x0000800000000000	/* NAND support        		*/  #define CFG_CMD_ALL	0xFFFFFFFFFFFFFFFF	/* ALL commands			*/ @@ -106,6 +107,7 @@  			CFG_CMD_JFFS2	| \  			CFG_CMD_KGDB	| \  			CFG_CMD_MII	| \ +			CFG_CMD_NAND	| \  			CFG_CMD_PCI	| \  			CFG_CMD_PCMCIA	| \  			CFG_CMD_REGINFO | \ diff --git a/include/cmd_nand.h b/include/cmd_nand.h new file mode 100644 index 000000000..febb27dd7 --- /dev/null +++ b/include/cmd_nand.h @@ -0,0 +1,55 @@ +/* + * 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 + */ + +/* + * NAND support + */ +#ifndef	_CMD_NAND_H +#define	_CMD_NAND_H + +#include <common.h> +#include <command.h> + + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#define	CMD_TBL_NAND	MK_CMD_TBL_ENTRY(					\ +	"nand",	3,	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  addr off size\n"						\ +	"nand write addr off size - read/write `size'"				\ +	" bytes starting at offset `off'\n"					\ +	"    to/from memory address `addr'\n"					\ +	"nand erase off size - erase `size' bytes of NAND from offset `off'\n"	\ +), + +#define CMD_TBL_NANDBOOT	MK_CMD_TBL_ENTRY(					\ +	"nboot", 4,	4,	1,	do_nandboot,				\ +	"nboot   - boot from NAND device\n",					\ +	"loadAddr dev\n"							\ +), + +int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#else +#define CMD_TBL_NAND +#define CMD_TBL_NANDBOOT +#endif + +#endif	/* _CMD_NAND_H */ diff --git a/include/commproc.h b/include/commproc.h index 5ff82b71a..a7d8dbd3e 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -1128,6 +1128,57 @@ typedef struct scc_enet {  /***  NETVIA  *******************************************************/ +/* SinoVee Microsystems SC8xx series FEL8xx-AT,SC823,SC850,SC855T,SC860T */ +#if ( defined CONFIG_SVM_SC8xx ) +# ifndef CONFIG_FEC_ENET + +#define PROFF_ENET      PROFF_SCC2 +#define CPM_CR_ENET     CPM_CR_CH_SCC2 +#define SCC_ENET        1 + +	/* Bits in parallel I/O port registers that have to be set/cleared +	 *  *  *  * to configure the pins for SCC2 use. +	 *   *   *   */ +#define PA_ENET_RXD     ((ushort)0x0004)        /* PA 13 */ +#define PA_ENET_TXD     ((ushort)0x0008)        /* PA 12 */ +#define PA_ENET_RCLK    ((ushort)0x0400)        /* PA  5 */ +#define PA_ENET_TCLK    ((ushort)0x0800)        /* PA  4 */ + +#define PB_ENET_TENA    ((uint)0x00002000)      /* PB 18 */ + +#define PC_ENET_CLSN    ((ushort)0x0040)        /* PC  9 */ +#define PC_ENET_RENA    ((ushort)0x0080)        /* PC  8 */ +/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to + *  *  *  * SCC2.  Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. + *   *   *   */ +#define SICR_ENET_MASK  ((uint)0x0000ff00) +#define SICR_ENET_CLKRT ((uint)0x00003700) + +# else                          /* Use FEC for Fast Ethernet */ + +#undef  SCC_ENET +#define FEC_ENET + +#define PD_MII_TXD1     ((ushort)0x1000)        /* PD  3 */ +#define PD_MII_TXD2     ((ushort)0x0800)        /* PD  4 */ +#define PD_MII_TXD3     ((ushort)0x0400)        /* PD  5 */ +#define PD_MII_RX_DV    ((ushort)0x0200)        /* PD  6 */ +#define PD_MII_RX_ERR   ((ushort)0x0100)        /* PD  7 */ +#define PD_MII_RX_CLK   ((ushort)0x0080)        /* PD  8 */ +#define PD_MII_TXD0     ((ushort)0x0040)        /* PD  9 */ +#define PD_MII_RXD0     ((ushort)0x0020)        /* PD 10 */ +#define PD_MII_TX_ERR   ((ushort)0x0010)        /* PD 11 */ +#define PD_MII_MDC      ((ushort)0x0008)        /* PD 12 */ +#define PD_MII_RXD1     ((ushort)0x0004)        /* PD 13 */ +#define PD_MII_RXD2     ((ushort)0x0002)        /* PD 14 */ +#define PD_MII_RXD3     ((ushort)0x0001)        /* PD 15 */ + +#define PD_MII_MASK     ((ushort)0x1FFF)        /* PD 3...15 */ + +# endif /* CONFIG_FEC_ENET */ +#endif  /* CONFIG_SVM_SC8xx */ +	 +	  #if defined(CONFIG_NETVIA)  /* Bits in parallel I/O port registers that have to be set/cleared   * to configure the pins for SCC2 use. diff --git a/include/configs/at91rm9200dk.h b/include/configs/at91rm9200dk.h new file mode 100644 index 000000000..6315f0a2c --- /dev/null +++ b/include/configs/at91rm9200dk.h @@ -0,0 +1,153 @@ +/* + * Rick Bronson <rick@efn.org> + * + * Configuation settings for the AT91RM9200DK 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 + +/* ARM asynchronous clock */ +#define AT91C_MAIN_CLOCK  179712000  /* from 18.432 MHz crystal (18432000 / 4 * 39) */ +#define AT91C_MASTER_CLOCK  59904000  /* peripheral clock (AT91C_MASTER_CLOCK / 3) */ + +#define CONFIG_AT91RM9200DK	1	/* on an AT91RM9200DK Board      */ +#undef CONFIG_USE_IRQ			/* we don't need IRQ/FIQ stuff */ +#define CONFIG_CMDLINE_TAG	 1	/* enable passing of ATAGs	*/ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG	 1 +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN	(CFG_ENV_SIZE + 128*1024) +#define CONFIG_BAUDRATE 115200 +/* + * Hardware drivers + */ + +/* + * select serial console configuration + */ +#define CONFIG_SERIAL3          1	/* we use SERIAL 3 */ + +#undef	CONFIG_HWFLOW			/* don't include RTS/CTS flow control support	*/ + +#undef	CONFIG_MODEM_SUPPORT		/* disable modem initialization stuff */ + +#define CONFIG_COMMANDS		\ +		       (CONFIG_CMD_DFL	| \ +			CFG_CMD_DHCP	| \ +			CFG_CMD_NAND	) +/* 			CFG_CMD_EEPROM	| \ might consider these +			CFG_CMD_I2C	| \ +			CFG_CMD_USB	| \ +			CFG_CMD_MII	| \ +			CFG_CMD_SDRAM	| \ */ +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CFG_MAX_NAND_DEVICE	1	/* Max number of NAND devices		*/ +#define SECTORSIZE 512 + +#define ADDR_COLUMN 1 +#define ADDR_PAGE 2 +#define ADDR_COLUMN_PAGE 3 + +#define NAND_ChipID_UNKNOWN 	0x00 +#define NAND_MAX_FLOORS 1 +#define NAND_MAX_CHIPS 1 + +#define AT91_SMART_MEDIA_ALE (1 << 22)  /* our ALE is AD22 */ +#define AT91_SMART_MEDIA_CLE (1 << 21)  /* our CLE is AD21 */ + +#define NAND_DISABLE_CE(nand) do { *AT91C_PIOC_SODR = AT91C_PIO_PC0;} while(0) +#define NAND_ENABLE_CE(nand) do { *AT91C_PIOC_CODR = AT91C_PIO_PC0;} while(0) + +#define NAND_WAIT_READY(nand) while (!(*AT91C_PIOC_PDSR & AT91C_PIO_PC2)) + +#define WRITE_NAND_COMMAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_CLE) = (__u8)(d); } while(0) +#define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_ALE) = (__u8)(d); } while(0) +#define WRITE_NAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)d; } while(0) +#define READ_NAND(adr) ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)adr)) +/* the following are NOP's in our implementation */ +#define NAND_CTL_CLRALE(nandptr) +#define NAND_CTL_SETALE(nandptr) +#define NAND_CTL_CLRCLE(nandptr) +#define NAND_CTL_SETCLE(nandptr) + +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM 0x20000000 +#define PHYS_SDRAM_SIZE 0x2000000  /* 32 megs */ + +#define CFG_MEMTEST_START PHYS_SDRAM +#define CFG_MEMTEST_END   CFG_MEMTEST_START + PHYS_SDRAM_SIZE - 262144 + +#define CONFIG_DRIVER_ETHER + +#define PHYS_FLASH_1 0x10000000 +#define PHYS_FLASH_SIZE 0x200000  /* 2 megs main flash */ +#define CFG_FLASH_BASE		PHYS_FLASH_1 +#define CFG_MAX_FLASH_BANKS 1 +#define CFG_MAX_FLASH_SECT 40 +#define CFG_FLASH_ERASE_TOUT	(2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT	(2*CFG_HZ) /* Timeout for Flash Write */ +#define	CFG_ENV_IS_IN_FLASH	1 +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0xe000) +#define CFG_ENV_SIZE 0x2000 +#define CFG_LOAD_ADDR 0x21000000  /* default load address */ + +#define CFG_BAUDRATE_TABLE {115200 , 19200, 38400, 57600, 9600 } + +#define CFG_PROMPT "Uboot> " /* Monitor Command Prompt */ +#define	CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +#ifndef __ASSEMBLY__ +/*----------------------------------------------------------------------- + * Board specific extension for bd_info + * + * This structure is embedded in the global bd_info (bd_t) structure + * and can be used by the board specific code (eg board/...) + */ + +struct bd_info_ext +{ +    /* helper variable for board environment handling +     * +     * env_crc_valid == 0    =>   uninitialised +     * env_crc_valid  > 0    =>   environment crc in flash is valid +     * env_crc_valid  < 0    =>   environment crc in flash is invalid +     */ +     int	env_crc_valid; +}; +#endif + +#define	CFG_HZ AT91C_MASTER_CLOCK/2  /* AT91C_TC0_CMR is implicitly set to +                                        AT91C_TC_TIMER_DIV1_CLOCK */ + +#define CONFIG_STACKSIZE	(32*1024)	/* regular stack */ + +#ifdef CONFIG_USE_IRQ +#error CONFIG_USE_IRQ not supported +#endif + +#endif diff --git a/include/configs/dnp1110.h b/include/configs/dnp1110.h index 5a7642b0c..8594e6582 100644 --- a/include/configs/dnp1110.h +++ b/include/configs/dnp1110.h @@ -76,7 +76,7 @@  #define CONFIG_NETMASK          255.255.0.0  #define CONFIG_IPADDR		172.22.2.23  #define CONFIG_SERVERIP		172.22.2.22 -#define CONFIG_BOOTFILE		"elinos-dnp1110" +#define CONFIG_BOOTFILE		"dnp1110"  #define CONFIG_BOOTCOMMAND	"tftp; bootm"  #if (CONFIG_COMMANDS & CFG_CMD_KGDB) @@ -128,21 +128,23 @@  #define PHYS_FLASH_1		0x00000000 /* Flash Bank #1 */  #define PHYS_FLASH_SIZE		0x01000000 /* 16 MB */ +#define PHYS_FLASH_BANK_SIZE    0x01000000 /* 32 MB Banks */ +#define PHYS_FLASH_SECT_SIZE    0x00020000 /* 256 KB sectors (x2) */  #define CFG_FLASH_BASE		PHYS_FLASH_1  /*-----------------------------------------------------------------------   * FLASH and environment organization   */ -#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks		*/ -#define CFG_MAX_FLASH_SECT	(31+8)	/* max number of sectors on one chip	*/ +#define CFG_MAX_FLASH_BANKS	1		/* max number of memory banks		*/ +#define CFG_MAX_FLASH_SECT	128		/* max number of sectors on one chip	*/  /* timeout values are in ticks */  #define CFG_FLASH_ERASE_TOUT	(2*CFG_HZ) /* Timeout for Flash Erase */  #define CFG_FLASH_WRITE_TOUT	(2*CFG_HZ) /* Timeout for Flash Write */  #define	CFG_ENV_IS_IN_FLASH	1 -#define CFG_ENV_ADDR		(PHYS_FLASH_1 + 0x1C000)	/* Addr of Environment Sector	*/ -#define CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/ +#define CFG_ENV_ADDR			(PHYS_FLASH_1 + 0xF80000)	/* Addr of Environment Sector	*/ +#define CFG_ENV_SIZE			0x20000						/* Total Size of Environment Sector	*/  #endif	/* __CONFIG_H */ diff --git a/include/configs/svm_sc8xx.h b/include/configs/svm_sc8xx.h new file mode 100644 index 000000000..b46b0be92 --- /dev/null +++ b/include/configs/svm_sc8xx.h @@ -0,0 +1,470 @@ +/* + * (C) Copyright 2000, 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@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 + */ + +/* + * board/config.h - configuration options, board specific, + *                  for SinoVee Microsystems SC8xx series SBC + *                  http://www.fel.com.cn (Chinese) + *                  http://www.sinovee.com (English) + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* Custom configuration */ +/* SC823,SC850,SC860SAR, FEL8xx-AT(823/850/860) */ +/* SC85T,SC860T, FEL8xx-AT(855T/860T) */ +/*#define CONFIG_FEL8xx_AT */ +/*#define CONFIG_LCD */ +/* if core > 50MHz , un-comment CONFIG_BUS_DIV2 */ +/* #define CONFIG_50MHz */ +/* #define CONFIG_66MHz */ +/* #define CONFIG_75MHz */ +#define CONFIG_80MHz +/*#define CONFIG_100MHz */ +/* #define CONFIG_BUS_DIV2	1 */ +/* for BOOT device port size */ +/* #define CONFIG_BOOT_8B */ +#define CONFIG_BOOT_16B +/* #define CONFIG_BOOT_32B */ +/* #define CONFIG_CAN_DRIVER */ +/* #define DEBUG */ +#define CONFIG_FEC_ENET + +/* #define CONFIG_SDRAM_16M */ +#define CONFIG_SDRAM_32M +/* #define CONFIG_SDRAM_64M */ +#define CFG_RESET_ADDRESS 0xffffffff +/* + * High Level Configuration Options + * (easy to change) + */ + +/* #define CONFIG_MPC823		1 */ +/* #define CONFIG_MPC850		1 */ +#define CONFIG_MPC855		1 +/* #define CONFIG_MPC860		1 */ +/* #define CONFIG_MPC860T		1 */ + +#undef	CONFIG_WATCHDOG			/* watchdog */ + +#define CONFIG_SVM_SC8xx		1	/* ...on SVM SC8xx series 	*/ + +#ifdef	CONFIG_LCD			/* with LCD controller ?	*/ +/* #define CONFIG_NEC_NL6648BC20 1 / * use NEC NL6648BC20 display	*/ +#endif + +#define	CONFIG_8xx_CONS_SMC1	1	/* Console is on SMC1		*/ +#undef	CONFIG_8xx_CONS_SMC2 +#undef	CONFIG_8xx_CONS_NONE +#define CONFIG_BAUDRATE		19200	/* console baudrate = 115kbps	*/ +#if 0 +#define CONFIG_BOOTDELAY	-1	/* autoboot disabled		*/ +#else +#define CONFIG_BOOTDELAY	1	/* autoboot after 5 seconds	*/ +#endif + +#define	CONFIG_CLOCKS_IN_MHZ	1	/* clocks passsed to Linux in MHz */ + +#define CONFIG_BOARD_TYPES      1       /* support board types          */ + +#define CONFIG_PREBOOT	"echo;echo Welcome to U-Boot SVM port;echo;echo Type \"? or help\" to get on-line help;echo" + +#undef	CONFIG_BOOTARGS +#define CONFIG_EXTRA_ENV_SETTINGS                                       \ +        "nfsargs=setenv bootargs root=/dev/nfs rw "                     \ +         "nfsroot=$(serverip):$(rootpath)\0"                     \ +        "ramargs=setenv bootargs root=/dev/ram rw\0"                    \ +        "addip=setenv bootargs $(bootargs) "                            \ +               "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)"      \ +                ":$(hostname):$(netdev):off panic=1\0"                  \ +	        "flash_nfs=run nfsargs addip;"                                  \ +             "bootm $(kernel_addr)\0"                                \ +        "flash_self=run ramargs addip;"                                 \ +               "bootm $(kernel_addr) $(ramdisk_addr)\0"                \ +        "net_nfs=tftp 0x210000 $(bootfile);run nfsargs addip;bootm\0"     \ +        "rootpath=/opt/sinovee/ppc8xx-linux-2.0/target\0"                                  \ +        "bootfile=pImage-sc855t\0"                           \ +        "kernel_addr=48000000\0"                                        \ +        "ramdisk_addr=48100000\0"                                       \ +        "" +#define CONFIG_BOOTCOMMAND							\ +	"setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " 	\ +	"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " 	\ +	"tftpboot 0x210000 pImage-sc855t;bootm 0x210000" + +#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/ +#undef	CFG_LOADS_BAUD_CHANGE		/* don't allow baudrate change	*/ + + +#ifdef CONFIG_LCD +# undef	 CONFIG_STATUS_LED		/* disturbs display		*/ +#else +# define CONFIG_STATUS_LED	1	/* Status LED enabled		*/ +#endif	/* CONFIG_LCD */ + +#undef	CONFIG_CAN_DRIVER		/* CAN Driver support disabled	*/ + +#define CONFIG_BOOTP_MASK	(CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +#define	CONFIG_RTC_MPC8xx		/* use internal RTC of MPC8xx	*/ + +#define CONFIG_COMMANDS	      ( CONFIG_CMD_DFL	| \ +		                CFG_CMD_ASKENV  | \ +		 		CFG_CMD_DHCP	| \ +				CFG_CMD_DOC	| \ +/*				CFG_CMD_IDE     |*/ \ +				CFG_CMD_DATE	) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define	CFG_LONGHELP			/* undef to save memory		*/ +#define	CFG_PROMPT	"=> "		/* Monitor Command Prompt	*/ + +#ifdef  CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2     "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define	CFG_CBSIZE	1024		/* Console I/O Buffer Size	*/ +#else +#define	CFG_CBSIZE	256		/* Console I/O Buffer Size	*/ +#endif +#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_MEMTEST_START	0x0400000	/* memtest works on	*/ +#define CFG_MEMTEST_END		0x0C00000	/* 4 ... 12 MB in DRAM	*/ + +#define	CFG_LOAD_ADDR		0x100000	/* default load address	*/ + +#define	CFG_HZ		1000		/* decrementer freq: 1 ms ticks	*/ + +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +/*----------------------------------------------------------------------- + * Internal Memory Mapped Register + */ +#define CFG_IMMR		0xFF000000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR	CFG_IMMR +#define	CFG_INIT_RAM_END	0x2F00	/* End of used area in DPRAM	*/ +#define	CFG_GBL_DATA_SIZE	64  /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define	CFG_INIT_SP_OFFSET	CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define	CFG_SDRAM_BASE		0x00000000 +#define CFG_FLASH_BASE		0x40000000 +#define	CFG_MONITOR_LEN		(384 << 10)	/* Reserve 192 kB for Monitor	*/ +#define CFG_MONITOR_BASE	CFG_FLASH_BASE +#define	CFG_MALLOC_LEN		(128 << 10)	/* Reserve 128 kB for malloc()	*/ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define	CFG_BOOTMAPSZ		(8 << 20)	/* Initial Memory map for Linux	*/ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS	2	/* max number of memory banks		*/ +#define CFG_MAX_FLASH_SECT	67	/* max number of sectors on one chip	*/ + +#define CFG_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/ +#define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/ + +#define	CFG_ENV_IS_IN_FLASH	1 + +#ifdef CONFIG_BOOT_8B +#define	CFG_ENV_OFFSET		0x10000	/*   Offset   of Environment Sector	*/ +#define	CFG_ENV_SIZE		0x10000	/* Total Size of Environment Sector	*/ +#elif defined (CONFIG_BOOT_16B) +#define	CFG_ENV_OFFSET		0x10000	/*   Offset   of Environment Sector	*/ +#define	CFG_ENV_SIZE		0x10000	/* Total Size of Environment Sector	*/ +#elif defined (CONFIG_BOOT_32B) +#define	CFG_ENV_OFFSET		0x8000	/*   Offset   of Environment Sector	*/ +#define	CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/ +#endif + +/* Address and size of Redundant Environment Sector     */ +#define CFG_ENV_OFFSET_REDUND   (CFG_ENV_OFFSET+CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND     (CFG_ENV_SIZE) + + +/*----------------------------------------------------------------------- + * Hardware Information Block + */ +#define CFG_HWINFO_OFFSET	0x0003FFC0	/* offset of HW Info block */ +#define CFG_HWINFO_SIZE		0x00000040	/* size   of HW Info block */ +#define CFG_HWINFO_MAGIC	0x46454C38	/* 'SVM8' */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE	16	/* For all MPC8xx CPUs			*/ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT	4	/* log base 2 of the above value	*/ +#endif + +/*----------------------------------------------------------------------- + * SYPCR - System Protection Control				11-9 + * SYPCR can only be written once after reset! + *----------------------------------------------------------------------- + * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze + */ +#if defined(CONFIG_WATCHDOG) +/*#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ +			 SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP) +*/ +#define CFG_SYPCR	(SYPCR_SWTC | SYPCR_BMT | SYPCR_SWF | \ +			 SYPCR_SWE  | SYPCR_SWRI| SYPCR_SWP) +#else +#define CFG_SYPCR 0xffffff88 +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration				11-6 + *----------------------------------------------------------------------- + * PCMCIA config., multi-function pin tri-state + */ +#ifndef	CONFIG_CAN_DRIVER +/*#define CFG_SIUMCR 0x00610c00	*/ +#define CFG_SIUMCR 0x00000000	 +#else	/* we must activate GPL5 in the SIUMCR for CAN */ +#define CFG_SIUMCR	(SIUMCR_DBGC11 | SIUMCR_DBPC00 | SIUMCR_MLRC01) +#endif	/* CONFIG_CAN_DRIVER */ + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control				11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freezing enabled + */ +#define CFG_TBSCR	0x0001 + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register		11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC	0x00c3 + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control		11-31 + *----------------------------------------------------------------------- + * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled + */ +#define CFG_PISCR	0x0000 + +/*----------------------------------------------------------------------- + * PLPRCR - PLL, Low-Power, and Reset Control Register		15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit + */ +#if defined (CONFIG_100MHz) +#define CFG_PLPRCR 0x06301000 +#define CONFIG_8xx_GCLK_FREQ 100000000 +#elif defined (CONFIG_80MHz) +#define CFG_PLPRCR 0x04f01000 +#define CONFIG_8xx_GCLK_FREQ 80000000 +#elif defined(CONFIG_75MHz)	 +#define CFG_PLPRCR 0x04a00100	 +#define CONFIG_8xx_GCLK_FREQ 75000000 +#elif defined(CONFIG_66MHz)	 +#define CFG_PLPRCR 0x04101000	 +#define CONFIG_8xx_GCLK_FREQ 66000000 +#elif defined(CONFIG_50MHz)	 +#define CFG_PLPRCR 0x03101000	 +#define CONFIG_8xx_GCLK_FREQ 50000000 +#endif	 + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register		15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK	SCCR_EBDF11 +#ifdef	CONFIG_BUS_DIV2	 +#define CFG_SCCR	0x02020000 | SCCR_RTSEL +#else			/* up to 50 MHz we use a 1:1 clock */ +#define CFG_SCCR    0x02000000 | SCCR_RTSEL +#endif	 + +/*----------------------------------------------------------------------- + * PCMCIA stuff + *----------------------------------------------------------------------- + * + */ +#define CFG_PCMCIA_MEM_ADDR	(0xE0000000) +#define CFG_PCMCIA_MEM_SIZE	( 64 << 20 ) +#define CFG_PCMCIA_DMA_ADDR	(0xE4000000) +#define CFG_PCMCIA_DMA_SIZE	( 64 << 20 ) +#define CFG_PCMCIA_ATTRB_ADDR	(0xE8000000) +#define CFG_PCMCIA_ATTRB_SIZE	( 64 << 20 ) +#define CFG_PCMCIA_IO_ADDR	(0xEC000000) +#define CFG_PCMCIA_IO_SIZE	( 64 << 20 ) + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#undef	CONFIG_IDE_8xx_PCCARD   	/* Use IDE with PC Card	Adapter	*/ + +#define	CONFIG_IDE_8xx_DIRECT	1	/* Direct IDE    not supported	*/ +#undef	CONFIG_IDE_LED			/* LED   for ide not supported	*/ +#undef	CONFIG_IDE_RESET		/* reset for ide not supported	*/ + +#define CFG_IDE_MAXBUS		1	/* max. 1 IDE bus		*/ +#define CFG_IDE_MAXDEVICE	1 	/* max. 1 drive per IDE bus	*/ + +#define CFG_ATA_BASE_ADDR       0xFE100010 +#define CFG_ATA_IDE0_OFFSET     0x0000 +/*#define CFG_ATA_IDE1_OFFSET     0x0C00 */ +#define CFG_ATA_DATA_OFFSET     0x0000  /* Offset for data I/O +					   */ +#define CFG_ATA_REG_OFFSET      0x0200  /* Offset for normal register accesses +					   */ +#define CFG_ATA_ALT_OFFSET      0x0210  /* Offset for alternate registers +					   */ +#define CONFIG_ATAPI     +#define CFG_PIO_MODE 0 + +/*----------------------------------------------------------------------- + * + *----------------------------------------------------------------------- + * + */ +/*#define	CFG_DER	0x2002000F*/ +#define CFG_DER	0x0 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM	0x40000000	/* FLASH bank #0	*/ +#define FLASH_BASE1_PRELIM	0x60000000	/* FLASH bank #0	*/ + +/* used to re-map FLASH both when starting from SRAM or FLASH: + * restrict access enough to keep SRAM working (if any) + * but not too much to meddle with FLASH accesses + */ +#define CFG_REMAP_OR_AM		0x80000000	/* OR addr mask */ +#define CFG_PRELIM_OR_AM	0xE0000000	/* OR addr mask */ + +/* + * FLASH timing: + */ +#if defined(CONFIG_100MHz)  +#define CFG_OR_TIMING_FLASH 0x000002f4	 +#define CFG_OR_TIMING_DOC   0x000002f4	 +#define CFG_MxMR_PTx 0x61000000 +#define CFG_MPTPR 0x400 + +#elif  defined(CONFIG_80MHz) +#define CFG_OR_TIMING_FLASH 0x00000ff4	 +#define CFG_OR_TIMING_DOC   0x000001f4	 +#define CFG_MxMR_PTx 0x4e000000 +#define CFG_MPTPR 0x400 + +#elif defined(CONFIG_75MHz)  +#define CFG_OR_TIMING_FLASH 0x000008f4	 +#define CFG_OR_TIMING_DOC   0x000002f4	 +#define CFG_MxMR_PTx 0x49000000 +#define CFG_MPTPR 0x400 + +#elif defined(CONFIG_66MHz) +#define CFG_OR_TIMING_FLASH     (OR_ACS_DIV1  | OR_TRLX | OR_CSNT_SAM | \ +        OR_SCY_3_CLK | OR_EHTR | OR_BI) +/*#define CFG_OR_TIMING_FLASH 0x000001f4 */ +#define CFG_OR_TIMING_DOC   0x000003f4	 +#define CFG_MxMR_PTx  0x40000000 +#define CFG_MPTPR 0x400 + +#else		/*   50 MHz */ +#define CFG_OR_TIMING_FLASH 0x00000ff4 +#define CFG_OR_TIMING_DOC   0x000001f4	 +#define CFG_MxMR_PTx  0x30000000 +#define CFG_MPTPR 0x400 +#endif	/*CONFIG_??MHz */ + + +#if  defined (CONFIG_BOOT_8B)   /* 512K X 8 ,29F040 , 2MB space */ +#define CFG_OR0_PRELIM	(0xffe00000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM	((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V | BR_PS_8) +#elif  defined (CONFIG_BOOT_16B)   /* 29lv160 X 16 , 4MB space */ +#define CFG_OR0_PRELIM	(0xffc00000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM	((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V | BR_PS_16) +#elif defined( CONFIG_BOOT_32B )  /* 29lv160 X 2 X 32, 4/8/16MB , 64MB space */ +#define CFG_OR0_PRELIM	(0xfc000000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM	((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V ) +#else +#error Boot device port size missing. +#endif + +/* + * Disk-On-Chip configuration + */ + +#define CFG_DOC_SHORT_TIMEOUT +#define CFG_MAX_DOC_DEVICE      1       /* Max number of DOC devices    */ + +#define CFG_DOC_SUPPORT_2000 +#define CFG_DOC_SUPPORT_MILLENNIUM +#define CFG_DOC_BASE 0x80000000 + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define	BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH	*/ +#define BOOTFLAG_WARM	0x02		/* Software reboot			*/ + +#endif	/* __CONFIG_H */ diff --git a/include/flash.h b/include/flash.h index b4c8bad3d..b7f13d340 100644 --- a/include/flash.h +++ b/include/flash.h @@ -105,6 +105,7 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot);  #define AMD_MANUFACT	0x00010001	/* AMD     manuf. ID in D23..D16, D7..D0 */  #define FUJ_MANUFACT	0x00040004	/* FUJITSU manuf. ID in D23..D16, D7..D0 */ +#define ATM_MANUFACT    0x001F001F      /* ATMEL */  #define STM_MANUFACT	0x00200020	/* STM (Thomson) manuf. ID in D23.. -"-	*/  #define SST_MANUFACT	0x00BF00BF	/* SST     manuf. ID in D23..D16, D7..D0 */  #define MT_MANUFACT	0x00890089	/* MT      manuf. ID in D23..D16, D7..D0 */ @@ -156,6 +157,8 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot);  #define AMD_ID_DL640	0x227E227E	/* 29DL640D ID (64 M, dual boot sectors)*/  #define AMD_ID_LV640U	0x22D722D7	/* 29LV640U ID (64 M, uniform sectors)	*/ +#define ATM_ID_BV1614   0x000000C0      /* 49BV1614 ID */ +  #define FUJI_ID_29F800BA  0x22582258   /* MBM29F800BA ID  (8M) */  #define FUJI_ID_29F800TA  0x22D622D6   /* MBM29F800TA ID  (8M) */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index a3a7ec352..442518721 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1,10 +1,11 @@  /* - *  u-boot/include/linux/mtd/nand.h + *  linux/include/linux/mtd/nand.h   *   *  Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>   *                     Steven J. Hill <sjhill@cotw.com> + *		       Thomas Gleixner <gleixner@autronix.de>   * - * $Id: nand.h,v 1.8 2000/10/30 17:16:17 sjhill Exp $ + * $Id: nand.h,v 1.13 2002/04/28 13:40:41 gleixner Exp $   *   * 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 @@ -23,6 +24,14 @@   *			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  + *			hardwarespecific function for accessing control lines + *   02-21-2002 TG	added support for different read/write adress and + *			ready/busy line access function + *   02-26-2002 TG	added chip_delay to nand_chip structure to optimize + *			command delay times for different chips + *   04-28-2002 TG	OOB config defines moved from nand.c to avoid duplicate + *			defines in jffs2/wbuf.c   */  #ifndef __LINUX_MTD_NAND_H  #define __LINUX_MTD_NAND_H @@ -42,6 +51,82 @@  #define NAND_CMD_RESET		0xff  /* + * Enumeration for NAND flash chip state + */ +typedef enum { +	FL_READY, +	FL_READING, +	FL_WRITING, +	FL_ERASING, +	FL_SYNCING +} nand_state_t; + + +/* + * NAND Private Flash Chip Data + * + * Structure overview: + * + *  IO_ADDR - address to access the 8 I/O lines of the flash device  + * + *  hwcontrol - hardwarespecific function for accesing control-lines + * + *  dev_ready - hardwarespecific function for accesing device ready/busy line + * + *  chip_lock - spinlock used to protect access to this structure + * + *  wq - wait queue to sleep on if a NAND operation is in progress + * + *  state - give the current state of the NAND device + * + *  page_shift - number of address bits in a page (column address bits) + * + *  data_buf - data buffer passed to/from MTD user modules + * + *  data_cache - data cache for redundant page access and shadow for + *		 ECC failure + * + *  ecc_code_buf - used only for holding calculated or read ECCs for + *                 a page read or written when ECC is in use + * + *  reserved - padding to make structure fall on word boundary if + *             when ECC is in use + */ +struct Nand { +	char floor, chip; +	unsigned long curadr; +	unsigned char curmode; +	/* Also some erase/write/pipeline info when we get that far */ +}; + +struct nand_chip { +	int 		page_shift; +	u_char 		*data_buf; +	u_char 		*data_cache; +	int		cache_page; +	u_char 		ecc_code_buf[6]; +	u_char 		reserved[2]; +	char ChipID; /* Type of DiskOnChip */ +	struct Nand *chips; +	int chipshift; +	char* chips_name; +	unsigned long erasesize; +	unsigned long mfr; /* Flash IDs - only one type of flash per device */ +	unsigned long id; +	char* name; +	struct NFTLrecord nftl; +	int nftl_found; +	int numchips; +	char page256; +	char pageadrlen; +	unsigned long IO_ADDR;  /* address to access the 8 I/O lines to the flash device */ +	unsigned long totlen; +	uint oobblock;  // Size of OOB blocks (e.g. 512) +	uint oobsize;   // Amount of OOB data per block (e.g. 16) +	uint eccsize; +}; + +/*   * NAND Flash Manufacturer ID Codes   */  #define NAND_MFR_TOSHIBA	0x98 @@ -84,4 +169,30 @@ struct nand_flash_dev {  	unsigned long erasesize;  }; +/* +* Constants for oob configuration +*/ +#define NAND_NOOB_ECCPOS0		0 +#define NAND_NOOB_ECCPOS1		1 +#define NAND_NOOB_ECCPOS2		2 +#define NAND_NOOB_ECCPOS3		3 +#define NAND_NOOB_ECCPOS4		4 +#define NAND_NOOB_ECCPOS5		5 +#define NAND_NOOB_BADBPOS		-1 +#define NAND_NOOB_ECCVPOS		-1 + +#define NAND_JFFS2_OOB_ECCPOS0		0 +#define NAND_JFFS2_OOB_ECCPOS1		1 +#define NAND_JFFS2_OOB_ECCPOS2		2 +#define NAND_JFFS2_OOB_ECCPOS3		3 +#define NAND_JFFS2_OOB_ECCPOS4		6 +#define NAND_JFFS2_OOB_ECCPOS5		7 +#define NAND_JFFS2_OOB_BADBPOS		5 +#define NAND_JFFS2_OOB_ECCVPOS		4 + +#define NAND_JFFS2_OOB8_FSDAPOS		6 +#define NAND_JFFS2_OOB16_FSDAPOS	8 +#define NAND_JFFS2_OOB8_FSDALEN		2 +#define NAND_JFFS2_OOB16_FSDALEN	8 +  #endif /* __LINUX_MTD_NAND_H */ diff --git a/include/pcmcia.h b/include/pcmcia.h index beb1c16e4..16653f35a 100644 --- a/include/pcmcia.h +++ b/include/pcmcia.h @@ -48,7 +48,7 @@  # else  #  define CONFIG_PCMCIA_SLOT_B  # endif -#elif defined(CONFIG_TQM8xxL) +#elif defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx)  # define	CONFIG_PCMCIA_SLOT_B	/* The TQM8xxL use SLOT_B	*/  #elif defined(CONFIG_SPD823TS)		/* The SPD8xx  use SLOT_B	*/  # define CONFIG_PCMCIA_SLOT_B diff --git a/include/status_led.h b/include/status_led.h index 369cce2f6..79d9fb475 100644 --- a/include/status_led.h +++ b/include/status_led.h @@ -269,6 +269,20 @@ void status_led_set  (int led, int state);  # define STATUS_LED_BOOT	0		/* LED 0 used for boot status */ +#elif defined(CONFIG_SVM_SC8xx) +# define STATUS_LED_PAR         im_cpm.cp_pbpar +# define STATUS_LED_DIR         im_cpm.cp_pbdir +# define STATUS_LED_ODR         im_cpm.cp_pbodr +# define STATUS_LED_DAT         im_cpm.cp_pbdat + +# define STATUS_LED_BIT         0x00000001 +# define STATUS_LED_PERIOD      (CFG_HZ / 2) +# define STATUS_LED_STATE       STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE      1               /* LED on for bit == 1  */ + +# define STATUS_LED_BOOT        0               /* LED 0 used for boot status */ +  /************************************************************************/  #else  # error Status LED configuration missing diff --git a/lib_arm/board.c b/lib_arm/board.c index 244c0b5b6..828c2f205 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -31,6 +31,9 @@  #include <version.h>  #include <net.h> +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +void nand_init (void); +#endif  const char version_string[] =  	U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; @@ -227,6 +230,10 @@ void start_armboot (void)  	mem_malloc_init (_armboot_real_end);  #endif /* CONFIG_VFD */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +	nand_init();		/* go init the NAND */ +#endif +  	/* initialize environment */  	env_relocate (); |