Browse Source

Merge branch 'u-boot-pxa/master' into 'u-boot-arm/master'

Albert ARIBAUD 12 years ago
parent
commit
e825b100d2
100 changed files with 3169 additions and 746 deletions
  1. 22 0
      Makefile
  2. 16 0
      README
  3. 0 7
      arch/arm/cpu/arm926ejs/mxs/spl_boot.c
  4. 0 7
      arch/arm/cpu/arm926ejs/spear/spl.c
  5. 1 1
      arch/arm/cpu/pxa/pxa2xx.c
  6. 0 11
      arch/arm/include/asm/arch-pxa/hardware.h
  7. 0 6
      arch/arm/lib/board.c
  8. 0 5
      arch/avr32/lib/board.c
  9. 0 14
      arch/blackfin/lib/board.c
  10. 0 7
      arch/m68k/lib/board.c
  11. 4 0
      arch/microblaze/include/asm/processor.h
  12. 30 35
      arch/microblaze/lib/board.c
  13. 0 7
      arch/mips/lib/board.c
  14. 0 7
      arch/nds32/lib/board.c
  15. 17 29
      arch/nios2/lib/board.c
  16. 0 12
      arch/openrisc/lib/board.c
  17. 0 6
      arch/powerpc/cpu/mpc512x/speed.c
  18. 3 0
      arch/powerpc/cpu/mpc85xx/cmd_errata.c
  19. 10 8
      arch/powerpc/cpu/mpc85xx/cpu.c
  20. 14 0
      arch/powerpc/cpu/mpc85xx/cpu_init.c
  21. 7 0
      arch/powerpc/cpu/mpc85xx/fdt.c
  22. 4 0
      arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
  23. 10 10
      arch/powerpc/cpu/mpc85xx/p2041_ids.c
  24. 10 10
      arch/powerpc/cpu/mpc85xx/p3041_ids.c
  25. 10 10
      arch/powerpc/cpu/mpc85xx/p5020_ids.c
  26. 17 3
      arch/powerpc/cpu/mpc85xx/portals.c
  27. 4 0
      arch/powerpc/cpu/ppc4xx/Makefile
  28. 72 0
      arch/powerpc/cpu/ppc4xx/spl_boot.c
  29. 33 4
      arch/powerpc/cpu/ppc4xx/start.S
  30. 74 0
      arch/powerpc/cpu/ppc4xx/u-boot-spl.lds
  31. 2 0
      arch/powerpc/cpu/ppc4xx/u-boot.lds
  32. 9 3
      arch/powerpc/include/asm/config_mpc85xx.h
  33. 4 0
      arch/powerpc/include/asm/fsl_memac.h
  34. 11 1
      arch/powerpc/include/asm/immap_85xx.h
  35. 0 9
      arch/powerpc/lib/board.c
  36. 4 1
      arch/sandbox/config.mk
  37. 5 0
      arch/sandbox/cpu/cpu.c
  38. 8 1
      arch/sandbox/cpu/start.c
  39. 8 0
      arch/sandbox/include/asm/io.h
  40. 1 0
      arch/sandbox/include/asm/state.h
  41. 2 20
      arch/sandbox/include/asm/u-boot.h
  42. 0 1
      arch/sandbox/lib/Makefile
  43. 0 285
      arch/sandbox/lib/board.c
  44. 0 9
      arch/sh/lib/board.c
  45. 0 9
      arch/sparc/lib/board.c
  46. 0 7
      arch/x86/lib/board.c
  47. 20 6
      board/a3m071/a3m071.c
  48. 17 2
      board/freescale/b4860qds/tlb.c
  49. 6 0
      board/freescale/common/Makefile
  50. 23 3
      board/freescale/common/cds_pci_ft.c
  51. 1 1
      board/freescale/common/sdhc_boot.c
  52. 1 1
      board/freescale/p1010rdb/p1010rdb.c
  53. 14 0
      board/freescale/p1022ds/Makefile
  54. 1 0
      board/freescale/p1022ds/law.c
  55. 129 0
      board/freescale/p1022ds/spl_minimal.c
  56. 14 6
      board/freescale/p1022ds/tlb.c
  57. 65 1
      board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
  58. 15 0
      board/freescale/p1_p2_rdb_pc/spl_minimal.c
  59. 9 0
      board/h2200/h2200.c
  60. 73 2
      board/lwmon5/lwmon5.c
  61. 3 1
      board/lwmon5/sdram.c
  62. 1 1
      board/sandbox/sandbox/sandbox.c
  63. 8 3
      board/xilinx/microblaze-generic/microblaze-generic.c
  64. 4 0
      board/xilinx/microblaze-generic/xparameters.h
  65. 3 0
      boards.cfg
  66. 93 15
      common/board_f.c
  67. 6 2
      common/board_r.c
  68. 57 30
      common/cmd_fdt.c
  69. 5 0
      common/cmd_ide.c
  70. 80 22
      common/cmd_nvedit.c
  71. 14 4
      common/cmd_sandbox.c
  72. 1 0
      common/cmd_sata.c
  73. 4 0
      common/cmd_scsi.c
  74. 287 9
      common/cmd_setexpr.c
  75. 7 4
      common/cmd_source.c
  76. 123 9
      common/env_mmc.c
  77. 11 0
      common/flash.c
  78. 0 8
      common/main.c
  79. 0 7
      common/spl/spl.c
  80. 1 0
      common/usb_storage.c
  81. 6 2
      config.mk
  82. 16 3
      disk/part_dos.c
  83. 22 16
      disk/part_efi.c
  84. 3 0
      disk/part_iso.c
  85. 5 1
      doc/README.fdt-control
  86. 199 0
      doc/README.p1010rdb
  87. 102 0
      doc/README.ramboot-ppc85xx
  88. 3 0
      doc/README.watchdog
  89. 7 12
      doc/feature-removal-schedule.txt
  90. 2 1
      doc/git-mailrc
  91. 1 0
      drivers/block/ata_piix.c
  92. 2 0
      drivers/block/pata_bfin.c
  93. 1 0
      drivers/block/systemace.c
  94. 14 12
      drivers/mmc/mmc.c
  95. 9 8
      drivers/mmc/spl_mmc.c
  96. 2 0
      drivers/mtd/nand/Makefile
  97. 1028 0
      drivers/mtd/nand/docg4.c
  98. 222 0
      drivers/mtd/nand/docg4_spl.c
  99. 0 9
      drivers/mtd/nand/mxc_nand_spl.c
  100. 17 0
      drivers/net/fm/memac.c

+ 22 - 0
Makefile

@@ -183,6 +183,16 @@ endif
 # load other configuration
 include $(TOPDIR)/config.mk
 
+# Targets which don't build the source code
+NON_BUILD_TARGETS = backup clean clobber distclean mkproper tidy unconfig
+
+# Only do the generic board check when actually building, not configuring
+ifeq ($(filter $(NON_BUILD_TARGETS),$(MAKECMDGOALS)),)
+ifeq ($(findstring _config,$(MAKECMDGOALS)),)
+$(CHECK_GENERIC_BOARD)
+endif
+endif
+
 # If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use
 # that (or fail if absent).  Otherwise, search for a linker script in a
 # standard location.
@@ -554,6 +564,18 @@ endif
 $(obj)u-boot-img.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
 		cat $(obj)spl/u-boot-spl.bin $(obj)u-boot.img > $@
 
+# PPC4xx needs the SPL at the end of the image, since the reset vector
+# is located at 0xfffffffc. So we can't use the "u-boot-img.bin" target
+# and need to introduce a new build target with the full blown U-Boot
+# at the start padded up to the start of the SPL image. And then concat
+# the SPL image to the end.
+$(obj)u-boot-img-spl-at-end.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
+		tr "\000" "\377" < /dev/zero | dd ibs=1 count=$(CONFIG_UBOOT_PAD_TO) \
+			of=$(obj)u-boot-pad.img 2>/dev/null
+		dd if=$(obj)u-boot.img of=$(obj)u-boot-pad.img \
+			conv=notrunc 2>/dev/null
+		cat $(obj)u-boot-pad.img $(obj)spl/u-boot-spl.bin > $@
+
 ifeq ($(CONFIG_SANDBOX),y)
 GEN_UBOOT = \
 		cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \

+ 16 - 0
README

@@ -930,6 +930,13 @@ The following options need to be configured:
 
 		XXX - this list needs to get updated!
 
+- Regular expression support:
+		CONFIG_REGEX
+                If this variable is defined, U-Boot is linked against
+                the SLRE (Super Light Regular Expression) library,
+                which adds regex support to some commands, as for
+                example "env grep" and "setexpr".
+
 - Device tree:
 		CONFIG_OF_CONTROL
 		If this variable is defined, U-Boot will use a device tree
@@ -3248,6 +3255,15 @@ Configuration Settings:
 		digits and dots.  Recommended value: 45 (9..1) for 80
 		column displays, 15 (3..1) for 40 column displays.
 
+- CONFIG_FLASH_VERIFY
+		If defined, the content of the flash (destination) is compared
+		against the source after the write operation. An error message
+		will be printed when the contents are not identical.
+		Please note that this option is useless in nearly all cases,
+		since such flash programming errors usually are detected earlier
+		while unprotecting/erasing/programming. Please only enable
+		this option if you really know what you are doing.
+
 - CONFIG_SYS_RX_ETH_BUFFER:
 		Defines the number of Ethernet receive buffers. On some
 		Ethernet controllers it is recommended to set this value

+ 0 - 7
arch/arm/cpu/arm926ejs/mxs/spl_boot.c

@@ -148,10 +148,3 @@ inline void board_init_r(gd_t *id, ulong dest_addr)
 	for (;;)
 		;
 }
-
-void hang(void) __attribute__ ((noreturn));
-void hang(void)
-{
-	for (;;)
-		;
-}

+ 0 - 7
arch/arm/cpu/arm926ejs/spear/spl.c

@@ -31,13 +31,6 @@
 #include <asm/arch/spr_misc.h>
 #include <asm/arch/spr_syscntl.h>
 
-inline void hang(void)
-{
-	serial_puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
-
 static void ddr_clock_init(void)
 {
 	struct misc_regs *misc_p = (struct misc_regs *)CONFIG_SPEAR_MISCBASE;

+ 1 - 1
arch/arm/cpu/pxa/pxa2xx.c

@@ -284,7 +284,7 @@ void i2c_clk_enable(void)
 	writel(readl(CKEN) | CKEN14_I2C, CKEN);
 }
 
-void reset_cpu(ulong ignored) __attribute__((noreturn));
+void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn));
 
 void reset_cpu(ulong ignored)
 {

+ 0 - 11
arch/arm/include/asm/arch-pxa/hardware.h

@@ -77,17 +77,6 @@
 #define GPIO_FALLING_EDGE	1
 #define GPIO_RISING_EDGE	2
 #define GPIO_BOTH_EDGES		3
-extern void set_GPIO_IRQ_edge( int gpio_nr, int edge_mask );
-
-/*
- * Handy routine to set GPIO alternate functions
- */
-extern void set_GPIO_mode( int gpio_mode );
-
-/*
- * return current lclk frequency in units of 10kHz
- */
-extern unsigned int get_lclk_frequency_10khz(void);
 
 #endif
 

+ 0 - 6
arch/arm/lib/board.c

@@ -706,9 +706,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;);
-}

+ 0 - 5
arch/avr32/lib/board.c

@@ -120,11 +120,6 @@ static int display_banner (void)
 	return 0;
 }
 
-void hang(void)
-{
-	for (;;) ;
-}
-
 static int display_dram_config (void)
 {
 	int i;

+ 0 - 14
arch/blackfin/lib/board.c

@@ -432,17 +432,3 @@ void board_init_r(gd_t * id, ulong dest_addr)
 	for (;;)
 		main_loop();
 }
-
-void hang(void)
-{
-#ifdef CONFIG_STATUS_LED
-	status_led_set(STATUS_LED_BOOT, STATUS_LED_OFF);
-	status_led_set(STATUS_LED_CRASH, STATUS_LED_BLINKING);
-#endif
-	puts("### ERROR ### Please RESET the board ###\n");
-	while (1)
-		/* If a JTAG emulator is hooked up, we'll automatically trigger
-		 * a breakpoint in it.  If one isn't, this is just a NOP.
-		 */
-		asm("emuexcpt;");
-}

+ 0 - 7
arch/m68k/lib/board.c

@@ -663,10 +663,3 @@ void board_init_r (gd_t *id, ulong dest_addr)
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-
-void hang(void)
-{
-	puts ("### ERROR ### Please RESET the board ###\n");
-	for (;;);
-}

+ 4 - 0
arch/microblaze/include/asm/processor.h

@@ -31,4 +31,8 @@ extern char __text_start[];
 /* Microblaze board initialization function */
 void board_init(void);
 
+/* Watchdog functions */
+extern int hw_watchdog_init(void);
+extern void hw_watchdog_disable(void);
+
 #endif /* __ASM_MICROBLAZE_PROCESSOR_H */

+ 30 - 35
arch/microblaze/lib/board.c

@@ -61,6 +61,9 @@ init_fnc_t *init_sequence[] = {
 	serial_init,
 	console_init_f,
 	interrupts_init,
+#ifdef CONFIG_XILINX_TB_WATCHDOG
+	hw_watchdog_init,
+#endif
 	timer_init,
 	NULL,
 };
@@ -71,15 +74,15 @@ void board_init_f(ulong not_used)
 {
 	bd_t *bd;
 	init_fnc_t **init_fnc_ptr;
-	gd = (gd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
-	bd = (bd_t *) (CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET \
+	gd = (gd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET);
+	bd = (bd_t *)(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_GBL_DATA_OFFSET
 						- GENERATED_BD_INFO_SIZE);
 #if defined(CONFIG_CMD_FLASH)
 	ulong flash_size = 0;
 #endif
 	asm ("nop");	/* FIXME gd is not initialize - wait */
-	memset ((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
-	memset ((void *)bd, 0, GENERATED_BD_INFO_SIZE);
+	memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
+	memset((void *)bd, 0, GENERATED_BD_INFO_SIZE);
 	gd->bd = bd;
 	gd->baudrate = CONFIG_BAUDRATE;
 	bd->bi_baudrate = CONFIG_BAUDRATE;
@@ -105,57 +108,55 @@ void board_init_f(ulong not_used)
 	 * aka CONFIG_SYS_MONITOR_BASE - Note there is no need for reloc_off
 	 * as our monitory code is run from SDRAM
 	 */
-	mem_malloc_init (CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
+	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
 
 	serial_initialize();
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		WATCHDOG_RESET ();
-		if ((*init_fnc_ptr) () != 0) {
-			hang ();
-		}
+		WATCHDOG_RESET();
+		if ((*init_fnc_ptr) () != 0)
+			hang();
 	}
 
 #ifdef CONFIG_OF_CONTROL
 	/* For now, put this check after the console is ready */
-	if (fdtdec_prepare_fdt()) {
-		panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
-			"doc/README.fdt-control");
-	} else
+	if (fdtdec_prepare_fdt())
+		panic("** No FDT - please see doc/README.fdt-control");
+	else
 		printf("DTB: 0x%x\n", (u32)gd->fdt_blob);
 #endif
 
-	puts ("SDRAM :\n");
-	printf ("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
-	printf ("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
-	printf ("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
+	puts("SDRAM :\n");
+	printf("\t\tIcache:%s\n", icache_status() ? "ON" : "OFF");
+	printf("\t\tDcache:%s\n", dcache_status() ? "ON" : "OFF");
+	printf("\tU-Boot Start:0x%08x\n", CONFIG_SYS_TEXT_BASE);
 
 #if defined(CONFIG_CMD_FLASH)
-	puts ("Flash: ");
+	puts("Flash: ");
 	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
 	flash_size = flash_init();
 	if (bd->bi_flashstart && flash_size > 0) {
 # ifdef CONFIG_SYS_FLASH_CHECKSUM
-		print_size (flash_size, "");
+		print_size(flash_size, "");
 		/*
 		 * Compute and print flash CRC if flashchecksum is set to 'y'
 		 *
 		 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
 		 */
 		if (getenv_yesno("flashchecksum") == 1) {
-			printf ("  CRC: %08X",
-				crc32(0, (const u8 *)bd->bi_flashstart,
-							flash_size)
+			printf("  CRC: %08X",
+			       crc32(0, (const u8 *)bd->bi_flashstart,
+				     flash_size)
 			);
 		}
-		putc ('\n');
+		putc('\n');
 # else	/* !CONFIG_SYS_FLASH_CHECKSUM */
-		print_size (flash_size, "\n");
+		print_size(flash_size, "\n");
 # endif /* CONFIG_SYS_FLASH_CHECKSUM */
 		bd->bi_flashsize = flash_size;
 		bd->bi_flashoffset = bd->bi_flashstart + flash_size;
 	} else {
-		puts ("Flash init FAILED");
+		puts("Flash init FAILED");
 		bd->bi_flashstart = 0;
 		bd->bi_flashsize = 0;
 		bd->bi_flashoffset = 0;
@@ -163,10 +164,10 @@ void board_init_f(ulong not_used)
 #endif
 
 	/* relocate environment function pointers etc. */
-	env_relocate ();
+	env_relocate();
 
 	/* Initialize stdio devices */
-	stdio_init ();
+	stdio_init();
 
 	/* Initialize the jump table for applications */
 	jumptable_init();
@@ -190,13 +191,7 @@ void board_init_f(ulong not_used)
 
 	/* main_loop */
 	for (;;) {
-		WATCHDOG_RESET ();
-		main_loop ();
+		WATCHDOG_RESET();
+		main_loop();
 	}
 }
-
-void hang (void)
-{
-	puts ("### ERROR ### Please RESET the board ###\n");
-	for (;;) ;
-}

+ 0 - 7
arch/mips/lib/board.c

@@ -344,10 +344,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}

+ 0 - 7
arch/nds32/lib/board.c

@@ -404,10 +404,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}

+ 17 - 29
arch/nios2/lib/board.c

@@ -64,7 +64,6 @@ typedef int (init_fnc_t) (void);
  ***********************************************************************/
 
 init_fnc_t *init_sequence[] = {
-
 #if defined(CONFIG_BOARD_EARLY_INIT_F)
 	board_early_init_f,	/* Call board-specific init code early.*/
 #endif
@@ -83,7 +82,7 @@ init_fnc_t *init_sequence[] = {
 
 
 /***********************************************************************/
-void board_init (void)
+void board_init(void)
 {
 	bd_t *bd;
 	init_fnc_t **init_fnc_ptr;
@@ -93,7 +92,7 @@ void board_init (void)
 	/* Pointer is writable since we allocated a register for it. */
 	gd = &gd_data;
 	/* compiler optimization barrier needed for GCC >= 3.4 */
-	__asm__ __volatile__("": : :"memory");
+	__asm__ __volatile__("" : : : "memory");
 
 	gd->bd = &bd_data;
 	gd->baudrate = CONFIG_BAUDRATE;
@@ -106,25 +105,24 @@ void board_init (void)
 	bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
 #endif
 #if	defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
-	bd->bi_sramstart= CONFIG_SYS_SRAM_BASE;
+	bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
 	bd->bi_sramsize	= CONFIG_SYS_SRAM_SIZE;
 #endif
 	bd->bi_baudrate	= CONFIG_BAUDRATE;
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		WATCHDOG_RESET ();
-		if ((*init_fnc_ptr) () != 0) {
-			hang ();
-		}
+		WATCHDOG_RESET();
+		if ((*init_fnc_ptr) () != 0)
+			hang();
 	}
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 
 	/* The Malloc area is immediately below the monitor copy in RAM */
 	mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
 
 #ifndef CONFIG_SYS_NO_FLASH
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	bd->bi_flashsize = flash_init();
 #endif
 
@@ -138,39 +136,29 @@ void board_init (void)
 	mmc_initialize(bd);
 #endif
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	env_relocate();
 
-	WATCHDOG_RESET ();
+	WATCHDOG_RESET();
 	stdio_init();
 	jumptable_init();
 	console_init_r();
 
-	WATCHDOG_RESET ();
-	interrupt_init ();
+	WATCHDOG_RESET();
+	interrupt_init();
 
 #if defined(CONFIG_BOARD_LATE_INIT)
-	board_late_init ();
+	board_late_init();
 #endif
 
 #if defined(CONFIG_CMD_NET)
-	puts ("Net:   ");
-	eth_initialize (bd);
+	puts("Net:   ");
+	eth_initialize(bd);
 #endif
 
 	/* main_loop */
 	for (;;) {
-		WATCHDOG_RESET ();
-		main_loop ();
+		WATCHDOG_RESET();
+		main_loop();
 	}
 }
-
-
-/***********************************************************************/
-
-void hang (void)
-{
-	disable_interrupts ();
-	puts("### ERROR ### Please reset board ###\n");
-	for (;;);
-}

+ 0 - 12
arch/openrisc/lib/board.c

@@ -154,15 +154,3 @@ void board_init(void)
 		main_loop();
 	}
 }
-
-
-/***********************************************************************/
-
-void hang(void)
-{
-	disable_interrupts();
-	puts("### ERROR ### Please reset board ###\n");
-
-	for (;;)
-		;
-}

+ 0 - 6
arch/powerpc/cpu/mpc512x/speed.c

@@ -151,9 +151,3 @@ U_BOOT_CMD(clocks, 1, 0, do_clocks,
 	"print clock configuration",
 	"    clocks"
 );
-
-int prt_mpc512x_clks (void)
-{
-	do_clocks (NULL, 0, 0, NULL);
-	return (0);
-}

+ 3 - 0
arch/powerpc/cpu/mpc85xx/cmd_errata.c

@@ -254,6 +254,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #endif
 #ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
 	puts("Work-around for Erratum PCIe-A003 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_USB14
+	puts("Work-around for Erratum USB14 enabled\n");
 #endif
 	return 0;
 }

+ 10 - 8
arch/powerpc/cpu/mpc85xx/cpu.c

@@ -281,14 +281,6 @@ unsigned long get_tbclk (void)
 
 
 #if defined(CONFIG_WATCHDOG)
-void
-watchdog_reset(void)
-{
-	int re_enable = disable_interrupts();
-	reset_85xx_watchdog();
-	if (re_enable) enable_interrupts();
-}
-
 void
 reset_85xx_watchdog(void)
 {
@@ -297,6 +289,16 @@ reset_85xx_watchdog(void)
 	 */
 	mtspr(SPRN_TSR, TSR_WIS);
 }
+
+void
+watchdog_reset(void)
+{
+	int re_enable = disable_interrupts();
+
+	reset_85xx_watchdog();
+	if (re_enable)
+		enable_interrupts();
+}
 #endif	/* CONFIG_WATCHDOG */
 
 /*

+ 14 - 0
arch/powerpc/cpu/mpc85xx/cpu_init.c

@@ -623,6 +623,20 @@ skip_l2:
 	}
 #endif
 
+#ifdef CONFIG_SYS_FSL_ERRATUM_USB14
+	/* On P204x/P304x/P50x0 Rev1.0, USB transmit will result internal
+	 * multi-bit ECC errors which has impact on performance, so software
+	 * should disable all ECC reporting from USB1 and USB2.
+	 */
+	if (IS_SVR_REV(get_svr(), 1, 0)) {
+		struct dcsr_dcfg_regs *dcfg = (struct dcsr_dcfg_regs *)
+			(CONFIG_SYS_DCSRBAR + CONFIG_SYS_DCSR_DCFG_OFFSET);
+		setbits_be32(&dcfg->ecccr1,
+				(DCSR_DCFG_ECC_DISABLE_USB1 |
+				 DCSR_DCFG_ECC_DISABLE_USB2));
+	}
+#endif
+
 #ifdef CONFIG_FMAN_ENET
 	fman_enet_init();
 #endif

+ 7 - 0
arch/powerpc/cpu/mpc85xx/fdt.c

@@ -663,6 +663,13 @@ void ft_cpu_setup(void *blob, bd_t *bd)
 #ifdef CONFIG_FSL_CORENET
 	do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-1.0",
 		"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
+	do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2",
+		"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
+	do_fixup_by_compat_u32(blob, "fsl,mpic",
+		"clock-frequency", get_bus_freq(0)/2, 1);
+#else
+	do_fixup_by_compat_u32(blob, "fsl,mpic",
+		"clock-frequency", get_bus_freq(0), 1);
 #endif
 
 	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);

+ 4 - 0
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c

@@ -103,6 +103,10 @@ static const struct {
 	{ 22, 168, FSL_SRDS_BANK_3 },
 	{ 23, 169, FSL_SRDS_BANK_3 },
 #endif
+#if SRDS_MAX_BANK > 3
+	{ 24, 175, FSL_SRDS_BANK_4 },
+	{ 25, 176, FSL_SRDS_BANK_4 },
+#endif
 };
 
 int serdes_get_lane_idx(int lane)

+ 10 - 10
arch/powerpc/cpu/mpc85xx/p2041_ids.c

@@ -27,16 +27,16 @@
 #ifdef CONFIG_SYS_DPAA_QBMAN
 struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
 	/* dqrr liodn, frame data liodn, liodn off, sdest */
-	SET_QP_INFO(1, 2, 1, 0),
-	SET_QP_INFO(3, 4, 2, 1),
-	SET_QP_INFO(5, 6, 3, 2),
-	SET_QP_INFO(7, 8, 4, 3),
-	SET_QP_INFO(9, 10, 5, 0),
-	SET_QP_INFO(11, 12, 1, 1),
-	SET_QP_INFO(13, 14, 2, 2),
-	SET_QP_INFO(15, 16, 3, 3),
-	SET_QP_INFO(17, 18, 4, 0), /* for now sdest to 0 */
-	SET_QP_INFO(19, 20, 5, 0), /* for now sdest to 0 */
+	SET_QP_INFO(1,  2,  1, 0),
+	SET_QP_INFO(3,  4,  2, 1),
+	SET_QP_INFO(5,  6,  3, 2),
+	SET_QP_INFO(7,  8,  4, 3),
+	SET_QP_INFO(9, 10,  5, 0),
+	SET_QP_INFO(11, 12,  6, 1),
+	SET_QP_INFO(13, 14,  7, 2),
+	SET_QP_INFO(15, 16,  8, 3),
+	SET_QP_INFO(17, 18,  9, 0), /* for now sdest to 0 */
+	SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */
 };
 #endif
 

+ 10 - 10
arch/powerpc/cpu/mpc85xx/p3041_ids.c

@@ -27,16 +27,16 @@
 #ifdef CONFIG_SYS_DPAA_QBMAN
 struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
 	/* dqrr liodn, frame data liodn, liodn off, sdest */
-	SET_QP_INFO(1, 2, 1, 0),
-	SET_QP_INFO(3, 4, 2, 1),
-	SET_QP_INFO(5, 6, 3, 2),
-	SET_QP_INFO(7, 8, 4, 3),
-	SET_QP_INFO(9, 10, 5, 0),
-	SET_QP_INFO(11, 12, 1, 1),
-	SET_QP_INFO(13, 14, 2, 2),
-	SET_QP_INFO(15, 16, 3, 3),
-	SET_QP_INFO(17, 18, 4, 0), /* for now sdest to 0 */
-	SET_QP_INFO(19, 20, 5, 0), /* for now sdest to 0 */
+	SET_QP_INFO(1,  2,  1, 0),
+	SET_QP_INFO(3,  4,  2, 1),
+	SET_QP_INFO(5,  6,  3, 2),
+	SET_QP_INFO(7,  8,  4, 3),
+	SET_QP_INFO(9, 10,  5, 0),
+	SET_QP_INFO(1, 12,  6, 1),
+	SET_QP_INFO(13, 14,  7, 2),
+	SET_QP_INFO(15, 16,  8, 3),
+	SET_QP_INFO(17, 18,  9, 0), /* for now sdest to 0 */
+	SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */
 };
 #endif
 

+ 10 - 10
arch/powerpc/cpu/mpc85xx/p5020_ids.c

@@ -27,16 +27,16 @@
 #ifdef CONFIG_SYS_DPAA_QBMAN
 struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
 	/* dqrr liodn, frame data liodn, liodn off, sdest */
-	SET_QP_INFO(1, 2, 1, 0),
-	SET_QP_INFO(3, 4, 2, 1),
-	SET_QP_INFO(5, 6, 3, 0),
-	SET_QP_INFO(7, 8, 4, 1),
-	SET_QP_INFO(9, 10, 5, 0),
-	SET_QP_INFO(11, 12, 1, 1),
-	SET_QP_INFO(13, 14, 2, 0),
-	SET_QP_INFO(15, 16, 3, 1),
-	SET_QP_INFO(17, 18, 4, 0),
-	SET_QP_INFO(19, 20, 5, 1),
+	SET_QP_INFO(1,  2,  1, 0),
+	SET_QP_INFO(3,  4,  2, 1),
+	SET_QP_INFO(5,  6,  3, 0),
+	SET_QP_INFO(7,  8,  4, 1),
+	SET_QP_INFO(9, 10,  5, 0),
+	SET_QP_INFO(11, 12,  6, 1),
+	SET_QP_INFO(13, 14,  7, 0),
+	SET_QP_INFO(15, 16,  8, 1),
+	SET_QP_INFO(17, 18,  9, 0),
+	SET_QP_INFO(19, 20, 10, 1),
 };
 #endif
 

+ 17 - 3
arch/powerpc/cpu/mpc85xx/portals.c

@@ -30,11 +30,9 @@
 #include <asm/fsl_portals.h>
 #include <asm/fsl_liodn.h>
 
-static ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
-static ccsr_bman_t *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR;
-
 void setup_portals(void)
 {
+	ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
 #ifdef CONFIG_FSL_CORENET
 	int i;
 
@@ -166,6 +164,20 @@ static int fdt_qportal(void *blob, int off, int id, char *name,
 			num = get_dpaa_liodn(dev, &liodns[0], id);
 			ret = fdt_setprop(blob, childoff, "fsl,liodn",
 					  &liodns[0], sizeof(u32) * num);
+			if (!strncmp(name, "pme", 3)) {
+				u32 pme_rev1, pme_rev2;
+				ccsr_pme_t *pme_regs =
+					(void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
+
+				pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1);
+				pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2);
+				ret = fdt_setprop(blob, childoff,
+					"fsl,pme-rev1", &pme_rev1, sizeof(u32));
+				if (ret < 0)
+					return ret;
+				ret = fdt_setprop(blob, childoff,
+					"fsl,pme-rev2", &pme_rev2, sizeof(u32));
+			}
 #endif
 		} else {
 			return childoff;
@@ -183,6 +195,7 @@ void fdt_fixup_qportals(void *blob)
 	int off, err;
 	unsigned int maj, min;
 	unsigned int ip_cfg;
+	ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
 	u32 rev_1 = in_be32(&qman->ip_rev_1);
 	u32 rev_2 = in_be32(&qman->ip_rev_2);
 	char compat[64];
@@ -272,6 +285,7 @@ void fdt_fixup_bportals(void *blob)
 	int off, err;
 	unsigned int maj, min;
 	unsigned int ip_cfg;
+	ccsr_bman_t *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR;
 	u32 rev_1 = in_be32(&bman->ip_rev_1);
 	u32 rev_2 = in_be32(&bman->ip_rev_2);
 	char compat[64];

+ 4 - 0
arch/powerpc/cpu/ppc4xx/Makefile

@@ -68,6 +68,10 @@ COBJS	+= miiphy.o
 COBJS	+= uic.o
 endif
 
+ifdef CONFIG_SPL_BUILD
+COBJS-y += spl_boot.o
+endif
+
 SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS-y))
 START	:= $(addprefix $(obj),$(START))

