Merge branch 'master' of git://git.denx.de/u-boot-mips
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ef78929..bc4283d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -36,6 +36,7 @@
 	select SUPPORTS_BIG_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 config TARGET_DBAU1X00
 	bool "Support dbau1x00"
@@ -43,12 +44,14 @@
 	select SUPPORTS_LITTLE_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 config TARGET_PB1X00
 	bool "Support pb1x00"
 	select SUPPORTS_LITTLE_ENDIAN
 	select SUPPORTS_CPU_MIPS32_R1
 	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
 
 endchoice
@@ -185,6 +188,9 @@
 config SWAP_IO_SPACE
 	bool
 
+config SYS_MIPS_CACHE_INIT_RAM_LOAD
+	bool
+
 endif
 
 endmenu
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 0a9e7e6..43f0f5c 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -2,9 +2,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-head-$(CONFIG_CPU_MIPS32) := arch/mips/cpu/mips32/start.o
-head-$(CONFIG_CPU_MIPS64) := arch/mips/cpu/mips64/start.o
+head-y := arch/mips/cpu/start.o
 
-libs-$(CONFIG_CPU_MIPS32) += arch/mips/cpu/mips32/
-libs-$(CONFIG_CPU_MIPS64) += arch/mips/cpu/mips64/
+libs-y += arch/mips/cpu/
 libs-y += arch/mips/lib/
