Merge branch 'master' of git://git.denx.de/u-boot-mips
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4991da2..ef78929 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -29,6 +29,7 @@
 	select SUPPORTS_LITTLE_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SWAP_IO_SPACE
 
 config TARGET_VCT
 	bool "Support vct"
@@ -116,6 +117,39 @@
 
 endchoice
 
+menu "OS boot interface"
+
+config MIPS_BOOT_CMDLINE_LEGACY
+	bool "Hand over legacy command line to Linux kernel"
+	default y
+	help
+	  Enable this option if you want U-Boot to hand over the Yamon-style
+	  command line to the kernel. All bootargs will be prepared as argc/argv
+	  compatible list. The argument count (argc) is stored in register $a0.
+	  The address of the argument list (argv) is stored in register $a1.
+
+config MIPS_BOOT_ENV_LEGACY
+	bool "Hand over legacy environment to Linux kernel"
+	default y
+	help
+	  Enable this option if you want U-Boot to hand over the Yamon-style
+	  environment to the kernel. Information like memory size, initrd
+	  address and size will be prepared as zero-terminated key/value list.
+	  The address of the enviroment is stored in register $a2.
+
+config MIPS_BOOT_FDT
+	bool "Hand over a flattened device tree to Linux kernel (INCOMPLETE)"
+	default n
+	help
+	  Enable this option if you want U-Boot to hand over a flattened
+	  device tree to the kernel.
+
+	  Note: the final hand over to the kernel is not yet implemented. After
+	        the community agreed on the MIPS boot interface for device trees,
+	        the corresponding code will be added.
+
+endmenu
+
 config SUPPORTS_BIG_ENDIAN
 	bool
 
@@ -133,6 +167,14 @@
 
 config SUPPORTS_CPU_MIPS64_R2
 	bool
+
+config CPU_MIPS32
+	bool
+	default y if CPU_MIPS32_R1 || CPU_MIPS32_R2
+
+config CPU_MIPS64
+	bool
+	default y if CPU_MIPS64_R1 || CPU_MIPS64_R2
 
 config 32BIT
 	bool
@@ -140,6 +182,9 @@
 config 64BIT
 	bool
 
+config SWAP_IO_SPACE
+	bool
+
 endif
 
 endmenu
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 1907b57..0a9e7e6 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -2,7 +2,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-head-y := arch/mips/cpu/$(CPU)/start.o
+head-$(CONFIG_CPU_MIPS32) := arch/mips/cpu/mips32/start.o
+head-$(CONFIG_CPU_MIPS64) := arch/mips/cpu/mips64/start.o
 
-libs-y += arch/mips/cpu/$(CPU)/
+libs-$(CONFIG_CPU_MIPS32) += arch/mips/cpu/mips32/
+libs-$(CONFIG_CPU_MIPS64) += arch/mips/cpu/mips64/
 libs-y += arch/mips/lib/
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S
index 384ea26..36b92cc 100644
--- a/arch/mips/cpu/mips32/start.S
+++ b/arch/mips/cpu/mips32/start.S
@@ -15,6 +15,11 @@
 #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
 #endif
 
+#ifndef CONFIG_SYS_INIT_SP_ADDR
+#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
+				CONFIG_SYS_INIT_SP_OFFSET)
+#endif
+
 	/*
 	 * For the moment disable interrupts, mark the kernel mode and
 	 * set ST0_KX so that the CPU does not spit fire when using
@@ -135,9 +140,31 @@
 #endif
 
 	/* Set up temporary stack */
-	li	sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+	li	t0, -16
+	li	t1, CONFIG_SYS_INIT_SP_ADDR
+	and	sp, t1, t0		# force 16 byte alignment
+	sub	sp, sp, GD_SIZE		# reserve space for gd
+	and	sp, sp, t0		# force 16 byte alignment
+	move	k0, sp			# save gd pointer
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	li	t2, CONFIG_SYS_MALLOC_F_LEN
+	sub	sp, sp, t2		# reserve space for early malloc
+	and	sp, sp, t0		# force 16 byte alignment
+#endif
 	move	fp, sp
 