+ 72 - 0
arch/powerpc/cpu/ppc4xx/spl_boot.c

@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Return selected boot device. On PPC4xx its only NOR flash right now.
+ */
+u32 spl_boot_device(void)
+{
+	return BOOT_DEVICE_NOR;
+}
+
+/*
+ * SPL version of board_init_f()
+ */
+void board_init_f(ulong bootflag)
+{
+	/*
+	 * First we need to initialize the SDRAM, so that the real
+	 * U-Boot or the OS (Linux) can be loaded
+	 */
+	initdram(0);
+
+	/* Clear bss */
+	memset(__bss_start, '\0', __bss_end - __bss_start);
+
+	/*
+	 * Init global_data pointer. Has to be done before calling
+	 * get_clocks(), as it stores some clock values into gd needed
+	 * later on in the serial driver.
+	 */
+	/* Pointer is writable since we allocated a register for it */
+	gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+	/* Clear initial global data */
+	memset((void *)gd, 0, sizeof(gd_t));
+
+	/*
+	 * get_clocks() needs to be called so that the serial driver
+	 * works correctly
+	 */
+	get_clocks();
+
+	/*
+	 * Do rudimental console / serial setup
+	 */
+	preloader_console_init();
+
+	/*
+	 * Call board_init_r() (SPL framework version) to load and boot
+	 * real U-Boot or OS
+	 */
+	board_init_r(NULL, 0);
+	/* Does not return!!! */
+}

+ 33 - 4
arch/powerpc/cpu/ppc4xx/start.S

@@ -232,7 +232,7 @@
  *
  * Use r12 to access the GOT
  */
-#if !defined(CONFIG_NAND_SPL)
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
 	START_GOT
 	GOT_ENTRY(_GOT2_TABLE_)
 	GOT_ENTRY(_FIXUP_TABLE_)
@@ -248,7 +248,8 @@
 	END_GOT
 #endif /* CONFIG_NAND_SPL */
 
-#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) && \
+	!defined(CONFIG_SPL_BUILD)
 	/*
 	 * NAND U-Boot image is started from offset 0
 	 */
@@ -270,6 +271,18 @@
 	bl	_start_440
 #endif
 
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+	/*
+	 * This is the entry of the real U-Boot from a board port
+	 * that supports SPL booting on the PPC4xx. We only need
+	 * to call board_init_f() here. Everything else has already
+	 * been done in the SPL u-boot version.
+	 */
+	GET_GOT			/* initialize GOT access		*/
+	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
+	/* NOTREACHED - board_init_f() does not return */
+#endif
+
 /*
  * 440 Startup -- on reset only the top 4k of the effective
  * address space is mapped in by an entry in the instruction
@@ -539,7 +552,7 @@ tlbnx2:	addi	r4,r4,1		/* Next TLB */
  * r3 - 1st arg to board_init(): IMMP pointer
  * r4 - 2nd arg to board_init(): boot flag
  */
-#ifndef CONFIG_NAND_SPL
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
 	.text
 	.long	0x27051956		/* U-Boot Magic Number			*/
 	.globl	version_string
@@ -612,6 +625,18 @@ _end_of_vectors:
 	.globl	_start
 _start:
 
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+	/*
+	 * This is the entry of the real U-Boot from a board port
+	 * that supports SPL booting on the PPC4xx. We only need
+	 * to call board_init_f() here. Everything else has already
+	 * been done in the SPL u-boot version.
+	 */
+	GET_GOT			/* initialize GOT access		*/
+	bl	board_init_f	/* run 1st part of board init code (in Flash)*/
+	/* NOTREACHED - board_init_f() does not return */
+#endif
+
 /*****************************************************************************/
 #if defined(CONFIG_440)
 
@@ -796,7 +821,9 @@ _start:
 #ifdef CONFIG_NAND_SPL
 	bl	nand_boot_common	/* will not return */
 #else
+#ifndef CONFIG_SPL_BUILD
 	GET_GOT
+#endif
 
 	bl	cpu_init_f	/* run low-level CPU init code	   (from Flash) */
 	bl	board_init_f
@@ -1080,7 +1107,7 @@ _start:
 	/*----------------------------------------------------------------------- */
 
 
-#ifndef CONFIG_NAND_SPL
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
 /*
  * This code finishes saving the registers to the exception frame
  * and jumps to the appropriate handler for the exception.
@@ -1262,6 +1289,7 @@ in32r:
 	lwbrx	r3,r0,r3
 	blr
 
+#if !defined(CONFIG_SPL_BUILD)
 /*
  * void relocate_code (addr_sp, gd, addr_moni)
  *
@@ -1626,6 +1654,7 @@ __440_msr_continue:
 
 	mtlr	r4			/* restore link register	*/
 	blr
+#endif /* CONFIG_SPL_BUILD */
 
 #if defined(CONFIG_440)
 /*----------------------------------------------------------------------------+

+ 74 - 0
arch/powerpc/cpu/ppc4xx/u-boot-spl.lds

@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2013 Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+MEMORY
+{
+	sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+		LENGTH = CONFIG_SPL_BSS_MAX_SIZE
+	flash : ORIGIN = CONFIG_SPL_TEXT_BASE,
+		LENGTH = CONFIG_SYS_SPL_MAX_LEN
+}
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+SECTIONS
+{
+#ifdef CONFIG_440
+	.bootpg 0xfffff000 :
+	{
+		arch/powerpc/cpu/ppc4xx/start.o	(.bootpg)
+
+		/*
+		 * PPC440 board need a board specific object with the
+		 * TLB definitions. This needs to get included right after
+		 * start.o, since the first shadow TLB only covers 4k
+		 * of address space.
+		 */
+		CONFIG_BOARDDIR/init.o	(.bootpg)
+	} > flash
+#endif
+
+	.resetvec 0xFFFFFFFC :
+	{
+		KEEP(*(.resetvec))
+	} > flash
+
+	.text :
+	{
+		__start = .;
+		arch/powerpc/cpu/ppc4xx/start.o	(.text)
+		CONFIG_BOARDDIR/init.o	(.text)
+		*(.text*)
+	} > flash
+
+	. = ALIGN(4);
+	.data : { *(SORT_BY_ALIGNMENT(.data*)) } > flash
+
+	. = ALIGN(4);
+	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } > flash
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start = .;
+		*(.bss*)
+		. = ALIGN(4);
+		__bss_end = .;
+	} > sdram
+}

+ 2 - 0
arch/powerpc/cpu/ppc4xx/u-boot.lds

@@ -96,6 +96,7 @@ SECTIONS
   . = ALIGN(256);
   __init_end = .;
 
+#ifndef CONFIG_SPL
 #ifdef CONFIG_440
   .bootpg RESET_VECTOR_ADDRESS - 0xffc :
   {
@@ -132,6 +133,7 @@ SECTIONS
 #if (RESET_VECTOR_ADDRESS == 0xfffffffc)
   . |= 0x10;
 #endif
+#endif /* CONFIG_SPL */
 
   __bss_start = .;
   .bss (NOLOAD)       :

+ 9 - 3
arch/powerpc/include/asm/config_mpc85xx.h

@@ -333,7 +333,9 @@
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+#define CONFIG_SYS_FSL_ERRATUM_USB14
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 #define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
@@ -365,7 +367,9 @@
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+#define CONFIG_SYS_FSL_ERRATUM_USB14
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 #define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
@@ -442,6 +446,8 @@
 #define CONFIG_SYS_FSL_USB2_PHY_ENABLE
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_USB14
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 #define CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS	2
@@ -473,7 +479,7 @@
 #define CONFIG_SYS_FSL_USB2_PHY_ENABLE
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
-#define CONFIG_SYS_FSL_ERRATUM_USB138
+#define CONFIG_SYS_FSL_ERRATUM_USB14
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 #define CONFIG_SYS_FSL_ERRATUM_A004699
@@ -490,7 +496,6 @@
 #define CONFIG_NUM_DDR_CONTROLLERS	1
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_NAND_FSL_IFC
-#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 
 #elif defined(CONFIG_BSC9132)
@@ -503,7 +508,6 @@
 #define CONFIG_NUM_DDR_CONTROLLERS	2
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_NAND_FSL_IFC
-#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_SYS_FSL_ESDHC_P1010_BROKEN_SDCLK
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.2"
@@ -560,6 +564,7 @@
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.4"
 #define CONFIG_SYS_FSL_USB1_PHY_ENABLE
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
+#define CONFIG_SYS_FSL_ERRATUM_A005871
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xfe000000
 
 #elif defined(CONFIG_PPC_B4860)
@@ -585,6 +590,7 @@
 #define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM	5
 #define CONFIG_SYS_FSL_USB1_PHY_ENABLE
 #define CONFIG_SYS_FSL_ERRATUM_A_004934
+#define CONFIG_SYS_FSL_ERRATUM_A005871
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xfe000000
 
 #else

+ 4 - 0
arch/powerpc/include/asm/fsl_memac.h

@@ -222,6 +222,10 @@ struct memac {
 
 /* IF_MODE - Interface Mode Register */
 #define IF_MODE_EN_AUTO	0x00008000 /* 1 - Enable automatic speed selection */
+#define IF_MODE_SETSP_100M	0x00000000 /* 00 - 100Mbps RGMII */
+#define IF_MODE_SETSP_10M	0x00002000 /* 01 - 10Mbps RGMII */
+#define IF_MODE_SETSP_1000M	0x00004000 /* 10 - 1000Mbps RGMII */
+#define IF_MODE_SETSP_MASK	0x00006000 /* setsp mask bits */
 #define IF_MODE_XGMII	0x00000000 /* 00- XGMII(10) interface mode */
 #define IF_MODE_GMII		0x00000002 /* 10- GMII interface mode */
 #define IF_MODE_MASK	0x00000003 /* mask for mode interface mode */

+ 11 - 1
arch/powerpc/include/asm/immap_85xx.h

@@ -2914,7 +2914,8 @@ struct ccsr_pman {
 #define CONFIG_SYS_MPC85xx_IFC_OFFSET		0x124000
 #define CONFIG_SYS_MPC85xx_GPIO_OFFSET		0x130000
 #define CONFIG_SYS_FSL_CORENET_RMAN_OFFSET	0x1e0000
-#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+#if defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2) && !defined(CONFIG_PPC_B4860)\
+	&& !defined(CONFIG_PPC_B4420)
 #define CONFIG_SYS_MPC85xx_PCIE1_OFFSET		0x240000
 #define CONFIG_SYS_MPC85xx_PCIE2_OFFSET		0x250000
 #define CONFIG_SYS_MPC85xx_PCIE3_OFFSET		0x260000
@@ -3160,4 +3161,13 @@ struct ccsr_cluster_l2 {
 #define CONFIG_SYS_FSL_CLUSTER_1_L2 \
 	(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CLUSTER_1_L2_OFFSET)
 #endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#define	CONFIG_SYS_DCSR_DCFG_OFFSET	0X20000
+struct dcsr_dcfg_regs {
+	u8  res_0[0x520];
+	u32 ecccr1;
+#define	DCSR_DCFG_ECC_DISABLE_USB1	0x00008000
+#define	DCSR_DCFG_ECC_DISABLE_USB2	0x00004000
+	u8  res_524[0x1000 - 0x524]; /* 0x524 - 0x1000 */
+};
 #endif /*__IMMAP_85xx__*/

+ 0 - 9
arch/powerpc/lib/board.c

@@ -1050,15 +1050,6 @@ void board_init_r(gd_t *id, ulong dest_addr)
 	/* NOTREACHED - no way out of command loop except booting */
 }
 
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
-	for (;;)
-		;
-}
-
-
 #if 0	/* We could use plain global data, but the resulting code is bigger */
 /*
  * Pointer to initial global data area

+ 4 - 1
arch/sandbox/config.mk

@@ -18,5 +18,8 @@
 # MA 02111-1307 USA
 
 PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE
-PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM
+PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM -DCONFIG_SYS_GENERIC_BOARD
 PLATFORM_LIBS += -lrt
+
+# Support generic board on sandbox
+__HAVE_ARCH_GENERIC_BOARD := y

+ 5 - 0
arch/sandbox/cpu/cpu.c

@@ -57,6 +57,11 @@ void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
 	return (void *)(gd->arch.ram_buf + paddr);
 }
 
+phys_addr_t map_to_sysmem(void *ptr)
+{
+	return (u8 *)ptr - gd->arch.ram_buf;
+}
+
 void flush_dcache_range(unsigned long start, unsigned long stop)
 {
 }

+ 8 - 1
arch/sandbox/cpu/start.c

@@ -90,7 +90,7 @@ int sandbox_main_loop_init(void)
 
 	/* Execute command if required */
 	if (state->cmd) {
-		run_command(state->cmd, 0);
+		run_command_list(state->cmd, -1, 0);
 		os_exit(state->exit_type);
 	}
 
@@ -104,6 +104,13 @@ static int sb_cmdline_cb_command(struct sandbox_state *state, const char *arg)
 }
 SB_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command");
 
+static int sb_cmdline_cb_fdt(struct sandbox_state *state, const char *arg)
+{
+	state->fdt_fname = arg;
+	return 0;
+}
+SB_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT");
+
 int main(int argc, char *argv[])
 {
 	struct sandbox_state *state;

+ 8 - 0
arch/sandbox/include/asm/io.h

@@ -20,6 +20,9 @@
  * MA 02111-1307 USA
  */
 
+#ifndef __SANDBOX_ASM_IO_H
+#define __SANDBOX_ASM_IO_H
+
 /*
  * Given a physical address and a length, return a virtual address
  * that can be used to access the memory range with the caching
@@ -49,3 +52,8 @@ static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
 static inline void unmap_sysmem(const void *vaddr)
 {
 }
+
+/* Map from a pointer to our RAM buffer */
+phys_addr_t map_to_sysmem(void *ptr);
+
+#endif

+ 1 - 0
arch/sandbox/include/asm/state.h

@@ -34,6 +34,7 @@ enum exit_type_id {
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
+	const char *fdt_fname;		/* Filename of FDT binary */
 	enum exit_type_id exit_type;	/* How we exited U-Boot */
 	const char *parse_err;		/* Error to report from parsing */
 	int argc;			/* Program arguments */

+ 2 - 20
arch/sandbox/include/asm/u-boot.h

@@ -36,26 +36,8 @@
 #ifndef _U_BOOT_H_
 #define _U_BOOT_H_	1
 
-typedef struct bd_info {
-	unsigned long	bi_memstart;	/* start of DRAM memory */
-	phys_size_t	bi_memsize;	/* size	 of DRAM memory in bytes */
-	unsigned long	bi_flashstart;	/* start of FLASH memory */
-	unsigned long	bi_flashsize;	/* size	 of FLASH memory */
-	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
-	unsigned long	bi_sramstart;	/* start of SRAM memory */
-	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
-	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
-	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
-	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
-	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
-	unsigned int	bi_baudrate;	/* Console Baudrate */
-	unsigned long   bi_boot_params;	/* where this board expects params */
-	struct				/* RAM configuration */
-	{
-		ulong start;
-		ulong size;
-	} bi_dram[CONFIG_NR_DRAM_BANKS];
-} bd_t;
+/* Use the generic board which requires a unified bd_info */
+#include <asm-generic/u-boot.h>
 
 /* For image.h:image_check_target_arch() */
 #define IH_ARCH_DEFAULT IH_ARCH_SANDBOX

+ 0 - 1
arch/sandbox/lib/Makefile

@@ -27,7 +27,6 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(ARCH).o
 
-COBJS-y	+= board.o
 COBJS-y	+= interrupts.o
 
 SRCS	:= $(COBJS-y:.o=.c)

+ 0 - 285
arch/sandbox/lib/board.c

@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- *
- * (C) Copyright 2002-2006
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-/*
- * This file was taken from ARM and changed to remove things we don't
- * need. This is most of it, so have tried to avoid being over-zealous!
- * For example, we want to have an emulation of the 'DRAM' used by
- * U-Boot.
- *
- * has been talk upstream of unifying the architectures w.r.t board.c,
- * so the less change here the better.
- */
-
-#include <common.h>
-#include <command.h>
-#include <malloc.h>
-#include <stdio_dev.h>
-#include <timestamp.h>
-#include <version.h>
-#include <serial.h>
-
-#include <os.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static gd_t gd_mem;
-
-/************************************************************************
- * Init Utilities							*
- ************************************************************************
- * Some of this code should be moved into the core functions,
- * or dropped completely,
- * but let's get it working (again) first...
- */
-
-static int display_banner(void)
-{
-	display_options();
-
-	return 0;
-}
-
-/**
- * Configure and report on the DRAM configuration, which in our case is
- * fairly simple.
- */
-static int display_dram_config(void)
-{
-	ulong size = 0;
-	int i;
-
-	debug("RAM Configuration:\n");
-
-	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
-#ifdef DEBUG
-		printf("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
-		print_size(gd->bd->bi_dram[i].size, "\n");
-#endif
-		size += gd->bd->bi_dram[i].size;
-	}
-	puts("DRAM:  ");
-	print_size(size, "\n");
-	return 0;
-}
-
-/*
- * Breathe some life into the board...
- *
- * Initialize a serial port as console, and carry out some hardware
- * tests.
- *
- * The first part of initialization is running from Flash memory;
- * its main purpose is to initialize the RAM so that we
- * can relocate the monitor code to RAM.
- */
-
-/*
- * All attempts to come up with a "common" initialization sequence
- * that works for all boards and architectures failed: some of the
- * requirements are just _too_ different. To get rid of the resulting
- * mess of board dependent #ifdef'ed code we now make the whole
- * initialization sequence configurable to the user.
- *
- * The requirements for any new initalization function is simple: it
- * receives a pointer to the "global data" structure as it's only
- * argument, and returns an integer return code, where 0 means
- * "continue" and != 0 means "fatal error, hang the system".
- */
-typedef int (init_fnc_t) (void);
-
-void __dram_init_banksize(void)
-{
-	gd->bd->bi_dram[0].start = 0;
-	gd->bd->bi_dram[0].size =  gd->ram_size;
-}
-
-void dram_init_banksize(void)
-	__attribute__((weak, alias("__dram_init_banksize")));
-
-init_fnc_t *init_sequence[] = {
-#if defined(CONFIG_ARCH_CPU_INIT)
-	arch_cpu_init,		/* basic arch cpu dependent setup */
-#endif
-#if defined(CONFIG_BOARD_EARLY_INIT_F)
-	board_early_init_f,
-#endif
-	timer_init,		/* initialize timer */
-	env_init,		/* initialize environment */
-	serial_init,		/* serial communications setup */
-	console_init_f,		/* stage 1 init of console */
-	sandbox_early_getopt_check,	/* process command line flags (err/help) */
-	display_banner,		/* say that we are here */
-#if defined(CONFIG_DISPLAY_CPUINFO)
-	print_cpuinfo,		/* display cpu info (and speed) */
-#endif
-#if defined(CONFIG_DISPLAY_BOARDINFO)
-	checkboard,		/* display board info */
-#endif
-	dram_init,		/* configure available RAM banks */
-	NULL,
-};
-
-void board_init_f(ulong bootflag)
-{
-	init_fnc_t **init_fnc_ptr;
-	uchar *mem;
-	unsigned long addr_sp, addr, size;
-
-	gd = &gd_mem;
-	assert(gd);
-
-	memset((void *)gd, 0, sizeof(gd_t));
-
-#if defined(CONFIG_OF_EMBED)
-	/* Get a pointer to the FDT */
-	gd->fdt_blob = _binary_dt_dtb_start;
-#elif defined(CONFIG_OF_SEPARATE)
-	/* FDT is at end of image */
-	gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
-#endif
-
-	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
-		if ((*init_fnc_ptr)() != 0)
-			hang();
-	}
-
-	size = CONFIG_SYS_SDRAM_SIZE;
-	mem = os_malloc(CONFIG_SYS_SDRAM_SIZE);
-
-	assert(mem);
-	gd->arch.ram_buf = mem;
-	addr = (ulong)(mem + size);
-
-	/*
-	 * reserve memory for malloc() arena
-	 */
-	addr_sp = addr - TOTAL_MALLOC_LEN;
-	debug("Reserving %dk for malloc() at: %08lx\n",
-			TOTAL_MALLOC_LEN >> 10, addr_sp);
-	/*
-	 * (permanently) allocate a Board Info struct
-	 * and a permanent copy of the "global" data
-	 */
-	addr_sp -= sizeof(bd_t);
-	gd->bd = (bd_t *) addr_sp;
-	debug("Reserving %zu Bytes for Board Info at: %08lx\n",
-			sizeof(bd_t), addr_sp);
-
-	/* Ram ist board specific, so move it to board code ... */
-	dram_init_banksize();
-	display_dram_config();	/* and display it */
-
-	/* We don't relocate, so just run the post-relocation code */
-	board_init_r(NULL, 0);
-
-	/* NOTREACHED - no way out of command loop except booting */
-}
-
-/************************************************************************
- *
- * This is the next part if the initialization sequence: we are now
- * running from RAM and have a "normal" C environment, i. e. global
- * data can be written, BSS has been cleared, the stack size in not
- * that critical any more, etc.
- *
- ************************************************************************
- */
-
-void board_init_r(gd_t *id, ulong dest_addr)
-{
-
-	if (id)
-		gd = id;
-
-	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
-
-	serial_initialize();
-
-#ifdef CONFIG_POST
-	post_output_backlog();
-#endif
-
-	/* The Malloc area is at the top of simulated DRAM */
-	mem_malloc_init((ulong)gd->arch.ram_buf + gd->ram_size -
-			TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
-
-	/* initialize environment */
-	env_relocate();
-
-	stdio_init();	/* get the devices list going. */
-
-	jumptable_init();
-
-	console_init_r();	/* fully init console as a device */
-
-#if defined(CONFIG_DISPLAY_BOARDINFO_LATE)
-	checkboard();
-#endif
-
-#if defined(CONFIG_ARCH_MISC_INIT)
-	/* miscellaneous arch dependent initialisations */
-	arch_misc_init();
-#endif
-#if defined(CONFIG_MISC_INIT_R)
-	/* miscellaneous platform dependent initialisations */
-	misc_init_r();
-#endif
-
-	 /* set up exceptions */
-	interrupt_init();
-	/* enable exceptions */
-	enable_interrupts();
-
-#ifdef CONFIG_BOARD_LATE_INIT
-	board_late_init();
-#endif
-
-#ifdef CONFIG_POST
-	post_run(NULL, POST_RAM | post_bootmode_get(0));
-#endif
-
-	sandbox_main_loop_init();
-
-	/*
-	 * For now, run the main loop. Later we might let this be done
-	 * in the main program.
-	 */
-	while (1)
-		main_loop();
-
-	/* NOTREACHED - no way out of command loop except booting */
-}
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}

+ 0 - 9
arch/sh/lib/board.c

@@ -200,12 +200,3 @@ void sh_generic_init(void)
 		main_loop();
 	}
 }