+
+libs-$(CONFIG_SOC_AU1X00) += arch/mips/mach-au1x00/
diff --git a/arch/mips/cpu/Makefile b/arch/mips/cpu/Makefile
new file mode 100644
index 0000000..fc6b455
--- /dev/null
+++ b/arch/mips/cpu/Makefile
@@ -0,0 +1,9 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+extra-y	= start.o
+
+obj-y += time.o
+obj-y += interrupts.o
+obj-y += cpu.o
diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c
new file mode 100644
index 0000000..8d3b2f5
--- /dev/null
+++ b/arch/mips/cpu/cpu.c
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <netdev.h>
+#include <linux/compiler.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+
+void __weak _machine_restart(void)
+{
+	fprintf(stderr, "*** reset failed ***\n");
+
+	while (1)
+		/* NOP */;
+}
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	_machine_restart();
+
+	return 0;
+}
+
+void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
+{
+	write_c0_entrylo0(low0);
+	write_c0_pagemask(pagemask);
+	write_c0_entrylo1(low1);
+	write_c0_entryhi(hi);
+	write_c0_index(index);
+	tlb_write_indexed();
+}
diff --git a/arch/mips/cpu/mips32/interrupts.c b/arch/mips/cpu/interrupts.c
similarity index 100%
rename from arch/mips/cpu/mips32/interrupts.c
rename to arch/mips/cpu/interrupts.c
diff --git a/arch/mips/cpu/mips32/Makefile b/arch/mips/cpu/mips32/Makefile
deleted file mode 100644
index fa82dd3..0000000
--- a/arch/mips/cpu/mips32/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# (C) Copyright 2003-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-extra-y	= start.o
-obj-y	= cache.o
-obj-y	+= cpu.o interrupts.o time.o
-
-obj-$(CONFIG_SOC_AU1X00) += au1x00/
diff --git a/arch/mips/cpu/mips32/cache.S b/arch/mips/cpu/mips32/cache.S
deleted file mode 100644
index 22bd844..0000000
--- a/arch/mips/cpu/mips32/cache.S
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- *  Cache-handling routined for MIPS CPUs
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/cacheops.h>
-
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE
-#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
-#endif
-
-#define RA		t9
-
-#define INDEX_BASE	CKSEG0
-
-	.macro	cache_op op addr
-	.set	push
-	.set	noreorder
-	.set	mips3
-	cache	\op, 0(\addr)
-	.set	pop
-	.endm
-
-	.macro	f_fill64 dst, offset, val
-	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
-#if LONGSIZE == 4
-	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
-#endif
-	.endm
-
-/*
- * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
- */
-LEAF(mips_init_icache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear tag to invalidate */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* fill once, so data field parity is correct */
-	PTR_LI		t0, INDEX_BASE
-2:	cache_op	FILL t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* invalidate again - prudent but not strictly neccessary */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_icache)
-
-/*
- * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
- */
-LEAF(mips_init_dcache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* load from each line (in cached space) */
-	PTR_LI		t0, INDEX_BASE
-2:	LONG_L		zero, 0(t0)
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_dcache)
-
-/*
- * mips_cache_reset - low level initialisation of the primary caches
- *
- * This routine initialises the primary caches to ensure that they have good
- * parity.  It must be called by the ROM before any cached locations are used
- * to prevent the possibility of data with bad parity being written to memory.
- *
- * To initialise the instruction cache it is essential that a source of data
- * with good parity is available. This routine will initialise an area of
- * memory starting at location zero to be used as a source of parity.
- *
- * RETURNS: N/A
- *
- */
-NESTED(mips_cache_reset, 0, ra)
-	move	RA, ra
-
-#if !defined(CONFIG_SYS_ICACHE_SIZE) || !defined(CONFIG_SYS_DCACHE_SIZE) || \
-    !defined(CONFIG_SYS_CACHELINE_SIZE)
-	/* read Config1 for use below */
-	mfc0	t5, CP0_CONFIG, 1
-#endif
-
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-	li	t7, CONFIG_SYS_CACHELINE_SIZE
-	li	t8, CONFIG_SYS_CACHELINE_SIZE
-#else
-	/* Detect I-cache line size. */
-	srl	t8, t5, MIPS_CONF1_IL_SHIFT
-	andi	t8, t8, (MIPS_CONF1_IL >> MIPS_CONF1_IL_SHIFT)
-	beqz	t8, 1f
-	li	t6, 2
-	sllv	t8, t6, t8
-
-1:	/* Detect D-cache line size. */
-	srl	t7, t5, MIPS_CONF1_DL_SHIFT
-	andi	t7, t7, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
-	beqz	t7, 1f
-	li	t6, 2
-	sllv	t7, t6, t7
-1:
-#endif
-
-#ifdef CONFIG_SYS_ICACHE_SIZE
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-#else
-	/* Detect I-cache size. */
-	srl	t6, t5, MIPS_CONF1_IS_SHIFT
-	andi	t6, t6, (MIPS_CONF1_IS >> MIPS_CONF1_IS_SHIFT)
-	li	t4, 32
-	xori	t2, t6, 0x7
-	beqz	t2, 1f
-	addi	t6, t6, 1
-	sllv	t4, t4, t6
-1:	/* At this point t4 == I-cache sets. */
-	mul	t2, t4, t8
-	srl	t6, t5, MIPS_CONF1_IA_SHIFT
-	andi	t6, t6, (MIPS_CONF1_IA >> MIPS_CONF1_IA_SHIFT)
-	addi	t6, t6, 1
-	/* At this point t6 == I-cache ways. */
-	mul	t2, t2, t6
-#endif
-
-#ifdef CONFIG_SYS_DCACHE_SIZE
-	li	t3, CONFIG_SYS_DCACHE_SIZE
-#else
-	/* Detect D-cache size. */
-	srl	t6, t5, MIPS_CONF1_DS_SHIFT
-	andi	t6, t6, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
-	li	t4, 32
-	xori	t3, t6, 0x7
-	beqz	t3, 1f
-	addi	t6, t6, 1
-	sllv	t4, t4, t6
-1:	/* At this point t4 == I-cache sets. */
-	mul	t3, t4, t7
-	srl	t6, t5, MIPS_CONF1_DA_SHIFT
-	andi	t6, t6, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
-	addi	t6, t6, 1
-	/* At this point t6 == I-cache ways. */
-	mul	t3, t3, t6
-#endif
-
-	/* Determine the largest L1 cache size */
-#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
-#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
-	li	v0, CONFIG_SYS_ICACHE_SIZE
-#else
-	li	v0, CONFIG_SYS_DCACHE_SIZE
-#endif
-#else
-	move	v0, t2
-	sltu	t1, t2, t3
-	movn	v0, t3, t1
-#endif
-	/*
-	 * Now clear that much memory starting from zero.
-	 */
-	PTR_LI		a0, CKSEG1
-	PTR_ADDU	a1, a0, v0
-2:	PTR_ADDIU	a0, 64
-	f_fill64	a0, -64, zero
-	bne		a0, a1, 2b
-
-	/*
-	 * The caches are probably in an indeterminate state,
-	 * so we force good parity into them by doing an
-	 * invalidate, load/fill, invalidate for each line.
-	 */
-
-	/*
-	 * Assume bottom of RAM will generate good parity for the cache.
-	 */
-
-	/*
-	 * Initialize the I-cache first,
-	 */
-	move	a1, t2
-	move	a2, t8
-	PTR_LA	v1, mips_init_icache
-	jalr	v1
-
-	/*
-	 * then initialize D-cache.
-	 */
-	move	a1, t3
-	move	a2, t7
-	PTR_LA	v1, mips_init_dcache
-	jalr	v1
-
-	jr	RA
-	END(mips_cache_reset)
-
-/*
- * dcache_status - get cache status
- *
- * RETURNS: 0 - cache disabled; 1 - cache enabled
- *
- */
-LEAF(dcache_status)
-	mfc0	t0, CP0_CONFIG
-	li	t1, CONF_CM_UNCACHED
-	andi	t0, t0, CONF_CM_CMASK
-	move	v0, zero
-	beq	t0, t1, 2f
-	li	v0, 1
-2:	jr	ra
-	END(dcache_status)
-
-/*
- * dcache_disable - disable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_disable)
-	mfc0	t0, CP0_CONFIG
-	li	t1, -8
-	and	t0, t0, t1
-	ori	t0, t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_disable)
-
-/*
- * dcache_enable - enable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_enable)
-	mfc0	t0, CP0_CONFIG
-	ori	t0, CONF_CM_CMASK
-	xori	t0, CONF_CM_CMASK
-	ori	t0, CONFIG_SYS_MIPS_CACHE_MODE
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_enable)
diff --git a/arch/mips/cpu/mips32/cpu.c b/arch/mips/cpu/mips32/cpu.c
deleted file mode 100644
index 278865b..0000000
--- a/arch/mips/cpu/mips32/cpu.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <netdev.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheops.h>
-#include <asm/reboot.h>
-
-#define cache_op(op,addr)						\
-	__asm__ __volatile__(						\
-	"	.set	push					\n"	\
-	"	.set	noreorder				\n"	\
-	"	.set	mips3\n\t				\n"	\
-	"	cache	%0, %1					\n"	\
-	"	.set	pop					\n"	\
-	:								\
-	: "i" (op), "R" (*(unsigned char *)(addr)))
-
-void __attribute__((weak)) _machine_restart(void)
-{
-}
-
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	_machine_restart();
-
-	fprintf(stderr, "*** reset failed ***\n");
-	return 0;
-}
-
-#ifdef CONFIG_SYS_CACHELINE_SIZE
-
-static inline unsigned long icache_line_size(void)
-{
-	return CONFIG_SYS_CACHELINE_SIZE;
-}
-
-static inline unsigned long dcache_line_size(void)
-{
-	return CONFIG_SYS_CACHELINE_SIZE;
-}
-
-#else /* !CONFIG_SYS_CACHELINE_SIZE */
-
-static inline unsigned long icache_line_size(void)
-{
-	unsigned long conf1, il;
-	conf1 = read_c0_config1();
-	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
-	if (!il)
-		return 0;
-	return 2 << il;
-}
-
-static inline unsigned long dcache_line_size(void)
-{
-	unsigned long conf1, dl;
-	conf1 = read_c0_config1();
-	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
-	if (!dl)
-		return 0;
-	return 2 << dl;
-}
-
-#endif /* !CONFIG_SYS_CACHELINE_SIZE */
-
-void flush_cache(ulong start_addr, ulong size)
-{
-	unsigned long ilsize = icache_line_size();
-	unsigned long dlsize = dcache_line_size();
-	unsigned long addr, aend;
-
-	/* aend will be miscalculated when size is zero, so we return here */
-	if (size == 0)
-		return;
-
-	addr = start_addr & ~(dlsize - 1);
-	aend = (start_addr + size - 1) & ~(dlsize - 1);
-
-	if (ilsize == dlsize) {
-		/* flush I-cache & D-cache simultaneously */
-		while (1) {
-			cache_op(HIT_WRITEBACK_INV_D, addr);
-			cache_op(HIT_INVALIDATE_I, addr);
-			if (addr == aend)
-				break;
-			addr += dlsize;
-		}
-		return;
-	}
-
-	/* flush D-cache */
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += dlsize;
-	}
-
-	/* flush I-cache */
-	addr = start_addr & ~(ilsize - 1);
-	aend = (start_addr + size - 1) & ~(ilsize - 1);
-	while (1) {
-		cache_op(HIT_INVALIDATE_I, addr);
-		if (addr == aend)
-			break;
-		addr += ilsize;
-	}
-}
-
-void flush_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = dcache_line_size();
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void invalidate_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = dcache_line_size();
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_INVALIDATE_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
-{
-	write_c0_entrylo0(low0);
-	write_c0_pagemask(pagemask);
-	write_c0_entrylo1(low1);
-	write_c0_entryhi(hi);
-	write_c0_index(index);
-	tlb_write_indexed();
-}
-
-int cpu_eth_init(bd_t *bis)
-{
-#ifdef CONFIG_SOC_AU1X00
-	au1x00_enet_initialize(bis);
-#endif
-	return 0;
-}
diff --git a/arch/mips/cpu/mips64/Makefile b/arch/mips/cpu/mips64/Makefile
deleted file mode 100644
index 899c319..0000000
--- a/arch/mips/cpu/mips64/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# (C) Copyright 2003-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-extra-y	= start.o
-obj-y	= cpu.o interrupts.o time.o cache.o
diff --git a/arch/mips/cpu/mips64/cache.S b/arch/mips/cpu/mips64/cache.S
deleted file mode 100644
index 36d8688..0000000
--- a/arch/mips/cpu/mips64/cache.S
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *  Cache-handling routined for MIPS CPUs
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/cacheops.h>
-
-#define RA		t9
-
-/*
- * 16kB is the maximum size of instruction and data caches on MIPS 4K,
- * 64kB is on 4KE, 24K, 5K, etc. Set bigger size for convenience.
- *
- * Note that the above size is the maximum size of primary cache. U-Boot
- * doesn't have L2 cache support for now.
- */
-#define MIPS_MAX_CACHE_SIZE	0x10000
-
-#define INDEX_BASE	CKSEG0
-
-	.macro	cache_op op addr
-	.set	push
-	.set	noreorder
-	.set	mips3
-	cache	\op, 0(\addr)
-	.set	pop
-	.endm
-
-	.macro	f_fill64 dst, offset, val
-	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
-#if LONGSIZE == 4
-	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
-	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
-#endif
-	.endm
-
-/*
- * mips_init_icache(uint PRId, ulong icache_size, unchar icache_linesz)
- */
-LEAF(mips_init_icache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear tag to invalidate */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* fill once, so data field parity is correct */
-	PTR_LI		t0, INDEX_BASE
-2:	cache_op	FILL t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* invalidate again - prudent but not strictly neccessary */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_I t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_icache)
-
-/*
- * mips_init_dcache(uint PRId, ulong dcache_size, unchar dcache_linesz)
- */
-LEAF(mips_init_dcache)
-	blez		a1, 9f
-	mtc0		zero, CP0_TAGLO
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, a1
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-	/* load from each line (in cached space) */
-	PTR_LI		t0, INDEX_BASE
-2:	LONG_L		zero, 0(t0)
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 2b
-	/* clear all tags */
-	PTR_LI		t0, INDEX_BASE
-1:	cache_op	INDEX_STORE_TAG_D t0
-	PTR_ADDU	t0, a2
-	bne		t0, t1, 1b
-9:	jr		ra
-	END(mips_init_dcache)
-
-/*
- * mips_cache_reset - low level initialisation of the primary caches
- *
- * This routine initialises the primary caches to ensure that they have good
- * parity.  It must be called by the ROM before any cached locations are used
- * to prevent the possibility of data with bad parity being written to memory.
- *
- * To initialise the instruction cache it is essential that a source of data
- * with good parity is available. This routine will initialise an area of
- * memory starting at location zero to be used as a source of parity.
- *
- * RETURNS: N/A
- *
- */
-NESTED(mips_cache_reset, 0, ra)
-	move	RA, ra
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-	li	t3, CONFIG_SYS_DCACHE_SIZE
-	li	t8, CONFIG_SYS_CACHELINE_SIZE
-
-	li	v0, MIPS_MAX_CACHE_SIZE
-
-	/*
-	 * Now clear that much memory starting from zero.
-	 */
-	PTR_LI		a0, CKSEG1
-	PTR_ADDU	a1, a0, v0
-2:	PTR_ADDIU	a0, 64
-	f_fill64	a0, -64, zero
-	bne		a0, a1, 2b
-
-	/*
-	 * The caches are probably in an indeterminate state,
-	 * so we force good parity into them by doing an
-	 * invalidate, load/fill, invalidate for each line.
-	 */
-
-	/*
-	 * Assume bottom of RAM will generate good parity for the cache.
-	 */
-
-	/*
-	 * Initialize the I-cache first,
-	 */
-	move	a1, t2
-	move	a2, t8
-	PTR_LA	v1, mips_init_icache
-	jalr	v1
-
-	/*
-	 * then initialize D-cache.
-	 */
-	move	a1, t3
-	move	a2, t8
-	PTR_LA	v1, mips_init_dcache
-	jalr	v1
-
-	jr	RA
-	END(mips_cache_reset)
-
-/*
- * dcache_status - get cache status
- *
- * RETURNS: 0 - cache disabled; 1 - cache enabled
- *
- */
-LEAF(dcache_status)
-	mfc0	t0, CP0_CONFIG
-	li	t1, CONF_CM_UNCACHED
-	andi	t0, t0, CONF_CM_CMASK
-	move	v0, zero
-	beq	t0, t1, 2f
-	li	v0, 1
-2:	jr	ra
-	END(dcache_status)
-
-/*
- * dcache_disable - disable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_disable)
-	mfc0	t0, CP0_CONFIG
-	li	t1, -8
-	and	t0, t0, t1
-	ori	t0, t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_disable)
-
-/*
- * dcache_enable - enable cache
- *
- * RETURNS: N/A
- *
- */
-LEAF(dcache_enable)
-	mfc0	t0, CP0_CONFIG
-	ori	t0, CONF_CM_CMASK
-	xori	t0, CONF_CM_CMASK
-	ori	t0, CONF_CM_CACHABLE_NONCOHERENT
-	mtc0	t0, CP0_CONFIG
-	jr	ra
-	END(dcache_enable)
diff --git a/arch/mips/cpu/mips64/cpu.c b/arch/mips/cpu/mips64/cpu.c
deleted file mode 100644
index 9f45cfc..0000000
--- a/arch/mips/cpu/mips64/cpu.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <command.h>
-#include <netdev.h>
-#include <asm/mipsregs.h>
-#include <asm/cacheops.h>
-#include <asm/reboot.h>
-
-#define cache_op(op, addr)						\
-	__asm__ __volatile__(						\
-	"	.set	push\n"						\
-	"	.set	noreorder\n"					\
-	"	.set	mips64\n"					\
-	"	cache	%0, %1\n"					\
-	"	.set	pop\n"						\
-	:								\
-	: "i" (op), "R" (*(unsigned char *)(addr)))
-
-void __attribute__((weak)) _machine_restart(void)
-{
-	fprintf(stderr, "*** reset failed ***\n");
-
-	while (1)
-		/* NOP */;
-}
-
-int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-	_machine_restart();
-
-	return 0;
-}
-
-void flush_cache(ulong start_addr, ulong size)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
-
-	/* aend will be miscalculated when size is zero, so we return here */
-	if (size == 0)
-		return;
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		cache_op(HIT_INVALIDATE_I, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void flush_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_WRITEBACK_INV_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void invalidate_dcache_range(ulong start_addr, ulong stop)
-{
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (stop - 1) & ~(lsize - 1);
-
-	while (1) {
-		cache_op(HIT_INVALIDATE_D, addr);
-		if (addr == aend)
-			break;
-		addr += lsize;
-	}
-}
-
-void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1)
-{
-	write_c0_entrylo0(low0);
-	write_c0_pagemask(pagemask);
-	write_c0_entrylo1(low1);
-	write_c0_entryhi(hi);
-	write_c0_index(index);
-	tlb_write_indexed();
-}
diff --git a/arch/mips/cpu/mips64/interrupts.c b/arch/mips/cpu/mips64/interrupts.c
deleted file mode 100644
index 275fcf5..0000000
--- a/arch/mips/cpu/mips64/interrupts.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-
-int interrupt_init(void)
-{
-	return 0;
-}
-
-void enable_interrupts(void)
-{
-}
-
-int disable_interrupts(void)
-{
-	return 0;
-}
diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S
deleted file mode 100644
index 471bc1e..0000000
--- a/arch/mips/cpu/mips64/start.S
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- *  Startup Code for MIPS64 CPU-core
- *
- *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE
-#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))
-#else
-#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
-	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
-#endif
-
-	/*
-	 * For the moment disable interrupts, mark the kernel mode and
-	 * set ST0_KX so that the CPU does not spit fire when using
-	 * 64-bit addresses.
-	 */
-	.macro	setup_c0_status set clr
-	.set	push
-	mfc0	t0, CP0_STATUS
-	or	t0, ST0_CU0 | \set | 0x1f | \clr
-	xor	t0, 0x1f | \clr
-	mtc0	t0, CP0_STATUS
-	.set	noreorder
-	sll	zero, 3				# ehb
-	.set	pop
-	.endm
-
-	.set noreorder
-
-	.globl _start
-	.text
-_start:
-	/* U-boot entry point */
-	b	reset
-	 nop
-
-	.org 0x200
-	/* TLB refill, 32 bit task */
-1:	b	1b
-	 nop
-
-	.org 0x280
-	/* XTLB refill, 64 bit task */
-1:	b	1b
-	 nop
-
-	.org 0x300
-	/* Cache error exception */
-1:	b	1b
-	 nop
-
-	.org 0x380
-	/* General exception */
-1:	b	1b
-	 nop
-
-	.org 0x400
-	/* Catch interrupt exceptions */
-1:	b	1b
-	 nop
-
-	.org 0x480
-	/* EJTAG debug exception */
-1:	b	1b
-	 nop
-
-	.align 4
-reset:
-
-	/* Clear watch registers */
-	dmtc0	zero, CP0_WATCHLO
-	dmtc0	zero, CP0_WATCHHI
-
-	/* WP(Watch Pending), SW0/1 should be cleared */
-	mtc0	zero, CP0_CAUSE
-
-	setup_c0_status ST0_KX 0
-
-	/* Init Timer */
-	mtc0	zero, CP0_COUNT
-	mtc0	zero, CP0_COMPARE
-
-#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	/* CONFIG0 register */
-	dli	t0, CONF_CM_UNCACHED
-	mtc0	t0, CP0_CONFIG
-#endif
-
-	/*
-	 * Initialize $gp, force 8 byte alignment of bal instruction to forbid
-	 * the compiler to put nop's between bal and _gp. This is required to
-	 * keep _gp and ra aligned to 8 byte.
-	 */
-	.align	3
-	bal	1f
-	 nop
-	.dword	_gp
-1:
-	ld	gp, 0(ra)
-
-#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	/* Initialize any external memory */
-	dla	t9, lowlevel_init
-	jalr	t9
-	 nop
-
-	/* Initialize caches... */
-	dla	t9, mips_cache_reset
-	jalr	t9
-	 nop
-
-	/* ... and enable them */
-	dli	t0, CONFIG_SYS_MIPS_CACHE_MODE
-	mtc0	t0, CP0_CONFIG
-#endif
-
-	/* Set up temporary stack */
-	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
-
-/*
- * void relocate_code (addr_sp, gd, addr_moni)
- *
- * This "function" does not return, instead it continues in RAM
- * after relocating the monitor code.
- *
- * a0 = addr_sp
- * a1 = gd
- * a2 = destination address
- */
-	.globl	relocate_code
-	.ent	relocate_code
-relocate_code:
-	move	sp, a0			# set new stack pointer
-	move	fp, sp
-
-	move	s0, a1			# save gd in s0
-	move	s2, a2			# save destination address in s2
-
-	dli	t0, CONFIG_SYS_MONITOR_BASE
-	dsub	s1, s2, t0		# s1 <-- relocation offset
-
-	dla	t3, in_ram
-	ld	t2, -24(t3)		# t2 <-- __image_copy_end
-	move	t1, a2
-
-	dadd	gp, s1			# adjust gp
-
-	/*
-	 * t0 = source address
-	 * t1 = target address
-	 * t2 = source end address
-	 */
-1:
-	lw	t3, 0(t0)
-	sw	t3, 0(t1)
-	daddu	t0, 4
-	blt	t0, t2, 1b
-	 daddu	t1, 4
-
-	/* If caches were enabled, we would have to flush them here. */
-	dsub	a1, t1, s2		# a1 <-- size
-	dla	t9, flush_cache
-	jalr	t9
-	 move	a0, s2			# a0 <-- destination address
-
-	/* Jump to where we've relocated ourselves */
-	daddi	t0, s2, in_ram - _start
-	jr	t0
-	 nop
-
-	.dword	__rel_dyn_end
-	.dword	__rel_dyn_start
-	.dword	__image_copy_end
-	.dword	_GLOBAL_OFFSET_TABLE_
-	.dword	num_got_entries
-
-in_ram:
-	/*
-	 * Now we want to update GOT.
-	 *
-	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
-	 * generated by GNU ld. Skip these reserved entries from relocation.
-	 */
-	ld	t3, -8(t0)		# t3 <-- num_got_entries
-	ld	t8, -16(t0)		# t8 <-- _GLOBAL_OFFSET_TABLE_
-	dadd	t8, s1			# t8 now holds relocated _G_O_T_
-	daddi	t8, t8, 16		# skipping first two entries
-	dli	t2, 2
-1:
-	ld	t1, 0(t8)
-	beqz	t1, 2f
-	 dadd	t1, s1
-	sd	t1, 0(t8)
-2:
-	daddi	t2, 1
-	blt	t2, t3, 1b
-	 daddi	t8, 8
-
-	/* Update dynamic relocations */
-	ld	t1, -32(t0)		# t1 <-- __rel_dyn_start
-	ld	t2, -40(t0)		# t2 <-- __rel_dyn_end
-
-	b	2f			# skip first reserved entry
-	 daddi	t1, 16
-
-1:
-	lw	t8, -4(t1)		# t8 <-- relocation info
-
-	dli	t3, MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
-	bne	t8, t3, 2f		# skip non R_MIPS_REL32 entries
-	 nop
-
-	ld	t3, -16(t1)		# t3 <-- location to fix up in FLASH
-
-	ld	t8, 0(t3)		# t8 <-- original pointer
-	dadd	t8, s1			# t8 <-- adjusted pointer
-
-	dadd	t3, s1			# t3 <-- location to fix up in RAM
-	sd	t8, 0(t3)
-
-2:
-	blt	t1, t2, 1b
-	 daddi	t1, 16			# each rel.dyn entry is 16 bytes
-
-	/*
-	 * Clear BSS
-	 *
-	 * GOT is now relocated. Thus __bss_start and __bss_end can be
-	 * accessed directly via $gp.
-	 */
-	dla	t1, __bss_start		# t1 <-- __bss_start
-	dla	t2, __bss_end		# t2 <-- __bss_end
-
-1:
-	sd	zero, 0(t1)
-	blt	t1, t2, 1b
-	 daddi	t1, 8
-
-	move	a0, s0			# a0 <-- gd
-	move	a1, s2
-	dla	t9, board_init_r
-	jr	t9
-	 move	ra, zero
-
-	.end	relocate_code
diff --git a/arch/mips/cpu/mips64/time.c b/arch/mips/cpu/mips64/time.c
deleted file mode 100644
index 553da5f..0000000
--- a/arch/mips/cpu/mips64/time.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/mipsregs.h>
-
-unsigned long notrace timer_read_counter(void)
-{
-	return read_c0_count();
-}
-
-ulong notrace get_tbclk(void)
-{
-	return CONFIG_SYS_MIPS_TIMER_FREQ;
-}
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/start.S
similarity index 61%
rename from arch/mips/cpu/mips32/start.S
rename to arch/mips/cpu/start.S
index 36b92cc..3b5b622 100644
--- a/arch/mips/cpu/mips32/start.S
+++ b/arch/mips/cpu/start.S
@@ -8,6 +8,7 @@
 
 #include <asm-offsets.h>
 #include <config.h>