+	/* Clear gd */
+	move	t0, k0
+1:
+	sw	zero, 0(t0)
+	blt	t0, t1, 1b
+	 addi	t0, 4
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	addu	t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
+	sw	sp, 0(t0)
+#endif
+
 	la	t9, board_init_f
 	jr	t9
 	 move	ra, zero
diff --git a/arch/mips/cpu/mips32/time.c b/arch/mips/cpu/mips32/time.c
index 386f45a..553da5f 100644
--- a/arch/mips/cpu/mips32/time.c
+++ b/arch/mips/cpu/mips32/time.c
@@ -8,63 +8,12 @@
 #include <common.h>
 #include <asm/mipsregs.h>
 
-static unsigned long timestamp;
-
-/* how many counter cycles in a jiffy */
-#define CYCLES_PER_JIFFY	\
-	(CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
-
-/*
- * timer without interrupts
- */
-
-int timer_init(void)
-{
-	/* Set up the timer for the first expiration. */
-	write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
-
-	return 0;
-}
-
-ulong get_timer(ulong base)
-{
-	unsigned int count;
-	unsigned int expirelo = read_c0_compare();
-
-	/* Check to see if we have missed any timestamps. */
-	count = read_c0_count();
-	while ((count - expirelo) < 0x7fffffff) {
-		expirelo += CYCLES_PER_JIFFY;
-		timestamp++;
-	}
-	write_c0_compare(expirelo);
-
-	return timestamp - base;
-}
-
-void __udelay(unsigned long usec)
-{
-	unsigned int tmo;
-
-	tmo = read_c0_count() + (usec * (CONFIG_SYS_MIPS_TIMER_FREQ / 1000000));
-	while ((tmo - read_c0_count()) < 0x7fffffff)
-		/*NOP*/;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On MIPS it just returns the timer value.
- */
-unsigned long long get_ticks(void)
+unsigned long notrace timer_read_counter(void)
 {
-	return get_timer(0);
+	return read_c0_count();
 }
 
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On MIPS it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
+ulong notrace get_tbclk(void)
 {
-	return CONFIG_SYS_HZ;
+	return CONFIG_SYS_MIPS_TIMER_FREQ;
 }
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S
index 6ff714e..471bc1e 100644
--- a/arch/mips/cpu/mips64/start.S
+++ b/arch/mips/cpu/mips64/start.S
@@ -15,6 +15,11 @@
 #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
 #endif
 
+#ifndef CONFIG_SYS_INIT_SP_ADDR
+#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
+				CONFIG_SYS_INIT_SP_OFFSET)
+#endif
+
 #ifdef CONFIG_SYS_LITTLE_ENDIAN
 #define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
 	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
@@ -129,9 +134,31 @@
 #endif
 
 	/* Set up temporary stack */
-	dli	sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
+	dli	t0, -16
+	dli	t1, CONFIG_SYS_INIT_SP_ADDR
+	and	sp, t1, t0		# force 16 byte alignment
+	dsub	sp, sp, GD_SIZE		# reserve space for gd
+	and	sp, sp, t0		# force 16 byte alignment
+	move	k0, sp			# save gd pointer
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	dli	t2, CONFIG_SYS_MALLOC_F_LEN
+	dsub	sp, sp, t2		# reserve space for early malloc
+	and	sp, sp, t0		# force 16 byte alignment
+#endif
 	move	fp, sp
 
+	/* Clear gd */
+	move	t0, k0
+1:
+	sw	zero, 0(t0)
+	blt	t0, t1, 1b
+	 daddi	t0, 4
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+	daddu	t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
+	sw	sp, 0(t0)
+#endif
+
 	dla	t9, board_init_f
 	jr	t9
 	 move	ra, zero
diff --git a/arch/mips/cpu/mips64/time.c b/arch/mips/cpu/mips64/time.c
index 0497acf..553da5f 100644
--- a/arch/mips/cpu/mips64/time.c
+++ b/arch/mips/cpu/mips64/time.c
@@ -8,63 +8,12 @@
 #include <common.h>
 #include <asm/mipsregs.h>
 
-static unsigned long timestamp;
-
-/* how many counter cycles in a jiffy */
-#define CYCLES_PER_JIFFY	 \
-	(CONFIG_SYS_MIPS_TIMER_FREQ + CONFIG_SYS_HZ / 2) / CONFIG_SYS_HZ
-
-/*
- * timer without interrupts
- */
-
-int timer_init(void)
-{
-	/* Set up the timer for the first expiration. */
-	write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
-
-	return 0;
-}
-
-ulong get_timer(ulong base)
-{
-	unsigned int count;
-	unsigned int expirelo = read_c0_compare();
-
-	/* Check to see if we have missed any timestamps. */
-	count = read_c0_count();
-	while ((count - expirelo) < 0x7fffffff) {
-		expirelo += CYCLES_PER_JIFFY;
-		timestamp++;
-	}
-	write_c0_compare(expirelo);
-
-	return timestamp - base;
-}
-
-void __udelay(unsigned long usec)
-{
-	unsigned int tmo;
-
-	tmo = read_c0_count() + (usec * (CONFIG_SYS_MIPS_TIMER_FREQ / 1000000));
-	while ((tmo - read_c0_count()) < 0x7fffffff)
-		/*NOP*/;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On MIPS it just returns the timer value.
- */
-unsigned long long get_ticks(void)
+unsigned long notrace timer_read_counter(void)
 {
-	return get_timer(0);
+	return read_c0_count();
 }
 
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On MIPS it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
+ulong notrace get_tbclk(void)
 {
-	return CONFIG_SYS_HZ;
+	return CONFIG_SYS_MIPS_TIMER_FREQ;
 }
diff --git a/arch/mips/include/asm/config.h b/arch/mips/include/asm/config.h
index 1c8a42b..3a891ba 100644
--- a/arch/mips/include/asm/config.h
+++ b/arch/mips/include/asm/config.h
@@ -7,8 +7,6 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_
 
-#define CONFIG_SYS_GENERIC_GLOBAL_DATA
-
 #define CONFIG_LMB
 #define CONFIG_SYS_BOOT_RAMDISK_HIGH
 
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index e0722d2..d9d8396 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <image.h>
+#include <fdt_support.h>
 #include <asm/addrspace.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -20,6 +21,18 @@
 #define mips_boot_malta		0
 #endif
 
+#if defined(CONFIG_MIPS_BOOT_CMDLINE_LEGACY)
+#define mips_boot_cmdline_legacy	1
+#else
+#define mips_boot_cmdline_legacy	0
+#endif
+
+#if defined(CONFIG_MIPS_BOOT_ENV_LEGACY)
+#define mips_boot_env_legacy	1
+#else
+#define mips_boot_env_legacy	0
+#endif
+
 static int linux_argc;
 static char **linux_argv;
 static char *linux_argp;
@@ -60,9 +73,39 @@
 	if (ret)
 		return ret;
 
+#if defined(CONFIG_MIPS_BOOT_FDT) && defined(CONFIG_OF_LIBFDT)
+	if (images->ft_len) {
+		boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
+
+		ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
+			&images->ft_len);
+		if (ret)
+			return ret;
+	}
+#endif
+
 	return 0;
 }
 