-
-/***********************************************************************/
-
-void hang(void)
-{
-	puts("Board ERROR\n");
-	for (;;)
-		;
-}

+ 0 - 9
arch/sparc/lib/board.c

@@ -411,13 +411,4 @@ void board_init_f(ulong bootflag)
 
 }
 
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-#ifdef CONFIG_SHOW_BOOT_PROGRESS
-	bootstage_error(BOOTSTAGE_ID_NEED_RESET);
-#endif
-	for (;;) ;
-}
-
 /************************************************************************/

+ 0 - 7
arch/x86/lib/board.c

@@ -264,10 +264,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
 
 	/* NOTREACHED - no way out of command loop except booting */
 }
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}

+ 20 - 6
board/a3m071/a3m071.c

@@ -8,7 +8,7 @@
  * (C) Copyright 2006
  * MicroSys GmbH
  *
- * Copyright 2012 Stefan Roese <sr@denx.de>
+ * Copyright 2012-2013 Stefan Roese <sr@denx.de>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -241,12 +241,26 @@ void spl_board_init(void)
 
 	/* And write new value back to register */
 	out_be32(&mm->ipbi_ws_ctrl, val);
-#endif
 
-	/*
-	 * No need to change the pin multiplexing (MPC5XXX_GPS_PORT_CONFIG)
-	 * as all 3 config versions (failsave level) have the same setup.
-	 */
+
+	/* Setup pin multiplexing */
+	if (failsavelevel == 2) {
+		/* fpga-version ok */
+#if defined(CONFIG_SYS_GPS_PORT_CONFIG_2)
+		out_be32(&gpio->port_config, CONFIG_SYS_GPS_PORT_CONFIG_2);
+#endif
+	} else if (failsavelevel == 1) {
+		/* digiboard-version ok - fpga not */
+#if defined(CONFIG_SYS_GPS_PORT_CONFIG_1)
+		out_be32(&gpio->port_config, CONFIG_SYS_GPS_PORT_CONFIG_1);
+#endif
+	} else {
+		/* full failsave-mode */
+#if defined(CONFIG_SYS_GPS_PORT_CONFIG)
+		out_be32(&gpio->port_config, CONFIG_SYS_GPS_PORT_CONFIG);
+#endif
+	}
+#endif
 
 	/*
 	 * Setup gpio_wkup_7 as watchdog AS INPUT to disable it - see

+ 17 - 2
board/freescale/b4860qds/tlb.c

@@ -111,8 +111,6 @@ struct fsl_e_tlb_entry tlb_table[] = {
 #ifdef CONFIG_SYS_NAND_BASE
 	/*
 	 * *I*G - NAND
-	 * entry 14 and 15 has been used hard coded, they will be disabled
-	 * in cpu_init_f, so we use entry 16 for nand.
 	 */
 	SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
 			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
@@ -122,6 +120,23 @@ struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 12, BOOKE_PAGESZ_4K, 1),
 
+	/*
+	 * *I*G - SRIO
+	 * entry 14 and 15 has been used hard coded, they will be disabled
+	 * in cpu_init_f, so we use entry 16 for SRIO2.
+	 */
+#ifdef CONFIG_SYS_SRIO1_MEM_PHYS
+	/* *I*G* - SRIO1 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO1_MEM_VIRT, CONFIG_SYS_SRIO1_MEM_PHYS,
+		MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 13, BOOKE_PAGESZ_256M, 1),
+#endif
+#ifdef CONFIG_SYS_SRIO2_MEM_PHYS
+	/* *I*G* - SRIO2 */
+	SET_TLB_ENTRY(1, CONFIG_SYS_SRIO2_MEM_VIRT, CONFIG_SYS_SRIO2_MEM_PHYS,
+		MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+		      0, 16, BOOKE_PAGESZ_256M, 1),
+#endif
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);

+ 6 - 0
board/freescale/common/Makefile

@@ -33,10 +33,14 @@ COBJS-$(CONFIG_FSL_CADMUS)	+= cadmus.o
 COBJS-$(CONFIG_FSL_VIA)		+= cds_via.o
 COBJS-$(CONFIG_FMAN_ENET)	+= fman.o
 COBJS-$(CONFIG_FSL_PIXIS)	+= pixis.o
+ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_FSL_NGPIXIS)	+= ngpixis.o
+endif
 COBJS-$(CONFIG_FSL_QIXIS)	+= qixis.o
 COBJS-$(CONFIG_PQ_MDS_PIB)	+= pq-mds-pib.o
+ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ID_EEPROM)	+= sys_eeprom.o
+endif
 COBJS-$(CONFIG_FSL_SGMII_RISER)	+= sgmii_riser.o
 ifndef CONFIG_RAMBOOT_PBL
 COBJS-$(CONFIG_FSL_FIXED_MMC_LOCATION)	+= sdhc_boot.o
@@ -48,7 +52,9 @@ COBJS-$(CONFIG_MPC8555CDS)	+= cds_pci_ft.o
 
 COBJS-$(CONFIG_MPC8536DS)	+= ics307_clk.o
 COBJS-$(CONFIG_MPC8572DS)	+= ics307_clk.o
+ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_P1022DS)		+= ics307_clk.o
+endif
 COBJS-$(CONFIG_P2020DS)		+= ics307_clk.o
 COBJS-$(CONFIG_P3041DS)		+= ics307_clk.o
 COBJS-$(CONFIG_P4080DS)		+= ics307_clk.o

+ 23 - 3
board/freescale/common/cds_pci_ft.c

@@ -31,7 +31,8 @@ static void cds_pci_fixup(void *blob)
 	int node;
 	const char *path;
 	int len, slot, i;
-	u32 *map = NULL;
+	u32 *map = NULL, *piccells = NULL;
+	int off, cells;
 
 	node = fdt_path_offset(blob, "/aliases");
 	if (node >= 0) {
@@ -41,6 +42,25 @@ static void cds_pci_fixup(void *blob)
 			if (node >= 0) {
 				map = fdt_getprop_w(blob, node, "interrupt-map", &len);
 			}
+			/* Each item in "interrupt-map" property is translated with
+			 * following cells:
+			 * PCI #address-cells, PCI #interrupt-cells,
+			 * PIC address, PIC #address-cells, PIC #interrupt-cells.
+			 */
+			cells = fdt_getprop_u32_default(blob, path, "#address-cells", 1);
+			cells += fdt_getprop_u32_default(blob, path, "#interrupt-cells", 1);
+			off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*(map+cells)));
+			if (off <= 0)
+				return;
+			cells += 1;
+			piccells = (u32 *)fdt_getprop(blob, off, "#address-cells", NULL);
+			if (piccells == NULL)
+				return;
+			cells += *piccells;
+			piccells = (u32 *)fdt_getprop(blob, off, "#interrupt-cells", NULL);
+			if (piccells == NULL)
+				return;
+			cells += *piccells;
 		}
 	}
 
@@ -49,12 +69,12 @@ static void cds_pci_fixup(void *blob)
 
 		slot = get_pci_slot();
 
-		for (i=0;i<len;i+=7) {
+		for (i=0;i<len;i+=cells) {
 			/* We rotate the interrupt pins so that the mapping
 			 * changes depending on the slot the carrier card is in.
 			 */
 			map[3] = ((map[3] + slot - 2) % 4) + 1;
-			map+=7;
+			map+=cells;
 		}
 	}
 }

+ 1 - 1
board/freescale/common/sdhc_boot.c

@@ -32,7 +32,7 @@
 #define ESDHC_BOOT_IMAGE_SIZE	0x48
 #define ESDHC_BOOT_IMAGE_ADDR	0x50
 
-int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr)
+int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
 {
 	u8 *tmp_buf;
 	u32 blklen, code_offset, code_len, n;

+ 1 - 1
board/freescale/p1010rdb/p1010rdb.c

@@ -217,7 +217,7 @@ void fdt_del_flexcan(void *blob)
 	int nodeoff = 0;
 
 	while ((nodeoff = fdt_node_offset_by_compatible(blob, 0,
-				"fsl,flexcan-v1.0")) >= 0) {
+				"fsl,p1010-flexcan")) >= 0) {
 		fdt_del_node(blob, nodeoff);
 	}
 }

+ 14 - 0
board/freescale/p1022ds/Makefile

@@ -11,12 +11,26 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y        += spl_minimal.o tlb.o law.o
+
+else
 COBJS-y	+= $(BOARD).o
 COBJS-y	+= ddr.o
 COBJS-y	+= law.o
 COBJS-y	+= tlb.o
 
 COBJS-$(CONFIG_FSL_DIU_FB) += diu.o
+endif
 
 SRCS	:= $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))

+ 1 - 0
board/freescale/p1022ds/law.c

@@ -16,6 +16,7 @@
 struct law_entry law_table[] = {
 	SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_256M, LAW_TRGT_IF_LBC),
 	SET_LAW(PIXIS_BASE_PHYS, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
+	SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_32K, LAW_TRGT_IF_LBC),
 };
 
 int num_law_entries = ARRAY_SIZE(law_table);

+ 129 - 0
board/freescale/p1022ds/spl_minimal.c

@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * 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 <ns16550.h>
+#include <asm/io.h>
+#include <nand.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+
+
+/*
+ * Fixed sdram init -- doesn't use serial presence detect.
+ */
+void sdram_init(void)
+{
+	volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+
+	__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
+	__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
+#if CONFIG_CHIP_SELECTS_PER_CTRL > 1
+	__raw_writel(CONFIG_SYS_DDR_CS1_BNDS, &ddr->cs1_bnds);
+	__raw_writel(CONFIG_SYS_DDR_CS1_CONFIG, &ddr->cs1_config);
+#endif
+	__raw_writel(CONFIG_SYS_DDR_TIMING_3, &ddr->timing_cfg_3);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_0, &ddr->timing_cfg_0);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_1, &ddr->timing_cfg_1);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_2, &ddr->timing_cfg_2);
+
+	__raw_writel(CONFIG_SYS_DDR_CONTROL_2, &ddr->sdram_cfg_2);
+	__raw_writel(CONFIG_SYS_DDR_MODE_1, &ddr->sdram_mode);
+	__raw_writel(CONFIG_SYS_DDR_MODE_2, &ddr->sdram_mode_2);
+
+	__raw_writel(CONFIG_SYS_DDR_INTERVAL, &ddr->sdram_interval);
+	__raw_writel(CONFIG_SYS_DDR_DATA_INIT, &ddr->sdram_data_init);
+	__raw_writel(CONFIG_SYS_DDR_CLK_CTRL, &ddr->sdram_clk_cntl);
+
+	__raw_writel(CONFIG_SYS_DDR_TIMING_4, &ddr->timing_cfg_4);
+	__raw_writel(CONFIG_SYS_DDR_TIMING_5, &ddr->timing_cfg_5);
+	__raw_writel(CONFIG_SYS_DDR_ZQ_CONTROL, &ddr->ddr_zq_cntl);
+	__raw_writel(CONFIG_SYS_DDR_WRLVL_CONTROL, &ddr->ddr_wrlvl_cntl);
+
+	/* Set, but do not enable the memory */
+	__raw_writel(CONFIG_SYS_DDR_CONTROL & ~SDRAM_CFG_MEM_EN,
+			&ddr->sdram_cfg);
+
+	in_be32(&ddr->sdram_cfg);
+	udelay(500);
+
+	/* Let the controller go */
+	out_be32(&ddr->sdram_cfg, in_be32(&ddr->sdram_cfg) | SDRAM_CFG_MEM_EN);
+	in_be32(&ddr->sdram_cfg);
+
+	set_next_law(0, CONFIG_SYS_SDRAM_SIZE_LAW, LAW_TRGT_IF_DDR_1);
+}
+
+const static u32 sysclk_tbl[] = {
+	66666000, 7499900, 83332500, 8999900,
+	99999000, 11111000, 12499800, 13333200
+};
+
+void board_init_f(ulong bootflag)
+{
+	int px_spd;
+	u32 plat_ratio, sys_clk, bus_clk;
+	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+	/* for FPGA */
+	set_lbc_br(2, CONFIG_SYS_BR2_PRELIM);
+	set_lbc_or(2, CONFIG_SYS_OR2_PRELIM);
+
+	/* initialize selected port with appropriate baud rate */
+	px_spd = in_8((unsigned char *)(PIXIS_BASE + PIXIS_SPD));
+	sys_clk = sysclk_tbl[px_spd & PIXIS_SPD_SYSCLK_MASK];
+	plat_ratio = in_be32(&gur->porpllsr) & MPC85xx_PORPLLSR_PLAT_RATIO;
+	bus_clk = sys_clk * plat_ratio / 2;
+
+	NS16550_init((NS16550_t)CONFIG_SYS_NS16550_COM1,
+			bus_clk / 16 / CONFIG_BAUDRATE);
+
+	puts("\nNAND boot... ");
+
+	/* Initialize the DDR3 */
+	sdram_init();
+
+	/* copy code to RAM and jump to it - this should not return */
+	/* NOTE - code has to be copied out of NAND buffer before
+	 * other blocks can be read.
+	 */
+	relocate_code(CONFIG_SPL_RELOC_STACK, 0,
+			CONFIG_SPL_RELOC_TEXT_BASE);
+}
+
+void board_init_r(gd_t *gd, ulong dest_addr)
+{
+	nand_boot();
+}
+
+void putc(char c)
+{
+	if (c == '\n')
+		NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, '\r');
+
+	NS16550_putc((NS16550_t)CONFIG_SYS_NS16550_COM1, c);
+}
+
+void puts(const char *str)
+{
+	while (*str)
+		putc(*str++);
+}

+ 14 - 6
board/freescale/p1022ds/tlb.c

@@ -41,6 +41,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 1, BOOKE_PAGESZ_1M, 1),
 
+#ifndef CONFIG_SPL_BUILD
 	/* W**G* - Flash/promjet, localbus */
 	/* This will be changed to *I*G* after relocation to RAM. */
 	SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
@@ -67,24 +68,31 @@ struct fsl_e_tlb_entry tlb_table[] = {
 	SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_IO_VIRT, CONFIG_SYS_PCIE3_IO_PHYS,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 6, BOOKE_PAGESZ_256K, 1),
+#endif
 
 	SET_TLB_ENTRY(1, PIXIS_BASE, PIXIS_BASE_PHYS,
 		      MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
 		      0, 7, BOOKE_PAGESZ_4K, 1),
 
-#ifdef CONFIG_SYS_RAMBOOT
-	/* *I*G - eSDHC/eSPI/NAND boot */
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
+	/* **** - eSDHC/eSPI/NAND boot */
 	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
 			MAS3_SX|MAS3_SW|MAS3_SR, 0,
 			0, 8, BOOKE_PAGESZ_1G, 1),
-
-	/* map the second 1G */
+	/* **** - eSDHC/eSPI/NAND boot - second 1GB of memory */
 	SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE + 0x40000000,
 			CONFIG_SYS_DDR_SDRAM_BASE + 0x40000000,
-			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+			MAS3_SX|MAS3_SW|MAS3_SR, 0,
 			0, 9, BOOKE_PAGESZ_1G, 1),
 #endif
-#
+
+#ifdef CONFIG_SYS_NAND_BASE
+	/* *I*G - NAND */
+	SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
+			MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+			0, 10, BOOKE_PAGESZ_16K, 1),
+#endif
+
 };
 
 int num_tlb_entries = ARRAY_SIZE(tlb_table);

+ 65 - 1
board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c

@@ -55,6 +55,13 @@
 #define GPIO_SLIC_PIN		30
 #define GPIO_SLIC_DATA		(1 << (31 - GPIO_SLIC_PIN))
 
+#if defined(CONFIG_P1021RDB) && !defined(CONFIG_SYS_RAMBOOT)
+#define GPIO_DDR_RST_PORT	1
+#define GPIO_DDR_RST_PIN	8
+#define GPIO_DDR_RST_DATA	(1 << (31 - GPIO_DDR_RST_PIN))
+
+#define GPIO_2BIT_MASK		(0x3 << (32 - (GPIO_DDR_RST_PIN + 1) * 2))
+#endif
 
 #if defined(CONFIG_P1025RDB) || defined(CONFIG_P1021RDB)
 #define PCA_IOPORT_I2C_ADDR		0x23
@@ -67,7 +74,7 @@
 const qe_iop_conf_t qe_iop_conf_tab[] = {
 	/* GPIO */
 	{1,   1, 2, 0, 0}, /* GPIO7/PB1   - LOAD_DEFAULT_N */
-#if 0
+#if defined(CONFIG_P1021RDB) && !defined(CONFIG_SYS_RAMBOOT)
 	{1,   8, 1, 1, 0}, /* GPIO10/PB8  - DDR_RST */
 #endif
 	{0,  15, 1, 0, 0}, /* GPIO11/A15  - WDI */
@@ -159,6 +166,16 @@ void board_gpio_init(void)
 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
 	par_io_t *par_io = (par_io_t *) &(gur->qe_par_io);
 
+#if defined(CONFIG_P1021RDB) && !defined(CONFIG_SYS_RAMBOOT)
+	/* reset DDR3 */
+	setbits_be32(&par_io[GPIO_DDR_RST_PORT].cpdat, GPIO_DDR_RST_DATA);
+	udelay(1000);
+	clrbits_be32(&par_io[GPIO_DDR_RST_PORT].cpdat, GPIO_DDR_RST_DATA);
+	udelay(1000);
+	setbits_be32(&par_io[GPIO_DDR_RST_PORT].cpdat, GPIO_DDR_RST_DATA);
+	/* disable CE_PB8 */
+	clrbits_be32(&par_io[GPIO_DDR_RST_PORT].cpdir1, GPIO_2BIT_MASK);
+#endif
 	/* Enable VSC7385 switch */
 	setbits_be32(&par_io[GPIO_GETH_SW_PORT].cpdat, GPIO_GETH_SW_DATA);
 
@@ -421,6 +438,8 @@ void ft_board_setup(void *blob, bd_t *bd)
 {
 	phys_addr_t base;
 	phys_size_t size;
+	const char *soc_usb_compat = "fsl-usb2-dr";
+	int err, usb1_off, usb2_off;
 
 	ft_cpu_setup(blob, bd);
 
@@ -442,5 +461,50 @@ void ft_board_setup(void *blob, bd_t *bd)
 #if defined(CONFIG_HAS_FSL_DR_USB)
 	fdt_fixup_dr_usb(blob, bd);
 #endif
+
+#if defined(CONFIG_SDCARD) || defined(CONFIG_SPIFLASH)
+	/* Delete eLBC node as it is muxed with USB2 controller */
+	if (hwconfig("usb2")) {
+		const char *soc_elbc_compat = "fsl,p1020-elbc";
+		int off = fdt_node_offset_by_compatible(blob, -1,
+				soc_elbc_compat);
+		if (off < 0) {
+			printf("WARNING: could not find compatible node %s: %s.\n",
+			       soc_elbc_compat,
+			       fdt_strerror(off));
+				return;
+		}
+		err = fdt_del_node(blob, off);
+		if (err < 0) {
+			printf("WARNING: could not remove %s: %s.\n",
+			       soc_elbc_compat, fdt_strerror(err));
+		}
+		return;
+	}
+#endif
+
+/* Delete USB2 node as it is muxed with eLBC */
+	usb1_off = fdt_node_offset_by_compatible(blob, -1,
+		soc_usb_compat);
+	if (usb1_off < 0) {
+		printf("WARNING: could not find compatible node %s: %s.\n",
+		       soc_usb_compat,
+		       fdt_strerror(usb1_off));
+		return;
+	}
+	usb2_off = fdt_node_offset_by_compatible(blob, usb1_off,
+			soc_usb_compat);
+	if (usb2_off < 0) {
+		printf("WARNING: could not find compatible node %s: %s.\n",
+		       soc_usb_compat,
+		       fdt_strerror(usb2_off));
+		return;
+	}
+	err = fdt_del_node(blob, usb2_off);
+	if (err < 0) {
+		printf("WARNING: could not remove %s: %s.\n",
+		       soc_usb_compat, fdt_strerror(err));
+	}
+
 }
 #endif

+ 15 - 0
board/freescale/p1_p2_rdb_pc/spl_minimal.c

@@ -81,6 +81,8 @@ void board_init_f(ulong bootflag)
 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
 #ifndef CONFIG_QE
 	ccsr_gpio_t *pgpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR);