+#include <asm/asm.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 
@@ -20,6 +21,23 @@
 				CONFIG_SYS_INIT_SP_OFFSET)
 #endif
 
+#ifdef CONFIG_32BIT
+# define MIPS_RELOC	3
+# define STATUS_SET	0
+#endif
+
+#ifdef CONFIG_64BIT
+# 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))
+# else
+#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
+	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
+# endif
+# define MIPS_RELOC	MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
+# define STATUS_SET	ST0_KX
+#endif
+
 	/*
 	 * For the moment disable interrupts, mark the kernel mode and
 	 * set ST0_KX so that the CPU does not spit fire when using
@@ -98,13 +116,13 @@
 reset:
 
 	/* Clear watch registers */
-	mtc0	zero, CP0_WATCHLO
-	mtc0	zero, CP0_WATCHHI
+	MTC0	zero, CP0_WATCHLO
+	MTC0	zero, CP0_WATCHHI
 
 	/* WP(Watch Pending), SW0/1 should be cleared */
 	mtc0	zero, CP0_CAUSE
 
-	setup_c0_status 0 0
+	setup_c0_status STATUS_SET 0
 
 	/* Init Timer */
 	mtc0	zero, CP0_COUNT
@@ -116,21 +134,26 @@
 	mtc0	t0, CP0_CONFIG
 #endif
 