+static void boot_setup_fdt(bootm_headers_t *images)
+{
+#if defined(CONFIG_MIPS_BOOT_FDT) && defined(CONFIG_OF_LIBFDT)
+	u64 mem_start = 0;
+	u64 mem_size = gd->ram_size;
+
+	debug("## setup FDT\n");
+
+	fdt_chosen(images->ft_addr, 1);
+	fdt_fixup_memory_banks(images->ft_addr, &mem_start, &mem_size, 1);
+	fdt_fixup_ethernet(images->ft_addr);
+	fdt_initrd(images->ft_addr, images->initrd_start, images->initrd_end, 1);
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+	ft_board_setup(images->ft_addr, gd->bd);
+#endif
+#endif
+}
+
 static void linux_cmdline_init(void)
 {
 	linux_argc = 1;
@@ -92,7 +135,7 @@
 		debug("   arg %03d: %s\n", i, linux_argv[i]);
 }
 
-static void boot_cmdline_linux(bootm_headers_t *images)
+static void linux_cmdline_legacy(bootm_headers_t *images)
 {
 	const char *bootargs, *next, *quote;
 
@@ -130,8 +173,40 @@
 
 		bootargs = next;
 	}
+}
 
-	linux_cmdline_dump();
+static void linux_cmdline_append(bootm_headers_t *images)
+{
+	char buf[24];
+	ulong mem, rd_start, rd_size;
+
+	/* append mem */
+	mem = gd->ram_size >> 20;
+	sprintf(buf, "mem=%luM", mem);
+	linux_cmdline_set(buf, strlen(buf));
+
+	/* append rd_start and rd_size */
+	rd_start = images->initrd_start;
+	rd_size = images->initrd_end - images->initrd_start;
+
+	if (rd_size) {
+		sprintf(buf, "rd_start=0x%08lX", rd_start);
+		linux_cmdline_set(buf, strlen(buf));
+		sprintf(buf, "rd_size=0x%lX", rd_size);
+		linux_cmdline_set(buf, strlen(buf));
+	}
+}
+
+static void boot_cmdline_linux(bootm_headers_t *images)
+{
+	if (mips_boot_cmdline_legacy && !images->ft_len) {
+		linux_cmdline_legacy(images);
+
+		if (!mips_boot_env_legacy)
+			linux_cmdline_append(images);
+
+		linux_cmdline_dump();
+	}
 }
 
 static void linux_env_init(void)