+#elif defined(CONFIG_P1021RDB)
+	par_io_t *par_io = (par_io_t *)&(gur->qe_par_io);
 #endif
 
 	/* initialize selected port with appropriate baud rate */
@@ -102,6 +104,19 @@ void board_init_f(ulong bootflag)
 	__raw_writel(0x00200000, &pgpio->gpdat);
 	udelay(1000);
 	__raw_writel(0x00000000, &pgpio->gpdir);
+#elif defined(CONFIG_P1021RDB)
+	/* init DDR3 reset signal CE_PB8 */
+	out_be32(&par_io[1].cpdir1, 0x00004000);
+	out_be32(&par_io[1].cpodr, 0x00800000);
+	out_be32(&par_io[1].cppar1, 0x00000000);
+	/* reset DDR3 */
+	out_be32(&par_io[1].cpdat, 0x00800000);
+	udelay(1000);
+	out_be32(&par_io[1].cpdat, 0x00000000);
+	udelay(1000);
+	out_be32(&par_io[1].cpdat, 0x00800000);
+	/* disable the CE_PB8 */
+	out_be32(&par_io[1].cpdir1, 0x00000000);
 #endif
 
 #ifndef CONFIG_SYS_INIT_L2_ADDR

+ 9 - 0
board/h2200/h2200.c

@@ -32,6 +32,15 @@ int board_eth_init(bd_t *bis)
 	return 0;
 }
 
+void reset_cpu(ulong ignore)
+{
+	/* Enable VLIO interface on Hamcop */
+	writeb(0x1, 0x4000);
+
+	/* Reset board (cold reset) */
+	writeb(0xff, 0x4002);
+}
+
 int board_init(void)
 {
 	/* We have RAM, disable cache */

+ 73 - 2
board/lwmon5/lwmon5.c

@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2007-2010
+ * (C) Copyright 2007-2013
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  * This program is free software; you can redistribute it and/or
@@ -200,9 +200,11 @@ int misc_init_r(void)
 	u32 pbcr;
 	int size_val = 0;
 	u32 reg;
+#ifndef CONFIG_LCD4_LWMON5
 	unsigned long usb2d0cr = 0;
 	unsigned long usb2phy0cr, usb2h0cr = 0;
 	unsigned long sdr0_pfc1, sdr0_srst;
+#endif
 
 	/*
 	 * FLASH stuff...
@@ -233,6 +235,7 @@ int misc_init_r(void)
 		      CONFIG_ENV_ADDR_REDUND + 2 * CONFIG_ENV_SECT_SIZE - 1,
 		      &flash_info[cfi_flash_num_flash_banks - 1]);
 
+#ifndef CONFIG_LCD4_LWMON5
 	/*
 	 * USB suff...
 	 */
@@ -306,6 +309,7 @@ int misc_init_r(void)
 	/* 7. Reassert internal PHY reset: */
 	mtsdr(SDR0_SRST1, SDR0_SRST1_USB20PHY);
 	udelay(1000);
+#endif
 
 	/*
 	 * Clear resets
@@ -313,7 +317,9 @@ int misc_init_r(void)
 	mtsdr(SDR0_SRST1, 0x00000000);
 	mtsdr(SDR0_SRST0, 0x00000000);
 
+#ifndef CONFIG_LCD4_LWMON5
 	printf("USB:   Host(int phy) Device(ext phy)\n");
+#endif
 
 	/*
 	 * Clear PLB4A0_ACR[WRP]
@@ -323,10 +329,12 @@ int misc_init_r(void)
 	reg = mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_WRP_MASK;
 	mtdcr(PLB4A0_ACR, reg);
 
+#ifndef CONFIG_LCD4_LWMON5
 	/*
 	 * Init matrix keyboard
 	 */
 	misc_init_r_kbd();
+#endif
 
 	return 0;
 }
@@ -336,7 +344,7 @@ int checkboard(void)
 	char buf[64];
 	int i = getenv_f("serial#", buf, sizeof(buf));
 
-	puts("Board: lwmon5");
+	printf("Board: %s", __stringify(CONFIG_HOSTNAME));
 
 	if (i > 0) {
 		puts(", serial# ");
@@ -495,3 +503,66 @@ void board_reset(void)
 {
 	gpio_write_bit(CONFIG_SYS_GPIO_BOARD_RESET, 1);
 }
+
+#ifdef CONFIG_SPL_OS_BOOT
+/*
+ * lwmon5 specific implementation of spl_start_uboot()
+ *
+ * RETURN
+ * 0 if booting into OS is selected (default)
+ * 1 if booting into U-Boot is selected
+ */
+int spl_start_uboot(void)
+{
+	char s[8];
+
+	env_init();
+	getenv_f("boot_os", s, sizeof(s));
+	if ((s != NULL) && (strcmp(s, "yes") == 0))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * This function is called from the SPL U-Boot version for
+ * early init stuff, that needs to be done for OS (e.g. Linux)
+ * booting. Doing it later in the real U-Boot would not work
+ * in case that the SPL U-Boot boots Linux directly.
+ */
+void spl_board_init(void)
+{
+	const gdc_regs *regs = board_get_regs();
+
+	/*
+	 * Setup PFC registers, mainly for ethernet support
+	 * later on in Linux
+	 */
+	board_early_init_f();
+
+	/*
+	 * Clear resets
+	 */
+	mtsdr(SDR0_SRST1, 0x00000000);
+	mtsdr(SDR0_SRST0, 0x00000000);
+
+	/*
+	 * Reset Lime controller
+	 */
+	gpio_write_bit(CONFIG_SYS_GPIO_LIME_S, 1);
+	udelay(500);
+	gpio_write_bit(CONFIG_SYS_GPIO_LIME_RST, 1);
+
+	out_be32((void *)CONFIG_SYS_LIME_SDRAM_CLOCK, CONFIG_SYS_MB862xx_CCF);
+	udelay(300);
+	out_be32((void *)CONFIG_SYS_LIME_MMR, CONFIG_SYS_MB862xx_MMR);
+
+	while (regs->index) {
+		out_be32((void *)(CONFIG_SYS_LIME_BASE_0 + GC_DISP_BASE) +
+			 regs->index, regs->value);
+		regs++;
+	}
+
+	board_backlight_brightness(DEFAULT_BRIGHTNESS);
+}
+#endif

+ 3 - 1
board/lwmon5/sdram.c

@@ -6,7 +6,7 @@
  * Alain Saurel,	    AMCC/IBM, alain.saurel@fr.ibm.com
  * Robert Snyder,	    AMCC/IBM, rob.snyder@fr.ibm.com
  *
- * (C) Copyright 2007-2008
+ * (C) Copyright 2007-2013
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
  * This program is free software; you can redistribute it and/or
@@ -160,6 +160,7 @@ static void program_ecc(u32 start_address,
  ************************************************************************/
 phys_size_t initdram (int board_type)
 {
+#if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_LCD4_LWMON5)
 	/* CL=4 */
 	mtsdram(DDR0_02, 0x00000000);
 
@@ -253,6 +254,7 @@ phys_size_t initdram (int board_type)
 	 * exceptions are enabled.
 	 */
 	set_mcsr(get_mcsr());
+#endif /* CONFIG_SPL_BUILD */
 
 	return (CONFIG_SYS_MBYTES_SDRAM << 20);
 }

+ 1 - 1
board/sandbox/sandbox/sandbox.c

@@ -56,6 +56,6 @@ int timer_init(void)
 
 int dram_init(void)
 {
-	gd->ram_size = CONFIG_DRAM_SIZE;
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
 	return 0;
 }

+ 8 - 3
board/xilinx/microblaze-generic/microblaze-generic.c

@@ -38,10 +38,15 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	*((unsigned long *)(CONFIG_SYS_GPIO_0_ADDR)) =
 	    ++(*((unsigned long *)(CONFIG_SYS_GPIO_0_ADDR)));
 #endif
-#ifdef CONFIG_SYS_RESET_ADDRESS
-	puts ("Reseting board\n");
-	asm ("bra r0");
+
+#ifdef CONFIG_XILINX_TB_WATCHDOG
+	hw_watchdog_disable();
 #endif
+
+	puts ("Reseting board\n");
+	__asm__ __volatile__ ("	mts rmsr, r0;" \
+				"bra r0");
+
 	return 0;
 }
 

+ 4 - 0
board/xilinx/microblaze-generic/xparameters.h

@@ -77,3 +77,7 @@
 #define XILINX_LLTEMAC_SDMA_CTRL_BASEADDR	0x42000180
 #define XILINX_LLTEMAC_BASEADDR1		0x44200000
 #define XILINX_LLTEMAC_FIFO_BASEADDR1		0x42100000
+
+/* Watchdog IP is wxi_timebase_wdt_0 */
+#define XILINX_WATCHDOG_BASEADDR	0x50000000
+#define XILINX_WATCHDOG_IRQ		1

+ 3 - 0
boards.cfg

@@ -811,6 +811,8 @@ P1021RDB-PC_NAND             powerpc     mpc85xx     p1_p2_rdb_pc        freesca
 P1021RDB-PC_SDCARD           powerpc     mpc85xx     p1_p2_rdb_pc        freescale      -           p1_p2_rdb_pc:P1021RDB,SDCARD
 P1021RDB-PC_SPIFLASH         powerpc     mpc85xx     p1_p2_rdb_pc        freescale      -           p1_p2_rdb_pc:P1021RDB,SPIFLASH
 P1022DS                      powerpc     mpc85xx     p1022ds             freescale
+P1022DS_NAND                 powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:NAND
+P1022DS_36BIT_NAND           powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:36BIT,NAND
 P1022DS_SPIFLASH             powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:SPIFLASH
 P1022DS_36BIT_SPIFLASH       powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:36BIT,SPIFLASH
 P1022DS_SDCARD               powerpc     mpc85xx     p1022ds             freescale	-	    P1022DS:SDCARD
@@ -1010,6 +1012,7 @@ JSE                          powerpc     ppc4xx      jse
 korat                        powerpc     ppc4xx
 korat_perm                   powerpc     ppc4xx      korat               -              -           korat:KORAT_PERMANENT
 lwmon5                       powerpc     ppc4xx
+lcd4_lwmon5                  powerpc     ppc4xx      lwmon5              -              -           lwmon5:LCD4_LWMON5
 pcs440ep                     powerpc     ppc4xx
 quad100hd                    powerpc     ppc4xx
 sbc405                       powerpc     ppc4xx

+ 93 - 15
common/board_f.c

@@ -31,6 +31,7 @@
 #include <version.h>
 #include <environment.h>
 #include <fdtdec.h>
+#include <fs.h>
 #if defined(CONFIG_CMD_IDE)
 #include <ide.h>
 #endif
@@ -49,9 +50,11 @@
 #include <mpc5xxx.h>
 #endif
 
+#include <os.h>
 #include <post.h>
 #include <spi.h>
 #include <watchdog.h>
+#include <asm/errno.h>
 #include <asm/io.h>
 #ifdef CONFIG_MP
 #include <asm/mp.h>
@@ -61,6 +64,9 @@
 #include <asm/init_helpers.h>
 #include <asm/relocate.h>
 #endif
+#ifdef CONFIG_SANDBOX
+#include <asm/state.h>
+#endif
 #include <linux/compiler.h>
 
 /*
@@ -155,6 +161,7 @@ static int init_baud_rate(void)
 
 static int display_text_info(void)
 {
+#ifndef CONFIG_SANDBOX
 	ulong bss_start, bss_end;
 
 #ifdef CONFIG_SYS_SYM_OFFSETS
@@ -166,6 +173,7 @@ static int display_text_info(void)
 #endif
 	debug("U-Boot code: %08X -> %08lX  BSS: -> %08lX\n",
 	      CONFIG_SYS_TEXT_BASE, bss_start, bss_end);
+#endif
 
 #ifdef CONFIG_MODEM_SUPPORT
 	debug("Modem Support enabled\n");
@@ -284,6 +292,8 @@ static int setup_mon_len(void)
 {
 #ifdef CONFIG_SYS_SYM_OFFSETS
 	gd->mon_len = _bss_end_ofs;
+#elif defined(CONFIG_SANDBOX)
+	gd->mon_len = (ulong)&_end - (ulong)_init;
 #else
 	/* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */
 	gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
@@ -296,6 +306,66 @@ __weak int arch_cpu_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_OF_HOSTFILE
+
+#define CHECK(x)		err = (x); if (err) goto failed;
+
+/* Create an empty device tree blob */
+static int make_empty_fdt(void *fdt)
+{
+	int err;
+
+	CHECK(fdt_create(fdt, 256));
+	CHECK(fdt_finish_reservemap(fdt));
+	CHECK(fdt_begin_node(fdt, ""));
+	CHECK(fdt_end_node(fdt));
+	CHECK(fdt_finish(fdt));
+
+	return 0;
+failed:
+	printf("Unable to create empty FDT: %s\n", fdt_strerror(err));
+	return -EACCES;
+}
+
+static int read_fdt_from_file(void)
+{
+	struct sandbox_state *state = state_get_current();
+	void *blob;
+	int size;
+	int err;
+
+	blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0);
+	if (!state->fdt_fname) {
+		err = make_empty_fdt(blob);
+		if (!err)
+			goto done;
+		return err;
+	}
+	err = fs_set_blk_dev("host", NULL, FS_TYPE_SANDBOX);
+	if (err)
+		return err;
+	size = fs_read(state->fdt_fname, CONFIG_SYS_FDT_LOAD_ADDR, 0, 0);
+	if (size < 0)
+		return -EIO;
+
+done:
+	gd->fdt_blob = blob;
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SANDBOX
+static int setup_ram_buf(void)
+{
+	gd->arch.ram_buf = os_malloc(CONFIG_SYS_SDRAM_SIZE);
+	assert(gd->arch.ram_buf);
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+#endif
+
 static int setup_fdt(void)
 {
 #ifdef CONFIG_OF_EMBED
@@ -308,6 +378,11 @@ static int setup_fdt(void)
 # else
 	gd->fdt_blob = (ulong *)&_end;
 # endif
+#elif defined(CONFIG_OF_HOSTFILE)
+	if (read_fdt_from_file()) {
+		puts("Failed to read control FDT\n");
+		return -1;
+	}
 #endif
 	/* Allow the early environment to override the fdt address */
 	gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
@@ -470,7 +545,7 @@ static int reserve_malloc(void)
 static int reserve_board(void)
 {
 	gd->dest_addr_sp -= sizeof(bd_t);
-	gd->bd = (bd_t *)gd->dest_addr_sp;
+	gd->bd = (bd_t *)map_sysmem(gd->dest_addr_sp, sizeof(bd_t));
 	memset(gd->bd, '\0', sizeof(bd_t));
 	debug("Reserving %zu Bytes for Board Info at: %08lx\n",
 			sizeof(bd_t), gd->dest_addr_sp);
@@ -489,7 +564,7 @@ static int setup_machine(void)
 static int reserve_global_data(void)
 {
 	gd->dest_addr_sp -= sizeof(gd_t);
-	gd->new_gd = (gd_t *)gd->dest_addr_sp;
+	gd->new_gd = (gd_t *)map_sysmem(gd->dest_addr_sp, sizeof(gd_t));
 	debug("Reserving %zu Bytes for Global Data at: %08lx\n",
 			sizeof(gd_t), gd->dest_addr_sp);
 	return 0;
@@ -506,9 +581,9 @@ static int reserve_fdt(void)
 		gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32);
 
 		gd->dest_addr_sp -= gd->fdt_size;
-		gd->new_fdt = (void *)gd->dest_addr_sp;
-		debug("Reserving %lu Bytes for FDT at: %p\n",
-		      gd->fdt_size, gd->new_fdt);
+		gd->new_fdt = map_sysmem(gd->dest_addr_sp, gd->fdt_size);
+		debug("Reserving %lu Bytes for FDT at: %08lx\n",
+		      gd->fdt_size, gd->dest_addr_sp);
 	}
 
 	return 0;
@@ -709,8 +784,9 @@ static int setup_reloc(void)
 	memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));
 
 	debug("Relocation Offset is: %08lx\n", gd->reloc_off);
-	debug("Relocating to %08lx, new gd at %p, sp at %08lx\n",
-	      gd->dest_addr, gd->new_gd, gd->dest_addr_sp);
+	debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n",
+	      gd->dest_addr, (ulong)map_to_sysmem(gd->new_gd),
+	      gd->dest_addr_sp);
 
 	return 0;
 }
@@ -736,6 +812,8 @@ static int jump_to_copy(void)
 	 * (CPU cache)
 	 */
 	board_init_f_r_trampoline(gd->start_addr_sp);
+#elif defined(CONFIG_SANDBOX)
+	board_init_r(gd->new_gd, 0);
 #else
 	relocate_code(gd->dest_addr_sp, gd->new_gd, gd->dest_addr);
 #endif
@@ -757,6 +835,9 @@ static init_fnc_t init_sequence_f[] = {
 		!defined(CONFIG_MPC83xx) && !defined(CONFIG_MPC85xx) && \
 		!defined(CONFIG_MPC86xx) && !defined(CONFIG_X86)
 	zero_global_data,
+#endif
+#ifdef CONFIG_SANDBOX
+	setup_ram_buf,
 #endif
 	setup_fdt,
 	setup_mon_len,
@@ -816,8 +897,11 @@ static init_fnc_t init_sequence_f[] = {
 	init_baud_rate,		/* initialze baudrate settings */
 	serial_init,		/* serial communications setup */
 	console_init_f,		/* stage 1 init of console */
-#if defined(CONFIG_X86) && defined(CONFIG_OF_CONTROL)
-	prepare_fdt,		/* TODO(sjg@chromium.org): remove */
+#ifdef CONFIG_SANDBOX
+	sandbox_early_getopt_check,
+#endif
+#ifdef CONFIG_OF_CONTROL
+	fdtdec_prepare_fdt,
 #endif
 	display_options,	/* say that we are here */
 	display_text_info,	/* show debugging info if required */
@@ -1003,9 +1087,3 @@ void board_init_f_r(void)
 	hang();
 }
 #endif /* CONFIG_X86 */
-
-void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;);
-}

+ 6 - 2
common/board_r.c

@@ -136,7 +136,7 @@ static int initr_reloc_global_data(void)
 {
 #ifdef CONFIG_SYS_SYM_OFFSETS
 	monitor_flash_len = _end_ofs;
-#else
+#elif !defined(CONFIG_SANDBOX)
 	monitor_flash_len = (ulong)&__init_end - gd->dest_addr;
 #endif
 #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
@@ -264,7 +264,8 @@ static int initr_malloc(void)
 
 	/* The malloc area is immediately below the monitor copy in DRAM */
 	malloc_start = gd->dest_addr - TOTAL_MALLOC_LEN;
-	mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN);
+	mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN),
+			TOTAL_MALLOC_LEN);
 	return 0;
 }
 