-	/* Initialize $gp */
+	/*
+	 * Initialize $gp, force pointer sized alignment of bal instruction to
+	 * forbid the compiler to put nop's between bal and _gp. This is
+	 * required to keep _gp and ra aligned to 8 byte.
+	 */
+	.align	PTRLOG
 	bal	1f
 	 nop
-	.word	_gp
+	PTR	_gp
 1:
-	lw	gp, 0(ra)
+	PTR_L	gp, 0(ra)
 
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
 	/* Initialize any external memory */
-	la	t9, lowlevel_init
+	PTR_LA	t9, lowlevel_init
 	jalr	t9
 	 nop
 
 	/* Initialize caches... */
-	la	t9, mips_cache_reset
+	PTR_LA	t9, mips_cache_reset
 	jalr	t9
 	 nop
 
@@ -140,15 +163,15 @@
 #endif
 
 	/* Set up temporary stack */
-	li	t0, -16
-	li	t1, CONFIG_SYS_INIT_SP_ADDR
+	PTR_LI	t0, -16
+	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
 	and	sp, t1, t0		# force 16 byte alignment
-	sub	sp, sp, GD_SIZE		# reserve space for gd
+	PTR_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
+	PTR_LI	t2, CONFIG_SYS_MALLOC_F_LEN
+	PTR_SUB	sp, sp, t2		# reserve space for early malloc
 	and	sp, sp, t0		# force 16 byte alignment
 #endif
 	move	fp, sp
