diff options
| author | wdenk <wdenk> | 2004-06-09 13:37:52 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-06-09 13:37:52 +0000 | 
| commit | f39748ae8edb03017647b0d731cdd06e7bdcde13 (patch) | |
| tree | 1401c99d4d11bef3828da3bda191e8923f3f1147 | |
| parent | aa24509041ff8a4892071c2abec023dddd53874f (diff) | |
| download | olio-uboot-2014.01-f39748ae8edb03017647b0d731cdd06e7bdcde13.tar.xz olio-uboot-2014.01-f39748ae8edb03017647b0d731cdd06e7bdcde13.zip | |
* Patch by Paul Ruhland, 17 May 2004:
  - Add support for the Logic Zoom LH7A40x based SDK board(s),
    specifically the LPD7A400.
* Patches by Robert Schwebel, 15 May 2004:
  - call MAC address reading code also for SMSC91C111;
  - make SMSC91C111 timeout configurable, remove duplicate code
  - fix get_timer() for PXA
  - update doc/README.JFFS2
  - use "bootfile" env variable also for jffs2
| -rw-r--r-- | CHANGELOG | 11 | ||||
| -rw-r--r-- | CREDITS | 4 | ||||
| -rw-r--r-- | MAKEALL | 7 | ||||
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README | 20 | ||||
| -rw-r--r-- | board/lpd7a40x/Makefile | 47 | ||||
| -rw-r--r-- | board/lpd7a40x/config.mk | 38 | ||||
| -rw-r--r-- | board/lpd7a40x/flash.c | 494 | ||||
| -rw-r--r-- | board/lpd7a40x/lpd7a40x.c | 82 | ||||
| -rw-r--r-- | board/lpd7a40x/memsetup.S | 212 | ||||
| -rw-r--r-- | board/lpd7a40x/u-boot.lds | 56 | ||||
| -rw-r--r-- | common/cmd_jffs2.c | 8 | ||||
| -rw-r--r-- | cpu/lh7a40x/Makefile | 43 | ||||
| -rw-r--r-- | cpu/lh7a40x/config.mk | 27 | ||||
| -rw-r--r-- | cpu/lh7a40x/cpu.c | 183 | ||||
| -rw-r--r-- | cpu/lh7a40x/interrupts.c | 326 | ||||
| -rw-r--r-- | cpu/lh7a40x/serial.c | 183 | ||||
| -rw-r--r-- | cpu/lh7a40x/speed.c | 83 | ||||
| -rw-r--r-- | cpu/lh7a40x/start.S | 426 | ||||
| -rw-r--r-- | cpu/pxa/interrupts.c | 2 | ||||
| -rw-r--r-- | doc/README.JFFS2 | 4 | ||||
| -rw-r--r-- | drivers/smc91111.c | 47 | ||||
| -rw-r--r-- | include/bmp_logo.h | 2 | ||||
| -rw-r--r-- | include/common.h | 5 | ||||
| -rw-r--r-- | include/configs/innokom.h | 1 | ||||
| -rw-r--r-- | include/configs/lpd7a400-10.h | 80 | ||||
| -rw-r--r-- | include/configs/lpd7a400.h | 114 | ||||
| -rw-r--r-- | include/lh7a400.h | 93 | ||||
| -rw-r--r-- | include/lh7a40x.h | 258 | ||||
| -rw-r--r-- | include/lpd7a400_cpld.h | 195 | ||||
| -rw-r--r-- | lib_arm/board.c | 15 | 
31 files changed, 3031 insertions, 37 deletions
| @@ -2,6 +2,17 @@  Changes since U-Boot 1.1.1:  ====================================================================== +* Patch by Paul Ruhland, 17 May 2004: +  - Add support for the Logic Zoom LH7A40x based SDK board(s), +    specifically the LPD7A400. + +* Patches by Robert Schwebel, 15 May 2004: +  - call MAC address reading code also for SMSC91C111; +  - make SMSC91C111 timeout configurable, remove duplicate code +  - fix get_timer() for PXA +  - update doc/README.JFFS2 +  - use "bootfile" env variable also for jffs2 +  * Patch by Tolunay Orkun, 14 May 2004:    Add support for Cogent CSB472 board (8MB Flash Rev) @@ -358,3 +358,7 @@ W: www.elinos.com  N: Xianghua Xiao  E: x.xiao@motorola.com  D: Support for Motorola 85xx(PowerQUICC III) chip, MPC8540ADS and MPC8560ADS boards. + +N: Paul Ruhland +E: pruhland@rochester.rr.com +D: Port to Logic Zoom LH7A40x SDK board(s) @@ -139,9 +139,10 @@ LIST_ARM7="B2 ep7312 impa7"  LIST_ARM9="	\  	at91rm9200dk	integratorcp	integratorap			\ -	omap1510inn	omap1610h2	omap1610inn			\ -	omap730p2	smdk2400	smdk2410			\ -	trab		VCMA9		versatile			\ +	lpd7a400	omap1510inn	omap1610h2			\ +	omap1610inn	omap730p2	smdk2400			\ +	smdk2410	trab		VCMA9				\ +	versatile							\  "  ######################################################################### @@ -1096,6 +1096,8 @@ trab_old_config:	unconfig  VCMA9_config	:	unconfig  	@./mkconfig $(@:_config=) arm arm920t vcma9 mpl +lpd7a400_config:	unconfig +	@./mkconfig $(@:_config=) arm lh7a40x lpd7a40x  #########################################################################  ## S3C44B0 Systems @@ -294,9 +294,9 @@ The following options need to be configured:  		CONFIG_AT91RM9200DK,		CONFIG_DNP1110,		CONFIG_EP7312,  		CONFIG_H2_OMAP1610,		CONFIG_HHP_CRADLE,	CONFIG_IMPA7,  		CONFIG_INNOVATOROMAP1510,   CONFIG_INNOVATOROMAP1610,	CONFIG_LART, -		CONFIG_LUBBOCK,			CONFIG_OSK_OMAP5912,	CONFIG_SHANNON, -		CONFIG_P2_OMAP730,		CONFIG_SMDK2400,	CONFIG_SMDK2410, -		CONFIG_TRAB,			CONFIG_VCMA9 +		CONFIG_LPD7A400			CONFIG_LUBBOCK,		CONFIG_OSK_OMAP5912, +		CONFIG_SHANNON,			CONFIG_P2_OMAP730,	CONFIG_SMDK2400, +		CONFIG_SMDK2410,		CONFIG_TRAB,		CONFIG_VCMA9  		MicroBlaze based boards:  		------------------------ @@ -741,6 +741,20 @@ The following options need to be configured:  			CONFIG_LAN91C96_USE_32_BIT  			Define this to enable 32 bit addressing +		CONFIG_DRIVER_SMC91111 +		Support for SMSC's LAN91C111 chip + +			CONFIG_SMC91111_BASE +			Define this to hold the physical address +			of the device (I/O space) + +			CONFIG_SMC_USE_32_BIT +			Define this if data bus is 32 bits + +			CONFIG_SMC_USE_IOFUNCS +			Define this to use i/o functions instead of macros +			(some hardware wont work with macros) +  - USB Support:  		At the moment only the UHCI host controller is  		supported (PIP405, MIP405, MPC5200); define diff --git a/board/lpd7a40x/Makefile b/board/lpd7a40x/Makefile new file mode 100644 index 000000000..f0999d173 --- /dev/null +++ b/board/lpd7a40x/Makefile @@ -0,0 +1,47 @@ +# +# (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 $(TOPDIR)/config.mk + +LIB	= lib$(BOARD).a + +OBJS	:= lpd7a40x.o flash.o +SOBJS	:= memsetup.o + +$(LIB):	$(OBJS) $(SOBJS) +	$(AR) crv $@ $(OBJS) $(SOBJS) + +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/lpd7a40x/config.mk b/board/lpd7a40x/config.mk new file mode 100644 index 000000000..bc03874a4 --- /dev/null +++ b/board/lpd7a40x/config.mk @@ -0,0 +1,38 @@ +# +# 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 +# + +# Logic ZOOM LH7A400 SDK board w/Logic LH7A400-10 card engine +# w/Sharp LH7A400 SoC (ARM920T) cpu +# + +# +# 32 or 64 MB SDRAM on SDCSC0 @ 0xc0000000 +# +# Linux-Kernel is @ 0xC0008000, entry 0xc0008000 +# params @ 0xc0000100 +# optionally with a ramdisk at 0xc0300000 +# +# we load ourself to 0xc1fc0000 (32M - 256K) +# +# download area is 0xc0f00000 +# + +TEXT_BASE = 0xc1fc0000 +#TEXT_BASE = 0x00000000 diff --git a/board/lpd7a40x/flash.c b/board/lpd7a40x/flash.c new file mode 100644 index 000000000..26a9ce457 --- /dev/null +++ b/board/lpd7a40x/flash.c @@ -0,0 +1,494 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (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 + */ + +/* #define DEBUG */ + +#include <common.h> +#include <environment.h> + +#define FLASH_BANK_SIZE 0x1000000	/* 16MB (2 x 8 MB) */ +#define MAIN_SECT_SIZE  0x40000		/* 256KB (2 x 128kB) */ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + + +#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 + +/*----------------------------------------------------------------------- + */ + +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 = +			(INTEL_MANUFACT     & FLASH_VENDMASK) | +			(INTEL_ID_28F640J3A & 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 = CFG_FLASH_BASE; +		else +			panic ("configured too many flash banks!\n"); +		for (j = 0; j < flash_info[i].sector_count; j++) { +			flash_info[i].start[j] = flashbase; + +			/* uniform sector size */ +			flashbase += MAIN_SECT_SIZE; +		} +		size += flash_info[i].size; +	} + +	/* +	 * Protect monitor and environment sectors +	 */ +	flash_protect ( FLAG_PROTECT_SET, +			CFG_FLASH_BASE, +			CFG_FLASH_BASE + monitor_flash_len - 1, +			&flash_info[0]); + +	flash_protect ( FLAG_PROTECT_SET, +			CFG_ENV_ADDR, +			CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); + +#ifdef CFG_ENV_ADDR_REDUND +	flash_protect ( FLAG_PROTECT_SET, +			CFG_ENV_ADDR_REDUND, +			CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, +			&flash_info[0]); +#endif + +	return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ +	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_28F640J3A & FLASH_TYPEMASK): +		printf ("2x 28F640J3A (64Mbit)\n"); +		break; +	default: +		printf ("Unknown Chip Type\n"); +		return; +		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"); +} + +/*----------------------------------------------------------------------- + */ + +int flash_error (ulong code) +{ +	/* 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 */ + +	/* sequence is described in Intel 290644-005 document */ + +	/* check Timeout */ +	if (code & BIT_TIMEOUT) { +		puts ("Timeout\n"); +		return ERR_TIMOUT; +	} + +	/* check Busy, SR.7 */ +	if (~code & BIT_BUSY) { +		puts ("Busy\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Vpp low, SR.3 */ +	if (code & BIT_VPP_RANGE_ERROR) { +		puts ("Vpp range error\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Device Protect Error, SR.1 */ +	if (code & BIT_PROTECT_ERROR) { +		puts ("Device protect error\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Command Seq Error, SR.4 & SR.5 */ +	if (code & BIT_SEQUENCE_ERROR) { +		puts ("Command seqence error\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Block Erase Error, SR.5 */ +	if (code & BIT_ERASE_ERROR) { +		puts ("Block erase error\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Program Error, SR.4 */ +	if (code & BIT_PROGRAM_ERROR) { +		puts ("Program error\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Block Erase Suspended, SR.6 */ +	if (code & BIT_ERASE_SUSPEND) { +		puts ("Block erase suspended\n"); +		return ERR_PROG_ERROR; +	} + +	/* check Program Suspended, SR.2 */ +	if (code & BIT_PROGRAM_SUSPEND) { +		puts ("Program suspended\n"); +		return ERR_PROG_ERROR; +	} + +	/* OK, no error */ +	return ERR_OK; +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ +	ulong result, result1; +	int iflag, prot, sect; +	int rc = ERR_OK; + +#ifdef USE_920T_MMU +	int cflag; +#endif + +	debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last); + +	/* 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) != +		(INTEL_MANUFACT & FLASH_VENDMASK)) { +		return ERR_UNKNOWN_FLASH_VENDOR; +	} + +	prot = 0; +	for (sect = s_first; sect <= s_last; ++sect) { +		if (info->protect[sect]) { +			prot++; +		} +	} + +	if (prot) { +		printf ("- Warning: %d protected sectors will not be erased!\n", +			prot); +	} else { +		printf ("\n"); +	} + +	/* +	 * 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. +	 */ +#ifdef USE_920T_MMU +	cflag = dcache_status (); +	dcache_disable (); +#endif +	iflag = disable_interrupts (); + +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { + +		debug ("Erasing sector %2d @ %08lX... ", +			sect, info->start[sect]); + +		/* arm simple, non interrupt dependent timer */ +		reset_timer(); + +		if (info->protect[sect] == 0) {	/* not protected */ +			vu_long *addr = (vu_long *) (info->start[sect]); +			ulong bsR7, bsR7_2, bsR5, bsR5_2; +			ulong tstart; + +			/* *addr = CMD_STATUS_RESET; */ +			*addr = CMD_ERASE_SETUP; +			*addr = CMD_ERASE_CONFIRM; + +			/* wait until flash is ready */ +			tstart = get_timer(0); +			do { +				ulong now; +				/* check timeout */ +				//if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { +				if ((now = get_timer(tstart)) > CFG_FLASH_ERASE_TOUT) { +					printf("tstart = 0x%08lx, now = 0x%08lx\n", tstart, now); +					*addr = CMD_STATUS_RESET; +					result = BIT_TIMEOUT; +					break; +				} + +				*addr = CMD_STATUS_READ; +				result = *addr; +				bsR7 = result & (1 << 7); +				bsR7_2 = result & (1 << 23); +			} while (!bsR7 | !bsR7_2); + +			*addr = CMD_STATUS_READ; +			result1 = *addr; +			bsR5 = result1 & (1 << 5); +			bsR5_2 = result1 & (1 << 21); +#ifdef SAMSUNG_FLASH_DEBUG +			printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2); +			if (bsR5 != 0 && bsR5_2 != 0) +				printf ("bsR5 %lx bsR5_2 %lx\n", bsR5, bsR5_2); +#endif + +			*addr = CMD_READ_ARRAY; +			*addr = CMD_RESUME; + +			if ((rc = flash_error (result)) != ERR_OK) +				goto outahere; +#if 0 +			printf ("ok.\n"); +		} else {		/* it was protected */ + +			printf ("protected!\n"); +#endif +		} +	} + +outahere: +	/* allow flash to settle - wait 10 ms */ +	udelay_masked (10000); + +	if (iflag) +		enable_interrupts (); + +#ifdef USE_920T_MMU +	if (cflag) +		dcache_enable (); +#endif +	return rc; +} + +/*----------------------------------------------------------------------- + * 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 iflag; + +#ifdef USE_920T_MMU +	int cflag; +#endif + +	/* +	 * 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. +	 */ +#ifdef USE_920T_MMU +	cflag = dcache_status (); +	dcache_disable (); +#endif +	iflag = disable_interrupts (); + +	/* *addr = CMD_STATUS_RESET; */ +	*addr = 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 = CMD_SUSPEND; +			result = BIT_TIMEOUT; +			break; +		} + +		*addr = CMD_STATUS_READ; +		result = *addr; +	} while (~result & BIT_BUSY); + +	/* *addr = CMD_READ_ARRAY; */ +	*addr = CMD_STATUS_READ; +	result = *addr; + +	rc = flash_error (result); + +	if (iflag) +		enable_interrupts (); + +#ifdef USE_920T_MMU +	if (cflag) +		dcache_enable (); +#endif +	*addr = CMD_READ_ARRAY; +	*addr = CMD_RESUME; +	return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ +	ulong cp, wp, data; +	int l; +	int i, 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 << 24); +		} +		for (; i < 4 && cnt > 0; ++i) { +			data = (data >> 8) | (*src++ << 24); +			--cnt; +			++cp; +		} +		for (; cnt == 0 && i < 4; ++i, ++cp) { +			data = (data >> 8) | (*(uchar *) cp << 24); +		} + +		if ((rc = write_word (info, wp, data)) != 0) { +			return (rc); +		} +		wp += 4; +	} + +	/* +	 * handle word aligned part +	 */ +	while (cnt >= 4) { +		data = *((vu_long *) src); +		if ((rc = write_word (info, wp, data)) != 0) { +			return (rc); +		} +		src += 4; +		wp += 4; +		cnt -= 4; +	} + +	if (cnt == 0) { +		return ERR_OK; +	} + +	/* +	 * handle unaligned tail bytes +	 */ +	data = 0; +	for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) { +		data = (data >> 8) | (*src++ << 24); +		--cnt; +	} +	for (; i < 4; ++i, ++cp) { +		data = (data >> 8) | (*(uchar *) cp << 24); +	} + +	return write_word (info, wp, data); +} diff --git a/board/lpd7a40x/lpd7a40x.c b/board/lpd7a40x/lpd7a40x.c new file mode 100644 index 000000000..8492df3d2 --- /dev/null +++ b/board/lpd7a40x/lpd7a40x.c @@ -0,0 +1,82 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (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 + */ + +#include <common.h> +#if defined(CONFIG_LH7A400) +#include <lh7a400.h> +#include <lpd7a400_cpld.h> +#elif defined(CONFIG_LH7A404) +#include <lh7a404.h> +#include <lpd7a404_cpld.h> +#else +#error "No CPU defined!" +#endif + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/* set up the I/O ports */ + +#if defined(CONFIG_LH7A400) + +	/* enable flash programming */ +	*(LPD7A400_CPLD_REGPTR(LPD7A400_CPLD_FLASH_REG)) |= FLASH_FPEN; + +	/* Auto wakeup, LCD disable, WLAN enable */ +	*(LPD7A400_CPLD_REGPTR(LPD7A400_CPLD_CECTL_REG)) &= +		~(CECTL_AWKP|CECTL_LCDV|CECTL_WLPE); + +	/* Status LED 2 on (leds are active low) */ +	*(LPD7A400_CPLD_REGPTR(LPD7A400_CPLD_EXTGPIO_REG)) = +		(EXTGPIO_STATUS1|EXTGPIO_GPIO1) & ~(EXTGPIO_STATUS2); + +	/* arch number of Logic-Board - MACH_TYPE_LPD7A400 */ +	gd->bd->bi_arch_number = MACH_TYPE_LPD7A400; + +#elif defined(CONFIG_LH7A404) +#endif + +	/* adress of boot parameters */ +	gd->bd->bi_boot_params = 0xc0000100; + +	return 0; +} + +int dram_init (void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	gd->bd->bi_dram[0].start = PHYS_SDRAM_1; +	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +	return 0; +} diff --git a/board/lpd7a40x/memsetup.S b/board/lpd7a40x/memsetup.S new file mode 100644 index 000000000..09ab5e74c --- /dev/null +++ b/board/lpd7a40x/memsetup.S @@ -0,0 +1,212 @@ +/* + * Memory Setup - initialize memory controller(s) for devices required + *                to boot and relocate + * + * 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> + + +/* memory controller */ +#define BCRX_DEFAULT	(0x0000fbe0) +#define BCRX_MW_8	(0x00000000) +#define BCRX_MW_16	(0x10000000) +#define BCRX_MW_32	(0x20000000) +#define BCRX_PME	(0x08000000) +#define BCRX_WP		(0x04000000) +#define BCRX_WST2_SHIFT	(11) +#define BCRX_WST1_SHIFT	(5) +#define BCRX_IDCY_SHIFT	(0) + +/* Bank0 Async Flash */ +#define BCR0	   	(0x80002000) +#define BCR0_FLASH	(BCRX_MW_32 | (0x08<<BCRX_WST2_SHIFT) | (0x0E<<BCRX_WST1_SHIFT)) + +/* Bank1 Open */ +#define BCR1	(0x80002004) + +/* Bank2 Not used (EEPROM?) */ +#define BCR2	(0x80002008) + +/* Bank3 Not used */ +#define BCR3	(0x8000200C) + +/* Bank4 PC Card1 */ + +/* Bank5 PC Card2 */ + +/* Bank6 CPLD IO Controller Peripherals (slow) */ +#define BCR6	 	(0x80002018) +#define BCR6_CPLD_SLOW	(BCRX_DEFAULT | BCRX_MW_16) + +/* Bank7 CPLD IO Controller Peripherals (fast) */ +#define BCR7		(0x8000201C) +#define BCR7_CPLD_FAST	(BCRX_MW_16 | (0x16<<BCRX_WST2_SHIFT) | (0x16<<BCRX_WST1_SHIFT) | (0x2<<BCRX_IDCY_SHIFT)) + +/* SDRAM */ +#define GBLCNFG		(0x80002404) +#define GC_CKE		(0x80000000) +#define GC_CKSD		(0x40000000) +#define GC_LCR		(0x00000040) +#define GC_SMEMBURST	(0x00000020) +#define GC_MRS		(0x00000002) +#define GC_INIT		(0x00000001) + +#define GC_CMD_NORMAL		(GC_CKE) +#define GC_CMD_MODE		(GC_CKE | GC_MRS) +#define GC_CMD_SYNCFLASH_LOAD	(GC_CKE | GC_MRS | GC_LCR) +#define GC_CMD_PRECHARGEALL	(GC_CKE | GC_INIT) +#define GC_CMD_NOP		(GC_CKE | GC_INIT | GC_MRS) + +#define RFSHTMR		(0x80002408) +#define RFSHTMR_INIT	(10)	/* period=100 ns, HCLK=100Mhz, (2048+1-15.6*66) */ +#define RFSHTMR_NORMAL	(1500)	/* period=15.6 us, HCLK=100Mhz, (2048+1-15.6*66) */ + +#define SDCSCX_BASE		(0x80002410) +#define SDCSCX_DEFAULT		(0x01220008) +#define SDCSCX_AUTOPC		(0x01000000) +#define SDCSCX_RAS2CAS_2	(0x00200000) +#define SDCSCX_RAS2CAS_3	(0x00300000) +#define SDCSCX_WBL		(0x00080000) +#define SDCSCX_CASLAT_8		(0x00070000) +#define SDCSCX_CASLAT_7		(0x00060000) +#define SDCSCX_CASLAT_6		(0x00050000) +#define SDCSCX_CASLAT_5		(0x00040000) +#define SDCSCX_CASLAT_4		(0x00030000) +#define SDCSCX_CASLAT_3		(0x00020000) +#define SDCSCX_CASLAT_2		(0x00010000) +#define SDCSCX_2KPAGE		(0x00000040) +#define SDCSCX_SROMLL		(0x00000020) +#define SDCSCX_SROM512		(0x00000010) +#define SDCSCX_4BNK		(0x00000008) +#define SDCSCX_2BNK		(0x00000000) +#define SDCSCX_EBW_16		(0x00000004) +#define SDCSCX_EBW_32		(0x00000000) + +#define SDRAM_BASE		(0xC0000000) +#define SDCSC_BANK_OFFSET	(0x10000000) + +/* + * The SDRAM DEVICE MODE PROGRAMMING VALUE + */ +#define BURST_LENGTH_4		(0x010 << 10) +#define BURST_LENGTH_8		(0x011 << 10) +#define WBURST_LENGTH_BL	(0x01 << 19) +#define WBURST_LENGTH_SINGLE	(0x01 << 19) +#define CAS_2			(0x010 << 14) +#define CAS_3			(0x011 << 14) +#define BAT_SEQUENTIAL		(0 << 13) +#define BAT_INTERLEAVED		(1 << 13) +#define OPM_NORMAL		(0x00 << 17) +#define SDRAM_DEVICE_MODE	(WBURST_LENGTH_BL|OPM_NORMAL|CAS_3|BAT_SEQUENTIAL|BURST_LENGTH_4) + + +#define TIMER1_BASE	(0x80000C00) + +/* + * special lookup flags + */ +#define DO_MEM_DELAY	1 +#define DO_MEM_READ	2 + +_TEXT_BASE: +	.word	TEXT_BASE + +.globl memsetup +memsetup: +	mov	r9, lr	@ save return address + +	/* memory control configuration */ +	/* make r0 relative the current location so that it */ +	/* reads INITMEM_DATA out of FLASH rather than memory ! */ +	/*   r0 = current word pointer */ +	/*   r1 = end word location, one word past last actual word */ +	/*   r3 = address for writes, special lookup flags */ +	/*   r4 = value for writes, delay constants, or read addresses */ +	/*   r2 = location for mem reads */ + +	ldr	r0, =INITMEM_DATA +	ldr	r1, _TEXT_BASE +	sub	r0, r0, r1 +	add	r1, r0, #112 + +mem_loop: +	cmp	r1, r0 +	moveq	pc, r9		@ Done + +	ldr	r3, [r0], #4	@ Fetch Destination Register Address, or 1 for delay +	ldr	r4, [r0], #4	@ value + +	cmp	r3, #DO_MEM_DELAY +	bleq	mem_delay +	beq	mem_loop +	cmp	r3, #DO_MEM_READ +	ldreq	r2, [r4] +	beq	mem_loop +	str	r4, [r3]	@ normal register/ram store +	b	mem_loop + +mem_delay: +	ldr	r5, =TIMER1_BASE +	mov	r6, r4, LSR #1	@ timer resolution is ~2us +	str	r6, [r5] +	mov	r6, #0x88	@ using 508.469KHz clock, enable +	str	r6, [r5, #8] +0:	ldr	r6, [r5, #4]	@ timer value +	cmp	r6, #0 +	bne	0b +	mov	r6, #0		@ disable timer +	str	r6, [r5, #8] +	mov	pc, lr + +	.ltorg +/* the literal pools origin */ + +INITMEM_DATA: +	.word	BCR0 +	.word	BCR0_FLASH +	.word	BCR6 +	.word	BCR6_CPLD_SLOW +	.word	BCR7 +	.word	BCR7_CPLD_FAST +	.word	SDCSCX_BASE +	.word	(SDCSCX_RAS2CAS_3 | SDCSCX_CASLAT_3 | SDCSCX_SROMLL | SDCSCX_4BNK | SDCSCX_EBW_32) +	.word	GBLCNFG +	.word	GC_CMD_NOP +	.word	DO_MEM_DELAY +	.word	200 +	.word	GBLCNFG +	.word	GC_CMD_PRECHARGEALL +	.word	RFSHTMR +	.word	RFSHTMR_INIT +	.word	DO_MEM_DELAY +	.word	8 +	.word	RFSHTMR +	.word	RFSHTMR_NORMAL +	.word	GBLCNFG +	.word	GC_CMD_MODE +	.word	DO_MEM_READ +	.word	(SDRAM_BASE | SDRAM_DEVICE_MODE) +	.word	GBLCNFG +	.word	GC_CMD_NORMAL +	.word	SDCSCX_BASE +	.word	(SDCSCX_AUTOPC | SDCSCX_RAS2CAS_3 | SDCSCX_CASLAT_3 | SDCSCX_SROMLL | SDCSCX_4BNK | SDCSCX_EBW_32) diff --git a/board/lpd7a40x/u-boot.lds b/board/lpd7a40x/u-boot.lds new file mode 100644 index 000000000..719d8b19f --- /dev/null +++ b/board/lpd7a40x/u-boot.lds @@ -0,0 +1,56 @@ +/* + * (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/lh7a40x/start.o	(.text) +	  *(.text) +	} + +	. = ALIGN(4); +	.rodata : { *(.rodata) } + +	. = ALIGN(4); +	.data : { *(.data) } + +	. = ALIGN(4); +	.got : { *(.got) } + +	__u_boot_cmd_start = .; +	.u_boot_cmd : { *(.u_boot_cmd) } +	__u_boot_cmd_end = .; + +	. = ALIGN(4); +	__bss_start = .; +	.bss : { *(.bss) } +	_end = .; +} diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 085781f74..207c211e8 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -126,7 +126,13 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])      int jffs2_1pass_load(char *, struct part_info *,const char *);      char *fsname; -	char *filename = "uImage"; +	char *filename; + +	/* pre-set Boot file name */ +	if ((filename = getenv("bootfile")) == NULL) { +		filename = "uImage"; +	} +  	ulong offset = load_addr;  	int size;  	struct part_info *part; diff --git a/cpu/lh7a40x/Makefile b/cpu/lh7a40x/Makefile new file mode 100644 index 000000000..b45bd6a29 --- /dev/null +++ b/cpu/lh7a40x/Makefile @@ -0,0 +1,43 @@ +# +# (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 $(TOPDIR)/config.mk + +LIB	= lib$(CPU).a + +START	= start.o +OBJS	= cpu.o speed.o interrupts.o serial.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/lh7a40x/config.mk b/cpu/lh7a40x/config.mk new file mode 100644 index 000000000..cef7d26f1 --- /dev/null +++ b/cpu/lh7a40x/config.mk @@ -0,0 +1,27 @@ +# +# (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 +# + +PLATFORM_RELFLAGS += -fno-strict-aliasing  -fno-common -ffixed-r8 \ +	-mshort-load-bytes -msoft-float + +PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4 diff --git a/cpu/lh7a40x/cpu.c b/cpu/lh7a40x/cpu.c new file mode 100644 index 000000000..2a2b57801 --- /dev/null +++ b/cpu/lh7a40x/cpu.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (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 + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <arm920t.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"); + +#ifdef MMU_DEBUG +	printf ("p15/c1 is = %08lx\n", value); +#endif +	return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1 (unsigned long value) +{ +#ifdef MMU_DEBUG +	printf ("write %08lx to p15/c1\n", value); +#endif +	__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_DC		(1<<2)		/* dcache 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_IC		(1<<12)		/* icache off/on */ +#define C1_HIGH_VECTORS	(1<<13)	/* location of vectors: low/high addresses */ +#define RESERVED_1	(0xf << 3)	/* must be 111b for R/W */ + +int cpu_init (void) +{ +	/* +	 * setup up stacks if necessary +	 */ +#ifdef CONFIG_USE_IRQ +	DECLARE_GLOBAL_DATA_PTR; + +	IRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4; +	FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; +#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 ... +	 */ + +	unsigned long i; + +	disable_interrupts (); + +	/* turn off I/D-cache */ +	asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i)); +	i &= ~(C1_DC | C1_IC); +	asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i)); + +	/* flush I/D-cache */ +	i = 0; +	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); +	return (0); +} + +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	extern void reset_cpu (ulong addr); + +	disable_interrupts (); +	reset_cpu (0); +	/*NOTREACHED*/ +	return (0); +} + +void icache_enable (void) +{ +	ulong reg; + +	reg = read_p15_c1 (); +	cp_delay (); +	write_p15_c1 (reg | C1_IC); +} + +void icache_disable (void) +{ +	ulong reg; + +	reg = read_p15_c1 (); +	cp_delay (); +	write_p15_c1 (reg & ~C1_IC); +} + +int icache_status (void) +{ +	return (read_p15_c1 () & C1_IC) != 0; +} + +#ifdef USE_920T_MMU +/* It makes no sense to use the dcache if the MMU is not enabled */ +void dcache_enable (void) +{ +	ulong reg; + +	reg = read_p15_c1 (); +	cp_delay (); +	write_p15_c1 (reg | C1_DC); +} + +void dcache_disable (void) +{ +	ulong reg; + +	reg = read_p15_c1 (); +	cp_delay (); +	reg &= ~C1_DC; +	write_p15_c1 (reg); +} + +int dcache_status (void) +{ +	return (read_p15_c1 () & C1_DC) != 0; +} +#endif diff --git a/cpu/lh7a40x/interrupts.c b/cpu/lh7a40x/interrupts.c new file mode 100644 index 000000000..2ebbe5635 --- /dev/null +++ b/cpu/lh7a40x/interrupts.c @@ -0,0 +1,326 @@ +/* + * (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> + * + * (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 + */ + +#include <common.h> +#include <arm920t.h> +#include <lh7a40x.h> + +#include <asm/proc-armv/ptrace.h> + +extern void reset_cpu(ulong addr); +static ulong timer_load_val = 0; + +/* macro to read the 16 bit timer */ +static inline ulong READ_TIMER(void) +{ +	LH7A40X_TIMERS_PTR(timers); +	lh7a40x_timer_t* timer = &timers->timer1; + +	return (timer->value & 0x0000ffff); +} + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts (void) +{ +	unsigned long temp; +	__asm__ __volatile__("mrs %0, cpsr\n" +			     "bic %0, %0, #0x80\n" +			     "msr cpsr_c, %0" +			     : "=r" (temp) +			     : +			     : "memory"); +} + + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts (void) +{ +	unsigned long old,temp; +	__asm__ __volatile__("mrs %0, cpsr\n" +			     "orr %1, %0, #0xc0\n" +			     "msr cpsr_c, %1" +			     : "=r" (old), "=r" (temp) +			     : +			     : "memory"); +	return (old & 0x80) == 0; +} +#else +void enable_interrupts (void) +{ +	return; +} +int disable_interrupts (void) +{ +	return 0; +} +#endif + + +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 lastdec; + +int interrupt_init (void) +{ +	LH7A40X_TIMERS_PTR(timers); +	lh7a40x_timer_t* timer = &timers->timer1; + +	/* a periodic timer using the 508kHz source */ +	timer->control = (TIMER_PER | TIMER_CLK508K); + +	if (timer_load_val == 0) { +		/* +		 * 10ms period with 508.469kHz clock = 5084 +		 */ +		timer_load_val = CFG_HZ/100; +	} + +	/* load value for 10 ms timeout */ +	lastdec = timer->load = timer_load_val; + +	/* auto load, start timer */ +	timer->control = timer->control | TIMER_EN; +	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) +{ +	ulong tmo,tmp; + +	/* normalize */ +	if (usec >= 1000) { +		tmo = usec / 1000; +		tmo *= CFG_HZ; +		tmo /= 1000; +	} +	else { +		if (usec > 1) { +			tmo = usec * CFG_HZ; +			tmo /= (1000*1000); +		} +		else +			tmo = 1; +	} + +	/* check for rollover during this delay */ +	tmp = get_timer (0); +	if ((tmp + tmo) < tmp ) +		reset_timer_masked();  /* timer would roll over */ +	else +		tmo += tmp; + +	while (get_timer_masked () < tmo); +} + +void reset_timer_masked (void) +{ +	/* reset time */ +	lastdec = READ_TIMER(); +	timestamp = 0; +} + +ulong get_timer_masked (void) +{ +	ulong now = READ_TIMER(); + +	if (lastdec >= now) { +		/* normal mode */ +		timestamp += (lastdec - now); +	} else { +		/* we have an overflow ... */ +		timestamp += ((lastdec + timer_load_val) - now); +	} +	lastdec = now; + +	return timestamp; +} + +void udelay_masked (unsigned long usec) +{ +	ulong tmo; + +	/* normalize */ +	if (usec >= 1000) { +		tmo = usec / 1000; +		tmo *= CFG_HZ; +		tmo /= 1000; +	} +	else { +		if (usec > 1) { +			tmo = usec * CFG_HZ; +			tmo /= (1000*1000); +		} +		else +			tmo = 1; +	} + +	reset_timer_masked (); + +	while (get_timer_masked () < tmo); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ +	return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ +	ulong tbclk; + +	tbclk = timer_load_val * 100; + +	return tbclk; +} diff --git a/cpu/lh7a40x/serial.c b/cpu/lh7a40x/serial.c new file mode 100644 index 000000000..241d568ea --- /dev/null +++ b/cpu/lh7a40x/serial.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * 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 <lh7a40x.h> + +#if defined(CONFIG_CONSOLE_UART1) +# define UART_CONSOLE 1 +#elif defined(CONFIG_CONSOLE_UART2) +# define UART_CONSOLE 2 +#elif defined(CONFIG_CONSOLE_UART3) +# define UART_CONSOLE 3 +#else +# error "No console configured ... " +#endif + +void serial_setbrg (void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	LH7A40X_UART_PTR(uart,UART_CONSOLE); +	int i; +	unsigned int reg = 0; + +	/* +	 * userguide 15.1.2.4 +	 * +	 * BAUDDIV is (UART_REF_FREQ/(16 X BAUD))-1 +	 * +	 *   UART_REF_FREQ = external system clock input / 2 (Hz) +	 *   BAUD is desired baudrate (bits/s) +	 * +	 *   NOTE: we add (divisor/2) to numerator to round for +	 *         more precision +	 */ +	reg = (((get_PLLCLK()/2) + ((16*gd->baudrate)/2)) / (16 * gd->baudrate)) - 1; +	uart->brcon = reg; + +	for (i = 0; i < 100; i++); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ +	LH7A40X_UART_PTR(uart,UART_CONSOLE); + +	/* UART must be enabled before writing to any config registers */ +	uart->con |= (UART_EN); + +#ifdef CONFIG_CONSOLE_UART1 +	/* infrared disabled */ +	uart->con |= UART_SIRD; +#endif +	/* loopback disabled */ +	uart->con &= ~(UART_LBE); + +	/* modem lines and tx/rx polarities */ +	uart->con &= ~(UART_MXP | UART_TXP | UART_RXP); + +	/* FIFO enable, N81 */ +	uart->fcon = (UART_WLEN_8 | UART_FEN | UART_STP2_1); + +	/* set baudrate */ +	serial_setbrg (); + +	/* enable rx interrupt */ +	uart->inten |= UART_RI; + +	return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ +	LH7A40X_UART_PTR(uart,UART_CONSOLE); + +	/* wait for character to arrive */ +	while (uart->status & UART_RXFE); + +	return(uart->data & 0xff); +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ +	switch(on) { +	case 0: +	default: +		break; /* return current */ +	case 1: +		hwflow = 1; /* turn on */ +		break; +	case -1: +		hwflow = 0; /* turn off */ +		break; +	} +	return hwflow; +} +#endif + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet = 0; +void disable_putc(void) +{ +	be_quiet = 1; +} + +void enable_putc(void) +{ +	be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ +	LH7A40X_UART_PTR(uart,UART_CONSOLE); + +#ifdef CONFIG_MODEM_SUPPORT +	if (be_quiet) +		return; +#endif + +	/* wait for room in the tx FIFO */ +	while (!(uart->status & UART_TXFE)); + +#ifdef CONFIG_HWFLOW +	/* Wait for CTS up */ +	while(hwflow && !(uart->status & UART_CTS)); +#endif + +	uart->data = c; + +	/* If \n, also do \r */ +	if (c == '\n') +		serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ +	LH7A40X_UART_PTR(uart,UART_CONSOLE); + +	return(!(uart->status & UART_RXFE)); +} + +void +serial_puts (const char *s) +{ +	while (*s) { +		serial_putc (*s++); +	} +} diff --git a/cpu/lh7a40x/speed.c b/cpu/lh7a40x/speed.c new file mode 100644 index 000000000..e80b046d3 --- /dev/null +++ b/cpu/lh7a40x/speed.c @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2001-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * 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 <lh7a40x.h> + + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +ulong get_PLLCLK (void) +{ +	return CONFIG_SYS_CLK_FREQ; +} + +/* return FCLK frequency */ +ulong get_FCLK (void) +{ +	LH7A40X_CSC_PTR (csc); +	ulong maindiv1, maindiv2, prediv, ps; + +	/* +	 * from userguide 6.1.1.2 +	 * +	 * FCLK = ((MAINDIV1 +2) * (MAINDIV2 +2) * 14.7456MHz) / +	 *                   ((PREDIV+2) * (2^PS)) +	 */ +	maindiv2 = (csc->clkset & CLKSET_MAINDIV2) >> 11; +	maindiv1 = (csc->clkset & CLKSET_MAINDIV1) >> 7; +	prediv = (csc->clkset & CLKSET_PREDIV) >> 2; +	ps = (csc->clkset & CLKSET_PS) >> 16; + +	return (((maindiv2 + 2) * (maindiv1 + 2) * CONFIG_SYS_CLK_FREQ) / +		((prediv + 2) * (1 << ps))); +} + + +/* return HCLK frequency */ +ulong get_HCLK (void) +{ +	LH7A40X_CSC_PTR (csc); + +	return (get_FCLK () / ((csc->clkset & CLKSET_HCLKDIV) + 1)); +} + +/* return PCLK frequency */ +ulong get_PCLK (void) +{ +	LH7A40X_CSC_PTR (csc); + +	return (get_HCLK () / +		(1 << (((csc->clkset & CLKSET_PCLKDIV) >> 16) + 1))); +} diff --git a/cpu/lh7a40x/start.S b/cpu/lh7a40x/start.S new file mode 100644 index 000000000..160f889df --- /dev/null +++ b/cpu/lh7a40x/start.S @@ -0,0 +1,426 @@ +/* + *  armboot - Startup Code for ARM920 CPU-core + * + *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de> + *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de> + *  Copyright (c) 2002	Gary Jennejohn <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 + */ + + +#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 + * + ************************************************************************* + */ + +_TEXT_BASE: +	.word	TEXT_BASE + +.globl _armboot_start +_armboot_start: +	.word _start + +/* + * These are defined in the board-specific linker script. + */ +.globl _bss_start +_bss_start: +	.word __bss_start + +.globl _bss_end +_bss_end: +	.word _end + +#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,#0xd3 +	msr	cpsr,r0 + +#define pWDTCTL		0x80001400  /* Watchdog Timer control register */ +#define pINTENC		0x8000050C  /* Interupt-Controller enable clear register */ +#define pCLKSET		0x80000420  /* clock divisor register */ + +	/* disable watchdog, set watchdog control register to +	 * all zeros (default reset) +	 */ +	ldr     r0, =pWDTCTL +	mov     r1, #0x0 +	str     r1, [r0] + +	/* +	 * mask all IRQs by setting all bits in the INTENC register (default) +	 */ +	mov	r1, #0xffffffff +	ldr	r0, =pINTENC +	str	r1, [r0] + +	/* FCLK:HCLK:PCLK = 1:2:2 */ +	/* default FCLK is 200 MHz, using 14.7456 MHz fin */ +	ldr	r0, =pCLKSET +	ldr r1, =0x0004ee39 +@	ldr r1, =0x0005ee39	@ 1: 2: 4 +	str	r1, [r0] + +	/* +	 * we do sys-critical inits only at reboot, +	 * not when booting from ram! +	 */ +#ifdef CONFIG_INIT_CRITICAL +	bl	cpu_init_crit +#endif + +relocate:				/* relocate U-Boot to RAM	    */ +	adr	r0, _start		/* r0 <- current position of code   */ +	ldr	r1, _TEXT_BASE		/* test if we run from flash or RAM */ +	cmp     r0, r1                  /* don't reloc during debug         */ +	beq     stack_setup + +	ldr	r2, _armboot_start +	ldr	r3, _bss_start +	sub	r2, r3, r2		/* r2 <- size of armboot            */ +	add	r2, r0, r2		/* r2 <- source end address         */ + +copy_loop: +	ldmia	r0!, {r3-r10}		/* copy from source address [r0]    */ +	stmia	r1!, {r3-r10}		/* copy to   target address [r1]    */ +	cmp	r0, r2			/* until source end addreee [r2]    */ +	blt	copy_loop		/* a 'ble' here actually copies     */ +					/*   four bytes of bss              */ + +	/* Set up the stack						    */ +stack_setup: +	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */ +	sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */ +	sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */ +#ifdef CONFIG_USE_IRQ +	sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) +#endif +	sub	sp, r0, #12		/* leave 3 words for abort-stack    */ + +clear_bss: +	ldr	r0, _bss_start		/* find start of bss segment        */ +	@add	r0, r0, #4		/* start at first byte of bss       */ +					/*   why inc. 4 bytes past then?    */ +	ldr	r1, _bss_end		/* stop here                        */ +	mov 	r2, #0x00000000		/* clear                            */ + +clbss_l:str	r2, [r0]		/* clear loop...                    */ +	add	r0, r0, #4 +	cmp	r0, r1 +	bne	clbss_l + +	ldr	pc, _start_armboot + +_start_armboot:	.word start_armboot + + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ + + +cpu_init_crit: +	/* +	 * flush v4 I/D caches +	 */ +	mov	r0, #0 +	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */ +	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */ + +	/* +	 * disable MMU stuff and caches +	 */ +	mrc	p15, 0, r0, c1, c0, 0 +	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS) +	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM) +	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align +	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache +	orr	r0, r0, #0x40000000	@ set bit 30 (nF) notFastBus +	mcr	p15, 0, r0, c1, c0, 0 + + +	/* +	 * before relocating, we have to setup RAM timing +	 * because memory timing is board-dependend, you will +	 * find a memsetup.S in your board directory. +	 */ +	mov	ip, lr +	bl	memsetup +	mov	lr, ip + +	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 +	ldr	r2, _armboot_start +	sub	r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +	sub	r2, r2, #(CFG_GBL_DATA_SIZE+8)  @ set base 2 words into abort stack +	ldmia	r2, {r2 - r3}			@ get pc, cpsr +	add	r0, sp, #S_FRAME_SIZE		@ restore sp_SVC + +	add	r5, sp, #S_SP +	mov	r1, lr +	stmia	r5, {r0 - r3}			@ save sp_SVC, lr_SVC, pc, cpsr +	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_start		@ setup our mode stack +	sub	r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN) +	sub	r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack + +	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 +	msr	spsr, 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: +	bl	disable_interrupts + +	/* Disable watchdog */ +	ldr	r1, =pWDTCTL +	mov	r3, #0 +	str	r3, [r1] + +	/* reset counter */ +	ldr	r3, =0x00001984 +	str	r3, [r1, #4] + +	/* Enable the watchdog */ +	mov	r3, #1 +	str	r3, [r1] + +_loop_forever: +	b	_loop_forever diff --git a/cpu/pxa/interrupts.c b/cpu/pxa/interrupts.c index b161b7468..8aec0b9dd 100644 --- a/cpu/pxa/interrupts.c +++ b/cpu/pxa/interrupts.c @@ -165,7 +165,7 @@ void reset_timer (void)  ulong get_timer (ulong base)  { -	return get_timer_masked (); +	return get_timer_masked () - base;  }  void set_timer (ulong t) diff --git a/doc/README.JFFS2 b/doc/README.JFFS2 index f85498455..270da9082 100644 --- a/doc/README.JFFS2 +++ b/doc/README.JFFS2 @@ -8,6 +8,7 @@ The module adds three new commands.  fsload  - load binary file from a file system image  fsinfo  - print information about file systems  ls      - list files in a directory +chpart  - change active partition  If you boot from a partition which is mounted writable, and you  update your boot environment by replacing single files on that @@ -68,9 +69,6 @@ jffs2_part_info(int part_num)  TODO. -	Add a new command so it's actually possible to change -	partition. -  	Remove the assumption that JFFS can dereference a pointer  	into the disk. The current code do not work with memory holes  	or hardware with a sliding window (PCMCIA). diff --git a/drivers/smc91111.c b/drivers/smc91111.c index 9f9f364f1..8b1103bb6 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -61,6 +61,7 @@  #include <common.h>  #include <command.h> +#include <config.h>  #include "smc91111.h"  #include <net.h> @@ -78,6 +79,11 @@ static const char version[] =  	"smc91111.c:v1.0 04/25/01 by Daris A Nevil (dnevil@snmc.com)\n";  #endif +/* Autonegotiation timeout in seconds */ +#ifndef CONFIG_SMC_AUTONEG_TIMEOUT +#define CONFIG_SMC_AUTONEG_TIMEOUT 10 +#endif +  /*------------------------------------------------------------------------   .   . Configuration options, for the experienced user to change. @@ -353,7 +359,7 @@ static inline void smc_wait_mmu_release_complete (void)  */  static void smc_reset (void)  { -	PRINTK2 ("%s:smc_reset\n", SMC_DEV_NAME); +	PRINTK2 ("%s: smc_reset\n", SMC_DEV_NAME);  	/* This resets the registers mostly to defaults, but doesn't  	   affect EEPROM.  That seems unnecessary */ @@ -414,7 +420,7 @@ static void smc_reset (void)  */  static void smc_enable()  { -	PRINTK2("%s:smc_enable\n", SMC_DEV_NAME); +	PRINTK2("%s: smc_enable\n", SMC_DEV_NAME);  	SMC_SELECT_BANK( 0 );  	/* see the header file for options in TCR/RCR DEFAULT*/  	SMC_outw( TCR_DEFAULT, TCR_REG ); @@ -440,7 +446,7 @@ static void smc_enable()  */  static void smc_shutdown()  { -	PRINTK2(CARDNAME ":smc_shutdown\n"); +	PRINTK2(CARDNAME ": smc_shutdown\n");  	/* no more interrupts for me */  	SMC_SELECT_BANK( 2 ); @@ -489,7 +495,7 @@ static int smc_send_packet (volatile void *packet, int packet_length)  	saved_pnr = SMC_inb( PN_REG );  	saved_ptr = SMC_inw( PTR_REG ); -	PRINTK3 ("%s:smc_hardware_send_packet\n", SMC_DEV_NAME); +	PRINTK3 ("%s: smc_hardware_send_packet\n", SMC_DEV_NAME);  	length = ETH_ZLEN < packet_length ? packet_length : ETH_ZLEN; @@ -677,7 +683,7 @@ again:  */  void smc_destructor()  { -	PRINTK2(CARDNAME ":smc_destructor\n"); +	PRINTK2(CARDNAME ": smc_destructor\n");  } @@ -691,7 +697,7 @@ static int smc_open (bd_t * bd)  {  	int i, err; -	PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME); +	PRINTK2 ("%s: smc_open\n", SMC_DEV_NAME);  	/* reset the hardware */  	smc_reset (); @@ -764,7 +770,7 @@ static int smc_rcv()  		return 0;  	} -	PRINTK3("%s:smc_rcv\n", SMC_DEV_NAME); +	PRINTK3("%s: smc_rcv\n", SMC_DEV_NAME);  	/*  start reading from the start of the packet */  	SMC_outw( PTR_READ | PTR_RCV | PTR_AUTOINC, PTR_REG ); @@ -860,7 +866,7 @@ static int smc_rcv()   -----------------------------------------------------*/  static int smc_close()  { -	PRINTK2("%s:smc_close\n", SMC_DEV_NAME); +	PRINTK2("%s: smc_close\n", SMC_DEV_NAME);  	/* clear everything */  	smc_shutdown(); @@ -1222,7 +1228,7 @@ static void smc_phy_configure ()  	word status = 0;	/*;my status = 0 */  	int failed = 0; -	PRINTK3 ("%s:smc_program_phy()\n", SMC_DEV_NAME); +	PRINTK3 ("%s: smc_program_phy()\n", SMC_DEV_NAME);  	/* Get the detected phy address */ @@ -1286,8 +1292,8 @@ static void smc_phy_configure ()  	/* the link does not come up. */  	smc_read_phy_register(PHY_AD_REG); -	PRINTK2 ("%s:phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); -	PRINTK2 ("%s:phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps); +	PRINTK2 ("%s: phy caps=%x\n", SMC_DEV_NAME, my_phy_caps); +	PRINTK2 ("%s: phy advertised caps=%x\n", SMC_DEV_NAME, my_ad_caps);  	/* Restart auto-negotiation process in order to advertise my caps */  	smc_write_phy_register (PHY_CNTL_REG, @@ -1296,8 +1302,9 @@ static void smc_phy_configure ()  	/* Wait for the auto-negotiation to complete.  This may take from */  	/* 2 to 3 seconds. */  	/* Wait for the reset to complete, or time out */ -	timeout = 20;		/* Wait up to 10 seconds */ +	timeout = CONFIG_SMC_AUTONEG_TIMEOUT * 2;  	while (timeout--) { +  		status = smc_read_phy_register (PHY_STAT_REG);  		if (status & PHY_STAT_ANEG_ACK) {  			/* auto-negotiate complete */ @@ -1308,11 +1315,11 @@ static void smc_phy_configure ()  		/* Restart auto-negotiation if remote fault */  		if (status & PHY_STAT_REM_FLT) { -			printf ("%s:PHY remote fault detected\n", +			printf ("%s: PHY remote fault detected\n",  				SMC_DEV_NAME);  			/* Restart auto-negotiation */ -			printf ("%s:PHY restarting auto-negotiation\n", +			printf ("%s: PHY restarting auto-negotiation\n",  				SMC_DEV_NAME);  			smc_write_phy_register (PHY_CNTL_REG,  						PHY_CNTL_ANEG_EN | @@ -1323,15 +1330,13 @@ static void smc_phy_configure ()  	}  	if (timeout < 1) { -		printf ("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME); -		printf ("%s:PHY auto-negotiate timed out\n", SMC_DEV_NAME); +		printf ("%s: PHY auto-negotiate timed out\n", SMC_DEV_NAME);  		failed = 1;  	}  	/* Fail if we detected an auto-negotiate remote fault */  	if (status & PHY_STAT_REM_FLT) { -		printf ("%s:PHY remote fault detected\n", SMC_DEV_NAME); -		printf ("%s:PHY remote fault detected\n", SMC_DEV_NAME); +		printf ("%s: PHY remote fault detected\n", SMC_DEV_NAME);  		failed = 1;  	} @@ -1469,12 +1474,16 @@ int get_rom_mac (char *v_rom_mac)  	return (1);  #else  	int i; +	int valid_mac = 0; +  	SMC_SELECT_BANK (1);  	for (i=0; i<6; i++)  	{  		v_rom_mac[i] = SMC_inb (ADDR0_REG + i); +		valid_mac |= v_rom_mac[i];  	} -	return (1); + +	return (valid_mac ? 1 : 0);  #endif  }  #endif /* CONFIG_DRIVER_SMC91111 */ diff --git a/include/bmp_logo.h b/include/bmp_logo.h index 265f744d0..9c924b859 100644 --- a/include/bmp_logo.h +++ b/include/bmp_logo.h @@ -18,7 +18,7 @@ unsigned short bmp_logo_palette[] = {  	0x0343,  0x0454,  0x0565,  0x0565,  0x0676,  0x0787,  0x0898,  0x0999,  	0x0AAA,  0x0ABA,  0x0BCB,  0x0CCC,  0x0DDD,  0x0EEE,  0x0FFF,  0x0FB3,  	0x0FB4,  0x0FC4,  0x0FC5,  0x0FC6,  0x0FD7,  0x0FD8,  0x0FD9,  0x0FDA, -	0x0FEA,  0x0FEB,  0x0FEC,  0x0FFD,  0x0FFE,  0x0FFF,  0x0FFF,   +	0x0FEA,  0x0FEB,  0x0FEC,  0x0FFD,  0x0FFE,  0x0FFF,  0x0FFF,  };  unsigned char bmp_logo_bitmap[] = { diff --git a/include/common.h b/include/common.h index 8a81e435e..db1a114de 100644 --- a/include/common.h +++ b/include/common.h @@ -384,12 +384,15 @@ int	prt_mpc5xxx_clks (void);  ulong	get_OPB_freq (void);  ulong	get_PCI_freq (void);  #endif -#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) +#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X)  ulong	get_FCLK (void);  ulong	get_HCLK (void);  ulong	get_PCLK (void);  ulong	get_UCLK (void);  #endif +#if defined(CONFIG_LH7A40X) +ulong	get_PLLCLK (void); +#endif  #if defined CONFIG_INCA_IP  uint	incaip_get_cpuclk (void);  #endif diff --git a/include/configs/innokom.h b/include/configs/innokom.h index 77439e641..f88451922 100644 --- a/include/configs/innokom.h +++ b/include/configs/innokom.h @@ -140,6 +140,7 @@  #define CONFIG_SMC91111_BASE		0x14000000 /* chip select 5         */  #undef  CONFIG_SMC_USE_32_BIT		           /* 16 bit bus access     */  #undef  CONFIG_SMC_91111_EXT_PHY		   /* we use internal phy   */ +#define CONFIG_SMC_AUTONEG_TIMEOUT	10	   /* timeout 10 seconds    */  #undef  CONFIG_SHOW_ACTIVITY  #define CONFIG_NET_RETRY_COUNT		10	   /* # of retries          */ diff --git a/include/configs/lpd7a400-10.h b/include/configs/lpd7a400-10.h new file mode 100644 index 000000000..ecf2b5ff8 --- /dev/null +++ b/include/configs/lpd7a400-10.h @@ -0,0 +1,80 @@ +/* + * 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 + */ + +/* + * Logic LH7A400-10 card engine + */ + +#ifndef __LPD7A400_10_H +#define __LPD7A400_10_H + + +#define CONFIG_ARM920T		1	/* arm920t core */ +#define CONFIG_LH7A40X		1	/* Sharp LH7A400 SoC */ +#define CONFIG_LH7A400		1 + +/* The system clock PLL input frequency */ +#define CONFIG_SYS_CLK_FREQ		14745600   /* System Clock PLL Input (Hz) */ + +/* ticks per second */ +#define CFG_HZ	(508469) + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE	(128*1024)	/* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ	(4*1024)	/* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ	(4*1024)	/* FIQ stack */ +#endif + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS	1	   /* we have 1 bank of DRAM */ +#define PHYS_SDRAM_1		0xc0000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE	0x02000000 /* 32 MB */ + +#define CFG_FLASH_BASE		0x00000000 /* Flash Bank #1 */ + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS	1	/* max number of memory banks */ +#define CFG_MAX_FLASH_SECT	(64)	/* max number of sectors on one chip */ + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT	(5*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT	(5*CFG_HZ) /* Timeout for Flash Write */ + +/*---------------------------------------------------------------------- + * Using SMC91C111 LAN chip + * + * Default IO base of chip is 0x300, Card Engine has this address lines + * (LAN chip) tied to Vcc, so we just care about the chip select + */ +#define CONFIG_DRIVER_SMC91111 +#define CONFIG_SMC91111_BASE	(0x70000000) +#undef CONFIG_SMC_USE_32_BIT +#define CONFIG_SMC_USE_IOFUNCS + +#endif  /* __LPD7A400_10_H */ diff --git a/include/configs/lpd7a400.h b/include/configs/lpd7a400.h new file mode 100644 index 000000000..3e915364b --- /dev/null +++ b/include/configs/lpd7a400.h @@ -0,0 +1,114 @@ +/* + * 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 __LPD7A400_H_ +#define __LPD7A400_H_ + +/* + * If we are developing, we might want to start armboot from ram + * so we MUST NOT initialize critical regs like mem-timing ... + */ +#define CONFIG_INIT_CRITICAL	/* undef for developing */ + +#undef CONFIG_USE_IRQ + +#define MACH_TYPE_LPD7A400	389 + +/* + * This board uses the logic LH7A400-10 card engine + */ +#include <configs/lpd7a400-10.h> + +#define CONFIG_LPD7A400		/* Logic LH7A400 SDK */ + +#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 CFG_GBL_DATA_SIZE	128	/* size in bytes reserved for initial data */ + +/* + * select serial console configuration + */ +#define CONFIG_CONSOLE_UART2	/* UART2 LH7A40x for console */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE		115200 +#define CONFIG_IPADDR		192.168.1.100 +#define CONFIG_NETMASK		255.255.1.0 +#define CONFIG_SERVERIP		192.168.1.1 + +#define	CONFIG_TIMESTAMP	1	/* Print timestamp info for images */ + +#ifndef USE_920T_MMU +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL | CFG_CMD_PING) & ~(CFG_CMD_CACHE)) +#else +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_DATE) +#endif + + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CONFIG_BOOTDELAY	3 + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE	115200		/* speed to run kgdb serial port */ +/* what's this ? it's not used anywhere */ +#define CONFIG_KGDB_SER_INDEX	1		/* which serial port to use */ +#endif + +/* + * Miscellaneous configurable options + */ +#define	CFG_LONGHELP				/* undef to save memory		*/ +#define	CFG_PROMPT		"LPD7A400> "	/* Monitor Command Prompt	*/ +#define	CFG_CBSIZE		256		/* Console I/O Buffer Size	*/ +#define	CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define	CFG_MAXARGS		16		/* max number of command args	*/ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/ + +#define CFG_MEMTEST_START	0xc0300000	/* memtest works on	*/ +#define CFG_MEMTEST_END		0xc0500000	/* 2 MB in DRAM	*/ + +#undef  CFG_CLKS_IN_HZ		/* everything, incl board info, in Hz */ + +#define	CFG_LOAD_ADDR		0xc0f00000	/* default load address	*/ + +/* valid baudrates */ +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } + +/* size and location of u-boot in flash */ +#define CFG_MONITOR_BASE	CFG_FLASH_BASE +#define CFG_MONITOR_LEN		(256<<10) + +#define	CFG_ENV_IS_IN_FLASH	1 + +/* Address and size of Primary Environment Sector	*/ +#define CFG_ENV_ADDR		(CFG_FLASH_BASE + 0xFC0000) +#define CFG_ENV_SIZE		0x40000 + +#endif  /* __LPD7A400_H_ */ diff --git a/include/lh7a400.h b/include/lh7a400.h new file mode 100644 index 000000000..e43667dc9 --- /dev/null +++ b/include/lh7a400.h @@ -0,0 +1,93 @@ +/* + * 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 + */ + +/* + * lh7a400 SoC interface + */ + +#ifndef __LH7A400_H__ +#define __LH7A400_H__ + +#include "lh7a40x.h" + +/* Interrupt Controller (userguide 8.2.1) */ +typedef struct { +	volatile u32  intsr; +	volatile u32  intrsr; +	volatile u32  intens; +	volatile u32  intenc; +	volatile u32  rsvd1; +	volatile u32  rsvd2; +	volatile u32  rsvd3; +} /*__attribute__((__packed__))*/ lh7a400_interrupt_t; +#define LH7A400_INTERRUPT_BASE    (0x80000500) +#define LH7A400_INTERRUPT_PTR(name)  lh7a400_interrupt_t* name = (lh7a400_interrupt_t*) LH7A400_INTERRUPT_BASE + +/* (DMA) Direct Memory Access Controller (userguide 9.2.1) */ +typedef struct { +	volatile u32  maxcnt; +	volatile u32  base; +	volatile u32  current; +	volatile u32  rsvd1; +} lh7a400_dmabuf_t; + +typedef struct { +	volatile u32      control; +	volatile u32      interrupt; +	volatile u32      rsvd1; +	volatile u32      status; +	volatile u32      rsvd2; +	volatile u32      remain; +	volatile u32      rsvd3; +	volatile u32      rsvd4; +	lh7a400_dmabuf_t  buf[2]; +} /*__attribute__((__packed__))*/ lh7a400_dmachan_t; + +typedef struct { +	lh7a400_dmachan_t  chan[15]; +	volatile u32       glblint; +	volatile u32       rsvd1; +	volatile u32       rsvd2; +	volatile u32       rsvd3; +} /*__attribute__((__packed__))*/ lh7a400_dma_t; +#define LH7A400_DMA_BASE      (0x80002800) +#define DMA_USBTX_OFFSET      (0x000) +#define DMA_USBRX_OFFSET      (0x040) +#define DMA_MMCTX_OFFSET      (0x080) +#define DMA_MMCRX_OFFSET      (0x0C0) +#define DMA_AC97_BASE         (0x80002A00) + +#define LH7A400_DMA_PTR(name)    lh7a400_dma_t* name = (lh7a400_dma_t*) LH7A400_DMA_BASE +#define LH7A400_DMA_USBTX(name) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_DMA_BASE + DMA_USBTX_OFFSET) +#define LH7A400_DMA_USBRX(name) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_DMA_BASE + DMA_USBRX_OFFSET) +#define LH7A400_DMA_MMCTX(name) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_DMA_BASE + DMA_MMCTX_OFFSET) +#define LH7A400_DMA_MMCRX(name) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_DMA_BASE + DMA_MMCRX_OFFSET) +#define LH7A400_AC97RX(name,n) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_AC97_BASE + \ +	((2*n) * sizeof(lh7a400_dmachan_t))) +#define LH7A400_AC97TX(name,n) \ +	lh7a400_dmachan_t* name = (lh7a400_dmachan_t*) (LH7A400_AC97_BASE + \ +	(((2*n)+1) * sizeof(lh7a400_dmachan_t))) + +#endif  /* __LH7A400_H__ */ diff --git a/include/lh7a40x.h b/include/lh7a40x.h new file mode 100644 index 000000000..081009c32 --- /dev/null +++ b/include/lh7a40x.h @@ -0,0 +1,258 @@ +/* + * 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 + */ + +/* + * lh7a40x SoC series common interface + */ + +#ifndef __LH7A40X_H__ +#define __LH7A40X_H__ + +/* (SMC) Static Memory Controller (usersguide 4.2.1) */ +typedef struct { +	volatile u32  attib; +	volatile u32  com; +	volatile u32  io; +	volatile u32  rsvd1; +} /*__attribute__((__packed__))*/ lh7a40x_pccard_t; + +typedef struct { +	volatile u32      bcr[8]; +	lh7a40x_pccard_t  pccard[2]; +	volatile u32	  pcmciacon; +} /*__attribute__((__packed__))*/ lh7a40x_smc_t; +#define LH7A40X_SMC_BASE    (0x80002000) +#define LH7A40X_SMC_PTR(name)  lh7a40x_smc_t* name = (lh7a40x_smc_t*) LH7A40X_SMC_BASE + +/* (SDMC) Synchronous Dynamic Ram Controller (usersguide 5.3.1) */ +typedef struct { +	volatile u32  rsvd1; +	volatile u32  gblcnfg; +	volatile u32  rfshtmr; +	volatile u32  bootstat; +	volatile u32  sdcsc[4]; +} /*__attribute__((__packed__))*/ lh7a40x_sdmc_t; +#define LH7A40X_SDMC_BASE    (0x80002400) +#define LH7A40X_SDMC_PTR(name)  lh7a40x_sdmc_t* name = (lh7a40x_sdmc_t*) LH7A40X_SDMC_BASE + +/* (CSC) Clock and State Controller (userguide 6.2.1) */ +typedef struct { +	volatile u32  pwrsr; +	volatile u32  pwrcnt; +	volatile u32  halt; +	volatile u32  stby; +	volatile u32  bleoi; +	volatile u32  mceoi; +	volatile u32  teoi; +	volatile u32  stfclr; +	volatile u32  clkset; +	volatile u32  scrreg[2]; +	volatile u32  rsvd1; +	volatile u32  usbreset; +} /*__attribute__((__packed__))*/ lh7a40x_csc_t; +#define LH7A40X_STPWR_BASE  (0x80000400) +#define LH7A40X_CSC_PTR(name)  lh7a40x_csc_t* name = (lh7a40x_csc_t*) LH7A40X_STPWR_BASE + +#define CLKSET_SMCROM		(0x01000000) +#define CLKSET_PS		(0x000C0000) +#define CLKSET_PS_0		(0x00000000) +#define CLKSET_PS_1		(0x00040000) +#define CLKSET_PS_2		(0x00080000) +#define CLKSET_PS_3		(0x000C0000) +#define CLKSET_PCLKDIV		(0x00030000) +#define CLKSET_PCLKDIV_2	(0x00000000) +#define CLKSET_PCLKDIV_4	(0x00010000) +#define CLKSET_PCLKDIV_8	(0x00020000) +#define CLKSET_MAINDIV2		(0x0000f800) +#define CLKSET_MAINDIV1		(0x00000780) +#define CLKSET_PREDIV		(0x0000007C) +#define CLKSET_HCLKDIV		(0x00000003) + +/* (WDT) Watchdog Timer (userguide 11.2.1) */ +typedef struct { +	volatile u32  ctl; +	volatile u32  rst; +	volatile u32  status; +	volatile u32  count[4]; +} /*__attribute__((__packed__))*/ lh7a40x_wdt_t; +#define LH7A40X_WDT_BASE    (0x80001400) +#define LH7A40X_WDT_PTR(name)  lh7a40x_wdt_t* name = (lh7a40x_wdt_t*) LH7A40X_WDT_BASE + +/* (RTC) Real Time Clock (lh7a400 userguide 12.2.1, lh7a404 userguide 13.2.1) */ +typedef struct { +	volatile u32  rtcdr; +	volatile u32  rtclr; +	volatile u32  rtcmr; +	volatile u32  unk1; +	volatile u32  rtcstat_eoi; +	volatile u32  rtccr; +	volatile u32  rsvd1[58]; +} /*__attribute__((__packed__))*/ lh7a40x_rtc_t; +#define LH7A40X_RTC_BASE    (0x80000D00) +#define LH7A40X_RTC_PTR(name)  lh7a40x_rtc_t* name = (lh7a40x_rtc_t*) LH7A40X_RTC_BASE + +/* Timers (lh7a400 userguide 13.2.1, lh7a404 userguide 11.2.1) */ +typedef struct { +	volatile u32  load; +	volatile u32  value; +	volatile u32  control; +	volatile u32  tceoi; +} /*__attribute__((__packed__))*/ lh7a40x_timer_t; + +typedef struct { +	lh7a40x_timer_t  timer1; +	volatile u32     rsvd1[4]; +	lh7a40x_timer_t  timer2; +	volatile u32     unk1[4]; +	volatile u32     bzcon; +	volatile u32     unk2[15]; +	lh7a40x_timer_t  timer3; +	/*volatile u32     rsvd2;*/ +} /*__attribute__((__packed__))*/ lh7a40x_timers_t; +#define LH7A40X_TIMERS_BASE    (0x80000C00) +#define LH7A40X_TIMERS_PTR(name)  lh7a40x_timers_t* name = (lh7a40x_timers_t*) LH7A40X_TIMERS_BASE + +#define TIMER_EN	(0x00000080) +#define TIMER_PER	(0x00000040) +#define TIMER_FREE	(0x00000000) +#define TIMER_CLK508K	(0x00000008) +#define TIMER_CLK2K	(0x00000000) + +/* (SSP) Sychronous Serial Ports (lh7a400 userguide 14.2.1, lh7a404 userguide 14.2.1) */ +typedef struct { +	volatile u32  cr0; +	volatile u32  cr1; +	volatile u32  irr_roeoi; +	volatile u32  dr; +	volatile u32  cpr; +	volatile u32  sr; +	/*volatile u32  rsvd1[58];*/ +} /*__attribute__((__packed__))*/ lh7a40x_ssp_t; +#define LH7A40X_SSP_BASE    (0x80000B00) +#define LH7A40X_SSP_PTR(name)  lh7a40x_ssp_t* name = (lh7a40x_ssp_t*) LH7A40X_SSP_BASE + +/* (UART) Universal Asychronous Receiver/Transmitter (lh7a400 userguide 15.2.1, lh7a404 userguide 15.2.1) */ +typedef struct { +	volatile u32  data; +	volatile u32  fcon; +	volatile u32  brcon; +	volatile u32  con; +	volatile u32  status; +	volatile u32  rawisr; +	volatile u32  inten; +	volatile u32  isr; +	volatile u32  rsvd1[56]; +} /*__attribute__((__packed__))*/ lh7a40x_uart_t; +#define LH7A40X_UART_BASE      (0x80000600) +#define LH7A40X_UART_PTR(name,n) \ +	lh7a40x_uart_t* name = (lh7a40x_uart_t*) (LH7A40X_UART_BASE + ((n-1) * sizeof(lh7a40x_uart_t))) + +#define UART_BE		(0x00000800)      /* the rx error bits */ +#define UART_OE		(0x00000400) +#define UART_PE		(0x00000200) +#define UART_FE		(0x00000100) + +#define UART_WLEN	(0x00000060)	/* fcon bits */ +#define UART_WLEN_8	(0x00000060) +#define UART_WLEN_7	(0x00000040) +#define UART_WLEN_6	(0x00000020) +#define UART_WLEN_5	(0x00000000) +#define UART_FEN	(0x00000010) +#define UART_STP2	(0x00000008) +#define UART_STP2_2	(0x00000008) +#define UART_STP2_1	(0x00000000) +#define UART_EPS	(0x00000004) +#define UART_EPS_EVEN	(0x00000004) +#define UART_EPS_ODD	(0x00000000) +#define UART_PEN	(0x00000002) +#define UART_BRK	(0x00000001) + +#define UART_BAUDDIV	(0x0000ffff)	/* brcon bits */ + +#define UART_SIRBD	(0x00000080)	/* con bits */ +#define UART_LBE	(0x00000040) +#define UART_MXP	(0x00000020) +#define UART_TXP	(0x00000010) +#define UART_RXP	(0x00000008) +#define UART_SIRLP	(0x00000004) +#define UART_SIRD	(0x00000002) +#define UART_EN		(0x00000001) + +#define UART_TXFE	(0x00000080)	/* status bits */ +#define UART_RXFF	(0x00000040) +#define UART_TXFF	(0x00000020) +#define UART_RXFE	(0x00000010) +#define UART_BUSY	(0x00000008) +#define UART_DCD	(0x00000004) +#define UART_DSR	(0x00000002) +#define UART_CTS	(0x00000001) + +#define UART_MSEOI	(0xfffffff0)	/* rawisr interrupt bits */ + +#define UART_RTI	(0x00000008)	/* generic interrupt bits */ +#define UART_MI		(0x00000004) +#define UART_TI		(0x00000002) +#define UART_RI		(0x00000001) + +/* (GPIO) General Purpose IO and External Interrupts (userguide 16.2.1) */ +typedef struct { +	volatile u32  pad; +	volatile u32  pbd; +	volatile u32  pcd; +	volatile u32  pdd; +	volatile u32  padd; +	volatile u32  pbdd; +	volatile u32  pcdd; +	volatile u32  pddd; +	volatile u32  ped; +	volatile u32  pedd; +	volatile u32  kbdctl; +	volatile u32  pinmux; +	volatile u32  pfd; +	volatile u32  pfdd; +	volatile u32  pgd; +	volatile u32  pgdd; +	volatile u32  phd; +	volatile u32  phdd; +	volatile u32  rsvd1; +	volatile u32  inttype1; +	volatile u32  inttype2; +	volatile u32  gpiofeoi; +	volatile u32  gpiointen; +	volatile u32  intstatus; +	volatile u32  rawintstatus; +	volatile u32  gpiodb; +	volatile u32  papd; +	volatile u32  pbpd; +	volatile u32  pcpd; +	volatile u32  pdpd; +	volatile u32  pepd; +	volatile u32  pfpd; +	volatile u32  pgpd; +	volatile u32  phpd; +} /*__attribute__((__packed__))*/ lh7a40x_gpioint_t; +#define LH7A40X_GPIOINT_BASE    (0x80000E00) +#define LH7A40X_GPIOINT_PTR(name)  lh7a40x_gpioint_t* name = (lh7a40x_gpioint_t*) LH7A40X_GPIOINT_BASE + +/* Embedded SRAM */ +#define CFG_SRAM_BASE	(0xB0000000) +#define CFG_SRAM_SIZE	(80*1024)	/* 80kB */ + +#endif  /* __LH7A40X_H__ */ diff --git a/include/lpd7a400_cpld.h b/include/lpd7a400_cpld.h new file mode 100644 index 000000000..c70af09e6 --- /dev/null +++ b/include/lpd7a400_cpld.h @@ -0,0 +1,195 @@ +/* + * 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 + */ + +/* + * Logic lh7a400-10 Card Engine CPLD interface + */ + +#ifndef __LPD7A400_CPLD_H_ +#define __LPD7A400_CPLD_H_ + + +/* + * IO Controller Address and Register Definitions + *   - using LH7A400-10 Card Engine IO Controller Specification + *     (logic PN: 70000079) + */ + +/*------------------------------------------------------------------ + * Slow Peripherals (nCS6) + */ +#define LPD7A400_CPLD_CF		(0x60200000) +#define LPD7A400_CPLD_ISA		(0x60400000) + +/*------------------------------------------------------------------ + * Fast Peripherals (nCS7) + * + * The CPLD directs access to 0x70000000-0x701fffff to the onboard + * ethernet controller + */ +#define LPD7A400_CPLD_WLAN_BASE		(0x70000000) + +/* All registers are 8 bit */ +#define LPD7A400_CPLD_CECTL_REG		(0x70200000) +#define LPD7A400_CPLD_SPIDATA_REG	(0x70600000) +#define LPD7A400_CPLD_SPICTL_REG	(0x70800000) +#define LPD7A400_CPLD_EEPSPI_REG	(0x70a00000) +#define LPD7A400_CPLD_INTMASK_REG	(0x70c00000) +#define LPD7A400_CPLD_MODE_REG		(0x70e00000) +#define LPD7A400_CPLD_FLASH_REG		(0x71000000) +#define LPD7A400_CPLD_PWRMG_REG		(0x71200000) +#define LPD7A400_CPLD_REV_REG		(0x71400000) +#define LPD7A400_CPLD_EXTGPIO_REG	(0x71600000) +#define LPD7A400_CPLD_GPIODATA_REG	(0x71800000) +#define LPD7A400_CPLD_GPIODIR_REG	(0x71a00000) + +#define LPD7A400_CPLD_REGPTR		(volatile u8*) + +/* Card Engine Control Register (section 3.1.2) */ +#define CECTL_SWINT	(0x80)	/* Software settable interrupt source +				   (routed to uP PF3) +				   0 = generate interrupt, 1 = do not */ +#define CECTL_OCMSK	(0x40)	/* USB1 connection interrupt mask +				   0 = not masked, 1 = masked */ +#define CECTL_PDRV	(0x20)	/* PCC_nDRV output +				   0 = active, 1 = inactive */ +#define CECTL_USB1C	(0x10)	/* USB1 connection interrupt +				   0 = active, 1 = inactive */ +#define CECTL_USB1P	(0x08)  /* USB1 Power enable +				   0 = enabled, 1 = disabled */ +#define CECTL_AWKP	(0x04)  /* Auto-Wakeup enable +				   0 = enabled, 1 = disabled */ +#define CECTL_LCDV	(0x02)  /* LCD VEE enable +				   0 = disabled, 1 = enabled */ +#define CECTL_WLPE	(0x01)  /* Wired LAN power enable +				   0 = enabled, 1 = disabled */ + +/* SPI Control Register (section 3.1.5) */ +#define SPICTL_SPLD	(0x20)	/* SPI load (R) +				   0 = data reg. has not been loaded, shift +				       count has not been reset +				   1 = data reg. loaded, shift count reset */ +#define SPICTL_SPST	(0x10)  /* SPI start (RW) +				   0 = don't load data reg. and reset shift count +				   1 = ready to load data reg and reset shift count */ +#define SPICTL_SPDN	(0x08)  /* SPI done (R) +				   0 = not done +				   1 = access done */ +#define SPICTL_SPRW	(0x04)  /* SPI read/write (RW) +				   0 = SPI write access +				   1 = SPI read access */ +#define SPICTL_STCS	(0x02)  /* SPI touch chip select (RW) +				   0 = not selected +				   1 = selected */ +#define SPICTL_SCCS	(0x01)  /* SPI CODEC chip select (RW) {not used} +				   0 = not selected +				   1 = selected */ + +/* EEPROM SPI Interface Register (section 3.1.6) */ +#define EEPSPI_EECS	(0x08)	/* EEPROM chip select (RW) +				   0 = not selected +				   1 = selected */ +#define EEPSPI_EECK	(0x04)	/* EEPROM SPI clock (RW) */ +#define EEPSPI_EETX	(0x02)  /* EEPROM SPI tx data (RW) */ +#define EEPSPI_EERX	(0x01)  /* EEPROM SPI rx data (R) */ + +/* Interrupt/Mask Register (section 3.1.7) */ +#define INTMASK_CMSK	(0x80)  /* CPLD_nIRQD interrupt mask (RW) +				   0 = not masked +				   1 = masked */ +#define INTMASK_CIRQ	(0x40)	/* interrupt signal to CPLD (R) +				   0 = interrupt active +				   1 = no interrupt */ +#define INTMASK_PIRQ	(0x10)	/* legacy, no effect */ +#define INTMASK_TMSK	(0x08)	/* Touch chip interrupt mask (RW) +				   0 = not masked +				   1 = masked */ +#define INTMASK_WMSK	(0x04)  /* Wired LAN interrupt mask (RW) +				   0 = not masked +				   1 = masked */ +#define INTMASK_TIRQ	(0x02)  /* Touch chip interrupt request (R) +				   0 = interrupt active +				   1 = no interrupt */ +#define INTMASK_WIRQ	(0x01)  /* Wired LAN interrupt request (R) +				   0 = interrupt active +				   1 = no interrupt */ + +/* Mode Register (section 3.1.8) */ +#define MODE_VS1	(0x80)  /* PCMCIA Voltage Sense 1 input (PCC_VS1) (R) +				   0 = active slot VS1 pin is low +				   1 = active slot VS1 pin is high */ +#define MODE_CD2	(0x40)  /* PCMCIA Card Detect 2 input (PCC_nCD2) (R) +				   0 = active slot CD2 is low +				   1 = active slot CD2 is high */ +#define MODE_IOIS16	(0x20)  /* PCMCIA IOIS16 input (PCC_nIOIS16) (R) +				   0 = 16 bit access area +				   1 = 8 bit access area */ +#define MODE_CD1	(0x10)  /* PCMCIA Card Detect 1 input (PCC_nCD1) (R) +				   0 = active slot CD1 is low +				   1 = active slot CD1 is high */ +#define MODE_upMODE3	(0x08)  /* Mode Pin 3 (R) +				   0 = off-board boot device +				   1 = on-board boot device (flash) */ +#define MODE_upMODE2	(0x04)  /* Mode Pin 2 (R) (LH7A400 Little Endian only) +				   0 = big endian +				   1 = little endian */ +#define MODE_upMODE1	(0x02)  /* Mode Pin 1 and Mode Pin 2 (R) */ +#define MODE_upMODE0	(0x01)  /*   - bus width at boot */ + + +/* Flash Register (section 3.1.9) */ +#define FLASH_FPOP	(0x08)	/* Flash populated (RW) +				   0 = populated, 1 = not */ +#define FLASH_FST2	(0x04)  /* Flash status (R) (RY/BY# pin for upper 16 bit chip +				   0 = busy, 1 = ready */ +#define FLASH_FST1	(0x02)  /* Flash status (R) (RY/BY# pin for lower 16 bit chip +				   0 = busy, 1 = ready */ +#define FLASH_FPEN	(0x01)  /* Flash program enable (RW) +				   0 = flash write protected +				   1 = programming enabled */ + +/* Power Management Register (section 3.1.10) + *    - when either of these is low an unmaskable interrupt to cpu + *      is generated + */ +#define PWRMG_STBY	(0x10)  /* state of nSTANDBY signal to CPLD (R) +				   0 = low, 1 = high */ +#define PWRMG_SPND	(0x04)  /* state of nSUSPEND signal to CPLD (R) +				   0 = low, 1 = high */ + + +/* Extended GPIO Register (section 3.1.12) */ +#define EXTGPIO_STATUS1	(0x04)  /* Status 1 output (RW) (uP_STATUS_1) +				   0 = set pin low, 1 = set pin high */ +#define EXTGPIO_STATUS2 (0x02)  /* Status 2 output (RW) (uP_STATUS_2) +				   0 = set pin low, 1 = set pin high */ +#define EXTGPIO_GPIO1	(0x01)  /* General purpose output (RW) (CPLD_GPIO_1) +				   0 = set pin low, 1 = set pin high */ + +/* GPIO Data Register (section 3.1.13) */ +#define GPIODATA_GPIO2	(0x01)  /* General purpose input/output (RW) (CPLD_GPIO_2) +				   0 = set low (output) / read low (input) +				   1 = set high (output) / read high (input) */ + +/* GPIO Direction Register (section 3.1.14) */ +#define GPIODIR_GPDR0	(0x01)  /* GPIO2 direction (RW) +				   0 = output, 1 = input */ + +#endif  /* __LH7A400_H__ */ diff --git a/lib_arm/board.c b/lib_arm/board.c index 193980eff..bba944af3 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -32,6 +32,13 @@  #include <version.h>  #include <net.h> +#ifdef CONFIG_DRIVER_SMC91111 +#include "../drivers/smc91111.h" +#endif +#ifdef CONFIG_DRIVER_LAN91C96 +#include "../drivers/lan91c96.h" +#endif +  #if (CONFIG_COMMANDS & CFG_CMD_NAND)  void nand_init (void);  #endif @@ -58,9 +65,6 @@ extern void cs8900_get_enetaddr (uchar * addr);  extern void rtl8019_get_enetaddr (uchar * addr);  #endif -#ifdef CONFIG_DRIVER_LAN91C96 -#include "../drivers/lan91c96.h" -#endif  /*   * Begin and End of memory area for malloc(), and current "brk"   */ @@ -302,11 +306,12 @@ void start_armboot (void)  	cs8900_get_enetaddr (gd->bd->bi_enetaddr);  #endif -#ifdef CONFIG_DRIVER_LAN91C96 +#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)  	if (getenv ("ethaddr")) {  		smc_set_mac_addr(gd->bd->bi_enetaddr);  	} -#endif /* CONFIG_DRIVER_LAN91C96 */ +	eth_init(gd->bd); +#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */  	/* Initialize from environment */  	if ((s = getenv ("loadaddr")) != NULL) { |