@@ -691,6 +692,9 @@ static int initr_modem(void)
 
 static int run_main_loop(void)
 {
+#ifdef CONFIG_SANDBOX
+	sandbox_main_loop_init();
+#endif
 	/* main_loop() can return to retry autoboot, if so just run it again */
 	for (;;)
 		main_loop();

+ 57 - 30
common/cmd_fdt.c

@@ -31,6 +31,7 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <asm/io.h>
 
 #define MAX_LEVEL	32		/* how deeply nested we will go */
 #define SCRATCHPAD	1024		/* bytes of scratchpad memory */
@@ -43,7 +44,7 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
-static int fdt_valid(void);
+static int fdt_valid(struct fdt_header **blobp);
 static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
 static int fdt_print(const char *pathp, char *prop, int depth);
 static int is_printable_string(const void *data, int len);
@@ -55,7 +56,10 @@ struct fdt_header *working_fdt;
 
 void set_working_fdt_addr(void *addr)
 {
-	working_fdt = addr;
+	void *buf;
+
+	buf = map_sysmem((ulong)addr, 0);
+	working_fdt = buf;
 	setenv_addr("fdtaddr", addr);
 }
 
@@ -100,40 +104,59 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 	if (argv[1][0] == 'a') {
 		unsigned long addr;
+		int control = 0;
+		struct fdt_header *blob;
 		/*
 		 * Set the address [and length] of the fdt.
 		 */
-		if (argc == 2) {
-			if (!fdt_valid()) {
+		argc -= 2;
+		argv += 2;
+/* Temporary #ifdef - some archs don't have fdt_blob yet */
+#ifdef CONFIG_OF_CONTROL
+		if (argc && !strcmp(*argv, "-c")) {
+			control = 1;
+			argc--;
+			argv++;
+		}
+#endif
+		if (argc == 0) {
+			if (control)
+				blob = (struct fdt_header *)gd->fdt_blob;
+			else
+				blob = working_fdt;
+			if (!blob || !fdt_valid(&blob))
 				return 1;
-			}
-			printf("The address of the fdt is %p\n", working_fdt);
+			printf("The address of the fdt is %#08lx\n",
+			       control ? (ulong)blob :
+					getenv_hex("fdtaddr", 0));
 			return 0;
 		}
 
-		addr = simple_strtoul(argv[2], NULL, 16);
-		set_working_fdt_addr((void *)addr);
-
-		if (!fdt_valid()) {
+		addr = simple_strtoul(argv[0], NULL, 16);
+		blob = map_sysmem(addr, 0);
+		if (!fdt_valid(&blob))
 			return 1;
-		}
+		if (control)
+			gd->fdt_blob = blob;
+		else
+			set_working_fdt_addr(blob);
 
-		if (argc >= 4) {
+		if (argc >= 2) {
 			int  len;
 			int  err;
 			/*
 			 * Optional new length
 			 */
-			len = simple_strtoul(argv[3], NULL, 16);
-			if (len < fdt_totalsize(working_fdt)) {
+			len = simple_strtoul(argv[1], NULL, 16);
+			if (len < fdt_totalsize(blob)) {
 				printf ("New length %d < existing length %d, "
 					"ignoring.\n",
-					len, fdt_totalsize(working_fdt));
+					len, fdt_totalsize(blob));
 			} else {
 				/*
 				 * Open in place with a new length.
 				 */
-				err = fdt_open_into(working_fdt, working_fdt, len);
+				err = fdt_open_into(blob, blob, len);
 				if (err != 0) {
 					printf ("libfdt fdt_open_into(): %s\n",
 						fdt_strerror(err));
@@ -167,9 +190,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		 * Set the address and length of the fdt.
 		 */
 		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
-		if (!fdt_valid()) {
+		if (!fdt_valid(&working_fdt))
 			return 1;
-		}
 
 		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
 
@@ -592,16 +614,23 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 /****************************************************************************/
 
-static int fdt_valid(void)
+/**
+ * fdt_valid() - Check if an FDT is valid. If not, change it to NULL
+ *
+ * @blobp: Pointer to FDT pointer
+ * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL)
+ */
+static int fdt_valid(struct fdt_header **blobp)
 {
-	int  err;
+	const void *blob = *blobp;
+	int err;
 
-	if (working_fdt == NULL) {
+	if (blob == NULL) {
 		printf ("The address of the fdt is invalid (NULL).\n");
 		return 0;
 	}
 
-	err = fdt_check_header(working_fdt);
+	err = fdt_check_header(blob);
 	if (err == 0)
 		return 1;	/* valid */
 
@@ -611,23 +640,21 @@ static int fdt_valid(void)
 		 * Be more informative on bad version.
 		 */
 		if (err == -FDT_ERR_BADVERSION) {
-			if (fdt_version(working_fdt) <
+			if (fdt_version(blob) <
 			    FDT_FIRST_SUPPORTED_VERSION) {
 				printf (" - too old, fdt %d < %d",
-					fdt_version(working_fdt),
+					fdt_version(blob),
 					FDT_FIRST_SUPPORTED_VERSION);
-				working_fdt = NULL;
 			}
-			if (fdt_last_comp_version(working_fdt) >
+			if (fdt_last_comp_version(blob) >
 			    FDT_LAST_SUPPORTED_VERSION) {
 				printf (" - too new, fdt %d > %d",
-					fdt_version(working_fdt),
+					fdt_version(blob),
 					FDT_LAST_SUPPORTED_VERSION);
-				working_fdt = NULL;
 			}
-			return 0;
 		}
 		printf("\n");
+		*blobp = NULL;
 		return 0;
 	}
 	return 1;
@@ -958,7 +985,7 @@ static int fdt_print(const char *pathp, char *prop, int depth)
 /********************************************************************/
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
-	"addr   <addr> [<length>]        - Set the fdt location to <addr>\n"
+	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
 #ifdef CONFIG_OF_BOARD_SETUP
 	"fdt boardsetup                      - Do board-specific set up\n"
 #endif

+ 5 - 0
common/cmd_ide.c

@@ -455,6 +455,8 @@ void ide_init(void)
 		ide_dev_desc[i].dev = i;
 		ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN;
 		ide_dev_desc[i].blksz = 0;
+		ide_dev_desc[i].log2blksz =
+			LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
 		ide_dev_desc[i].lba = 0;
 		ide_dev_desc[i].block_read = ide_read;
 		ide_dev_desc[i].block_write = ide_write;
@@ -806,6 +808,7 @@ static void ide_ident(block_dev_desc_t *dev_desc)
 	/* assuming HD */
 	dev_desc->type = DEV_TYPE_HARDDISK;
 	dev_desc->blksz = ATA_BLOCKSIZE;
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 	dev_desc->lun = 0;	/* just to fill something in... */
 
 #if 0				/* only used to test the powersaving mode,
@@ -1448,6 +1451,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc)
 	dev_desc->lun = 0;
 	dev_desc->lba = 0;
 	dev_desc->blksz = 0;
+	dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz));
 	dev_desc->type = iobuf[0] & 0x1f;
 
 	if ((iobuf[1] & 0x80) == 0x80)
@@ -1492,6 +1496,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc)
 	dev_desc->blksz = ((unsigned long) iobuf[4] << 24) +
 		((unsigned long) iobuf[5] << 16) +
 		((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]);
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 #ifdef CONFIG_LBA48
 	/* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
 	dev_desc->lba48 = 0;

+ 80 - 22
common/cmd_nvedit.c

@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000-2010
+ * (C) Copyright 2000-2013
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
@@ -164,31 +164,57 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc,
 static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
 		       int argc, char * const argv[])
 {
-	ENTRY *match;
-	unsigned char matched[env_htab.size / 8];
-	int rcode = 1, arg = 1, idx;
+	char *res = NULL;
+	int len, grep_how, grep_what;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
 
-	memset(matched, 0, env_htab.size / 8);
+	grep_how  = H_MATCH_SUBSTR;	/* default: substring search	*/
+	grep_what = H_MATCH_BOTH;	/* default: grep names and values */
 
-	while (arg <= argc) {
-		idx = 0;
-		while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) {
-			if (!(matched[idx / 8] & (1 << (idx & 7)))) {
-				puts(match->key);
-				puts("=");
-				puts(match->data);
-				puts("\n");
+	while (argc > 1 && **(argv + 1) == '-') {
+		char *arg = *++argv;
+
+		--argc;
+		while (*++arg) {
+			switch (*arg) {
+#ifdef CONFIG_REGEX
+			case 'e':		/* use regex matching */
+				grep_how  = H_MATCH_REGEX;
+				break;
+#endif
+			case 'n':		/* grep for name */
+				grep_what = H_MATCH_KEY;
+				break;
+			case 'v':		/* grep for value */
+				grep_what = H_MATCH_DATA;
+				break;
+			case 'b':		/* grep for both */
+				grep_what = H_MATCH_BOTH;
+				break;
+			case '-':
+				goto DONE;
+			default:
+				return CMD_RET_USAGE;
 			}
-			matched[idx / 8] |= 1 << (idx & 7);
-			rcode = 0;
 		}
-		arg++;
 	}
 
-	return rcode;
+DONE:
+	len = hexport_r(&env_htab, '\n',
+			flag | grep_what | grep_how,
+			&res, 0, argc, argv);
+
+	if (len > 0) {
+		puts(res);
+		free(res);
+	}
+
+	if (len < 2)
+		return 1;
+
+	return 0;
 }
 #endif
 #endif /* CONFIG_SPL_BUILD */
@@ -315,6 +341,21 @@ int setenv_hex(const char *varname, ulong value)
 	return setenv(varname, str);
 }
 
+ulong getenv_hex(const char *varname, ulong default_val)
+{
+	const char *s;
+	ulong value;
+	char *endp;
+
+	s = getenv(varname);
+	if (s)
+		value = simple_strtoul(s, &endp, 16);
+	if (!s || endp == s)
+		return default_val;
+
+	return value;
+}
+
 #ifndef CONFIG_SPL_BUILD
 static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -877,7 +918,9 @@ NXTARG:		;
 	argv++;
 
 	if (sep) {		/* export as text file */
-		len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv);
+		len = hexport_r(&env_htab, sep,
+				H_MATCH_KEY | H_MATCH_IDENT,
+				&addr, size, argc, argv);
 		if (len < 0) {
 			error("Cannot export environment: errno = %d\n", errno);
 			return 1;
@@ -895,7 +938,9 @@ NXTARG:		;
 	else			/* export as raw binary data */
 		res = addr;
 
-	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv);
+	len = hexport_r(&env_htab, '\0',
+			H_MATCH_KEY | H_MATCH_IDENT,
+			&res, ENV_SIZE, argc, argv);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
@@ -1114,7 +1159,11 @@ static char env_help_text[] =
 	"env flags - print variables that have non-default flags\n"
 #endif
 #if defined(CONFIG_CMD_GREPENV)
-	"env grep string [...] - search environment\n"
+#ifdef CONFIG_REGEX
+	"env grep [-e] [-n | -v | -b] string [...] - search environment\n"
+#else
+	"env grep [-n | -v | -b] string [...] - search environment\n"
+#endif
 #endif
 #if defined(CONFIG_CMD_IMPORTENV)
 	"env import [-d] [-t | -b | -c] addr [size] - import environment\n"
@@ -1161,8 +1210,17 @@ U_BOOT_CMD_COMPLETE(
 U_BOOT_CMD_COMPLETE(
 	grepenv, CONFIG_SYS_MAXARGS, 0,  do_env_grep,
 	"search environment variables",
-	"string ...\n"
-	"    - list environment name=value pairs matching 'string'",
+#ifdef CONFIG_REGEX
+	"[-e] [-n | -v | -b] string ...\n"
+#else
+	"[-n | -v | -b] string ...\n"
+#endif
+	"    - list environment name=value pairs matching 'string'\n"
+#ifdef CONFIG_REGEX
+	"      \"-e\": enable regular expressions;\n"
+#endif
+	"      \"-n\": search variable names; \"-v\": search values;\n"
+	"      \"-b\": search both names and values (default)",
 	var_complete
 );
 #endif

+ 14 - 4
common/cmd_sandbox.c

@@ -32,9 +32,16 @@ static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc,
 	return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX);
 }
 
+static int do_sandbox_save(cmd_tbl_t *cmdtp, int flag, int argc,
+			   char * const argv[])
+{
+	return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX, 16);
+}
+
 static cmd_tbl_t cmd_sandbox_sub[] = {
-	U_BOOT_CMD_MKENT(load, 3, 0, do_sandbox_load, "", ""),
+	U_BOOT_CMD_MKENT(load, 7, 0, do_sandbox_load, "", ""),
 	U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""),
+	U_BOOT_CMD_MKENT(save, 6, 0, do_sandbox_save, "", ""),
 };
 
 static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -56,8 +63,11 @@ static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc,
 }
 
 U_BOOT_CMD(
-	sb,	6,	1,	do_sandbox,
+	sb,	8,	1,	do_sandbox,
 	"Miscellaneous sandbox commands",
-	"load host <addr> <filename> [<bytes> <offset>]  - load a file from host\n"
-	"sb ls host <filename>      - save a file to host"
+	"load host <dev> <addr> <filename> [<bytes> <offset>]  - "
+		"load a file from host\n"
+	"sb ls host <filename>                      - list files on host\n"
+	"sb save host <dev> <filename> <addr> <bytes> [<offset>] - "
+		"save a file to host\n"
 );

+ 1 - 0
common/cmd_sata.c

@@ -44,6 +44,7 @@ int __sata_initialize(void)
 		sata_dev_desc[i].type = DEV_TYPE_HARDDISK;
 		sata_dev_desc[i].lba = 0;
 		sata_dev_desc[i].blksz = 512;
+		sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz);
 		sata_dev_desc[i].block_read = sata_read;
 		sata_dev_desc[i].block_write = sata_write;
 

+ 4 - 0
common/cmd_scsi.c

@@ -106,6 +106,8 @@ void scsi_scan(int mode)
 		scsi_dev_desc[i].lun=0xff;
 		scsi_dev_desc[i].lba=0;
 		scsi_dev_desc[i].blksz=0;
+		scsi_dev_desc[i].log2blksz =
+			LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz));
 		scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN;
 		scsi_dev_desc[i].vendor[0]=0;
 		scsi_dev_desc[i].product[0]=0;
@@ -166,6 +168,8 @@ void scsi_scan(int mode)
 			}
 			scsi_dev_desc[scsi_max_devs].lba=capacity;
 			scsi_dev_desc[scsi_max_devs].blksz=blksz;
+			scsi_dev_desc[scsi_max_devs].log2blksz =
+				LOG2(scsi_dev_desc[scsi_max_devs].blksz);
 			scsi_dev_desc[scsi_max_devs].type=perq;
 			init_part(&scsi_dev_desc[scsi_max_devs]);
 removable:

+ 287 - 9
common/cmd_setexpr.c

@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2013 Wolfgang Denk <wd@denx.de>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -50,28 +51,295 @@ static ulong get_arg(char *s, int w)
 	}
 }
 
+#ifdef CONFIG_REGEX
+
+#include <slre.h>
+
+#define SLRE_BUFSZ	16384
+#define SLRE_PATSZ	4096
+
+/*
+ * memstr - Find the first substring in memory
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ *
+ * Similar to and based on strstr(),
+ * but strings do not need to be NUL terminated.
+ */
+static char *memstr(const char *s1, int l1, const char *s2, int l2)
+{
+	if (!l2)
+		return (char *)s1;
+
+	while (l1 >= l2) {
+		l1--;
+		if (!memcmp(s1, s2, l2))
+			return (char *)s1;
+		s1++;
+	}
+	return NULL;
+}
+
+static char *substitute(char *string,	/* string buffer */
+			int *slen,	/* current string length */
+			int ssize,	/* string bufer size */
+			const char *old,/* old (replaced) string */
+			int olen,	/* length of old string */
+			const char *new,/* new (replacement) string */
+			int nlen)	/* length of new string */
+{
+	char *p = memstr(string, *slen, old, olen);
+
+	if (p == NULL)
+		return NULL;
+
+	debug("## Match at pos %ld: match len %d, subst len %d\n",
+		(long)(p - string), olen, nlen);
+
+	/* make sure replacement matches */
+	if (*slen + nlen - olen > ssize) {
+		printf("## error: substitution buffer overflow\n");
+		return NULL;
+	}
+
+	/* move tail if needed */
+	if (olen != nlen) {
+		int tail, len;
+
+		len = (olen > nlen) ? olen : nlen;
+
+		tail = ssize - (p + len - string);
+
+		debug("## tail len %d\n", tail);
+
+		memmove(p + nlen, p + olen, tail);
+	}
+
+	/* insert substitue */
+	memcpy(p, new, nlen);
+
+	*slen += nlen - olen;
+
+	return p + nlen;
+}
+
+/*
+ * Perform regex operations on a environment variable
+ *
+ * Returns 0 if OK, 1 in case of errors.
+ */
+static int regex_sub(const char *name,
+	const char *r, const char *s, const char *t,
+	int global)
+{
+	struct slre slre;
+	char data[SLRE_BUFSZ];
+	char *datap = data;
+	const char *value;
+	int res, len, nlen, loop;
+
+	if (name == NULL)
+		return 1;
+
+	if (slre_compile(&slre, r) == 0) {
+		printf("Error compiling regex: %s\n", slre.err_str);
+		return 1;
+	}
+
+	if (t == NULL) {
+		value = getenv(name);
+
+		if (value == NULL) {
+			printf("## Error: variable \"%s\" not defined\n", name);
+			return 1;
+		}
+		t = value;
+	}
+
+	debug("REGEX on %s=%s\n", name, t);
+	debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n",
+		r, s ? s : "<NULL>", global);
+
+	len = strlen(t);
+	if (len + 1 > SLRE_BUFSZ) {
+		printf("## error: subst buffer overflow: have %d, need %d\n",
+			SLRE_BUFSZ, len + 1);
+		return 1;
+	}
+
+	strcpy(data, t);
+
+	if (s == NULL)
+		nlen = 0;
+	else
+		nlen = strlen(s);
+
+	for (loop = 0;; loop++) {
+		struct cap caps[slre.num_caps + 2];
+		char nbuf[SLRE_PATSZ];
+		const char *old;
+		char *np;
+		int i, olen;
+
+		(void) memset(caps, 0, sizeof(caps));
+
+		res = slre_match(&slre, datap, len, caps);
+
+		debug("Result: %d\n", res);
+
+		for (i = 0; i < slre.num_caps; i++) {
+			if (caps[i].len > 0) {
+				debug("Substring %d: [%.*s]\n", i,
+					caps[i].len, caps[i].ptr);
+			}
+		}
+
+		if (res == 0) {
+			if (loop == 0) {
+				printf("%s: No match\n", t);
+				return 1;
+			} else {
+				break;
+			}
+		}
+
+		debug("## MATCH ## %s\n", data);
+
+		if (s == NULL) {
+			printf("%s=%s\n", name, t);
+			return 1;
+		}
+
+		old = caps[0].ptr;
+		olen = caps[0].len;
+
+		if (nlen + 1 >= SLRE_PATSZ) {
+			printf("## error: pattern buffer overflow: have %d, need %d\n",
+				SLRE_BUFSZ, nlen + 1);
+			return 1;
+		}
+		strcpy(nbuf, s);
+
+		debug("## SUBST(1) ## %s\n", nbuf);
+
+		/*
+		 * Handle back references
+		 *
+		 * Support for \0 ... \9, where \0 is the
+		 * whole matched pattern (similar to &).
+		 *
+		 * Implementation is a bit simpleminded as
+		 * backrefs are substituted sequentially, one
+		 * by one.  This will lead to somewhat
+		 * unexpected results if the replacement
+		 * strings contain any \N strings then then
+		 * may get substitued, too.  We accept this
+		 * restriction for the sake of simplicity.
+		 */
+		for (i = 0; i < 10; ++i) {
+			char backref[2] = {
+				'\\',
+				'0',
+			};
+
+			if (caps[i].len == 0)
+				break;
+
+			backref[1] += i;
+
+			debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n",
+				i,
+				2, backref,
+				caps[i].len, caps[i].ptr,
+				nbuf);
+
+			for (np = nbuf;;) {
+				char *p = memstr(np, nlen, backref, 2);
+
+				if (p == NULL)
+					break;
+
+				np = substitute(np, &nlen,
+					SLRE_PATSZ,
+					backref, 2,
+					caps[i].ptr, caps[i].len);
+
+				if (np == NULL)
+					return 1;
+			}
+		}
+		debug("## SUBST(2) ## %s\n", nbuf);
+
+		datap = substitute(datap, &len, SLRE_BUFSZ,
+				old, olen,
+				nbuf, nlen);
+
+		if (datap == NULL)
+			return 1;
+
+		debug("## REMAINDER: %s\n", datap);
+
+		debug("## RESULT: %s\n", data);
+
+		if (!global)
+			break;
+	}
+	debug("## FINAL (now setenv()) :  %s\n", data);
+
+	printf("%s=%s\n", name, data);
+
+	return setenv(name, data);
+}
+#endif
+
 static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	ulong a, b;
 	ulong value;
 	int w;
 
-	/* Validate arguments */
-	if (argc != 5 && argc != 3)
-		return CMD_RET_USAGE;
-	if (argc == 5 && strlen(argv[3]) != 1)
+	/*
+	 * We take 3, 5, or 6 arguments:
+	 * 3 : setexpr name value
+	 * 5 : setexpr name val1 op val2
+	 *     setexpr name [g]sub r s
+	 * 6 : setexpr name [g]sub r s t
+	 */
+
+	/* > 6 already tested by max command args */
+	if ((argc < 3) || (argc == 4))
 		return CMD_RET_USAGE;
 
 	w = cmd_get_data_size(argv[0], 4);
 
 	a = get_arg(argv[2], w);
 
+	/* plain assignment: "setexpr name value" */
 	if (argc == 3) {
 		setenv_hex(argv[1], a);
-
 		return 0;
 	}
 
+	/* 5 or 6 args (6 args only with [g]sub) */
+#ifdef CONFIG_REGEX
+	/*
+	 * rexep handling: "setexpr name [g]sub r s [t]"
+	 * with 5 args, "t" will be NULL
+	 */
+	if (strcmp(argv[2], "gsub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 1);
+
+	if (strcmp(argv[2], "sub") == 0)
+		return regex_sub(argv[1], argv[3], argv[4], argv[5], 0);
+#endif
+
+	/* standard operators: "setexpr name val1 op val2" */
+	if (argc != 5)
+		return CMD_RET_USAGE;
+
+	if (strlen(argv[3]) != 1)
+		return CMD_RET_USAGE;
+
 	b = get_arg(argv[4], w);
 
 	switch (argv[3][0]) {
@@ -110,13 +378,23 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 }
 
 U_BOOT_CMD(
-	setexpr, 5, 0, do_setexpr,
+	setexpr, 6, 0, do_setexpr,
 	"set environment variable as the result of eval expression",
 	"[.b, .w, .l] name [*]value1 <op> [*]value2\n"
 	"    - set environment variable 'name' to the result of the evaluated\n"
-	"      express specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
+	"      expression specified by <op>.  <op> can be &, |, ^, +, -, *, /, %\n"
 	"      size argument is only meaningful if value1 and/or value2 are\n"
 	"      memory addresses (*)\n"
-	"setexpr[.b, .w, .l] name *value\n"
-	"    - load a memory address into a variable"
+	"setexpr[.b, .w, .l] name [*]value\n"
+	"    - load a value into a variable"
+#ifdef CONFIG_REGEX
+	"\n"
+	"setexpr name gsub r s [t]\n"
+	"    - For each substring matching the regular expression <r> in the\n"
+	"      string <t>, substitute the string <s>.  The result is\n"
+	"      assigned to <name>.  If <t> is not supplied, use the old\n"
+	"      value of <name>\n"
+	"setexpr name sub r s [t]\n"
+	"    - Just like gsub(), but replace only the first matching substring"
+#endif
 );

+ 7 - 4
common/cmd_source.c

@@ -36,6 +36,7 @@
 #include <image.h>
 #include <malloc.h>
 #include <asm/byteorder.h>
+#include <asm/io.h>
 #if defined(CONFIG_8xx)
 #include <mpc8xx.h>
 #endif
@@ -44,9 +45,10 @@ int
 source (ulong addr, const char *fit_uname)
 {
 	ulong		len;
-	image_header_t	*hdr;
+	const image_header_t *hdr;
 	ulong		*data;
 	int		verify;
+	void *buf;
 #if defined(CONFIG_FIT)
 	const void*	fit_hdr;
 	int		noffset;
@@ -56,9 +58,10 @@ source (ulong addr, const char *fit_uname)
 
 	verify = getenv_yesno ("verify");
 
-	switch (genimg_get_format ((void *)addr)) {
+	buf = map_sysmem(addr, 0);
+	switch (genimg_get_format(buf)) {
 	case IMAGE_FORMAT_LEGACY:
-		hdr = (image_header_t *)addr;
+		hdr = buf;
 
 		if (!image_check_magic (hdr)) {
 			puts ("Bad magic number\n");
@@ -104,7 +107,7 @@ source (ulong addr, const char *fit_uname)
 			return 1;
 		}
 
-		fit_hdr = (const void *)addr;
+		fit_hdr = buf;
 		if (!fit_check_format (fit_hdr)) {
 			puts ("Bad FIT image format\n");
 			return 1;

+ 123 - 9
common/env_mmc.c

@@ -32,6 +32,11 @@
 #include <search.h>
 #include <errno.h>
 
+#if defined(CONFIG_ENV_SIZE_REDUND) &&  \
+	(CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE)
+#error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE
+#endif
+
 char *env_name_spec = "MMC";
 
 #ifdef ENV_IS_EMBEDDED
@@ -46,9 +51,13 @@ DECLARE_GLOBAL_DATA_PTR;
 #define CONFIG_ENV_OFFSET 0
 #endif
 
-__weak int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr)
+__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
 {
 	*env_addr = CONFIG_ENV_OFFSET;
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	if (copy)
+		*env_addr = CONFIG_ENV_OFFSET_REDUND;
+#endif
 	return 0;
 }
 
@@ -110,6 +119,10 @@ static inline int write_env(struct mmc *mmc, unsigned long size,
 	return (n == blk_cnt) ? 0 : -1;
 }
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+static unsigned char env_flags;
+#endif
+
 int saveenv(void)
 {
 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
@@ -117,16 +130,11 @@ int saveenv(void)
 	char	*res;
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 	u32	offset;
-	int	ret;
+	int	ret, copy = 0;
 
 	if (init_mmc_for_env(mmc))
 		return 1;
 
-	if (mmc_get_env_addr(mmc, &offset)) {
-		ret = 1;
-		goto fini;
-	}
-
 	res = (char *)&env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
@@ -136,7 +144,21 @@ int saveenv(void)
 	}
 
 	env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
-	printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	env_new->flags	= ++env_flags; /* increase the serial */
+
+	if (gd->env_valid == 1)
+		copy = 1;
+#endif
+
+	if (mmc_get_env_addr(mmc, copy, &offset)) {
+		ret = 1;
+		goto fini;
+	}
+
+	printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "",
+	       CONFIG_SYS_MMC_ENV_DEV);
 	if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) {
 		puts("failed\n");
 		ret = 1;
@@ -146,6 +168,10 @@ int saveenv(void)
 	puts("done\n");
 	ret = 0;
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+	gd->env_valid = gd->env_valid == 2 ? 1 : 2;
+#endif
+
 fini:
 	fini_mmc_for_env(mmc);
 	return ret;
@@ -166,6 +192,93 @@ static inline int read_env(struct mmc *mmc, unsigned long size,
 	return (n == blk_cnt) ? 0 : -1;
 }
 
+#ifdef CONFIG_ENV_OFFSET_REDUND
+void env_relocate_spec(void)
+{
+#if !defined(ENV_IS_EMBEDDED)
+	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
+	u32 offset1, offset2;
+	int read1_fail = 0, read2_fail = 0;
+	int crc1_ok = 0, crc2_ok = 0;
+	env_t *ep, *tmp_env1, *tmp_env2;
+	int ret;
+
+	tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE);
+	tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE);
+	if (tmp_env1 == NULL || tmp_env2 == NULL) {
+		puts("Can't allocate buffers for environment\n");
+		ret = 1;
+		goto err;
+	}
+
+	if (init_mmc_for_env(mmc)) {
+		ret = 1;
+		goto err;
+	}
+
+	if (mmc_get_env_addr(mmc, 0, &offset1) ||
+	    mmc_get_env_addr(mmc, 1, &offset2)) {
+		ret = 1;
+		goto fini;
+	}
+
+	read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1);
+	read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2);
+
+	if (read1_fail && read2_fail)
+		puts("*** Error - No Valid Environment Area found\n");
+	else if (read1_fail || read2_fail)
+		puts("*** Warning - some problems detected "
+		     "reading environment; recovered successfully\n");
+
+	crc1_ok = !read1_fail &&
+		(crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
+	crc2_ok = !read2_fail &&
+		(crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
+
+	if (!crc1_ok && !crc2_ok) {
+		ret = 1;
+		goto fini;
+	} else if (crc1_ok && !crc2_ok) {
+		gd->env_valid = 1;
+	} else if (!crc1_ok && crc2_ok) {
+		gd->env_valid = 2;
+	} else {
+		/* both ok - check serial */
+		if (tmp_env1->flags == 255 && tmp_env2->flags == 0)
+			gd->env_valid = 2;
+		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0)
+			gd->env_valid = 1;
+		else if (tmp_env1->flags > tmp_env2->flags)
+			gd->env_valid = 1;
+		else if (tmp_env2->flags > tmp_env1->flags)
+			gd->env_valid = 2;
+		else /* flags are equal - almost impossible */
+			gd->env_valid = 1;
+	}
+
+	free(env_ptr);
+
+	if (gd->env_valid == 1)
+		ep = tmp_env1;
+	else
+		ep = tmp_env2;
+
+	env_flags = ep->flags;
+	env_import((char *)ep, 0);
+	ret = 0;
+
+fini:
+	fini_mmc_for_env(mmc);
+err:
+	if (ret)
+		set_default_env(NULL);
+
+	free(tmp_env1);
+	free(tmp_env2);
+#endif
+}
+#else /* ! CONFIG_ENV_OFFSET_REDUND */
 void env_relocate_spec(void)
 {
 #if !defined(ENV_IS_EMBEDDED)
@@ -179,7 +292,7 @@ void env_relocate_spec(void)
 		goto err;
 	}
 
-	if (mmc_get_env_addr(mmc, &offset)) {
+	if (mmc_get_env_addr(mmc, 0, &offset)) {
 		ret = 1;
 		goto fini;
 	}
@@ -199,3 +312,4 @@ err:
 		set_default_env(NULL);
 #endif
 }
+#endif /* CONFIG_ENV_OFFSET_REDUND */

+ 11 - 0
common/flash.c

@@ -149,6 +149,9 @@ flash_write (char *src, ulong addr, ulong cnt)
 	flash_info_t *info_first = addr2info (addr);
 	flash_info_t *info_last  = addr2info (end );
 	flash_info_t *info;
+	__maybe_unused char *src_orig = src;
+	__maybe_unused char *addr_orig = (char *)addr;
+	__maybe_unused ulong cnt_orig = cnt;
 
 	if (cnt == 0) {
 		return (ERR_OK);
@@ -185,6 +188,14 @@ flash_write (char *src, ulong addr, ulong cnt)
 		addr += len;
 		src  += len;
 	}
+
+#if defined(CONFIG_FLASH_VERIFY)
+	if (memcmp(src_orig, addr_orig, cnt_orig)) {
+		printf("\nVerify failed!\n");
+		return ERR_PROG_ERROR;
+	}
+#endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */
+
 	return (ERR_OK);
 #endif /* CONFIG_SPD823TS */
 }