@@ -158,14 +181,14 @@
 1:
 	sw	zero, 0(t0)
 	blt	t0, t1, 1b
-	 addi	t0, 4
+	 PTR_ADDI t0, 4
 
 #ifdef CONFIG_SYS_MALLOC_F_LEN
-	addu	t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
+	PTR_ADDU t0, k0, GD_MALLOC_BASE	# gd->malloc_base offset
 	sw	sp, 0(t0)
 #endif
 
-	la	t9, board_init_f
+	PTR_LA	t9, board_init_f
 	jr	t9
 	 move	ra, zero
 
@@ -188,14 +211,14 @@
 	move	s0, a1			# save gd in s0
 	move	s2, a2			# save destination address in s2
 
-	li	t0, CONFIG_SYS_MONITOR_BASE
-	sub	s1, s2, t0		# s1 <-- relocation offset
+	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
+	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
 
-	la	t3, in_ram
-	lw	t2, -12(t3)		# t2 <-- __image_copy_end
+	PTR_LA	t3, in_ram
+	PTR_L	t2, -(3 * PTRSIZE)(t3)	# t2 <-- __image_copy_end
 	move	t1, a2
 
-	add	gp, s1			# adjust gp
+	PTR_ADD	gp, s1			# adjust gp
 
 	/*
 	 * t0 = source address
@@ -205,26 +228,26 @@
 1:
 	lw	t3, 0(t0)
 	sw	t3, 0(t1)
-	addu	t0, 4
+	PTR_ADDU t0, 4
 	blt	t0, t2, 1b
-	 addu	t1, 4
+	 PTR_ADDU t1, 4
 
 	/* If caches were enabled, we would have to flush them here. */
-	sub	a1, t1, s2		# a1 <-- size
-	la	t9, flush_cache
+	PTR_SUB	a1, t1, s2		# a1 <-- size
+	PTR_LA	t9, flush_cache
 	jalr	t9
 	 move	a0, s2			# a0 <-- destination address
 
 	/* Jump to where we've relocated ourselves */
-	addi	t0, s2, in_ram - _start
+	PTR_ADDI t0, s2, in_ram - _start
 	jr	t0
 	 nop
 
-	.word	__rel_dyn_end
-	.word	__rel_dyn_start
-	.word	__image_copy_end
-	.word	_GLOBAL_OFFSET_TABLE_
-	.word	num_got_entries
+	PTR	__rel_dyn_end
+	PTR	__rel_dyn_start
+	PTR	__image_copy_end
+	PTR	_GLOBAL_OFFSET_TABLE_
+	PTR	num_got_entries
 
 in_ram:
 	/*
@@ -233,46 +256,46 @@
 	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
 	 * generated by GNU ld. Skip these reserved entries from relocation.
 	 */