@@ -165,7 +240,7 @@
 	}
 }
 
-static void boot_prep_linux(bootm_headers_t *images)
+static void linux_env_legacy(bootm_headers_t *images)
 {
 	char env_buf[12];
 	const char *cp;
@@ -213,6 +288,15 @@
 	}
 }
 
+static void boot_prep_linux(bootm_headers_t *images)
+{
+	if (mips_boot_env_legacy && !images->ft_len)
+		linux_env_legacy(images);
+
+	if (images->ft_len)
+		boot_setup_fdt(images);
+}
+
 static void boot_jump_linux(bootm_headers_t *images)
 {
 	typedef void __noreturn (*kernel_entry_t)(int, ulong, ulong, ulong);
@@ -226,8 +310,12 @@
 	if (mips_boot_malta)
 		linux_extra = gd->ram_size;
 
-	/* we assume that the kernel is in place */
-	printf("\nStarting kernel ...\n\n");
+#ifdef CONFIG_BOOTSTAGE_FDT
+	bootstage_fdt_add_report();
+#endif
+#ifdef CONFIG_BOOTSTAGE_REPORT
+	bootstage_report();
+#endif
 
 	kernel(linux_argc, (ulong)linux_argv, (ulong)linux_env, linux_extra);
 }
diff --git a/include/configs/malta.h b/include/configs/malta.h
index a29b86b..684d249 100644
--- a/include/configs/malta.h
+++ b/include/configs/malta.h
@@ -38,8 +38,6 @@
 #define CONFIG_SYS_MHZ			250	/* arbitrary value */
 #define CONFIG_SYS_MIPS_TIMER_FREQ	(CONFIG_SYS_MHZ * 1000000)
 
-#define CONFIG_SWAP_IO_SPACE
-
 /*
  * Memory map
  */