+ 0 - 8
common/main.c

@@ -45,10 +45,6 @@
 #include <fdtdec.h>
 #endif
 
-#ifdef CONFIG_OF_LIBFDT
-#include <fdt_support.h>
-#endif /* CONFIG_OF_LIBFDT */
-
 #include <post.h>
 #include <linux/ctype.h>
 #include <menu.h>
@@ -376,10 +372,6 @@ void main_loop (void)
 
 	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
 
-#if defined CONFIG_OF_CONTROL
-       set_working_fdt_addr((void *)gd->fdt_blob);
-#endif /* CONFIG_OF_CONTROL */
-
 #ifdef CONFIG_BOOTCOUNT_LIMIT
 	bootcount = bootcount_load();
 	bootcount++;

+ 0 - 7
common/spl/spl.c

@@ -48,13 +48,6 @@ struct spl_image_info spl_image;
 /* Define board data structure */
 static bd_t bdata __attribute__ ((section(".data")));
 
-inline void hang(void)
-{
-	puts("### ERROR ### Please RESET the board ###\n");
-	for (;;)
-		;
-}
-
 /*
  * Default function to determine if u-boot or the OS should
  * be started. This implementation always returns 1.

+ 1 - 0
common/usb_storage.c

@@ -1430,6 +1430,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
 			*capacity, *blksz);
 	dev_desc->lba = *capacity;
 	dev_desc->blksz = *blksz;
+	dev_desc->log2blksz = LOG2(dev_desc->blksz);
 	dev_desc->type = perq;
 	USB_STOR_PRINTF(" address %d\n", dev_desc->target);
 	USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type);

+ 6 - 2
config.mk

@@ -222,6 +222,10 @@ ifneq ($(CONFIG_SPL_PAD_TO),)
 CPPFLAGS += -DCONFIG_SPL_PAD_TO=$(CONFIG_SPL_PAD_TO)
 endif
 
+ifneq ($(CONFIG_UBOOT_PAD_TO),)
+CPPFLAGS += -DCONFIG_UBOOT_PAD_TO=$(CONFIG_UBOOT_PAD_TO)
+endif
+
 ifeq ($(CONFIG_SPL_BUILD),y)
 CPPFLAGS += -DCONFIG_SPL_BUILD
 endif
@@ -229,8 +233,8 @@ endif
 # Does this architecture support generic board init?
 ifeq ($(__HAVE_ARCH_GENERIC_BOARD),)
 ifneq ($(CONFIG_SYS_GENERIC_BOARD),)
-$(error Your architecture does not support generic board. Please undefined \
-CONFIG_SYS_GENERIC_BOARD in your board config file)
+CHECK_GENERIC_BOARD = $(error Your architecture does not support generic board. \
+Please undefined CONFIG_SYS_GENERIC_BOARD in your board config file)
 endif
 endif
 

+ 16 - 3
disk/part_dos.c

@@ -74,13 +74,26 @@ static void print_one_part(dos_partition_t *p, int ext_part_sector,
 
 static int test_block_type(unsigned char *buffer)
 {
+	int slot;
+	struct dos_partition *p;
+
 	if((buffer[DOS_PART_MAGIC_OFFSET + 0] != 0x55) ||
 	    (buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) ) {
 		return (-1);
 	} /* no DOS Signature at all */
-	if (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],"FAT",3)==0 ||
-	    strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],"FAT32",5)==0) {
-		return DOS_PBR; /* is PBR */
+	p = (struct dos_partition *)&buffer[DOS_PART_TBL_OFFSET];
+	for (slot = 0; slot < 3; slot++) {
+		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
+			if (!slot &&
+			    (strncmp((char *)&buffer[DOS_PBR_FSTYPE_OFFSET],
+				     "FAT", 3) == 0 ||
+			     strncmp((char *)&buffer[DOS_PBR32_FSTYPE_OFFSET],
+				     "FAT32", 5) == 0)) {
+				return DOS_PBR; /* is PBR */
+			} else {
+				return -1;
+			}
+		}
 	}
 	return DOS_MBR;	    /* Is MBR */
 }

+ 22 - 16
disk/part_efi.c

@@ -115,7 +115,7 @@ static inline int is_bootable(gpt_entry *p)
 
 void print_part_efi(block_dev_desc_t * dev_desc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
 	gpt_entry *gpt_pte = NULL;
 	int i = 0;
 	char uuid[37];
@@ -162,7 +162,7 @@ void print_part_efi(block_dev_desc_t * dev_desc)
 int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
 				disk_partition_t * info)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(gpt_header, gpt_head, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(gpt_header, gpt_head, 1, dev_desc->blksz);
 	gpt_entry *gpt_pte = NULL;
 
 	/* "part" argument must be at least 1 */
@@ -190,7 +190,7 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
 	/* The ending LBA is inclusive, to calculate size, add 1 to it */
 	info->size = ((u64)le64_to_cpu(gpt_pte[part - 1].ending_lba) + 1)
 		     - info->start;
-	info->blksz = GPT_BLOCK_SIZE;
+	info->blksz = dev_desc->blksz;
 
 	sprintf((char *)info->name, "%s",
 			print_efiname(&gpt_pte[part - 1]));
@@ -210,7 +210,7 @@ int get_partition_info_efi(block_dev_desc_t * dev_desc, int part,
 
 int test_part_efi(block_dev_desc_t * dev_desc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(legacy_mbr, legacymbr, 1);
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(legacy_mbr, legacymbr, 1, dev_desc->blksz);
 
 	/* Read legacy MBR from block 0 and validate it */
 	if ((dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)legacymbr) != 1)
@@ -311,9 +311,8 @@ static int string_uuid(char *uuid, u8 *dst)
 int write_gpt_table(block_dev_desc_t *dev_desc,
 		gpt_header *gpt_h, gpt_entry *gpt_e)
 {
-	const int pte_blk_num = (gpt_h->num_partition_entries
-		* sizeof(gpt_entry)) / dev_desc->blksz;
-
+	const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
+					   * sizeof(gpt_entry)), dev_desc);
 	u32 calc_crc32;
 	u64 val;
 
@@ -336,8 +335,8 @@ int write_gpt_table(block_dev_desc_t *dev_desc,
 	if (dev_desc->block_write(dev_desc->dev, 1, 1, gpt_h) != 1)
 		goto err;
 
-	if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_num, gpt_e)
-	    != pte_blk_num)
+	if (dev_desc->block_write(dev_desc->dev, 2, pte_blk_cnt, gpt_e)
+	    != pte_blk_cnt)
 		goto err;
 
 	/* recalculate the values for the Second GPT Header */
@@ -352,7 +351,7 @@ int write_gpt_table(block_dev_desc_t *dev_desc,
 
 	if (dev_desc->block_write(dev_desc->dev,
 				  le32_to_cpu(gpt_h->last_usable_lba + 1),
-				  pte_blk_num, gpt_e) != pte_blk_num)
+				  pte_blk_cnt, gpt_e) != pte_blk_cnt)
 		goto err;
 
 	if (dev_desc->block_write(dev_desc->dev,
@@ -462,13 +461,18 @@ int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
 {
 	int ret;
 
-	gpt_header *gpt_h = calloc(1, sizeof(gpt_header));
+	gpt_header *gpt_h = calloc(1, PAD_TO_BLOCKSIZE(sizeof(gpt_header),
+						       dev_desc));
+	gpt_entry *gpt_e;
+
 	if (gpt_h == NULL) {
 		printf("%s: calloc failed!\n", __func__);
 		return -1;
 	}
 
-	gpt_entry *gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry));
+	gpt_e = calloc(1, PAD_TO_BLOCKSIZE(GPT_ENTRY_NUMBERS
+					       * sizeof(gpt_entry),
+					       dev_desc));
 	if (gpt_e == NULL) {
 		printf("%s: calloc failed!\n", __func__);
 		free(gpt_h);
@@ -652,7 +656,7 @@ static int is_gpt_valid(block_dev_desc_t * dev_desc, unsigned long long lba,
 static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
 					 gpt_header * pgpt_head)
 {
-	size_t count = 0;
+	size_t count = 0, blk_cnt;
 	gpt_entry *pte = NULL;
 
 	if (!dev_desc || !pgpt_head) {
@@ -669,7 +673,8 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
 
 	/* Allocate memory for PTE, remember to FREE */
 	if (count != 0) {
-		pte = memalign(ARCH_DMA_MINALIGN, count);
+		pte = memalign(ARCH_DMA_MINALIGN,
+			       PAD_TO_BLOCKSIZE(count, dev_desc));
 	}
 
 	if (count == 0 || pte == NULL) {
@@ -680,10 +685,11 @@ static gpt_entry *alloc_read_gpt_entries(block_dev_desc_t * dev_desc,
 	}
 
 	/* Read GPT Entries from device */
+	blk_cnt = BLOCK_CNT(count, dev_desc);
 	if (dev_desc->block_read (dev_desc->dev,
 		le64_to_cpu(pgpt_head->partition_entry_lba),
-		(lbaint_t) (count / GPT_BLOCK_SIZE), pte)
-		!= (count / GPT_BLOCK_SIZE)) {
+		(lbaint_t) (blk_cnt), pte)
+		!= blk_cnt) {
 
 		printf("*** ERROR: Can't read GPT Entries ***\n");
 		free(pte);

+ 3 - 0
disk/part_iso.c

@@ -73,6 +73,9 @@ int get_partition_info_iso_verb(block_dev_desc_t * dev_desc, int part_num, disk_
 	iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
 	iso_init_def_entry_t *pide;
 
+	if (dev_desc->blksz != CD_SECTSIZE)
+		return -1;
+
 	/* the first sector (sector 0x10) must be a primary volume desc */
 	blkaddr=PVD_OFFSET;
 	if (dev_desc->block_read (dev_desc->dev, PVD_OFFSET, 1, (ulong *) tmpbuf) != 1)

+ 5 - 1
doc/README.fdt-control

@@ -142,7 +142,11 @@ join the two:
 
 and then flash image.bin onto your board.
 
-You cannot use both of these options at the same time.
+If CONFIG_OF_HOSTFILE is defined, then it will be read from a file on
+startup. This is only useful for sandbox. Use the -d flag to U-Boot to
+specify the file to read.
+
+You cannot use more than one of these options at the same time.
 
 If you wish to put the fdt at a different address in memory, you can
 define the "fdtcontroladdr" environment variable. This is the hex

+ 199 - 0
doc/README.p1010rdb

@@ -0,0 +1,199 @@
+Overview
+=========
+The P1010RDB is a Freescale reference design board that hosts the P1010 SoC.
+
+The P1010 is a cost-effective, low-power, highly integrated host processor
+based on a Power Architecture e500v2 core (maximum core frequency 800/1000 MHz),
+that addresses the requirements of several routing, gateways, storage, consumer,
+and industrial applications. Applications of interest include the main CPUs and
+I/O processors in network attached storage (NAS), the voice over IP (VoIP)
+router/gateway, and wireless LAN (WLAN) and industrial controllers.
+
+The P1010RDB board features are as follows:
+Memory subsystem:
+	- 1Gbyte unbuffered DDR3 SDRAM discrete devices (32-bit bus)
+	- 32 Mbyte NOR flash single-chip memory
+	- 32 Mbyte NAND flash memory
+	- 256 Kbit M24256 I2C EEPROM
+	- 16 Mbyte SPI memory
+	- I2C Board EEPROM 128x8 bit memory
+	- SD/MMC connector to interface with the SD memory card
+Interfaces:
+	- PCIe:
+		- Lane0: x1 mini-PCIe slot
+		- Lane1: x1 PCIe standard slot
+	- SATA:
+		- 1 internal SATA connector to 2.5" 160G SATA2 HDD
+		- 1 eSATA connector to rear panel
+	- 10/100/1000 BaseT Ethernet ports:
+		- eTSEC1, RGMII: one 10/100/1000 port using Vitesse VSC8641XKO
+		- eTSEC2, SGMII: one 10/100/1000 port using Vitesse VSC8221
+		- eTSEC3, SGMII: one 10/100/1000 port using Vitesse VSC8221
+	- USB 2.0 port:
+		- x1 USB2.0 port: via an ULPI PHY to micro-AB connector
+		- x1 USB2.0 poort via an internal PHY to micro-AB connector
+	- FlexCAN ports:
+		- x2 DB-9 female connectors for FlexCAN bus(revision 2.0B)
+		   interface;
+	- DUART interface:
+		- DUART interface: supports two UARTs up to 115200 bps for
+		  console display
+		- J45 connectors are used for these 2 UART ports.
+	- TDM
+		- 2 FXS ports connected via an external SLIC to the TDM
+		   interface. SLIC is controllled via SPI.
+		- 1 FXO port connected via a relay to FXS for switchover to
+		   POTS
+Board connectors:
+	- Mini-ITX power supply connector
+	- JTAG/COP for debugging
+IEEE Std. 1588 signals for test and measurement
+Real-time clock on I2C bus
+POR
+	- support critical POR setting changed via switch on board
+PCB
+	- 6-layer routing (4-layer signals, 2-layer power and ground)
+
+
+Serial Port Configuration on P1010RDB
+=====================================
+Configure the serial port of the attached computer with the following values:
+	-Data rate: 115200 bps
+	-Number of data bits: 8
+	-Parity: None
+	-Number of Stop bits: 1
+	-Flow Control: Hardware/None
+
+
+Settings of DIP-switch
+======================
+  SW4[1:4]= 1111 and SW6[4]=0 for boot from 16bit NOR flash
+  SW4[1:4]= 1000 and SW6[4]=1 for boot from 8bit NAND flash
+  SW4[1:4]= 0110 and SW6[4]=0 for boot from SPI flash
+Note: 1 stands for 'on', 0 stands for 'off'
+
+
+Setting of hwconfig
+===================
+If FlexCAN or TDM is needed, please set "fsl_p1010mux:tdm_can=can" or
+"fsl_p1010mux:tdm_can=tdm" explicitly in u-booot prompt as below for example:
+setenv hwconfig "fsl_p1010mux:tdm_can=tdm;usb1:dr_mode=host,phy_type=utmi"
+By default, don't set fsl_p1010mux:tdm_can, in this case, spi chip selection
+is set to spi-flash instead of to SLIC/TDM/DAC and tdm_can_sel is set to TDM
+instead of to CAN/UART1.
+
+
+Build and burn u-boot to NOR flash
+==================================
+1. Build u-boot.bin image
+	export ARCH=powerpc
+	export CROSS_COMPILE=/your_path/powerpc-linux-gnu-
+	make P1010RDB_NOR
+
+2. Burn u-boot.bin into NOR flash
+	=> tftp $loadaddr $uboot
+	=> protect off eff80000 +$filesize
+	=> erase eff80000 +$filesize
+	=> cp.b $loadaddr eff80000 $filesize
+
+3. Check SW4[1:4]= 1111 and SW6[4]=0, then power on.
+
+
+Alternate NOR bank
+============================
+1. Burn u-boot.bin into alternate NOR bank
+	=> tftp $loadaddr $uboot
+	=> protect off eef80000 +$filesize
+	=> erase eef80000 +$filesize
+	=> cp.b $loadaddr eef80000 $filesize
+
+2. Switch to alternate NOR bank
+	=> mw.b ffb00009 1
+	=> reset
+	or set SW1[8]= ON
+
+SW1[8]= OFF: Upper bank used for booting start
+SW1[8]= ON:  Lower bank used for booting start
+CPLD NOR bank selection register address 0xFFB00009 Bit[0]:
+0 - boot from upper 4 sectors
+1 - boot from lower 4 sectors
+
+
+Build and burn u-boot to NAND flash
+===================================
+1. Build u-boot.bin image
+	export ARCH=powerpc
+	export CROSS_COMPILE=/your_path/powerpc-linux-gnu-
+	make P1010RDB_NAND
+
+2. Burn u-boot-nand.bin into NAND flash
+	=> tftp $loadaddr $uboot-nand
+	=> nand erase 0 $filesize
+	=> nand write $loadaddr 0 $filesize
+
+3. Check SW4[1:4]= 1000 and SW6[4]=1, then power on.
+
+
+
+Build and burn u-boot to SPI flash
+==================================
+1. Build u-boot-spi.bin image
+	make P1010RDB_SPIFLASH_config; make
+	Boot up kernel with rootfs.ext2.gz.uboot.p1010rdb
+	Download u-boot.bin to linux and you can find some config files
+	under /usr/share such as config_xx.dat. Do below command:
+	boot_format config_ddr3_1gb_p1010rdb_800M.dat u-boot.bin -spi \
+			u-boot-spi.bin
+	to generate u-boot-spi.bin.
+
+2. Burn u-boot-spi.bin into SPI flash
+	=> tftp $loadaddr $uboot-spi
+	=> sf erase 0 100000
+	=> sf write $loadaddr 0 $filesize
+
+3. Check SW4[1:4]= 0110 and SW6[4]=0, then power on.
+
+
+
+CPLD POR setting registers
+==========================
+1. Set POR switch selection register (addr 0xFFB00011) to 0.
+2. Write CPLD POR registers (BCSR0~BCSR3, addr 0xFFB00014~0xFFB00017) with
+   proper values.
+   If change boot ROM location to NOR or NAND flash, need write the IFC_CS0
+   switch command by I2C.
+3. Send reset command.
+   After reset, the new POR setting will be implemented.
+
+Two examples are given in below:
+Switch from NOR to NAND boot with default frequency:
+	=> i2c dev 0
+	=> i2c mw 18 1 f9
+	=> i2c mw 18 3 f0
+	=> mw.b ffb00011 0
+	=> mw.b ffb00017 1
+	=> reset
+Switch from NAND to NOR boot with Core/CCB/DDR (800/400/667 MHz):
+	=> i2c dev 0
+	=> i2c mw 18 1 f1
+	=> i2c mw 18 3 f0
+	=> mw.b ffb00011 0
+	=> mw.b ffb00014 2
+	=> mw.b ffb00015 5
+	=> mw.b ffb00016 3
+	=> mw.b ffb00017 f
+	=> reset
+
+
+
+Boot Linux from network using TFTP on P1010RDB
+==============================================
+Place uImage, p1010rdb.dtb and rootfs files in the TFTP disk area.
+	=> tftp 1000000 uImage
+	=> tftp 2000000 p1010rdb.dtb
+	=> tftp 3000000 rootfs.ext2.gz.uboot.p1010rdb
+	=> bootm 1000000 3000000 2000000
+
+
+Please contact your local field applications engineer or sales representative
+to obtain related documents, such as P1010-RDB User Guide for details.

+ 102 - 0
doc/README.ramboot-ppc85xx

@@ -0,0 +1,102 @@
+			RAMBOOT for MPC85xx Platforms
+			==============================
+
+RAMBOOT literally means boot from DDR. But since DDR is volatile memory some
+pre-mechanism is required to load the DDR with the bootloader binary.
+- In case of SD and SPI boot this is done by BootROM code inside the chip
+  itself.
+- In case of NAND boot FCM supports loading initial 4K code from NAND flash
+  which can initialize the DDR and get the complete bootloader copied to DDR.
+
+In addition to the above there could be some more methods to initialize the DDR
+and load it manually.
+Two of them are described below.There is also an explanation as to where these
+methods could be handy.
+1. Load the RAM based bootloader onto DDR via JTAG/BDI interface. And then
+   execute the bootloader from DDR.
+   This may be handy in the following cases:
+     - In very early stage of platform bringup where other boot options are not
+       functional because of various reasons.
+     - In case the support to program the flashes on the board is not available.
+
+2. Load the RAM based bootloader onto DDR using already existing bootloader on
+   the board.And then execute the bootloader from DDR.
+   Some usecases where this may be used:
+      - While developing some new feature of u-boot, for example USB driver or
+        SPI driver.
+        Suppose the board already has a working bootloader on it. And you would
+        prefer to keep it intact, at the same time want to test your bootloader.
+        In this case you can get your test bootloader binary into DDR via tftp
+        for example. Then execute the test bootloader.
+     - Suppose a platform already has a propreitery bootloader which does not
+       support for example AMP boot. In this case also RAM boot loader can be
+       utilized.
+
+   So basically when the original bootloader is required to be kept intact
+   RAM based bootloader can offer an updated bootloader on the system.
+
+Both the above Bootloaders are slight variants of SDcard or SPI Flash
+bootloader or for that matter even NAND bootloader.
+All of them define CONFIG_SYS_RAMBOOT.
+The main difference among all of them is the way the pre-environment is getting
+configured and who is doing that.
+- In case of SD card and SPI flash bootloader this is done by On Chip BootROM inside the Si itself.
+- In case of NAND boot SPL/TPL code does it with some support from Si itself.
+- In case of the pure RAM based bootloaders we have to do it by JTAG manually or already existing bootloader.
+
+How to use them:
+1. Using JTAG
+   Boot up in core hold off mode or stop the core after reset using JTAG
+   interface.
+   Preconfigure DDR/L2SRAM through JTAG interface.
+	- setup DDR controller registers.
+	- setup DDR LAWs
+	- setup DDR TLB
+   Load the RAM based boot loader to the proper location in DDR/L2SRAM.
+   set up IAR (Instruction counter properly)
+   Enable the core to execute.
+
+2. Using already existing bootloader.
+   get the rambased boot loader binary into DDR/L2SRAM via tftp.
+   execute the RAM based bootloader.
+      => tftp 11000000 u-boot-ram.bin
+      => go 1107f000
+
+Please note that L2SRAM can also be used instead of DDR if the SOC has
+sufficient size of L2SRAM.
+
+Necessary Code changes Required:
+=====================================
+Please note that below mentioned changes are for 85xx platforms.
+They have been tested on P1020/P2020/P1010 RDB.
+
+The main difference between the above two methods from technical perspective is
+that in 1st case SOC is just out of reset so it is in default configuration.
+(CCSRBAR is at 0xff700000).
+In the 2nd case bootloader has already re-located CCSRBAR to 0xffe00000
+
+1. File name-> boards.cfg
+   There can be added specific Make options for RAMBoot. We can keep different
+   options for the two cases mentioned above.
+   for example
+   P1020RDB_JTAG_RAMBOOT and P1020RDB_GO_RAMBOOT.
+
+2. platform config file
+   for example include/configs/P1_P2_RDB.h
+
+   #ifdef CONFIG_RAMBOOT
+   #define CONFIG_SDCARD
+   #endif
+
+   This will finally use the CONFIG_SYS_RAMBOOT.
+
+3. File name-> arch/powerpc/include/asm/config_mpc85xx.h
+   In the section of the particular SOC, for example P1020,
+
+   #if defined(CONFIG_GO)
+   #define CONFIG_SYS_CCSRBAR_DEFAULT	0xffe00000
+   #else
+   #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
+   #endif
+
+For JTAG  RAMBOOT this is not required because CCSRBAR is at ff700000.

+ 3 - 0
doc/README.watchdog

@@ -27,3 +27,6 @@ CONFIG_IMX_WATCHDOG
 	Available for i.mx31/35/5x/6x to service the watchdog. This is not
 	automatically set because some boards (vision2) still need to define
 	their own hw_watchdog_reset routine.
+
+CONFIG_XILINX_TB_WATCHDOG
+	Available for Xilinx Axi platforms to service timebase watchdog timer.

+ 7 - 12
doc/feature-removal-schedule.txt

@@ -7,20 +7,15 @@ file.
 
 ---------------------------
 
-What:	Remove CONFIG_CMD_MEMTEST from default list
-When:	Release v2013.07
+What:	Remove unused CONFIG_SYS_MEMTEST_START/END
+When:	Release v2013.10
 
-Why:	The "mtest" command is of little practical use (if any), and
-	experience has shown that a large number of board configu-
-	rations define useless or even dangerous start and end
-	addresses.  If not even the board maintainers are able to
-	figure out which memory range can be reliably tested, how can
-	we expect such from the end users?  As this problem comes up
-	repeatedly, we rather do not enable this command by default,
-	so only people who know what they are doing will be confronted
-	with it.
+Why:	As the 'mtest' command is no longer default, a number of platforms
+	have not opted to turn the command back on and thus provide unused
+	defines (which are likely to be propogated to new platforms from
+	copy/paste).  Remove these defines when unused.
 
-Who:	Wolfgang Denk <wd@denx.de>
+Who:	Tom Rini <trini@ti.com>
 
 ---------------------------
 

+ 2 - 1
doc/git-mailrc

@@ -34,6 +34,7 @@ alias sjg            Simon Glass <sjg@chromium.org>
 alias smcnutt        Scott McNutt <smcnutt@psyent.com>
 alias sonic          Sonic Zhang <sonic.adi@gmail.com>
 alias stroese        Stefan Roese <sr@denx.de>
+alias trini          Tom Rini <trini@ti.com>
 alias vapier         Mike Frysinger <vapier@gentoo.org>
 alias wd             Wolfgang Denk <wd@denx.de>
 
@@ -54,7 +55,7 @@ alias s5pc           samsung
 alias samsung        uboot, prom
 alias tegra          uboot, sjg, Tom Warren <twarren@nvidia.com>, Stephen Warren <swarren@nvidia.com>
 alias tegra2         tegra
-alias ti             uboot, Tom Rini <trini@ti.com>
+alias ti             uboot, trini
 
 alias avr32          uboot, abiessmann
 

+ 1 - 0
drivers/block/ata_piix.c

@@ -406,6 +406,7 @@ void sata_identify(int num, int dev)
 	/* assuming HD */
 	sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
 	sata_dev_desc[devno].blksz = ATA_BLOCKSIZE;
+	sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz);
 	sata_dev_desc[devno].lun = 0;	/* just to fill something in... */
 }
 

+ 2 - 0
drivers/block/pata_bfin.c

@@ -897,6 +897,8 @@ static void bfin_ata_identify(struct ata_port *ap, int dev)
 	/* assuming HD */
 	sata_dev_desc[ap->port_no].type = DEV_TYPE_HARDDISK;
 	sata_dev_desc[ap->port_no].blksz = ATA_SECT_SIZE;
+	sata_dev_desc[ap->port_no].log2blksz =
+		LOG2(sata_dev_desc[ap->port_no].blksz);
 	sata_dev_desc[ap->port_no].lun = 0;	/* just to fill something in... */
 
 	printf("PATA device#%d %s is found on ata port#%d.\n",

+ 1 - 0
drivers/block/systemace.c

@@ -127,6 +127,7 @@ block_dev_desc_t *systemace_get_dev(int dev)
 		systemace_dev.part_type = PART_TYPE_UNKNOWN;
 		systemace_dev.type = DEV_TYPE_HARDDISK;
 		systemace_dev.blksz = 512;
+		systemace_dev.log2blksz = LOG2(systemace_dev.blksz);
 		systemace_dev.removable = 1;
 		systemace_dev.block_read = systemace_read;
 

+ 14 - 12
drivers/mmc/mmc.c

@@ -601,7 +601,7 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
 
 	data.dest = (char *)ext_csd;
 	data.blocks = 1;
-	data.blocksize = 512;
+	data.blocksize = MMC_MAX_BLOCK_LEN;
 	data.flags = MMC_DATA_READ;
 
 	err = mmc_send_cmd(mmc, &cmd, &data);
@@ -634,7 +634,7 @@ static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 
 static int mmc_change_freq(struct mmc *mmc)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
 	char cardtype;
 	int err;
 
@@ -899,8 +899,8 @@ static int mmc_startup(struct mmc *mmc)
 	uint mult, freq;
 	u64 cmult, csize, capacity;
 	struct mmc_cmd cmd;
-	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, 512);
-	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, 512);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
+	ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN);
 	int timeout = 1000;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
@@ -1016,11 +1016,11 @@ static int mmc_startup(struct mmc *mmc)
 	mmc->capacity = (csize + 1) << (cmult + 2);
 	mmc->capacity *= mmc->read_bl_len;
 
-	if (mmc->read_bl_len > 512)
-		mmc->read_bl_len = 512;
+	if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN)
+		mmc->read_bl_len = MMC_MAX_BLOCK_LEN;
 
-	if (mmc->write_bl_len > 512)
-		mmc->write_bl_len = 512;
+	if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN)
+		mmc->write_bl_len = MMC_MAX_BLOCK_LEN;
 
 	/* Select the card, and put it into Transfer Mode */
 	if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