-	lw	t3, -4(t0)		# t3 <-- num_got_entries
-	lw	t8, -8(t0)		# t8 <-- _GLOBAL_OFFSET_TABLE_
-	add	t8, s1			# t8 now holds relocated _G_O_T_
-	addi	t8, t8, 8		# skipping first two entries
-	li	t2, 2
+	PTR_L	t3, -(1 * PTRSIZE)(t0)	# t3 <-- num_got_entries
+	PTR_L	t8, -(2 * PTRSIZE)(t0)	# t8 <-- _GLOBAL_OFFSET_TABLE_
+	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
+	PTR_ADDI t8, t8, 2 * PTRSIZE	# skipping first two entries
+	PTR_LI	t2, 2
 1:
-	lw	t1, 0(t8)
+	PTR_L	t1, 0(t8)
 	beqz	t1, 2f
-	 add	t1, s1
-	sw	t1, 0(t8)
+	 PTR_ADD t1, s1
+	PTR_S	t1, 0(t8)
 2:
-	addi	t2, 1
+	PTR_ADDI t2, 1
 	blt	t2, t3, 1b
-	 addi	t8, 4
+	 PTR_ADDI t8, PTRSIZE
 
 	/* Update dynamic relocations */
-	lw	t1, -16(t0)		# t1 <-- __rel_dyn_start
-	lw	t2, -20(t0)		# t2 <-- __rel_dyn_end
+	PTR_L	t1, -(4 * PTRSIZE)(t0)	# t1 <-- __rel_dyn_start
+	PTR_L	t2, -(5 * PTRSIZE)(t0)	# t2 <-- __rel_dyn_end
 
 	b	2f			# skip first reserved entry
-	 addi	t1, 8
+	 PTR_ADDI t1, 2 * PTRSIZE
 
 1:
 	lw	t8, -4(t1)		# t8 <-- relocation info
 
-	li	t3, 3
-	bne	t8, t3, 2f		# skip non R_MIPS_REL32 entries
+	PTR_LI	t3, MIPS_RELOC
+	bne	t8, t3, 2f		# skip non-MIPS_RELOC entries
 	 nop
 
-	lw	t3, -8(t1)		# t3 <-- location to fix up in FLASH
+	PTR_L	t3, -(2 * PTRSIZE)(t1)	# t3 <-- location to fix up in FLASH
 
-	lw	t8, 0(t3)		# t8 <-- original pointer
-	add	t8, s1			# t8 <-- adjusted pointer
+	PTR_L	t8, 0(t3)		# t8 <-- original pointer
+	PTR_ADD	t8, s1			# t8 <-- adjusted pointer
 
-	add	t3, s1			# t3 <-- location to fix up in RAM
-	sw	t8, 0(t3)
+	PTR_ADD	t3, s1			# t3 <-- location to fix up in RAM
+	PTR_S	t8, 0(t3)
 
 2:
 	blt	t1, t2, 1b
-	 addi	t1, 8			# each rel.dyn entry is 8 bytes
+	 PTR_ADDI t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
 
 	/*
 	 * Clear BSS
@@ -280,17 +303,17 @@
 	 * GOT is now relocated. Thus __bss_start and __bss_end can be
 	 * accessed directly via $gp.
 	 */
-	la	t1, __bss_start		# t1 <-- __bss_start
-	la	t2, __bss_end		# t2 <-- __bss_end
+	PTR_LA	t1, __bss_start		# t1 <-- __bss_start
+	PTR_LA	t2, __bss_end		# t2 <-- __bss_end
 
 1:
-	sw	zero, 0(t1)
+	PTR_S	zero, 0(t1)
 	blt	t1, t2, 1b
-	 addi	t1, 4
+	 PTR_ADDI t1, PTRSIZE
 
 	move	a0, s0			# a0 <-- gd
 	move	a1, s2
-	la	t9, board_init_r
+	PTR_LA	t9, board_init_r
 	jr	t9
 	 move	ra, zero
 
diff --git a/arch/mips/cpu/mips32/time.c b/arch/mips/cpu/time.c
similarity index 100%
rename from arch/mips/cpu/mips32/time.c
rename to arch/mips/cpu/time.c
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 6464250..75ec380 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -11,6 +11,19 @@
 #ifndef	__ASM_CACHEOPS_H
 #define	__ASM_CACHEOPS_H
 
+#ifndef __ASSEMBLY__
+
+static inline void mips_cache(int op, const volatile void *addr)
+{
+#ifdef __GCC_HAVE_BUILTIN_MIPS_CACHE
+	__builtin_mips_cache(op, addr);
+#else
+	__asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr))
+#endif
+}
+
+#endif /* !__ASSEMBLY__ */
+
 /*
  * Cache Operations available on all MIPS processors with R4000-style caches
  */
diff --git a/arch/mips/include/asm/malta.h b/arch/mips/include/asm/malta.h
index 9e7c045..d9ffc15 100644
--- a/arch/mips/include/asm/malta.h
+++ b/arch/mips/include/asm/malta.h
@@ -64,4 +64,9 @@
 
 #define PCI_CFG_PIIX4_GENCFG_SERIRQ	(1 << 16)
 
+#define PCI_CFG_PIIX4_IDETIM_PRI	0x40
+#define PCI_CFG_PIIX4_IDETIM_SEC	0x42
+
+#define PCI_CFG_PIIX4_IDETIM_IDE	(1 << 15)
+
 #endif /* _MIPS_ASM_MALTA_H */
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 7f9b653..ac536da 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,6 +5,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-y	+= cache.o
+obj-y	+= cache_init.o
 obj-y	+= io.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c
