[U-Boot] [PATCH 6/7] adding uC5282 dimm module support

David Wu davidwu at arcturusnetworks.com
Thu Apr 8 02:00:39 CEST 2010


Signed-off-by: David Wu <davidwu at arcturusnetworks.com>
---
  Makefile                          |   47 +
  board/Arcturus/uC5282/Makefile    |   44 +
  board/Arcturus/uC5282/cfm_flash.c |  201 ++++
  board/Arcturus/uC5282/cfm_flash.h |   42 +
  board/Arcturus/uC5282/config.mk   |   23 +
  board/Arcturus/uC5282/flash.c     | 2087  
+++++++++++++++++++++++++++++++++++++
  board/Arcturus/uC5282/u-boot.lds  |  140 +++
  board/Arcturus/uC5282/uC5282.c    |   98 ++
  include/configs/uC5282.h          |  299 ++++++
  9 files changed, 2981 insertions(+), 0 deletions(-)
  create mode 100644 board/Arcturus/uC5282/Makefile
  create mode 100644 board/Arcturus/uC5282/cfm_flash.c
  create mode 100644 board/Arcturus/uC5282/cfm_flash.h
  create mode 100644 board/Arcturus/uC5282/config.mk
  create mode 100644 board/Arcturus/uC5282/flash.c
  create mode 100644 board/Arcturus/uC5282/u-boot.lds
  create mode 100644 board/Arcturus/uC5282/uC5282.c
  create mode 100644 include/configs/uC5282.h

diff --git a/Makefile b/Makefile
index 6dad806..af3c3ff 100644
--- a/Makefile
+++ b/Makefile
@@ -2289,6 +2289,53 @@ uC5275-16EE32M150_config:	unconfig
  	fi ;
  	@$(MKCONFIG) -a uC5275 m68k mcf52x2 uC5275 Arcturus

+uC5282-4E16C64_config \
+uC5282-8E16C64_config \
+uC5282-16E16C64_config \
+uC5282-16E16C80_config :	unconfig
+	@mkdir -p $(obj)include
+	@if [ "$(findstring C80,$@)" ] ; then \
+		echo "#define SYSCLK_80MHZ " >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring C64,$@)" ] ; then \
+		echo "#define SYSCLK_64MHZ " >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring 4E,$@)" ] ; then \
+		echo "#define __4MFlash__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_FLASH_SIZE 0x00400000"  
>>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring 8E,$@)" ] ; then \
+		echo "#define __8MFlash__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_FLASH_SIZE 0x00800000"  
>>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring 16E,$@)" ] ; then \
+		echo "#define __16MFlash__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_FLASH_SIZE 0x01000000"  
>>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring 32E,$@)" ] ; then \
+		echo "#define __32MFlash__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_FLASH_SIZE 0x02000000"  
>>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_MAX_FLASH_BANKS 4" >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_MAX_FLASH_SECT 600" >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring E8,$@)" ] ; then \
+		echo "#define __8MRam__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_SDRAM_SIZE 8" >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring E16,$@)" ] ; then \
+		echo "#define __16MRam__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_SDRAM_SIZE 16" >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring E32,$@)" ] ; then \
+		echo "#define __32MRam__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_SDRAM_SIZE 32" >>$(obj)include/config.h ;\
+	fi ;
+	@if [ "$(findstring E64,$@)" ] ; then \
+		echo "#define __64MRam__ " >>$(obj)include/config.h ;\
+		echo "#define CONFIG_SYS_SDRAM_SIZE 64" >>$(obj)include/config.h ;\
+	fi ;
+	@$(MKCONFIG) -a uC5282 m68k mcf52x2 uC5282 Arcturus
+
  #########################################################################
  ## MPC83xx Systems
  #########################################################################