@@ -1051,7 +1051,7 @@ static int mmc_startup(struct mmc *mmc)
 					| ext_csd[EXT_CSD_SEC_CNT + 1] << 8
 					| ext_csd[EXT_CSD_SEC_CNT + 2] << 16
 					| ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
-			capacity *= 512;
+			capacity *= MMC_MAX_BLOCK_LEN;
 			if ((capacity >> 20) > 2 * 1024)
 				mmc->capacity = capacity;
 		}
@@ -1079,10 +1079,11 @@ static int mmc_startup(struct mmc *mmc)
 		 * group size from ext_csd directly, or calculate
 		 * the group size from the csd value.
 		 */
-		if (ext_csd[EXT_CSD_ERASE_GROUP_DEF])
+		if (ext_csd[EXT_CSD_ERASE_GROUP_DEF]) {
 			mmc->erase_grp_size =
-			      ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 512 * 1024;
-		else {
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
+					MMC_MAX_BLOCK_LEN * 1024;
+		} else {
 			int erase_gsz, erase_gmul;
 			erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
 			erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
@@ -1202,6 +1203,7 @@ static int mmc_startup(struct mmc *mmc)
 	mmc->block_dev.lun = 0;
 	mmc->block_dev.type = 0;
 	mmc->block_dev.blksz = mmc->read_bl_len;
+	mmc->block_dev.log2blksz = LOG2(mmc->block_dev.blksz);
 	mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
 	sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
 		mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),

+ 9 - 8
drivers/mmc/spl_mmc.c

@@ -34,8 +34,9 @@ DECLARE_GLOBAL_DATA_PTR;
 
 static void mmc_load_image_raw(struct mmc *mmc)
 {
-	u32 image_size_sectors, err;
-	const struct image_header *header;
+	unsigned long err;
+	u32 image_size_sectors;
+	struct image_header *header;
 
 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
 						sizeof(struct image_header));
@@ -43,9 +44,9 @@ static void mmc_load_image_raw(struct mmc *mmc)
 	/* read image header to find the image size & load address */
 	err = mmc->block_dev.block_read(0,
 			CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, 1,
-			(void *)header);
+			header);
 
-	if (err <= 0)
+	if (err == 0)
 		goto end;
 
 	spl_parse_image_header(header);
@@ -60,8 +61,8 @@ static void mmc_load_image_raw(struct mmc *mmc)
 			image_size_sectors, (void *)spl_image.load_addr);
 
 end:
-	if (err <= 0) {
-		printf("spl: mmc blk read err - %d\n", err);
+	if (err == 0) {
+		printf("spl: mmc blk read err - %lu\n", err);
 		hang();
 	}
 }
@@ -69,7 +70,7 @@ end:
 #ifdef CONFIG_SPL_FAT_SUPPORT
 static void mmc_load_image_fat(struct mmc *mmc)
 {
-	s32 err;
+	int err;
 	struct image_header *header;
 
 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
@@ -83,7 +84,7 @@ static void mmc_load_image_fat(struct mmc *mmc)
 	}
 
 	err = file_fat_read(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME,
-				(u8 *)header, sizeof(struct image_header));
+				header, sizeof(struct image_header));
 	if (err <= 0)
 		goto end;
 

+ 2 - 0
drivers/mtd/nand/Makefile

@@ -34,6 +34,7 @@ NORMAL_DRIVERS=y
 endif
 
 COBJS-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
+COBJS-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
 COBJS-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 COBJS-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 COBJS-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
@@ -77,6 +78,7 @@ COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o
 COBJS-$(CONFIG_TEGRA_NAND) += tegra_nand.o
 COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
 COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
+COBJS-$(CONFIG_NAND_DOCG4) += docg4.o
 
 else  # minimal SPL drivers
 

+ 1028 - 0
drivers/mtd/nand/docg4.c