new file mode 100644
index 0000000..e245614
--- /dev/null
+++ b/arch/mips/lib/cache.c
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/cacheops.h>
+#include <asm/mipsregs.h>
+
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+
+static inline unsigned long icache_line_size(void)
+{
+	return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+	return CONFIG_SYS_CACHELINE_SIZE;
+}
+
+#else /* !CONFIG_SYS_CACHELINE_SIZE */
+
+static inline unsigned long icache_line_size(void)
+{
+	unsigned long conf1, il;
+	conf1 = read_c0_config1();
+	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHIFT;
+	if (!il)
+		return 0;
+	return 2 << il;
+}
+
+static inline unsigned long dcache_line_size(void)
+{
+	unsigned long conf1, dl;
+	conf1 = read_c0_config1();
+	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHIFT;
+	if (!dl)
+		return 0;
+	return 2 << dl;
+}
+
+#endif /* !CONFIG_SYS_CACHELINE_SIZE */
+
+void flush_cache(ulong start_addr, ulong size)
+{
+	unsigned long ilsize = icache_line_size();
+	unsigned long dlsize = dcache_line_size();
+	const void *addr, *aend;
+
+	/* aend will be miscalculated when size is zero, so we return here */
+	if (size == 0)
+		return;
+
+	addr = (const void *)(start_addr & ~(dlsize - 1));
+	aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
+
+	if (ilsize == dlsize) {
+		/* flush I-cache & D-cache simultaneously */
+		while (1) {
+			mips_cache(HIT_WRITEBACK_INV_D, addr);
+			mips_cache(HIT_INVALIDATE_I, addr);
+			if (addr == aend)
+				break;
+			addr += dlsize;
+		}
+		return;
+	}
+
+	/* flush D-cache */
+	while (1) {
+		mips_cache(HIT_WRITEBACK_INV_D, addr);
+		if (addr == aend)
+			break;
+		addr += dlsize;
+	}
+
+	/* flush I-cache */
+	addr = (const void *)(start_addr & ~(ilsize - 1));
+	aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
+	while (1) {
+		mips_cache(HIT_INVALIDATE_I, addr);
+		if (addr == aend)
+			break;
+		addr += ilsize;
+	}
+}
+
+void flush_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = dcache_line_size();
+	const void *addr = (const void *)(start_addr & ~(lsize - 1));
+	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
+
+	while (1) {
+		mips_cache(HIT_WRITEBACK_INV_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
+
+void invalidate_dcache_range(ulong start_addr, ulong stop)
+{
+	unsigned long lsize = dcache_line_size();
+	const void *addr = (const void *)(start_addr & ~(lsize - 1));
+	const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
+
+	while (1) {
+		mips_cache(HIT_INVALIDATE_D, addr);
+		if (addr == aend)
+			break;
+		addr += lsize;
+	}
+}
diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S
new file mode 100644
index 0000000..137d728
--- /dev/null
+++ b/arch/mips/lib/cache_init.S
@@ -0,0 +1,241 @@
+/*
+ *  Cache-handling routined for MIPS CPUs
+ *
+ *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+
+#ifndef CONFIG_SYS_MIPS_CACHE_MODE
+#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
+#endif
+
+#define INDEX_BASE	CKSEG0
+
+	.macro	f_fill64 dst, offset, val
+	LONG_S	\val, (\offset +  0 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  1 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  2 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  3 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  4 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  5 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  6 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  7 * LONGSIZE)(\dst)
+#if LONGSIZE == 4
+	LONG_S	\val, (\offset +  8 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset +  9 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 10 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 11 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 12 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 13 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 14 * LONGSIZE)(\dst)
+	LONG_S	\val, (\offset + 15 * LONGSIZE)(\dst)
+#endif
+	.endm
+
+	.macro cache_loop	curr, end, line_sz, op
+10:	cache		\op, 0(\curr)
+	PTR_ADDU	\curr, \curr, \line_sz
+	bne		\curr, \end, 10b
+	.endm
+
+	.macro	l1_info		sz, line_sz, off
+	.set	push
+	.set	noat
+
+	mfc0	$1, CP0_CONFIG, 1
+
+	/* detect line size */
+	srl	\line_sz, $1, \off + MIPS_CONF1_DL_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	\line_sz, \line_sz, (MIPS_CONF1_DL >> MIPS_CONF1_DL_SHIFT)
+	move	\sz, zero
+	beqz	\line_sz, 10f
+	li	\sz, 2
+	sllv	\line_sz, \sz, \line_sz
+
+	/* detect associativity */
+	srl	\sz, $1, \off + MIPS_CONF1_DA_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	\sz, \sz, (MIPS_CONF1_DA >> MIPS_CONF1_DA_SHIFT)
+	addi	\sz, \sz, 1
+
+	/* sz *= line_sz */
+	mul	\sz, \sz, \line_sz
+
+	/* detect log32(sets) */
+	srl	$1, $1, \off + MIPS_CONF1_DS_SHIFT - MIPS_CONF1_DA_SHIFT
+	andi	$1, $1, (MIPS_CONF1_DS >> MIPS_CONF1_DS_SHIFT)
+	addiu	$1, $1, 1
+	andi	$1, $1, 0x7
+
+	/* sz <<= log32(sets) */
+	sllv	\sz, \sz, $1
+
+	/* sz *= 32 */
+	li	$1, 32
+	mul	\sz, \sz, $1
+10:
+	.set	pop
+	.endm
+/*
+ * mips_cache_reset - low level initialisation of the primary caches
+ *
+ * This routine initialises the primary caches to ensure that they have good
+ * parity.  It must be called by the ROM before any cached locations are used
+ * to prevent the possibility of data with bad parity being written to memory.
+ *
+ * To initialise the instruction cache it is essential that a source of data
+ * with good parity is available. This routine will initialise an area of
+ * memory starting at location zero to be used as a source of parity.
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(mips_cache_reset)
+#ifdef CONFIG_SYS_ICACHE_SIZE
+	li	t2, CONFIG_SYS_ICACHE_SIZE
+	li	t8, CONFIG_SYS_CACHELINE_SIZE
+#else
+	l1_info	t2, t8, MIPS_CONF1_IA_SHIFT
+#endif
+
+#ifdef CONFIG_SYS_DCACHE_SIZE
+	li	t3, CONFIG_SYS_DCACHE_SIZE
+	li	t9, CONFIG_SYS_CACHELINE_SIZE
+#else
+	l1_info	t3, t9, MIPS_CONF1_DA_SHIFT
+#endif
+
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+
+	/* Determine the largest L1 cache size */
+#if defined(CONFIG_SYS_ICACHE_SIZE) && defined(CONFIG_SYS_DCACHE_SIZE)
+#if CONFIG_SYS_ICACHE_SIZE > CONFIG_SYS_DCACHE_SIZE
+	li	v0, CONFIG_SYS_ICACHE_SIZE
+#else
+	li	v0, CONFIG_SYS_DCACHE_SIZE
+#endif
+#else
+	move	v0, t2
+	sltu	t1, t2, t3
+	movn	v0, t3, t1
+#endif
+	/*
+	 * Now clear that much memory starting from zero.
+	 */
+	PTR_LI		a0, CKSEG1
+	PTR_ADDU	a1, a0, v0
+2:	PTR_ADDIU	a0, 64
+	f_fill64	a0, -64, zero
+	bne		a0, a1, 2b
+
+#endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
+
+	/*
+	 * The TagLo registers used depend upon the CPU implementation, but the
+	 * architecture requires that it is safe for software to write to both
+	 * TagLo selects 0 & 2 covering supported cases.
+	 */
+	mtc0		zero, CP0_TAGLO
+	mtc0		zero, CP0_TAGLO, 2
+
+	/*
+	 * The caches are probably in an indeterminate state, so we force good
+	 * parity into them by doing an invalidate for each line. If
+	 * CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD is set then we'll proceed to
+	 * perform a load/fill & a further invalidate for each line, assuming
+	 * that the bottom of RAM (having just been cleared) will generate good
+	 * parity for the cache.
+	 */
+
+	/*
+	 * Initialize the I-cache first,
+	 */
+	blez		t2, 1f
+	PTR_LI		t0, INDEX_BASE
+	PTR_ADDU	t1, t0, t2
+	/* clear tag to invalidate */
+	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+	/* fill once, so data field parity is correct */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t8, FILL
+	/* invalidate again - prudent but not strictly neccessary */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+#endif
+
+	/*
+	 * then initialize D-cache.
+	 */
+1:	blez		t3, 3f
+	PTR_LI		t0, INDEX_BASE
+	PTR_ADDU	t1, t0, t3
+	/* clear all tags */
+	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+#ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+	/* load from each line (in cached space) */
+	PTR_LI		t0, INDEX_BASE
+2:	LONG_L		zero, 0(t0)
+	PTR_ADDU	t0, t9
+	bne		t0, t1, 2b
+	/* clear all tags */
+	PTR_LI		t0, INDEX_BASE
+	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+#endif
+
+3:	jr	ra
+	END(mips_cache_reset)
+
+/*
+ * dcache_status - get cache status
+ *
+ * RETURNS: 0 - cache disabled; 1 - cache enabled
+ *
+ */
+LEAF(dcache_status)
+	mfc0	t0, CP0_CONFIG
+	li	t1, CONF_CM_UNCACHED
+	andi	t0, t0, CONF_CM_CMASK
+	move	v0, zero
+	beq	t0, t1, 2f
+	li	v0, 1
+2:	jr	ra
+	END(dcache_status)
+
+/*
+ * dcache_disable - disable cache
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(dcache_disable)
+	mfc0	t0, CP0_CONFIG
+	li	t1, -8
+	and	t0, t0, t1
+	ori	t0, t0, CONF_CM_UNCACHED
+	mtc0	t0, CP0_CONFIG
+	jr	ra
+	END(dcache_disable)
+
+/*
+ * dcache_enable - enable cache
+ *
+ * RETURNS: N/A
+ *
+ */
+LEAF(dcache_enable)
+	mfc0	t0, CP0_CONFIG
+	ori	t0, CONF_CM_CMASK
+	xori	t0, CONF_CM_CMASK
+	ori	t0, CONFIG_SYS_MIPS_CACHE_MODE
+	mtc0	t0, CP0_CONFIG
+	jr	ra
+	END(dcache_enable)
diff --git a/arch/mips/cpu/mips32/au1x00/Makefile b/arch/mips/mach-au1x00/Makefile
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/Makefile
rename to arch/mips/mach-au1x00/Makefile
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
similarity index 98%
rename from arch/mips/cpu/mips32/au1x00/au1x00_eth.c
rename to arch/mips/mach-au1x00/au1x00_eth.c
index 4770f56..39c5b6b 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -294,3 +294,9 @@
 
 	return 1;
 }
+
+int cpu_eth_init(bd_t *bis)
+{
+	au1x00_enet_initialize(bis);
+	return 0;
+}
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_ide.c b/arch/mips/mach-au1x00/au1x00_ide.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_ide.c
rename to arch/mips/mach-au1x00/au1x00_ide.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_serial.c b/arch/mips/mach-au1x00/au1x00_serial.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_serial.c
rename to arch/mips/mach-au1x00/au1x00_serial.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c b/arch/mips/mach-au1x00/au1x00_usb_ohci.c
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c
rename to arch/mips/mach-au1x00/au1x00_usb_ohci.c
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.h b/arch/mips/mach-au1x00/au1x00_usb_ohci.h
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.h
rename to arch/mips/mach-au1x00/au1x00_usb_ohci.h
diff --git a/arch/mips/cpu/mips32/au1x00/config.mk b/arch/mips/mach-au1x00/config.mk
similarity index 100%
rename from arch/mips/cpu/mips32/au1x00/config.mk
rename to arch/mips/mach-au1x00/config.mk
diff --git a/board/imgtec/malta/malta.c b/board/imgtec/malta/malta.c
index 78c4bd4..79562f7 100644
--- a/board/imgtec/malta/malta.c
+++ b/board/imgtec/malta/malta.c
@@ -6,6 +6,7 @@
  */
 
 #include <common.h>
+#include <ide.h>
 #include <netdev.h>
 #include <pci.h>
 #include <pci_gt64120.h>
@@ -123,6 +124,7 @@
 
 	reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE);
 	__raw_writel(GORESET, reset_base);
