diff options
| -rw-r--r-- | board/RRvision/flash.c | 522 | ||||
| -rw-r--r-- | board/bmw/Makefile | 43 | ||||
| -rw-r--r-- | board/bmw/README | 340 | ||||
| -rw-r--r-- | board/bmw/m48t59y.c | 323 | ||||
| -rw-r--r-- | board/csb226/config.mk | 16 | ||||
| -rw-r--r-- | board/csb226/flash.c | 364 | 
6 files changed, 1608 insertions, 0 deletions
| diff --git a/board/RRvision/flash.c b/board/RRvision/flash.c new file mode 100644 index 000000000..06f7c4b7a --- /dev/null +++ b/board/RRvision/flash.c @@ -0,0 +1,522 @@ +/* + * (C) Copyright 2000-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 + */ + +#define DEBUG + +#include <common.h> +#include <mpc8xx.h> + +#ifndef	CFG_ENV_ADDR +#define CFG_ENV_ADDR	(CFG_FLASH_BASE + CFG_ENV_OFFSET) +#endif + +flash_info_t	flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips	*/ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ +	volatile immap_t     *immap  = (immap_t *)CFG_IMMR; +	volatile memctl8xx_t *memctl = &immap->im_memctl; +	unsigned long size; +	int i; + +	/* Init: no FLASHes known */ +	for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { +		flash_info[i].flash_id = FLASH_UNKNOWN; +	} + +	/* Static FLASH Bank configuration here - FIXME XXX */ + +	size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + +	if (flash_info[0].flash_id == FLASH_UNKNOWN) { +		printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", +			size, size<<20); +	} + +	/* Remap FLASH according to real size */ +	memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size & OR_AM_MSK); +	memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; + +	/* Re-do sizing to get full correct info */ +	size = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +	/* monitor protection ON by default */ +	flash_protect(FLAG_PROTECT_SET, +		      CFG_MONITOR_BASE, +		      CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, +		      &flash_info[0]); +#endif + +#ifdef	CFG_ENV_IS_IN_FLASH +	/* ENV protection ON by default */ +	flash_protect(FLAG_PROTECT_SET, +		      CFG_ENV_ADDR, +		      CFG_ENV_ADDR+CFG_ENV_SIZE-1, +		      &flash_info[0]); +#endif + +	flash_info[0].size = size; + +	return (size); +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +	int i; + +	if (info->flash_id == FLASH_UNKNOWN) { +		puts ("missing or unknown FLASH type\n"); +		return; +	} + +	switch (info->flash_id & FLASH_VENDMASK) { +	case FLASH_MAN_AMD:	puts ("AMD ");			break; +	case FLASH_MAN_FUJ:	puts ("FUJITSU ");		break; +	default:		puts ("Unknown Vendor ");	break; +	} + +	switch (info->flash_id & FLASH_TYPEMASK) { +	case FLASH_AM400B:	puts ("AM29LV400B (4 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM400T:	puts ("AM29LV400T (4 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM800B:	puts ("AM29LV800B (8 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM800T:	puts ("AM29LV800T (8 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM160B:	puts ("AM29LV160B (16 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM160T:	puts ("AM29LV160T (16 Mbit, top boot sector)\n"); +				break; +	case FLASH_AM320B:	puts ("AM29LV320B (32 Mbit, bottom boot sect)\n"); +				break; +	case FLASH_AM320T:	puts ("AM29LV320T (32 Mbit, top boot sector)\n"); +				break; +	default:		puts ("Unknown Chip Type\n"); +				break; +	} + +	printf ("  Size: %ld MB in %d Sectors\n", +		info->size >> 20, info->sector_count); + +	puts ("  Sector Start Addresses:"); +	for (i=0; i<info->sector_count; ++i) { +		if ((i % 5) == 0) +			puts ("\n   "); +		printf (" %08lX%s", +			info->start[i], +			info->protect[i] ? " (RO)" : "     " +		); +	} +	puts ("\n"); +	return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ +	short i; +	ulong value; +	ulong base = (ulong)addr; + +	/* Write auto select command: read Manufacturer ID */ +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; +	addr[0x0555] = 0x00900090; + +	value = addr[0]; + +	switch (value) { +	case AMD_MANUFACT: +		info->flash_id = FLASH_MAN_AMD; +		break; +	case FUJ_MANUFACT: +		info->flash_id = FLASH_MAN_FUJ; +		break; +	default: +		info->flash_id = FLASH_UNKNOWN; +		info->sector_count = 0; +		info->size = 0; +		return (0);			/* no or unknown flash	*/ +	} + +	value = addr[1];			/* device ID		*/ + +	switch (value) { +	case AMD_ID_LV400T: +		info->flash_id += FLASH_AM400T; +		info->sector_count = 11; +		info->size = 0x00100000; +		break;				/* => 1 MB		*/ + +	case AMD_ID_LV400B: +		info->flash_id += FLASH_AM400B; +		info->sector_count = 11; +		info->size = 0x00100000; +		break;				/* => 1 MB		*/ + +	case AMD_ID_LV800T: +		info->flash_id += FLASH_AM800T; +		info->sector_count = 19; +		info->size = 0x00200000; +		break;				/* => 2 MB		*/ + +	case AMD_ID_LV800B: +		info->flash_id += FLASH_AM800B; +		info->sector_count = 19; +		info->size = 0x00200000; +		break;				/* => 2 MB		*/ + +	case AMD_ID_LV160T: +		info->flash_id += FLASH_AM160T; +		info->sector_count = 35; +		info->size = 0x00400000; +		break;				/* => 4 MB		*/ + +	case AMD_ID_LV160B: +		info->flash_id += FLASH_AM160B; +		info->sector_count = 35; +		info->size = 0x00400000; +		break;				/* => 4 MB		*/ +	case AMD_ID_LV320T: +		info->flash_id += FLASH_AM320T; +		info->sector_count = 71; +		info->size = 0x00800000; +		break;				/* => 8 MB		*/ + +	case AMD_ID_LV320B: +		info->flash_id += FLASH_AM320B; +		info->sector_count = 71; +		info->size = 0x00800000; +		break;				/* => 8 MB		*/ +	default: +		info->flash_id = FLASH_UNKNOWN; +		return (0);			/* => no or unknown flash */ +	} + +	/* set up sector start address table */ +	switch (value) { +	case AMD_ID_LV400B: +	case AMD_ID_LV800B: +	case AMD_ID_LV160B: +		/* set sector offsets for bottom boot block type	*/ +		info->start[0] = base + 0x00000000; +		info->start[1] = base + 0x00008000; +		info->start[2] = base + 0x0000C000; +		info->start[3] = base + 0x00010000; +		for (i = 4; i < info->sector_count; i++) { +			info->start[i] = base + (i * 0x00020000) - 0x00060000; +		} +		break; +	case AMD_ID_LV400T: +	case AMD_ID_LV800T: +	case AMD_ID_LV160T: +		/* set sector offsets for top boot block type		*/ +		i = info->sector_count - 1; +		info->start[i--] = base + info->size - 0x00008000; +		info->start[i--] = base + info->size - 0x0000C000; +		info->start[i--] = base + info->size - 0x00010000; +		for (; i >= 0; i--) { +			info->start[i] = base + i * 0x00020000; +		} +		break; +	case AMD_ID_LV320B: +		for (i = 0; i < info->sector_count; i++) { +			info->start[i] = base; +			/* +			 * The first 8 sectors are 8 kB, +			 * all the other ones  are 64 kB +			 */ +			base += (i < 8) +				?  2 * ( 8 << 10) +				:  2 * (64 << 10); +		} +		break; +	case AMD_ID_LV320T: +		for (i = 0; i < info->sector_count; i++) { +			info->start[i] = base; +			/* +			 * The last 8 sectors are 8 kB, +			 * all the other ones  are 64 kB +			 */ +			base += (i < (info->sector_count - 8)) +				?  2 * (64 << 10) +				:  2 * ( 8 << 10); +		} +		break; +	default: +		return (0); +		break; +	} + +	/* check for protected sectors */ +	for (i = 0; i < info->sector_count; i++) { +		/* read sector protection at sector address, (A7 .. A0) = 0x02 */ +		/* D0 = 1 if protected */ +		addr = (volatile unsigned long *)(info->start[i]); +		info->protect[i] = addr[2] & 1; +	} + +	/* +	 * Prevent writes to uninitialized FLASH. +	 */ +	if (info->flash_id != FLASH_UNKNOWN) { +		addr = (volatile unsigned long *)info->start[0]; + +		*addr = 0x00F000F0;	/* reset bank */ +	} + +	return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int	flash_erase (flash_info_t *info, int s_first, int s_last) +{ +	vu_long *addr = (vu_long*)(info->start[0]); +	int flag, prot, sect, l_sect; +	ulong start, now, last; + +	if ((s_first < 0) || (s_first > s_last)) { +		if (info->flash_id == FLASH_UNKNOWN) { +			puts ("- missing\n"); +		} else { +			puts ("- no sectors to erase\n"); +		} +		return 1; +	} + +	if ((info->flash_id == FLASH_UNKNOWN) || +	    (info->flash_id > FLASH_AMD_COMP)) { +		printf ("Can't erase unknown flash type %08lx - aborted\n", +			info->flash_id); +		return 1; +	} + +	prot = 0; +	for (sect=s_first; sect<=s_last; ++sect) { +		if (info->protect[sect]) { +			prot++; +		} +	} + +	if (prot) { +		printf ("- Warning: %d protected sectors will not be erased!\n", +			prot); +	} else { +		puts ("\n"); +	} + +	l_sect = -1; + +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); + +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; +	addr[0x0555] = 0x00800080; +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; + +	/* Start erase on unprotected sectors */ +	for (sect = s_first; sect<=s_last; sect++) { +		if (info->protect[sect] == 0) {	/* not protected */ +			addr = (vu_long*)(info->start[sect]); +			addr[0] = 0x00300030; +			l_sect = sect; +		} +	} + +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +	/* wait at least 80us - let's wait 1 ms */ +	udelay (1000); + +	/* +	 * We wait for the last triggered sector +	 */ +	if (l_sect < 0) +		goto DONE; + +	start = get_timer (0); +	last  = start; +	addr = (vu_long*)(info->start[l_sect]); +	while ((addr[0] & 0x00800080) != 0x00800080) { +		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { +			puts ("Timeout\n"); +			return 1; +		} +		/* show that we're waiting */ +		if ((now - last) > 1000) {	/* every second */ +			putc ('.'); +			last = now; +		} +	} + +DONE: +	/* reset to read mode */ +	addr = (volatile unsigned long *)info->start[0]; +	addr[0] = 0x00F000F0;	/* reset bank */ + +	puts (" done\n"); +	return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +	ulong cp, wp, data; +	int i, l, rc; + +	wp = (addr & ~3);	/* get lower word aligned address */ + +	/* +	 * handle unaligned start bytes +	 */ +	if ((l = addr - wp) != 0) { +		data = 0; +		for (i=0, cp=wp; i<l; ++i, ++cp) { +			data = (data << 8) | (*(uchar *)cp); +		} +		for (; i<4 && cnt>0; ++i) { +			data = (data << 8) | *src++; +			--cnt; +			++cp; +		} +		for (; cnt==0 && i<4; ++i, ++cp) { +			data = (data << 8) | (*(uchar *)cp); +		} + +		if ((rc = write_word(info, wp, data)) != 0) { +			return (rc); +		} +		wp += 4; +	} + +	/* +	 * handle word aligned part +	 */ +	while (cnt >= 4) { +		data = 0; +		for (i=0; i<4; ++i) { +			data = (data << 8) | *src++; +		} +		if ((rc = write_word(info, wp, data)) != 0) { +			return (rc); +		} +		wp  += 4; +		cnt -= 4; +	} + +	if (cnt == 0) { +		return (0); +	} + +	/* +	 * handle unaligned tail bytes +	 */ +	data = 0; +	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { +		data = (data << 8) | *src++; +		--cnt; +	} +	for (; i<4; ++i, ++cp) { +		data = (data << 8) | (*(uchar *)cp); +	} + +	return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ +	vu_long *addr = (vu_long*)(info->start[0]); +	ulong start; +	int flag; + +	/* Check if Flash is (sufficiently) erased */ +	if ((*((vu_long *)dest) & data) != data) { +		return (2); +	} +	/* Disable interrupts which might cause a timeout here */ +	flag = disable_interrupts(); + +	addr[0x0555] = 0x00AA00AA; +	addr[0x02AA] = 0x00550055; +	addr[0x0555] = 0x00A000A0; + +	*((vu_long *)dest) = data; + +	/* re-enable interrupts if necessary */ +	if (flag) +		enable_interrupts(); + +	/* data polling for D7 */ +	start = get_timer (0); +	while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) { +		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { +			return (1); +		} +	} +	return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/bmw/Makefile b/board/bmw/Makefile new file mode 100644 index 000000000..46fe7910e --- /dev/null +++ b/board/bmw/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2002 +# James F. Dougherty, Broadcom Corporation, jfd@broadcom.com +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= lib$(BOARD).a + +OBJS	= $(BOARD).o flash.o ns16550.o serial.o m48t59y.o + +SOBJS	= early_init.o + +$(LIB):	.depend $(OBJS) $(SOBJS) +	$(AR) crv $@ $^ + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/bmw/README b/board/bmw/README new file mode 100644 index 000000000..55ef56ebe --- /dev/null +++ b/board/bmw/README @@ -0,0 +1,340 @@ +Broadcom 95xx BMW CPCI Platform + +Overview +========= +BMW is an MPC8245 system controller featuring: +* 3U CPCI Form Factor +* BCM5703 Gigabit Ethernet +* M48T59Y NVRAM +* 16MB DOC +* DIP Socket for Socketed DOC up to 1GB +* 64MB SDRAM +* LCD Display +* Configurable Jumper options for 66,85, and 100Mhz memory bus + + +BMW System Address Map +====================== +BMW uses the MPC8245 CHRP Address MAP B found in the MPC8245 Users Manual +(P.121, Section 3.1 Address Maps, Address Map B). Other I/O devices found +onboard the processor module are listed briefly below: + +0x00000000 - 0x40000000 - 64MB SDRAM SIMM +                          (Unregistered PC-100 SDRAM DIMM Module) + +0xFF000000 - 0xFF001FFF - M-Systems DiskOnChip (TM) 2000 +                          TSOP 16MB (MD2211-D16-V3) + +0x70000000 - 0x70001FFF - M-Systems DiskOnChip (TM) 2000 +                          DIP32 (Socketed 16MB - 1GB ) * +                          NOTE: this is not populated on all systems. + +0x7c000000 - 0x7c000000 - Reset Register +                          (Write 0 to reset) + +0x7c000001 - 0x7c000001 - System LED +                          (Clear Bit 7 to turn on, set to shut off) + +0x7c000002 - 0x7c000002 - M48T59 Watchdog IRQ3 +                          (Clear bit 7 to reset, set to assert IRQ3) + +0x7c000003 - 0x7c000003 - M48T59 Write-Protect Register +                          (Clear bit 7 to make R/W, set to make R/O) + +0x7c002000 - 0x7c002003 - Infineon OSRAM DLR2416 4 Character +                          5x7 Dot Matrix Alphanumeric Display +                          (Each byte sets the appropriate character) + +0x7c004000 - 0x7c005FF0 - SGS-THOMSON M48T59Y 8K NVRAM/RTC +                          NVRAM Memory Region + +0x7c005FF0 - 0x7c005FFF - SGS-THOMSON M48T59Y 8K NVRAM/RTC +                          Realtime Clock Registers + +0xFFF00000 - 0xFFF80000 - 512K PLCC32 BootRom +                          (AMD AM29F040, ST 29W040B) + +0xFFF00100 -              System Reset Vector + + +IO/MMU (BAT) Configuration +====================== +The following Block-Address-Translation (BAT) configuration +is recommended to access all I/O devices. + +#define CFG_IBAT0L  (0x00000000 | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U  (0x00000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L  (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT1U  (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT2L  (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U  (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT3L  (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U  (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L  CFG_IBAT0L +#define CFG_DBAT0U  CFG_IBAT0U +#define CFG_DBAT1L  CFG_IBAT1L +#define CFG_DBAT1U  CFG_IBAT1U +#define CFG_DBAT2L  CFG_IBAT2L +#define CFG_DBAT2U  CFG_IBAT2U +#define CFG_DBAT3L  CFG_IBAT3L +#define CFG_DBAT3U  CFG_IBAT3U + + +Interrupt Mappings +====================== +BMW uses MPC8245 discrete mode interrupts. With the following +hardwired mappings: + +BCM5701 10/100/1000 Ethernet 		IRQ1 +CompactPCI Interrupt A			IRQ2 +RTC/Watchdog Interrupt			IRQ3 +Internal NS16552 UART			IRQ4 + + +Jumper Settings +====================== + +BMW has a jumper (JP600) for selecting 66, 85, or 100Mhz memory bus. +A jumper (X) is a 0 bit. + +Hence 66= 10110 +      85= 11000 +     100= 10000 + +Jumper Settings for various Speeds +======================= +J1 J2 J3 J4 J5 +    X        X    66Mhz +======================= +J1 J2 J3 J4 J5 +       X  X  X    85Mhz +======================= +J1 J2 J3 J4 J5 +    X  X  X  X   100Mhz +======================= + +Obviously, 100Mhz memory bus is recommended for optimum performance. + + +U-Boot +=============== +Broadcom BMW board is supported under config_BWM option. +Supported features: + +- NVRAM setenv/getenv (used by Linux Kernel for configuration variables) +- BCM570x TFTP file transfer support +- LCD Display Support +- DOC Support - (underway) + + + +U-Boot 1.2.0 (Aug  6 2002 - 17:44:48) + +CPU:   MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache +Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B) +Built: Aug  6 2002 at 17:44:37 +Local Bus at 66 MHz +DRAM:  64 MB +FLASH: 4095 MB +In:    serial +Out:   serial +Err:   serial +DOC:   No DiskOnChip found +Hit any key to stop autoboot:  0 +=>printenv +bootdelay=5 +baudrate=9600 +clocks_in_mhz=1 +hostname=switch-2 +bootcmd=tftp 100000 vmlinux.img;bootm +gateway=10.16.64.1 +ethaddr=00:00:10:18:10:10 +nfsroot=172.16.40.111:/boot/root-fs +filesize=5ec8c +netmask=255.255.240.0 +ipaddr=172.16.40.114 +serverip=172.16.40.111 +root=/dev/nfs +stdin=serial +stdout=serial +stderr=serial + +Environment size: 315/8172 bytes +=>boot + + + + + + + +DevTools +======== +ELDK +        DENX Embedded Linux Development Kit + +ROM Emulator +	Grammar Engine PROMICE P1160-90-AI21E (2MBx8bit, 90ns access time) +	Grammar Engine PL32E 32Pin PLCC Emulation cables +	Grammar Engine 3VA8CON (3Volt adapter with Short cables) +	Grammar Engine FPNET PromICE Ethernet Adapters + +ICE +	WRS/EST VisionICE-II (PPC8240) + + + +=>reset + + +U-Boot 1.2.0 (Aug  6 2002 - 17:44:48) + +CPU:   MPC8245 Revision 16.20 at 264 MHz: 16 kB I-Cache 16 kB D-Cache +Board: BMW MPC8245/KAHLUA2 - CHRP (MAP B) +Built: Aug  6 2002 at 17:44:37 +Local Bus at 66 MHz +DRAM:  64 MB +FLASH: 4095 MB +In:    serial +Out:   serial +Err:   serial +DOC:   No DiskOnChip found +Hit any key to stop autoboot:  0 + +Broadcom BCM5701 1000Base-T: bus 0, device 13, function 0: MBAR=0x80100000 +BCM570x PCI Memory base address @0x80100000 +eth0:Broadcom BCM5701 1000Base-T: 100 Mbps half duplex link up, flow control OFF +eth0: Broadcom BCM5701 1000Base-T @0x80100000,node addr 000010181010 +eth0: BCM5700 with Broadcom BCM5701 Integrated Copper transceiver found +eth0: 32-bit PCI 33MHz, MTU: 1500,Rx Checksum ON +ARP broadcast 1 +TFTP from server 172.16.40.111; our IP address is 172.16.40.114 +Filename 'vmlinux.img'. +Load address: 0x100000 +Loading: ################################################################# +         ####################################T ############################# +         ###################### +done +Bytes transferred = 777199 (bdbef hex) + +eth0:Broadcom BCM5701 1000Base-T,HALT,POWER DOWN,done - offline. +## Booting image at 00100000 ... +   Image Name:   vmlinux.bin.gz +   Created:      2002-08-06   6:30:13 UTC +   Image Type:   PowerPC Linux Kernel Image (gzip compressed) +   Data Size:    777135 Bytes = 758 kB = 0 MB +   Load Address: 00000000 +   Entry Point:  00000000 +   Verifying Checksum ... OK +   Uncompressing Kernel Image ... OK +Memory BAT mapping: BAT2=64Mb, BAT3=0Mb, residual: 0Mb +Linux version 2.4.19-rc3 (jfd@que) (gcc version 2.95.3 20010111 (prerelease/franzo/20010111)) #168 Mon Aug 5 23:29:20 PDT 2002 +CPU:82xx: 32 I-Cache Block Size, 32 D-Cache Block Size PVR: 0x810000 +U-Boot Environment: 0xc01b08f0 +IP PNP: 802.3 Ethernet Address=<0:0:10:18:10:10> +cpu0: MPC8245/KAHLUA-II : BMW Platform : 64MB RAM: BPLD Rev. 6e +NOTICE: mounting root file system via NFS +IP PNP: switch-2: eth0 IP 172.16.40.114/255.255.240.0 gateway 10.16.64.1 server 172.16.40.111 +On node 0 totalpages: 16384 +zone(0): 16384 pages. +zone(1): 0 pages. +zone(2): 0 pages. +Kernel command line: console=ttyS0,9600 ip=172.16.40.114:172.16.40.111:10.16.64.1:255.255.240.0:switch-2:eth0 root=/dev/nfs rw nfsroot=172.16.40.111:/boot/root-fs,timeo=200,retrans=500 nfsaddrs=172.16.40.114:172.16.40.111 +root_dev_setup:/dev/nfs or 00:ff +time_init: decrementer frequency = 16.501145 MHz +Calibrating delay loop... 175.71 BogoMIPS +Memory: 62572k available (1396k kernel code, 436k data, 100k init, 0k highmem) +Dentry cache hash table entries: 8192 (order: 4, 65536 bytes) +Inode cache hash table entries: 4096 (order: 3, 32768 bytes) +Mount-cache hash table entries: 1024 (order: 1, 8192 bytes) +Buffer-cache hash table entries: 4096 (order: 2, 16384 bytes) +Page-cache hash table entries: 16384 (order: 4, 65536 bytes) +POSIX conformance testing by UNIFIX +PCI: Probing PCI hardware +Linux NET4.0 for Linux 2.4 +Based upon Swansea University Computer Society NET3.039 +Initializing RT netlink socket +Starting kswapd +devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au) +devfs: devfs_debug: 0x0 +devfs: boot_options: 0x1 +Installing knfsd (copyright (C) 1996 okir@monad.swb.de). +pty: 256 Unix98 ptys configured +Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ SERIAL_PCI enabled +Testing ttyS0 (0xf7f51500, 0xf7f51500)... +Testing ttyS1 (0xfc004600, 0xfc004600)... +ttyS00 at 0xf7f51500 (irq = 24) is a ST16650 +ttyS01 at 0xfc004600 (irq = 25) is a 16550A +Real Time Clock Driver v1.10e +RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize +loop: loaded (max 8 devices) +TFFS 5.1.1 Flash disk driver for DiskOnChip +Copyright (C) 1998,2001 M-Systems Flash Disk Pioneers Ltd. +DOC device(s) found: 1 +fl_init: registered device at major: 100 +fl_geninit: registered device at major: 100 +Partition check: + fla: p1 +partition: /dev/fl/0: start_sect: 0,nr_sects: 32000 Fl_blk_size[]: 16000KB +partition: /dev/fl/1: start_sect: 2,nr_sects: 31998 Fl_blk_size[]: 15999KB +partition: /dev/fl/2: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB +partition: /dev/fl/3: start_sect: 0,nr_sects: 0 Fl_blk_size[]: 0KB +Broadcom Gigabit Ethernet Driver bcm5700 ver. 3.0.7 (07/17/02) +eth0: Broadcom BCM5701 found at mem bfff0000, IRQ 1, node addr 000010181010 +eth0: Broadcom BCM5701 Integrated Copper transceiver found +eth0: Scatter-gather ON, 64-bit DMA ON, Tx Checksum ON, Rx Checksum ON, 802.1Q VLAN ON +bond0 registered without MII link monitoring, in bonding mode. +rtc: unable to get misc minor +NET4: Linux TCP/IP 1.0 for NET4.0 +IP Protocols: ICMP, UDP, TCP, IGMP +IP: routing cache hash table of 512 buckets, 4Kbytes +TCP: Hash tables configured (established 4096 bind 4096) +bcm5700: eth0 NIC Link is UP, 100 Mbps half duplex +IP-Config: Gateway not on directly connected network. +NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. +802.1Q VLAN Support v1.7 Ben Greear <greearb@candelatech.com> +All bugs added by David S. Miller <davem@redhat.com> +Looking up port of RPC 100003/2 on 172.16.40.111 +Looking up port of RPC 100005/1 on 172.16.40.111 +VFS: Mounted root (nfs filesystem). +Mounted devfs on /dev +Freeing unused kernel memory: 100k init +INIT: version 2.78 booting +Mounting local filesystems... +not mounted anything +Setting up symlinks in /dev...done. +Setting up extra devices in /dev...done. +Starting devfsd...Started device management daemon for /dev +INIT: Entering runlevel: 2 +Starting internet superserver: inetd. + + +Welcome to Linux/PPC +MPC8245/BMW + + + +switch-2 login: root +Password: +PAM_unix[49]: (login) session opened for user root by LOGIN(uid=0) +Last login: Thu Nov 25 11:51:14 1920 on console + + +Welcome to Linux/PPC +MPC8245/BMW + + + +login[49]: ROOT LOGIN on `console' + +root@switch-2:~# cat /proc/cpuinfo +cpu             : 82xx +revision        : 16.20 (pvr 8081 1014) +bogomips        : 175.71 +vendor          : Broadcom +machine         : BMW/MPC8245 +root@switch-2:~# diff --git a/board/bmw/m48t59y.c b/board/bmw/m48t59y.c new file mode 100644 index 000000000..469f1adaf --- /dev/null +++ b/board/bmw/m48t59y.c @@ -0,0 +1,323 @@ +/* + * SGS M48-T59Y TOD/NVRAM Driver + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 1999, by Curt McDowell, 08-06-99, Broadcom Corp. + * + * (C) Copyright 2001, James Dougherty, 07/18/01, Broadcom Corp. + * + * 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 + */ + +/* + * SGS M48-T59Y TOD/NVRAM Driver + * + * The SGS M48 an 8K NVRAM starting at offset M48_BASE_ADDR and + * continuing for 8176 bytes. After that starts the Time-Of-Day (TOD) + * registers which are used to set/get the internal date/time functions. + * + * This module implements Y2K compliance by taking full year numbers + * and translating back and forth from the TOD 2-digit year. + * + * NOTE: for proper interaction with an operating system, the TOD should + * be used to store Universal Coordinated Time (GMT) and timezone + * conversions should be used. + * + * Here is a diagram of the memory layout: + * + * +---------------------------------------------+ 0xffe0a000 + * | Non-volatile memory                         | . + * |                                             | . + * | (8176 bytes of Non-volatile memory)         | . + * |                                             | . + * +---------------------------------------------+ 0xffe0bff0 + * | Flags                                       | + * +---------------------------------------------+ 0xffe0bff1 + * | Unused                                      | + * +---------------------------------------------+ 0xffe0bff2 + * | Alarm Seconds                               | + * +---------------------------------------------+ 0xffe0bff3 + * | Alarm Minutes                               | + * +---------------------------------------------+ 0xffe0bff4 + * | Alarm Date                                  | + * +---------------------------------------------+ 0xffe0bff5 + * | Interrupts                                  | + * +---------------------------------------------+ 0xffe0bff6 + * | WatchDog                                    | + * +---------------------------------------------+ 0xffe0bff7 + * | Calibration                                 | + * +---------------------------------------------+ 0xffe0bff8 + * | Seconds                                     | + * +---------------------------------------------+ 0xffe0bff9 + * | Minutes                                     | + * +---------------------------------------------+ 0xffe0bffa + * | Hours                                       | + * +---------------------------------------------+ 0xffe0bffb + * | Day                                         | + * +---------------------------------------------+ 0xffe0bffc + * | Date                                        | + * +---------------------------------------------+ 0xffe0bffd + * | Month                                       | + * +---------------------------------------------+ 0xffe0bffe + * | Year (2 digits only)                        | + * +---------------------------------------------+ 0xffe0bfff + */ +#include <common.h> +#include <rtc.h> +#include "bmw.h" + +/* + * Imported from mousse.h: + * + *   TOD_REG_BASE		Base of m48t59y TOD registers + *   SYS_TOD_UNPROTECT()	Disable NVRAM write protect + *   SYS_TOD_PROTECT()		Re-enable NVRAM write protect + */ + +#define YEAR		0xf +#define MONTH		0xe +#define DAY		0xd +#define DAY_OF_WEEK	0xc +#define HOUR		0xb +#define MINUTE		0xa +#define SECOND		0x9 +#define CONTROL		0x8 +#define WATCH		0x7 +#define INTCTL		0x6 +#define WD_DATE		0x5 +#define WD_HOUR		0x4 +#define WD_MIN		0x3 +#define WD_SEC		0x2 +#define _UNUSED		0x1 +#define FLAGS		0x0 + +#define M48_ADDR	((volatile unsigned char *) TOD_REG_BASE) + +int m48_tod_init(void) +{ +    SYS_TOD_UNPROTECT(); + +    M48_ADDR[CONTROL] = 0; +    M48_ADDR[WATCH] = 0; +    M48_ADDR[INTCTL] = 0; + +    /* +     * If the oscillator is currently stopped (as on a new part shipped +     * from the factory), start it running. +     * +     * Here is an example of the TOD bytes on a brand new M48T59Y part: +     *		00 00 00 00 00 00 00 00 00 88 8c c3 bf c8 f5 01 +     */ + +    if (M48_ADDR[SECOND] & 0x80) +	M48_ADDR[SECOND] = 0; + +    /* Is battery low */ +    if ( M48_ADDR[FLAGS] & 0x10) { +	 printf("NOTICE: Battery low on Real-Time Clock (replace SNAPHAT).\n"); +    } + +    SYS_TOD_PROTECT(); + +    return 0; +} + +/* + * m48_tod_set + */ + +static int to_bcd(int value) +{ +    return value / 10 * 16 + value % 10; +} + +static int from_bcd(int value) +{ +    return value / 16 * 10 + value % 16; +} + +static int day_of_week(int y, int m, int d)	/* 0-6 ==> Sun-Sat */ +{ +    static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; +    y -= m < 3; +    return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; +} + +/* + * Note: the TOD should store the current GMT + */ + +int m48_tod_set(int year,		/* 1980-2079 */ +		int month,		/* 01-12 */ +		int day,		/* 01-31 */ +		int hour,		/* 00-23 */ +		int minute,		/* 00-59 */ +		int second)		/* 00-59 */ + +{ +    SYS_TOD_UNPROTECT(); + +    M48_ADDR[CONTROL] |= 0x80;	/* Set WRITE bit */ + +    M48_ADDR[YEAR] = to_bcd(year % 100); +    M48_ADDR[MONTH] = to_bcd(month); +    M48_ADDR[DAY] = to_bcd(day); +    M48_ADDR[DAY_OF_WEEK] = day_of_week(year, month, day) + 1; +    M48_ADDR[HOUR] = to_bcd(hour); +    M48_ADDR[MINUTE] = to_bcd(minute); +    M48_ADDR[SECOND] = to_bcd(second); + +    M48_ADDR[CONTROL] &= ~0x80;	/* Clear WRITE bit */ + +    SYS_TOD_PROTECT(); + +    return 0; +} + +/* + * Note: the TOD should store the current GMT + */ + +int m48_tod_get(int *year,		/* 1980-2079 */ +		int *month,		/* 01-12 */ +		int *day,		/* 01-31 */ +		int *hour,		/* 00-23 */ +		int *minute,		/* 00-59 */ +		int *second)		/* 00-59 */ +{ +    int y; + +    SYS_TOD_UNPROTECT(); + +    M48_ADDR[CONTROL] |= 0x40;	/* Set READ bit */ + +    y = from_bcd(M48_ADDR[YEAR]); +    *year = y < 80 ? 2000 + y : 1900 + y; +    *month = from_bcd(M48_ADDR[MONTH]); +    *day = from_bcd(M48_ADDR[DAY]); +    /* day_of_week = M48_ADDR[DAY_OF_WEEK] & 0xf; */ +    *hour = from_bcd(M48_ADDR[HOUR]); +    *minute = from_bcd(M48_ADDR[MINUTE]); +    *second = from_bcd(M48_ADDR[SECOND] & 0x7f); + +    M48_ADDR[CONTROL] &= ~0x40;	/* Clear READ bit */ + +    SYS_TOD_PROTECT(); + +    return 0; +} + +int m48_tod_get_second(void) +{ +    return from_bcd(M48_ADDR[SECOND] & 0x7f); +} + +/* + * Watchdog function + * + *  If usec is 0, the watchdog timer is disarmed. + * + *  If usec is non-zero, the watchdog timer is armed (or re-armed) for + *    approximately usec microseconds (if the exact requested usec is + *    not supported by the chip, the next higher available value is used). + * + *  Minimum watchdog timeout = 62500 usec + *  Maximum watchdog timeout = 124 sec (124000000 usec) + */ + +void m48_watchdog_arm(int usec) +{ +    int		mpy, res; + +    SYS_TOD_UNPROTECT(); + +    if (usec == 0) { +	res = 0; +	mpy = 0; +    } else if (usec < 2000000) {	/* Resolution: 1/16s if below 2s */ +	res = 0; +	mpy = (usec + 62499) / 62500; +    } else if (usec < 8000000) {	/* Resolution: 1/4s if below 8s */ +	res = 1; +	mpy = (usec + 249999) / 250000; +    } else if (usec < 32000000) {	/* Resolution: 1s if below 32s */ +	res = 2; +	mpy = (usec + 999999) / 1000000; +    } else {				/* Resolution: 4s up to 124s */ +	res = 3; +	mpy = (usec + 3999999) / 4000000; +	if (mpy > 31) +	    mpy = 31; +    } + +    M48_ADDR[WATCH] = (0x80 |		/* Steer to RST signal (IRQ = N/C) */ +		       mpy << 2 | +		       res); + +    SYS_TOD_PROTECT(); +} + +/* + * U-Boot RTC support. + */ +void +rtc_get( struct rtc_time *tmp ) +{ +	m48_tod_get(&tmp->tm_year, +		    &tmp->tm_mon, +		    &tmp->tm_mday, +		    &tmp->tm_hour, +		    &tmp->tm_min, +		    &tmp->tm_sec); +	tmp->tm_yday = 0; +	tmp->tm_isdst= 0; + +#ifdef RTC_DEBUG +	printf( "Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n", +		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, +		tmp->tm_hour, tmp->tm_min, tmp->tm_sec ); +#endif +} + +void +rtc_set( struct rtc_time *tmp ) +{ +	m48_tod_set(tmp->tm_year,		/* 1980-2079 */ +		    tmp->tm_mon,		/* 01-12 */ +		    tmp->tm_mday,              /* 01-31 */ +		    tmp->tm_hour,		/* 00-23 */ +		    tmp->tm_min,		/* 00-59 */ +		    tmp->tm_sec);		/* 00-59 */ + +#ifdef RTC_DEBUG +	printf( "Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n", +		tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, +		tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + +} + +void +rtc_reset (void) +{ +  m48_tod_init(); +} + diff --git a/board/csb226/config.mk b/board/csb226/config.mk new file mode 100644 index 000000000..939ffffcf --- /dev/null +++ b/board/csb226/config.mk @@ -0,0 +1,16 @@ +# +# Linux-Kernel is expected to be at c000'8000, entry c000'8000 +# +# we load ourself to c170'0000, the upper 1 MB of second bank +# +# download areas is c800'0000 +# + +# This is the address where U-Boot lives in flash: +#TEXT_BASE = 0 + +# FIXME: armboot does only work correctly when being compiled +# for the addresses _after_ relocation to RAM!! Otherwhise the +# .bss segment is assumed in flash... +TEXT_BASE = 0xa1fe0000 + diff --git a/board/csb226/flash.c b/board/csb226/flash.c new file mode 100644 index 000000000..0b956480f --- /dev/null +++ b/board/csb226/flash.c @@ -0,0 +1,364 @@ +/* + * (C) Copyright 2002 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#define FLASH_BANK_SIZE 0x02000000 +#define MAIN_SECT_SIZE  0x40000         /* 2x16 = 256k per sector */ + +flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; + + +/*----------------------------------------------------------------------- + */ + +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_28F128J3 & 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); + +        switch (i) +        { +           case 0: +	        flashbase = PHYS_FLASH_1; +                break; +           default: +	        panic("configured to many flash banks!\n"); +                break; +        } +	for (j = 0; j < flash_info[i].sector_count; j++) +	{ +	    flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE; +	} +	size += flash_info[i].size; +    } + +    /* Protect monitor and environment sectors +     */ +    flash_protect(FLAG_PROTECT_SET, +		  CFG_FLASH_BASE, +		  CFG_FLASH_BASE + _armboot_end_data - _armboot_start, +		  &flash_info[0]); + +    flash_protect(FLAG_PROTECT_SET, +		  CFG_ENV_ADDR, +		  CFG_ENV_ADDR + CFG_ENV_SIZE - 1, +		  &flash_info[0]); + +    return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info  (flash_info_t *info) +{ +    int i, j; + +    for (j=0; j<CFG_MAX_FLASH_BANKS; j++) +    { +        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_28F128J3 & FLASH_TYPEMASK): +	        printf("28F128J3 (128Mbit)\n"); +	        break; +        default: +	        printf("Unknown Chip Type\n"); +	        goto Done; +	        break; +        } + +        printf("  Size: %ld MB in %d Sectors\n", +	        info->size >> 20, info->sector_count); + +        printf("  Sector Start Addresses:"); +        for (i = 0; i < info->sector_count; i++) +        { +	        if ((i % 5) == 0) +	        { +	        printf ("\n   "); +	        } +	        printf (" %08lX%s", info->start[i], +		        info->protect[i] ? " (RO)" : "     "); +        } +        printf ("\n"); +        info++; +    } + +Done: +} + +/*----------------------------------------------------------------------- + */ + +int	flash_erase (flash_info_t *info, int s_first, int s_last) +{ +    int flag, prot, sect; +    int rc = ERR_OK; + +    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) +	return ERR_PROTECTED; + +    /* +     * Disable interrupts which might cause a timeout +     * here. Remember that our exception vectors are +     * at address 0 in the flash, and we don't want a +     * (ticker) exception to happen while the flash +     * chip is in programming mode. +     */ +    flag = disable_interrupts(); + +    /* Start erase on unprotected sectors */ +    for (sect = s_first; sect<=s_last && !ctrlc(); sect++) { + +	printf("Erasing sector %2d ... ", sect); + +	/* arm simple, non interrupt dependent timer */ +	reset_timer_masked(); + +	if (info->protect[sect] == 0) {	/* not protected */ +	    /* vushort *addr = (vushort *)(info->start[sect]); */ +	    ushort *addr = (ushort *)(info->start[sect]); + +	    *addr = 0x20;	/* erase setup */ +	    *addr = 0xD0;	/* erase confirm */ + +	    while ((*addr & 0x80) != 0x80) { +		if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) { +		    *addr = 0xB0; /* suspend erase */ +		    *addr = 0xFF;	/* reset to read mode */ +		    rc = ERR_TIMOUT; +		    goto outahere; +		} +	    } + +	    /* clear status register command */ +	    *addr = 0x50; +	    /* reset to read mode */ +	    *addr = 0xFF; +	} +	printf("ok.\n"); +    } +    if (ctrlc()) +      printf("User Interrupt!\n"); + +outahere: + +    /* allow flash to settle - wait 10 ms */ +    udelay_masked(10000); + +    if (flag) +      enable_interrupts(); + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +static int write_word (flash_info_t *info, ulong dest, ushort data) +{ +    /* vushort *addr = (vushort *)dest, val; */ +    ushort *addr = (ushort *)dest, val; +    int rc = ERR_OK; +    int flag; + +    /* Check if Flash is (sufficiently) erased +     */ +    if ((*addr & 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. +     */ +    flag = disable_interrupts(); + +    /* clear status register command */ +    *addr = 0x50; + +    /* program set-up command */ +    *addr = 0x40; + +    /* latch address/data */ +    *addr = data; + +    /* arm simple, non interrupt dependent timer */ +    reset_timer_masked(); + +    /* wait while polling the status register */ +    while(((val = *addr) & 0x80) != 0x80) +    { +	if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) { +	    rc = ERR_TIMOUT; +	    /* suspend program command */ +	    *addr = 0xB0; +	    goto outahere; +	} +    } + +    if(val & 0x1A) {	/* check for error */ +        printf("\nFlash write error %02x at address %08lx\n", +    	   (int)val, (unsigned long)dest); +        if(val & (1<<3)) { +	    printf("Voltage range error.\n"); +	    rc = ERR_PROG_ERROR; +	    goto outahere; +        } +        if(val & (1<<1)) { +	    printf("Device protect error.\n"); +	    rc = ERR_PROTECTED; +	    goto outahere; +        } +        if(val & (1<<4)) { +	    printf("Programming error.\n"); +	    rc = ERR_PROG_ERROR; +	    goto outahere; +        } +        rc = ERR_PROG_ERROR; +        goto outahere; +    } + +outahere: +    /* read array command */ +    *addr = 0xFF; + +    if (flag) +      enable_interrupts(); + +    return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ +    ulong cp, wp; +    ushort data; +    int l; +    int i, rc; + +    wp = (addr & ~1);	/* get lower word aligned address */ + +    /* +     * handle unaligned start bytes +     */ +    if ((l = addr - wp) != 0) { +	data = 0; +	for (i=0, cp=wp; i<l; ++i, ++cp) { +	    data = (data >> 8) | (*(uchar *)cp << 8); +	} +	for (; i<2 && cnt>0; ++i) { +	    data = (data >> 8) | (*src++ << 8); +	    --cnt; +	    ++cp; +	} +	for (; cnt==0 && i<2; ++i, ++cp) { +	    data = (data >> 8) | (*(uchar *)cp << 8); +	} + +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	wp += 2; +    } + +    /* +     * handle word aligned part +     */ +    while (cnt >= 2) { +	/* data = *((vushort*)src); */ +	data = *((ushort*)src); +	if ((rc = write_word(info, wp, data)) != 0) { +	    return (rc); +	} +	src += 2; +	wp  += 2; +	cnt -= 2; +    } + +    if (cnt == 0) { +	return ERR_OK; +    } + +    /* +     * handle unaligned tail bytes +     */ +    data = 0; +    for (i=0, cp=wp; i<2 && cnt>0; ++i, ++cp) { +	data = (data >> 8) | (*src++ << 8); +	--cnt; +    } +    for (; i<2; ++i, ++cp) { +	data = (data >> 8) | (*(uchar *)cp << 8); +    } + +    return write_word(info, wp, data); +} |