diff options
105 files changed, 3228 insertions, 986 deletions
@@ -405,7 +405,8 @@ D: Atmel AT91CAP9ADK support N: Ricardo Ribalda Delgado E: ricardo.ribalda@uam.es -D: PPC440x5 (Virtex5), ML507 Board, eeprom_simul, adt7460 +D: PPC440x5 (Virtex5), ML507 Board, eeprom_simul, adt7460, v5fx30teval +D: Virtex ppc440 generic architecture W: http://www.ii.uam.es/~rribalda N: Stefan Roese diff --git a/MAINTAINERS b/MAINTAINERS index 3f16dab..64d8409 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -314,6 +314,8 @@ Daniel Poirot <dan.poirot@windriver.com> Ricardo Ribalda <ricardo.ribalda@uam.es> ml507 PPC440x5 + v5fx30teval PPC440x5 + xilinx-pp440-generic PPC440x5 Stefan Roese <sr@denx.de> @@ -230,12 +230,16 @@ LIST_4xx=" \ sequoia_nand \ taihu \ taishan \ + v5fx30teval \ + v5fx30teval_flash \ VOH405 \ VOM405 \ W7OLMC \ W7OLMG \ walnut \ WUH405 \ + xilinx-ppc440-generic \ + xilinx-ppc440-generic_flash \ XPEDITE1K \ yellowstone \ yosemite \ @@ -295,7 +295,7 @@ $(obj)u-boot.hex: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ $(obj)u-boot.srec: $(obj)u-boot - $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ + $(OBJCOPY) -O srec $< $@ $(obj)u-boot.bin: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ @@ -1242,12 +1242,15 @@ CMS700_config: unconfig CPCI2DP_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx cpci2dp esd -CPCI405_config \ -CPCI4052_config \ +CPCI405_config: unconfig + @$(MKCONFIG) $(@:_config=) ppc ppc4xx cpci405 esd + +CPCI4052_config \ CPCI405DT_config \ CPCI405AB_config: unconfig + @mkdir -p $(obj)board/esd/cpci405 + @echo "TEXT_BASE = 0xFFFC0000" > $(obj)board/esd/cpci405/config.tmp @$(MKCONFIG) $(@:_config=) ppc ppc4xx cpci405 esd - @echo "BOARD_REVISION = $(@:_config=)" >> $(obj)include/config.mk CPCIISER4_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx cpciiser4 esd @@ -1356,16 +1359,23 @@ ML2_config: unconfig ml300_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx ml300 xilinx -ml507_flash_config: unconfig +ml507_flash_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic @mkdir -p $(obj)include $(obj)board/xilinx/ml507 - @cp $(obj)board/xilinx/ml507/u-boot-rom.lds $(obj)board/xilinx/ml507/u-boot.lds - @echo "TEXT_BASE = 0xFE360000" > $(obj)board/xilinx/ml507/config.tmp - @$(MKCONFIG) $(@:_flash_config=) ppc ppc4xx ml507 xilinx - -ml507_config: unconfig + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-rom.lds"\ + > $(obj)board/xilinx/ml507/config.tmp + @echo "TEXT_BASE := 0xFE360000" \ + >> $(obj)board/xilinx/ml507/config.tmp + @$(MKCONFIG) ml507 ppc ppc4xx ml507 xilinx + +ml507_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic @mkdir -p $(obj)include $(obj)board/xilinx/ml507 - @cp $(obj)board/xilinx/ml507/u-boot-ram.lds $(obj)board/xilinx/ml507/u-boot.lds - @$(MKCONFIG) $(@:_config=) ppc ppc4xx ml507 xilinx + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-ram.lds"\ + > $(obj)board/xilinx/ml507/config.tmp + @echo "TEXT_BASE := 0x04000000" \ + >> $(obj)board/xilinx/ml507/config.tmp + @$(MKCONFIG) ml507 ppc ppc4xx ml507 xilinx ocotea_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx ocotea amcc @@ -1461,6 +1471,24 @@ taihu_config: unconfig taishan_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx taishan amcc +v5fx30teval_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic + @mkdir -p $(obj)include $(obj)board/avnet/v5fx30teval + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-ram.lds"\ + > $(obj)board/avnet/v5fx30teval/config.tmp + @echo "TEXT_BASE := 0x03000000" \ + >> $(obj)board/avnet/v5fx30teval/config.tmp + @$(MKCONFIG) v5fx30teval ppc ppc4xx v5fx30teval avnet + +v5fx30teval_flash_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic + @mkdir -p $(obj)include $(obj)board/avnet/v5fx30teval + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-rom.lds"\ + > $(obj)/board/avnet/v5fx30teval/config.tmp + @echo "TEXT_BASE := 0xFF1C0000" \ + >> $(obj)/board/avnet/v5fx30teval/config.tmp + @$(MKCONFIG) v5fx30teval ppc ppc4xx v5fx30teval avnet + VOH405_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx voh405 esd @@ -1479,6 +1507,22 @@ sycamore_config: unconfig WUH405_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx wuh405 esd +xilinx-ppc440-generic_flash_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-rom.lds"\ + > $(obj)board/xilinx/ppc440-generic/config.tmp + @echo "TEXT_BASE := 0xFE360000" \ + >> $(obj)board/xilinx/ppc440-generic/config.tmp + @$(MKCONFIG) xilinx-ppc440-generic ppc ppc4xx ppc440-generic xilinx + +xilinx-ppc440-generic_config: unconfig + @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic + @echo "LDSCRIPT:=$(SRCTREE)/board/xilinx/ppc440-generic/u-boot-ram.lds"\ + > $(obj)board/xilinx/ppc440-generic/config.tmp + @echo "TEXT_BASE := 0x04000000" \ + >> $(obj)board/xilinx/ppc440-generic/config.tmp + @$(MKCONFIG) xilinx-ppc440-generic ppc ppc4xx ppc440-generic xilinx + XPEDITE1K_config: unconfig @$(MKCONFIG) $(@:_config=) ppc ppc4xx xpedite1k @@ -380,11 +380,11 @@ The following options need to be configured: param header, the default value is zero if undefined. - Serial Ports: - CFG_PL010_SERIAL + CONFIG_PL010_SERIAL Define this if you want support for Amba PrimeCell PL010 UARTs. - CFG_PL011_SERIAL + CONFIG_PL011_SERIAL Define this if you want support for Amba PrimeCell PL011 UARTs. @@ -3030,8 +3030,9 @@ details; basically, the header defines the following image properties: * Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD, 4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, - LynxOS, pSOS, QNX, RTEMS, ARTOS; - Currently supported: Linux, NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS). + LynxOS, pSOS, QNX, RTEMS, INTEGRITY; + Currently supported: Linux, NetBSD, VxWorks, QNX, RTEMS, LynxOS, + INTEGRITY). * Target CPU Architecture (Provisions for Alpha, ARM, AVR32, Intel x86, IA64, MIPS, NIOS, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit; Currently supported: ARM, AVR32, Intel x86, MIPS, NIOS, PowerPC). @@ -3089,9 +3090,9 @@ But now you can ignore ALL boot loader code (in arch/ppc/mbxboot). Just make sure your machine specific header file (for instance include/asm-ppc/tqm8xx.h) includes the same definition of the Board -Information structure as we define in include/u-boot.h, and make -sure that your definition of IMAP_ADDR uses the same value as your -U-Boot configuration in CFG_IMMR. +Information structure as we define in include/asm-<arch>/u-boot.h, +and make sure that your definition of IMAP_ADDR uses the same value +as your U-Boot configuration in CFG_IMMR. Configuring the Linux kernel: diff --git a/board/atc/atc.c b/board/atc/atc.c index 79527f4..b627c1c 100644 --- a/board/atc/atc.c +++ b/board/atc/atc.c @@ -380,7 +380,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/avnet/v5fx30teval/Makefile b/board/avnet/v5fx30teval/Makefile new file mode 100644 index 0000000..de23f29 --- /dev/null +++ b/board/avnet/v5fx30teval/Makefile @@ -0,0 +1,27 @@ +# +# (C) Copyright 2008 +# Ricardo Ribalda,Universidad Autonoma de Madrid, ricardo.ribalda@uam.es +# This work has been supported by: Qtechnology http://qtec.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 +# + +COBJS += $(BOARD).o + +include $(SRCTREE)/board/xilinx/ppc440-generic/Makefile diff --git a/board/avnet/v5fx30teval/config.mk b/board/avnet/v5fx30teval/config.mk new file mode 100644 index 0000000..51448ce --- /dev/null +++ b/board/avnet/v5fx30teval/config.mk @@ -0,0 +1,26 @@ +# +# (C) Copyright 2008 +# Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es +# Work supported by Qtechnology http://www.qtec.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 +# +# + +sinclude $(SRCTREE)/board/xilinx/ppc440-generic/config.mk diff --git a/board/avnet/v5fx30teval/v5fx30teval.c b/board/avnet/v5fx30teval/v5fx30teval.c new file mode 100644 index 0000000..14a1d5d --- /dev/null +++ b/board/avnet/v5fx30teval/v5fx30teval.c @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> +#include <common.h> +#include <asm/processor.h> + + +int checkboard(void) +{ + puts("Avnet Virtex 5 FX30 Evaluation Board\n"); + return 0; +} diff --git a/board/avnet/v5fx30teval/xparameters.h b/board/avnet/v5fx30teval/xparameters.h new file mode 100644 index 0000000..bb657fc --- /dev/null +++ b/board/avnet/v5fx30teval/xparameters.h @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * based on xparameters.h by Xilinx + * + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef XPARAMETER_H +#define XPARAMETER_H + +#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000 +#define XPAR_INTC_0_BASEADDR 0x81800000 +#define XPAR_UARTLITE_0_BASEADDR 0x84000000 +#define XPAR_FLASH_MEM0_BASEADDR 0xFF000000 +#define XPAR_PLB_CLOCK_FREQ_HZ 100000000 +#define XPAR_CORE_CLOCK_FREQ_HZ 400000000 +#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13 +#define XPAR_UARTLITE_0_BAUDRATE 9600 + +#endif diff --git a/board/cpu86/cpu86.c b/board/cpu86/cpu86.c index 9e76c72..23ec283 100644 --- a/board/cpu86/cpu86.c +++ b/board/cpu86/cpu86.c @@ -313,7 +313,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/cpu87/cpu87.c b/board/cpu87/cpu87.c index 454987c..c7a96f9 100644 --- a/board/cpu87/cpu87.c +++ b/board/cpu87/cpu87.c @@ -323,7 +323,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/esd/cpci405/config.mk b/board/esd/cpci405/config.mk index 0be45c7..6cfb891 100644 --- a/board/esd/cpci405/config.mk +++ b/board/esd/cpci405/config.mk @@ -21,20 +21,8 @@ # MA 02111-1307 USA # -# -# esd CPCI405 boards -# +sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp -ifeq ($(BOARD_REVISION),CPCI4052) -TEXT_BASE = 0xFFFC0000 -else -ifeq ($(BOARD_REVISION),CPCI405DT) -TEXT_BASE = 0xFFFC0000 -else -ifeq ($(BOARD_REVISION),CPCI405AB) -TEXT_BASE = 0xFFFC0000 -else +ifndef TEXT_BASE TEXT_BASE = 0xFFFD0000 endif -endif -endif diff --git a/board/esd/cpci405/u-boot.lds b/board/esd/cpci405/u-boot.lds index 21547ac..2a1fc31 100644 --- a/board/esd/cpci405/u-boot.lds +++ b/board/esd/cpci405/u-boot.lds @@ -57,22 +57,7 @@ SECTIONS .plt : { *(.plt) } .text : { - /* WARNING - the following is hand-optimized to fit within */ - /* the sector layout of our flash chips! XXX FIXME XXX */ - cpu/ppc4xx/start.o (.text) - cpu/ppc4xx/traps.o (.text) - cpu/ppc4xx/interrupts.o (.text) - cpu/ppc4xx/4xx_uart.o (.text) - cpu/ppc4xx/cpu_init.o (.text) - cpu/ppc4xx/speed.o (.text) - common/dlmalloc.o (.text) - lib_generic/crc32.o (.text) - lib_ppc/extable.o (.text) - lib_generic/zlib.o (.text) - -/* . = env_offset;*/ -/* common/environment.o(.text)*/ *(.text) *(.fixup) diff --git a/board/gen860t/gen860t.c b/board/gen860t/gen860t.c index e3d0e43..5c497b6 100644 --- a/board/gen860t/gen860t.c +++ b/board/gen860t/gen860t.c @@ -223,8 +223,6 @@ phys_size_t initdram (int board_type) * The DOC lives in the CS2* space */ #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); - void doc_init (void) { printf ("Probing at 0x%.8x: ", DOC_BASE); diff --git a/board/integratorcp/integratorcp.c b/board/integratorcp/integratorcp.c index d6d6e13..220513f 100644 --- a/board/integratorcp/integratorcp.c +++ b/board/integratorcp/integratorcp.c @@ -34,6 +34,7 @@ */ #include <common.h> +#include <div64.h> DECLARE_GLOBAL_DATA_PTR; @@ -244,7 +245,11 @@ ulong get_timer_masked (void) total_count += lastdec - now; } lastdec = now; - timestamp = (ulong)(total_count/div_timer); + + /* Reuse "now" */ + now = total_count; + do_div(now, div_timer); + timestamp = now; return timestamp; } diff --git a/board/mcc200/mcc200.c b/board/mcc200/mcc200.c index 77ee3d7..4444650 100644 --- a/board/mcc200/mcc200.c +++ b/board/mcc200/mcc200.c @@ -323,7 +323,6 @@ void ide_set_reset (int idereset) #endif #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c index 24ce807..1f9a772 100644 --- a/board/mpl/common/common_util.c +++ b/board/mpl/common/common_util.c @@ -565,7 +565,6 @@ int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_CMD_DOC) -extern void doc_probe(ulong physadr); void doc_init (void) { doc_probe(MULTI_PURPOSE_SOCKET_ADDR); diff --git a/board/netstal/hcu5/sdram.c b/board/netstal/hcu5/sdram.c index 66a958c..e5df62e 100644 --- a/board/netstal/hcu5/sdram.c +++ b/board/netstal/hcu5/sdram.c @@ -122,7 +122,7 @@ void sdram_panic(const char *reason) } #ifdef CONFIG_DDR_ECC -static void blank_string(int size) +void blank_string(int size) { int i; diff --git a/board/netta2/netta2.c b/board/netta2/netta2.c index a97c14c..1dbdde1 100644 --- a/board/netta2/netta2.c +++ b/board/netta2/netta2.c @@ -620,20 +620,6 @@ void hw_watchdog_reset(void) #endif -#ifdef CONFIG_SHOW_ACTIVITY - -/* called from timer interrupt every 1/CFG_HZ sec */ -void board_show_activity(ulong timestamp) -{ -} - -/* called when looping */ -void show_activity(int arg) -{ -} - -#endif - #if defined(CFG_CONSOLE_IS_IN_ENV) && defined(CFG_CONSOLE_OVERWRITE_ROUTINE) int overwrite_console(void) { diff --git a/board/pm520/pm520.c b/board/pm520/pm520.c index a9d63cc..6db93fb 100644 --- a/board/pm520/pm520.c +++ b/board/pm520/pm520.c @@ -316,7 +316,6 @@ void ide_set_reset (int idereset) #endif #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/pm826/pm826.c b/board/pm826/pm826.c index d8b0929..2304420 100644 --- a/board/pm826/pm826.c +++ b/board/pm826/pm826.c @@ -312,7 +312,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/pm828/pm828.c b/board/pm828/pm828.c index b163d5b..296a199 100644 --- a/board/pm828/pm828.c +++ b/board/pm828/pm828.c @@ -345,7 +345,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/sc520_cdp/sc520_cdp.c b/board/sc520_cdp/sc520_cdp.c index f21c730..99debde 100644 --- a/board/sc520_cdp/sc520_cdp.c +++ b/board/sc520_cdp/sc520_cdp.c @@ -114,7 +114,7 @@ static void irq_init(void) } - +#ifdef CONFIG_PCI /* PCI stuff */ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) { @@ -129,7 +129,7 @@ static void pci_sc520_cdp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) }; static int next_irq_index=0; - char tmp_pin; + uchar tmp_pin; int pin; pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &tmp_pin); @@ -193,7 +193,7 @@ void pci_init_board(void) { pci_sc520_init(&sc520_cdp_hose); } - +#endif static void silence_uart(int port) { @@ -563,12 +563,12 @@ void spi_eeprom_probe(int x) { } -int spi_eeprom_read(int x, int offset, char *buffer, int len) +int spi_eeprom_read(int x, int offset, uchar *buffer, int len) { return 0; } -int spi_eeprom_write(int x, int offset, char *buffer, int len) +int spi_eeprom_write(int x, int offset, uchar *buffer, int len) { return 0; } diff --git a/board/stxxtc/stxxtc.c b/board/stxxtc/stxxtc.c index a750374..4bb2d68 100644 --- a/board/stxxtc/stxxtc.c +++ b/board/stxxtc/stxxtc.c @@ -599,20 +599,6 @@ void hw_watchdog_reset(void) #endif -#ifdef CONFIG_SHOW_ACTIVITY - -/* called from timer interrupt every 1/CFG_HZ sec */ -void board_show_activity(ulong timestamp) -{ -} - -/* called when looping */ -void show_activity(int arg) -{ -} - -#endif - #if defined(CFG_CONSOLE_IS_IN_ENV) && defined(CFG_CONSOLE_OVERWRITE_ROUTINE) int overwrite_console(void) { diff --git a/board/svm_sc8xx/svm_sc8xx.c b/board/svm_sc8xx/svm_sc8xx.c index 06fb18b..48e05b8 100644 --- a/board/svm_sc8xx/svm_sc8xx.c +++ b/board/svm_sc8xx/svm_sc8xx.c @@ -154,7 +154,6 @@ phys_size_t initdram (int board_type) } #if defined(CONFIG_CMD_DOC) -extern void doc_probe (ulong physadr); void doc_init (void) { doc_probe (CFG_DOC_BASE); diff --git a/board/trab/tsc2000.c b/board/trab/tsc2000.c index 382a85b..f13a5a9 100644 --- a/board/trab/tsc2000.c +++ b/board/trab/tsc2000.c @@ -27,6 +27,7 @@ #include <common.h> #include <s3c2400.h> +#include <div64.h> #include "tsc2000.h" #include "Pt1000_temp_data.h" @@ -332,6 +333,7 @@ void tsc2000_reg_init (void) int tsc2000_interpolate(long value, long data[][2], long *result) { int i; + unsigned long long val; /* the data is sorted and the first element is upper * limit so we can easily check for out-of-band values @@ -347,10 +349,10 @@ int tsc2000_interpolate(long value, long data[][2], long *result) result in 'long long'. */ - *result = data[i-1][1] + - ((unsigned long long)(data[i][1] - data[i-1][1]) - * (unsigned long long)(value - data[i-1][0])) - / (data[i][0] - data[i-1][0]); + val = ((unsigned long long)(data[i][1] - data[i-1][1]) + * (unsigned long long)(value - data[i-1][0])); + do_div(val, (data[i][0] - data[i-1][0])); + *result = data[i-1][1] + val; return 0; } diff --git a/board/xilinx/ml507/Makefile b/board/xilinx/ml507/Makefile index 7283704..de23f29 100644 --- a/board/xilinx/ml507/Makefile +++ b/board/xilinx/ml507/Makefile @@ -1,6 +1,7 @@ # -# (C) Copyright 2000-2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# (C) Copyright 2008 +# Ricardo Ribalda,Universidad Autonoma de Madrid, ricardo.ribalda@uam.es +# This work has been supported by: Qtechnology http://qtec.com/ # # See file CREDITS for list of people who contributed to this # project. @@ -21,38 +22,6 @@ # MA 02111-1307 USA # -include $(TOPDIR)/config.mk -ifneq ($(OBJTREE),$(SRCTREE)) -endif +COBJS += $(BOARD).o -INCS := -CFLAGS += $(INCS) -HOST_CFLAGS += $(INCS) - -LIB = $(obj)lib$(BOARD).a - -COBJS = $(BOARD).o - -SOBJS = init.o - -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) -SOBJS := $(addprefix $(obj),$(SOBJS)) - -$(LIB): $(OBJS) $(SOBJS) - $(AR) $(ARFLAGS) $@ $^ - -clean: - rm -f $(SOBJS) $(OBJS) - -distclean: clean - rm -f $(LIB) core *.bak .depend - -######################################################################### - -# defines $(obj).depend target -include $(SRCTREE)/rules.mk - -sinclude $(obj).depend - -######################################################################### +include $(SRCTREE)/board/xilinx/ppc440-generic/Makefile diff --git a/board/xilinx/ml507/config.mk b/board/xilinx/ml507/config.mk index e827e8a..51448ce 100644 --- a/board/xilinx/ml507/config.mk +++ b/board/xilinx/ml507/config.mk @@ -1,6 +1,7 @@ # -# (C) Copyright 2000 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# (C) Copyright 2008 +# Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es +# Work supported by Qtechnology http://www.qtec.com # # See file CREDITS for list of people who contributed to this # project. @@ -20,8 +21,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA # -sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp +# -ifndef TEXT_BASE -TEXT_BASE = 0x04000000 -endif +sinclude $(SRCTREE)/board/xilinx/ppc440-generic/config.mk diff --git a/board/xilinx/ml507/init.S b/board/xilinx/ml507/init.S deleted file mode 100644 index 3228a65..0000000 --- a/board/xilinx/ml507/init.S +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (C) Copyright 2008 - * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es - * This work has been supported by: QTechnology http://qtec.com/ - * - * 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, see <http://www.gnu.org/licenses/>. -*/ - -#include <ppc_asm.tmpl> -#include <config.h> -#include <asm-ppc/mmu.h> - -.section .bootpg,"ax" -.globl tlbtab - -tlbtab: -tlbtab_start - /* SDRAM */ -tlbentry(XPAR_DDR2_SDRAM_MEM_BASEADDR, SZ_256M, CFG_SDRAM_BASE, 0, - AC_R | AC_W | AC_X | SA_G | SA_I) - /* UART */ -tlbentry(XPAR_UARTLITE_0_BASEADDR, SZ_64K, XPAR_UARTLITE_0_BASEADDR, 0, - AC_R | AC_W | SA_G | SA_I) - /* PIC */ -tlbentry(XPAR_INTC_0_BASEADDR, SZ_64K, XPAR_INTC_0_BASEADDR, 0, - AC_R | AC_W | SA_G | SA_I) -#ifdef XPAR_IIC_EEPROM_BASEADDR - /* I2C */ -tlbentry(XPAR_IIC_EEPROM_BASEADDR, SZ_64K, XPAR_IIC_EEPROM_BASEADDR, 0, - AC_R | AC_W | SA_G | SA_I) -#endif -#ifdef XPAR_LLTEMAC_0_BASEADDR - /* Net */ -tlbentry(XPAR_LLTEMAC_0_BASEADDR, SZ_64K, XPAR_LLTEMAC_0_BASEADDR, 0, - AC_R | AC_W | SA_G | SA_I) -#endif -#ifdef XPAR_FLASH_MEM0_BASEADDR - /*Flash*/ -tlbentry(XPAR_FLASH_MEM0_BASEADDR, SZ_256M, XPAR_FLASH_MEM0_BASEADDR, 0, - AC_R | AC_W | AC_X | SA_G | SA_I) -#endif -tlbtab_end diff --git a/board/xilinx/ml507/ml507.c b/board/xilinx/ml507/ml507.c index d499303..f9789cf 100644 --- a/board/xilinx/ml507/ml507.c +++ b/board/xilinx/ml507/ml507.c @@ -20,28 +20,9 @@ #include <common.h> #include <asm/processor.h> -int board_pre_init(void) -{ - return 0; -} int checkboard(void) { - puts("ML507 Board\n"); + puts("Xilinx ML507 Board\n"); return 0; } - -phys_size_t initdram(int board_type) -{ - return get_ram_size(XPAR_DDR2_SDRAM_MEM_BASEADDR, - CFG_SDRAM_SIZE_MB * 1024 * 1024); -} - -void get_sys_info(sys_info_t * sysInfo) -{ - sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ; - sysInfo->freqPLB = XPAR_PLB_CLOCK_FREQ_HZ; - sysInfo->freqPCI = 0; - - return; -} diff --git a/board/xilinx/ml507/xparameters.h b/board/xilinx/ml507/xparameters.h index 77d2ddf..1992fff 100644 --- a/board/xilinx/ml507/xparameters.h +++ b/board/xilinx/ml507/xparameters.h @@ -21,15 +21,14 @@ #ifndef XPARAMETER_H #define XPARAMETER_H -#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000 -#define XPAR_IIC_EEPROM_BASEADDR 0x81600000 -#define XPAR_INTC_0_BASEADDR 0x81800000 -#define XPAR_LLTEMAC_0_BASEADDR 0x81C00000 -#define XPAR_UARTLITE_0_BASEADDR 0x84000000 -#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000 -#define XPAR_PLB_CLOCK_FREQ_HZ 100000000 -#define XPAR_CORE_CLOCK_FREQ_HZ 400000000 -#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13 +#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000 +#define XPAR_IIC_EEPROM_BASEADDR 0x81600000 +#define XPAR_INTC_0_BASEADDR 0x81800000 +#define XPAR_UARTLITE_0_BASEADDR 0x84000000 +#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000 +#define XPAR_PLB_CLOCK_FREQ_HZ 100000000 +#define XPAR_CORE_CLOCK_FREQ_HZ 400000000 +#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13 #define XPAR_UARTLITE_0_BAUDRATE 9600 #endif diff --git a/board/xilinx/ppc440-generic/Makefile b/board/xilinx/ppc440-generic/Makefile new file mode 100644 index 0000000..bf0a6ba --- /dev/null +++ b/board/xilinx/ppc440-generic/Makefile @@ -0,0 +1,62 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es +# Work supported by Qtechnology http://www.qtec.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 +# + +include $(TOPDIR)/config.mk +ifneq ($(OBJTREE),$(SRCTREE)) +endif + +INCS := +CFLAGS += $(INCS) +HOST_CFLAGS += $(INCS) + +LIB = $(obj)lib$(BOARD).a + +COBJS += ../../xilinx/ppc440-generic/xilinx_ppc440_generic.o + +SOBJS += ../../xilinx/ppc440-generic/init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/xilinx/ppc440-generic/config.mk b/board/xilinx/ppc440-generic/config.mk new file mode 100644 index 0000000..8d220da --- /dev/null +++ b/board/xilinx/ppc440-generic/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2008 +# Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es +# Work supported by Qtechnology http://www.qtec.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 +# + +sinclude $(obj)/board/$(BOARDDIR)/config.tmp diff --git a/board/xilinx/ppc440-generic/init.S b/board/xilinx/ppc440-generic/init.S new file mode 100644 index 0000000..1409467 --- /dev/null +++ b/board/xilinx/ppc440-generic/init.S @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <ppc_asm.tmpl> +#include <config.h> +#include <asm-ppc/mmu.h> + +.section .bootpg,"ax" +.globl tlbtab + +tlbtab: +tlbtab_start +tlbentry(0x00000000, SZ_256M, 0x00000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x10000000, SZ_256M, 0x10000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x20000000, SZ_256M, 0x20000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x30000000, SZ_256M, 0x30000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x40000000, SZ_256M, 0x40000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x50000000, SZ_256M, 0x50000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x60000000, SZ_256M, 0x60000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x70000000, SZ_256M, 0x70000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x80000000, SZ_256M, 0x80000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0x90000000, SZ_256M, 0x90000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xa0000000, SZ_256M, 0xa0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xb0000000, SZ_256M, 0xb0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xc0000000, SZ_256M, 0xc0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xd0000000, SZ_256M, 0xd0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xe0000000, SZ_256M, 0xe0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbentry(0xf0000000, SZ_256M, 0xf0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I) +tlbtab_end diff --git a/board/xilinx/ml507/u-boot-ram.lds b/board/xilinx/ppc440-generic/u-boot-ram.lds index 2c98d27..2c98d27 100644 --- a/board/xilinx/ml507/u-boot-ram.lds +++ b/board/xilinx/ppc440-generic/u-boot-ram.lds diff --git a/board/xilinx/ml507/u-boot-rom.lds b/board/xilinx/ppc440-generic/u-boot-rom.lds index d5da018..d5da018 100644 --- a/board/xilinx/ml507/u-boot-rom.lds +++ b/board/xilinx/ppc440-generic/u-boot-rom.lds diff --git a/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c b/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c new file mode 100644 index 0000000..0867226 --- /dev/null +++ b/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> +#include <common.h> +#include <asm/processor.h> + +int __board_pre_init(void) +{ + return 0; +} +int board_pre_init(void) __attribute__((weak, alias("__board_pre_init"))); + +int __checkboard(void) +{ + puts("Xilinx PPC440 Generic Board\n"); + return 0; +} +int checkboard(void) __attribute__((weak, alias("__checkboard"))); + +phys_size_t __initdram(int board_type) +{ + return get_ram_size(XPAR_DDR2_SDRAM_MEM_BASEADDR, + CFG_SDRAM_SIZE_MB * 1024 * 1024); +} +phys_size_t initdram(int) __attribute__((weak, alias("__initdram"))); + +void __get_sys_info(sys_info_t *sysInfo) +{ + sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ; + sysInfo->freqPLB = XPAR_PLB_CLOCK_FREQ_HZ; + sysInfo->freqPCI = 0; + + return; +} +void get_sys_info(sys_info_t *) __attribute__((weak, alias("__get_sys_info"))); diff --git a/board/xilinx/ppc440-generic/xparameters.h b/board/xilinx/ppc440-generic/xparameters.h new file mode 100644 index 0000000..1992fff --- /dev/null +++ b/board/xilinx/ppc440-generic/xparameters.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * based on xparameters-ml507.h by Xilinx + * + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef XPARAMETER_H +#define XPARAMETER_H + +#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000 +#define XPAR_IIC_EEPROM_BASEADDR 0x81600000 +#define XPAR_INTC_0_BASEADDR 0x81800000 +#define XPAR_UARTLITE_0_BASEADDR 0x84000000 +#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000 +#define XPAR_PLB_CLOCK_FREQ_HZ 100000000 +#define XPAR_CORE_CLOCK_FREQ_HZ 400000000 +#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13 +#define XPAR_UARTLITE_0_BAUDRATE 9600 + +#endif diff --git a/common/Makefile b/common/Makefile index 0fe9c8b..8d4a426 100644 --- a/common/Makefile +++ b/common/Makefile @@ -56,7 +56,8 @@ COBJS-y += env_nowhere.o # command COBJS-$(CONFIG_CMD_AMBAPP) += cmd_ambapp.o -COBJS-$(CONFIG_AUTOSCRIPT)$(CONFIG_CMD_AUTOSCRIPT) += cmd_autoscript.o +COBJS-$(CONFIG_AUTOSCRIPT) += cmd_autoscript.o +COBJS-$(CONFIG_CMD_AUTOSCRIPT) += cmd_autoscript.o COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o @@ -110,7 +111,8 @@ COBJS-$(CONFIG_LOGBUFFER) += cmd_log.o COBJS-y += cmd_mac.o COBJS-y += cmd_mem.o COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o -COBJS-$(CONFIG_MII)$(CONFIG_CMD_MII) += miiphyutil.o +COBJS-$(CONFIG_MII) += miiphyutil.o +COBJS-$(CONFIG_CMD_MII) += miiphyutil.o COBJS-$(CONFIG_CMD_MII) += cmd_mii.o COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o @@ -151,8 +153,7 @@ COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o -COBJS-y += $(COBJS-yy) -COBJS := $(COBJS-y) +COBJS := $(sort $(COBJS-y)) SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS)) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 751f5b9..861712b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -108,8 +108,8 @@ static boot_os_fn do_bootm_qnxelf; int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -static boot_os_fn do_bootm_artos; +#if defined(CONFIG_INTEGRITY) +static boot_os_fn do_bootm_integrity; #endif ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ @@ -337,13 +337,13 @@ static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) return BOOTM_ERR_UNIMPLEMENTED; } puts ("OK\n"); - debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, load_end); + debug (" kernel loaded at 0x%08lx, end = 0x%8p\n", load, load_end); if (boot_progress) show_boot_progress (7); if ((load < blob_end) && (*load_end > blob_start)) { debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); - debug ("images.os.load = 0x%lx, load_end = 0x%lx\n", load, load_end); + debug ("images.os.load = 0x%lx, load_end = 0x%p\n", load, load_end); return BOOTM_ERR_OVERLAP; } @@ -455,9 +455,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; #endif -#ifdef CONFIG_ARTOS - case IH_OS_ARTOS: - do_bootm_artos (0, argc, argv, &images); +#ifdef CONFIG_INTEGRITY + case IH_OS_INTEGRITY: + do_bootm_integrity (0, argc, argv, &images); break; #endif } @@ -854,6 +854,12 @@ static int image_info (ulong addr) } fit_print_contents (hdr); + + if (!fit_all_image_check_hashes (hdr)) { + puts ("Bad hash in FIT image!\n"); + return 1; + } + return 0; #endif default: @@ -1153,92 +1159,31 @@ static int do_bootm_qnxelf(int flag, int argc, char *argv[], } #endif -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -static int do_bootm_artos (int flag, int argc, char *argv[], +#ifdef CONFIG_INTEGRITY +static int do_bootm_integrity (int flag, int argc, char *argv[], bootm_headers_t *images) { - ulong top; - char *s, *cmdline; - char **fwenv, **ss; - int i, j, nxt, len, envno, envsz; - bd_t *kbd; - void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); + void (*entry_point)(void); #if defined(CONFIG_FIT) if (!images->legacy_hdr_valid) { - fit_unsupported_reset ("ARTOS"); + fit_unsupported_reset ("INTEGRITY"); return 1; } #endif - /* - * Booting an ARTOS kernel image + application - */ + entry_point = (void (*)(void))images->ep; - /* this used to be the top of memory, but was wrong... */ -#ifdef CONFIG_PPC - /* get stack pointer */ - asm volatile ("mr %0,1" : "=r"(top) ); -#endif - debug ("## Current stack ends at 0x%08lX ", top); - - top -= 2048; /* just to be sure */ - if (top > CFG_BOOTMAPSZ) - top = CFG_BOOTMAPSZ; - top &= ~0xF; - - debug ("=> set upper limit to 0x%08lX\n", top); - - /* first check the artos specific boot args, then the linux args*/ - if ((s = getenv( "abootargs")) == NULL && (s = getenv ("bootargs")) == NULL) - s = ""; - - /* get length of cmdline, and place it */ - len = strlen (s); - top = (top - (len + 1)) & ~0xF; - cmdline = (char *)top; - debug ("## cmdline at 0x%08lX ", top); - strcpy (cmdline, s); - - /* copy bdinfo */ - top = (top - sizeof (bd_t)) & ~0xF; - debug ("## bd at 0x%08lX ", top); - kbd = (bd_t *)top; - memcpy (kbd, gd->bd, sizeof (bd_t)); - - /* first find number of env entries, and their size */ - envno = 0; - envsz = 0; - for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) - ; - envno++; - envsz += (nxt - i) + 1; /* plus trailing zero */ - } - envno++; /* plus the terminating zero */ - debug ("## %u envvars total size %u ", envno, envsz); - - top = (top - sizeof (char **) * envno) & ~0xF; - fwenv = (char **)top; - debug ("## fwenv at 0x%08lX ", top); - - top = (top - envsz) & ~0xF; - s = (char *)top; - ss = fwenv; - - /* now copy them */ - for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) - ; - *ss++ = s; - for (j = i; j < nxt; ++j) - *s++ = env_get_char (j); - *s++ = '\0'; - } - *ss++ = NULL; /* terminate */ + printf ("## Transferring control to INTEGRITY (at address %08lx) ...\n", + (ulong)entry_point); - entry = (void (*)(bd_t *, char *, char **, ulong))images->ep; - (*entry) (kbd, cmdline, fwenv, top); + show_boot_progress (15); + + /* + * INTEGRITY Parameters: + * None + */ + (*entry_point)(); return 1; } diff --git a/common/image.c b/common/image.c index 94f01ad..f7e8606 100644 --- a/common/image.c +++ b/common/image.c @@ -105,9 +105,6 @@ static table_entry_t uimage_arch[] = { static table_entry_t uimage_os[] = { { IH_OS_INVALID, NULL, "Invalid OS", }, -#if defined(CONFIG_ARTOS) || defined(USE_HOSTCC) - { IH_OS_ARTOS, "artos", "ARTOS", }, -#endif { IH_OS_LINUX, "linux", "Linux", }, #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) { IH_OS_LYNXOS, "lynxos", "LynxOS", }, @@ -119,6 +116,9 @@ static table_entry_t uimage_os[] = { { IH_OS_QNX, "qnx", "QNX", }, { IH_OS_VXWORKS, "vxworks", "VxWorks", }, #endif +#if defined(CONFIG_INTEGRITY) || defined(USE_HOSTCC) + { IH_OS_INTEGRITY,"integrity", "INTEGRITY", }, +#endif #ifdef USE_HOSTCC { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, { IH_OS_DELL, "dell", "Dell", }, @@ -2645,27 +2645,29 @@ int fit_image_check_hashes (const void *fit, int image_noffset) continue; if (fit_image_hash_get_algo (fit, noffset, &algo)) { - err_msg = "Can't get hash algo property"; + err_msg = " error!\nCan't get hash algo " + "property"; goto error; } printf ("%s", algo); if (fit_image_hash_get_value (fit, noffset, &fit_value, &fit_value_len)) { - err_msg = "Can't get hash value property"; + err_msg = " error!\nCan't get hash value " + "property"; goto error; } if (calculate_hash (data, size, algo, value, &value_len)) { - err_msg = "Unsupported hash algorithm"; + err_msg = " error!\nUnsupported hash algorithm"; goto error; } if (value_len != fit_value_len) { - err_msg = "Bad hash value len"; + err_msg = " error !\nBad hash value len"; goto error; } else if (memcmp (value, fit_value, value_len) != 0) { - err_msg = "Bad hash value"; + err_msg = " error!\nBad hash value"; goto error; } printf ("+ "); @@ -2682,6 +2684,55 @@ error: } /** + * fit_all_image_check_hashes - verify data intergity for all images + * @fit: pointer to the FIT format image header + * + * fit_all_image_check_hashes() goes over all images in the FIT and + * for every images checks if all it's hashes are valid. + * + * returns: + * 1, if all hashes of all images are valid + * 0, otherwise (or on error) + */ +int fit_all_image_check_hashes (const void *fit) +{ + int images_noffset; + int noffset; + int ndepth; + int count; + + /* Find images parent node offset */ + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return 0; + } + + /* Process all image subnodes, check hashes for each */ + printf ("## Checking hash(es) for FIT Image at %08lx ...\n", + (ulong)fit); + for (ndepth = 0, count = 0, + noffset = fdt_next_node (fit, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + printf (" Hash(es) for Image %u (%s): ", count++, + fit_get_name (fit, noffset, NULL)); + + if (!fit_image_check_hashes (fit, noffset)) + return 0; + printf ("\n"); + } + } + return 1; +} + +/** * fit_image_check_os - check whether image node is of a given os type * @fit: pointer to the FIT format image header * @noffset: component image node offset diff --git a/common/usb.c b/common/usb.c index 9502f39..52e5964 100644 --- a/common/usb.c +++ b/common/usb.c @@ -126,10 +126,15 @@ int usb_init(void) */ int usb_stop(void) { - asynch_allowed=1; - usb_started = 0; - usb_hub_reset(); - return usb_lowlevel_stop(); + int res = 0; + + if (usb_started) { + asynch_allowed = 1; + usb_started = 0; + usb_hub_reset(); + res = usb_lowlevel_stop(); + } + return res; } /* diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 108bd60..920bb0f 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -162,6 +162,8 @@ int drv_usb_kbd_init(void) /* scan all USB Devices */ for(i=0;i<USB_MAX_DEVICE;i++) { dev=usb_get_dev_index(i); /* get device */ + if(dev == NULL) + return -1; if(dev->devnum!=-1) { if(usb_kbd_probe(dev,0)==1) { /* Ok, we found a keyboard */ /* check, if it is already registered */ diff --git a/cpu/arm1176/s3c64xx/interrupts.c b/cpu/arm1176/s3c64xx/interrupts.c index 8356ae4..e34369f 100644 --- a/cpu/arm1176/s3c64xx/interrupts.c +++ b/cpu/arm1176/s3c64xx/interrupts.c @@ -41,6 +41,7 @@ #include <common.h> #include <asm/proc-armv/ptrace.h> #include <s3c6400.h> +#include <div64.h> static ulong timer_load_val; @@ -148,7 +149,9 @@ void reset_timer(void) ulong get_timer_masked(void) { - return get_ticks() / (timer_load_val / (100 * CFG_HZ)); + unsigned long long res = get_ticks(); + do_div (res, (timer_load_val / (100 * CFG_HZ))); + return res; } ulong get_timer(ulong base) diff --git a/cpu/arm946es/config.mk b/cpu/arm946es/config.mk index 81ca288..f774c7e 100644 --- a/cpu/arm946es/config.mk +++ b/cpu/arm946es/config.mk @@ -25,3 +25,10 @@ PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ -msoft-float PLATFORM_CPPFLAGS += -march=armv4 +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) diff --git a/cpu/arm_intcm/config.mk b/cpu/arm_intcm/config.mk index 81ca288..f774c7e 100644 --- a/cpu/arm_intcm/config.mk +++ b/cpu/arm_intcm/config.mk @@ -25,3 +25,10 @@ PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ -msoft-float PLATFORM_CPPFLAGS += -march=armv4 +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index 15250d4..f1d7684 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -60,8 +60,6 @@ "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \ } while (0) -static inline void ppc4xx_ibm_ddr2_register_dump(void); - #if defined(CONFIG_SPD_EEPROM) /*-----------------------------------------------------------------------------+ @@ -260,62 +258,19 @@ static void program_ecc_addr(unsigned long start_address, unsigned long num_bytes, unsigned long tlb_word2_i_value); #endif +#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) static void program_DQS_calibration(unsigned long *dimm_populated, - unsigned char *iic0_dimm_addr, - unsigned long num_dimm_banks); + unsigned char *iic0_dimm_addr, + unsigned long num_dimm_banks); #ifdef HARD_CODED_DQS /* calibration test with hardvalues */ static void test(void); #else static void DQS_calibration_process(void); #endif +#endif int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); void dcbz_area(u32 start_address, u32 num_bytes); -static u32 mfdcr_any(u32 dcr) -{ - u32 val; - - switch (dcr) { - case SDRAM_R0BAS + 0: - val = mfdcr(SDRAM_R0BAS + 0); - break; - case SDRAM_R0BAS + 1: - val = mfdcr(SDRAM_R0BAS + 1); - break; - case SDRAM_R0BAS + 2: - val = mfdcr(SDRAM_R0BAS + 2); - break; - case SDRAM_R0BAS + 3: - val = mfdcr(SDRAM_R0BAS + 3); - break; - default: - printf("DCR %d not defined in case statement!!!\n", dcr); - val = 0; /* just to satisfy the compiler */ - } - - return val; -} - -static void mtdcr_any(u32 dcr, u32 val) -{ - switch (dcr) { - case SDRAM_R0BAS + 0: - mtdcr(SDRAM_R0BAS + 0, val); - break; - case SDRAM_R0BAS + 1: - mtdcr(SDRAM_R0BAS + 1, val); - break; - case SDRAM_R0BAS + 2: - mtdcr(SDRAM_R0BAS + 2, val); - break; - case SDRAM_R0BAS + 3: - mtdcr(SDRAM_R0BAS + 3, val); - break; - default: - printf("DCR %d not defined in case statement!!!\n", dcr); - } -} - static unsigned char spd_read(uchar chip, uint addr) { unsigned char data[2]; @@ -609,7 +564,11 @@ phys_size_t initdram(int board_type) /*------------------------------------------------------------------ * DQS calibration. *-----------------------------------------------------------------*/ +#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) + DQS_autocalibration(); +#else program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks); +#endif #ifdef CONFIG_DDR_ECC /*------------------------------------------------------------------ @@ -2329,18 +2288,6 @@ static unsigned long is_ecc_enabled(void) return ecc; } -static void blank_string(int size) -{ - int i; - - for (i=0; i<size; i++) - putc('\b'); - for (i=0; i<size; i++) - putc(' '); - for (i=0; i<size; i++) - putc('\b'); -} - #ifdef CONFIG_DDR_ECC /*-----------------------------------------------------------------------------+ * program_ecc. @@ -2468,6 +2415,7 @@ static void program_ecc_addr(unsigned long start_address, } #endif +#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) /*-----------------------------------------------------------------------------+ * program_DQS_calibration. *-----------------------------------------------------------------------------*/ @@ -3001,7 +2949,8 @@ static void test(void) (ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK) | ecc_temp); } -#endif +#endif /* !HARD_CODED_DQS */ +#endif /* !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */ #else /* CONFIG_SPD_EEPROM */ @@ -3104,9 +3053,12 @@ phys_size_t initdram(int board_type) /* Set Delay Control Registers */ mtsdram(SDRAM_DLCR, CFG_SDRAM0_DLCR); + +#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) mtsdram(SDRAM_RDCC, CFG_SDRAM0_RDCC); mtsdram(SDRAM_RQDC, CFG_SDRAM0_RQDC); mtsdram(SDRAM_RFDC, CFG_SDRAM0_RFDC); +#endif /* !CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ /* * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1: @@ -3115,18 +3067,98 @@ phys_size_t initdram(int board_type) mfsdram(SDRAM_MCOPT2, val); mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE); +#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) +#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) + /*------------------------------------------------------------------ + | DQS calibration. + +-----------------------------------------------------------------*/ + DQS_autocalibration(); +#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ +#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ + #if defined(CONFIG_DDR_ECC) ecc_init(CFG_SDRAM_BASE, CFG_MBYTES_SDRAM << 20); #endif /* defined(CONFIG_DDR_ECC) */ ppc4xx_ibm_ddr2_register_dump(); + +#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) + /* + * Clear potential errors resulting from auto-calibration. + * If not done, then we could get an interrupt later on when + * exceptions are enabled. + */ + set_mcsr(get_mcsr()); +#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */ + #endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */ return (CFG_MBYTES_SDRAM << 20); } #endif /* CONFIG_SPD_EEPROM */ -static inline void ppc4xx_ibm_ddr2_register_dump(void) +#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) +#if defined(CONFIG_440) +u32 mfdcr_any(u32 dcr) +{ + u32 val; + + switch (dcr) { + case SDRAM_R0BAS + 0: + val = mfdcr(SDRAM_R0BAS + 0); + break; + case SDRAM_R0BAS + 1: + val = mfdcr(SDRAM_R0BAS + 1); + break; + case SDRAM_R0BAS + 2: + val = mfdcr(SDRAM_R0BAS + 2); + break; + case SDRAM_R0BAS + 3: + val = mfdcr(SDRAM_R0BAS + 3); + break; + default: + printf("DCR %d not defined in case statement!!!\n", dcr); + val = 0; /* just to satisfy the compiler */ + } + + return val; +} + +void mtdcr_any(u32 dcr, u32 val) +{ + switch (dcr) { + case SDRAM_R0BAS + 0: + mtdcr(SDRAM_R0BAS + 0, val); + break; + case SDRAM_R0BAS + 1: + mtdcr(SDRAM_R0BAS + 1, val); + break; + case SDRAM_R0BAS + 2: + mtdcr(SDRAM_R0BAS + 2, val); + break; + case SDRAM_R0BAS + 3: + mtdcr(SDRAM_R0BAS + 3, val); + break; + default: + printf("DCR %d not defined in case statement!!!\n", dcr); + } +} +#endif /* defined(CONFIG_440) */ + +void blank_string(int size) +{ + int i; + + for (i = 0; i < size; i++) + putc('\b'); + for (i = 0; i < size; i++) + putc(' '); + for (i = 0; i < size; i++) + putc('\b'); +} +#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ + +inline void ppc4xx_ibm_ddr2_register_dump(void) { #if defined(DEBUG) printf("\nPPC4xx IBM DDR2 Register Dump:\n"); diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index 8a38335..6d4d043 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -198,6 +198,7 @@ #define BI_PHYMODE_RMII 8 #endif #endif +#define BI_PHYMODE_SGMII 9 #if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ @@ -216,6 +217,52 @@ #define MAL_RX_CHAN_MUL 1 #endif +/*--------------------------------------------------------------------+ + * Fixed PHY (PHY-less) support for Ethernet Ports. + *--------------------------------------------------------------------*/ + +/* + * Some boards do not have a PHY for each ethernet port. These ports + * are known as Fixed PHY (or PHY-less) ports. For such ports, set + * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and + * then define CFG_FIXED_PHY_PORTS to define what the speed and + * duplex should be for these ports in the board configuration + * file. + * + * For Example: + * #define CONFIG_FIXED_PHY 0xFFFFFFFF + * + * #define CONFIG_PHY_ADDR CONFIG_FIXED_PHY + * #define CONFIG_PHY1_ADDR 1 + * #define CONFIG_PHY2_ADDR CONFIG_FIXED_PHY + * #define CONFIG_PHY3_ADDR 3 + * + * #define CFG_FIXED_PHY_PORT(devnum,speed,duplex) \ + * {devnum, speed, duplex}, + * + * #define CFG_FIXED_PHY_PORTS \ + * CFG_FIXED_PHY_PORT(0,1000,FULL) \ + * CFG_FIXED_PHY_PORT(2,100,HALF) + */ + +#ifndef CONFIG_FIXED_PHY +#define CONFIG_FIXED_PHY 0xFFFFFFFF /* Fixed PHY (PHY-less) */ +#endif + +#ifndef CFG_FIXED_PHY_PORTS +#define CFG_FIXED_PHY_PORTS /* default is an empty array */ +#endif + +struct fixed_phy_port { + unsigned int devnum; /* ethernet port */ + unsigned int speed; /* specified speed 10,100 or 1000 */ + unsigned int duplex; /* specified duplex FULL or HALF */ +}; + +static const struct fixed_phy_port fixed_phy_port[] = { + CFG_FIXED_PHY_PORTS /* defined in board configuration file */ +}; + /*-----------------------------------------------------------------------------+ * Global variables. TX and RX descriptors and buffers. *-----------------------------------------------------------------------------*/ @@ -611,8 +658,17 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) #if defined(CONFIG_460EX) mode = 9; + mfsdr(SDR0_ETH_CFG, eth_cfg); + if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) && + ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0)) + mode = 11; /* config SGMII */ #else mode = 10; + mfsdr(SDR0_ETH_CFG, eth_cfg); + if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) && + ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0) && + ((eth_cfg & SDR0_ETH_CFG_SGMII2_ENABLE) > 0)) + mode = 12; /* config SGMII */ #endif /* TODO: @@ -635,6 +691,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) /* * Right now only 2*RGMII is supported. Please extend when needed. * sr - 2008-02-19 + * Add SGMII support. + * vg - 2008-07-28 */ switch (mode) { case 1: @@ -761,6 +819,20 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis) bis->bi_phymode[2] = BI_PHYMODE_RGMII; bis->bi_phymode[3] = BI_PHYMODE_RGMII; break; + case 11: + /* 2 SGMII - 460EX */ + bis->bi_phymode[0] = BI_PHYMODE_SGMII; + bis->bi_phymode[1] = BI_PHYMODE_SGMII; + bis->bi_phymode[2] = BI_PHYMODE_NONE; + bis->bi_phymode[3] = BI_PHYMODE_NONE; + break; + case 12: + /* 3 SGMII - 460GT */ + bis->bi_phymode[0] = BI_PHYMODE_SGMII; + bis->bi_phymode[1] = BI_PHYMODE_SGMII; + bis->bi_phymode[2] = BI_PHYMODE_SGMII; + bis->bi_phymode[3] = BI_PHYMODE_NONE; + break; default: break; } @@ -945,9 +1017,50 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg); #endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ +#if defined(CONFIG_GPCS_PHY_ADDR) || defined(CONFIG_GPCS_PHY1_ADDR) || \ + defined(CONFIG_GPCS_PHY2_ADDR) || defined(CONFIG_GPCS_PHY3_ADDR) + if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) { + /* + * In SGMII mode, GPCS access is needed for + * communication with the internal SGMII SerDes. + */ + switch (devnum) { +#if defined(CONFIG_GPCS_PHY_ADDR) + case 0: + reg = CONFIG_GPCS_PHY_ADDR; + break; +#endif +#if defined(CONFIG_GPCS_PHY1_ADDR) + case 1: + reg = CONFIG_GPCS_PHY1_ADDR; + break; +#endif +#if defined(CONFIG_GPCS_PHY2_ADDR) + case 2: + reg = CONFIG_GPCS_PHY2_ADDR; + break; +#endif +#if defined(CONFIG_GPCS_PHY3_ADDR) + case 3: + reg = CONFIG_GPCS_PHY3_ADDR; + break; +#endif + } + + mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr); + mode_reg |= EMAC_M1_MF_1000GPCS | EMAC_M1_IPPA_SET(reg); + out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg); + + /* Configure GPCS interface to recommended setting for SGMII */ + miiphy_reset(dev->name, reg); + miiphy_write(dev->name, reg, 0x04, 0x8120); /* AsymPause, FDX */ + miiphy_write(dev->name, reg, 0x07, 0x2801); /* msg_pg, toggle */ + miiphy_write(dev->name, reg, 0x00, 0x0140); /* 1Gbps, FDX */ + } +#endif /* defined(CONFIG_GPCS_PHY_ADDR) */ + /* wait for PHY to complete auto negotiation */ reg_short = 0; -#ifndef CONFIG_CS8952_PHY switch (devnum) { case 0: reg = CONFIG_PHY_ADDR; @@ -974,6 +1087,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) bis->bi_phynum[devnum] = reg; + if (reg == CONFIG_FIXED_PHY) + goto get_speed; + #if defined(CONFIG_PHY_RESET) /* * Reset the phy, only if its the first time through @@ -986,6 +1102,27 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) miiphy_write (dev->name, reg, 0x09, 0x0e00); miiphy_write (dev->name, reg, 0x04, 0x01e1); #endif +#if defined(CONFIG_M88E1112_PHY) + if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) { + /* + * Marvell 88E1112 PHY needs to have the SGMII MAC + * interace (page 2) properly configured to + * communicate with the 460EX/GT GPCS interface. + */ + + /* Set access to Page 2 */ + miiphy_write(dev->name, reg, 0x16, 0x0002); + + miiphy_write(dev->name, reg, 0x00, 0x0040); /* 1Gbps */ + miiphy_read(dev->name, reg, 0x1a, ®_short); + reg_short |= 0x8000; /* bypass Auto-Negotiation */ + miiphy_write(dev->name, reg, 0x1a, reg_short); + miiphy_reset(dev->name, reg); /* reset MAC interface */ + + /* Reset access to Page 0 */ + miiphy_write(dev->name, reg, 0x16, 0x0000); + } +#endif /* defined(CONFIG_M88E1112_PHY) */ miiphy_reset (dev->name, reg); #if defined(CONFIG_440GX) || \ @@ -1022,7 +1159,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) miiphy_write (dev->name, reg, 0x1f, 0x0000); /* end Vitesse/Cicada errata */ } -#endif +#endif /* defined(CONFIG_CIS8201_PHY) */ #if defined(CONFIG_ET1011C_PHY) /* @@ -1041,9 +1178,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) miiphy_write(dev->name, reg, 0x1c, 0x74f0); } -#endif +#endif /* defined(CONFIG_ET1011C_PHY) */ -#endif +#endif /* defined(CONFIG_440GX) ... */ /* Start/Restart autonegotiation */ phy_setup_aneg (dev->name, reg); udelay (1000); @@ -1073,15 +1210,30 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis) } udelay (1000); /* 1 ms */ miiphy_read (dev->name, reg, PHY_BMSR, ®_short); - } puts (" done\n"); udelay (500000); /* another 500 ms (results in faster booting) */ } -#endif /* #ifndef CONFIG_CS8952_PHY */ - speed = miiphy_speed (dev->name, reg); - duplex = miiphy_duplex (dev->name, reg); +get_speed: + if (reg == CONFIG_FIXED_PHY) { + for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) { + if (devnum == fixed_phy_port[i].devnum) { + speed = fixed_phy_port[i].speed; + duplex = fixed_phy_port[i].duplex; + break; + } + } + + if (i == ARRAY_SIZE(fixed_phy_port)) { + printf("ERROR: PHY (%s) not configured correctly!\n", + dev->name); + return -1; + } + } else { + speed = miiphy_speed(dev->name, reg); + duplex = miiphy_duplex(dev->name, reg); + } if (hw_p->print_speed) { hw_p->print_speed = 0; diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c new file mode 100644 index 0000000..83b9883 --- /dev/null +++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c @@ -0,0 +1,1212 @@ +/* + * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c + * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a + * DDR2 controller (non Denali Core). Those currently are: + * + * 405: 405EX + * 440/460: 440SP/440SPe/460EX/460GT/460SX + * + * (C) Copyright 2008 Applied Micro Circuits Corporation + * Adam Graham <agraham@amcc.com> + * + * (C) Copyright 2007-2008 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * COPYRIGHT AMCC CORPORATION 2004 + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#undef DEBUG + +#include <common.h> +#include <ppc4xx.h> +#include <asm/io.h> +#include <asm/processor.h> + +#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) + +/* + * Only compile the DDR auto-calibration code for NOR boot and + * not for NAND boot (NAND SPL and NAND U-Boot - NUB) + */ +#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) + +#define MAXBXCF 4 +#define SDRAM_RXBAS_SHIFT_1M 20 + +#if defined(CFG_DECREMENT_PATTERNS) +#define NUMMEMTESTS 24 +#else +#define NUMMEMTESTS 8 +#endif /* CFG_DECREMENT_PATTERNS */ +#define NUMLOOPS 1 /* configure as you deem approporiate */ +#define NUMMEMWORDS 16 + +/* Private Structure Definitions */ + +struct autocal_regs { + u32 rffd; + u32 rqfd; +}; + +struct ddrautocal { + u32 rffd; + u32 rffd_min; + u32 rffd_max; + u32 rffd_size; + u32 rqfd; + u32 rqfd_size; + u32 rdcc; + u32 flags; +}; + +struct sdram_timing { + u32 wrdtr; + u32 clktr; +}; + +struct sdram_timing_clks { + u32 wrdtr; + u32 clktr; + u32 rdcc; + u32 flags; +}; + +struct autocal_clks { + struct sdram_timing_clks clocks; + struct ddrautocal autocal; +}; + +/*--------------------------------------------------------------------------+ + * Prototypes + *--------------------------------------------------------------------------*/ +#if defined(CONFIG_PPC4xx_DDR_METHOD_A) +static u32 DQS_calibration_methodA(struct ddrautocal *); +static u32 program_DQS_calibration_methodA(struct ddrautocal *); +#else +static u32 DQS_calibration_methodB(struct ddrautocal *); +static u32 program_DQS_calibration_methodB(struct ddrautocal *); +#endif +static int short_mem_test(u32 *); + +/* + * To provide an interface for board specific config values in this common + * DDR setup code, we implement he "weak" default functions here. They return + * the default value back to the caller. + * + * Please see include/configs/yucca.h for an example fora board specific + * implementation. + */ + +#if !defined(CONFIG_SPD_EEPROM) +u32 __ddr_wrdtr(u32 default_val) +{ + return default_val; +} +u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr"))); + +u32 __ddr_clktr(u32 default_val) +{ + return default_val; +} +u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr"))); + +/* + * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed + */ +void __spd_ddr_init_hang(void) +{ + hang(); +} +void +spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang"))); +#endif /* defined(CONFIG_SPD_EEPROM) */ + +ulong __ddr_scan_option(ulong default_val) +{ + return default_val; +} +ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option"))); + +static u32 *get_membase(int bxcr_num) +{ + ulong bxcf; + u32 *membase; + +#if defined(SDRAM_R0BAS) + /* BAS from Memory Queue rank reg. */ + membase = + (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num))); + bxcf = 0; /* just to satisfy the compiler */ +#else + /* BAS from SDRAM_MBxCF mem rank reg. */ + mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); + membase = (u32 *)((bxcf & 0xfff80000) << 3); +#endif + + return membase; +} + +static inline void ecc_clear_status_reg(void) +{ + mtsdram(SDRAM_ECCCR, 0xffffffff); +#if defined(SDRAM_R0BAS) + mtdcr(SDRAM_ERRSTATLL, 0xffffffff); +#endif +} + +static int ecc_check_status_reg(void) +{ + u32 ecc_status; + + /* + * Compare suceeded, now check + * if got ecc error. If got an + * ecc error, then don't count + * this as a passing value + */ + mfsdram(SDRAM_ECCCR, ecc_status); + if (ecc_status != 0x00000000) { + /* clear on error */ + ecc_clear_status_reg(); + /* ecc check failure */ + return 0; + } + ecc_clear_status_reg(); + sync(); + + return 1; +} + +/* return 1 if passes, 0 if fail */ +static int short_mem_test(u32 *base_address) +{ + int i, j, l; + u32 ecc_mode = 0; + + ulong test[NUMMEMTESTS][NUMMEMWORDS] = { + /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, + /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, + /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, + /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, + /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, + /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, + /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, + /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}, + +#if defined(CFG_DECREMENT_PATTERNS) + /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe, + 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe}, + /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, + 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, + 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd, + 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd}, + /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, + 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc}, + /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, + 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, + 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb, + 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb}, + /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa, + 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa, + 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa, + 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa}, + /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, + 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, + 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, + 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9}, + /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, + 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, + 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, + 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8}, + /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, + 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, + 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7, + 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7}, + /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, + 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, + 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7, + 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7}, + /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, + 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, + 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5, + 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5}, + /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, + 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, + 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4, + 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4}, + /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, + 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, + 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3, + 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3}, + /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, + 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, + 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2, + 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2}, + /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, + 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, + 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1, + 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1}, + /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, + 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, + 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, + 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0}, +#endif /* CFG_DECREMENT_PATTERNS */ + }; + + mfsdram(SDRAM_MCOPT1, ecc_mode); + if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) == + SDRAM_MCOPT1_MCHK_CHK_REP) { + ecc_clear_status_reg(); + sync(); + ecc_mode = 1; + } else { + ecc_mode = 0; + } + + /* + * Run the short memory test. + */ + for (i = 0; i < NUMMEMTESTS; i++) { + for (j = 0; j < NUMMEMWORDS; j++) { + base_address[j] = test[i][j]; + ppcDcbf((ulong)&(base_address[j])); + } + sync(); + for (l = 0; l < NUMLOOPS; l++) { + for (j = 0; j < NUMMEMWORDS; j++) { + if (base_address[j] != test[i][j]) { + ppcDcbf((u32)&(base_address[j])); + return 0; + } else { + if (ecc_mode) { + if (!ecc_check_status_reg()) + return 0; + } + } + ppcDcbf((u32)&(base_address[j])); + } /* for (j = 0; j < NUMMEMWORDS; j++) */ + sync(); + } /* for (l=0; l<NUMLOOPS; l++) */ + } + + return 1; +} + +#if defined(CONFIG_PPC4xx_DDR_METHOD_A) +/*-----------------------------------------------------------------------------+ +| program_DQS_calibration_methodA. ++-----------------------------------------------------------------------------*/ +static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal) +{ + u32 pass_result = 0; + +#ifdef DEBUG + ulong temp; + + mfsdram(SDRAM_RDCC, temp); + debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp); +#endif + + pass_result = DQS_calibration_methodA(ddrcal); + + return pass_result; +} + +/* + * DQS_calibration_methodA() + * + * Autocalibration Method A + * + * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros + * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros + * MEMWRITE(addr, expected_data); + * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD + * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD + * MEMREAD(addr, actual_data); + * if (actual_data == expected_data) { + * DQS_Valid_Window[i] = 1; RQDC.RQFD + * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD + * } + * } + * } + */ +static u32 DQS_calibration_methodA(struct ddrautocal *cal) +{ + ulong rfdc_reg; + ulong rffd; + + ulong rqdc_reg; + ulong rqfd; + + u32 *membase; + ulong bxcf; + int rqfd_average; + int bxcr_num; + int rffd_average; + int pass; + u32 passed = 0; + + int in_window; + struct autocal_regs curr_win_min; + struct autocal_regs curr_win_max; + struct autocal_regs best_win_min; + struct autocal_regs best_win_max; + struct autocal_regs loop_win_min; + struct autocal_regs loop_win_max; + +#ifdef DEBUG + ulong temp; +#endif + ulong rdcc; + + char slash[] = "\\|/-\\|/-"; + int loopi = 0; + + /* start */ + in_window = 0; + + memset(&curr_win_min, 0, sizeof(curr_win_min)); + memset(&curr_win_max, 0, sizeof(curr_win_max)); + memset(&best_win_min, 0, sizeof(best_win_min)); + memset(&best_win_max, 0, sizeof(best_win_max)); + memset(&loop_win_min, 0, sizeof(loop_win_min)); + memset(&loop_win_max, 0, sizeof(loop_win_max)); + + rdcc = 0; + + /* + * Program RDCC register + * Read sample cycle auto-update enable + */ + mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE); + +#ifdef DEBUG + mfsdram(SDRAM_RDCC, temp); + debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp); + mfsdram(SDRAM_RTSR, temp); + debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp); + mfsdram(SDRAM_FCSR, temp); + debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp); +#endif + + /* + * Program RQDC register + * Internal DQS delay mechanism enable + */ + mtsdram(SDRAM_RQDC, + SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00)); + +#ifdef DEBUG + mfsdram(SDRAM_RQDC, temp); + debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp); +#endif + + /* + * Program RFDC register + * Set Feedback Fractional Oversample + * Auto-detect read sample cycle enable + */ + mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE | + SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0)); + +#ifdef DEBUG + mfsdram(SDRAM_RFDC, temp); + debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp); +#endif + + putc(' '); + for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { + + mfsdram(SDRAM_RQDC, rqdc_reg); + rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); + mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); + + putc('\b'); + putc(slash[loopi++ % 8]); + + curr_win_min.rffd = 0; + curr_win_max.rffd = 0; + in_window = 0; + + for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { + mfsdram(SDRAM_RFDC, rfdc_reg); + rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); + mtsdram(SDRAM_RFDC, + rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); + + for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { + mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); + + /* Banks enabled */ + if (bxcf & SDRAM_BXCF_M_BE_MASK) { + /* Bank is enabled */ + membase = get_membase(bxcr_num); + pass = short_mem_test(membase); + } /* if bank enabled */ + } /* for bxcr_num */ + + /* If this value passed update RFFD windows */ + if (pass && !in_window) { /* at the start of window */ + in_window = 1; + curr_win_min.rffd = curr_win_max.rffd = rffd; + curr_win_min.rqfd = curr_win_max.rqfd = rqfd; + mfsdram(SDRAM_RDCC, rdcc); /*record this value*/ + } else if (!pass && in_window) { /* at end of window */ + in_window = 0; + } else if (pass && in_window) { /* within the window */ + curr_win_max.rffd = rffd; + curr_win_max.rqfd = rqfd; + } + /* else if (!pass && !in_window) + skip - no pass, not currently in a window */ + + if (in_window) { + if ((curr_win_max.rffd - curr_win_min.rffd) > + (best_win_max.rffd - best_win_min.rffd)) { + best_win_min.rffd = curr_win_min.rffd; + best_win_max.rffd = curr_win_max.rffd; + + best_win_min.rqfd = curr_win_min.rqfd; + best_win_max.rqfd = curr_win_max.rqfd; + cal->rdcc = rdcc; + } + passed = 1; + } + } /* RFDC.RFFD */ + + /* + * save-off the best window results of the RFDC.RFFD + * for this RQDC.RQFD setting + */ + /* + * if (just ended RFDC.RFDC loop pass window) > + * (prior RFDC.RFFD loop pass window) + */ + if ((best_win_max.rffd - best_win_min.rffd) > + (loop_win_max.rffd - loop_win_min.rffd)) { + loop_win_min.rffd = best_win_min.rffd; + loop_win_max.rffd = best_win_max.rffd; + loop_win_min.rqfd = rqfd; + loop_win_max.rqfd = rqfd; + debug("RQFD.min 0x%08x, RQFD.max 0x%08x, " + "RFFD.min 0x%08x, RFFD.max 0x%08x\n", + loop_win_min.rqfd, loop_win_max.rqfd, + loop_win_min.rffd, loop_win_max.rffd); + } + } /* RQDC.RQFD */ + + putc('\b'); + + debug("\n"); + + if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) && + (best_win_min.rffd == 0) && (best_win_max.rffd == 0) && + (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) { + passed = 0; + } + + /* + * Need to program RQDC before RFDC. + */ + debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd); + debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd); + rqfd_average = loop_win_max.rqfd; + + if (rqfd_average < 0) + rqfd_average = 0; + + if (rqfd_average > SDRAM_RQDC_RQFD_MAX) + rqfd_average = SDRAM_RQDC_RQFD_MAX; + + debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average); + mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | + SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); + + debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd); + debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd); + rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2); + + if (rffd_average < 0) + rffd_average = 0; + + if (rffd_average > SDRAM_RFDC_RFFD_MAX) + rffd_average = SDRAM_RFDC_RFFD_MAX; + + debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average); + mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); + + /* if something passed, then return the size of the largest window */ + if (passed != 0) { + passed = loop_win_max.rffd - loop_win_min.rffd; + cal->rqfd = rqfd_average; + cal->rffd = rffd_average; + cal->rffd_min = loop_win_min.rffd; + cal->rffd_max = loop_win_max.rffd; + } + + return (u32)passed; +} + +#else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */ + +/*-----------------------------------------------------------------------------+ +| program_DQS_calibration_methodB. ++-----------------------------------------------------------------------------*/ +static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal) +{ + u32 pass_result = 0; + +#ifdef DEBUG + ulong temp; +#endif + + /* + * Program RDCC register + * Read sample cycle auto-update enable + */ + mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE); + +#ifdef DEBUG + mfsdram(SDRAM_RDCC, temp); + debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp); +#endif + + /* + * Program RQDC register + * Internal DQS delay mechanism enable + */ + mtsdram(SDRAM_RQDC, +#if defined(CONFIG_DDR_RQDC_START_VAL) + SDRAM_RQDC_RQDE_ENABLE | + SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL)); +#else + SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38)); +#endif + +#ifdef DEBUG + mfsdram(SDRAM_RQDC, temp); + debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp); +#endif + + /* + * Program RFDC register + * Set Feedback Fractional Oversample + * Auto-detect read sample cycle enable + */ + mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE | + SDRAM_RFDC_RFOS_ENCODE(0) | + SDRAM_RFDC_RFFD_ENCODE(0)); + +#ifdef DEBUG + mfsdram(SDRAM_RFDC, temp); + debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp); +#endif + + pass_result = DQS_calibration_methodB(ddrcal); + + return pass_result; +} + +/* + * DQS_calibration_methodB() + * + * Autocalibration Method B + * + * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros + * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros + * MEMWRITE(addr, expected_data); + * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38). + * + * for (j = 0; j < Entire Feedback Range; j++) { + * MEMREAD(addr, actual_data); + * if (actual_data == expected_data) { + * FDBK_Valid_Window[j] = 1; + * } + * } + * + * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window. + * + * for (i = 0; i < Entire DQS Range; i++) { + * MEMREAD(addr, actual_data); + * if (actual_data == expected_data) { + * DQS_Valid_Window[i] = 1; + * } + * } + * + * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window. + */ +/*-----------------------------------------------------------------------------+ +| DQS_calibration_methodB. ++-----------------------------------------------------------------------------*/ +static u32 DQS_calibration_methodB(struct ddrautocal *cal) +{ + ulong rfdc_reg; + ulong rffd; + + ulong rqdc_reg; + ulong rqfd; + + ulong rdcc; + + u32 *membase; + ulong bxcf; + int rqfd_average; + int bxcr_num; + int rffd_average; + int pass; + uint passed = 0; + + int in_window; + u32 curr_win_min, curr_win_max; + u32 best_win_min, best_win_max; + u32 size = 0; + + /*------------------------------------------------------------------ + | Test to determine the best read clock delay tuning bits. + | + | Before the DDR controller can be used, the read clock delay needs to + | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. + | This value cannot be hardcoded into the program because it changes + | depending on the board's setup and environment. + | To do this, all delay values are tested to see if they + | work or not. By doing this, you get groups of fails with groups of + | passing values. The idea is to find the start and end of a passing + | window and take the center of it to use as the read clock delay. + | + | A failure has to be seen first so that when we hit a pass, we know + | that it is truely the start of the window. If we get passing values + | to start off with, we don't know if we are at the start of the window + | + | The code assumes that a failure will always be found. + | If a failure is not found, there is no easy way to get the middle + | of the passing window. I guess we can pretty much pick any value + | but some values will be better than others. Since the lowest speed + | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), + | from experimentation it is safe to say you will always have a failure + +-----------------------------------------------------------------*/ + + debug("\n\n"); + + in_window = 0; + rdcc = 0; + + curr_win_min = curr_win_max = 0; + best_win_min = best_win_max = 0; + for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { + mfsdram(SDRAM_RFDC, rfdc_reg); + rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); + mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); + + pass = 1; + for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { + mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); + + /* Banks enabled */ + if (bxcf & SDRAM_BXCF_M_BE_MASK) { + /* Bank is enabled */ + membase = get_membase(bxcr_num); + pass &= short_mem_test(membase); + } /* if bank enabled */ + } /* for bxcf_num */ + + /* If this value passed */ + if (pass && !in_window) { /* start of passing window */ + in_window = 1; + curr_win_min = curr_win_max = rffd; + mfsdram(SDRAM_RDCC, rdcc); /* record this value */ + } else if (!pass && in_window) { /* end passing window */ + in_window = 0; + } else if (pass && in_window) { /* within the passing window */ + curr_win_max = rffd; + } + + if (in_window) { + if ((curr_win_max - curr_win_min) > + (best_win_max - best_win_min)) { + best_win_min = curr_win_min; + best_win_max = curr_win_max; + cal->rdcc = rdcc; + } + passed = 1; + } + } /* for rffd */ + + if ((best_win_min == 0) && (best_win_max == 0)) + passed = 0; + else + size = best_win_max - best_win_min; + + debug("RFFD Min: 0x%x\n", best_win_min); + debug("RFFD Max: 0x%x\n", best_win_max); + rffd_average = ((best_win_min + best_win_max) / 2); + + cal->rffd_min = best_win_min; + cal->rffd_max = best_win_max; + + if (rffd_average < 0) + rffd_average = 0; + + if (rffd_average > SDRAM_RFDC_RFFD_MAX) + rffd_average = SDRAM_RFDC_RFFD_MAX; + + mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); + + rffd = rffd_average; + in_window = 0; + + curr_win_min = curr_win_max = 0; + best_win_min = best_win_max = 0; + for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { + mfsdram(SDRAM_RQDC, rqdc_reg); + rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); + mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); + + pass = 1; + for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { + + mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf); + + /* Banks enabled */ + if (bxcf & SDRAM_BXCF_M_BE_MASK) { + /* Bank is enabled */ + membase = get_membase(bxcr_num); + pass &= short_mem_test(membase); + } /* if bank enabled */ + } /* for bxcf_num */ + + /* If this value passed */ + if (pass && !in_window) { + in_window = 1; + curr_win_min = curr_win_max = rqfd; + } else if (!pass && in_window) { + in_window = 0; + } else if (pass && in_window) { + curr_win_max = rqfd; + } + + if (in_window) { + if ((curr_win_max - curr_win_min) > + (best_win_max - best_win_min)) { + best_win_min = curr_win_min; + best_win_max = curr_win_max; + } + passed = 1; + } + } /* for rqfd */ + + if ((best_win_min == 0) && (best_win_max == 0)) + passed = 0; + + debug("RQFD Min: 0x%x\n", best_win_min); + debug("RQFD Max: 0x%x\n", best_win_max); + rqfd_average = ((best_win_min + best_win_max) / 2); + + if (rqfd_average < 0) + rqfd_average = 0; + + if (rqfd_average > SDRAM_RQDC_RQFD_MAX) + rqfd_average = SDRAM_RQDC_RQFD_MAX; + + mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | + SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); + + mfsdram(SDRAM_RQDC, rqdc_reg); + mfsdram(SDRAM_RFDC, rfdc_reg); + + /* + * Need to program RQDC before RFDC. The value is read above. + * That is the reason why auto cal not work. + * See, comments below. + */ + mtsdram(SDRAM_RQDC, rqdc_reg); + mtsdram(SDRAM_RFDC, rfdc_reg); + + debug("RQDC: 0x%08X\n", rqdc_reg); + debug("RFDC: 0x%08X\n", rfdc_reg); + + /* if something passed, then return the size of the largest window */ + if (passed != 0) { + passed = size; + cal->rqfd = rqfd_average; + cal->rffd = rffd_average; + } + + return (uint)passed; +} +#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */ + +/* + * Default table for DDR auto-calibration of all + * possible WRDTR and CLKTR values. + * Table format is: + * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} + * + * Table is terminated with {-1, -1} value pair. + * + * Board vendors can specify their own board specific subset of + * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value + * pairs via a board defined ddr_scan_option() function. + */ +struct sdram_timing full_scan_options[] = { + {0, 0}, {0, 1}, {0, 2}, {0, 3}, + {1, 0}, {1, 1}, {1, 2}, {1, 3}, + {2, 0}, {2, 1}, {2, 2}, {2, 3}, + {3, 0}, {3, 1}, {3, 2}, {3, 3}, + {4, 0}, {4, 1}, {4, 2}, {4, 3}, + {5, 0}, {5, 1}, {5, 2}, {5, 3}, + {6, 0}, {6, 1}, {6, 2}, {6, 3}, + {-1, -1} +}; + +/*---------------------------------------------------------------------------+ +| DQS_calibration. ++----------------------------------------------------------------------------*/ +u32 DQS_autocalibration(void) +{ + u32 wdtr; + u32 clkp; + u32 result = 0; + u32 best_result = 0; + u32 best_rdcc; + struct ddrautocal ddrcal; + struct autocal_clks tcal; + ulong rfdc_reg; + ulong rqdc_reg; + u32 val; + int verbose_lvl = 0; + char *str; + char slash[] = "\\|/-\\|/-"; + int loopi = 0; + struct sdram_timing *scan_list; + +#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) + int i; + char tmp[64]; /* long enough for environment variables */ +#endif + + memset(&tcal, 0, sizeof(tcal)); + + ddr_scan_option((ulong)full_scan_options); + + scan_list = + (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options); + + mfsdram(SDRAM_MCOPT1, val); + if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP) + str = "ECC Auto calibration -"; + else + str = "Auto calibration -"; + + puts(str); + +#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION) + i = getenv_r("autocalib", tmp, sizeof(tmp)); + if (i < 0) + strcpy(tmp, CONFIG_AUTOCALIB); + + if (strcmp(tmp, "final") == 0) { + /* display the final autocalibration results only */ + verbose_lvl = 1; + } else if (strcmp(tmp, "loop") == 0) { + /* display summary autocalibration info per iteration */ + verbose_lvl = 2; + } else if (strcmp(tmp, "display") == 0) { + /* display full debug autocalibration window info. */ + verbose_lvl = 3; + } +#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */ + + best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30); + + while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) { + wdtr = scan_list->wrdtr; + clkp = scan_list->clktr; + + mfsdram(SDRAM_WRDTR, val); + val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK); + mtsdram(SDRAM_WRDTR, (val | + ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25)))); + + mtsdram(SDRAM_CLKTR, clkp << 30); + + putc('\b'); + putc(slash[loopi++ % 8]); + +#ifdef DEBUG + debug("\n"); + debug("*** --------------\n"); + mfsdram(SDRAM_WRDTR, val); + debug("*** SDRAM_WRDTR set to 0x%08x\n", val); + mfsdram(SDRAM_CLKTR, val); + debug("*** SDRAM_CLKTR set to 0x%08x\n", val); +#endif + + debug("\n"); + if (verbose_lvl > 2) { + printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr); + printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp); + } + + memset(&ddrcal, 0, sizeof(ddrcal)); + + /* + * DQS calibration. + */ + /* + * program_DQS_calibration_method[A|B]() returns 0 if no + * passing RFDC.[RFFD] window is found or returns the size + * of the best passing window; in the case of a found passing + * window, the ddrcal will contain the values of the best + * window RQDC.[RQFD] and RFDC.[RFFD]. + */ + + /* + * Call PPC4xx SDRAM DDR autocalibration methodA or methodB. + * Default is methodB. + * Defined the autocalibration method in the board specific + * header file. + * Please see include/configs/kilauea.h for an example for + * a board specific implementation. + */ +#if defined(CONFIG_PPC4xx_DDR_METHOD_A) + result = program_DQS_calibration_methodA(&ddrcal); +#else + result = program_DQS_calibration_methodB(&ddrcal); +#endif + + sync(); + + /* + * Clear potential errors resulting from auto-calibration. + * If not done, then we could get an interrupt later on when + * exceptions are enabled. + */ + set_mcsr(get_mcsr()); + + val = ddrcal.rdcc; /* RDCC from the best passing window */ + + udelay(100); + + if (verbose_lvl > 1) { + char *tstr; + switch ((val >> 30)) { + case 0: + if (result != 0) + tstr = "T1"; + else + tstr = "N/A"; + break; + case 1: + tstr = "T2"; + break; + case 2: + tstr = "T3"; + break; + case 3: + tstr = "T4"; + break; + default: + tstr = "unknown"; + break; + } + printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), " + "max-min(0x%04x)(0x%04x), RDCC: %s\n", + wdtr, clkp, result, best_result, + ddrcal.rffd_min, ddrcal.rffd_max, tstr); + } + + /* + * The DQS calibration "result" is either "0" + * if no passing window was found, or is the + * size of the RFFD passing window. + */ + if (result != 0) { + tcal.autocal.flags = 1; + debug("*** (%d)(%d) result passed window size: 0x%08x, " + "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n", + wdtr, clkp, result, ddrcal.rqfd, + ddrcal.rffd, ddrcal.rdcc); + /* + * Save the SDRAM_WRDTR and SDRAM_CLKTR + * settings for the largest returned + * RFFD passing window size. + */ + if (result > best_result) { + /* + * want the lowest Read Sample Cycle Select + */ + val = (val & SDRAM_RDCC_RDSS_MASK) >> 30; + debug("*** (%d) (%d) current_rdcc, best_rdcc\n", + val, best_rdcc); + if (val <= best_rdcc) { + best_rdcc = val; + tcal.clocks.wrdtr = wdtr; + tcal.clocks.clktr = clkp; + tcal.clocks.rdcc = (val << 30); + tcal.autocal.rqfd = ddrcal.rqfd; + tcal.autocal.rffd = ddrcal.rffd; + best_result = result; + + if (verbose_lvl > 2) { + printf("** (%d)(%d) " + "best result: 0x%04x\n", + wdtr, clkp, + best_result); + printf("** (%d)(%d) " + "best WRDTR: 0x%04x\n", + wdtr, clkp, + tcal.clocks.wrdtr); + printf("** (%d)(%d) " + "best CLKTR: 0x%04x\n", + wdtr, clkp, + tcal.clocks.clktr); + printf("** (%d)(%d) " + "best RQDC: 0x%04x\n", + wdtr, clkp, + tcal.autocal.rqfd); + printf("** (%d)(%d) " + "best RFDC: 0x%04x\n", + wdtr, clkp, + tcal.autocal.rffd); + printf("** (%d)(%d) " + "best RDCC: 0x%08x\n", + wdtr, clkp, + (u32)tcal.clocks.rdcc); + mfsdram(SDRAM_RTSR, val); + printf("** (%d)(%d) best " + "loop RTSR: 0x%08x\n", + wdtr, clkp, val); + mfsdram(SDRAM_FCSR, val); + printf("** (%d)(%d) best " + "loop FCSR: 0x%08x\n", + wdtr, clkp, val); + } + } /* if (val <= best_rdcc) */ + } /* if (result >= best_result) */ + } /* if (result != 0) */ + scan_list++; + } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */ + + if (tcal.autocal.flags == 1) { + if (verbose_lvl > 0) { + printf("*** --------------\n"); + printf("*** best_result window size: %d\n", + best_result); + printf("*** best_result WRDTR: 0x%04x\n", + tcal.clocks.wrdtr); + printf("*** best_result CLKTR: 0x%04x\n", + tcal.clocks.clktr); + printf("*** best_result RQFD: 0x%04x\n", + tcal.autocal.rqfd); + printf("*** best_result RFFD: 0x%04x\n", + tcal.autocal.rffd); + printf("*** best_result RDCC: 0x%04x\n", + tcal.clocks.rdcc); + printf("*** --------------\n"); + printf("\n"); + } + + /* + * if got best passing result window, then lock in the + * best CLKTR, WRDTR, RQFD, and RFFD values + */ + mfsdram(SDRAM_WRDTR, val); + mtsdram(SDRAM_WRDTR, (val & + ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | + ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | + (tcal.clocks.wrdtr << 25))); + + mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30); + + mfsdram(SDRAM_RQDC, rqdc_reg); + rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); + mtsdram(SDRAM_RQDC, rqdc_reg | + SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd)); + + mfsdram(SDRAM_RQDC, rqdc_reg); + debug("*** best_result: read value SDRAM_RQDC 0x%08x\n", + rqdc_reg); + + mfsdram(SDRAM_RFDC, rfdc_reg); + rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); + mtsdram(SDRAM_RFDC, rfdc_reg | + SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd)); + + mfsdram(SDRAM_RFDC, rfdc_reg); + debug("*** best_result: read value SDRAM_RFDC 0x%08x\n", + rfdc_reg); + mfsdram(SDRAM_RDCC, val); + debug("*** SDRAM_RDCC 0x%08x\n", val); + } else { + /* + * no valid windows were found + */ + printf("DQS memory calibration window can not be determined, " + "terminating u-boot.\n"); + ppc4xx_ibm_ddr2_register_dump(); + spd_ddr_init_hang(); + } + + blank_string(strlen(str)); + + return 0; +} +#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */ +u32 DQS_autocalibration(void) +{ + return 0; +} +#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */ +#endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */ diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index c773400..463b575 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -35,6 +35,9 @@ SOBJS += kgdb.o COBJS := 40x_spd_sdram.o COBJS += 44x_spd_ddr.o COBJS += 44x_spd_ddr2.o +ifdef CONFIG_PPC4xx_DDR_AUTOCALIBRATION +COBJS += 4xx_ibm_ddr2_autocalib.o +endif COBJS += 4xx_pci.o COBJS += 4xx_pcie.o COBJS += bedbug_405.o diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index c882720..84b1bbe 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -180,8 +180,10 @@ int phy_setup_aneg (char *devname, unsigned char addr) * * sr: Currently on 460EX only EMAC0 works with MDIO, so we always * return EMAC0 offset here + * vg: For 460EX/460GT if internal GPCS PHY address is specified + * return appropriate EMAC offset */ -unsigned int miiphy_getemac_offset (void) +unsigned int miiphy_getemac_offset(u8 addr) { #if (defined(CONFIG_440) && \ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ @@ -233,6 +235,35 @@ unsigned int miiphy_getemac_offset (void) return 0x100; #endif +#if defined(CONFIG_460EX) || defined(CONFIG_460GT) + u32 eoffset = 0; + + switch (addr) { +#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR) + case CONFIG_GPCS_PHY1_ADDR: + if (addr == EMAC_M1_IPPA_GET(in_be32((void *)EMAC_M1 + 0x100))) + eoffset = 0x100; + break; +#endif +#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR) + case CONFIG_GPCS_PHY2_ADDR: + if (addr == EMAC_M1_IPPA_GET(in_be32((void *)EMAC_M1 + 0x300))) + eoffset = 0x300; + break; +#endif +#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR) + case CONFIG_GPCS_PHY3_ADDR: + if (addr == EMAC_M1_IPPA_GET(in_be32((void *)EMAC_M1 + 0x400))) + eoffset = 0x400; + break; +#endif + default: + eoffset = 0; + break; + } + return eoffset; +#endif + return 0; #endif } @@ -262,7 +293,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value) u32 emac_reg; u32 sta_reg; - emac_reg = miiphy_getemac_offset(); + emac_reg = miiphy_getemac_offset(addr); /* wait for completion */ if (emac_miiphy_wait(emac_reg) != 0) @@ -311,7 +342,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg, unsigned long sta_reg; unsigned long emac_reg; - emac_reg = miiphy_getemac_offset (); + emac_reg = miiphy_getemac_offset(addr); if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0) return -1; diff --git a/disk/part.c b/disk/part.c index 5c4bf6b..877e988 100644 --- a/disk/part.c +++ b/disk/part.c @@ -124,6 +124,12 @@ void dev_print (block_dev_desc_t *dev_desc) dev_desc->revision, dev_desc->product); break; + case IF_TYPE_USB: + printf ("Vendor: %s Rev: %s Prod: %s\n", + dev_desc->vendor, + dev_desc->revision, + dev_desc->product); + break; case IF_TYPE_UNKNOWN: default: puts ("not available\n"); diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index c1244fb..157936e 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -169,7 +169,7 @@ the '/images' node should have the following layout: - os : OS name, mandatory for type="kernel", valid OS names are: "openbsd", "netbsd", "freebsd", "4_4bsd", "linux", "svr4", "esix", "solaris", "irix", "sco", "dell", "ncr", "lynxos", "vxworks", "psos", "qnx", "u_boot", - "rtems", "artos", "unity". + "rtems", "unity", "integrity". - arch : Architecture name, mandatory for types: "standalone", "kernel", "firmware", "ramdisk" and "fdt". Valid architecture names are: "alpha", "arm", "i386", "ia64", "mips", "mips64", "ppc", "s390", "sh", "sparc", diff --git a/drivers/mtd/mw_eeprom.c b/drivers/mtd/mw_eeprom.c index f32ced4..f7791b51 100644 --- a/drivers/mtd/mw_eeprom.c +++ b/drivers/mtd/mw_eeprom.c @@ -1,7 +1,7 @@ /* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */ #include <common.h> -#include <ssi.h> +#include <asm/ic/ssi.h> /* * Serial EEPROM opcodes, including start bit diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index f41f33d..94bc518 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -32,8 +32,8 @@ COBJS-y += date.o COBJS-$(CONFIG_RTC_DS12887) += ds12887.o COBJS-$(CONFIG_RTC_DS1302) += ds1302.o COBJS-$(CONFIG_RTC_DS1306) += ds1306.o -COBJS-$(CONFIG_RTC_DS1307)$(CONFIG_RTC_DS1338) += ds1307.o -COBJS-y += $(COBJS-yy) +COBJS-$(CONFIG_RTC_DS1307) += ds1307.o +COBJS-$(CONFIG_RTC_DS1338) += ds1307.o COBJS-$(CONFIG_RTC_DS1337) += ds1337.o COBJS-$(CONFIG_RTC_DS1374) += ds1374.o COBJS-$(CONFIG_RTC_DS1556) += ds1556.o @@ -59,7 +59,7 @@ COBJS-$(CONFIG_RTC_RX8025) += rx8025.o COBJS-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o COBJS-$(CONFIG_RTC_X1205) += x1205.o -COBJS := $(COBJS-y) +COBJS := $(sort $(COBJS-y)) SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c index b6c234e..dabf322 100644 --- a/drivers/rtc/mk48t59.c +++ b/drivers/rtc/mk48t59.c @@ -227,7 +227,7 @@ void rtc_reset (void) rtc_write(RTC_CONTROLB, control_b); } -int rtc_set_watchdog(short multi, short res) +void rtc_set_watchdog(short multi, short res) { uchar wd_value; diff --git a/drivers/rtc/rs5c372.c b/drivers/rtc/rs5c372.c index 34514d0..82dd969 100644 --- a/drivers/rtc/rs5c372.c +++ b/drivers/rtc/rs5c372.c @@ -195,8 +195,7 @@ rtc_get (struct rtc_time *tmp) /* * Set the RTC */ -void -rtc_set (struct rtc_time *tmp) +int rtc_set (struct rtc_time *tmp) { unsigned char buf[8], reg15; int ret; diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index f30014d..eafe543 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -33,13 +33,13 @@ COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o COBJS-$(CONFIG_S3C64XX) += s3c64xx.o COBJS-y += serial.o COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o -COBJS-y += serial_pl010.o -COBJS-y += serial_pl011.o +COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o +COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o COBJS-$(CONFIG_USB_TTY) += usbtty.o -COBJS := $(COBJS-y) +COBJS := $(sort $(COBJS-y)) SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/drivers/serial/serial_pl011.c b/drivers/serial/serial_pl011.c deleted file mode 100644 index 4d35fe5..0000000 --- a/drivers/serial/serial_pl011.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * (C) Copyright 2000 - * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. - * - * (C) Copyright 2004 - * ARM Ltd. - * Philippe Robin, <philippe.robin@arm.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 - */ - -/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ -/* Should be fairly simple to make it work with the PL010 as well */ - -#include <common.h> - -#ifdef CFG_PL011_SERIAL - -#include "serial_pl011.h" - -#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) -#define IO_READ(addr) (*(volatile unsigned int *)(addr)) - -/* - * IntegratorCP has two UARTs, use the first one, at 38400-8-N-1 - * Versatile PB has four UARTs. - */ - -#define CONSOLE_PORT CONFIG_CONS_INDEX -#define baudRate CONFIG_BAUDRATE -static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; -#define NUM_PORTS (sizeof(port)/sizeof(port[0])) - -static void pl011_putc (int portnum, char c); -static int pl011_getc (int portnum); -static int pl011_tstc (int portnum); - - -int serial_init (void) -{ - unsigned int temp; - unsigned int divider; - unsigned int remainder; - unsigned int fraction; - - /* - ** First, disable everything. - */ - IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, 0x0); - - /* - ** Set baud rate - ** - ** IBRD = UART_CLK / (16 * BAUD_RATE) - ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE)) - */ - temp = 16 * baudRate; - divider = CONFIG_PL011_CLOCK / temp; - remainder = CONFIG_PL011_CLOCK % temp; - temp = (8 * remainder) / baudRate; - fraction = (temp >> 1) + (temp & 1); - - IO_WRITE (port[CONSOLE_PORT] + UART_PL011_IBRD, divider); - IO_WRITE (port[CONSOLE_PORT] + UART_PL011_FBRD, fraction); - - /* - ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. - */ - IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH, - (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN)); - - /* - ** Finally, enable the UART - */ - IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, - (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | - UART_PL011_CR_RXE)); - - return 0; -} - -void serial_putc (const char c) -{ - if (c == '\n') - pl011_putc (CONSOLE_PORT, '\r'); - - pl011_putc (CONSOLE_PORT, c); -} - -void serial_puts (const char *s) -{ - while (*s) { - serial_putc (*s++); - } -} - -int serial_getc (void) -{ - return pl011_getc (CONSOLE_PORT); -} - -int serial_tstc (void) -{ - return pl011_tstc (CONSOLE_PORT); -} - -void serial_setbrg (void) -{ -} - -static void pl011_putc (int portnum, char c) -{ - /* Wait until there is space in the FIFO */ - while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF); - - /* Send the character */ - IO_WRITE (port[portnum] + UART_PL01x_DR, c); -} - -static int pl011_getc (int portnum) -{ - unsigned int data; - - /* Wait until there is data in the FIFO */ - while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); - - data = IO_READ (port[portnum] + UART_PL01x_DR); - - /* Check for an error flag */ - if (data & 0xFFFFFF00) { - /* Clear the error */ - IO_WRITE (port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF); - return -1; - } - - return (int) data; -} - -static int pl011_tstc (int portnum) -{ - return !(IO_READ (port[portnum] + UART_PL01x_FR) & - UART_PL01x_FR_RXFE); -} - -#endif diff --git a/drivers/serial/serial_pl010.c b/drivers/serial/serial_pl01x.c index 134ed09..c645cef 100644 --- a/drivers/serial/serial_pl010.c +++ b/drivers/serial/serial_pl01x.c @@ -25,30 +25,31 @@ * MA 02111-1307 USA */ -/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ -/* Should be fairly simple to make it work with the PL010 as well */ +/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */ #include <common.h> #include <watchdog.h> -#ifdef CFG_PL010_SERIAL - -#include "serial_pl011.h" +#include "serial_pl01x.h" #define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) #define IO_READ(addr) (*(volatile unsigned int *)(addr)) -/* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 */ +/* + * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 + * Integrator CP has two UARTs, use the first one, at 38400-8-N-1 + * Versatile PB has four UARTs. + */ #define CONSOLE_PORT CONFIG_CONS_INDEX #define baudRate CONFIG_BAUDRATE static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; #define NUM_PORTS (sizeof(port)/sizeof(port[0])) +static void pl01x_putc (int portnum, char c); +static int pl01x_getc (int portnum); +static int pl01x_tstc (int portnum); -static void pl010_putc (int portnum, char c); -static int pl010_getc (int portnum); -static int pl010_tstc (int portnum); - +#ifdef CONFIG_PL010_SERIAL int serial_init (void) { @@ -103,15 +104,64 @@ int serial_init (void) */ IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, (UART_PL010_CR_UARTEN)); - return (0); + return 0; } +#endif /* CONFIG_PL010_SERIAL */ + +#ifdef CONFIG_PL011_SERIAL + +int serial_init (void) +{ + unsigned int temp; + unsigned int divider; + unsigned int remainder; + unsigned int fraction; + + /* + ** First, disable everything. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, 0x0); + + /* + ** Set baud rate + ** + ** IBRD = UART_CLK / (16 * BAUD_RATE) + ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE)) + */ + temp = 16 * baudRate; + divider = CONFIG_PL011_CLOCK / temp; + remainder = CONFIG_PL011_CLOCK % temp; + temp = (8 * remainder) / baudRate; + fraction = (temp >> 1) + (temp & 1); + + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_IBRD, divider); + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_FBRD, fraction); + + /* + ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH, + (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN)); + + /* + ** Finally, enable the UART + */ + IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, + (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | + UART_PL011_CR_RXE)); + + return 0; +} + +#endif /* CONFIG_PL011_SERIAL */ + void serial_putc (const char c) { if (c == '\n') - pl010_putc (CONSOLE_PORT, '\r'); + pl01x_putc (CONSOLE_PORT, '\r'); - pl010_putc (CONSOLE_PORT, c); + pl01x_putc (CONSOLE_PORT, c); } void serial_puts (const char *s) @@ -123,19 +173,19 @@ void serial_puts (const char *s) int serial_getc (void) { - return pl010_getc (CONSOLE_PORT); + return pl01x_getc (CONSOLE_PORT); } int serial_tstc (void) { - return pl010_tstc (CONSOLE_PORT); + return pl01x_tstc (CONSOLE_PORT); } void serial_setbrg (void) { } -static void pl010_putc (int portnum, char c) +static void pl01x_putc (int portnum, char c) { /* Wait until there is space in the FIFO */ while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF) @@ -145,7 +195,7 @@ static void pl010_putc (int portnum, char c) IO_WRITE (port[portnum] + UART_PL01x_DR, c); } -static int pl010_getc (int portnum) +static int pl01x_getc (int portnum) { unsigned int data; @@ -165,11 +215,9 @@ static int pl010_getc (int portnum) return (int) data; } -static int pl010_tstc (int portnum) +static int pl01x_tstc (int portnum) { WATCHDOG_RESET(); return !(IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); } - -#endif diff --git a/drivers/serial/serial_pl011.h b/drivers/serial/serial_pl01x.h index 5f20fdd..5f20fdd 100644 --- a/drivers/serial/serial_pl011.h +++ b/drivers/serial/serial_pl01x.h diff --git a/drivers/usb/usb_ohci.c b/drivers/usb/usb_ohci.c index fd5567f..da11ecb 100644 --- a/drivers/usb/usb_ohci.c +++ b/drivers/usb/usb_ohci.c @@ -1943,7 +1943,9 @@ int usb_lowlevel_stop(void) if(usb_cpu_stop()) return -1; #endif - + /* This driver is no longer initialised. It needs a new low-level + * init (board/cpu) before it can be used again. */ + ohci_inited = 0; return 0; } #endif /* CONFIG_USB_OHCI_NEW */ diff --git a/examples/82559_eeprom.c b/examples/82559_eeprom.c index 1a121d4..d99af26 100644 --- a/examples/82559_eeprom.c +++ b/examples/82559_eeprom.c @@ -51,13 +51,17 @@ static inline unsigned short swap16(unsigned short x) } -static inline void *memcpy(void *dst, const void *src, unsigned int len) +void * memcpy(void * dest,const void *src,size_t count) { - void * ret = dst; - while (len-- > 0) *((char *)dst)++ = *((char *)src)++; - return ret; + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; } + /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5) #define EE_READ_CMD (6) @@ -156,7 +160,7 @@ static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr) int size_test; int i; - printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr); + printf("Resetting i82559 EEPROM @ 0x%08lx ... ", ioaddr); size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27); eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6; @@ -305,7 +309,7 @@ write_config_word(int bus, int dev, int func, int reg, u16 data) int main (int argc, char *argv[]) { unsigned char *eth_addr; - char buf[6]; + uchar buf[6]; int instance; app_startup(argv); diff --git a/include/asm-i386/byteorder.h b/include/asm-i386/byteorder.h index a9c69d5..7dfeb8b 100644 --- a/include/asm-i386/byteorder.h +++ b/include/asm-i386/byteorder.h @@ -6,7 +6,7 @@ #ifdef __GNUC__ -static __inline__ __const__ __u32 ___arch__swab32(__u32 x) +static __inline__ __u32 ___arch__swab32(__u32 x) { #ifdef CONFIG_X86_BSWAP __asm__("bswap %0" : "=r" (x) : "0" (x)); @@ -20,7 +20,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x) return x; } -static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +static __inline__ __u16 ___arch__swab16(__u16 x) { __asm__("xchgb %b0,%h0" /* swap bytes */ \ : "=q" (x) \ diff --git a/include/asm-i386/global_data.h b/include/asm-i386/global_data.h index 35bad23..cc30689 100644 --- a/include/asm-i386/global_data.h +++ b/include/asm-i386/global_data.h @@ -59,8 +59,8 @@ typedef struct { #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ -extern gd_t *global_data; +extern gd_t *gd; -#define DECLARE_GLOBAL_DATA_PTR gd_t *gd = global_data +#define DECLARE_GLOBAL_DATA_PTR #endif /* __ASM_GBL_DATA_H */ diff --git a/include/asm-i386/ic/ssi.h b/include/asm-i386/ic/ssi.h new file mode 100644 index 0000000..bd48eab --- /dev/null +++ b/include/asm-i386/ic/ssi.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2008 + * Graeme Russ <graeme.russ@gmail.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 + */ + +#ifndef _ASM_IC_SSI_H_ +#define _ASM_IC_SSI_H_ 1 + +int ssi_set_interface(int, int, int, int); +void ssi_chip_select(int); +u8 ssi_txrx_byte(u8); +void ssi_tx_byte(u8); +u8 ssi_rx_byte(void); + + +#endif diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index bde9550..050a2bb 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -31,5 +31,4 @@ int pci_enable_legacy_video_ports(struct pci_controller* hose); int pci_shadow_rom(pci_dev_t dev, unsigned char *dest); void pci_remove_rom_window(struct pci_controller* hose, u32 addr); u32 pci_get_rom_window(struct pci_controller* hose, int size); - #endif diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h index 91a23f9..3643a79 100644 --- a/include/asm-i386/string.h +++ b/include/asm-i386/string.h @@ -5,6 +5,8 @@ * We don't do inline string functions, since the * optimised inline asm versions are not small. */ +#undef __HAVE_ARCH_STRNCPY +extern char *strncpy(char *__dest, __const__ char *__src, __kernel_size_t __n); #undef __HAVE_ARCH_STRRCHR extern char * strrchr(const char * s, int c); diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h index 0174d62..8efa557 100644 --- a/include/asm-ppc/ppc4xx-sdram.h +++ b/include/asm-ppc/ppc4xx-sdram.h @@ -29,6 +29,7 @@ /* * SDRAM Controller */ + /* * XXX - ToDo: Revisit file to change all these lower case defines into * upper case. Also needs to be done in the controller setup code too @@ -256,6 +257,7 @@ #define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK) #define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2) +#if !defined(CONFIG_405EX) /* * Memory queue defines */ @@ -293,7 +295,6 @@ #define SDRAM_PLBADDUHB (SDRAMQ_DCR_BASE+0x10) /* PLB base address upper 32 LL */ -#if !defined(CONFIG_405EX) /* * Memory Bank 0-7 configuration */ @@ -1401,4 +1402,18 @@ #endif /* CONFIG_SDRAM_PPC4xx_DENALI_DDR2 */ +#ifndef __ASSEMBLY__ +/* + * Prototypes + */ +void inline blank_string(int size); +inline void ppc4xx_ibm_ddr2_register_dump(void); +u32 mfdcr_any(u32); +void mtdcr_any(u32, u32); +u32 ddr_wrdtr(u32); +u32 ddr_clktr(u32); +void spd_ddr_init_hang(void); +u32 DQS_autocalibration(void); +#endif /* __ASSEMBLY__ */ + #endif /* _PPC4xx_SDRAM_H_ */ diff --git a/include/common.h b/include/common.h index a394988..33c6e10 100644 --- a/include/common.h +++ b/include/common.h @@ -236,6 +236,9 @@ int autoscript (ulong addr, const char *fit_uname); extern ulong load_addr; /* Default Load Address */ +/* common/cmd_doc.c */ +void doc_probe(unsigned long physadr); + /* common/cmd_nvedit.c */ int env_init (void); void env_relocate (void); diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h index fd49f56..9ec1721 100644 --- a/include/configs/CPCI4052.h +++ b/include/configs/CPCI4052.h @@ -146,6 +146,8 @@ #define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CONFIG_CMDLINE_EDITING /* add command line history */ + #define CONFIG_LOOPW 1 /* enable loopw command */ #define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ @@ -219,6 +221,10 @@ * the maximum mapped by the Linux kernel during initialization. */ #define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP + /*----------------------------------------------------------------------- * FLASH organization */ diff --git a/include/configs/CPCI405AB.h b/include/configs/CPCI405AB.h index 55dd629..7899598 100644 --- a/include/configs/CPCI405AB.h +++ b/include/configs/CPCI405AB.h @@ -144,6 +144,8 @@ #define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CONFIG_CMDLINE_EDITING /* add command line history */ + #define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ #define CONFIG_VERSION_VARIABLE 1 /* include version env variable */ @@ -215,6 +217,10 @@ * the maximum mapped by the Linux kernel during initialization. */ #define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_BOARD_SETUP + /*----------------------------------------------------------------------- * FLASH organization */ diff --git a/include/configs/NETPHONE.h b/include/configs/NETPHONE.h index 6c18b81..1494190 100644 --- a/include/configs/NETPHONE.h +++ b/include/configs/NETPHONE.h @@ -487,8 +487,6 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ -#define CONFIG_ARTOS /* include ARTOS support */ - #define CONFIG_LAST_STAGE_INIT /* needed to reset the damn phys */ /****************************************************************/ diff --git a/include/configs/NETTA.h b/include/configs/NETTA.h index 1f1bc54..6480634 100644 --- a/include/configs/NETTA.h +++ b/include/configs/NETTA.h @@ -496,8 +496,6 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ -#define CONFIG_ARTOS /* include ARTOS support */ - #define CONFIG_LAST_STAGE_INIT /* needed to reset the damn phys */ /*********************************************************************************************************** diff --git a/include/configs/NETTA2.h b/include/configs/NETTA2.h index 9a1f1d6..efa91e3 100644 --- a/include/configs/NETTA2.h +++ b/include/configs/NETTA2.h @@ -488,8 +488,6 @@ #define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ #define BOOTFLAG_WARM 0x02 /* Software reboot */ -#define CONFIG_ARTOS /* include ARTOS support */ - #define CONFIG_LAST_STAGE_INIT /* needed to reset the damn phys */ /****************************************************************/ @@ -745,7 +743,6 @@ typedef unsigned int led_id_t; /* use board specific hardware */ #undef CONFIG_WATCHDOG /* watchdog disabled */ #define CONFIG_HW_WATCHDOG -#define CONFIG_SHOW_ACTIVITY /*************************************************************************************************/ diff --git a/include/configs/NETVIA.h b/include/configs/NETVIA.h index c029594..40e09fb 100644 --- a/include/configs/NETVIA.h +++ b/include/configs/NETVIA.h @@ -357,8 +357,6 @@ /* Ethernet at SCC2 */ #define CONFIG_SCC2_ENET -#define CONFIG_ARTOS /* include ARTOS support */ - /****************************************************************/ #define DSP_SIZE 0x00010000 /* 64K */ diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h index 2ceda00..86ea6c6 100644 --- a/include/configs/PIP405.h +++ b/include/configs/PIP405.h @@ -281,7 +281,6 @@ ***********************************************************/ #define CONFIG_MII 1 /* MII PHY management */ #define CONFIG_PHY_ADDR 1 /* PHY address */ -#define CONFIG_CS8952_PHY 1 /* its a CS8952 PHY */ /************************************************************ * RTC ***********************************************************/ diff --git a/include/configs/integratorap.h b/include/configs/integratorap.h index 1452bf2..ba3c531 100644 --- a/include/configs/integratorap.h +++ b/include/configs/integratorap.h @@ -58,7 +58,7 @@ /* * PL010 Configuration */ -#define CFG_PL010_SERIAL +#define CONFIG_PL010_SERIAL #define CONFIG_CONS_INDEX 0 #define CONFIG_BAUDRATE 38400 #define CONFIG_PL01x_PORTS { (void *) (CFG_SERIAL0), (void *) (CFG_SERIAL1) } diff --git a/include/configs/integratorcp.h b/include/configs/integratorcp.h index 347fa02..5340f7c 100644 --- a/include/configs/integratorcp.h +++ b/include/configs/integratorcp.h @@ -61,7 +61,7 @@ /* * NS16550 Configuration */ -#define CFG_PL011_SERIAL +#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK 14745600 #define CONFIG_PL01x_PORTS { (void *)CFG_SERIAL0, (void *)CFG_SERIAL1 } #define CONFIG_CONS_INDEX 0 diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h index a475f97..f9eaa77 100644 --- a/include/configs/kilauea.h +++ b/include/configs/kilauea.h @@ -223,6 +223,22 @@ *----------------------------------------------------------------------*/ #define CFG_MBYTES_SDRAM (256) /* 256MB */ +/* + * CONFIG_PPC4xx_DDR_AUTOCALIBRATION + * + * Note: DDR Autocalibration Method_A scans the full range of possible PPC4xx + * SDRAM Controller DDR autocalibration values and takes a lot longer + * to run than Method_B. + * (See the Method_A and Method_B algorithm discription in the file: + * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c) + * Define CONFIG_PPC4xx_DDR_METHOD_A to use DDR autocalibration Method_A + * + * DDR Autocalibration Method_B is the default. + */ +#define CONFIG_PPC4xx_DDR_AUTOCALIBRATION /* IBM DDR autocalibration */ +#define DEBUG_PPC4xx_DDR_AUTOCALIBRATION /* dynamic DDR autocal debug */ +#undef CONFIG_PPC4xx_DDR_METHOD_A + #define CFG_SDRAM0_MB0CF_BASE (( 0 << 20) + CFG_SDRAM_BASE) /* DDR1/2 SDRAM Device Control Register Data Values */ @@ -386,6 +402,9 @@ #define CONFIG_HAS_ETH1 1 /* add support for "eth1addr" */ #define CONFIG_PHY1_ADDR 2 +/* Debug messages for the DDR autocalibration */ +#define CONFIG_AUTOCALIB "silent\0" /* default is non-verbose */ + /* * Default environment variables */ diff --git a/include/configs/ml507.h b/include/configs/ml507.h index f8cd499..37d93bb 100644 --- a/include/configs/ml507.h +++ b/include/configs/ml507.h @@ -17,106 +17,33 @@ #ifndef __CONFIG_H #define __CONFIG_H -/* -#define DEBUG -#define ET_DEBUG -*/ - /*CPU*/ -#define CONFIG_XILINX_ML507 1 -#define CONFIG_XILINX_440 1 + +/*CPU*/ #define CONFIG_440 1 -#define CONFIG_4xx 1 +#define CONFIG_XILINX_ML507 1 #include "../board/xilinx/ml507/xparameters.h" /*Mem Map*/ -#define CFG_SDRAM_BASE 0x0 #define CFG_SDRAM_SIZE_MB 256 -#define CFG_MONITOR_BASE TEXT_BASE -#define CFG_MONITOR_LEN ( 192 * 1024 ) -#define CFG_MALLOC_LEN ( CFG_ENV_SIZE + 128 * 1024 ) - -/*Uart*/ -#define CONFIG_XILINX_UARTLITE -#define CONFIG_BAUDRATE XPAR_UARTLITE_0_BAUDRATE -#define CFG_BAUDRATE_TABLE { XPAR_UARTLITE_0_BAUDRATE } -#define CONFIG_SERIAL_BASE XPAR_UARTLITE_0_BASEADDR - -/*Cmd*/ -#include <config_cmd_default.h> -#define CONFIG_CMD_ASKENV -#define CONFIG_CMD_CACHE -#define CONFIG_CMD_DIAG -#define CONFIG_CMD_ELF -#define CONFIG_CMD_IRQ -#define CONFIG_CMD_REGINFO -#define CONFIG_CMD_JFFS2 -#define CONFIG_JFFS2_CMDLINE -#undef CONFIG_CMD_I2C -#undef CONFIG_CMD_DTT -#undef CONFIG_CMD_NET -#undef CONFIG_CMD_PING -#undef CONFIG_CMD_DHCP -#undef CONFIG_CMD_EEPROM -#undef CONFIG_CMD_IMLS /*Env*/ -#define CFG_ENV_IS_IN_FLASH +#define CFG_ENV_IS_IN_FLASH 1 #define CFG_ENV_SIZE 0x20000 #define CFG_ENV_SECT_SIZE 0x20000 -#define CFG_ENV_OFFSET 0x340000 -#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET) +#define CFG_ENV_OFFSET 0x340000 +#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET) /*Misc*/ -#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ -#define CFG_LONGHELP /* undef to save memory */ -#define CFG_PROMPT "board:/# " /* Monitor Command Prompt */ -#if defined(CONFIG_CMD_KGDB) -#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ -#else -#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ -#endif -#define CFG_PBSIZE ( CFG_CBSIZE + sizeof( CFG_PROMPT ) + 16 ) -#define CFG_MAXARGS 16 /* max number of command args */ -#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ -#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ -#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */ -#define CFG_LOAD_ADDR 0x00400000 /* default load address */ -#define CFG_EXTBDINFO 1 /* Extended board_into (bd_t) */ -#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ -#define CONFIG_CMDLINE_EDITING /* add command line history */ -#define CONFIG_AUTO_COMPLETE /* add autocompletion support */ -#define CONFIG_LOOPW /* enable loopw command */ -#define CONFIG_MX_CYCLIC /* enable mdc/mwc commands */ -#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ -#define CONFIG_VERSION_VARIABLE /* include version env variable */ -#define CFG_CONSOLE_INFO_QUIET /* don't print console @ startup */ -#define CFG_HUSH_PARSER /* Use the HUSH parser */ -#define CFG_PROMPT_HUSH_PS2 "> " -#define CONFIG_LOADS_ECHO /* echo on for serial download */ -#define CFG_LOADS_BAUD_CHANGE /* allow baudrate change */ -#define CFG_BOOTMAPSZ ( 8 << 20 ) /* Initial Memory map for Linux */ +#define CFG_PROMPT "ml507:/# " /* Monitor Command Prompt */ #define CONFIG_PREBOOT "echo U-Boot is up and runnining;" -/*Stack*/ -#define CFG_INIT_RAM_ADDR 0x800000 /* Initial RAM address */ -#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ -#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */ -#define CFG_GBL_DATA_OFFSET ( CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE ) -#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET -/*Speed*/ -#define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ - /*Flash*/ -#define CFG_FLASH_BASE XPAR_FLASH_MEM0_BASEADDR #define CFG_FLASH_SIZE (32*1024*1024) -#define CFG_FLASH_CFI 1 -#define CONFIG_FLASH_CFI_DRIVER 1 -#define CFG_FLASH_EMPTY_INFO 1 -#define CFG_MAX_FLASH_BANKS 1 #define CFG_MAX_FLASH_SECT 259 -#define CFG_FLASH_PROTECTION #define MTDIDS_DEFAULT "nor0=ml507-flash" #define MTDPARTS_DEFAULT "mtdparts=ml507-flash:-(user)" +/*Generic Configs*/ +#include <configs/xilinx-ppc440.h> #endif /* __CONFIG_H */ diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h index e29655e..dfe7b7d 100644 --- a/include/configs/sc520_cdp.h +++ b/include/configs/sc520_cdp.h @@ -28,6 +28,7 @@ #ifndef __CONFIG_H #define __CONFIG_H +#define GRUSS_TESTING /* * High Level Configuration Options * (easy to change) @@ -81,7 +82,11 @@ #include <config_cmd_default.h> #define CONFIG_CMD_PCI +#ifndef GRUSS_TESTING #define CONFIG_CMD_SATA +#else +#undef CONFIG_CMD_SATA +#endif #define CONFIG_CMD_JFFS2 #define CONFIG_CMD_NET #define CONFIG_CMD_EEPROM @@ -175,10 +180,18 @@ /************************************************************ *SATA/Native Stuff ************************************************************/ +#ifndef GRUSS_TESTING #define CFG_SATA_MAXBUS 2 /*Max Sata buses supported */ #define CFG_SATA_DEVS_PER_BUS 2 /*Max no. of devices per bus/port */ #define CFG_SATA_MAX_DEVICE (CFG_SATA_MAXBUS* CFG_SATA_DEVS_PER_BUS) #define CONFIG_ATA_PIIX 1 /*Supports ata_piix driver */ +#else +#undef CFG_SATA_MAXBUS +#undef CFG_SATA_DEVS_PER_BUS +#undef CFG_SATA_MAX_DEVICE +#undef CONFIG_ATA_PIIX +#endif + /************************************************************ * DISK Partition support @@ -190,7 +203,11 @@ /************************************************************ * Video/Keyboard support ************************************************************/ +#ifndef GRUSS_TESTING #define CONFIG_VIDEO /* To enable video controller support */ +#else +#undef CONFIG_VIDEO +#endif #define CONFIG_I8042_KBD #define CFG_ISA_IO 0 @@ -203,6 +220,7 @@ /* * PCI stuff */ +#ifndef GRUSS_TESTING #define CONFIG_PCI /* include pci support */ #define CONFIG_PCI_PNP /* pci plug-and-play */ #define CONFIG_PCI_SCAN_SHOW @@ -211,5 +229,11 @@ #define CFG_SECOND_PCI_IRQ 9 #define CFG_THIRD_PCI_IRQ 11 #define CFG_FORTH_PCI_IRQ 15 +#else +#undef CONFIG_PCI +#undef CONFIG_PCI_PNP +#undef CONFIG_PCI_SCAN_SHOW +#endif + #endif /* __CONFIG_H */ diff --git a/include/configs/stxxtc.h b/include/configs/stxxtc.h index 37a52cf..0dc9f8a 100644 --- a/include/configs/stxxtc.h +++ b/include/configs/stxxtc.h @@ -580,7 +580,6 @@ typedef unsigned int led_id_t; /* use board specific hardware */ #undef CONFIG_WATCHDOG /* watchdog disabled */ #define CONFIG_HW_WATCHDOG -#define CONFIG_SHOW_ACTIVITY /*****************************************************************************/ diff --git a/include/configs/v5fx30teval.h b/include/configs/v5fx30teval.h new file mode 100644 index 0000000..67d8d7f --- /dev/null +++ b/include/configs/v5fx30teval.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/*CPU*/ +#define CONFIG_440 1 +#define CONFIG_XILINX_ML507 1 +#include "../board/avnet/v5fx30teval/xparameters.h" + +/*Mem Map*/ +#define CFG_SDRAM_SIZE_MB 64 + +/*Env*/ +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE 0x20000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_OFFSET 0x1A0000 +#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET) + +/*Misc*/ +#define CFG_PROMPT "v5fx30t:/# " /* Monitor Command Prompt */ +#define CONFIG_PREBOOT "echo U-Boot is up and runnining;" + +/*Flash*/ +#define CFG_FLASH_SIZE (16*1024*1024) +#define CFG_MAX_FLASH_SECT 131 +#define MTDIDS_DEFAULT "nor0=v5fx30t-flash" +#define MTDPARTS_DEFAULT "mtdparts=v5fx30t-flash:-(user)" + +/*Generic Configs*/ +#include <configs/xilinx-ppc440.h> + +#endif /* __CONFIG_H */ diff --git a/include/configs/versatile.h b/include/configs/versatile.h index a88d356..c18a248 100644 --- a/include/configs/versatile.h +++ b/include/configs/versatile.h @@ -86,7 +86,7 @@ /* * NS16550 Configuration */ -#define CFG_PL011_SERIAL +#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK 24000000 #define CONFIG_PL01x_PORTS { (void *)CFG_SERIAL0, (void *)CFG_SERIAL1 } #define CONFIG_CONS_INDEX 0 diff --git a/include/configs/xilinx-ppc440-generic.h b/include/configs/xilinx-ppc440-generic.h new file mode 100644 index 0000000..4e8080b --- /dev/null +++ b/include/configs/xilinx-ppc440-generic.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/*CPU*/ +#define CONFIG_440 1 +#define CONFIG_XILINX_PPC440_GENERIC 1 +#include "../board/xilinx/ppc440-generic/xparameters.h" + +/*Mem Map*/ +#define CFG_SDRAM_SIZE_MB 256 + +/*Env*/ +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE 0x20000 +#define CFG_ENV_SECT_SIZE 0x20000 +#define CFG_ENV_OFFSET 0x340000 +#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET) + +/*Misc*/ +#define CFG_PROMPT "board:/# " /* Monitor Command Prompt */ +#define CONFIG_PREBOOT "echo U-Boot is up and runnining;" + +/*Flash*/ +#define CFG_FLASH_SIZE (32*1024*1024) +#define CFG_MAX_FLASH_SECT 259 +#define MTDIDS_DEFAULT "nor0=ml507-flash" +#define MTDPARTS_DEFAULT "mtdparts=ml507-flash:-(user)" + +/*Generic Configs*/ +#include <configs/xilinx-ppc440.h> + +#endif /* __CONFIG_H */ diff --git a/include/configs/xilinx-ppc440.h b/include/configs/xilinx-ppc440.h new file mode 100644 index 0000000..40293cd --- /dev/null +++ b/include/configs/xilinx-ppc440.h @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2008 + * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es + * This work has been supported by: QTechnology http://qtec.com/ + * 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __CONFIG_GEN_H +#define __CONFIG_GEN_H +/* +#define DEBUG +#define ET_DEBUG +*/ + /*CPU*/ +#define CONFIG_XILINX_440 1 +#define CONFIG_440 1 +#define CONFIG_4xx 1 + +/*Mem Map*/ +#define CFG_SDRAM_BASE 0x0 +#define CFG_MONITOR_BASE TEXT_BASE +#define CFG_MONITOR_LEN (192 * 1024) +#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128 * 1024) + +/*Uart*/ +#define CONFIG_XILINX_UARTLITE +#define CONFIG_BAUDRATE XPAR_UARTLITE_0_BAUDRATE +#define CFG_BAUDRATE_TABLE { XPAR_UARTLITE_0_BAUDRATE } +#define CONFIG_SERIAL_BASE XPAR_UARTLITE_0_BASEADDR + +/*Cmd*/ +#include <config_cmd_default.h> +#define CONFIG_CMD_ASKENV +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_DIAG +#define CONFIG_CMD_ELF +#define CONFIG_CMD_IRQ +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_JFFS2 +#define CONFIG_JFFS2_CMDLINE +#undef CONFIG_CMD_SPI +#undef CONFIG_CMD_I2C +#undef CONFIG_CMD_DTT +#undef CONFIG_CMD_NET +#undef CONFIG_CMD_PING +#undef CONFIG_CMD_DHCP +#undef CONFIG_CMD_EEPROM +#undef CONFIG_CMD_IMLS + +/*Misc*/ +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#define CFG_LONGHELP /* undef to save memory */ +#if defined(CONFIG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */ +#define CFG_LOAD_ADDR 0x00400000 /* default load address */ +#define CFG_EXTBDINFO 1 /* Extended board_into (bd_t) */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CONFIG_CMDLINE_EDITING /* add command line history */ +#define CONFIG_AUTO_COMPLETE /* add autocompletion support */ +#define CONFIG_LOOPW /* enable loopw command */ +#define CONFIG_MX_CYCLIC /* enable mdc/mwc commands */ +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ +#define CONFIG_VERSION_VARIABLE /* include version env variable */ +#define CFG_CONSOLE_INFO_QUIET /* don't print console @ startup */ +#define CFG_HUSH_PARSER /* Use the HUSH parser */ +#define CFG_PROMPT_HUSH_PS2 "> " +#define CONFIG_LOADS_ECHO /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate change */ +#define CFG_BOOTMAPSZ (8 << 20)/* Initial Memory map for Linux */ + +/*Stack*/ +#define CFG_INIT_RAM_ADDR 0x800000 /* Initial RAM address */ +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET +/*Speed*/ +#define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ + +/*Flash*/ +#define CFG_FLASH_BASE XPAR_FLASH_MEM0_BASEADDR +#define CFG_FLASH_CFI 1 +#define CONFIG_FLASH_CFI_DRIVER 1 +#define CFG_FLASH_EMPTY_INFO 1 +#define CFG_MAX_FLASH_BANKS 1 +#define CFG_FLASH_PROTECTION + +#endif /* __CONFIG_H */ diff --git a/include/image.h b/include/image.h index 9be806e..8c63686 100644 --- a/include/image.h +++ b/include/image.h @@ -85,6 +85,7 @@ #define IH_OS_RTEMS 18 /* RTEMS */ #define IH_OS_ARTOS 19 /* ARTOS */ #define IH_OS_UNITY 20 /* Unity OS */ +#define IH_OS_INTEGRITY 21 /* INTEGRITY */ /* * CPU Architecture Codes (supported by Linux) @@ -573,6 +574,7 @@ int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, int value_len); int fit_image_check_hashes (const void *fit, int noffset); +int fit_all_image_check_hashes (const void *fit); int fit_image_check_os (const void *fit, int noffset, uint8_t os); int fit_image_check_arch (const void *fit, int noffset, uint8_t arch); int fit_image_check_type (const void *fit, int noffset, uint8_t type); diff --git a/include/onenand_uboot.h b/include/onenand_uboot.h index 6605e4f..e960257 100644 --- a/include/onenand_uboot.h +++ b/include/onenand_uboot.h @@ -15,6 +15,7 @@ #define __UBOOT_ONENAND_H #include <linux/types.h> +#include <linux/mtd/mtd.h> struct mtd_info; struct erase_info; diff --git a/include/ppc440.h b/include/ppc440.h index 3584fd2..be8d3ff 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -2064,19 +2064,6 @@ #ifndef __ASSEMBLY__ -static inline u32 get_mcsr(void) -{ - u32 val; - - asm volatile("mfspr %0, 0x23c" : "=r" (val) :); - return val; -} - -static inline void set_mcsr(u32 val) -{ - asm volatile("mtspr 0x23c, %0" : "=r" (val) :); -} - #endif /* _ASMLANGUAGE */ #endif /* __PPC440_H__ */ diff --git a/include/ppc4xx.h b/include/ppc4xx.h index 59a3b06..e216663 100644 --- a/include/ppc4xx.h +++ b/include/ppc4xx.h @@ -203,6 +203,19 @@ typedef struct unsigned long pllPlbDiv; } PPC4xx_SYS_INFO; +static inline u32 get_mcsr(void) +{ + u32 val; + + asm volatile("mfspr %0, 0x23c" : "=r" (val) :); + return val; +} + +static inline void set_mcsr(u32 val) +{ + asm volatile("mtspr 0x23c, %0" : "=r" (val) :); +} + #endif /* __ASSEMBLY__ */ #endif /* __PPC4XX_H__ */ diff --git a/include/ppc4xx_enet.h b/include/ppc4xx_enet.h index b74c6fc..00669a7 100644 --- a/include/ppc4xx_enet.h +++ b/include/ppc4xx_enet.h @@ -376,6 +376,7 @@ typedef struct emac_4xx_hw_st { #define EMAC_M1_APP (0x08000000) #define EMAC_M1_RSVD (0x06000000) #define EMAC_M1_IST (0x01000000) +#define EMAC_M1_MF_1000GPCS (0x00C00000) #define EMAC_M1_MF_1000MBPS (0x00800000) /* 0's for 10MBPS */ #define EMAC_M1_MF_100MBPS (0x00400000) #define EMAC_M1_RFS_MASK (0x00380000) @@ -394,6 +395,8 @@ typedef struct emac_4xx_hw_st { #define EMAC_M1_MWSW (0x00007000) #define EMAC_M1_JUMBO_ENABLE (0x00000800) #define EMAC_M1_IPPA (0x000007c0) +#define EMAC_M1_IPPA_SET(id) (((id) & 0x1f) << 6) +#define EMAC_M1_IPPA_GET(id) (((id) >> 6) & 0x1f) #define EMAC_M1_OBCI_GT100 (0x00000020) #define EMAC_M1_OBCI_100 (0x00000018) #define EMAC_M1_OBCI_83 (0x00000010) diff --git a/lib_arm/bootm.c b/lib_arm/bootm.c index 6c2f37e..772fa7f 100644 --- a/lib_arm/bootm.c +++ b/lib_arm/bootm.c @@ -62,7 +62,6 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char *s; int machid = bd->bi_arch_number; void (*theKernel)(int zero, int arch, uint params); - int ret; #ifdef CONFIG_CMDLINE_TAG char *commandline = getenv ("bootargs"); @@ -125,7 +124,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) theKernel (0, machid, bd->bi_boot_params); /* does not return */ -error: + return 1; } diff --git a/lib_i386/bios_setup.c b/lib_i386/bios_setup.c index 75f04a0..33c842c 100644 --- a/lib_i386/bios_setup.c +++ b/lib_i386/bios_setup.c @@ -140,8 +140,9 @@ int bios_setup(void) { static int done=0; int vector; +#ifdef CONFIG_PCI struct pci_controller *pri_hose; - +#endif if (done) { return 0; } @@ -223,12 +224,13 @@ int bios_setup(void) * (This, ofcause break on multi hose systems, * but our PCI BIOS only support one hose anyway) */ +#ifdef CONFIG_PCI pri_hose = pci_bus_to_hose(0); if (NULL != pri_hose) { /* fill in last pci bus number for use by the realmode * PCI BIOS */ RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno; } - +#endif return 0; } diff --git a/lib_i386/board.c b/lib_i386/board.c index 55fa42a..f3da0a2 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -213,7 +213,7 @@ init_fnc_t *init_sequence[] = { NULL, }; -gd_t *global_data; +gd_t *gd; void start_i386boot (void) { @@ -226,7 +226,7 @@ void start_i386boot (void) show_boot_progress(0x21); - gd = global_data = &gd_data; + gd = &gd_data; /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); @@ -266,7 +266,7 @@ void start_i386boot (void) int i; ulong reg; char *s, *e; - uchar tmp[64]; + char tmp[64]; i = getenv_r ("ethaddr", tmp, sizeof (tmp)); s = (i > 0) ? tmp : NULL; @@ -412,7 +412,10 @@ void hang (void) unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[]) { /* - * Nios function pointers are address >> 1 + * TODO: Test this function - changed to fix compiler error. + * Original code was: + * return (entry >> 1) (argc, argv); + * with a comment about Nios function pointers are address >> 1 */ - return (entry >> 1) (argc, argv); + return (entry) (argc, argv); } diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c index 522d7ad..613e339 100644 --- a/lib_i386/bootm.c +++ b/lib_i386/bootm.c @@ -34,7 +34,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) void *base_ptr; ulong os_data, os_len; image_header_t *hdr; - int ret; + #if defined(CONFIG_FIT) const void *data; size_t len; diff --git a/lib_i386/video_bios.c b/lib_i386/video_bios.c index 45f78e2..ce96a3e 100644 --- a/lib_i386/video_bios.c +++ b/lib_i386/video_bios.c @@ -136,6 +136,8 @@ static u32 probe_pci_video(void) #endif +#ifdef CONFIG_VIDEO + static int probe_isa_video(void) { u32 ptr; @@ -217,3 +219,4 @@ int video_bios_init(void) return 1; } +#endif diff --git a/lib_mips/Makefile b/lib_mips/Makefile index 8176437..7967e58 100644 --- a/lib_mips/Makefile +++ b/lib_mips/Makefile @@ -28,7 +28,11 @@ LIB = $(obj)lib$(ARCH).a SOBJS-y += COBJS-y += board.o +ifeq ($(CONFIG_QEMU_MIPS),y) +COBJS-y += bootm_qemu_mips.o +else COBJS-y += bootm.o +endif COBJS-y += time.o SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) diff --git a/lib_mips/bootm.c b/lib_mips/bootm.c index c1bf21e..dced28c 100644 --- a/lib_mips/bootm.c +++ b/lib_mips/bootm.c @@ -73,7 +73,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) linux_env_set ("memsize", env_buf); sprintf (env_buf, "0x%08X", (uint) UNCACHED_SDRAM (images->rd_start)); - linux_env_set ("images->rd_start", env_buf); + linux_env_set ("initrd_start", env_buf); sprintf (env_buf, "0x%X", (uint) (images->rd_end - images->rd_start)); linux_env_set ("initrd_size", env_buf); diff --git a/lib_mips/bootm_qemu_mips.c b/lib_mips/bootm_qemu_mips.c new file mode 100644 index 0000000..cc70fa9 --- /dev/null +++ b/lib_mips/bootm_qemu_mips.c @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2008 + * Jean-Christophe PLAGNIOL-VILLARD <jcplagniol@jcrosoft.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 + * + */ + +#include <common.h> +#include <command.h> +#include <image.h> +#include <asm/byteorder.h> +#include <asm/addrspace.h> + +DECLARE_GLOBAL_DATA_PTR; + +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + void (*theKernel) (int, char **, char **, int *); + char *bootargs = getenv ("bootargs"); + char *start; + uint len; + + /* find kernel entry point */ + theKernel = (void (*)(int, char **, char **, int *))images->ep; + + show_boot_progress (15); + + debug ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) theKernel); + + gd->bd->bi_boot_params = gd->bd->bi_memstart + (16 << 20) - 256; + debug ("%-12s= 0x%08lX\n", "boot_params", (ulong)gd->bd->bi_boot_params); + + /* set Magic */ + *(int32_t *)(gd->bd->bi_boot_params - 4) = 0x12345678; + /* set ram_size */ + *(int32_t *)(gd->bd->bi_boot_params - 8) = gd->ram_size; + + start = (char*)gd->bd->bi_boot_params; + + len = strlen(bootargs); + + strncpy(start, bootargs, len + 1); + + start += len; + + len = images->rd_end - images->rd_start; + if (len > 0) { + start += sprintf(start," rd_start=0x%08X rd_size=0x%0X", + (uint) UNCACHED_SDRAM (images->rd_start), + (uint) len); + } + + /* we assume that the kernel is in place */ + printf ("\nStarting kernel ...\n\n"); + + theKernel (0, NULL, NULL, 0); + /* does not return */ + return 1; +} diff --git a/lib_ppc/interrupts.c b/lib_ppc/interrupts.c index b803952..c5951e9 100644 --- a/lib_ppc/interrupts.c +++ b/lib_ppc/interrupts.c @@ -32,7 +32,12 @@ #endif #ifdef CONFIG_SHOW_ACTIVITY - extern void board_show_activity (ulong); +void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity"))); + +void __board_show_activity (ulong dummy) +{ + return; +} #endif /* CONFIG_SHOW_ACTIVITY */ #ifndef CFG_WATCHDOG_FREQ diff --git a/tools/env/README b/tools/env/README index f8a644e..91e679a 100644 --- a/tools/env/README +++ b/tools/env/README @@ -22,9 +22,11 @@ following lines are relevant: #define DEVICE1_OFFSET 0x0000 #define ENV1_SIZE 0x4000 #define DEVICE1_ESIZE 0x4000 +#define DEVICE1_ENVSECTORS 2 #define DEVICE2_OFFSET 0x0000 #define ENV2_SIZE 0x4000 #define DEVICE2_ESIZE 0x4000 +#define DEVICE2_ENVSECTORS 2 Current configuration matches the environment layout of the TRAB board. @@ -46,3 +48,7 @@ then 1 sector. DEVICEx_ESIZE defines the size of the first sector in the flash partition where the environment resides. + +DEVICEx_ENVSECTORS defines the number of sectors that may be used for +this environment instance. On NAND this is used to limit the range +within which bad blocks are skipped, on NOR it is not used. diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index e4fc02d..b6036c8 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -2,6 +2,9 @@ * (C) Copyright 2000-2008 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * + * (C) Copyright 2008 + * Guennadi Liakhovetski, DENX Software Engineering, lg@denx.de. + * * See file CREDITS for list of people who contributed to this * project. * @@ -45,36 +48,75 @@ #define CMD_GETENV "fw_printenv" #define CMD_SETENV "fw_setenv" -typedef struct envdev_s { +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +struct envdev_s { char devname[16]; /* Device name */ ulong devoff; /* Device offset */ ulong env_size; /* environment size */ ulong erase_size; /* device erase size */ -} envdev_t; + ulong env_sectors; /* number of environment sectors */ + uint8_t mtd_type; /* type of the MTD device */ +}; -static envdev_t envdevices[2]; -static int curdev; +static struct envdev_s envdevices[2] = +{ + { + .mtd_type = MTD_ABSENT, + }, { + .mtd_type = MTD_ABSENT, + }, +}; +static int dev_current; #define DEVNAME(i) envdevices[(i)].devname #define DEVOFFSET(i) envdevices[(i)].devoff #define ENVSIZE(i) envdevices[(i)].env_size #define DEVESIZE(i) envdevices[(i)].erase_size +#define ENVSECTORS(i) envdevices[(i)].env_sectors +#define DEVTYPE(i) envdevices[(i)].mtd_type -#define CFG_ENV_SIZE ENVSIZE(curdev) +#define CFG_ENV_SIZE ENVSIZE(dev_current) #define ENV_SIZE getenvsize() -typedef struct environment_s { - ulong crc; /* CRC32 over data bytes */ - unsigned char flags; /* active or obsolete */ - char *data; -} env_t; +struct env_image_single { + uint32_t crc; /* CRC32 over data bytes */ + char data[]; +}; -static env_t environment; +struct env_image_redundant { + uint32_t crc; /* CRC32 over data bytes */ + unsigned char flags; /* active or obsolete */ + char data[]; +}; + +enum flag_scheme { + FLAG_NONE, + FLAG_BOOLEAN, + FLAG_INCREMENTAL, +}; + +struct environment { + void *image; + uint32_t *crc; + unsigned char *flags; + char *data; + enum flag_scheme flag_scheme; +}; + +static struct environment environment = { + .flag_scheme = FLAG_NONE, +}; static int HaveRedundEnv = 0; static unsigned char active_flag = 1; +/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */ static unsigned char obsolete_flag = 0; @@ -157,7 +199,7 @@ static char default_environment[] = { #ifdef CONFIG_EXTRA_ENV_SETTINGS CONFIG_EXTRA_ENV_SETTINGS #endif - "\0" /* Termimate env_t data with 2 NULs */ + "\0" /* Termimate struct environment data with 2 NULs */ }; static int flash_io (int mode); @@ -186,7 +228,7 @@ char *fw_getenv (char *name) char *env, *nxt; if (env_init ()) - return (NULL); + return NULL; for (env = environment.data; *env; env = nxt + 1) { char *val; @@ -195,15 +237,15 @@ char *fw_getenv (char *name) if (nxt >= &environment.data[ENV_SIZE]) { fprintf (stderr, "## Error: " "environment not terminated\n"); - return (NULL); + return NULL; } } val = envmatch (name, env); if (!val) continue; - return (val); + return val; } - return (NULL); + return NULL; } /* @@ -217,7 +259,7 @@ int fw_printenv (int argc, char *argv[]) int rc = 0; if (env_init ()) - return (-1); + return -1; if (argc == 1) { /* Print all env variables */ for (env = environment.data; *env; env = nxt + 1) { @@ -225,13 +267,13 @@ int fw_printenv (int argc, char *argv[]) if (nxt >= &environment.data[ENV_SIZE]) { fprintf (stderr, "## Error: " "environment not terminated\n"); - return (-1); + return -1; } } printf ("%s\n", env); } - return (0); + return 0; } if (strcmp (argv[1], "-n") == 0) { @@ -241,7 +283,7 @@ int fw_printenv (int argc, char *argv[]) if (argc != 2) { fprintf (stderr, "## Error: " "`-n' option requires exactly one argument\n"); - return (-1); + return -1; } } else { n_flag = 0; @@ -257,7 +299,7 @@ int fw_printenv (int argc, char *argv[]) if (nxt >= &environment.data[ENV_SIZE]) { fprintf (stderr, "## Error: " "environment not terminated\n"); - return (-1); + return -1; } } val = envmatch (name, env); @@ -276,11 +318,11 @@ int fw_printenv (int argc, char *argv[]) } } - return (rc); + return rc; } /* - * Deletes or sets environment variables. Returns errno style error codes: + * Deletes or sets environment variables. Returns -1 and sets errno error codes: * 0 - OK * EINVAL - need at least 1 argument * EROFS - certain variables ("ethaddr", "serial#") cannot be @@ -295,11 +337,12 @@ int fw_setenv (int argc, char *argv[]) char *name; if (argc < 2) { - return (EINVAL); + errno = EINVAL; + return -1; } if (env_init ()) - return (errno); + return -1; name = argv[1]; @@ -311,7 +354,8 @@ int fw_setenv (int argc, char *argv[]) if (nxt >= &environment.data[ENV_SIZE]) { fprintf (stderr, "## Error: " "environment not terminated\n"); - return (EINVAL); + errno = EINVAL; + return -1; } } if ((oldval = envmatch (name, env)) != NULL) @@ -328,7 +372,8 @@ int fw_setenv (int argc, char *argv[]) if ((strcmp (name, "ethaddr") == 0) || (strcmp (name, "serial#") == 0)) { fprintf (stderr, "Can't overwrite \"%s\"\n", name); - return (EROFS); + errno = EROFS; + return -1; } if (*++nxt == '\0') { @@ -367,7 +412,7 @@ int fw_setenv (int argc, char *argv[]) fprintf (stderr, "Error: environment overflow, \"%s\" deleted\n", name); - return (-1); + return -1; } while ((*env = *name++) != '\0') env++; @@ -383,195 +428,430 @@ int fw_setenv (int argc, char *argv[]) WRITE_FLASH: - /* Update CRC */ - environment.crc = crc32 (0, (uint8_t*) environment.data, ENV_SIZE); + /* + * Update CRC + */ + *environment.crc = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); /* write environment back to flash */ if (flash_io (O_RDWR)) { fprintf (stderr, "Error: can't write fw_env to flash\n"); - return (-1); + return -1; } - return (0); + return 0; } -static int flash_io (int mode) +/* + * Test for bad block on NAND, just returns 0 on NOR, on NAND: + * 0 - block is good + * > 0 - block is bad + * < 0 - failed to test + */ +static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart) { - int fd, fdr, rc, otherdev, len, resid; - struct erase_info_user erase; - char *data = NULL; + if (mtd_type == MTD_NANDFLASH) { + int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart); - if ((fd = open (DEVNAME (curdev), mode)) < 0) { - fprintf (stderr, - "Can't open %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); + if (badblock < 0) { + perror ("Cannot read bad block mark"); + return badblock; + } + + if (badblock) { +#ifdef DEBUG + fprintf (stderr, "Bad block at 0x%llx, " + "skipping\n", *blockstart); +#endif + return badblock; + } } - len = sizeof (environment.crc); - if (HaveRedundEnv) { - len += sizeof (environment.flags); + return 0; +} + +/* + * Read data from flash at an offset into a provided buffer. On NAND it skips + * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from + * the DEVOFFSET (dev) block. On NOR the loop is only run once. + */ +static int flash_read_buf (int dev, int fd, void *buf, size_t count, + off_t offset, uint8_t mtd_type) +{ + size_t blocklen; /* erase / write length - one block on NAND, + 0 on NOR */ + size_t processed = 0; /* progress counter */ + size_t readlen = count; /* current read length */ + off_t top_of_range; /* end of the last block we may use */ + off_t block_seek; /* offset inside the current block to the start + of the data */ + loff_t blockstart; /* running start of the current block - + MEMGETBADBLOCK needs 64 bits */ + int rc; + + /* + * Start of the first block to be read, relies on the fact, that + * erase sector size is always a power of 2 + */ + blockstart = offset & ~(DEVESIZE (dev) - 1); + + /* Offset inside a block */ + block_seek = offset - blockstart; + + if (mtd_type == MTD_NANDFLASH) { + /* + * NAND: calculate which blocks we are reading. We have + * to read one block at a time to skip bad blocks. + */ + blocklen = DEVESIZE (dev); + + /* + * To calculate the top of the range, we have to use the + * global DEVOFFSET (dev), which can be different from offset + */ + top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) + + ENVSECTORS (dev) * blocklen; + + /* Limit to one block for the first read */ + if (readlen > blocklen - block_seek) + readlen = blocklen - block_seek; + } else { + blocklen = 0; + top_of_range = offset + count; } - if (mode == O_RDWR) { - if (HaveRedundEnv) { - /* switch to next partition for writing */ - otherdev = !curdev; - if ((fdr = open (DEVNAME (otherdev), mode)) < 0) { - fprintf (stderr, - "Can't open %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } - } else { - otherdev = curdev; - fdr = fd; - } - printf ("Unlocking flash...\n"); - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (otherdev); - ioctl (fdr, MEMUNLOCK, &erase); + /* This only runs once on NOR flash */ + while (processed < count) { + rc = flash_bad_block (fd, mtd_type, &blockstart); + if (rc < 0) /* block test failed */ + return -1; - if (HaveRedundEnv) { - erase.length = DEVESIZE (curdev); - erase.start = DEVOFFSET (curdev); - ioctl (fd, MEMUNLOCK, &erase); - environment.flags = active_flag; + if (blockstart + block_seek + readlen > top_of_range) { + /* End of range is reached */ + fprintf (stderr, + "Too few good blocks within range\n"); + return -1; } - printf ("Done\n"); - resid = DEVESIZE (otherdev) - CFG_ENV_SIZE; - if (resid) { - if ((data = malloc (resid)) == NULL) { - fprintf (stderr, - "Cannot malloc %d bytes: %s\n", - resid, - strerror (errno)); - return (-1); - } - if (lseek (fdr, DEVOFFSET (otherdev) + CFG_ENV_SIZE, SEEK_SET) - == -1) { - fprintf (stderr, "seek error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } - if ((rc = read (fdr, data, resid)) != resid) { - fprintf (stderr, - "read error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); - } + if (rc) { /* block is bad */ + blockstart += blocklen; + continue; } - printf ("Erasing old environment...\n"); + /* + * If a block is bad, we retry in the next block at the same + * offset - see common/env_nand.c::writeenv() + */ + lseek (fd, blockstart + block_seek, SEEK_SET); - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (otherdev); - if (ioctl (fdr, MEMERASE, &erase) != 0) { - fprintf (stderr, "MTD erase error on %s: %s\n", - DEVNAME (otherdev), - strerror (errno)); - return (-1); + rc = read (fd, buf + processed, readlen); + if (rc != readlen) { + fprintf (stderr, "Read error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; } +#ifdef DEBUG + fprintf (stderr, "Read 0x%x bytes at 0x%llx\n", + rc, blockstart + block_seek); +#endif + processed += readlen; + readlen = min (blocklen, count - processed); + block_seek = 0; + blockstart += blocklen; + } + + return processed; +} + +/* + * Write count bytes at offset, but stay within ENVSETCORS (dev) sectors of + * DEVOFFSET (dev). Similar to the read case above, on NOR we erase and write + * the whole data at once. + */ +static int flash_write_buf (int dev, int fd, void *buf, size_t count, + off_t offset, uint8_t mtd_type) +{ + void *data; + struct erase_info_user erase; + size_t blocklen; /* length of NAND block / NOR erase sector */ + size_t erase_len; /* whole area that can be erased - may include + bad blocks */ + size_t erasesize; /* erase / write length - one block on NAND, + whole area on NOR */ + size_t processed = 0; /* progress counter */ + size_t write_total; /* total size to actually write - excludinig + bad blocks */ + off_t erase_offset; /* offset to the first erase block (aligned) + below offset */ + off_t block_seek; /* offset inside the erase block to the start + of the data */ + off_t top_of_range; /* end of the last block we may use */ + loff_t blockstart; /* running start of the current block - + MEMGETBADBLOCK needs 64 bits */ + int rc; + + blocklen = DEVESIZE (dev); + + /* Erase sector size is always a power of 2 */ + top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) + + ENVSECTORS (dev) * blocklen; - printf ("Done\n"); + erase_offset = offset & ~(blocklen - 1); - printf ("Writing environment to %s...\n", DEVNAME (otherdev)); - if (lseek (fdr, DEVOFFSET (otherdev), SEEK_SET) == -1) { + /* Maximum area we may use */ + erase_len = top_of_range - erase_offset; + + blockstart = erase_offset; + /* Offset inside a block */ + block_seek = offset - erase_offset; + + /* + * Data size we actually have to write: from the start of the block + * to the start of the data, then count bytes of data, and to the + * end of the block + */ + write_total = (block_seek + count + blocklen - 1) & ~(blocklen - 1); + + /* + * Support data anywhere within erase sectors: read out the complete + * area to be erased, replace the environment image, write the whole + * block back again. + */ + if (write_total > count) { + data = malloc (erase_len); + if (!data) { fprintf (stderr, - "seek error on %s: %s\n", - DEVNAME (otherdev), strerror (errno)); - return (-1); + "Cannot malloc %u bytes: %s\n", + erase_len, strerror (errno)); + return -1; } - if (write (fdr, &environment, len) != len) { - fprintf (stderr, - "CRC write error on %s: %s\n", - DEVNAME (otherdev), strerror (errno)); - return (-1); + + rc = flash_read_buf (dev, fd, data, write_total, erase_offset, + mtd_type); + if (write_total != rc) + return -1; + + /* Overwrite the old environment */ + memcpy (data + block_seek, buf, count); + } else { + /* + * We get here, iff offset is block-aligned and count is a + * multiple of blocklen - see write_total calculation above + */ + data = buf; + } + + if (mtd_type == MTD_NANDFLASH) { + /* + * NAND: calculate which blocks we are writing. We have + * to write one block at a time to skip bad blocks. + */ + erasesize = blocklen; + } else { + erasesize = erase_len; + } + + erase.length = erasesize; + + /* This only runs once on NOR flash */ + while (processed < write_total) { + rc = flash_bad_block (fd, mtd_type, &blockstart); + if (rc < 0) /* block test failed */ + return rc; + + if (blockstart + erasesize > top_of_range) { + fprintf (stderr, "End of range reached, aborting\n"); + return -1; } - if (write (fdr, environment.data, ENV_SIZE) != ENV_SIZE) { + + if (rc) { /* block is bad */ + blockstart += blocklen; + continue; + } + + erase.start = blockstart; + ioctl (fd, MEMUNLOCK, &erase); + + if (ioctl (fd, MEMERASE, &erase) != 0) { + fprintf (stderr, "MTD erase error on %s: %s\n", + DEVNAME (dev), + strerror (errno)); + return -1; + } + + if (lseek (fd, blockstart, SEEK_SET) == -1) { fprintf (stderr, - "Write error on %s: %s\n", - DEVNAME (otherdev), strerror (errno)); - return (-1); + "Seek error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; } - if (resid) { - if (write (fdr, data, resid) != resid) { - fprintf (stderr, - "write error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - free (data); + +#ifdef DEBUG + printf ("Write 0x%x bytes at 0x%llx\n", erasesize, blockstart); +#endif + if (write (fd, data + processed, erasesize) != erasesize) { + fprintf (stderr, "Write error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; } + + ioctl (fd, MEMLOCK, &erase); + + processed += blocklen; + block_seek = 0; + blockstart += blocklen; + } + + if (write_total > count) + free (data); + + return processed; +} + +/* + * Set obsolete flag at offset - NOR flash only + */ +static int flash_flag_obsolete (int dev, int fd, off_t offset) +{ + int rc; + + /* This relies on the fact, that obsolete_flag == 0 */ + rc = lseek (fd, offset, SEEK_SET); + if (rc < 0) { + fprintf (stderr, "Cannot seek to set the flag on %s \n", + DEVNAME (dev)); + return rc; + } + rc = write (fd, &obsolete_flag, sizeof (obsolete_flag)); + if (rc < 0) + perror ("Could not set obsolete flag"); + + return rc; +} + +static int flash_write (int fd_current, int fd_target, int dev_target) +{ + int rc; + + switch (environment.flag_scheme) { + case FLAG_NONE: + break; + case FLAG_INCREMENTAL: + (*environment.flags)++; + break; + case FLAG_BOOLEAN: + *environment.flags = active_flag; + break; + default: + fprintf (stderr, "Unimplemented flash scheme %u \n", + environment.flag_scheme); + return -1; + } + +#ifdef DEBUG + printf ("Writing new environment at 0x%lx on %s\n", + DEVOFFSET (dev_target), DEVNAME (dev_target)); +#endif + rc = flash_write_buf (dev_target, fd_target, environment.image, + CFG_ENV_SIZE, DEVOFFSET (dev_target), + DEVTYPE(dev_target)); + if (rc < 0) + return rc; + + if (environment.flag_scheme == FLAG_BOOLEAN) { + /* Have to set obsolete flag */ + off_t offset = DEVOFFSET (dev_current) + + offsetof (struct env_image_redundant, flags); +#ifdef DEBUG + printf ("Setting obsolete flag in environment at 0x%lx on %s\n", + DEVOFFSET (dev_current), DEVNAME (dev_current)); +#endif + flash_flag_obsolete (dev_current, fd_current, offset); + } + + return 0; +} + +static int flash_read (int fd) +{ + struct mtd_info_user mtdinfo; + int rc; + + rc = ioctl (fd, MEMGETINFO, &mtdinfo); + if (rc < 0) { + perror ("Cannot get MTD information"); + return -1; + } + + if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) { + fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type); + return -1; + } + + DEVTYPE(dev_current) = mtdinfo.type; + + rc = flash_read_buf (dev_current, fd, environment.image, CFG_ENV_SIZE, + DEVOFFSET (dev_current), mtdinfo.type); + + return (rc != CFG_ENV_SIZE) ? -1 : 0; +} + +static int flash_io (int mode) +{ + int fd_current, fd_target, rc, dev_target; + + /* dev_current: fd_current, erase_current */ + fd_current = open (DEVNAME (dev_current), mode); + if (fd_current < 0) { + fprintf (stderr, + "Can't open %s: %s\n", + DEVNAME (dev_current), strerror (errno)); + return -1; + } + + if (mode == O_RDWR) { if (HaveRedundEnv) { - /* change flag on current active env partition */ - if (lseek (fd, DEVOFFSET (curdev) + sizeof (ulong), SEEK_SET) - == -1) { - fprintf (stderr, "seek error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - if (write (fd, &obsolete_flag, sizeof (obsolete_flag)) != - sizeof (obsolete_flag)) { + /* switch to next partition for writing */ + dev_target = !dev_current; + /* dev_target: fd_target, erase_target */ + fd_target = open (DEVNAME (dev_target), mode); + if (fd_target < 0) { fprintf (stderr, - "Write error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); + "Can't open %s: %s\n", + DEVNAME (dev_target), + strerror (errno)); + rc = -1; + goto exit; } + } else { + dev_target = dev_current; + fd_target = fd_current; } - printf ("Done\n"); - printf ("Locking ...\n"); - erase.length = DEVESIZE (otherdev); - erase.start = DEVOFFSET (otherdev); - ioctl (fdr, MEMLOCK, &erase); + + rc = flash_write (fd_current, fd_target, dev_target); + if (HaveRedundEnv) { - erase.length = DEVESIZE (curdev); - erase.start = DEVOFFSET (curdev); - ioctl (fd, MEMLOCK, &erase); - if (close (fdr)) { + if (close (fd_target)) { fprintf (stderr, "I/O error on %s: %s\n", - DEVNAME (otherdev), + DEVNAME (dev_target), strerror (errno)); - return (-1); + rc = -1; } } - printf ("Done\n"); } else { - - if (lseek (fd, DEVOFFSET (curdev), SEEK_SET) == -1) { - fprintf (stderr, - "seek error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - if (read (fd, &environment, len) != len) { - fprintf (stderr, - "CRC read error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } - if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) { - fprintf (stderr, - "Read error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); - } + rc = flash_read (fd_current); } - if (close (fd)) { +exit: + if (close (fd_current)) { fprintf (stderr, - "I/O error on %s: %s\n", - DEVNAME (curdev), strerror (errno)); - return (-1); + "I/O error on %s: %s\n", + DEVNAME (dev_current), strerror (errno)); + return -1; } - /* everything ok */ - return (0); + return rc; } /* @@ -585,10 +865,10 @@ static char *envmatch (char * s1, char * s2) while (*s1 == *s2++) if (*s1++ == '=') - return (s2); + return s2; if (*s1 == '\0' && *(s2 - 1) == '=') - return (s2); - return (NULL); + return s2; + return NULL; } /* @@ -596,108 +876,156 @@ static char *envmatch (char * s1, char * s2) */ static int env_init (void) { + int crc0, crc0_ok; + char flag0; + void *addr0; + int crc1, crc1_ok; - char *addr1; + char flag1; + void *addr1; - int crc2, crc2_ok; - char flag1, flag2, *addr2; + struct env_image_single *single; + struct env_image_redundant *redundant; if (parse_config ()) /* should fill envdevices */ - return 1; + return -1; - if ((addr1 = calloc (1, ENV_SIZE)) == NULL) { + addr0 = calloc (1, CFG_ENV_SIZE); + if (addr0 == NULL) { fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", - ENV_SIZE); - return (errno); + CFG_ENV_SIZE); + return -1; } /* read environment from FLASH to local buffer */ - environment.data = addr1; - curdev = 0; - if (flash_io (O_RDONLY)) { - return (errno); + environment.image = addr0; + + if (HaveRedundEnv) { + redundant = addr0; + environment.crc = &redundant->crc; + environment.flags = &redundant->flags; + environment.data = redundant->data; + } else { + single = addr0; + environment.crc = &single->crc; + environment.flags = NULL; + environment.data = single->data; } - crc1_ok = ((crc1 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE)) - == environment.crc); + dev_current = 0; + if (flash_io (O_RDONLY)) + return -1; + + crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); + crc0_ok = (crc0 == *environment.crc); if (!HaveRedundEnv) { - if (!crc1_ok) { + if (!crc0_ok) { fprintf (stderr, "Warning: Bad CRC, using default environment\n"); memcpy(environment.data, default_environment, sizeof default_environment); } } else { - flag1 = environment.flags; + flag0 = *environment.flags; - curdev = 1; - if ((addr2 = calloc (1, ENV_SIZE)) == NULL) { + dev_current = 1; + addr1 = calloc (1, CFG_ENV_SIZE); + if (addr1 == NULL) { fprintf (stderr, "Not enough memory for environment (%ld bytes)\n", - ENV_SIZE); - return (errno); + CFG_ENV_SIZE); + return -1; } - environment.data = addr2; + redundant = addr1; - if (flash_io (O_RDONLY)) { - return (errno); + /* + * have to set environment.image for flash_read(), careful - + * other pointers in environment still point inside addr0 + */ + environment.image = addr1; + if (flash_io (O_RDONLY)) + return -1; + + /* Check flag scheme compatibility */ + if (DEVTYPE(dev_current) == MTD_NORFLASH && + DEVTYPE(!dev_current) == MTD_NORFLASH) { + environment.flag_scheme = FLAG_BOOLEAN; + } else if (DEVTYPE(dev_current) == MTD_NANDFLASH && + DEVTYPE(!dev_current) == MTD_NANDFLASH) { + environment.flag_scheme = FLAG_INCREMENTAL; + } else { + fprintf (stderr, "Incompatible flash types!\n"); + return -1; } - crc2_ok = ((crc2 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE)) - == environment.crc); - flag2 = environment.flags; - - if (crc1_ok && !crc2_ok) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; - curdev = 0; - free (addr2); - } else if (!crc1_ok && crc2_ok) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; - curdev = 1; - free (addr1); - } else if (!crc1_ok && !crc2_ok) { + crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE); + crc1_ok = (crc1 == redundant->crc); + flag1 = redundant->flags; + + if (crc0_ok && !crc1_ok) { + dev_current = 0; + } else if (!crc0_ok && crc1_ok) { + dev_current = 1; + } else if (!crc0_ok && !crc1_ok) { fprintf (stderr, "Warning: Bad CRC, using default environment\n"); - memcpy(environment.data, default_environment, sizeof default_environment); - curdev = 0; - free (addr1); - } else if (flag1 == active_flag && flag2 == obsolete_flag) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; - curdev = 0; - free (addr2); - } else if (flag1 == obsolete_flag && flag2 == active_flag) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; - curdev = 1; - free (addr1); - } else if (flag1 == flag2) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; - curdev = 0; - free (addr2); - } else if (flag1 == 0xFF) { - environment.data = addr1; - environment.flags = flag1; - environment.crc = crc1; - curdev = 0; - free (addr2); - } else if (flag2 == 0xFF) { - environment.data = addr2; - environment.flags = flag2; - environment.crc = crc2; - curdev = 1; + memcpy (environment.data, default_environment, + sizeof default_environment); + dev_current = 0; + } else { + switch (environment.flag_scheme) { + case FLAG_BOOLEAN: + if (flag0 == active_flag && + flag1 == obsolete_flag) { + dev_current = 0; + } else if (flag0 == obsolete_flag && + flag1 == active_flag) { + dev_current = 1; + } else if (flag0 == flag1) { + dev_current = 0; + } else if (flag0 == 0xFF) { + dev_current = 0; + } else if (flag1 == 0xFF) { + dev_current = 1; + } else { + dev_current = 0; + } + break; + case FLAG_INCREMENTAL: + if ((flag0 == 255 && flag1 == 0) || + flag1 > flag0) + dev_current = 1; + else if ((flag1 == 255 && flag0 == 0) || + flag0 > flag1) + dev_current = 0; + else /* flags are equal - almost impossible */ + dev_current = 0; + break; + default: + fprintf (stderr, "Unknown flag scheme %u \n", + environment.flag_scheme); + return -1; + } + } + + /* + * If we are reading, we don't need the flag and the CRC any + * more, if we are writing, we will re-calculate CRC and update + * flags before writing out + */ + if (dev_current) { + environment.image = addr1; + environment.crc = &redundant->crc; + environment.flags = &redundant->flags; + environment.data = redundant->data; + free (addr0); + } else { + environment.image = addr0; + /* Other pointers are already set */ free (addr1); } } - return (0); + return 0; } @@ -710,18 +1038,20 @@ static int parse_config () if (get_config (CONFIG_FILE)) { fprintf (stderr, "Cannot parse config file: %s\n", strerror (errno)); - return 1; + return -1; } #else strcpy (DEVNAME (0), DEVICE1_NAME); DEVOFFSET (0) = DEVICE1_OFFSET; ENVSIZE (0) = ENV1_SIZE; DEVESIZE (0) = DEVICE1_ESIZE; + ENVSECTORS (0) = DEVICE1_ENVSECTORS; #ifdef HAVE_REDUND strcpy (DEVNAME (1), DEVICE2_NAME); DEVOFFSET (1) = DEVICE2_OFFSET; ENVSIZE (1) = ENV2_SIZE; DEVESIZE (1) = DEVICE2_ESIZE; + ENVSECTORS (1) = DEVICE2_ENVSECTORS; HaveRedundEnv = 1; #endif #endif @@ -729,14 +1059,14 @@ static int parse_config () fprintf (stderr, "Cannot access MTD device %s: %s\n", DEVNAME (0), strerror (errno)); - return 1; + return -1; } if (HaveRedundEnv && stat (DEVNAME (1), &st)) { fprintf (stderr, "Cannot access MTD device %s: %s\n", DEVNAME (1), strerror (errno)); - return 1; + return -1; } return 0; } @@ -749,21 +1079,28 @@ static int get_config (char *fname) int rc; char dump[128]; - if ((fp = fopen (fname, "r")) == NULL) { - return 1; - } - - while ((i < 2) && ((rc = fscanf (fp, "%s %lx %lx %lx", - DEVNAME (i), - &DEVOFFSET (i), - &ENVSIZE (i), - &DEVESIZE (i) )) != EOF)) { + fp = fopen (fname, "r"); + if (fp == NULL) + return -1; + while (i < 2 && fgets (dump, sizeof (dump), fp)) { /* Skip incomplete conversions and comment strings */ - if ((rc < 3) || (*DEVNAME (i) == '#')) { - fgets (dump, sizeof (dump), fp); /* Consume till end */ + if (dump[0] == '#') continue; - } + + rc = sscanf (dump, "%s %lx %lx %lx %lx", + DEVNAME (i), + &DEVOFFSET (i), + &ENVSIZE (i), + &DEVESIZE (i), + &ENVSECTORS (i)); + + if (rc < 4) + continue; + + if (rc < 5) + /* Default - 1 sector */ + ENVSECTORS (i) = 1; i++; } @@ -772,7 +1109,7 @@ static int get_config (char *fname) HaveRedundEnv = i - 1; if (!i) { /* No valid entries found */ errno = EINVAL; - return 1; + return -1; } else return 0; } diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config index 2432bd8..0fe37c9 100644 --- a/tools/env/fw_env.config +++ b/tools/env/fw_env.config @@ -1,7 +1,11 @@ # Configuration file for fw_(printenv/saveenv) utility. # Up to two entries are valid, in this case the redundand # environment sector is assumed present. +# Notice, that the "Number of sectors" is ignored on NOR. -# MTD device name Device offset Env. size Flash sector size +# MTD device name Device offset Env. size Flash sector size Number of sectors /dev/mtd1 0x0000 0x4000 0x4000 /dev/mtd2 0x0000 0x4000 0x4000 + +# NAND example +#/dev/mtd0 0x4000 0x4000 0x20000 2 |