@@ -0,0 +1,1028 @@
+/*
+ * drivers/mtd/nand/docg4.c
+ *
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ * mtd nand driver for M-Systems DiskOnChip G4
+ *
+ * Tested on the Palm Treo 680.  The G4 is also present on Toshiba Portege, Asus
+ * P526, some HTC smartphones (Wizard, Prophet, ...), O2 XDA Zinc, maybe others.
+ * Should work on these as well.  Let me know!
+ *
+ * TODO:
+ *
+ *  Mechanism for management of password-protected areas
+ *
+ *  Hamming ecc when reading oob only
+ *
+ *  According to the M-Sys documentation, this device is also available in a
+ *  "dual-die" configuration having a 256MB capacity, but no mechanism for
+ *  detecting this variant is documented.  Currently this driver assumes 128MB
+ *  capacity.
+ *
+ *  Support for multiple cascaded devices ("floors").  Not sure which gadgets
+ *  contain multiple G4s in a cascaded configuration, if any.
+ *
+ */
+
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/errno.h>
+#include <malloc.h>
+#include <nand.h>
+#include <linux/bch.h>
+#include <linux/bitrev.h>
+#include <linux/mtd/docg4.h>
+
+/*
+ * The device has a nop register which M-Sys claims is for the purpose of
+ * inserting precise delays.  But beware; at least some operations fail if the
+ * nop writes are replaced with a generic delay!
+ */
+static inline void write_nop(void __iomem *docptr)
+{
+	writew(0, docptr + DOC_NOP);
+}
+
+
+static int poll_status(void __iomem *docptr)
+{
+	/*
+	 * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
+	 * register.  Operations known to take a long time (e.g., block erase)
+	 * should sleep for a while before calling this.
+	 */
+
+	uint8_t flash_status;
+
+	/* hardware quirk requires reading twice initially */
+	flash_status = readb(docptr + DOC_FLASHCONTROL);
+
+	do {
+		flash_status = readb(docptr + DOC_FLASHCONTROL);
+	} while (!(flash_status & DOC_CTRL_FLASHREADY));
+
+	return 0;
+}
+
+static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
+{
+	/* write the four address bytes packed in docg4_addr to the device */
+
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+}
+
+/*
+ * This is a module parameter in the linux kernel version of this driver.  It is
+ * hard-coded to 'off' for u-boot.  This driver uses oob to mark bad blocks.
+ * This can be problematic when dealing with data not intended for the mtd/nand
+ * subsystem.  For example, on boards that boot from the docg4 and use the IPL
+ * to load an spl + u-boot image, the blocks containing the image will be
+ * reported as "bad" because the oob of the first page of each block contains a
+ * magic number that the IPL looks for, which causes the badblock scan to
+ * erroneously add them to the bad block table.  To erase such a block, use
+ * u-boot's 'nand scrub'.  scrub is safe for the docg4.  The device does have a
+ * factory bad block table, but it is read-only, and is used in conjunction with
+ * oob bad block markers that are written by mtd/nand when a block is deemed to
+ * be bad.  To read data from "bad" blocks, use 'read.raw'.  Unfortunately,
+ * read.raw does not use ecc, which would still work fine on such misidentified
+ * bad blocks.  TODO: u-boot nand utilities need the ability to ignore bad
+ * blocks.
+ */
+static const int ignore_badblocks; /* remains false */
+
+struct docg4_priv {
+	int status;
+	struct {
+		unsigned int command;
+		int column;
+		int page;
+	} last_command;
+	uint8_t oob_buf[16];
+	uint8_t ecc_buf[7];
+	int oob_page;
+	struct bch_control *bch;
+};
+/*
+ * Oob bytes 0 - 6 are available to the user.
+ * Byte 7 is hamming ecc for first 7 bytes.  Bytes 8 - 14 are hw-generated ecc.
+ * Byte 15 (the last) is used by the driver as a "page written" flag.
+ */
+static struct nand_ecclayout docg4_oobinfo = {
+	.eccbytes = 9,
+	.eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15},
+	.oobavail = 7,
+	.oobfree = { {0, 7} }
+};
+
+static void reset(void __iomem *docptr)
+{
+	/* full device reset */
+
+	writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, docptr + DOC_ASICMODE);
+	writew(~(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN),
+	       docptr + DOC_ASICMODECONFIRM);
+	write_nop(docptr);
+
+	writew(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN,
+	       docptr + DOC_ASICMODE);
+	writew(~(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN),
+	       docptr + DOC_ASICMODECONFIRM);
+
+	writew(DOC_ECCCONF1_ECC_ENABLE, docptr + DOC_ECCCONF1);
+
+	poll_status(docptr);
+}
+
+static void docg4_select_chip(struct mtd_info *mtd, int chip)
+{
+	/*
+	 * Select among multiple cascaded chips ("floors").  Multiple floors are
+	 * not yet supported, so the only valid non-negative value is 0.
+	 */
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+
+	if (chip < 0)
+		return;		/* deselected */
+
+	if (chip > 0)
+		printf("multiple floors currently unsupported\n");
+
+	writew(0, docptr + DOC_DEVICESELECT);
+}
+
+static void read_hw_ecc(void __iomem *docptr, uint8_t *ecc_buf)
+{
+	/* read the 7 hw-generated ecc bytes */
+
+	int i;
+	for (i = 0; i < 7; i++) { /* hw quirk; read twice */
+		ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
+		ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
+	}
+}
+
+static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
+{
+	/*
+	 * Called after a page read when hardware reports bitflips.
+	 * Up to four bitflips can be corrected.
+	 */
+
+	struct nand_chip *nand = mtd->priv;
+	struct docg4_priv *doc = nand->priv;
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	int i, numerrs;
+	unsigned int errpos[4];
+	const uint8_t blank_read_hwecc[8] = {
+		0xcf, 0x72, 0xfc, 0x1b, 0xa9, 0xc7, 0xb9, 0 };
+
+	read_hw_ecc(docptr, doc->ecc_buf); /* read 7 hw-generated ecc bytes */
+
+	/* check if read error is due to a blank page */
+	if (!memcmp(doc->ecc_buf, blank_read_hwecc, 7))
+		return 0;	/* yes */
+
+	/* skip additional check of "written flag" if ignore_badblocks */
+	if (!ignore_badblocks) {
+		/*
+		 * If the hw ecc bytes are not those of a blank page, there's
+		 * still a chance that the page is blank, but was read with
+		 * errors.  Check the "written flag" in last oob byte, which
+		 * is set to zero when a page is written.  If more than half
+		 * the bits are set, assume a blank page.  Unfortunately, the
+		 * bit flips(s) are not reported in stats.
+		 */
+
+		if (doc->oob_buf[15]) {
+			int bit, numsetbits = 0;
+			unsigned long written_flag = doc->oob_buf[15];
+
+			for (bit = 0; bit < 8; bit++) {
+				if (written_flag & 0x01)
+					numsetbits++;
+				written_flag >>= 1;
+			}
+			if (numsetbits > 4) { /* assume blank */
+				printf("errors in blank page at offset %08x\n",
+				       page * DOCG4_PAGE_SIZE);
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 * The hardware ecc unit produces oob_ecc ^ calc_ecc.  The kernel's bch
+	 * algorithm is used to decode this.  However the hw operates on page
+	 * data in a bit order that is the reverse of that of the bch alg,
+	 * requiring that the bits be reversed on the result.  Thanks to Ivan
+	 * Djelic for his analysis!
+	 */
+	for (i = 0; i < 7; i++)
+		doc->ecc_buf[i] = bitrev8(doc->ecc_buf[i]);
+
+	numerrs = decode_bch(doc->bch, NULL, DOCG4_USERDATA_LEN, NULL,
+			     doc->ecc_buf, NULL, errpos);
+
+	if (numerrs == -EBADMSG) {
+		printf("uncorrectable errors at offset %08x\n",
+		       page * DOCG4_PAGE_SIZE);
+		return -EBADMSG;
+	}
+
+	BUG_ON(numerrs < 0);	/* -EINVAL, or anything other than -EBADMSG */
+
+	/* undo last step in BCH alg (modulo mirroring not needed) */
+	for (i = 0; i < numerrs; i++)
+		errpos[i] = (errpos[i] & ~7)|(7-(errpos[i] & 7));
+
+	/* fix the errors */
+	for (i = 0; i < numerrs; i++) {
+		/* ignore if error within oob ecc bytes */
+		if (errpos[i] > DOCG4_USERDATA_LEN * 8)
+			continue;
+
+		/* if error within oob area preceeding ecc bytes... */
+		if (errpos[i] > DOCG4_PAGE_SIZE * 8)
+			__change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
+				     (unsigned long *)doc->oob_buf);
+
+		else    /* error in page data */
+			__change_bit(errpos[i], (unsigned long *)buf);
+	}
+
+	printf("%d error(s) corrected at offset %08x\n",
+	       numerrs, page * DOCG4_PAGE_SIZE);
+
+	return numerrs;
+}
+
+static int read_progstatus(struct docg4_priv *doc, void __iomem *docptr)
+{
+	/*
+	 * This apparently checks the status of programming.  Done after an
+	 * erasure, and after page data is written.  On error, the status is
+	 * saved, to be later retrieved by the nand infrastructure code.
+	 */
+
+	/* status is read from the I/O reg */
+	uint16_t status1 = readw(docptr + DOC_IOSPACE_DATA);
+	uint16_t status2 = readw(docptr + DOC_IOSPACE_DATA);
+	uint16_t status3 = readw(docptr + DOCG4_MYSTERY_REG);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s: %02x %02x %02x\n",
+	    __func__, status1, status2, status3);
+
+	if (status1 != DOCG4_PROGSTATUS_GOOD ||
+	    status2 != DOCG4_PROGSTATUS_GOOD_2 ||
+	    status3 != DOCG4_PROGSTATUS_GOOD_2) {
+		doc->status = NAND_STATUS_FAIL;
+		printf("read_progstatus failed: %02x, %02x, %02x\n",
+		       status1, status2, status3);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int pageprog(struct mtd_info *mtd)
+{
+	/*
+	 * Final step in writing a page.  Writes the contents of its
+	 * internal buffer out to the flash array, or some such.
+	 */
+
+	struct nand_chip *nand = mtd->priv;
+	struct docg4_priv *doc = nand->priv;
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	int retval = 0;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s\n", __func__);
+
+	writew(DOCG4_SEQ_PAGEPROG, docptr + DOC_FLASHSEQUENCE);
+	writew(DOC_CMD_PROG_CYCLE2, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/* Just busy-wait; usleep_range() slows things down noticeably. */
+	poll_status(docptr);
+
+	writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
+	writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
+	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	retval = read_progstatus(doc, docptr);
+	writew(0, docptr + DOC_DATAEND);
+	write_nop(docptr);
+	poll_status(docptr);
+	write_nop(docptr);
+
+	return retval;
+}
+
+static void sequence_reset(void __iomem *docptr)
+{
+	/* common starting sequence for all operations */
+
+	writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL);
+	writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
+	writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+	poll_status(docptr);
+	write_nop(docptr);
+}
+
+static void read_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
+{
+	/* first step in reading a page */
+
+	sequence_reset(docptr);
+
+	writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
+	writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+
+	write_addr(docptr, docg4_addr);
+
+	write_nop(docptr);
+	writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	poll_status(docptr);
+}
+
+static void write_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
+{
+	/* first step in writing a page */
+
+	sequence_reset(docptr);
+	writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE);
+	writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_addr(docptr, docg4_addr);
+	write_nop(docptr);
+	write_nop(docptr);
+	poll_status(docptr);
+}
+
+static uint32_t mtd_to_docg4_address(int page, int column)
+{
+	/*
+	 * Convert mtd address to format used by the device, 32 bit packed.
+	 *
+	 * Some notes on G4 addressing... The M-Sys documentation on this device
+	 * claims that pages are 2K in length, and indeed, the format of the
+	 * address used by the device reflects that.  But within each page are
+	 * four 512 byte "sub-pages", each with its own oob data that is
+	 * read/written immediately after the 512 bytes of page data.  This oob
+	 * data contains the ecc bytes for the preceeding 512 bytes.
+	 *
+	 * Rather than tell the mtd nand infrastructure that page size is 2k,
+	 * with four sub-pages each, we engage in a little subterfuge and tell
+	 * the infrastructure code that pages are 512 bytes in size.  This is
+	 * done because during the course of reverse-engineering the device, I
+	 * never observed an instance where an entire 2K "page" was read or
+	 * written as a unit.  Each "sub-page" is always addressed individually,
+	 * its data read/written, and ecc handled before the next "sub-page" is
+	 * addressed.
+	 *
+	 * This requires us to convert addresses passed by the mtd nand
+	 * infrastructure code to those used by the device.
+	 *
+	 * The address that is written to the device consists of four bytes: the
+	 * first two are the 2k page number, and the second is the index into
+	 * the page.  The index is in terms of 16-bit half-words and includes
+	 * the preceeding oob data, so e.g., the index into the second
+	 * "sub-page" is 0x108, and the full device address of the start of mtd
+	 * page 0x201 is 0x00800108.
+	 */
+	int g4_page = page / 4;	                      /* device's 2K page */
+	int g4_index = (page % 4) * 0x108 + column/2; /* offset into page */
+	return (g4_page << 16) | g4_index;	      /* pack */
+}
+
+static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
+			  int page_addr)
+{
+	/* handle standard nand commands */
+
+	struct nand_chip *nand = mtd->priv;
+	struct docg4_priv *doc = nand->priv;
+	uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s %x, page_addr=%x, column=%x\n",
+	    __func__, command, page_addr, column);
+
+	/*
+	 * Save the command and its arguments.  This enables emulation of
+	 * standard flash devices, and also some optimizations.
+	 */
+	doc->last_command.command = command;
+	doc->last_command.column = column;
+	doc->last_command.page = page_addr;
+
+	switch (command) {
+	case NAND_CMD_RESET:
+		reset(CONFIG_SYS_NAND_BASE);
+		break;
+
+	case NAND_CMD_READ0:
+		read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
+		break;
+
+	case NAND_CMD_STATUS:
+		/* next call to read_byte() will expect a status */
+		break;
+
+	case NAND_CMD_SEQIN:
+		write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
+
+		/* hack for deferred write of oob bytes */
+		if (doc->oob_page == page_addr)
+			memcpy(nand->oob_poi, doc->oob_buf, 16);
+		break;
+
+	case NAND_CMD_PAGEPROG:
+		pageprog(mtd);
+		break;
+
+	/* we don't expect these, based on review of nand_base.c */
+	case NAND_CMD_READOOB:
+	case NAND_CMD_READID:
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+		printf("docg4_command: unexpected nand command 0x%x\n",
+		       command);
+		break;
+	}
+}
+
+static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	int i;
+	struct nand_chip *nand = mtd->priv;
+	uint16_t *p = (uint16_t *)buf;
+	len >>= 1;
+
+	for (i = 0; i < len; i++)
+		p[i] = readw(nand->IO_ADDR_R);
+}
+
+static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+			  int page, int sndcmd)
+{
+	struct docg4_priv *doc = nand->priv;
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	uint16_t status;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %x\n", __func__, page);
+
+	/*
+	 * Oob bytes are read as part of a normal page read.  If the previous
+	 * nand command was a read of the page whose oob is now being read, just
+	 * copy the oob bytes that we saved in a local buffer and avoid a
+	 * separate oob read.
+	 */
+	if (doc->last_command.command == NAND_CMD_READ0 &&
+	    doc->last_command.page == page) {
+		memcpy(nand->oob_poi, doc->oob_buf, 16);
+		return 0;
+	}
+
+	/*
+	 * Separate read of oob data only.
+	 */
+	docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
+
+	writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/* the 1st byte from the I/O reg is a status; the rest is oob data */
+	status = readw(docptr + DOC_IOSPACE_DATA);
+	if (status & DOCG4_READ_ERROR) {
+		printf("docg4_read_oob failed: status = 0x%02x\n", status);
+		return -EIO;
+	}
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: status = 0x%x\n", __func__, status);
+
+	docg4_read_buf(mtd, nand->oob_poi, 16);
+
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	writew(0, docptr + DOC_DATAEND);
+	write_nop(docptr);
+
+	return 0;
+}
+
+static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
+			   int page)
+{
+	/*
+	 * Writing oob-only is not really supported, because MLC nand must write
+	 * oob bytes at the same time as page data.  Nonetheless, we save the
+	 * oob buffer contents here, and then write it along with the page data
+	 * if the same page is subsequently written.  This allows user space
+	 * utilities that write the oob data prior to the page data to work
+	 * (e.g., nandwrite).  The disdvantage is that, if the intention was to
+	 * write oob only, the operation is quietly ignored.  Also, oob can get
+	 * corrupted if two concurrent processes are running nandwrite.
+	 */
+
+	/* note that bytes 7..14 are hw generated hamming/ecc and overwritten */
+	struct docg4_priv *doc = nand->priv;
+	doc->oob_page = page;
+	memcpy(doc->oob_buf, nand->oob_poi, 16);
+	return 0;
+}
+
+static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	/* only called when module_param ignore_badblocks is set */
+	return 0;
+}
+
+static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	int i;
+	struct nand_chip *nand = mtd->priv;
+	uint16_t *p = (uint16_t *)buf;
+	len >>= 1;
+
+	for (i = 0; i < len; i++)
+		writew(p[i], nand->IO_ADDR_W);
+}
+
+static void write_page(struct mtd_info *mtd, struct nand_chip *nand,
+		       const uint8_t *buf, int use_ecc)
+{
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	uint8_t ecc_buf[8];
+
+	writew(DOC_ECCCONF0_ECC_ENABLE |
+	       DOC_ECCCONF0_UNKNOWN |
+	       DOCG4_BCH_SIZE,
+	       docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+
+	/* write the page data */
+	docg4_write_buf16(mtd, buf, DOCG4_PAGE_SIZE);
+
+	/* oob bytes 0 through 5 are written to I/O reg */
+	docg4_write_buf16(mtd, nand->oob_poi, 6);
+
+	/* oob byte 6 written to a separate reg */
+	writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7);
+
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/* write hw-generated ecc bytes to oob */
+	if (likely(use_ecc)) {
+		/* oob byte 7 is hamming code */
+		uint8_t hamming = readb(docptr + DOC_HAMMINGPARITY);
+		hamming = readb(docptr + DOC_HAMMINGPARITY); /* 2nd read */
+		writew(hamming, docptr + DOCG4_OOB_6_7);
+		write_nop(docptr);
+
+		/* read the 7 bch bytes from ecc regs */
+		read_hw_ecc(docptr, ecc_buf);
+		ecc_buf[7] = 0;         /* clear the "page written" flag */
+	}
+
+	/* write user-supplied bytes to oob */
+	else {
+		writew(nand->oob_poi[7], docptr + DOCG4_OOB_6_7);
+		write_nop(docptr);
+		memcpy(ecc_buf, &nand->oob_poi[8], 8);
+	}
+
+	docg4_write_buf16(mtd, ecc_buf, 8);
+	write_nop(docptr);
+	write_nop(docptr);
+	writew(0, docptr + DOC_DATAEND);
+	write_nop(docptr);
+}
+
+static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
+				 const uint8_t *buf)
+{
+	return write_page(mtd, nand, buf, 0);
+}
+
+static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
+			     const uint8_t *buf)
+{
+	return write_page(mtd, nand, buf, 1);
+}
+
+static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
+		     uint8_t *buf, int page, int use_ecc)
+{
+	struct docg4_priv *doc = nand->priv;
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	uint16_t status, edc_err, *buf16;
+
+	writew(DOC_ECCCONF0_READ_MODE |
+	       DOC_ECCCONF0_ECC_ENABLE |
+	       DOC_ECCCONF0_UNKNOWN |
+	       DOCG4_BCH_SIZE,
+	       docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/* the 1st byte from the I/O reg is a status; the rest is page data */
+	status = readw(docptr + DOC_IOSPACE_DATA);
+	if (status & DOCG4_READ_ERROR) {
+		printf("docg4_read_page: bad status: 0x%02x\n", status);
+		writew(0, docptr + DOC_DATAEND);
+		return -EIO;
+	}
+
+	docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
+
+	/* first 14 oob bytes read from I/O reg */
+	docg4_read_buf(mtd, nand->oob_poi, 14);
+
+	/* last 2 read from another reg */
+	buf16 = (uint16_t *)(nand->oob_poi + 14);
+	*buf16 = readw(docptr + DOCG4_MYSTERY_REG);
+
+	/*
+	 * Diskonchips read oob immediately after a page read.  Mtd
+	 * infrastructure issues a separate command for reading oob after the
+	 * page is read.  So we save the oob bytes in a local buffer and just
+	 * copy it if the next command reads oob from the same page.
+	 */
+	memcpy(doc->oob_buf, nand->oob_poi, 16);
+
+	write_nop(docptr);
+
+	if (likely(use_ecc)) {
+		/* read the register that tells us if bitflip(s) detected  */
+		edc_err = readw(docptr + DOC_ECCCONF1);
+		edc_err = readw(docptr + DOC_ECCCONF1);
+
+		/* If bitflips are reported, attempt to correct with ecc */
+		if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
+			int bits_corrected = correct_data(mtd, buf, page);
+			if (bits_corrected == -EBADMSG)
+				mtd->ecc_stats.failed++;
+			else
+				mtd->ecc_stats.corrected += bits_corrected;
+		}
+	}
+
+	writew(0, docptr + DOC_DATAEND);
+	return 0;
+}
+
+
+static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
+			       uint8_t *buf, int page)
+{
+	return read_page(mtd, nand, buf, page, 0);
+}
+
+static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+			   uint8_t *buf, int page)
+{
+	return read_page(mtd, nand, buf, page, 1);
+}
+
+static void docg4_erase_block(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct docg4_priv *doc = nand->priv;
+	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
+	uint16_t g4_page;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %04x\n", __func__, page);
+
+	sequence_reset(docptr);
+
+	writew(DOCG4_SEQ_BLOCKERASE, docptr + DOC_FLASHSEQUENCE);
+	writew(DOC_CMD_PROG_BLOCK_ADDR, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+
+	/* only 2 bytes of address are written to specify erase block */
+	g4_page = (uint16_t)(page / 4);  /* to g4's 2k page addressing */
+	writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
+	g4_page >>= 8;
+	writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
+	write_nop(docptr);
+
+	/* start the erasure */
+	writew(DOC_CMD_ERASECYCLE2, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	poll_status(docptr);
+	writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
+	writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
+	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	read_progstatus(doc, docptr);
+
+	writew(0, docptr + DOC_DATAEND);
+	write_nop(docptr);
+	poll_status(docptr);
+	write_nop(docptr);
+}
+
+static int read_factory_bbt(struct mtd_info *mtd)
+{
+	/*
+	 * The device contains a read-only factory bad block table.  Read it and
+	 * update the memory-based bbt accordingly.
+	 */
+
+	struct nand_chip *nand = mtd->priv;
+	uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
+	uint8_t *buf;
+	int i, block, status;
+
+	buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
+	status = docg4_read_page(mtd, nand, buf, DOCG4_FACTORY_BBT_PAGE);
+	if (status)
+		goto exit;
+
+	/*
+	 * If no memory-based bbt was created, exit.  This will happen if module
+	 * parameter ignore_badblocks is set.  Then why even call this function?
+	 * For an unknown reason, block erase always fails if it's the first
+	 * operation after device power-up.  The above read ensures it never is.
+	 * Ugly, I know.
+	 */
+	if (nand->bbt == NULL)  /* no memory-based bbt */
+		goto exit;
+
+	/*
+	 * Parse factory bbt and update memory-based bbt.  Factory bbt format is
+	 * simple: one bit per block, block numbers increase left to right (msb
+	 * to lsb).  Bit clear means bad block.
+	 */
+	for (i = block = 0; block < DOCG4_NUMBLOCKS; block += 8, i++) {
+		int bitnum;
+		uint8_t mask;
+		for (bitnum = 0, mask = 0x80;
+		     bitnum < 8; bitnum++, mask >>= 1) {
+			if (!(buf[i] & mask)) {
+				int badblock = block + bitnum;
+				nand->bbt[badblock / 4] |=
+					0x03 << ((badblock % 4) * 2);
+				mtd->ecc_stats.badblocks++;
+				printf("factory-marked bad block: %d\n",
+				       badblock);
+			}
+		}
+	}
+ exit:
+	kfree(buf);
+	return status;
+}
+
+static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	/*
+	 * Mark a block as bad.  Bad blocks are marked in the oob area of the
+	 * first page of the block.  The default scan_bbt() in the nand
+	 * infrastructure code works fine for building the memory-based bbt
+	 * during initialization, as does the nand infrastructure function that
+	 * checks if a block is bad by reading the bbt.  This function replaces
+	 * the nand default because writes to oob-only are not supported.
+	 */
+
+	int ret, i;
+	uint8_t *buf;
+	struct nand_chip *nand = mtd->priv;
+	struct nand_bbt_descr *bbtd = nand->badblock_pattern;
+	int block = (int)(ofs >> nand->bbt_erase_shift);
+	int page = (int)(ofs >> nand->page_shift);
+	uint32_t g4_addr = mtd_to_docg4_address(page, 0);
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: %08llx\n", __func__, ofs);
+
+	if (unlikely(ofs & (DOCG4_BLOCK_SIZE - 1)))
+		printf("%s: ofs %llx not start of block!\n",
+		       __func__, ofs);
+
+	/* allocate blank buffer for page data */
+	buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	/* update bbt in memory */
+	nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2);
+
+	/* write bit-wise negation of pattern to oob buffer */
+	memset(nand->oob_poi, 0xff, mtd->oobsize);
+	for (i = 0; i < bbtd->len; i++)
+		nand->oob_poi[bbtd->offs + i] = ~bbtd->pattern[i];
+
+	/* write first page of block */
+	write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
+	docg4_write_page(mtd, nand, buf);
+	ret = pageprog(mtd);
+	if (!ret)
+		mtd->ecc_stats.badblocks++;
+
+	kfree(buf);
+
+	return ret;
+}
+
+static uint8_t docg4_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct docg4_priv *doc = nand->priv;
+
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__);
+
+	if (doc->last_command.command == NAND_CMD_STATUS) {
+		int status;
+
+		/*
+		 * Previous nand command was status request, so nand
+		 * infrastructure code expects to read the status here.  If an
+		 * error occurred in a previous operation, report it.
+		 */
+		doc->last_command.command = 0;
+
+		if (doc->status) {
+			status = doc->status;
+			doc->status = 0;
+		}
+
+		/* why is NAND_STATUS_WP inverse logic?? */
+		else
+			status = NAND_STATUS_WP | NAND_STATUS_READY;
+
+		return status;
+	}
+
+	printf("unexpectd call to read_byte()\n");
+
+	return 0;
+}
+
+static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand)
+{
+	struct docg4_priv *doc = nand->priv;
+	int status = NAND_STATUS_WP;       /* inverse logic?? */
+	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s...\n", __func__);
+
+	/* report any previously unreported error */
+	if (doc->status) {
+		status |= doc->status;
+		doc->status = 0;
+		return status;
+	}
+
+	status |= poll_status(CONFIG_SYS_NAND_BASE);
+	return status;
+}
+
+int docg4_nand_init(struct mtd_info *mtd, struct nand_chip *nand, int devnum)
+{
+	uint16_t id1, id2;
+	struct docg4_priv *docg4;
+	int retval;
+
+	docg4 = kzalloc(sizeof(*docg4), GFP_KERNEL);
+	if (!docg4)
+		return -1;
+
+	mtd->priv = nand;
+	nand->priv = docg4;
+
+	/* These must be initialized here because the docg4 is non-standard
+	 * and doesn't produce an id that the nand code can use to look up
+	 * these values (nand_scan_ident() not called).
+	 */
+	mtd->size = DOCG4_CHIP_SIZE;
+	mtd->name = "Msys_Diskonchip_G4";
+	mtd->writesize = DOCG4_PAGE_SIZE;
+	mtd->erasesize = DOCG4_BLOCK_SIZE;
+	mtd->oobsize = DOCG4_OOB_SIZE;
+
+	nand->IO_ADDR_R =
+		(void __iomem *)CONFIG_SYS_NAND_BASE + DOC_IOSPACE_DATA;
+	nand->IO_ADDR_W = nand->IO_ADDR_R;
+	nand->chipsize = DOCG4_CHIP_SIZE;
+	nand->chip_shift = DOCG4_CHIP_SHIFT;
+	nand->bbt_erase_shift = DOCG4_ERASE_SHIFT;
+	nand->phys_erase_shift = DOCG4_ERASE_SHIFT;
+	nand->chip_delay = 20;
+	nand->page_shift = DOCG4_PAGE_SHIFT;
+	nand->pagemask = 0x3ffff;
+	nand->badblockpos = NAND_LARGE_BADBLOCK_POS;
+	nand->badblockbits = 8;
+	nand->ecc.layout = &docg4_oobinfo;
+	nand->ecc.mode = NAND_ECC_HW_SYNDROME;
+	nand->ecc.size = DOCG4_PAGE_SIZE;
+	nand->ecc.prepad = 8;
+	nand->ecc.bytes	= 8;
+	nand->options =
+		NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE | NAND_NO_AUTOINCR;
+	nand->controller = &nand->hwcontrol;
+
+	/* methods */
+	nand->cmdfunc = docg4_command;
+	nand->waitfunc = docg4_wait;
+	nand->select_chip = docg4_select_chip;
+	nand->read_byte = docg4_read_byte;
+	nand->block_markbad = docg4_block_markbad;
+	nand->read_buf = docg4_read_buf;
+	nand->write_buf = docg4_write_buf16;
+	nand->scan_bbt = nand_default_bbt;
+	nand->erase_cmd = docg4_erase_block;
+	nand->ecc.read_page = docg4_read_page;
+	nand->ecc.write_page = docg4_write_page;
+	nand->ecc.read_page_raw = docg4_read_page_raw;
+	nand->ecc.write_page_raw = docg4_write_page_raw;
+	nand->ecc.read_oob = docg4_read_oob;
+	nand->ecc.write_oob = docg4_write_oob;
+
+	/*
+	 * The way the nand infrastructure code is written, a memory-based bbt
+	 * is not created if NAND_SKIP_BBTSCAN is set.  With no memory bbt,
+	 * nand->block_bad() is used.  So when ignoring bad blocks, we skip the
+	 * scan and define a dummy block_bad() which always returns 0.
+	 */
+	if (ignore_badblocks) {
+		nand->options |= NAND_SKIP_BBTSCAN;
+		nand->block_bad	= docg4_block_neverbad;
+	}
+
+	reset(CONFIG_SYS_NAND_BASE);
+
+	/* check for presence of g4 chip by reading id registers */
+	id1 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID);
+	id1 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
+	id2 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID_INV);
+	id2 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
+	if (id1 != DOCG4_IDREG1_VALUE || id2 != DOCG4_IDREG2_VALUE)
+		return -1;
+
+	/* initialize bch algorithm */
+	docg4->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
+	if (docg4->bch == NULL)
+		return -1;
+
+	retval = nand_scan_tail(mtd);
+	if (retval)
+		return -1;
+
+	/*
+	 * Scan for bad blocks and create bbt here, then add the factory-marked
+	 * bad blocks to the bbt.
+	 */
+	nand->scan_bbt(mtd);
+	nand->options |= NAND_BBT_SCANNED;
+	retval = read_factory_bbt(mtd);
+	if (retval)
+		return -1;
+
+	retval = nand_register(devnum);
+	if (retval)
+		return -1;
+
+	return 0;
+}

+ 222 - 0
drivers/mtd/nand/docg4_spl.c

@@ -0,0 +1,222 @@
+/*
+ * SPL driver for Diskonchip G4 nand flash
+ *
+ * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
+ *
+ * This file is released under the terms of GPL v2 and any later version.
+ * See the file COPYING in the root directory of the source tree for details.
+ *
+ *
+ * This driver basically mimics the load functionality of a typical IPL (initial
+ * program loader) resident in the 2k NOR-like region of the docg4 that is
+ * mapped to the reset vector.  It allows the u-boot SPL to continue loading if
+ * the IPL loads a fixed number of flash blocks that is insufficient to contain
+ * the entire u-boot image.  In this case, a concatenated spl + u-boot image is
+ * written at the flash offset from which the IPL loads an image, and when the
+ * IPL jumps to the SPL, the SPL resumes loading where the IPL left off.  See
+ * the palmtreo680 for an example.
+ *
+ * This driver assumes that the data was written to the flash using the device's
+ * "reliable" mode, and also assumes that each 512 byte page is stored
+ * redundantly in the subsequent page.  This storage format is likely to be used
+ * by all boards that boot from the docg4.  The format compensates for the lack
+ * of ecc in the IPL.
+ *
+ * Reliable mode reduces the capacity of a block by half, and the redundant
+ * pages reduce it by half again.  As a result, the normal 256k capacity of a
+ * block is reduced to 64k for the purposes of the IPL/SPL.
+ */
+
+#include <asm/io.h>
+#include <linux/mtd/docg4.h>
+
+/* forward declarations */
+static inline void write_nop(void __iomem *docptr);
+static int poll_status(void __iomem *docptr);
+static void write_addr(void __iomem *docptr, uint32_t docg4_addr);
+static void address_sequence(unsigned int g4_page, unsigned int g4_index,
+			     void __iomem *docptr);
+static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr);
+
+int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
+{
+	void *load_addr = dst;
+	uint32_t flash_offset = offs;
+	const unsigned int block_count =
+		(size + DOCG4_BLOCK_CAPACITY_SPL - 1)
+		/ DOCG4_BLOCK_CAPACITY_SPL;
+	int i;
+
+	for (i = 0; i < block_count; i++) {
+		int ret = docg4_load_block_reliable(flash_offset, load_addr);
+		if (ret)
+			return ret;
+		load_addr += DOCG4_BLOCK_CAPACITY_SPL;
+		flash_offset += DOCG4_BLOCK_SIZE;
+	}
+	return 0;
+}
+
+static inline void write_nop(void __iomem *docptr)
+{
+	writew(0, docptr + DOC_NOP);
+}
+
+static int poll_status(void __iomem *docptr)
+{
+	/*
+	 * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
+	 * register.  Operations known to take a long time (e.g., block erase)
+	 * should sleep for a while before calling this.
+	 */
+
+	uint8_t flash_status;
+
+	/* hardware quirk requires reading twice initially */
+	flash_status = readb(docptr + DOC_FLASHCONTROL);
+
+	do {
+		flash_status = readb(docptr + DOC_FLASHCONTROL);
+	} while (!(flash_status & DOC_CTRL_FLASHREADY));
+
+	return 0;
+}
+
+static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
+{
+	/* write the four address bytes packed in docg4_addr to the device */
+
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+	docg4_addr >>= 8;
+	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
+}
+
+static void address_sequence(unsigned int g4_page, unsigned int g4_index,
+			     void __iomem *docptr)
+{
+	writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
+	writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_addr(docptr, ((uint32_t)g4_page << 16) | g4_index);
+	write_nop(docptr);
+}
+
+static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr)
+{
+	void __iomem *docptr = (void *)CONFIG_SYS_NAND_BASE;
+	unsigned int g4_page = flash_offset >> 11; /* 2k page */
+	const unsigned int last_g4_page = g4_page + 0x80; /* last in block */
+	int g4_index = 0;
+	uint16_t flash_status;
+	uint16_t *buf;
+	uint16_t discard, magic_high, magic_low;
+
+	/* flash_offset must be aligned to the start of a block */
+	if (flash_offset & 0x3ffff)
+		return -1;
+
+	writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
+	writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+	poll_status(docptr);
+	write_nop(docptr);
+	writew(0x45, docptr + DOC_FLASHSEQUENCE);
+	writew(0xa3, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	writew(0x22, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+
+	/* read 1st 4 oob bytes of first subpage of block */
+	address_sequence(g4_page, 0x0100, docptr); /* index at oob */
+	write_nop(docptr);
+	flash_status = readw(docptr + DOC_FLASHCONTROL);
+	flash_status = readw(docptr + DOC_FLASHCONTROL);
+	if (flash_status & 0x06) /* sequence or protection errors */
+		return -1;
+	writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
+	write_nop(docptr);
+	write_nop(docptr);
+	poll_status(docptr);
+	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/*
+	 * Here we read the first four oob bytes of the first page of the block.
+	 * The IPL on the palmtreo680 requires that this contain a 32 bit magic
+	 * number, or the load aborts.  We'll ignore it.
+	 */
+	discard = readw(docptr + 0x103c); /* hw quirk; 1st read discarded */
+	magic_low = readw(docptr + 0x103c);
+	magic_high = readw(docptr + DOCG4_MYSTERY_REG);
+	writew(0, docptr + DOC_DATAEND);
+	write_nop(docptr);
+	write_nop(docptr);
+
+	/* load contents of block to memory */
+	buf = (uint16_t *)dest_addr;
+	do {
+		int i;
+
+		address_sequence(g4_page, g4_index, docptr);
+		writew(DOCG4_CMD_READ2,
+		       docptr + DOC_FLASHCOMMAND);
+		write_nop(docptr);
+		write_nop(docptr);
+		poll_status(docptr);
+		writew(DOC_ECCCONF0_READ_MODE |
+		       DOC_ECCCONF0_ECC_ENABLE |
+		       DOCG4_BCH_SIZE,
+		       docptr + DOC_ECCCONF0);
+		write_nop(docptr);
+		write_nop(docptr);
+		write_nop(docptr);
+		write_nop(docptr);
+		write_nop(docptr);
+
+		/* read the 512 bytes of page data, 2 bytes at a time */
+		discard = readw(docptr + 0x103c);
+		for (i = 0; i < 256; i++)
+			*buf++ = readw(docptr + 0x103c);
+
+		/* read oob, but discard it */
+		for (i = 0; i < 7; i++)
+			discard = readw(docptr + 0x103c);
+		discard = readw(docptr + DOCG4_OOB_6_7);
+		discard = readw(docptr + DOCG4_OOB_6_7);
+
+		writew(0, docptr + DOC_DATAEND);
+		write_nop(docptr);
+		write_nop(docptr);
+
+		if (!(g4_index & 0x100)) {
+			/* not redundant subpage read; check for ecc error */
+			write_nop(docptr);
+			flash_status = readw(docptr + DOC_ECCCONF1);
+			flash_status = readw(docptr + DOC_ECCCONF1);
+			if (flash_status & 0x80) { /* ecc error */
+				g4_index += 0x108; /* read redundant subpage */
+				buf -= 256;        /* back up ram ptr */
+				continue;
+			} else                       /* no ecc error */
+				g4_index += 0x210; /* skip redundant subpage */
+		} else  /* redundant page was just read; skip ecc error check */
+			g4_index += 0x108;
+
+		if (g4_index == 0x420) { /* finished with 2k page */
+			g4_index = 0;
+			g4_page += 2; /* odd-numbered 2k pages skipped */
+		}
+
+	} while (g4_page != last_g4_page); /* while still on same block */
+
+	return 0;
+}

+ 0 - 9
drivers/mtd/nand/mxc_nand_spl.c

@@ -355,12 +355,3 @@ void nand_boot(void)
 		hang();
 	}
 }
-
-/*
- * Called in case of an exception.
- */
-void hang(void)
-{
-	/* Loop forever */
-	while (1) ;
-}

+ 17 - 0
drivers/net/fm/memac.c

@@ -112,6 +112,23 @@ static void memac_set_interface_mode(struct fsl_enet_mac *mac,
 	/* Enable automatic speed selection */
 	if_mode |= IF_MODE_EN_AUTO;
 
+	if (type == PHY_INTERFACE_MODE_RGMII) {
+		if_mode &= ~IF_MODE_EN_AUTO;
+		if_mode &= ~IF_MODE_SETSP_MASK;
+		switch (speed) {
+		case SPEED_1000:
+			if_mode |= IF_MODE_SETSP_1000M;
+			break;
+		case SPEED_100:
+			if_mode |= IF_MODE_SETSP_100M;
+			break;
+		case SPEED_10:
+			if_mode |= IF_MODE_SETSP_10M;
+		default:
+			break;
+		}
+	}
+
 	debug(" %s, if_mode = %x\n", __func__,  if_mode);
 	debug(" %s, if_status = %x\n", __func__,  if_status);
 	out_be32(&regs->if_mode, if_mode);

Some files were not shown because too many files changed in this diff