[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