
Signed-off-by: David Wu davidwu@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@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@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@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@bus-elektonik.de + * + * Based On + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include "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@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@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@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 */