diff --git a/board/Arcturus/uC5282/Makefile  
b/board/Arcturus/uC5282/Makefile
new file mode 100644
index 0000000..44961b9
--- /dev/null
+++ b/board/Arcturus/uC5282/Makefile
@@ -0,0 +1,44 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd at 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	= $(obj)lib$(BOARD).a
+
+COBJS	= $(BOARD).o cfm_flash.o flash.o
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+SOBJS	:= $(addprefix $(obj),$(SOBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/Arcturus/uC5282/cfm_flash.c  
b/board/Arcturus/uC5282/cfm_flash.c
new file mode 100644
index 0000000..dcf7531
--- /dev/null
+++ b/board/Arcturus/uC5282/cfm_flash.c
@@ -0,0 +1,201 @@
+/*
+ * Basic Flash Driver for Freescale MCF 5281/5282 internal FLASH
+ *
+ * (C) Copyright 2005 BuS Elektronik GmbH & Co.KG <esw at bus-elektonik.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 <asm/m5282.h>
+#include  "cfm_flash.h"
+
+#if (CONFIG_SYS_CLK > 20000000)
+#define CFM_CLK  (((long) CONFIG_SYS_CLK / (400000 * 8) + 1) | 0x40)
+#else
+#define CFM_CLK  ((long) CONFIG_SYS_CLK / 400000 + 1)
+#endif
+
+#define cmf_backdoor_address(addr)	(((addr) & 0x0007FFFF) | 0x04000000 | \
+					 (CONFIG_SYS_MBAR & 0xC0000000))
+
+void cfm_flash_print_info(flash_info_t *info)
+{
+	printf("Freescale: ");
+	switch (info->flash_id & FLASH_TYPEMASK) {
+	case FREESCALE_ID_MCF5281 & FLASH_TYPEMASK:
+		printf("ColdFire Flash Module (CFM) internal FLASH\n");
+		break;
+	case FREESCALE_ID_MCF5282 & FLASH_TYPEMASK:
+		printf("ColdFire Flash Module (CFM) internal FLASH\n");
+		break;
+	default:
+		printf("Unknown Chip Type\n");
+		break;
+	}
+}
+
+void cfm_flash_init(flash_info_t *info)
+{
+	int sector;
+	ulong protection;
+	MCFCFM_MCR = 0;
+	MCFCFM_CLKD = CFM_CLK;
+	debug("CFM Clock divider: %ld (%d Hz @ %ld Hz)\n", CFM_CLK,
+	      CONFIG_SYS_CLK / (2 * ((CFM_CLK & 0x3F) + 1) *
+				(1 + ((CFM_CLK & 0x40) >> 6) * 7)),
+	      CONFIG_SYS_CLK);
+	MCFCFM_SACC = 0;
+	MCFCFM_DACC = 0;
+
+	if (MCFCFM_SEC & MCFCFM_SEC_KEYEN)
+		puts("CFM backdoor access is enabled\n");
+	if (MCFCFM_SEC & MCFCFM_SEC_SECSTAT)
+		puts("CFM securety is enabled\n");
+
+	info->vendor = FREESCALE_MANUFACT;
+	info->manufacturer_id = 0;
+	info->device_id = 0;
+	info->erase_blk_tout = 0;
+	info->write_tout = 0;
+	info->buffer_size = 1;
+#ifdef CONFIG_M5281
+	info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) |
+	    (FREESCALE_ID_MCF5281 & FLASH_TYPEMASK);
+	info->size = 256 * 1024;
+	info->sector_count = 16;
+#else
+	info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) |
+	    (FREESCALE_ID_MCF5282 & FLASH_TYPEMASK);
+	info->size = 512 * 1024;
+	info->sector_count = 32;
+#endif
+	protection = MCFCFM_PROT;
+	for (sector = 0; sector < info->sector_count; sector++) {
+		if (sector == 0)
+			info->start[sector] = CONFIG_SYS_INT_FLASH_BASE;
+		else
+			info->start[sector] = info->start[sector - 1] + 0x04000;
+
+		info->protect[sector] = protection & 1;
+		protection >>= 1;
+	}
+}
+
+int cfm_flash_readycheck(int checkblank)
+{
+	int rc;
+	unsigned char state;
+
+	rc = ERR_OK;
+	while (!(MCFCFM_USTAT & MCFCFM_USTAT_CCIF)) ;
+	state = MCFCFM_USTAT;
+	if (state & MCFCFM_USTAT_ACCERR) {
+		debug("%s(): CFM access error", __FUNCTION__);
+		rc = ERR_PROG_ERROR;
+	}
+	if (state & MCFCFM_USTAT_PVIOL) {
+		debug("%s(): CFM protection violation", __FUNCTION__);
+		rc = ERR_PROTECTED;
+	}
+	if (checkblank) {
+		if (!(state & MCFCFM_USTAT_BLANK)) {
+			debug("%s(): CFM erras error", __FUNCTION__);
+			rc = ERR_NOT_ERASED;
+		}
+	}
+	MCFCFM_USTAT = state & 0x34;	/* reset state */
+	return rc;
+}
+
+/* Erase 16KiB = 8 2KiB pages */
+
+int cfm_flash_erase_sector(flash_info_t *info, int sector)
+{
+	ulong address;
+	int page;
+	int rc;
+	rc = ERR_OK;
+	address = cmf_backdoor_address(info->start[sector]);
+	for (page = 0; (page < 8) && (rc == ERR_OK); page++) {
+		*(volatile __u32 *)address = 0;
+		MCFCFM_CMD = MCFCFM_CMD_PGERS;
+		MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
+		rc = cfm_flash_readycheck(0);
+		if (rc == ERR_OK) {
+			*(volatile __u32 *)address = 0;
+			MCFCFM_CMD = MCFCFM_CMD_PGERSVER;
+			MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
+			rc = cfm_flash_readycheck(1);
+		}
+		address += 0x800;
+	}
+	return rc;
+}
+
+int cfm_flash_write_buff(flash_info_t *info, uchar *src, ulong addr,
+			 ulong cnt)
+{
+	int rc;
+	ulong dest, data;
+
+	rc = ERR_OK;
+	if (addr & 3) {
+		debug("Byte and Word alignment not supported\n");
+		rc = ERR_ALIGN;
+	}
+	if (cnt & 3) {
+		debug("Byte and Word transfer not supported\n");
+		rc = ERR_ALIGN;
+	}
+	dest = cmf_backdoor_address(addr);
+	while ((cnt >= 4) && (rc == ERR_OK)) {
+		data = *((volatile u32 *)src);
+		*(volatile u32 *)dest = data;
+		MCFCFM_CMD = MCFCFM_CMD_PGM;
+		MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
+		rc = cfm_flash_readycheck(0);
+		if (*(volatile u32 *)addr != data)
+			rc = ERR_PROG_ERROR;
+		src += 4;
+		dest += 4;
+		addr += 4;
+		cnt -= 4;
+	}
+	return rc;
+}
+
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+
+int cfm_flash_protect(flash_info_t *info, long sector, int prot)
+{
+	int rc;
+
+	rc = ERR_OK;
+	if (prot) {
+		MCFCFM_PROT |= (1 << sector);
+		info->protect[sector] = 1;
+	} else {
+		MCFCFM_PROT &= ~(1 << sector);
+		info->protect[sector] = 0;
+	}
+	return rc;
+}
+
+#endif
diff --git a/board/Arcturus/uC5282/cfm_flash.h  
b/board/Arcturus/uC5282/cfm_flash.h
new file mode 100644
index 0000000..166f208
--- /dev/null
+++ b/board/Arcturus/uC5282/cfm_flash.h
@@ -0,0 +1,42 @@
+/*
+ * Basic Flash Driver for Freescale MCF 5282 internal FLASH
+ *
+ * (C) Copyright 2005 BuS Elektronik GmbH & Co.KG <esw at bus-elektonik.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
+ */
+
+#ifndef __CFM_FLASH_H_
+#define __CFM_FLASH_H_
+
+#define	FREESCALE_MANUFACT 0xFACFFACF
+#define	FREESCALE_VENDOR   0xFACF
+#define	FREESCALE_ID_MCF5281 0x5281
+#define	FREESCALE_ID_MCF5282 0x5282
+
+extern void cfm_flash_print_info(flash_info_t *info);
+extern int cfm_flash_erase_sector(flash_info_t *info, int sector);
+extern void cfm_flash_init(flash_info_t *info);
+extern int cfm_flash_write_buff(flash_info_t *info, uchar *src, ulong  
addr,
+				ulong cnt);
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+extern int cfm_flash_protect(flash_info_t *info, long sector, int prot);
+#endif
+
+#endif
diff --git a/board/Arcturus/uC5282/config.mk  
b/board/Arcturus/uC5282/config.mk
new file mode 100644
index 0000000..7f35d4a
--- /dev/null
+++ b/board/Arcturus/uC5282/config.mk
@@ -0,0 +1,23 @@
+#
+# (c) Copyright 2010 Arcturus Networks Inc.
+#     by David Wu <www.ArcturusNetworks.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+TEXT_BASE = 0xF0000000
diff --git a/board/Arcturus/uC5282/flash.c b/board/Arcturus/uC5282/flash.c
new file mode 100644
index 0000000..0bb9166
--- /dev/null
+++ b/board/Arcturus/uC5282/flash.c
@@ -0,0 +1,2087 @@
+/*
+ * (c) Copyright 2010 Arcturus Networks Inc.
+ *     by David Wu <www.ArcturusNetworks.com>
+ *
+ * Based on
+ * (C) Copyright 2005
+ * BuS Elektronik GmbH & Co.KG <esw at bus-elektonik.de>
+ *
+ * Based On
+ * Wolfgang Denk, DENX Software Engineering, wd at 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 "cfm_flash.h"
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <environment.h>
+
+#ifndef CONFIG_SYS_FLASH_BANKS_LIST
+#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
+#endif
+
+#define FLASH_CMD_CFI			0x98
+#define FLASH_CMD_READ_ID		0x90
+#define FLASH_CMD_RESET			0xff
+#define FLASH_CMD_BLOCK_ERASE		0x20
+#define FLASH_CMD_ERASE_CONFIRM		0xD0
+#define FLASH_CMD_WRITE			0x40
+#define FLASH_CMD_PROTECT		0x60
+#define FLASH_CMD_PROTECT_SET		0x01
+#define FLASH_CMD_PROTECT_CLEAR		0xD0
+#define FLASH_CMD_CLEAR_STATUS		0x50
+#define FLASH_CMD_READ_STATUS		0x70
+#define FLASH_CMD_WRITE_TO_BUFFER	0xE8
+#define FLASH_CMD_WRITE_BUFFER_PROG	0xE9
+#define FLASH_CMD_WRITE_BUFFER_CONFIRM	0xD0
+
+#define FLASH_STATUS_DONE		0x80
+#define FLASH_STATUS_ESS		0x40
+#define FLASH_STATUS_ECLBS		0x20
+#define FLASH_STATUS_PSLBS		0x10
+#define FLASH_STATUS_VPENS		0x08
+#define FLASH_STATUS_PSS		0x04
+#define FLASH_STATUS_DPS		0x02
+#define FLASH_STATUS_R			0x01
+#define FLASH_STATUS_PROTECT		0x01
+
+#define AMD_CMD_RESET			0xF0
+#define AMD_CMD_WRITE			0xA0
+#define AMD_CMD_ERASE_START		0x80
+#define AMD_CMD_ERASE_SECTOR		0x30
+#define AMD_CMD_UNLOCK_START		0xAA
+#define AMD_CMD_UNLOCK_ACK		0x55
+#define AMD_CMD_WRITE_TO_BUFFER		0x25
+#define AMD_CMD_WRITE_BUFFER_CONFIRM	0x29
+
+#define AMD_STATUS_TOGGLE		0x40
+#define AMD_STATUS_ERROR		0x20
+
+#define ATM_CMD_UNLOCK_SECT		0x70
+#define ATM_CMD_SOFTLOCK_START		0x80
+#define ATM_CMD_LOCK_SECT		0x40
+
+#define FLASH_OFFSET_MANUFACTURER_ID	0x00
+#define FLASH_OFFSET_DEVICE_ID		0x01
+#define FLASH_OFFSET_DEVICE_ID2		0x0E
+#define FLASH_OFFSET_DEVICE_ID3		0x0F
+#define FLASH_OFFSET_CFI		0x55
+#define FLASH_OFFSET_CFI_ALT		0x555
+#define FLASH_OFFSET_CFI_RESP		0x10
+#define FLASH_OFFSET_PRIMARY_VENDOR	0x13
+/* extended query table primary address */
+#define FLASH_OFFSET_EXT_QUERY_T_P_ADDR	0x15
+#define FLASH_OFFSET_WTOUT		0x1F
+#define FLASH_OFFSET_WBTOUT		0x20
+#define FLASH_OFFSET_ETOUT		0x21
+#define FLASH_OFFSET_CETOUT		0x22
+#define FLASH_OFFSET_WMAX_TOUT		0x23
+#define FLASH_OFFSET_WBMAX_TOUT		0x24
+#define FLASH_OFFSET_EMAX_TOUT		0x25
+#define FLASH_OFFSET_CEMAX_TOUT		0x26
+#define FLASH_OFFSET_SIZE		0x27
+#define FLASH_OFFSET_INTERFACE		0x28
+#define FLASH_OFFSET_BUFFER_SIZE	0x2A
+#define FLASH_OFFSET_NUM_ERASE_REGIONS	0x2C
+#define FLASH_OFFSET_ERASE_REGIONS	0x2D
+#define FLASH_OFFSET_PROTECT		0x02
+#define FLASH_OFFSET_USER_PROTECTION	0x85
+#define FLASH_OFFSET_INTEL_PROTECTION	0x81
+
+#define CFI_CMDSET_NONE			0
+#define CFI_CMDSET_INTEL_EXTENDED	1
+#define CFI_CMDSET_AMD_STANDARD		2
+#define CFI_CMDSET_INTEL_STANDARD	3
+#define CFI_CMDSET_AMD_EXTENDED		4
+#define CFI_CMDSET_MITSU_STANDARD	256
+#define CFI_CMDSET_MITSU_EXTENDED	257
+#define CFI_CMDSET_SST			258
+#define CFI_CMDSET_INTEL_PROG_REGIONS	512
+
+#ifdef CONFIG_SYS_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on  
UC100 */
+# undef  FLASH_CMD_RESET
+# define FLASH_CMD_RESET	AMD_CMD_RESET	/* use AMD-Reset instead */
+#endif
+
+typedef union {
+	unsigned char c;
+	unsigned short w;
+	unsigned long l;
+	unsigned long long ll;
+} cfiword_t;
+
+#define NUM_ERASE_REGIONS	4	/* max. number of erase regions */
+
+static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI,  
FLASH_OFFSET_CFI_ALT };
+static uint flash_verbose = 1;
+
+/* use CONFIG_SYS_MAX_FLASH_BANKS_DETECT if defined */
+#ifdef CONFIG_SYS_MAX_FLASH_BANKS_DETECT
+# define CFI_MAX_FLASH_BANKS	CONFIG_SYS_MAX_FLASH_BANKS_DETECT
+#else
+# define CFI_MAX_FLASH_BANKS	CONFIG_SYS_MAX_FLASH_BANKS
+#endif
+
+flash_info_t flash_info[CFI_MAX_FLASH_BANKS];	/* FLASH chips info */
+
+/*
+ * Check if chip width is defined. If not, start detecting with 8bit.
+ */
+#ifndef CONFIG_SYS_FLASH_CFI_WIDTH
+#define CONFIG_SYS_FLASH_CFI_WIDTH	FLASH_CFI_8BIT
+#endif
+
+/* CFI standard query structure */
+struct cfi_qry {
+	u8 qry[3];
+	u16 p_id;
+	u16 p_adr;
+	u16 a_id;
+	u16 a_adr;
+	u8 vcc_min;
+	u8 vcc_max;
+	u8 vpp_min;
+	u8 vpp_max;
+	u8 word_write_timeout_typ;
+	u8 buf_write_timeout_typ;
+	u8 block_erase_timeout_typ;
+	u8 chip_erase_timeout_typ;
+	u8 word_write_timeout_max;
+	u8 buf_write_timeout_max;
+	u8 block_erase_timeout_max;
+	u8 chip_erase_timeout_max;
+	u8 dev_size;
+	u16 interface_desc;
+	u16 max_buf_write_size;
+	u8 num_erase_regions;
+	u32 erase_region_info[NUM_ERASE_REGIONS];
+} __attribute__ ((packed));
+
+struct cfi_pri_hdr {
+	u8 pri[3];
+	u8 major_version;
+	u8 minor_version;
+} __attribute__ ((packed));
+
+static void __flash_write8(u8 value, void *addr)
+{
+	__raw_writeb(value, addr);
+}
+
+static void __flash_write16(u16 value, void *addr)
+{
+	__raw_writew(value, addr);
+}
+
+static void __flash_write32(u32 value, void *addr)
+{
+	__raw_writel(value, addr);
+}
+
+static void __flash_write64(u64 value, void *addr)
+{
+	/* No architectures currently implement __raw_writeq() */
+	*(volatile u64 *)addr = value;
+}
+
+static u8 __flash_read8(void *addr)
+{
+	return __raw_readb(addr);
+}
+
+static u16 __flash_read16(void *addr)
+{
+	return __raw_readw(addr);
+}
+
+static u32 __flash_read32(void *addr)
+{
+	return __raw_readl(addr);
+}
+
+static u64 __flash_read64(void *addr)
+{
+	/* No architectures currently implement __raw_readq() */
+	return *(volatile u64 *)addr;
+}
+
+#ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
+void flash_write8(u8 value, void *addr)
+    __attribute__ ((weak, alias("__flash_write8")));
+void flash_write16(u16 value, void *addr)
+    __attribute__ ((weak, alias("__flash_write16")));
+void flash_write32(u32 value, void *addr)
+    __attribute__ ((weak, alias("__flash_write32")));
+void flash_write64(u64 value, void *addr)
+    __attribute__ ((weak, alias("__flash_write64")));
+u8 flash_read8(void *addr) __attribute__ ((weak, alias("__flash_read8")));
+u16 flash_read16(void *addr) __attribute__ ((weak,  
alias("__flash_read16")));
+u32 flash_read32(void *addr) __attribute__ ((weak,  
alias("__flash_read32")));
+u64 flash_read64(void *addr) __attribute__ ((weak,  
alias("__flash_read64")));
+#else
+#define flash_write8	__flash_write8
+#define flash_write16	__flash_write16
+#define flash_write32	__flash_write32
+#define flash_write64	__flash_write64
+#define flash_read8	__flash_read8
+#define flash_read16	__flash_read16
+#define flash_read32	__flash_read32
+#define flash_read64	__flash_read64
+#endif
+int cfi_flash_erase(flash_info_t *info, int sect);
+void cfi_flash_print_info(flash_info_t *info);
+int cfi_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+int cfi_flash_real_protect(flash_info_t *info, long sector, int prot);
+
+/*-----------------------------------------------------------------------
+ */
+#if defined(CONFIG_ENV_IS_IN_FLASH) || defined(CONFIG_ENV_ADDR_REDUND) ||  
\
+	(CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE)
+flash_info_t *flash_get_info(ulong base)
+{
+	int i;
+	flash_info_t *info = 0;
+
+	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
+		info = &flash_info[i];
+		if (info->size && info->start[0] <= base &&
+		    base <= info->start[0] + info->size - 1)
+			break;
+	}
+
+	return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
+}
+#endif
+
+unsigned long flash_sector_size(flash_info_t *info, flash_sect_t sect)
+{
+	if (sect != (info->sector_count - 1))
+		return info->start[sect + 1] - info->start[sect];
+	else
+		return info->start[0] + info->size - info->start[sect];
+}
+
+/*-----------------------------------------------------------------------
+ * create an address based on the offset and the port width
+ */
+static inline void *flash_map(flash_info_t *info, flash_sect_t sect,
+			      uint offset)
+{
+	unsigned int byte_offset = offset * info->portwidth;
+
+	return (void *)(info->start[sect] + byte_offset);
+}
+
+static inline void flash_unmap(flash_info_t *info, flash_sect_t sect,
+			       unsigned int offset, void *addr)
+{
+}
+
+/*-----------------------------------------------------------------------
+ * make a proper sized command based on the port and chip widths
+ */
+static void flash_make_cmd(flash_info_t *info, u32 cmd, void *cmdbuf)
+{
+	int i;
+	int cword_offset;
+	int cp_offset;
+#if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+	u32 cmd_le = cpu_to_le32(cmd);
+#endif
+	uchar val;
+	uchar *cp = (uchar *) cmdbuf;
+
+	for (i = info->portwidth; i > 0; i--) {
+		cword_offset = (info->portwidth - i) % info->chipwidth;
+#if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+		cp_offset = info->portwidth - i;
+		val = *((uchar *) &cmd_le + cword_offset);
+#else
+		cp_offset = i - 1;
+		val = *((uchar *) &cmd + sizeof(u32) - cword_offset - 1);
+#endif
+		cp[cp_offset] = (cword_offset >= sizeof(u32)) ? 0x00 : val;
+	}
+}
+
+#ifdef DEBUG
+/*-----------------------------------------------------------------------
+ * Debug support
+ */
+static void print_longlong(char *str, unsigned long long data)
+{
+	int i;
+	char *cp;
+
+	cp = (char *)&data;
+	for (i = 0; i < 8; i++)
+		sprintf(&str[i * 2], "%2.2x", *cp++);
+}
+
+static void flash_printqry(struct cfi_qry *qry)
+{
+	u8 *p = (u8 *) qry;
+	int x, y;
+
+	for (x = 0; x < sizeof(struct cfi_qry); x += 16) {
+		debug("%02x : ", x);
+		for (y = 0; y < 16; y++)
+			debug("%2.2x ", p[x + y]);
+		debug(" ");
+		for (y = 0; y < 16; y++) {
+			unsigned char c = p[x + y];
+			if (c >= 0x20 && c <= 0x7e)
+				debug("%c", c);
+			else
+				debug(".");
+		}
+		debug("\n");
+	}
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ * read a character at a port width address
+ */
+static inline uchar flash_read_uchar(flash_info_t *info, uint offset)
+{
+	uchar *cp;
+	uchar retval;
+
+	cp = flash_map(info, 0, offset);
+#if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+	retval = flash_read8(cp);
+#else
+	retval = flash_read8(cp + info->portwidth - 1);
+#endif
+	flash_unmap(info, 0, offset, cp);
+	return retval;
+}
+
+/*-----------------------------------------------------------------------
+ * read a word at a port width address, assume 16bit bus
+ */
+static inline ushort flash_read_word(flash_info_t *info, uint offset)
+{
+	ushort *addr, retval;
+
+	addr = flash_map(info, 0, offset);
+	retval = flash_read16(addr);
+	flash_unmap(info, 0, offset, addr);
+	return retval;
+}
+
+/*-----------------------------------------------------------------------
+ * read a long word by picking the least significant byte of each maximum
+ * port size word. Swap for ppc format.
+ */
+static ulong flash_read_long(flash_info_t *info, flash_sect_t sect,
+			     uint offset)
+{
+	uchar *addr;
+	ulong retval;
+
+#ifdef DEBUG
+	int x;
+#endif
+	addr = flash_map(info, sect, offset);
+
+#ifdef DEBUG
+	debug("long addr is at %p info->portwidth = %d\n", addr,
+	      info->portwidth);
+	for (x = 0; x < 4 * info->portwidth; x++)
+		debug("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
+
+#endif
+#if defined(__LITTLE_ENDIAN) || defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+	retval = ((flash_read8(addr) << 16) |
+		  (flash_read8(addr + info->portwidth) << 24) |
+		  (flash_read8(addr + 2 * info->portwidth)) |
+		  (flash_read8(addr + 3 * info->portwidth) << 8));
+#else
+	retval = ((flash_read8(addr + 2 * info->portwidth - 1) << 24) |
+		  (flash_read8(addr + info->portwidth - 1) << 16) |
+		  (flash_read8(addr + 4 * info->portwidth - 1) << 8) |
+		  (flash_read8(addr + 3 * info->portwidth - 1)));
+#endif
+	flash_unmap(info, sect, offset, addr);
+
+	return retval;
+}
+
+/*
+ * Write a proper sized command to the correct address
+ */
+static void flash_write_cmd(flash_info_t *info, flash_sect_t sect,
+			    uint offset, u32 cmd)
+{
+
+	void *addr;
+	cfiword_t cword;
+
+	addr = flash_map(info, sect, offset);
+	flash_make_cmd(info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		debug("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
+		      cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write8(cword.c, addr);
+		break;
+	case FLASH_CFI_16BIT:
+		debug("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
+		      cmd, cword.w, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write16(cword.w, addr);
+		break;
+	case FLASH_CFI_32BIT:
+		debug("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
+		      cmd, cword.l, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write32(cword.l, addr);
+		break;
+	case FLASH_CFI_64BIT:
+#ifdef DEBUG
+		{
+			char str[20];
+
+			print_longlong(str, cword.ll);
+
+			debug("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
+			      addr, cmd, str,
+			      info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		}
+#endif
+		flash_write64(cword.ll, addr);
+		break;
+	}
+
+	/* Ensure all the instructions are fully finished */
+	sync();
+
+	flash_unmap(info, sect, offset, addr);
+}
+
+static void flash_unlock_seq(flash_info_t *info, flash_sect_t sect)
+{
+	flash_write_cmd(info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START);
+	flash_write_cmd(info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_isequal(flash_info_t *info, flash_sect_t sect,
+			 uint offset, uchar cmd)
+{
+	void *addr;
+	cfiword_t cword;
+	int retval;
+
+	addr = flash_map(info, sect, offset);
+	flash_make_cmd(info, cmd, &cword);
+
+	debug("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		debug("is= %x %x\n", flash_read8(addr), cword.c);
+		retval = (flash_read8(addr) == cword.c);
+		break;
+	case FLASH_CFI_16BIT:
+		debug("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
+		retval = (flash_read16(addr) == cword.w);
+		break;
+	case FLASH_CFI_32BIT:
+		debug("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l);
+		retval = (flash_read32(addr) == cword.l);
+		break;
+	case FLASH_CFI_64BIT:
+#ifdef DEBUG
+		{
+			char str1[20];
+			char str2[20];
+
+			print_longlong(str1, flash_read64(addr));
+			print_longlong(str2, cword.ll);
+			debug("is= %s %s\n", str1, str2);
+		}
+#endif
+		retval = (flash_read64(addr) == cword.ll);
+		break;
+	default:
+		retval = 0;
+		break;
+	}
+	flash_unmap(info, sect, offset, addr);
+
+	return retval;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_isset(flash_info_t *info, flash_sect_t sect,
+		       uint offset, uchar cmd)
+{
+	void *addr;
+	cfiword_t cword;
+	int retval;
+
+	addr = flash_map(info, sect, offset);
+	flash_make_cmd(info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		retval = ((flash_read8(addr) & cword.c) == cword.c);
+		break;
+	case FLASH_CFI_16BIT:
+		retval = ((flash_read16(addr) & cword.w) == cword.w);
+		break;
+	case FLASH_CFI_32BIT:
+		retval = ((flash_read32(addr) & cword.l) == cword.l);
+		break;
+	case FLASH_CFI_64BIT:
+		retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+		break;
+	default:
+		retval = 0;
+		break;
+	}
+	flash_unmap(info, sect, offset, addr);
+
+	return retval;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_toggle(flash_info_t *info, flash_sect_t sect,
+			uint offset, uchar cmd)
+{
+	void *addr;
+	cfiword_t cword;
+	int retval;
+
+	addr = flash_map(info, sect, offset);
+	flash_make_cmd(info, cmd, &cword);
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		retval = flash_read8(addr) != flash_read8(addr);
+		break;
+	case FLASH_CFI_16BIT:
+		retval = flash_read16(addr) != flash_read16(addr);
+		break;
+	case FLASH_CFI_32BIT:
+		retval = flash_read32(addr) != flash_read32(addr);
+		break;
+	case FLASH_CFI_64BIT:
+		retval = ((flash_read32(addr) != flash_read32(addr)) ||
+			  (flash_read32(addr + 4) != flash_read32(addr + 4)));
+		break;
+	default:
+		retval = 0;
+		break;
+	}
+	flash_unmap(info, sect, offset, addr);
+
+	return retval;
+}
+
+/*
+ * flash_is_busy - check to see if the flash is busy
+ *
+ * This routine checks the status of the chip and returns true if the
+ * chip is busy.
+ */
+static int flash_is_busy(flash_info_t *info, flash_sect_t sect)
+{
+	int retval;
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		retval = !flash_isset(info, sect, 0, FLASH_STATUS_DONE);
+		break;
+	case CFI_CMDSET_AMD_STANDARD:
+	case CFI_CMDSET_AMD_EXTENDED:
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+#endif
+		retval = flash_toggle(info, sect, 0, AMD_STATUS_TOGGLE);
+		break;
+	default:
+		retval = 0;
+	}
+	debug("flash_is_busy: %d\n", retval);
+	return retval;
+}
+
+/*-----------------------------------------------------------------------
+ *  wait for XSR.7 to be set. Time out with an error if it does not.
+ *  This routine does not set the flash to read-array mode.
+ */
+static int flash_status_check(flash_info_t *info, flash_sect_t sector,
+			      ulong tout, char *prompt)
+{
+	ulong start;
+
+#if CONFIG_SYS_HZ != 1000
+	tout *= CONFIG_SYS_HZ / 1000;
+#endif
+
+	/* Wait for command completion */
+	start = get_timer(0);
+	while (flash_is_busy(info, sector)) {
+		if (get_timer(start) > tout) {
+			printf("Flash %s timeout at address %lx data %lx\n",
+			       prompt, info->start[sector],
+			       flash_read_long(info, sector, 0));
+			flash_write_cmd(info, sector, 0, info->cmd_reset);
+			return ERR_TIMOUT;
+		}
+		udelay(1);	/* also triggers watchdog */
+	}
+	return ERR_OK;
+}
+
+/*-----------------------------------------------------------------------
+ * Wait for XSR.7 to be set, if it times out print an error, otherwise
+ * do a full status check.
+ *
+ * This routine sets the flash to read-array mode.
+ */
+static int flash_full_status_check(flash_info_t *info, flash_sect_t  
sector,
+				   ulong tout, char *prompt)
+{
+	int retcode;
+
+	retcode = flash_status_check(info, sector, tout, prompt);
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_EXTENDED:
+	case CFI_CMDSET_INTEL_STANDARD:
+		if ((retcode != ERR_OK)
+		    && !flash_isequal(info, sector, 0, FLASH_STATUS_DONE)) {
+			retcode = ERR_INVAL;
+			printf("Flash %s error at address %lx\n", prompt,
+			       info->start[sector]);
+			if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS |
+					FLASH_STATUS_PSLBS)) {
+				puts("Command Sequence Error.\n");
+			} else if (flash_isset(info, sector, 0,
+					       FLASH_STATUS_ECLBS)) {
+				puts("Block Erase Error.\n");
+				retcode = ERR_NOT_ERASED;
+			} else if (flash_isset(info, sector, 0,
+					       FLASH_STATUS_PSLBS)) {
+				puts("Locking Error\n");
+			}
+			if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
+				puts("Block locked.\n");
+				retcode = ERR_PROTECTED;
+			}
+			if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
+				puts("Vpp Low Error.\n");
+		}
+		flash_write_cmd(info, sector, 0, info->cmd_reset);
+		break;
+	default:
+		break;
+	}
+	return retcode;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_add_byte(flash_info_t *info, cfiword_t *cword, uchar c)
+{
+#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+	unsigned short w;
+	unsigned int l;
+	unsigned long long ll;
+#endif
+
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		cword->c = c;
+		break;
+	case FLASH_CFI_16BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+		w = c;
+		w <<= 8;
+		cword->w = (cword->w >> 8) | w;
+#else
+		cword->w = (cword->w << 8) | c;
+#endif
+		break;
+	case FLASH_CFI_32BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+		l = c;
+		l <<= 24;
+		cword->l = (cword->l >> 8) | l;
+#else
+		cword->l = (cword->l << 8) | c;
+#endif
+		break;
+	case FLASH_CFI_64BIT:
+#if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
+		ll = c;
+		ll <<= 56;
+		cword->ll = (cword->ll >> 8) | ll;
+#else
+		cword->ll = (cword->ll << 8) | c;
+#endif
+		break;
+	}
+}
+
+/*
+ * Loop through the sector table starting from the previously found  
sector.
+ * Searches forwards or backwards, dependent on the passed address.
+ */
+static flash_sect_t find_sector(flash_info_t *info, ulong addr)
+{
+	static flash_sect_t saved_sector;	/* previously found sector */
+	flash_sect_t sector = saved_sector;
+
+	while ((info->start[sector] < addr)
+	       && (sector < info->sector_count - 1))
+		sector++;
+	while ((info->start[sector] > addr) && (sector > 0))
+		/*
+		 * also decrements the sector in case of an overshot
+		 * in the first loop
+		 */
+		sector--;
+
+	saved_sector = sector;
+	return sector;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int flash_write_cfiword(flash_info_t *info, ulong dest, cfiword_t  
cword)
+{
+	void *dstaddr = (void *)dest;
+	int flag;
+	flash_sect_t sect = 0;
+	char sect_found = 0;
+
+	/* Check if Flash is (sufficiently) erased */
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
+		break;
+	case FLASH_CFI_16BIT:
+		flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
+		break;
+	case FLASH_CFI_32BIT:
+		flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
+		break;
+	case FLASH_CFI_64BIT:
+		flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
+		break;
+	default:
+		flag = 0;
+		break;
+	}
+	if (!flag)
+		return ERR_NOT_ERASED;
+
+	/* Disable interrupts which might cause a timeout here */
+	flag = disable_interrupts();
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_EXTENDED:
+	case CFI_CMDSET_INTEL_STANDARD:
+		flash_write_cmd(info, 0, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd(info, 0, 0, FLASH_CMD_WRITE);
+		break;
+	case CFI_CMDSET_AMD_EXTENDED:
+	case CFI_CMDSET_AMD_STANDARD:
+		sect = find_sector(info, dest);
+		flash_unlock_seq(info, sect);
+		flash_write_cmd(info, sect, info->addr_unlock1, AMD_CMD_WRITE);
+		sect_found = 1;
+		break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+		sect = find_sector(info, dest);
+		flash_unlock_seq(info, 0);
+		flash_write_cmd(info, 0, info->addr_unlock1, AMD_CMD_WRITE);
+		sect_found = 1;
+		break;
+#endif
+	}
+
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		flash_write8(cword.c, dstaddr);
+		break;
+	case FLASH_CFI_16BIT:
+		flash_write16(cword.w, dstaddr);
+		break;
+	case FLASH_CFI_32BIT:
+		flash_write32(cword.l, dstaddr);
+		break;
+	case FLASH_CFI_64BIT:
+		flash_write64(cword.ll, dstaddr);
+		break;
+	}
+
+	/* re-enable interrupts if necessary */
+	if (flag)
+		enable_interrupts();
+
+	if (!sect_found)
+		sect = find_sector(info, dest);
+
+	return flash_full_status_check(info, sect, info->write_tout, "write");
+}
+
+#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+
+static int flash_write_cfibuffer(flash_info_t *info, ulong dest, uchar  
*cp,
+				 int len)
+{
+	flash_sect_t sector;
+	int cnt;
+	int retcode;
+	void *src = cp;
+	void *dst = (void *)dest;
+	void *dst2 = dst;
+	int flag = 0;
+	uint offset = 0;
+	unsigned int shift;
+	uchar write_cmd;
+
+	switch (info->portwidth) {
+	case FLASH_CFI_8BIT:
+		shift = 0;
+		break;
+	case FLASH_CFI_16BIT:
+		shift = 1;
+		break;
+	case FLASH_CFI_32BIT:
+		shift = 2;
+		break;
+	case FLASH_CFI_64BIT:
+		shift = 3;
+		break;
+	default:
+		retcode = ERR_INVAL;
+		goto out_unmap;
+	}
+
+	cnt = len >> shift;
+
+	while ((cnt-- > 0) && (flag == 0)) {
+		switch (info->portwidth) {
+		case FLASH_CFI_8BIT:
+			flag = ((flash_read8(dst2) & flash_read8(src)) ==
+				flash_read8(src));
+			src += 1, dst2 += 1;
+			break;
+		case FLASH_CFI_16BIT:
+			flag = ((flash_read16(dst2) & flash_read16(src)) ==
+				flash_read16(src));
+			src += 2, dst2 += 2;
+			break;
+		case FLASH_CFI_32BIT:
+			flag = ((flash_read32(dst2) & flash_read32(src)) ==
+				flash_read32(src));
+			src += 4, dst2 += 4;
+			break;
+		case FLASH_CFI_64BIT:
+			flag = ((flash_read64(dst2) & flash_read64(src)) ==
+				flash_read64(src));
+			src += 8, dst2 += 8;
+			break;
+		}
+	}
+	if (!flag) {
+		retcode = ERR_NOT_ERASED;
+		goto out_unmap;
+	}
+
+	src = cp;
+	sector = find_sector(info, dest);
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		write_cmd = (info->vendor == CFI_CMDSET_INTEL_PROG_REGIONS) ?
+		    FLASH_CMD_WRITE_BUFFER_PROG : FLASH_CMD_WRITE_TO_BUFFER;
+		flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd(info, sector, 0, FLASH_CMD_READ_STATUS);
+		flash_write_cmd(info, sector, 0, write_cmd);
+		retcode = flash_status_check(info, sector,
+					     info->buffer_write_tout,
+					     "write to buffer");
+		if (retcode == ERR_OK) {
+			/* reduce the number of loops by the width of
+			 * the port */
+			cnt = len >> shift;
+			flash_write_cmd(info, sector, 0, cnt - 1);
+			while (cnt-- > 0) {
+				switch (info->portwidth) {
+				case FLASH_CFI_8BIT:
+					flash_write8(flash_read8(src), dst);
+					src += 1, dst += 1;
+					break;
+				case FLASH_CFI_16BIT:
+					flash_write16(flash_read16(src), dst);
+					src += 2, dst += 2;
+					break;
+				case FLASH_CFI_32BIT:
+					flash_write32(flash_read32(src), dst);
+					src += 4, dst += 4;
+					break;
+				case FLASH_CFI_64BIT:
+					flash_write64(flash_read64(src), dst);
+					src += 8, dst += 8;
+					break;
+				default:
+					retcode = ERR_INVAL;
+					goto out_unmap;
+				}
+			}
+			flash_write_cmd(info, sector, 0,
+					FLASH_CMD_WRITE_BUFFER_CONFIRM);
+			retcode =
+			    flash_full_status_check(info, sector,
+						    info->buffer_write_tout,
+						    "buffer write");
+		}
+
+		break;
+
+	case CFI_CMDSET_AMD_STANDARD:
+	case CFI_CMDSET_AMD_EXTENDED:
+		flash_unlock_seq(info, 0);
+
+#ifdef CONFIG_FLASH_SPANSION_S29WS_N
+		offset = ((unsigned long)dst - info->start[sector]) >> shift;
+#endif
+		flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);
+		cnt = len >> shift;
+		flash_write_cmd(info, sector, offset, cnt - 1);
+
+		switch (info->portwidth) {
+		case FLASH_CFI_8BIT:
+			while (cnt-- > 0) {
+				flash_write8(flash_read8(src), dst);
+				src += 1, dst += 1;
+			}
+			break;
+		case FLASH_CFI_16BIT:
+			while (cnt-- > 0) {
+				flash_write16(flash_read16(src), dst);
+				src += 2, dst += 2;
+			}
+			break;
+		case FLASH_CFI_32BIT:
+			while (cnt-- > 0) {
+				flash_write32(flash_read32(src), dst);
+				src += 4, dst += 4;
+			}
+			break;
+		case FLASH_CFI_64BIT:
+			while (cnt-- > 0) {
+				flash_write64(flash_read64(src), dst);
+				src += 8, dst += 8;
+			}
+			break;
+		default:
+			retcode = ERR_INVAL;
+			goto out_unmap;
+		}
+
+		flash_write_cmd(info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+		retcode = flash_full_status_check(info, sector,
+						  info->buffer_write_tout,
+						  "buffer write");
+		break;
+
+	default:
+		debug("Unknown Command Set\n");
+		retcode = ERR_INVAL;
+		break;
+	}
+
+out_unmap:
+	return retcode;
+}
+#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
+
+/*-----------------------------------------------------------------------
+ */
+int flash_erase(flash_info_t *info, int s_first, int s_last)
+{
+	int iflag, cflag;
+	int sector;
+	int rc;
+
+	rc = ERR_OK;
+
+	if (info->flash_id == FLASH_UNKNOWN)
+		rc = ERR_UNKNOWN_FLASH_TYPE;
+
+	/* (info->flash_id == FLASH_UNKNOWN) */
+	if ((s_first < 0) || (s_first > s_last) || s_last >= info->sector_count)
+		rc = ERR_INVAL;
+
+	cflag = icache_status();
+	icache_disable();
+	iflag = disable_interrupts();
+
+	for (sector = s_first; (sector <= s_last) && (rc == ERR_OK); sector++) {
+
+		if (info->protect[sector]) {
+			putc('P');	/*  protected sector will not erase */
+		} else {
+			/* erase on unprotected sector */
+			puts("E\b");
+			switch (info->flash_id & FLASH_VENDMASK) {
+			case (FREESCALE_MANUFACT & FLASH_VENDMASK):
+				rc = cfm_flash_erase_sector(info, sector);
+				break;
+			default:
+				rc = cfi_flash_erase(info, sector);
+			}
+			putc('.');
+		}
+	}
+	if (rc != ERR_OK) {
+		printf("\n   ");
+		flash_perror(rc);
+	} else {
+		printf(" done\n");
+	}
+
+	udelay(10000);		/* allow flash to settle - wait 10 ms */
+
+	if (iflag)
+		enable_interrupts();
+
+	if (cflag)
+		icache_enable();
+
+	return rc;
+}
+
+int cfi_flash_erase(flash_info_t *info, int sect)
+{
+	int rcode = 0;
+
+	{
+		if (info->protect[sect] == 0) {	/* not protected */
+			switch (info->vendor) {
+			case CFI_CMDSET_INTEL_PROG_REGIONS:
+			case CFI_CMDSET_INTEL_STANDARD:
+			case CFI_CMDSET_INTEL_EXTENDED:
+				flash_write_cmd(info, sect, 0,
+						FLASH_CMD_CLEAR_STATUS);
+				flash_write_cmd(info, sect, 0,
+						FLASH_CMD_BLOCK_ERASE);
+				flash_write_cmd(info, sect, 0,
+						FLASH_CMD_ERASE_CONFIRM);
+				break;
+			case CFI_CMDSET_AMD_STANDARD:
+			case CFI_CMDSET_AMD_EXTENDED:
+				flash_unlock_seq(info, sect);
+				flash_write_cmd(info, sect,
+						info->addr_unlock1,
+						AMD_CMD_ERASE_START);
+				flash_unlock_seq(info, sect);
+				flash_write_cmd(info, sect, 0,
+						AMD_CMD_ERASE_SECTOR);
+				break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+			case CFI_CMDSET_AMD_LEGACY:
+				flash_unlock_seq(info, 0);
+				flash_write_cmd(info, 0, info->addr_unlock1,
+						AMD_CMD_ERASE_START);
+				flash_unlock_seq(info, 0);
+				flash_write_cmd(info, sect, 0,
+						AMD_CMD_ERASE_SECTOR);
+				break;
+#endif
+			default:
+				debug("Unkown flash vendor %d\n", info->vendor);
+				break;
+			}
+
+			if (flash_full_status_check
+			    (info, sect, info->erase_blk_tout, "erase")) {
+				rcode = 1;
+			}
+		}
+	}
+
+	return rcode;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+void flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case FREESCALE_MANUFACT & FLASH_VENDMASK:
+		cfm_flash_print_info(info);
+		break;
+	default:
+		return cfi_flash_print_info(info);
+		break;
+	}
+
+	puts("  Size: ");
+	if ((info->size >> 20) > 0)
+		printf("%ld MiB", info->size >> 20);
+	else
+		printf("%ld KiB", info->size >> 10);
+	printf(" in %d Sectors\n", info->sector_count);
+
+	printf("  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; i++) {
+		if ((i % 4) == 0)
+			printf("\n    ");
+		printf("%02d: %08lX%s  ", i, info->start[i],
+		       info->protect[i] ? " P" : "  ");
+	}
+	printf("\n\n");
+}
+
+void cfi_flash_print_info(flash_info_t *info)
+{
+	int i;
+
+	if (info->flash_id != FLASH_MAN_CFI) {
+		puts("missing or unknown FLASH type\n");
+		return;
+	}
+
+	printf("%s FLASH (%d x %d)",
+	       info->name, (info->portwidth << 3), (info->chipwidth << 3));
+	if (info->size < 1024 * 1024)
+		printf("  Size: %ld kB in %d Sectors\n",
+		       info->size >> 10, info->sector_count);
+	else
+		printf("  Size: %ld MB in %d Sectors\n",
+		       info->size >> 20, info->sector_count);
+	printf("  ");
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+		printf("Intel Prog Regions");
+		break;
+	case CFI_CMDSET_INTEL_STANDARD:
+		printf("Intel Standard");
+		break;
+	case CFI_CMDSET_INTEL_EXTENDED:
+		printf("Intel Extended");
+		break;
+	case CFI_CMDSET_AMD_STANDARD:
+		printf("AMD Standard");
+		break;
+	case CFI_CMDSET_AMD_EXTENDED:
+		printf("AMD Extended");
+		break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+		printf("AMD Legacy");
+		break;
+#endif
+	default:
+		printf("Unknown (%d)", info->vendor);
+		break;
+	}
+	printf(" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
+	       info->manufacturer_id, info->device_id);
+	if (info->device_id == 0x7E)
+		printf("%04X", info->device_id2);
+	printf("\n  Erase timeout: %ld ms, write timeout: %ld ms\n",
+	       info->erase_blk_tout, info->write_tout);
+	if (info->buffer_size > 1) {
+		printf("  Buffer write timeout: %ld ms, "
+		       "buffer size: %d bytes\n",
+		       info->buffer_write_tout, info->buffer_size);
+	}
+
+	puts("\n  Sector Start Addresses:");
+	for (i = 0; i < info->sector_count; ++i) {
+		if ((i % 5) == 0)
+			printf("\n");
+#ifdef CONFIG_SYS_FLASH_EMPTY_INFO
+		int k;
+		int size;
+		int erased;
+		volatile unsigned long *flash;
+
+		/*
+		 * Check if whole sector is erased
+		 */
+		size = flash_sector_size(info, i);
+		erased = 1;
+		flash = (volatile unsigned long *)info->start[i];
+		size = size >> 2;	/* divide by 4 for longword access */
+		for (k = 0; k < size; k++) {
+			if (*flash++ != 0xffffffff) {
+				erased = 0;
+				break;
+			}
+		}
+
+		/* print empty and read-only info */
+		printf("  %08lX %c %s ",
+		       info->start[i],
+		       erased ? 'E' : ' ', info->protect[i] ? "RO" : "  ");
+#else /* ! CONFIG_SYS_FLASH_EMPTY_INFO */
+		printf("  %08lX   %s ",
+		       info->start[i], info->protect[i] ? "RO" : "  ");
+#endif
+	}
+	putc('\n');
+	return;
+}
+
+/*-----------------------------------------------------------------------
+ * This is used in a few places in write_buf() to show programming
+ * progress.  Making it a function is nasty because it needs to do side
+ * effect updates to digit and dots.  Repeated code is nasty too, so
+ * we define it once here.
+ */
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
+	if (flash_verbose) { \
+		dots -= dots_sub; \
+		if ((scale > 0) && (dots <= 0)) { \
+			if ((digit % 5) == 0) \
+				printf("%d", digit / 5); \
+			else \
+				putc('.'); \
+			digit--; \
+			dots += scale; \
+		} \
+	}
+#else
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub)
+#endif
+
+/*-----------------------------------------------------------------------
+ * 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)
+{
+	int rc;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case (FREESCALE_MANUFACT & FLASH_VENDMASK):
+		rc = cfm_flash_write_buff(info, src, addr, cnt);
+		break;
+	default:
+		rc = cfi_write_buff(info, src, addr, cnt);
+		break;
+	}
+	return rc;
+
+}
+
+int cfi_write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+	ulong wp;
+	uchar *p;
+	int aln;
+	cfiword_t cword;
+	int i, rc;
+#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+	int buffered_size;
+#endif
+
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+	int digit = CONFIG_FLASH_SHOW_PROGRESS;
+	int scale = 0;
+	int dots = 0;
+
+	/*
+	 * Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes.
+	 */
+	if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) {
+		scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) /
+			      CONFIG_FLASH_SHOW_PROGRESS);
+	}
+#endif
+
+	/* get lower aligned address */
+	wp = (addr & ~(info->portwidth - 1));
+
+	/* handle unaligned start */
+	aln = addr - wp;
+	if (aln) {
+		cword.l = 0;
+		p = (uchar *) wp;
+		for (i = 0; i < aln; ++i)
+			flash_add_byte(info, &cword, flash_read8(p + i));
+
+		for (; (i < info->portwidth) && (cnt > 0); i++) {
+			flash_add_byte(info, &cword, *src++);
+			cnt--;
+		}
+		for (; (cnt == 0) && (i < info->portwidth); ++i)
+			flash_add_byte(info, &cword, flash_read8(p + i));
+
+		rc = flash_write_cfiword(info, wp, cword);
+		if (rc != 0)
+			return rc;
+
+		wp += i;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, i);
+	}
+
+	/* handle the aligned part */
+#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+	buffered_size = (info->portwidth / info->chipwidth);
+	buffered_size *= info->buffer_size;
+	while (cnt >= info->portwidth) {
+		/* prohibit buffer write when buffer_size is 1 */
+		if (info->buffer_size == 1) {
+			cword.l = 0;
+			for (i = 0; i < info->portwidth; i++)
+				flash_add_byte(info, &cword, *src++);
+			rc = flash_write_cfiword(info, wp, cword);
+			if (rc)
+				return rc;
+			wp += info->portwidth;
+			cnt -= info->portwidth;
+			continue;
+		}
+
+		/* write buffer until next buffered_size aligned boundary */
+		i = buffered_size - (wp % buffered_size);
+		if (i > cnt)
+			i = cnt;
+		rc = flash_write_cfibuffer(info, wp, src, i);
+		if (rc != ERR_OK)
+			return rc;
+		i -= i & (info->portwidth - 1);
+		wp += i;
+		src += i;
+		cnt -= i;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, i);
+	}
+#else
+	while (cnt >= info->portwidth) {
+		cword.l = 0;
+		for (i = 0; i < info->portwidth; i++)
+			flash_add_byte(info, &cword, *src++);
+		rc = flash_write_cfiword(info, wp, cword);
+		if (rc)
+			return rc;
+		wp += info->portwidth;
+		cnt -= info->portwidth;
+		FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
+	}
+#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
+
+	if (cnt == 0)
+		return 0;
+
+	/*
+	 * handle unaligned tail bytes
+	 */
+	cword.l = 0;
+	p = (uchar *) wp;
+	for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
+		flash_add_byte(info, &cword, *src++);
+		--cnt;
+	}
+	for (; i < info->portwidth; ++i)
+		flash_add_byte(info, &cword, flash_read8(p + i));
+
+	return flash_write_cfiword(info, wp, cword);
+}
+
+/*-----------------------------------------------------------------------
+ */
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+
+int flash_real_protect(flash_info_t *info, long sector, int prot)
+{
+	int rc;
+
+	switch (info->flash_id & FLASH_VENDMASK) {
+	case (FREESCALE_MANUFACT & FLASH_VENDMASK):
+		rc = cfm_flash_protect(info, sector, prot);
+		break;
+	default:
+		rc = cfi_flash_real_protect(info, sector, prot);
+		break;
+	}
+	return rc;
+}
+
+int cfi_flash_real_protect(flash_info_t *info, long sector, int prot)
+{
+	int retcode = 0;
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
+		if (prot)
+			flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
+		else
+			flash_write_cmd(info, sector, 0,
+					FLASH_CMD_PROTECT_CLEAR);
+		break;
+	case CFI_CMDSET_AMD_EXTENDED:
+	case CFI_CMDSET_AMD_STANDARD:
+		/* U-Boot only checks the first byte */
+		if (info->manufacturer_id == (uchar) ATM_MANUFACT) {
+			if (prot) {
+				flash_unlock_seq(info, 0);
+				flash_write_cmd(info, 0,
+						info->addr_unlock1,
+						ATM_CMD_SOFTLOCK_START);
+				flash_unlock_seq(info, 0);
+				flash_write_cmd(info, sector, 0,
+						ATM_CMD_LOCK_SECT);
+			} else {
+				flash_write_cmd(info, 0,
+						info->addr_unlock1,
+						AMD_CMD_UNLOCK_START);
+				if (info->device_id == ATM_ID_BV6416)
+					flash_write_cmd(info, sector,
+							0, ATM_CMD_UNLOCK_SECT);
+			}
+		}
+		break;
+#ifdef CONFIG_FLASH_CFI_LEGACY
+	case CFI_CMDSET_AMD_LEGACY:
+		flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+		flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
+		if (prot)
+			flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
+		else
+			flash_write_cmd(info, sector, 0,
+					FLASH_CMD_PROTECT_CLEAR);
+		break;
+#endif
+	default:
+		break;
+	};
+
+	retcode = flash_full_status_check(info, sector, info->erase_blk_tout,
+					  prot ? "protect" : "unprotect");
+	if (retcode == 0) {
+		info->protect[sector] = prot;
+		/*
+		 * On some of Intel's flash chips (marked via legacy_unlock)
+		 * unprotect unprotects all locking.
+		 */
+		if ((prot == 0) && (info->legacy_unlock)) {
+			flash_sect_t i;
+
+			for (i = 0; i < info->sector_count; i++) {
+				if (info->protect[i])
+					flash_real_protect(info, i, 1);
+			}
+		}
+	}
+	return retcode;
+}
+
+/*-----------------------------------------------------------------------
+ * flash_read_user_serial - read the OneTimeProgramming cells
+ */
+void flash_read_user_serial(flash_info_t *info, void *buffer, int offset,
+			    int len)
+{
+	uchar *src;
+	uchar *dst;
+
+	dst = buffer;
+	src = flash_map(info, 0, FLASH_OFFSET_USER_PROTECTION);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+	memcpy(dst, src + offset, len);
+	flash_write_cmd(info, 0, 0, info->cmd_reset);
+	flash_unmap(info, 0, FLASH_OFFSET_USER_PROTECTION, src);
+}
+
+/*
+ * flash_read_factory_serial - read the device Id from the protection area
+ */
+void flash_read_factory_serial(flash_info_t *info, void *buffer, int  
offset,
+			       int len)
+{
+	uchar *src;
+
+	src = flash_map(info, 0, FLASH_OFFSET_INTEL_PROTECTION);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+	memcpy(buffer, src + offset, len);
+	flash_write_cmd(info, 0, 0, info->cmd_reset);
+	flash_unmap(info, 0, FLASH_OFFSET_INTEL_PROTECTION, src);
+}
+
+#endif /* CONFIG_SYS_FLASH_PROTECTION */
+
+/*-----------------------------------------------------------------------
+ * Reverse the order of the erase regions in the CFI QRY structure.
+ * This is needed for chips that are either a) correctly detected as
+ * top-boot, or b) buggy.
+ */
+static void cfi_reverse_geometry(struct cfi_qry *qry)
+{
+	unsigned int i, j;
+	u32 tmp;
+
+	for (i = 0, j = qry->num_erase_regions - 1; i < j; i++, j--) {
+		tmp = qry->erase_region_info[i];
+		qry->erase_region_info[i] = qry->erase_region_info[j];
+		qry->erase_region_info[j] = tmp;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ * read jedec ids from device and set corresponding fields in info struct
+ *
+ * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
+ *
+ */
+static void cmdset_intel_read_jedec_ids(flash_info_t *info)
+{
+	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID);
+	udelay(1000);		/* some flash are slow to respond */
+	info->manufacturer_id = flash_read_uchar(info,
+						 FLASH_OFFSET_MANUFACTURER_ID);
+	info->device_id = flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+}
+
+static int cmdset_intel_init(flash_info_t *info, struct cfi_qry *qry)
+{
+	info->cmd_reset = FLASH_CMD_RESET;
+
+	cmdset_intel_read_jedec_ids(info);
+	flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+	/* read legacy lock/unlock bit from intel flash */
+	if (info->ext_addr) {
+		info->legacy_unlock = flash_read_uchar(info,
+						       info->ext_addr +
+						       5) & 0x08;
+	}
+#endif
+
+	return 0;
+}
+
+static void cmdset_amd_read_jedec_ids(flash_info_t *info)
+{
+	flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+	flash_unlock_seq(info, 0);
+	flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID);
+	udelay(1000);		/* some flash are slow to respond */
+
+	info->manufacturer_id = flash_read_uchar(info,
+						 FLASH_OFFSET_MANUFACTURER_ID);
+
+	switch (info->chipwidth) {
+	case FLASH_CFI_8BIT:
+		info->device_id = flash_read_uchar(info,
+						   FLASH_OFFSET_DEVICE_ID);
+		if (info->device_id == 0x7E) {
+			/* AMD 3-byte (expanded) device ids */
+			info->device_id2 = flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID2);
+			info->device_id2 <<= 8;
+			info->device_id2 |= flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID3);
+		}
+		break;
+	case FLASH_CFI_16BIT:
+		info->device_id = flash_read_word(info, FLASH_OFFSET_DEVICE_ID);
+		break;
+	default:
+		break;
+	}
+	flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+}
+
+static int cmdset_amd_init(flash_info_t *info, struct cfi_qry *qry)
+{
+	info->cmd_reset = AMD_CMD_RESET;
+
+	cmdset_amd_read_jedec_ids(info);
+	flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+	return 0;
+}
+
+#ifdef CONFIG_FLASH_CFI_LEGACY
+static void flash_read_jedec_ids(flash_info_t *info)
+{
+	info->manufacturer_id = 0;
+	info->device_id = 0;
+	info->device_id2 = 0;
+
+	switch (info->vendor) {
+	case CFI_CMDSET_INTEL_PROG_REGIONS:
+	case CFI_CMDSET_INTEL_STANDARD:
+	case CFI_CMDSET_INTEL_EXTENDED:
+		cmdset_intel_read_jedec_ids(info);
+		break;
+	case CFI_CMDSET_AMD_STANDARD:
+	case CFI_CMDSET_AMD_EXTENDED:
+		cmdset_amd_read_jedec_ids(info);
+		break;
+	default:
+		break;
+	}
+}
+
+/*-----------------------------------------------------------------------
+ * Call board code to request info about non-CFI flash.
+ * board_flash_get_legacy needs to fill in at least:
+ * info->portwidth, info->chipwidth and info->interface for Jedec probing.
+ */
+static int flash_detect_legacy(phys_addr_t base, int banknum)
+{
+	flash_info_t *info = &flash_info[banknum];
+
+	if (board_flash_get_legacy(base, banknum, info)) {
+		/* board code may have filled info completely. If not, we
+		   use JEDEC ID probing. */
+		if (!info->vendor) {
+			int modes[] = {
+				CFI_CMDSET_AMD_STANDARD,
+				CFI_CMDSET_INTEL_STANDARD
+			};
+			int i;
+
+			for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
+				info->vendor = modes[i];
+				info->start[0] =
+				    (ulong) map_physmem(base,
+							info->portwidth,
+							MAP_NOCACHE);
+				if (info->portwidth == FLASH_CFI_8BIT
+				    && info->interface == FLASH_CFI_X8X16) {
+					info->addr_unlock1 = 0x2AAA;
+					info->addr_unlock2 = 0x5555;
+				} else {
+					info->addr_unlock1 = 0x5555;
+					info->addr_unlock2 = 0x2AAA;
+				}
+				flash_read_jedec_ids(info);
+				debug("JEDEC PROBE: ID %x %x %x\n",
+				      info->manufacturer_id,
+				      info->device_id, info->device_id2);
+				if (jedec_flash_match(info, info->start[0]))
+					break;
+				else
+					unmap_physmem((void *)info->start[0],
+						      MAP_NOCACHE);
+			}
+		}
+
+		switch (info->vendor) {
+		case CFI_CMDSET_INTEL_PROG_REGIONS:
+		case CFI_CMDSET_INTEL_STANDARD:
+		case CFI_CMDSET_INTEL_EXTENDED:
+			info->cmd_reset = FLASH_CMD_RESET;
+			break;
+		case CFI_CMDSET_AMD_STANDARD:
+		case CFI_CMDSET_AMD_EXTENDED:
+		case CFI_CMDSET_AMD_LEGACY:
+			info->cmd_reset = AMD_CMD_RESET;
+			break;
+		}
+		info->flash_id = FLASH_MAN_CFI;
+		return 1;
+	}
+	return 0;		/* use CFI */
+}
+#else
+static inline int flash_detect_legacy(phys_addr_t base, int banknum)
+{
+	return 0;		/* use CFI */
+}
+#endif
+
+/*-----------------------------------------------------------------------
+ * detect if flash is compatible with the Common Flash Interface (CFI)
+ * http://www.jedec.org/download/search/jesd68.pdf
+ */
+static void flash_read_cfi(flash_info_t *info, void *buf,
+			   unsigned int start, size_t len)
+{
+	u8 *p = buf;
+	unsigned int i;
+
+	for (i = 0; i < len; i++)
+		p[i] = flash_read_uchar(info, start + i);
+}
+
+static int __flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry)
+{
+	int cfi_offset;
+
+	/* We do not yet know what kind of commandset to use, so we issue
+	   the reset command in both Intel and AMD variants, in the hope
+	   that AMD flash roms ignore the Intel command. */
+	flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+	flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+
+	for (cfi_offset = 0;
+	     cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
+	     cfi_offset++) {
+		flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset],
+				FLASH_CMD_CFI);
+		if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
+		    && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
+		    && flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
+			flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+				       sizeof(struct cfi_qry));
+			info->interface = le16_to_cpu(qry->interface_desc);
+
+			info->cfi_offset = flash_offset_cfi[cfi_offset];
+			debug("device interface is %d\n", info->interface);
+			debug("found port %d chip %d ",
+			      info->portwidth, info->chipwidth);
+			debug("port %d bits chip %d bits\n",
+			      info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+			      info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
+			/* calculate command offsets as in the Linux driver */
+			info->addr_unlock1 = 0x555;
+			info->addr_unlock2 = 0x2aa;
+
+			/*
+			 * modify the unlock address if we are
+			 * in compatibility mode
+			 */
+			if (/* x8/x16 in x8 mode */
+			    ((info->chipwidth == FLASH_CFI_BY8) &&
+			     (info->interface == FLASH_CFI_X8X16)) ||
+			    /* x16/x32 in x16 mode */
+			    ((info->chipwidth == FLASH_CFI_BY16) &&
+			     (info->interface == FLASH_CFI_X16X32))) {
+				info->addr_unlock1 = 0xaaa;
+				info->addr_unlock2 = 0x555;
+			}
+
+			info->name = "CFI conformant";
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int flash_detect_cfi(flash_info_t *info, struct cfi_qry *qry)
+{
+	debug("flash detect cfi\n");
+
+	for (info->portwidth = CONFIG_SYS_FLASH_CFI_WIDTH;
+	     info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
+		for (info->chipwidth = FLASH_CFI_BY8;
+		     info->chipwidth <= info->portwidth; info->chipwidth <<= 1)
+			if (__flash_detect_cfi(info, qry))
+				return 1;
+	}
+	debug("not found\n");
+	return 0;
+}
+
+/*
+ * Manufacturer-specific quirks. Add workarounds for geometry
+ * reversal, etc. here.
+ */
+static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry)
+{
+	/* check if flash geometry needs reversal */
+	if (qry->num_erase_regions > 1) {
+		/* reverse geometry if top boot part */
+		if (info->cfi_version < 0x3131) {
+			/* CFI < 1.1, try to guess from device id */
+			if ((info->device_id & 0x80) != 0)
+				cfi_reverse_geometry(qry);
+		} else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
+			/* CFI >= 1.1, deduct from top/bottom flag */
+			/* note: ext_addr is valid since cfi_version > 0 */
+			cfi_reverse_geometry(qry);
+		}
+	}
+}
+
+static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry)
+{
+	int reverse_geometry = 0;
+
+	/* Check the "top boot" bit in the PRI */
+	if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
+		reverse_geometry = 1;
+
+	/* AT49BV6416(T) list the erase regions in the wrong order.
+	 * However, the device ID is identical with the non-broken
+	 * AT49BV642D they differ in the high byte.
+	 */
+	if (info->device_id == 0xd6 || info->device_id == 0xd2)
+		reverse_geometry = !reverse_geometry;
+
+	if (reverse_geometry)
+		cfi_reverse_geometry(qry);
+}
+
+static void flash_fixup_stm(flash_info_t *info, struct cfi_qry *qry)
+{
+	/* check if flash geometry needs reversal */
+	if (qry->num_erase_regions > 1) {
+		/* reverse geometry if top boot part */
+		if (info->cfi_version < 0x3131) {
+			/* CFI < 1.1, guess by device id(M29W320{DT,ET} only) */
+			if (info->device_id == 0x22CA ||
+			    info->device_id == 0x2256) {
+				cfi_reverse_geometry(qry);
+			}
+		}
+	}
+}
+
+/*
+ * The following code cannot be run from FLASH!
+ *
+ */
+ulong flash_get_size(phys_addr_t base, int banknum)
+{
+	flash_info_t *info = &flash_info[banknum];
+	int i, j;
+	flash_sect_t sect_cnt;
+	phys_addr_t sector;
+	unsigned long tmp;
+	int size_ratio;
+	uchar num_erase_regions;
+	int erase_region_size;
+	int erase_region_count;
+	struct cfi_qry qry;
+
+	memset(&qry, 0, sizeof(qry));
+
+	info->ext_addr = 0;
+	info->cfi_version = 0;
+#ifdef CONFIG_SYS_FLASH_PROTECTION
+	info->legacy_unlock = 0;
+#endif
+
+	info->start[0] =
+	    (ulong) map_physmem(base, info->portwidth, MAP_NOCACHE);
+
+	if (flash_detect_cfi(info, &qry)) {
+		info->vendor = le16_to_cpu(qry.p_id);
+		info->ext_addr = le16_to_cpu(qry.p_adr);
+		num_erase_regions = qry.num_erase_regions;
+
+		if (info->ext_addr) {
+			info->cfi_version = (ushort) flash_read_uchar(info,
+								      info->
+								      ext_addr +
+								      3) << 8;
+			info->cfi_version |=
+			    (ushort) flash_read_uchar(info, info->ext_addr + 4);
+		}
+#ifdef DEBUG
+		flash_printqry(&qry);
+#endif
+
+		switch (info->vendor) {
+		case CFI_CMDSET_INTEL_PROG_REGIONS:
+		case CFI_CMDSET_INTEL_STANDARD:
+		case CFI_CMDSET_INTEL_EXTENDED:
+			cmdset_intel_init(info, &qry);
+			break;
+		case CFI_CMDSET_AMD_STANDARD:
+		case CFI_CMDSET_AMD_EXTENDED:
+			cmdset_amd_init(info, &qry);
+			break;
+		default:
+			printf("CFI: Unknown command set 0x%x\n", info->vendor);
+			/*
+			 * Unfortunately, this means we don't know how
+			 * to get the chip back to Read mode. Might
+			 * as well try an Intel-style reset...
+			 */
+			flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+			return 0;
+		}
+
+		/* Do manufacturer-specific fixups */
+		switch (info->manufacturer_id) {
+		case 0x0001:
+			flash_fixup_amd(info, &qry);
+			break;
+		case 0x001f:
+			flash_fixup_atmel(info, &qry);
+			break;
+		case 0x0020:
+			flash_fixup_stm(info, &qry);
+			break;
+		}
+
+		debug("manufacturer is %d\n", info->vendor);
+		debug("manufacturer id is 0x%x\n", info->manufacturer_id);
+		debug("device id is 0x%x\n", info->device_id);
+		debug("device id2 is 0x%x\n", info->device_id2);
+		debug("cfi version is 0x%04x\n", info->cfi_version);
+
+		size_ratio = info->portwidth / info->chipwidth;
+		/* if the chip is x8/x16 reduce the ratio by half */
+		if ((info->interface == FLASH_CFI_X8X16)
+		    && (info->chipwidth == FLASH_CFI_BY8)) {
+			size_ratio >>= 1;
+		}
+		debug("size_ratio %d port %d bits chip %d bits\n",
+		      size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+		      info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		debug("found %d erase regions\n", num_erase_regions);
+		sect_cnt = 0;
+		sector = base;
+		for (i = 0; i < num_erase_regions; i++) {
+			if (i > NUM_ERASE_REGIONS) {
+				printf("%d erase regions found, only %d used\n",
+				       num_erase_regions, NUM_ERASE_REGIONS);
+				break;
+			}
+
+			tmp = le32_to_cpu(qry.erase_region_info[i]);
+			debug("erase region %u: 0x%08lx\n", i, tmp);
+
+			erase_region_count = (tmp & 0xffff) + 1;
+			tmp >>= 16;
+			erase_region_size =
+			    (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
+			debug
+			    ("erase_region_count = %d erase_region_size = %d\n",
+			     erase_region_count, erase_region_size);
+			for (j = 0; j < erase_region_count; j++) {
+				if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {
+					printf
+					    ("ERROR: too many flash sectors\n");
+					break;
+				}
+				info->start[sect_cnt] =
+				    (ulong) map_physmem(sector,
+							info->portwidth,
+							MAP_NOCACHE);
+				sector += (erase_region_size * size_ratio);
+
+				/*
+				 * Only read protection status from
+				 * supported devices (intel...)
+				 */
+				switch (info->vendor) {
+				case CFI_CMDSET_INTEL_PROG_REGIONS:
+				case CFI_CMDSET_INTEL_EXTENDED:
+				case CFI_CMDSET_INTEL_STANDARD:
+					info->protect[sect_cnt] =
+					    flash_isset(info, sect_cnt,
+							FLASH_OFFSET_PROTECT,
+							FLASH_STATUS_PROTECT);
+					break;
+				default:
+					/* default: not protected */
+					info->protect[sect_cnt] = 0;
+				}
+
+				sect_cnt++;
+			}
+		}
+
+		info->sector_count = sect_cnt;
+		info->size = 1 << qry.dev_size;
+		/* multiply the size by the number of chips */
+		info->size *= size_ratio;
+		info->buffer_size = 1 << le16_to_cpu(qry.max_buf_write_size);
+		tmp = 1 << qry.block_erase_timeout_typ;
+		info->erase_blk_tout = tmp * (1 << qry.block_erase_timeout_max);
+		tmp = (1 << qry.buf_write_timeout_typ) *
+		    (1 << qry.buf_write_timeout_max);
+
+		/* round up when converting to ms */
+		info->buffer_write_tout = (tmp + 999) / 1000;
+		tmp = (1 << qry.word_write_timeout_typ) *
+		    (1 << qry.word_write_timeout_max);
+		/* round up when converting to ms */
+		info->write_tout = (tmp + 999) / 1000;
+		info->flash_id = FLASH_MAN_CFI;
+		if ((info->interface == FLASH_CFI_X8X16) &&
+		    (info->chipwidth == FLASH_CFI_BY8)) {
+			/* XXX - Need to test on x8/x16 in parallel. */
+			info->portwidth >>= 1;
+		}
+
+		flash_write_cmd(info, 0, 0, info->cmd_reset);
+	}
+
+	return info->size;
+}
+
+void flash_set_verbose(uint v)
+{
+	flash_verbose = v;
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init(void)
+{
+	unsigned long size = 0;
+	int i;
+
+#define BANK_BASE(i) \
+	(((phys_addr_t [CFI_MAX_FLASH_BANKS])CONFIG_SYS_FLASH_BANKS_LIST)[i])
+
+	/* Init: no FLASHes known */
+	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
+		flash_info[i].flash_id = FLASH_UNKNOWN;
+#ifdef CONFIG_SYS_INT_FLASH_BASE
+		if ((BANK_BASE(i) == CONFIG_SYS_INT_FLASH_BASE)) {
+			cfm_flash_init(&flash_info[i]);
+		} else
+#endif
+		if (!flash_detect_legacy(BANK_BASE(i), i))
+			flash_get_size(BANK_BASE(i), i);
+
+		size += flash_info[i].size;
+	}
+
+	flash_protect(FLAG_PROTECT_SET,
+		      CONFIG_SYS_INT_FLASH_BASE,
+		      CONFIG_SYS_INT_FLASH_BASE + CONFIG_SYS_INT_FLASH_SIZE - 1,
+		      flash_get_info(CONFIG_SYS_INT_FLASH_BASE));
+
+	return size;
+}
diff --git a/board/Arcturus/uC5282/u-boot.lds  
b/board/Arcturus/uC5282/u-boot.lds
new file mode 100644
index 0000000..f46e025
--- /dev/null
+++ b/board/Arcturus/uC5282/u-boot.lds
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(m68k)
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text)	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data)	}
+  .rel.rodata    : { *(.rel.rodata)	}
+  .rela.rodata   : { *(.rela.rodata)	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+  .init          : { *(.init)	}
+  .plt : { *(.plt) }
+  .text      :
+  {
+    /* WARNING - the following is hand-optimized to fit within	*/
+    /* the sector layout of our flash chips!	XXX FIXME XXX	*/
+
+    cpu/mcf52x2/start.o	(.text)
+    common/dlmalloc.o	(.text)
+    lib_generic/string.o	(.text)
+    lib_generic/vsprintf.o	(.text)
+    lib_generic/crc32.o	(.text)
+
+    . = DEFINED(env_offset) ? env_offset : .;
+    common/env_embedded.o(.text)
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _erotext = .;
+  PROVIDE (erotext = .);
+    .reloc   :
+  {
+    __got_start = .;
+    *(.got)
+    __got_end = .;
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  . = .;
+  __u_boot_cmd_start = .;
+  .u_boot_cmd : { *(.u_boot_cmd) }
+  __u_boot_cmd_end = .;
+
+  . = .;
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss (NOLOAD)       :
+  {
+   _sbss = .;
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   . = ALIGN(4);
+   _ebss = .;
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/board/Arcturus/uC5282/uC5282.c  
b/board/Arcturus/uC5282/uC5282.c
new file mode 100644
index 0000000..c5fd0f1
--- /dev/null
+++ b/board/Arcturus/uC5282/uC5282.c
@@ -0,0 +1,98 @@
+/*
+ * (c) Copyright 2010 Arcturus Networks Inc.
+ *     by David Wu <www.ArcturusNetworks.com>
+ *
+ * Based on
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd at 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 <asm/immap.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkboard(void)
+{
+	puts("Board: ");
+	puts(PRODUCT_FACTORY);
+	puts(PRODUCT_REVISION);
+	puts("\n");
+	return 0;
+}
+
+phys_size_t initdram(int board_type)
+{
+	u32 dramsize, i, dramclk;
+
+	dramsize = CONFIG_SYS_SDRAM_SIZE * 0x100000;
+
+	if (!(MCFSDRAMC_DACR0 & MCFSDRAMC_DACR_RE)) {
+		dramclk = gd->bus_clk / (CONFIG_SYS_HZ * CONFIG_SYS_HZ);
+
+		/* Initialize DRAM Control Register: DCR */
+		MCFSDRAMC_DCR = (0
+				 | MCFSDRAMC_DCR_RTIM_6
+				 | MCFSDRAMC_DCR_RC((15 * dramclk) >> 4));
+		asm("nop");
+
+		/* Initialize DACR0 */
+		MCFSDRAMC_DACR0 = (0
+				   | MCFSDRAMC_DACR_BASE(CONFIG_SYS_SDRAM_BASE)
+				   | MCFSDRAMC_DACR_CASL(1)
+				   | MCFSDRAMC_DACR_CBM(3)
+				   | MCFSDRAMC_DACR_PS_32);
+		asm("nop");
+
+		/* Initialize DMR0 */
+		MCFSDRAMC_DMR0 = (0 | ((dramsize - 1) & 0xFFFC0000)
+				  | MCFSDRAMC_DMR_V);
+		asm("nop");
+
+		/* Set IP (bit 3) in DACR */
+		MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP;
+		asm("nop");
+
+		/* Wait 30ns to allow banks to precharge */
+		for (i = 0; i < 5; i++)
+			asm("nop");
+
+		/* Write to this block to initiate precharge */
+		*(u32 *) (CONFIG_SYS_SDRAM_BASE) = 0xA5A59696;
+		asm("nop");
+
+		/* Set RE (bit 15) in DACR */
+		MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_RE;
+		asm("nop");
+
+		/* Wait for at least 8 auto refresh cycles to occur */
+		for (i = 0; i < 2000; i++)
+			asm(" nop");
+
+		/* Finish the configuration by issuing the IMRS. */
+		MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IMRS;
+		asm("nop");
+
+		/* Write to the SDRAM Mode Register */
+		*(u32 *) (CONFIG_SYS_SDRAM_BASE + 0x400) = 0xA5A59696;
+	}
+	return dramsize;
+}
diff --git a/include/configs/uC5282.h b/include/configs/uC5282.h
new file mode 100644
index 0000000..d8f536c
--- /dev/null
+++ b/include/configs/uC5282.h
@@ -0,0 +1,299 @@
+/*
+ * Configuation settings for Arcturus Networks Inc.'s uC5282 board.
+ *
+ * (c) Copyright 2010 Arcturus Networks Inc.
+ *     by David Wu <www.ArcturusNetworks.com>
+ *
+ * Based in part on: include/configs/M5282EVB.h
+ *	(C) Copyright 2003 Josef Baumgartner <josef.baumgartner at telex.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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef _CONFIG_UC5282_H
+#define _CONFIG_UC5282_H
+
+#if defined(__4MFlash__)
+#define FLASH_STR		"4"
+#elif defined(__8MFlash__)
+#define FLASH_STR		"8"
+#elif defined(__16MFlash__)
+#define FLASH_STR		"16"
+#elif defined(__32MFlash__)
+#define FLASH_STR		"32"
+#else
+#error "NO VALID FLASH SIZE DEFINITION PLEASE ADD ONE TO YOUR CONFIG FILE"
+#endif
+
+#define ETH0_STR		"E"
+#define ETH1_STR		""
+
+#if defined(__8MRam__)
+#define RAM_STR			"8"
+#elif defined(__16MRam__)
+#define RAM_STR			"16"
+#elif defined(__32MRam__)
+#define RAM_STR			"32"
+#elif defined(__64MRam__)
+#define RAM_STR			"64"
+#else
+#error "NO VALID RAM SIZE DEFINITION PLEASE ADD ONE TO YOUR CFLAGS"
+#endif
+
+#define FEATURE_STR		"C"
+
+#if defined(SYSCLK_64MHZ)
+#define SPEED_STR		"64"
+#else
+#define SPEED_STR		"80"
+#endif
+
+#define CPU_STR			"5282"
+
+#define PRODUCT_FACTORY		"Arcturus Networks Inc. "
+#define PRODUCT_REVISION	"uC" CPU_STR "-" FLASH_STR ETH0_STR \
+				ETH1_STR RAM_STR FEATURE_STR SPEED_STR
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define	CONFIG_MCF52x2		/* define processor family */
+#define CONFIG_M5282		/* define processor type */
+
+#define CONFIG_MCFTMR
+
+#define CONFIG_MCFUART
+#define CONFIG_SYS_UART_PORT		(0)
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600 , 19200 , 38400 , 57600, 115200 }
+
+#define CONFIG_SYS_ENABLE_ICACHE	/* enable icache */
+/* define if monitor is started from a pre-loader */
+#undef	CONFIG_MONITOR_IS_IN_RAM
+
+/* Configuration for environment
+ * Environment variables are embedded in the second 256k bytes of the  
Flash
+ */
+#define CONFIG_ENV_ADDR		0xf0040000
+#define CONFIG_ENV_SIZE		0x40000
+#define CONFIG_ENV_IS_IN_FLASH	1
+/* default kernel image address, start of external Flash */
+#define CONFIG_SYS_LOAD_ADDR	(CONFIG_SYS_CS0_BASE)
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_MII
+
+#undef CONFIG_CMD_LOADS
+#undef CONFIG_CMD_LOADB
+
+#define CONFIG_MCFFEC
+#ifdef CONFIG_MCFFEC
+#	define CONFIG_NET_MULTI		1
+#	define CONFIG_MII		1
+#	define CONFIG_MII_INIT		1
+#	define CONFIG_SYS_DISCOVER_PHY
+#	define CONFIG_SYS_RX_ETH_BUFFER	8
+#	define CONFIG_SYS_FAULT_ECHO_LINK_DOWN
+
+#	define CONFIG_SYS_FEC0_PINMUX	0
+#	define CONFIG_SYS_FEC0_MIIBASE	CONFIG_SYS_FEC0_IOBASE
+#	define MCFFEC_TOUT_LOOP		50000
+#	ifndef CONFIG_SYS_DISCOVER_PHY
+#		define FECDUPLEX	FULL
+#		define FECSPEED		_100BASET
+#	else
+#		ifndef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
+#			define CONFIG_SYS_FAULT_ECHO_LINK_DOWN
+#		endif
+#	endif /* CONFIG_SYS_DISCOVER_PHY */
+#endif
+
+#define CONFIG_BOOTDELAY	5
+#ifdef CONFIG_MCFFEC
+#	define CONFIG_ETHADDR	00:00:00:00:00:00
+#	define CONFIG_IPADDR	192.168.1.200
+#	define CONFIG_NETMASK	255.255.255.0
+#	define CONFIG_SERVERIP	192.168.1.1
+#	define CONFIG_GATEWAYIP	192.168.1.1
+#	define CONFIG_OVERWRITE_ETHADDR_ONCE
+#endif /* CONFIG_MCFFEC */
+
+#define CONFIG_HOSTNAME		uC5282
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	"REVISION="PRODUCT_REVISION"\0"		\
+	"netdev=eth0\0"				\
+	"loadaddr=10000\0"			\
+	"u-boot=u-boot.bin\0"			\
+	"load=tftp ${loadaddr) ${u-boot}\0"	\
+	"upd=run load; run prog\0"		\
+	"prog=prot off f0000000 f003ffff;"	\
+	"era f0000000 f003ffff;"		\
+	"cp.b ${loadaddr} f0000000 ${filesize};"\
+	"setenv filesize;save\0"		\
+	""
+
+#define CONFIG_SYS_PROMPT		"uC5282-> "
+#define	CONFIG_SYS_LONGHELP	/* undef to save memory         */
+
+#if defined(CONFIG_CMD_KGDB)
+#define	CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size      */
+#else
+#define	CONFIG_SYS_CBSIZE	256	/* Console I/O Buffer Size      */
+#endif
+#define	CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)
+				/* Print Buffer Size */
+#define	CONFIG_SYS_MAXARGS	16	/* max number of command args   */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer  
Size */
+#define CONFIG_SYS_MEMTEST_START 0x400
+#define CONFIG_SYS_MEMTEST_END	0x380000
+
+#define CONFIG_SYS_HZ		1000
+
+#if defined(SYSCLK_80MHZ)
+#define	CONFIG_SYS_CLK		80000000
+/* PLL Configuration: Ext Clock * 10 (see table 9-4 of MCF user manual) */
+#define CONFIG_SYS_MFD		0x03	/* PLL Multiplication Factor Devider */
+#endif
+
+#if !defined(CONFIG_SYS_CLK)
+#define	CONFIG_SYS_CLK			64000000
+/* PLL Configuration: Ext Clock * 8 (see table 9-4 of MCF user manual) */
+#define CONFIG_SYS_MFD		0x02	/* PLL Multiplication Factor Devider */
+#endif
+#define CONFIG_SYS_RFD		0x00	/* PLL Reduce Frecuency Devider */
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+#define	CONFIG_SYS_MBAR			0x40000000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CONFIG_SYS_INIT_RAM_ADDR 0x20000000
+#define CONFIG_SYS_INIT_RAM_END  0x10000 /* End of used area in internal  
SRAM */
+#define CONFIG_SYS_GBL_DATA_SIZE 64 /*size in bytes reserved for initial  
data */
+#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_INIT_RAM_END - \
+					 CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CONFIG_SYS_SDRAM_BASE _must_ start at 0
+ */
+#define CONFIG_SYS_SDRAM_BASE		0x00000000
+#if !defined(CONFIG_SYS_SDRAM_SIZE)
+#define	CONFIG_SYS_SDRAM_SIZE		16	/* SDRAM size in MB */
+#endif
+#define CONFIG_SYS_FLASH_BASE		CONFIG_SYS_CS0_BASE
+#define	CONFIG_SYS_INT_FLASH_BASE	0xF0000000
+#define CONFIG_SYS_INT_FLASH_SIZE	0x80000
+#define CONFIG_SYS_INT_FLASH_ENABLE	0x21
+
+/* If M5282 port is fully implemented the monitor base will be behind
+ * the vector table. */
+#if (TEXT_BASE != CONFIG_SYS_INT_FLASH_BASE)
+#define CONFIG_SYS_MONITOR_BASE		(CONFIG_SYS_FLASH_BASE + 0x400)
+#else
+#define CONFIG_SYS_MONITOR_BASE	(TEXT_BASE + 0x418) /* 24 Byte for  
CFM-Config */
+#endif
+
+#define CONFIG_SYS_MONITOR_LEN		0x20000
+#define CONFIG_SYS_MALLOC_LEN		(256 << 10)
+#define CONFIG_SYS_BOOTPARAMS_LEN	(64*1024)
+
+#define CONFIG_SYS_BOOTMAPSZ  
(CONFIG_SYS_SDRAM_BASE+(CONFIG_SYS_SDRAM_SIZE<<20))
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_CFI_WIDTH	FLASH_CFI_16BIT
+#if !defined(CONFIG_SYS_MAX_FLASH_BANKS)
+#define CONFIG_SYS_MAX_FLASH_BANKS	2	/* max number of memory banks */
+#endif
+#if !defined(CONFIG_SYS_MAX_FLASH_SECT)
+#define CONFIG_SYS_MAX_FLASH_SECT 264 /* max number of sectors on one  
chip */
+#endif
+#define CONFIG_SYS_FLASH_ERASE_TOUT	10000000
+#define CONFIG_SYS_FLASH_PROTECTION /* "Real" (hardware) sectors  
protection */
+#define CONFIG_SYS_FLASH_BANKS_LIST	{ CONFIG_SYS_INT_FLASH_BASE, \
+					 CONFIG_SYS_FLASH_BASE }
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define ICACHE_STATUS	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_END  
- 8)
+#define DCACHE_STATUS	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_END  
- 4)
+#define CONFIG_SYS_ICACHE_INV		(CF_CACR_CINV | CF_CACR_INVI)
+#define CONFIG_SYS_CACHE_ACR0		(CONFIG_SYS_SDRAM_BASE | \
+					 CF_ADDRMASK(CONFIG_SYS_SDRAM_SIZE) | \
+					 CF_ACR_EN | CF_ACR_SM_ALL)
+#define CONFIG_SYS_CACHE_ICACR	(CF_CACR_CENB | CF_CACR_DISD)	/*  
0x80400000 */
+#define CONFIG_SYS_CACHELINE_SIZE	16
+
+/*-----------------------------------------------------------------------
+ * Memory bank definitions
+ */
+#define CONFIG_SYS_CS0_BASE		0x10000000
+#define CONFIG_SYS_CS0_CTRL		0x00003d80
+#define CONFIG_SYS_CS0_MASK		0x00FF0001
+
+/*-----------------------------------------------------------------------
+ * Port configuration
+ */
+#define CONFIG_SYS_PACNT		0x0000000	/* Port A D[31:24] */
+#define CONFIG_SYS_PADDR		0x0000000
+#define CONFIG_SYS_PADAT		0x0000000
+
+#define CONFIG_SYS_PBCNT		0x0000000	/* Port B D[23:16] */
+#define CONFIG_SYS_PBDDR		0x0000000
+#define CONFIG_SYS_PBDAT		0x0000000
+
+#define CONFIG_SYS_PCCNT		0x0000000	/* Port C D[15:08] */
+#define CONFIG_SYS_PCDDR		0x0000000
+#define CONFIG_SYS_PCDAT		0x0000000
+
+#define CONFIG_SYS_PDCNT		0x0000000	/* Port D D[07:00] */
+#define CONFIG_SYS_PCDDR		0x0000000
+#define CONFIG_SYS_PCDAT		0x0000000
+
+#define CONFIG_SYS_PEHLPAR		0xC0
+#define CONFIG_SYS_PUAPAR		0x0F	/* UA0..UA3 = Uart 0 +1 */
+#define CONFIG_SYS_DDRUA		0x05
+#define CONFIG_SYS_PJPAR		0xFF
+
+#endif /* _CONFIG_UC5282_H */
-- 
1.5.6


More information about the U-Boot mailing list