+	mdelay(1000);
 }
 
 int board_early_init_f(void)
@@ -217,4 +219,22 @@
 	pci_read_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, &val8);
 	val8 |= PCI_CFG_PIIX4_SERIRQC_EN | PCI_CFG_PIIX4_SERIRQC_CONT;
 	pci_write_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, val8);
+
+	bdf = pci_find_device(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82371AB, 0);
+	if (bdf == -1)
+		panic("Failed to find PIIX4 IDE controller\n");
+
+	/* enable bus master & IO access */
+	val32 |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
+	pci_write_config_dword(bdf, PCI_COMMAND, val32);
+
+	/* set latency */
+	pci_write_config_byte(bdf, PCI_LATENCY_TIMER, 0x40);
+
+	/* enable IDE/ATA */
+	pci_write_config_dword(bdf, PCI_CFG_PIIX4_IDETIM_PRI,
+			       PCI_CFG_PIIX4_IDETIM_IDE);
+	pci_write_config_dword(bdf, PCI_CFG_PIIX4_IDETIM_SEC,
+			       PCI_CFG_PIIX4_IDETIM_IDE);
 }
diff --git a/include/configs/malta.h b/include/configs/malta.h
index 684d249..354672e 100644
--- a/include/configs/malta.h
+++ b/include/configs/malta.h
@@ -71,6 +71,7 @@
 					 sizeof(CONFIG_SYS_PROMPT) + 16)
 #define CONFIG_SYS_MAXARGS		16
 
+#define CONFIG_SYS_HUSH_PARSER
 #define CONFIG_AUTO_COMPLETE
 #define CONFIG_CMDLINE_EDITING
 
@@ -107,6 +108,16 @@
 	(CONFIG_SYS_FLASH_BASE + (4 << 20) - CONFIG_ENV_SIZE)
 
 /*
+ * IDE/ATA
+ */
+#define CONFIG_SYS_IDE_MAXBUS		1
+#define CONFIG_SYS_IDE_MAXDEVICE	2
+#define CONFIG_SYS_ATA_BASE_ADDR	CONFIG_SYS_ISA_IO_BASE_ADDRESS
+#define CONFIG_SYS_ATA_IDE0_OFFSET	0x01f0
+#define CONFIG_SYS_ATA_DATA_OFFSET	0
+#define CONFIG_SYS_ATA_REG_OFFSET	0
+
+/*
  * Commands
  */
 #include <config_cmd_default.h>
@@ -118,6 +129,8 @@
 
 #define CONFIG_CMD_DATE
 #define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_IDE
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_PING