diff --git a/arch/mips/cpu/mips32/cache.S b/arch/mips/cpu/mips32/cache.S
index 12f656cad0a7746f1cbcb2c56a3238f04c67c198..22bd844eae750610e2b1367e6bb581db9e17902a 100644
--- a/arch/mips/cpu/mips32/cache.S
+++ b/arch/mips/cpu/mips32/cache.S
@@ -20,15 +20,6 @@
 
 #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
@@ -126,12 +117,85 @@ LEAF(mips_init_dcache)
  */
 NESTED(mips_cache_reset, 0, ra)
 	move	RA, ra
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-	li	t3, CONFIG_SYS_DCACHE_SIZE
+
+#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
 
-	li	v0, MIPS_MAX_CACHE_SIZE
+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.
 	 */
@@ -163,7 +227,7 @@ NESTED(mips_cache_reset, 0, ra)
 	 * then initialize D-cache.
 	 */
 	move	a1, t3
-	move	a2, t8
+	move	a2, t7
 	PTR_LA	v1, mips_init_dcache
 	jalr	v1
 
diff --git a/arch/mips/cpu/mips32/cpu.c b/arch/mips/cpu/mips32/cpu.c
index 28d5c456832be0ecbe547efb70b7ee77c243fa12..278865b6fff54849c98b0e1bd69a7cc7b2e5ba6f 100644
--- a/arch/mips/cpu/mips32/cpu.c
+++ b/arch/mips/cpu/mips32/cpu.c
@@ -34,28 +34,89 @@ int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	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 lsize = CONFIG_SYS_CACHELINE_SIZE;
-	unsigned long addr = start_addr & ~(lsize - 1);
-	unsigned long aend = (start_addr + size - 1) & ~(lsize - 1);
+	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 += lsize;
+		addr += ilsize;
 	}
 }
 
 void flush_dcache_range(ulong start_addr, ulong stop)
 {
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+	unsigned long lsize = dcache_line_size();
 	unsigned long addr = start_addr & ~(lsize - 1);
 	unsigned long aend = (stop - 1) & ~(lsize - 1);
 
@@ -69,7 +130,7 @@ void flush_dcache_range(ulong start_addr, ulong stop)
 
 void invalidate_dcache_range(ulong start_addr, ulong stop)
 {
-	unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE;
+	unsigned long lsize = dcache_line_size();
 	unsigned long addr = start_addr & ~(lsize - 1);
 	unsigned long aend = (stop - 1) & ~(lsize - 1);
 
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S
index 70ad198cc9d2a54888d447a8641345bc5faa491a..68e59b596f1146f605a91383c7dd950945fddc2f 100644
--- a/arch/mips/cpu/mips32/start.S
+++ b/arch/mips/cpu/mips32/start.S
@@ -51,7 +51,7 @@ _start:
 	 */
 	.word CONFIG_SYS_XWAY_EBU_BOOTCFG
 	.word 0x0
-#elif defined(CONFIG_QEMU_MALTA)
+#elif defined(CONFIG_MALTA)
 	/*
 	 * Linux expects the Board ID here.
 	 */
diff --git a/arch/mips/include/asm/malta.h b/arch/mips/include/asm/malta.h
index d4d44a299f1c3351f11d8363a0ae6b3896159002..9b1100bc4950807065c51c19cecacb47d4e767bf 100644
--- a/arch/mips/include/asm/malta.h
+++ b/arch/mips/include/asm/malta.h
@@ -1,23 +1,60 @@
 /*
  * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 Imagination Technologies
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #ifndef _MIPS_ASM_MALTA_H
 #define _MIPS_ASM_MALTA_H
 
-#define MALTA_IO_PORT_BASE	0x18000000
+#define MALTA_GT_BASE			0x1be00000
+#define MALTA_GT_PCIIO_BASE		0x18000000
+#define MALTA_GT_UART0_BASE		(MALTA_GT_PCIIO_BASE + 0x3f8)
 
-#define MALTA_UART_BASE		(MALTA_IO_PORT_BASE + 0x3f8)
+#define MALTA_MSC01_BIU_BASE		0x1bc80000
+#define MALTA_MSC01_PCI_BASE		0x1bd00000
+#define MALTA_MSC01_PBC_BASE		0x1bd40000
+#define MALTA_MSC01_IP1_BASE		0x1bc00000
+#define MALTA_MSC01_IP1_SIZE		0x00400000
+#define MALTA_MSC01_IP2_BASE1		0x10000000
+#define MALTA_MSC01_IP2_SIZE1		0x08000000
+#define MALTA_MSC01_IP2_BASE2		0x18000000
+#define MALTA_MSC01_IP2_SIZE2		0x04000000
+#define MALTA_MSC01_IP3_BASE		0x1c000000
+#define MALTA_MSC01_IP3_SIZE		0x04000000
+#define MALTA_MSC01_PCIMEM_BASE		0x10000000
+#define MALTA_MSC01_PCIMEM_SIZE		0x10000000
+#define MALTA_MSC01_PCIMEM_MAP		0x10000000
+#define MALTA_MSC01_PCIIO_BASE		0x1b000000
+#define MALTA_MSC01_PCIIO_SIZE		0x00800000
+#define MALTA_MSC01_PCIIO_MAP		0x00000000
+#define MALTA_MSC01_UART0_BASE		(MALTA_MSC01_PCIIO_BASE + 0x3f8)
 
-#define MALTA_GT_BASE		0x1be00000
+#define MALTA_ASCIIWORD			0x1f000410
+#define MALTA_ASCIIPOS0			0x1f000418
+#define MALTA_ASCIIPOS1			0x1f000420
+#define MALTA_ASCIIPOS2			0x1f000428
+#define MALTA_ASCIIPOS3			0x1f000430
+#define MALTA_ASCIIPOS4			0x1f000438
+#define MALTA_ASCIIPOS5			0x1f000440
+#define MALTA_ASCIIPOS6			0x1f000448
+#define MALTA_ASCIIPOS7			0x1f000450
 
-#define MALTA_RESET_BASE	0x1f000500
-#define GORESET			0x42
+#define MALTA_RESET_BASE		0x1f000500
+#define GORESET				0x42
 
-#define MALTA_FLASH_BASE	0x1fc00000
+#define MALTA_FLASH_BASE		0x1fc00000
+
+#define MALTA_REVISION			0x1fc00010
+#define MALTA_REVISION_CORID_SHF	10
+#define MALTA_REVISION_CORID_MSK	(0x3f << MALTA_REVISION_CORID_SHF)
+#define MALTA_REVISION_CORID_CORE_LV		1
+#define MALTA_REVISION_CORID_CORE_FPGA6		14
+
+#define PCI_CFG_PIIX4_PIRQRCA		0x60
+#define PCI_CFG_PIIX4_PIRQRCB		0x61
+#define PCI_CFG_PIIX4_PIRQRCC		0x62
+#define PCI_CFG_PIIX4_PIRQRCD		0x63
 
 #endif /* _MIPS_ASM_MALTA_H */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index be7e5c65ec1f38e91435844192af5a9637c2b337..3571e4fdf2e2867153ed1677cd5d12c639a09047 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -494,11 +494,17 @@
 #define MIPS_CONF1_PC		(_ULCAST_(1) <<  4)
 #define MIPS_CONF1_MD		(_ULCAST_(1) <<  5)
 #define MIPS_CONF1_C2		(_ULCAST_(1) <<  6)
+#define MIPS_CONF1_DA_SHIFT	7
 #define MIPS_CONF1_DA		(_ULCAST_(7) <<  7)
+#define MIPS_CONF1_DL_SHIFT	10
 #define MIPS_CONF1_DL		(_ULCAST_(7) << 10)
+#define MIPS_CONF1_DS_SHIFT	13
 #define MIPS_CONF1_DS		(_ULCAST_(7) << 13)
+#define MIPS_CONF1_IA_SHIFT	16
 #define MIPS_CONF1_IA		(_ULCAST_(7) << 16)
+#define MIPS_CONF1_IL_SHIFT	19
 #define MIPS_CONF1_IL		(_ULCAST_(7) << 19)
+#define MIPS_CONF1_IS_SHIFT	22
 #define MIPS_CONF1_IS		(_ULCAST_(7) << 22)
 #define MIPS_CONF1_TLBS		(_ULCAST_(63)<< 25)
 
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 66340ea47046319083cdfc0556b5dc292681b980..1febf2986530744335caea094815032e3915e3f4 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -17,10 +17,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define	LINUX_MAX_ENVS		256
 #define	LINUX_MAX_ARGS		256
 
-#if defined(CONFIG_QEMU_MALTA)
-#define mips_boot_qemu_malta	1
+#if defined(CONFIG_MALTA)
+#define mips_boot_malta		1
 #else
-#define mips_boot_qemu_malta	0
+#define mips_boot_malta		0
 #endif
 
 static int linux_argc;
@@ -139,7 +139,7 @@ static void linux_env_set(const char *env_name, const char *env_val)
 		strcpy(linux_env_p, env_name);
 		linux_env_p += strlen(env_name);
 
-		if (mips_boot_qemu_malta) {
+		if (mips_boot_malta) {
 			linux_env_p++;
 			linux_env[++linux_env_idx] = linux_env_p;
 		} else {
@@ -196,7 +196,7 @@ static void boot_prep_linux(bootm_headers_t *images)
 	if (cp)
 		linux_env_set("eth1addr", cp);
 
-	if (mips_boot_qemu_malta)
+	if (mips_boot_malta)
 		linux_env_set("modetty0", "38400n8r");
 }
 
@@ -210,7 +210,7 @@ static void boot_jump_linux(bootm_headers_t *images)
 
 	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
-	if (mips_boot_qemu_malta)
+	if (mips_boot_malta)
 		linux_extra = gd->ram_size;
 
 	/* we assume that the kernel is in place */
diff --git a/board/qemu-malta/Makefile b/board/imgtec/malta/Makefile
similarity index 81%
rename from board/qemu-malta/Makefile
rename to board/imgtec/malta/Makefile
index 5d727f6f521999f0ba33c2636916ea03fc7f2ace..19dd3a3c3b2d95cf4e7beb351f7281f621ddf76d 100644
--- a/board/qemu-malta/Makefile
+++ b/board/imgtec/malta/Makefile
@@ -5,5 +5,6 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	= qemu-malta.o
+obj-y	= malta.o
 obj-y	+= lowlevel_init.o
+obj-y	+= superio.o
diff --git a/board/imgtec/malta/flash-malta-boot.tcl b/board/imgtec/malta/flash-malta-boot.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..0eedf07acecab57fa612a6e662c2d0fed23e79ad
--- /dev/null
+++ b/board/imgtec/malta/flash-malta-boot.tcl
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2013 Imagination Technologies
+#
+# Programs a MIPS Malta boot flash with a flat binary image.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+proc flash-boot { binfile } {
+  puts "flash monitor binary $binfile"
+  config Coherent on
+  config CoherencyDuringLoad on
+
+  if {[endian]=="big"} {
+    puts "CPU in BE mode"
+    flash device sharp_16x32_be;
+  } else {
+    puts "CPU in LE mode"
+    flash device sharp_16x32;
+  }
+
+  flash clear all;
+  flash set 0xBE000000..0xBE0FFFFF
+  flash erase sector 0xbe000000;
+  flash erase sector 0xbe020000;
+  flash erase sector 0xbe040000;
+  flash erase sector 0xbe060000;
+  flash erase sector 0xbe080000;
+  flash erase sector 0xbe0a0000;
+  flash erase sector 0xbe0c0000;
+  flash erase sector 0xbe0e0000;
+  puts "finished erasing boot flash";
+
+  puts "programming flash, please be patient"
+  load bin 0xbe000000 $binfile size4
+
+  flash clear all
+  config CoherencyDuringLoad off
+  puts "finished programming boot flash";
+}
diff --git a/board/imgtec/malta/lowlevel_init.S b/board/imgtec/malta/lowlevel_init.S
new file mode 100644
index 0000000000000000000000000000000000000000..ae09c27d07ec61d1743e89ceafff94fda82fa2dd
--- /dev/null
+++ b/board/imgtec/malta/lowlevel_init.S
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <config.h>
+#include <gt64120.h>
+#include <msc01.h>
+#include <pci.h>
+
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/malta.h>
+#include <asm/mipsregs.h>
+
+#ifdef CONFIG_SYS_BIG_ENDIAN
+#define CPU_TO_GT32(_x)		((_x))
+#else
+#define CPU_TO_GT32(_x) (					\
+	(((_x) & 0xff) << 24) | (((_x) & 0xff00) << 8) |	\
+	(((_x) & 0xff0000) >> 8) | (((_x) & 0xff000000) >> 24))
+#endif
+
+	.text
+	.set noreorder
+	.set mips32
+
+	.globl	lowlevel_init
+lowlevel_init:
+	/* disable any L2 cache for now */
+	sync
+	mfc0	t0, CP0_CONFIG, 2
+	ori	t0, t0, 0x1 << 12
+	mtc0	t0, CP0_CONFIG, 2
+
+	/* detect the core card */
+	li	t0, KSEG1ADDR(MALTA_REVISION)
+	lw	t0, 0(t0)
+	srl	t0, t0, MALTA_REVISION_CORID_SHF
+	andi	t0, t0, (MALTA_REVISION_CORID_MSK >> \
+			 MALTA_REVISION_CORID_SHF)
+
+	/* core cards using the gt64120 system controller */
+	li	t1, MALTA_REVISION_CORID_CORE_LV
+	beq	t0, t1, _gt64120
+
+	/* core cards using the MSC01 system controller */
+	 li	t1, MALTA_REVISION_CORID_CORE_FPGA6
+	beq	t0, t1, _msc01
+	 nop
+
+	/* unknown system controller */
+	b	.
+	 nop
+
+	/*
+	 * Load BAR registers of GT64120 as done by YAMON
+	 *
+	 * based on a patch sent by Antony Pavlov <antonynpavlov@gmail.com>
+	 * to the barebox mailing list.
+	 * The subject of the original patch:
+	 *   'MIPS: qemu-malta: add YAMON-style GT64120 memory map'
+	 * URL:
+	 * http://www.mail-archive.com/barebox@lists.infradead.org/msg06128.html
+	 *
+	 * based on write_bootloader() in qemu.git/hw/mips_malta.c
+	 * see GT64120 manual and qemu.git/hw/gt64xxx.c for details
+	 */
+_gt64120:
+	/* move GT64120 registers from 0x14000000 to 0x1be00000 */
+	li	t1, KSEG1ADDR(GT_DEF_BASE)
+	li	t0, CPU_TO_GT32(0xdf000000)
+	sw	t0, GT_ISD_OFS(t1)
+
+	/* setup MEM-to-PCI0 mapping */
+	li	t1, KSEG1ADDR(MALTA_GT_BASE)
+
+	/* setup PCI0 io window to 0x18000000-0x181fffff */
+	li	t0, CPU_TO_GT32(0xc0000000)
+	sw	t0, GT_PCI0IOLD_OFS(t1)
+	li	t0, CPU_TO_GT32(0x40000000)
+	sw	t0, GT_PCI0IOHD_OFS(t1)
+
+	/* setup PCI0 mem windows */
+	li	t0, CPU_TO_GT32(0x80000000)
+	sw	t0, GT_PCI0M0LD_OFS(t1)
+	li	t0, CPU_TO_GT32(0x3f000000)
+	sw	t0, GT_PCI0M0HD_OFS(t1)
+
+	li	t0, CPU_TO_GT32(0xc1000000)
+	sw	t0, GT_PCI0M1LD_OFS(t1)
+	li	t0, CPU_TO_GT32(0x5e000000)
+	sw	t0, GT_PCI0M1HD_OFS(t1)
+
+	jr	ra
+	 nop
+
+	/*
+	 *
+	 */
+_msc01:
+	/* setup peripheral bus controller clock divide */
+	li	t0, KSEG1ADDR(MALTA_MSC01_PBC_BASE)
+	li	t1, 0x1 << MSC01_PBC_CLKCFG_SHF
+	sw	t1, MSC01_PBC_CLKCFG_OFS(t0)
+
+	/* tweak peripheral bus controller timings */
+	li	t1, (0x1 << MSC01_PBC_CS0TIM_CDT_SHF) | \
+		    (0x1 << MSC01_PBC_CS0TIM_CAT_SHF)
+	sw	t1, MSC01_PBC_CS0TIM_OFS(t0)
+	li	t1, (0x0 << MSC01_PBC_CS0RW_RDT_SHF) | \
+		    (0x2 << MSC01_PBC_CS0RW_RAT_SHF) | \
+		    (0x0 << MSC01_PBC_CS0RW_WDT_SHF) | \
+		    (0x2 << MSC01_PBC_CS0RW_WAT_SHF)
+	sw	t1, MSC01_PBC_CS0RW_OFS(t0)
+	lw	t1, MSC01_PBC_CS0CFG_OFS(t0)
+	li	t2, MSC01_PBC_CS0CFG_DTYP_MSK
+	and	t1, t2
+	ori	t1, (0x0 << MSC01_PBC_CS0CFG_ADM_SHF) | \
+		    (0x3 << MSC01_PBC_CS0CFG_WSIDLE_SHF) | \
+		    (0x10 << MSC01_PBC_CS0CFG_WS_SHF)
+	sw	t1, MSC01_PBC_CS0CFG_OFS(t0)
+
+	/* setup basic address decode */
+	li	t0, KSEG1ADDR(MALTA_MSC01_BIU_BASE)
+	li	t1, 0x0
+	li	t2, -CONFIG_SYS_MEM_SIZE
+	sw	t1, MSC01_BIU_MCBAS1L_OFS(t0)
+	sw	t2, MSC01_BIU_MCMSK1L_OFS(t0)
+	sw	t1, MSC01_BIU_MCBAS2L_OFS(t0)
+	sw	t2, MSC01_BIU_MCMSK2L_OFS(t0)
+
+	/* initialise IP1 - unused */
+	li	t1, MALTA_MSC01_IP1_BASE
+	li	t2, -MALTA_MSC01_IP1_SIZE
+	sw	t1, MSC01_BIU_IP1BAS1L_OFS(t0)
+	sw	t2, MSC01_BIU_IP1MSK1L_OFS(t0)
+	sw	t1, MSC01_BIU_IP1BAS2L_OFS(t0)
+	sw	t2, MSC01_BIU_IP1MSK2L_OFS(t0)
+
+	/* initialise IP2 - PCI */
+	li	t1, MALTA_MSC01_IP2_BASE1
+	li	t2, -MALTA_MSC01_IP2_SIZE1
+	sw	t1, MSC01_BIU_IP2BAS1L_OFS(t0)
+	sw	t2, MSC01_BIU_IP2MSK1L_OFS(t0)
+	li	t1, MALTA_MSC01_IP2_BASE2
+	li	t2, -MALTA_MSC01_IP2_SIZE2
+	sw	t1, MSC01_BIU_IP2BAS2L_OFS(t0)
+	sw	t2, MSC01_BIU_IP2MSK2L_OFS(t0)
+
+	/* initialise IP3 - peripheral bus controller */
+	li	t1, MALTA_MSC01_IP3_BASE
+	li	t2, -MALTA_MSC01_IP3_SIZE
+	sw	t1, MSC01_BIU_IP3BAS1L_OFS(t0)
+	sw	t2, MSC01_BIU_IP3MSK1L_OFS(t0)
+	sw	t1, MSC01_BIU_IP3BAS2L_OFS(t0)
+	sw	t2, MSC01_BIU_IP3MSK2L_OFS(t0)
+
+	/* setup PCI memory */
+	li	t0, KSEG1ADDR(MALTA_MSC01_PCI_BASE)
+	li	t1, MALTA_MSC01_PCIMEM_BASE
+	li	t2, (-MALTA_MSC01_PCIMEM_SIZE) & MSC01_PCI_SC2PMMSKL_MSK_MSK
+	li	t3, MALTA_MSC01_PCIMEM_MAP
+	sw	t1, MSC01_PCI_SC2PMBASL_OFS(t0)
+	sw	t2, MSC01_PCI_SC2PMMSKL_OFS(t0)
+	sw	t3, MSC01_PCI_SC2PMMAPL_OFS(t0)
+
+	/* setup PCI I/O */
+	li	t1, MALTA_MSC01_PCIIO_BASE
+	li	t2, (-MALTA_MSC01_PCIIO_SIZE) & MSC01_PCI_SC2PIOMSKL_MSK_MSK
+	li	t3, MALTA_MSC01_PCIIO_MAP
+	sw	t1, MSC01_PCI_SC2PIOBASL_OFS(t0)
+	sw	t2, MSC01_PCI_SC2PIOMSKL_OFS(t0)
+	sw	t3, MSC01_PCI_SC2PIOMAPL_OFS(t0)
+
+	/* setup PCI_BAR0 memory window */
+	li	t1, -CONFIG_SYS_MEM_SIZE
+	sw	t1, MSC01_PCI_BAR0_OFS(t0)
+
+	/* setup PCI to SysCon/CPU translation */
+	sw	t1, MSC01_PCI_P2SCMSKL_OFS(t0)
+	sw	zero, MSC01_PCI_P2SCMAPL_OFS(t0)
+
+	/* setup PCI vendor & device IDs */
+	li	t1, (PCI_VENDOR_ID_MIPS << MSC01_PCI_HEAD0_VENDORID_SHF) | \
+		    (PCI_DEVICE_ID_MIPS_MSC01 << MSC01_PCI_HEAD0_DEVICEID_SHF)
+	sw	t1, MSC01_PCI_HEAD0_OFS(t0)
+
+	/* setup PCI subsystem vendor & device IDs */
+	sw	t1, MSC01_PCI_HEAD11_OFS(t0)
+
+	/* setup PCI class, revision */
+	li	t1, (PCI_CLASS_BRIDGE_HOST << MSC01_PCI_HEAD2_CLASS_SHF) | \
+		    (0x1 << MSC01_PCI_HEAD2_REV_SHF)
+	sw	t1, MSC01_PCI_HEAD2_OFS(t0)
+
+	/* ensure a sane setup */
+	sw	zero, MSC01_PCI_HEAD3_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD4_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD5_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD6_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD7_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD8_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD9_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD10_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD12_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD13_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD14_OFS(t0)
+	sw	zero, MSC01_PCI_HEAD15_OFS(t0)
+
+	/* setup PCI command register */
+	li	t1, (PCI_COMMAND_FAST_BACK | \
+		     PCI_COMMAND_SERR | \
+		     PCI_COMMAND_PARITY | \
+		     PCI_COMMAND_MASTER | \
+		     PCI_COMMAND_MEMORY)
+	sw	t1, MSC01_PCI_HEAD1_OFS(t0)
+
+	/* setup PCI byte swapping */
+#ifdef CONFIG_SYS_BIG_ENDIAN
+	li	t1, (0x1 << MSC01_PCI_SWAP_BAR0_BSWAP_SHF) | \
+		    (0x1 << MSC01_PCI_SWAP_IO_BSWAP_SHF)
+	sw	t1, MSC01_PCI_SWAP_OFS(t0)
+#else
+	sw	zero, MSC01_PCI_SWAP_OFS(t0)
+#endif
+
+	/* enable PCI host configuration cycles */
+	lw	t1, MSC01_PCI_CFG_OFS(t0)
+	li	t2, MSC01_PCI_CFG_RA_MSK | \
+		    MSC01_PCI_CFG_G_MSK | \
+		    MSC01_PCI_CFG_EN_MSK
+	or	t1, t1, t2
+	sw	t1, MSC01_PCI_CFG_OFS(t0)
+
+	jr	ra
+	 nop
diff --git a/board/imgtec/malta/malta.c b/board/imgtec/malta/malta.c
new file mode 100644
index 0000000000000000000000000000000000000000..a1a4c0186606656a4bf52fe8fe205c42306d93f3
--- /dev/null
+++ b/board/imgtec/malta/malta.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <pci.h>
+#include <pci_gt64120.h>
+#include <pci_msc01.h>
+#include <rtc.h>
+#include <serial.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/malta.h>
+
+#include "superio.h"
+
+enum core_card {
+	CORE_UNKNOWN,
+	CORE_LV,
+	CORE_FPGA6,
+};
+
+enum sys_con {
+	SYSCON_UNKNOWN,
+	SYSCON_GT64120,
+	SYSCON_MSC01,
+};
+
+static void malta_lcd_puts(const char *str)
+{
+	int i;
+	void *reg = (void *)CKSEG1ADDR(MALTA_ASCIIPOS0);
+
+	/* print up to 8 characters of the string */
+	for (i = 0; i < min(strlen(str), 8); i++) {
+		__raw_writel(str[i], reg);
+		reg += MALTA_ASCIIPOS1 - MALTA_ASCIIPOS0;
+	}
+
+	/* fill the rest of the display with spaces */
+	for (; i < 8; i++) {
+		__raw_writel(' ', reg);
+		reg += MALTA_ASCIIPOS1 - MALTA_ASCIIPOS0;
+	}
+}
+
+static enum core_card malta_core_card(void)
+{
+	u32 corid, rev;
+
+	rev = __raw_readl(CKSEG1ADDR(MALTA_REVISION));
+	corid = (rev & MALTA_REVISION_CORID_MSK) >> MALTA_REVISION_CORID_SHF;
+
+	switch (corid) {
+	case MALTA_REVISION_CORID_CORE_LV:
+		return CORE_LV;
+
+	case MALTA_REVISION_CORID_CORE_FPGA6:
+		return CORE_FPGA6;
+
+	default:
+		return CORE_UNKNOWN;
+	}
+}
+
+static enum sys_con malta_sys_con(void)
+{
+	switch (malta_core_card()) {
+	case CORE_LV:
+		return SYSCON_GT64120;
+
+	case CORE_FPGA6:
+		return SYSCON_MSC01;
+
+	default:
+		return SYSCON_UNKNOWN;
+	}
+}
+
+phys_size_t initdram(int board_type)
+{
+	return CONFIG_SYS_MEM_SIZE;
+}
+
+int checkboard(void)
+{
+	enum core_card core;
+
+	malta_lcd_puts("U-boot");
+	puts("Board: MIPS Malta");
+
+	core = malta_core_card();
+	switch (core) {
+	case CORE_LV:
+		puts(" CoreLV");
+		break;
+
+	case CORE_FPGA6:
+		puts(" CoreFPGA6");
+		break;
+
+	default:
+		puts(" CoreUnknown");
+	}
+
+	putc('\n');
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+
+void _machine_restart(void)
+{
+	void __iomem *reset_base;
+
+	reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE);
+	__raw_writel(GORESET, reset_base);
+}
+
+int board_early_init_f(void)
+{
+	void *io_base;
+
+	/* choose correct PCI I/O base */
+	switch (malta_sys_con()) {
+	case SYSCON_GT64120:
+		io_base = (void *)CKSEG1ADDR(MALTA_GT_PCIIO_BASE);
+		break;
+
+	case SYSCON_MSC01:
+		io_base = (void *)CKSEG1ADDR(MALTA_MSC01_PCIIO_BASE);
+		break;
+
+	default:
+		return -1;
+	}
+
+	/* setup FDC37M817 super I/O controller */
+	malta_superio_init(io_base);
+
+	return 0;
+}
+
+int misc_init_r(void)
+{
+	rtc_reset();
+
+	return 0;
+}
+
+struct serial_device *default_serial_console(void)
+{
+	switch (malta_sys_con()) {
+	case SYSCON_GT64120:
+		return &eserial1_device;
+
+	default:
+	case SYSCON_MSC01:
+		return &eserial2_device;
+	}
+}
+
+void pci_init_board(void)
+{
+	pci_dev_t bdf;
+
+	switch (malta_sys_con()) {
+	case SYSCON_GT64120:
+		set_io_port_base(CKSEG1ADDR(MALTA_GT_PCIIO_BASE));
+
+		gt64120_pci_init((void *)CKSEG1ADDR(MALTA_GT_BASE),
+				 0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE,
+				 0x10000000, 0x10000000, 128 * 1024 * 1024,
+				 0x00000000, 0x00000000, 0x20000);
+		break;
+
+	default:
+	case SYSCON_MSC01:
+		set_io_port_base(CKSEG1ADDR(MALTA_MSC01_PCIIO_BASE));
+
+		msc01_pci_init((void *)CKSEG1ADDR(MALTA_MSC01_PCI_BASE),
+			       0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE,
+			       MALTA_MSC01_PCIMEM_MAP,
+			       CKSEG1ADDR(MALTA_MSC01_PCIMEM_BASE),
+			       MALTA_MSC01_PCIMEM_SIZE, MALTA_MSC01_PCIIO_MAP,
+			       0x00000000, MALTA_MSC01_PCIIO_SIZE);
+		break;
+	}
+
+	bdf = pci_find_device(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82371AB_0, 0);
+	if (bdf == -1)
+		panic("Failed to find PIIX4 PCI bridge\n");
+
+	/* setup PCI interrupt routing */
+	pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCA, 10);
+	pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCB, 10);
+	pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCC, 11);
+	pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCD, 11);
+}
diff --git a/board/imgtec/malta/superio.c b/board/imgtec/malta/superio.c
new file mode 100644
index 0000000000000000000000000000000000000000..eaa14df39e8c9bcaba9605bfcc76a2f2966cf678
--- /dev/null
+++ b/board/imgtec/malta/superio.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * Setup code for the FDC37M817 super I/O controller
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#define SIO_CONF_PORT		0x3f0
+#define SIO_DATA_PORT		0x3f1
+
+enum sio_conf_key {
+	SIOCONF_DEVNUM		= 0x07,
+	SIOCONF_ACTIVATE	= 0x30,
+	SIOCONF_ENTER_SETUP	= 0x55,
+	SIOCONF_BASE_HIGH	= 0x60,
+	SIOCONF_BASE_LOW	= 0x61,
+	SIOCONF_PRIMARY_INT	= 0x70,
+	SIOCONF_EXIT_SETUP	= 0xaa,
+	SIOCONF_MODE		= 0xf0,
+};
+
+static struct {
+	u8 key;
+	u8 data;
+} sio_config[] = {
+	/* tty0 */
+	{ SIOCONF_DEVNUM,	0x04 },
+	{ SIOCONF_BASE_HIGH,	0x03 },
+	{ SIOCONF_BASE_LOW,	0xf8 },
+	{ SIOCONF_MODE,		0x02 },
+	{ SIOCONF_PRIMARY_INT,	0x04 },
+	{ SIOCONF_ACTIVATE,	0x01 },
+
+	/* tty1 */
+	{ SIOCONF_DEVNUM,	0x05 },
+	{ SIOCONF_BASE_HIGH,	0x02 },
+	{ SIOCONF_BASE_LOW,	0xf8 },
+	{ SIOCONF_MODE,		0x02 },
+	{ SIOCONF_PRIMARY_INT,	0x03 },
+	{ SIOCONF_ACTIVATE,	0x01 },
+};
+
+void malta_superio_init(void *io_base)
+{
+	unsigned i;
+
+	/* enter config state */
+	writeb(SIOCONF_ENTER_SETUP, io_base + SIO_CONF_PORT);
+
+	/* configure peripherals */
+	for (i = 0; i < ARRAY_SIZE(sio_config); i++) {
+		writeb(sio_config[i].key, io_base + SIO_CONF_PORT);
+		writeb(sio_config[i].data, io_base + SIO_DATA_PORT);
+	}
+
+	/* exit config state */
+	writeb(SIOCONF_EXIT_SETUP, io_base + SIO_CONF_PORT);
+}
diff --git a/board/imgtec/malta/superio.h b/board/imgtec/malta/superio.h
new file mode 100644
index 0000000000000000000000000000000000000000..1450da56dd38dc63a82c358554d76411d9853cae
--- /dev/null
+++ b/board/imgtec/malta/superio.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * Setup code for the FDC37M817 super I/O controller
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __BOARD_MALTA_SUPERIO_H__
+#define __BOARD_MALTA_SUPERIO_H__
+
+extern void malta_superio_init(void *io_base);
+
+#endif /* __BOARD_MALTA_SUPERIO_H__ */
diff --git a/board/qemu-malta/lowlevel_init.S b/board/qemu-malta/lowlevel_init.S
deleted file mode 100644
index fa0b6a7d132b719531abf49fac82f62ac07ff00a..0000000000000000000000000000000000000000
--- a/board/qemu-malta/lowlevel_init.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
- *
- * SPDX-License-Identifier:	GPL-2.0
- */
-
-#include <config.h>
-#include <gt64120.h>
-
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/malta.h>
-
-#ifdef CONFIG_SYS_BIG_ENDIAN
-#define CPU_TO_GT32(_x)		((_x))
-#else
-#define CPU_TO_GT32(_x) (					\
-	(((_x) & 0xff) << 24) | (((_x) & 0xff00) << 8) |	\
-	(((_x) & 0xff0000) >> 8) | (((_x) & 0xff000000) >> 24))
-#endif
-
-	.text
-	.set noreorder
-	.set mips32
-
-	.globl	lowlevel_init
-lowlevel_init:
-
-	/*
-	 * Load BAR registers of GT64120 as done by YAMON
-	 *
-	 * based on a patch sent by Antony Pavlov <antonynpavlov@gmail.com>
-	 * to the barebox mailing list.
-	 * The subject of the original patch:
-	 *   'MIPS: qemu-malta: add YAMON-style GT64120 memory map'
-	 * URL:
-	 * http://www.mail-archive.com/barebox@lists.infradead.org/msg06128.html
-	 *
-	 * based on write_bootloader() in qemu.git/hw/mips_malta.c
-	 * see GT64120 manual and qemu.git/hw/gt64xxx.c for details
-	 */
-
-	/* move GT64120 registers from 0x14000000 to 0x1be00000 */
-	li	t1, KSEG1ADDR(GT_DEF_BASE)
-	li	t0, CPU_TO_GT32(0xdf000000)
-	sw	t0, GT_ISD_OFS(t1)
-
-	/* setup MEM-to-PCI0 mapping */
-	li	t1, KSEG1ADDR(MALTA_GT_BASE)
-
-	/* setup PCI0 io window to 0x18000000-0x181fffff */
-	li	t0, CPU_TO_GT32(0xc0000000)
-	sw	t0, GT_PCI0IOLD_OFS(t1)
-	li	t0, CPU_TO_GT32(0x40000000)
-	sw	t0, GT_PCI0IOHD_OFS(t1)
-
-	/* setup PCI0 mem windows */
-	li	t0, CPU_TO_GT32(0x80000000)
-	sw	t0, GT_PCI0M0LD_OFS(t1)
-	li	t0, CPU_TO_GT32(0x3f000000)
-	sw	t0, GT_PCI0M0HD_OFS(t1)
-
-	li	t0, CPU_TO_GT32(0xc1000000)
-	sw	t0, GT_PCI0M1LD_OFS(t1)
-	li	t0, CPU_TO_GT32(0x5e000000)
-	sw	t0, GT_PCI0M1HD_OFS(t1)
-
-	jr	ra
-	 nop
diff --git a/board/qemu-malta/qemu-malta.c b/board/qemu-malta/qemu-malta.c
deleted file mode 100644
index 7eddf1ce6646e2d9f5bd795cd2e26fb27d69b82d..0000000000000000000000000000000000000000
--- a/board/qemu-malta/qemu-malta.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org>
- *
- * SPDX-License-Identifier:	GPL-2.0
- */
-
-#include <common.h>
-#include <netdev.h>
-
-#include <asm/addrspace.h>
-#include <asm/io.h>
-#include <asm/malta.h>
-#include <pci_gt64120.h>
-
-phys_size_t initdram(int board_type)
-{
-	return CONFIG_SYS_MEM_SIZE;
-}
-
-int checkboard(void)
-{
-	puts("Board: MIPS Malta CoreLV (Qemu)\n");
-	return 0;
-}
-
-int board_eth_init(bd_t *bis)
-{
-	return pci_eth_init(bis);
-}
-
-void _machine_restart(void)
-{
-	void __iomem *reset_base;
-
-	reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE);
-	__raw_writel(GORESET, reset_base);
-}
-
-void pci_init_board(void)
-{
-	set_io_port_base(CKSEG1ADDR(MALTA_IO_PORT_BASE));
-
-	gt64120_pci_init((void *)CKSEG1ADDR(MALTA_GT_BASE),
-			 0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE,
-			 0x10000000, 0x10000000, 128 * 1024 * 1024,
-			 0x00000000, 0x00000000, 0x20000);
-}
diff --git a/boards.cfg b/boards.cfg
index ce5b686066ed631a52237c4335e8c94649940e8a..7ee63ee3c055ddd02fd14484e275fdb1a46115e4 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -482,10 +482,10 @@ Active  m68k        mcf547x_8x     -           freescale       m548xevb
 Active  m68k        mcf547x_8x     -           freescale       m548xevb            M5485GFE                             M5485EVB:SYS_BUSCLK=100000000,SYS_BOOTSZ=4,SYS_DRAMSZ=64                                                                          TsiChung Liew <Tsi-Chung.Liew@freescale.com>
 Active  m68k        mcf547x_8x     -           freescale       m548xevb            M5485HFE                             M5485EVB:SYS_BUSCLK=100000000,SYS_BOOTSZ=2,SYS_DRAMSZ=64,SYS_NOR1SZ=16,SYS_VIDEO                                                  TsiChung Liew <Tsi-Chung.Liew@freescale.com>
 Active  microblaze  microblaze     -           xilinx          microblaze-generic  microblaze-generic                   -                                                                                                                                 Michal Simek <monstr@monstr.eu>
-Active  mips        mips32         -           -               qemu-malta          qemu_malta                           qemu-malta:MIPS32,SYS_BIG_ENDIAN                                                                                                  -
-Active  mips        mips32         -           -               qemu-malta          qemu_maltael                         qemu-malta:MIPS32,SYS_LITTLE_ENDIAN                                                                                               -
 Active  mips        mips32         -           -               qemu-mips           qemu_mips                            qemu-mips:SYS_BIG_ENDIAN                                                                                                          Vlad Lungu <vlad.lungu@windriver.com>
 Active  mips        mips32         -           -               qemu-mips           qemu_mipsel                          qemu-mips:SYS_LITTLE_ENDIAN                                                                                                       -
+Active  mips        mips32         -           imgtec          malta               malta                                malta:MIPS32,SYS_BIG_ENDIAN                                                                                                       Paul Burton <paul.burton@imgtec.com>
+Active  mips        mips32         -           imgtec          malta               maltael                              malta:MIPS32,SYS_LITTLE_ENDIAN                                                                                                    Paul Burton <paul.burton@imgtec.com>
 Active  mips        mips32         -           micronas        vct                 vct_platinum                         vct:VCT_PLATINUM                                                                                                                  -
 Active  mips        mips32         -           micronas        vct                 vct_platinum_onenand                 vct:VCT_PLATINUM,VCT_ONENAND                                                                                                      -
 Active  mips        mips32         -           micronas        vct                 vct_platinum_onenand_small           vct:VCT_PLATINUM,VCT_ONENAND,VCT_SMALL_IMAGE                                                                                      -
diff --git a/doc/README.malta b/doc/README.malta
new file mode 100644
index 0000000000000000000000000000000000000000..a495d0245595c575f01941cf7cb1796659aad152
--- /dev/null
+++ b/doc/README.malta
@@ -0,0 +1,16 @@
+MIPS Malta board
+
+How to flash using a MIPS Navigator Probe:
+
+  - Ensure that your Malta has jumper JP1 fitted. Without this jumper you will
+    be unable to flash your Malta using a Navigator Probe.
+
+  - Connect Navigator Console to your probe and Malta as usual.
+
+  - Within Navigator Console run the following commands:
+
+      source /path/to/u-boot/board/malta/flash-malta-boot.tcl
+      reset
+      flash-boot /path/to/u-boot/u-boot.bin
+
+  - You should now be able to reboot your Malta to a U-boot shell.
diff --git a/drivers/net/pcnet.c b/drivers/net/pcnet.c
index 283cb48b4e30d4125ba7663e737f70041b16b7d6..5b248bee431ad4caf287bf0550aab8b777255174 100644
--- a/drivers/net/pcnet.c
+++ b/drivers/net/pcnet.c
@@ -89,39 +89,39 @@ static pcnet_priv_t *lp;
 #define PCNET_RESET		0x14
 #define PCNET_BDP		0x16
 
-static u16 pcnet_read_csr (struct eth_device *dev, int index)
+static u16 pcnet_read_csr(struct eth_device *dev, int index)
 {
-	outw (index, dev->iobase + PCNET_RAP);
-	return inw (dev->iobase + PCNET_RDP);
+	outw(index, dev->iobase + PCNET_RAP);
+	return inw(dev->iobase + PCNET_RDP);
 }
 
-static void pcnet_write_csr (struct eth_device *dev, int index, u16 val)
+static void pcnet_write_csr(struct eth_device *dev, int index, u16 val)
 {
-	outw (index, dev->iobase + PCNET_RAP);
-	outw (val, dev->iobase + PCNET_RDP);
+	outw(index, dev->iobase + PCNET_RAP);
+	outw(val, dev->iobase + PCNET_RDP);
 }
 
-static u16 pcnet_read_bcr (struct eth_device *dev, int index)
+static u16 pcnet_read_bcr(struct eth_device *dev, int index)
 {
-	outw (index, dev->iobase + PCNET_RAP);
-	return inw (dev->iobase + PCNET_BDP);
+	outw(index, dev->iobase + PCNET_RAP);
+	return inw(dev->iobase + PCNET_BDP);
 }
 
-static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val)
+static void pcnet_write_bcr(struct eth_device *dev, int index, u16 val)
 {
-	outw (index, dev->iobase + PCNET_RAP);
-	outw (val, dev->iobase + PCNET_BDP);
+	outw(index, dev->iobase + PCNET_RAP);
+	outw(val, dev->iobase + PCNET_BDP);
 }
 
-static void pcnet_reset (struct eth_device *dev)
+static void pcnet_reset(struct eth_device *dev)
 {
-	inw (dev->iobase + PCNET_RESET);
+	inw(dev->iobase + PCNET_RESET);
 }
 
-static int pcnet_check (struct eth_device *dev)
+static int pcnet_check(struct eth_device *dev)
 {
-	outw (88, dev->iobase + PCNET_RAP);
-	return (inw (dev->iobase + PCNET_RAP) == 88);
+	outw(88, dev->iobase + PCNET_RAP);
+	return inw(dev->iobase + PCNET_RAP) == 88;
 }
 
 static int pcnet_init (struct eth_device *dev, bd_t * bis);
@@ -139,63 +139,64 @@ static struct pci_device_id supported[] = {
 };
 
 
-int pcnet_initialize (bd_t * bis)
+int pcnet_initialize(bd_t *bis)
 {
 	pci_dev_t devbusfn;
 	struct eth_device *dev;
 	u16 command, status;
 	int dev_nr = 0;
 
-	PCNET_DEBUG1 ("\npcnet_initialize...\n");
+	PCNET_DEBUG1("\npcnet_initialize...\n");
 
 	for (dev_nr = 0;; dev_nr++) {
 
 		/*
 		 * Find the PCnet PCI device(s).
 		 */
-		if ((devbusfn = pci_find_devices (supported, dev_nr)) < 0) {
+		devbusfn = pci_find_devices(supported, dev_nr);
+		if (devbusfn < 0)
 			break;
-		}
 
 		/*
 		 * Allocate and pre-fill the device structure.
 		 */
-		dev = (struct eth_device *) malloc (sizeof *dev);
+		dev = (struct eth_device *)malloc(sizeof(*dev));
 		if (!dev) {
 			printf("pcnet: Can not allocate memory\n");
 			break;
 		}
 		memset(dev, 0, sizeof(*dev));
-		dev->priv = (void *) devbusfn;
-		sprintf (dev->name, "pcnet#%d", dev_nr);
+		dev->priv = (void *)devbusfn;
+		sprintf(dev->name, "pcnet#%d", dev_nr);
 
 		/*
 		 * Setup the PCI device.
 		 */
-		pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0,
-				       (unsigned int *) &dev->iobase);
-		dev->iobase=pci_io_to_phys (devbusfn, dev->iobase);
+		pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0,
+				      (unsigned int *)&dev->iobase);
+		dev->iobase = pci_io_to_phys(devbusfn, dev->iobase);
 		dev->iobase &= ~0xf;
 
-		PCNET_DEBUG1 ("%s: devbusfn=0x%x iobase=0x%x: ",
-			      dev->name, devbusfn, dev->iobase);
+		PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ",
+			     dev->name, devbusfn, dev->iobase);
 
 		command = PCI_COMMAND_IO | PCI_COMMAND_MASTER;
-		pci_write_config_word (devbusfn, PCI_COMMAND, command);
-		pci_read_config_word (devbusfn, PCI_COMMAND, &status);
+		pci_write_config_word(devbusfn, PCI_COMMAND, command);
+		pci_read_config_word(devbusfn, PCI_COMMAND, &status);
 		if ((status & command) != command) {
-			printf ("%s: Couldn't enable IO access or Bus Mastering\n", dev->name);
-			free (dev);
+			printf("%s: Couldn't enable IO access or Bus Mastering\n",
+			       dev->name);
+			free(dev);
 			continue;
 		}
 
-		pci_write_config_byte (devbusfn, PCI_LATENCY_TIMER, 0x40);
+		pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40);
 
 		/*
 		 * Probe the PCnet chip.
 		 */
-		if (pcnet_probe (dev, bis, dev_nr) < 0) {
-			free (dev);
+		if (pcnet_probe(dev, bis, dev_nr) < 0) {
+			free(dev);
 			continue;
 		}
 
@@ -207,15 +208,15 @@ int pcnet_initialize (bd_t * bis)
 		dev->send = pcnet_send;
 		dev->recv = pcnet_recv;
 
-		eth_register (dev);
+		eth_register(dev);
 	}
 
-	udelay (10 * 1000);
+	udelay(10 * 1000);
 
 	return dev_nr;
 }
 
-static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_nr)
+static int pcnet_probe(struct eth_device *dev, bd_t *bis, int dev_nr)
 {
 	int chip_version;
 	char *chipname;
@@ -225,17 +226,17 @@ static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_nr)
 #endif
 
 	/* Reset the PCnet controller */
-	pcnet_reset (dev);
+	pcnet_reset(dev);
 
 	/* Check if register access is working */
-	if (pcnet_read_csr (dev, 0) != 4 || !pcnet_check (dev)) {
-		printf ("%s: CSR register access check failed\n", dev->name);
+	if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) {
+		printf("%s: CSR register access check failed\n", dev->name);
 		return -1;
 	}
 
 	/* Identify the chip */
 	chip_version =
-		pcnet_read_csr (dev, 88) | (pcnet_read_csr (dev, 89) << 16);
+		pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev, 89) << 16);
 	if ((chip_version & 0xfff) != 0x003)
 		return -1;
 	chip_version = (chip_version >> 12) & 0xffff;
@@ -254,12 +255,12 @@ static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_nr)
 		break;
 #endif
 	default:
-		printf ("%s: PCnet version %#x not supported\n",
-			dev->name, chip_version);
+		printf("%s: PCnet version %#x not supported\n",
+		       dev->name, chip_version);
 		return -1;
 	}
 
-	PCNET_DEBUG1 ("AMD %s\n", chipname);
+	PCNET_DEBUG1("AMD %s\n", chipname);
 
 #ifdef PCNET_HAS_PROM
 	/*
@@ -270,7 +271,7 @@ static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_nr)
 	for (i = 0; i < 3; i++) {
 		unsigned int val;
 
-		val = pcnet_read_csr (dev, i + 12) & 0x0ffff;
+		val = pcnet_read_csr(dev, i + 12) & 0x0ffff;
 		/* There may be endianness issues here. */
 		dev->enetaddr[2 * i] = val & 0x0ff;
 		dev->enetaddr[2 * i + 1] = (val >> 8) & 0x0ff;
@@ -280,35 +281,50 @@ static int pcnet_probe (struct eth_device *dev, bd_t * bis, int dev_nr)
 	return 0;
 }
 
-static int pcnet_init (struct eth_device *dev, bd_t * bis)
+static int pcnet_init(struct eth_device *dev, bd_t *bis)
 {
 	int i, val;
 	u32 addr;
 
-	PCNET_DEBUG1 ("%s: pcnet_init...\n", dev->name);
+	PCNET_DEBUG1("%s: pcnet_init...\n", dev->name);
 
 	/* Switch pcnet to 32bit mode */
-	pcnet_write_bcr (dev, 20, 2);
+	pcnet_write_bcr(dev, 20, 2);
 
 #ifdef CONFIG_PN62
 	/* Setup LED registers */
-	val = pcnet_read_bcr (dev, 2) | 0x1000;
-	pcnet_write_bcr (dev, 2, val);	/* enable LEDPE */
-	pcnet_write_bcr (dev, 4, 0x5080);	/* 100MBit */
-	pcnet_write_bcr (dev, 5, 0x40c0);	/* LNKSE */
-	pcnet_write_bcr (dev, 6, 0x4090);	/* TX Activity */
-	pcnet_write_bcr (dev, 7, 0x4084);	/* RX Activity */
+	val = pcnet_read_bcr(dev, 2) | 0x1000;
+	pcnet_write_bcr(dev, 2, val);	/* enable LEDPE */
+	pcnet_write_bcr(dev, 4, 0x5080);	/* 100MBit */
+	pcnet_write_bcr(dev, 5, 0x40c0);	/* LNKSE */
+	pcnet_write_bcr(dev, 6, 0x4090);	/* TX Activity */
+	pcnet_write_bcr(dev, 7, 0x4084);	/* RX Activity */
 #endif
 
 	/* Set/reset autoselect bit */
-	val = pcnet_read_bcr (dev, 2) & ~2;
+	val = pcnet_read_bcr(dev, 2) & ~2;
 	val |= 2;
-	pcnet_write_bcr (dev, 2, val);
+	pcnet_write_bcr(dev, 2, val);
 
 	/* Enable auto negotiate, setup, disable fd */
-	val = pcnet_read_bcr (dev, 32) & ~0x98;
+	val = pcnet_read_bcr(dev, 32) & ~0x98;
 	val |= 0x20;
-	pcnet_write_bcr (dev, 32, val);
+	pcnet_write_bcr(dev, 32, val);
+
+	/*
+	 * Enable NOUFLO on supported controllers, with the transmit
+	 * start point set to the full packet. This will cause entire
+	 * packets to be buffered by the ethernet controller before
+	 * transmission, eliminating underflows which are common on
+	 * slower devices. Controllers which do not support NOUFLO will
+	 * simply be left with a larger transmit FIFO threshold.
+	 */
+	val = pcnet_read_bcr(dev, 18);
+	val |= 1 << 11;
+	pcnet_write_bcr(dev, 18, val);
+	val = pcnet_read_csr(dev, 80);
+	val |= 0x3 << 10;
+	pcnet_write_csr(dev, 80, val);
 
 	/*
 	 * We only maintain one structure because the drivers will never
@@ -316,12 +332,12 @@ static int pcnet_init (struct eth_device *dev, bd_t * bis)
 	 * must be aligned on 16-byte boundaries.
 	 */
 	if (lp == NULL) {
-		addr = (u32) malloc (sizeof (pcnet_priv_t) + 0x10);
+		addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10);
 		addr = (addr + 0xf) & ~0xf;
-		lp = (pcnet_priv_t *) addr;
+		lp = (pcnet_priv_t *)addr;
 	}
 
-	lp->init_block.mode = cpu_to_le16 (0x0000);
+	lp->init_block.mode = cpu_to_le16(0x0000);
 	lp->init_block.filter[0] = 0x00000000;
 	lp->init_block.filter[1] = 0x00000000;
 
@@ -330,9 +346,9 @@ static int pcnet_init (struct eth_device *dev, bd_t * bis)
 	 */
 	lp->cur_rx = 0;
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		lp->rx_ring[i].base = PCI_TO_MEM_LE (dev, lp->rx_buf[i]);
-		lp->rx_ring[i].buf_length = cpu_to_le16 (-PKT_BUF_SZ);
-		lp->rx_ring[i].status = cpu_to_le16 (0x8000);
+		lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);
+		lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
+		lp->rx_ring[i].status = cpu_to_le16(0x8000);
 		PCNET_DEBUG1
 			("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n", i,
 			 lp->rx_ring[i].base, lp->rx_ring[i].buf_length,
@@ -352,48 +368,49 @@ static int pcnet_init (struct eth_device *dev, bd_t * bis)
 	/*
 	 * Setup Init Block.
 	 */
-	PCNET_DEBUG1 ("Init block at 0x%p: MAC", &lp->init_block);
+	PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->init_block);
 
 	for (i = 0; i < 6; i++) {
 		lp->init_block.phys_addr[i] = dev->enetaddr[i];
-		PCNET_DEBUG1 (" %02x", lp->init_block.phys_addr[i]);
+		PCNET_DEBUG1(" %02x", lp->init_block.phys_addr[i]);
 	}
 
-	lp->init_block.tlen_rlen = cpu_to_le16 (TX_RING_LEN_BITS |
-						RX_RING_LEN_BITS);
-	lp->init_block.rx_ring = PCI_TO_MEM_LE (dev, lp->rx_ring);
-	lp->init_block.tx_ring = PCI_TO_MEM_LE (dev, lp->tx_ring);
+	lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS |
+					       RX_RING_LEN_BITS);
+	lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
+	lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);
+	flush_dcache_range((unsigned long)lp, (unsigned long)&lp->rx_buf);
 
-	PCNET_DEBUG1 ("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
-		      lp->init_block.tlen_rlen,
-		      lp->init_block.rx_ring, lp->init_block.tx_ring);
+	PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
+		     lp->init_block.tlen_rlen,
+		     lp->init_block.rx_ring, lp->init_block.tx_ring);
 
 	/*
 	 * Tell the controller where the Init Block is located.
 	 */
-	addr = PCI_TO_MEM (dev, &lp->init_block);
-	pcnet_write_csr (dev, 1, addr & 0xffff);
-	pcnet_write_csr (dev, 2, (addr >> 16) & 0xffff);
+	addr = PCI_TO_MEM(dev, &lp->init_block);
+	pcnet_write_csr(dev, 1, addr & 0xffff);
+	pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff);
 
-	pcnet_write_csr (dev, 4, 0x0915);
-	pcnet_write_csr (dev, 0, 0x0001);	/* start */
+	pcnet_write_csr(dev, 4, 0x0915);
+	pcnet_write_csr(dev, 0, 0x0001);	/* start */
 
 	/* Wait for Init Done bit */
 	for (i = 10000; i > 0; i--) {
-		if (pcnet_read_csr (dev, 0) & 0x0100)
+		if (pcnet_read_csr(dev, 0) & 0x0100)
 			break;
-		udelay (10);
+		udelay(10);
 	}
 	if (i <= 0) {
-		printf ("%s: TIMEOUT: controller init failed\n", dev->name);
-		pcnet_reset (dev);
+		printf("%s: TIMEOUT: controller init failed\n", dev->name);
+		pcnet_reset(dev);
 		return -1;
 	}
 
 	/*
 	 * Finally start network controller operation.
 	 */
-	pcnet_write_csr (dev, 0, 0x0002);
+	pcnet_write_csr(dev, 0, 0x0002);
 
 	return 0;
 }
@@ -403,20 +420,25 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len)
 	int i, status;
 	struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx];
 
-	PCNET_DEBUG2 ("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len,
-		      packet);
+	PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len,
+		     packet);
+
+	flush_dcache_range((unsigned long)packet,
+			   (unsigned long)packet + pkt_len);
 
 	/* Wait for completion by testing the OWN bit */
 	for (i = 1000; i > 0; i--) {
-		status = le16_to_cpu (entry->status);
+		invalidate_dcache_range((unsigned long)entry,
+					(unsigned long)entry + sizeof(*entry));
+		status = le16_to_cpu(entry->status);
 		if ((status & 0x8000) == 0)
 			break;
-		udelay (100);
-		PCNET_DEBUG2 (".");
+		udelay(100);
+		PCNET_DEBUG2(".");
 	}
 	if (i <= 0) {
-		printf ("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n",
-			dev->name, lp->cur_tx, status);
+		printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n",
+		       dev->name, lp->cur_tx, status);
 		pkt_len = 0;
 		goto failure;
 	}
@@ -426,19 +448,21 @@ static int pcnet_send(struct eth_device *dev, void *packet, int pkt_len)
 	 * set the status with the "ownership" bits last.
 	 */
 	status = 0x8300;
-	entry->length = le16_to_cpu (-pkt_len);
+	entry->length = cpu_to_le16(-pkt_len);
 	entry->misc = 0x00000000;
-	entry->base = PCI_TO_MEM_LE (dev, packet);
-	entry->status = le16_to_cpu (status);
+	entry->base = PCI_TO_MEM_LE(dev, packet);
+	entry->status = cpu_to_le16(status);
+	flush_dcache_range((unsigned long)entry,
+			   (unsigned long)entry + sizeof(*entry));
 
 	/* Trigger an immediate send poll. */
-	pcnet_write_csr (dev, 0, 0x0008);
+	pcnet_write_csr(dev, 0, 0x0008);
 
       failure:
 	if (++lp->cur_tx >= TX_RING_SIZE)
 		lp->cur_tx = 0;
 
-	PCNET_DEBUG2 ("done\n");
+	PCNET_DEBUG2("done\n");
 	return pkt_len;
 }
 
@@ -450,43 +474,49 @@ static int pcnet_recv (struct eth_device *dev)
 
 	while (1) {
 		entry = &lp->rx_ring[lp->cur_rx];
+		invalidate_dcache_range((unsigned long)entry,
+					(unsigned long)entry + sizeof(*entry));
 		/*
 		 * If we own the next entry, it's a new packet. Send it up.
 		 */
-		if (((status = le16_to_cpu (entry->status)) & 0x8000) != 0) {
+		status = le16_to_cpu(entry->status);
+		if ((status & 0x8000) != 0)
 			break;
-		}
 		status >>= 8;
 
 		if (status != 0x03) {	/* There was an error. */
-
-			printf ("%s: Rx%d", dev->name, lp->cur_rx);
-			PCNET_DEBUG1 (" (status=0x%x)", status);
+			printf("%s: Rx%d", dev->name, lp->cur_rx);
+			PCNET_DEBUG1(" (status=0x%x)", status);
 			if (status & 0x20)
-				printf (" Frame");
+				printf(" Frame");
 			if (status & 0x10)
-				printf (" Overflow");
+				printf(" Overflow");
 			if (status & 0x08)
-				printf (" CRC");
+				printf(" CRC");
 			if (status & 0x04)
-				printf (" Fifo");
-			printf (" Error\n");
-			entry->status &= le16_to_cpu (0x03ff);
+				printf(" Fifo");
+			printf(" Error\n");
+			entry->status &= le16_to_cpu(0x03ff);
 
 		} else {
-
-			pkt_len =
-				(le32_to_cpu (entry->msg_length) & 0xfff) - 4;
+			pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4;
 			if (pkt_len < 60) {
-				printf ("%s: Rx%d: invalid packet length %d\n", dev->name, lp->cur_rx, pkt_len);
+				printf("%s: Rx%d: invalid packet length %d\n",
+				       dev->name, lp->cur_rx, pkt_len);
 			} else {
-				NetReceive (lp->rx_buf[lp->cur_rx], pkt_len);
-				PCNET_DEBUG2 ("Rx%d: %d bytes from 0x%p\n",
-					      lp->cur_rx, pkt_len,
-					      lp->rx_buf[lp->cur_rx]);
+				invalidate_dcache_range(
+					(unsigned long)lp->rx_buf[lp->cur_rx],
+					(unsigned long)lp->rx_buf[lp->cur_rx] +
+					pkt_len);
+				NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
+				PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n",
+					     lp->cur_rx, pkt_len,
+					     lp->rx_buf[lp->cur_rx]);
 			}
 		}
-		entry->status |= cpu_to_le16 (0x8000);
+		entry->status |= cpu_to_le16(0x8000);
+		flush_dcache_range((unsigned long)entry,
+				   (unsigned long)entry + sizeof(*entry));
 
 		if (++lp->cur_rx >= RX_RING_SIZE)
 			lp->cur_rx = 0;
@@ -494,22 +524,21 @@ static int pcnet_recv (struct eth_device *dev)
 	return pkt_len;
 }
 
-static void pcnet_halt (struct eth_device *dev)
+static void pcnet_halt(struct eth_device *dev)
 {
 	int i;
 
-	PCNET_DEBUG1 ("%s: pcnet_halt...\n", dev->name);
+	PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name);
 
 	/* Reset the PCnet controller */
-	pcnet_reset (dev);
+	pcnet_reset(dev);
 
 	/* Wait for Stop bit */
 	for (i = 1000; i > 0; i--) {
-		if (pcnet_read_csr (dev, 0) & 0x4)
+		if (pcnet_read_csr(dev, 0) & 0x4)
 			break;
-		udelay (10);
-	}
-	if (i <= 0) {
-		printf ("%s: TIMEOUT: controller reset failed\n", dev->name);
+		udelay(10);
 	}
+	if (i <= 0)
+		printf("%s: TIMEOUT: controller reset failed\n", dev->name);
 }
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 99d51a6a976ba9476639804805d07497839016ff..6182a5904dbd059d70a5eb7de58976bb6b0a978a 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
 obj-$(CONFIG_PCI) += pci.o pci_auto.o
 obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
 obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
+obj-$(CONFIG_PCI_MSC01) += pci_msc01.o
 obj-$(CONFIG_FTPCI100) += pci_ftpci100.o
 obj-$(CONFIG_IXP_PCI) += pci_ixp.o
 obj-$(CONFIG_SH4_PCI) += pci_sh4.o
diff --git a/drivers/pci/pci_msc01.c b/drivers/pci/pci_msc01.c
new file mode 100644
index 0000000000000000000000000000000000000000..284ffa09b62f1ea49720e0304512bf7f0269cb03
--- /dev/null
+++ b/drivers/pci/pci_msc01.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <msc01.h>
+#include <pci.h>
+#include <pci_msc01.h>
+#include <asm/io.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+struct msc01_pci_controller {
+	struct pci_controller hose;
+	void *base;
+};
+
+static inline struct msc01_pci_controller *
+hose_to_msc01(struct pci_controller *hose)
+{
+	return container_of(hose, struct msc01_pci_controller, hose);
+}
+
+static int msc01_config_access(struct msc01_pci_controller *msc01,
+			       unsigned char access_type, pci_dev_t bdf,
+			       int where, u32 *data)
+{
+	const u32 aborts = MSC01_PCI_INTSTAT_MA_MSK | MSC01_PCI_INTSTAT_TA_MSK;
+	void *intstat = msc01->base + MSC01_PCI_INTSTAT_OFS;
+	void *cfgdata = msc01->base + MSC01_PCI_CFGDATA_OFS;
+	unsigned int bus = PCI_BUS(bdf);
+	unsigned int dev = PCI_DEV(bdf);
+	unsigned int devfn = PCI_DEV(bdf) << 3 | PCI_FUNC(bdf);
+
+	/* clear abort status */
+	__raw_writel(aborts, intstat);
+
+	/* setup address */
+	__raw_writel((bus << MSC01_PCI_CFGADDR_BNUM_SHF) |
+		     (dev << MSC01_PCI_CFGADDR_DNUM_SHF) |
+		     (devfn << MSC01_PCI_CFGADDR_FNUM_SHF) |
+		     ((where / 4) << MSC01_PCI_CFGADDR_RNUM_SHF),
+		     msc01->base + MSC01_PCI_CFGADDR_OFS);
+
+	/* perform access */
+	if (access_type == PCI_ACCESS_WRITE)
+		__raw_writel(*data, cfgdata);
+	else
+		*data = __raw_readl(cfgdata);
+
+	/* check for aborts */
+	if (__raw_readl(intstat) & aborts) {
+		/* clear abort status */
+		__raw_writel(aborts, intstat);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int msc01_read_config_dword(struct pci_controller *hose, pci_dev_t dev,
+				   int where, u32 *value)
+{
+	struct msc01_pci_controller *msc01 = hose_to_msc01(hose);
+
+	*value = 0xffffffff;
+	return msc01_config_access(msc01, PCI_ACCESS_READ, dev, where, value);
+}
+
+static int msc01_write_config_dword(struct pci_controller *hose, pci_dev_t dev,
+				    int where, u32 value)
+{
+	struct msc01_pci_controller *gt = hose_to_msc01(hose);
+	u32 data = value;
+
+	return msc01_config_access(gt, PCI_ACCESS_WRITE, dev, where, &data);
+}
+
+void msc01_pci_init(void *base, unsigned long sys_bus, unsigned long sys_phys,
+		    unsigned long sys_size, unsigned long mem_bus,
+		    unsigned long mem_phys, unsigned long mem_size,
+		    unsigned long io_bus, unsigned long io_phys,
+		    unsigned long io_size)
+{
+	static struct msc01_pci_controller global_msc01;
+	struct msc01_pci_controller *msc01;
+	struct pci_controller *hose;
+
+	msc01 = &global_msc01;
+	msc01->base = base;
+
+	hose = &msc01->hose;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0;
+
+	/* System memory space */
+	pci_set_region(&hose->regions[0], sys_bus, sys_phys, sys_size,
+		       PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+	/* PCI memory space */
+	pci_set_region(&hose->regions[1], mem_bus, mem_phys, mem_size,
+		       PCI_REGION_MEM);
+
+	/* PCI I/O space */
+	pci_set_region(&hose->regions[2], io_bus, io_phys, io_size,
+		       PCI_REGION_IO);
+
+	hose->region_count = 3;
+
+	pci_set_ops(hose,
+		    pci_hose_read_config_byte_via_dword,
+		    pci_hose_read_config_word_via_dword,
+		    msc01_read_config_dword,
+		    pci_hose_write_config_byte_via_dword,
+		    pci_hose_write_config_word_via_dword,
+		    msc01_write_config_dword);
+
+	pci_register_hose(hose);
+	hose->last_busno = pci_hose_scan(hose);
+}
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index 5f9d359590b592658c63eae13a08b77037623535..f7cf1064f9052de9b2e56fcc7de3d53544826efa 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -15,7 +15,7 @@
 #include <command.h>
 #include <rtc.h>
 
-#ifdef __I386__
+#if defined(__I386__) || defined(CONFIG_MALTA)
 #include <asm/io.h>
 #define in8(p) inb(p)
 #define out8(p, v) outb(v, p)
diff --git a/include/configs/qemu-malta.h b/include/configs/malta.h
similarity index 72%
rename from include/configs/qemu-malta.h
rename to include/configs/malta.h
index 03514d165be9a6917ff4ee7e5ed3b4932bd3b114..4098e724fef68a7e4cc9865e746a6221a9fcf697 100644
--- a/include/configs/qemu-malta.h
+++ b/include/configs/malta.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier:	GPL-2.0
  */
 
-#ifndef _QEMU_MALTA_CONFIG_H
-#define _QEMU_MALTA_CONFIG_H
+#ifndef _MALTA_CONFIG_H
+#define _MALTA_CONFIG_H
 
 #include <asm/addrspace.h>
 #include <asm/malta.h>
@@ -13,12 +13,21 @@
 /*
  * System configuration
  */
-#define CONFIG_QEMU_MALTA
+#define CONFIG_MALTA
+
+#define CONFIG_MEMSIZE_IN_BYTES
 
 #define CONFIG_PCI
 #define CONFIG_PCI_GT64120
+#define CONFIG_PCI_MSC01
 #define CONFIG_PCI_PNP
 #define CONFIG_PCNET
+#define CONFIG_PCNET_79C973
+#define PCNET_HAS_PROM
+
+#define CONFIG_MISC_INIT_R
+#define CONFIG_RTC_MC146818
+#define CONFIG_SYS_ISA_IO_BASE_ADDRESS	0
 
 /*
  * CPU Configuration
@@ -26,10 +35,6 @@
 #define CONFIG_SYS_MHZ			250	/* arbitrary value */
 #define CONFIG_SYS_MIPS_TIMER_FREQ	(CONFIG_SYS_MHZ * 1000000)
 
-#define CONFIG_SYS_DCACHE_SIZE		16384	/* arbitrary value */
-#define CONFIG_SYS_ICACHE_SIZE		16384	/* arbitrary value */
-#define CONFIG_SYS_CACHELINE_SIZE	32	/* arbitrary value */
-
 #define CONFIG_SWAP_IO_SPACE
 
 /*
@@ -54,9 +59,9 @@
  * Console configuration
  */
 #if defined(CONFIG_SYS_LITTLE_ENDIAN)
-#define CONFIG_SYS_PROMPT		"qemu-maltael # "
+#define CONFIG_SYS_PROMPT		"maltael # "
 #else
-#define CONFIG_SYS_PROMPT		"qemu-malta # "
+#define CONFIG_SYS_PROMPT		"malta # "
 #endif
 
 #define CONFIG_SYS_CBSIZE		256
@@ -76,15 +81,10 @@
 #define CONFIG_SYS_NS16550_SERIAL
 #define CONFIG_SYS_NS16550_REG_SIZE	1
 #define CONFIG_SYS_NS16550_CLK		115200
-#define CONFIG_SYS_NS16550_COM1		CKSEG1ADDR(MALTA_UART_BASE)
+#define CONFIG_SYS_NS16550_COM1		CKSEG1ADDR(MALTA_GT_UART0_BASE)
+#define CONFIG_SYS_NS16550_COM2		CKSEG1ADDR(MALTA_MSC01_UART0_BASE)
 #define CONFIG_CONS_INDEX		1
 
-/*
- * Environment
- */
-#define CONFIG_ENV_IS_NOWHERE
-#define CONFIG_ENV_SIZE			0x10000
-
 /*
  * Flash configuration
  */
@@ -95,6 +95,15 @@
 #define CONFIG_FLASH_CFI_DRIVER
 #define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
 
+/*
+ * Environment
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_SECT_SIZE		0x20000
+#define CONFIG_ENV_SIZE			CONFIG_ENV_SECT_SIZE
+#define CONFIG_ENV_ADDR \
+	(CONFIG_SYS_FLASH_BASE + (4 << 20) - CONFIG_ENV_SIZE)
+
 /*
  * Commands
  */
@@ -105,9 +114,11 @@
 #undef CONFIG_CMD_LOADS
 #undef CONFIG_CMD_NFS
 
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_PING
 
 #define CONFIG_SYS_LONGHELP		/* verbose help, undef to save memory */
 
-#endif /* _QEMU_MALTA_CONFIG_H */
+#endif /* _MALTA_CONFIG_H */
diff --git a/include/msc01.h b/include/msc01.h
new file mode 100644
index 0000000000000000000000000000000000000000..37cf963f133e41b3a98d390b03ea587450be9f03
--- /dev/null
+++ b/include/msc01.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __MSC01_H__
+#define __MSC01_H__
+
+/*
+ * Bus Interface Unit
+ */
+
+#define MSC01_BIU_IP1BAS1L_OFS		0x0208
+#define MSC01_BIU_IP1MSK1L_OFS		0x0218
+#define MSC01_BIU_IP1BAS2L_OFS		0x0248
+#define MSC01_BIU_IP1MSK2L_OFS		0x0258
+#define MSC01_BIU_IP2BAS1L_OFS		0x0288
+#define MSC01_BIU_IP2MSK1L_OFS		0x0298
+#define MSC01_BIU_IP2BAS2L_OFS		0x02c8
+#define MSC01_BIU_IP2MSK2L_OFS		0x02d8
+#define MSC01_BIU_IP3BAS1L_OFS		0x0308
+#define MSC01_BIU_IP3MSK1L_OFS		0x0318
+#define MSC01_BIU_IP3BAS2L_OFS		0x0348
+#define MSC01_BIU_IP3MSK2L_OFS		0x0358
+#define MSC01_BIU_MCBAS1L_OFS		0x0388
+#define MSC01_BIU_MCMSK1L_OFS		0x0398
+#define MSC01_BIU_MCBAS2L_OFS		0x03c8
+#define MSC01_BIU_MCMSK2L_OFS		0x03d8
+
+/*
+ * PCI Bridge
+ */
+
+#define MSC01_PCI_SC2PMBASL_OFS		0x0208
+#define MSC01_PCI_SC2PMMSKL_OFS		0x0218
+#define MSC01_PCI_SC2PMMAPL_OFS		0x0228
+#define MSC01_PCI_SC2PIOBASL_OFS	0x0248
+#define MSC01_PCI_SC2PIOMSKL_OFS	0x0258
+#define MSC01_PCI_SC2PIOMAPL_OFS	0x0268
+#define MSC01_PCI_P2SCMSKL_OFS		0x0308
+#define MSC01_PCI_P2SCMAPL_OFS		0x0318
+#define MSC01_PCI_INTSTAT_OFS		0x0608
+#define MSC01_PCI_CFGADDR_OFS		0x0610
+#define MSC01_PCI_CFGDATA_OFS		0x0618
+#define MSC01_PCI_HEAD0_OFS		0x2000
+#define MSC01_PCI_HEAD1_OFS		0x2008
+#define MSC01_PCI_HEAD2_OFS		0x2010
+#define MSC01_PCI_HEAD3_OFS		0x2018
+#define MSC01_PCI_HEAD4_OFS		0x2020
+#define MSC01_PCI_HEAD5_OFS		0x2028
+#define MSC01_PCI_HEAD6_OFS		0x2030
+#define MSC01_PCI_HEAD7_OFS		0x2038
+#define MSC01_PCI_HEAD8_OFS		0x2040
+#define MSC01_PCI_HEAD9_OFS		0x2048
+#define MSC01_PCI_HEAD10_OFS		0x2050
+#define MSC01_PCI_HEAD11_OFS		0x2058
+#define MSC01_PCI_HEAD12_OFS		0x2060
+#define MSC01_PCI_HEAD13_OFS		0x2068
+#define MSC01_PCI_HEAD14_OFS		0x2070
+#define MSC01_PCI_HEAD15_OFS		0x2078
+#define MSC01_PCI_BAR0_OFS		0x2220
+#define MSC01_PCI_CFG_OFS		0x2380
+#define MSC01_PCI_SWAP_OFS		0x2388
+
+#define MSC01_PCI_SC2PMMSKL_MSK_MSK	0xff000000
+#define MSC01_PCI_SC2PIOMSKL_MSK_MSK	0xff000000
+
+#define MSC01_PCI_INTSTAT_TA_SHF	6
+#define MSC01_PCI_INTSTAT_TA_MSK	(0x1 << MSC01_PCI_INTSTAT_TA_SHF)
+#define MSC01_PCI_INTSTAT_MA_SHF	7
+#define MSC01_PCI_INTSTAT_MA_MSK	(0x1 << MSC01_PCI_INTSTAT_MA_SHF)
+
+#define MSC01_PCI_CFGADDR_BNUM_SHF	16
+#define MSC01_PCI_CFGADDR_BNUM_MSK	(0xff << MSC01_PCI_CFGADDR_BNUM_SHF)
+#define MSC01_PCI_CFGADDR_DNUM_SHF	11
+#define MSC01_PCI_CFGADDR_DNUM_MSK	(0x1f << MSC01_PCI_CFGADDR_DNUM_SHF)
+#define MSC01_PCI_CFGADDR_FNUM_SHF	8
+#define MSC01_PCI_CFGADDR_FNUM_MSK	(0x3 << MSC01_PCI_CFGADDR_FNUM_SHF)
+#define MSC01_PCI_CFGADDR_RNUM_SHF	2
+#define MSC01_PCI_CFGADDR_RNUM_MSK	(0x3f << MSC01_PCI_CFGADDR_RNUM_SHF)
+
+#define MSC01_PCI_HEAD0_VENDORID_SHF	0
+#define MSC01_PCI_HEAD0_DEVICEID_SHF	16
+
+#define MSC01_PCI_HEAD2_REV_SHF		0
+#define MSC01_PCI_HEAD2_CLASS_SHF	16
+
+#define MSC01_PCI_CFG_EN_SHF		15
+#define MSC01_PCI_CFG_EN_MSK		(0x1 << MSC01_PCI_CFG_EN_SHF)
+#define MSC01_PCI_CFG_G_SHF		16
+#define MSC01_PCI_CFG_G_MSK		(0x1 << MSC01_PCI_CFG_G_SHF)
+#define MSC01_PCI_CFG_RA_SHF		17
+#define MSC01_PCI_CFG_RA_MSK		(0x1 << MSC01_PCI_CFG_RA_SHF)
+
+#define MSC01_PCI_SWAP_BAR0_BSWAP_SHF	0
+#define MSC01_PCI_SWAP_IO_BSWAP_SHF	18
+
+/*
+ * Peripheral Bus Controller
+ */
+
+#define MSC01_PBC_CLKCFG_OFS		0x0100
+#define MSC01_PBC_CS0CFG_OFS		0x0400
+#define MSC01_PBC_CS0TIM_OFS		0x0500
+#define MSC01_PBC_CS0RW_OFS		0x0600
+
+#define MSC01_PBC_CLKCFG_SHF		0
+#define MSC01_PBC_CLKCFG_MSK		(0x1f << MSC01_PBC_CLKCFG_SHF)
+
+#define MSC01_PBC_CS0CFG_WS_SHF		0
+#define MSC01_PBC_CS0CFG_WS_MSK		(0x1f << MSC01_PBC_CS0CFG_WS_SHF)
+#define MSC01_PBC_CS0CFG_WSIDLE_SHF	8
+#define MSC01_PBC_CS0CFG_WSIDLE_MSK	(0x1f << MSC01_PBC_CS0CFG_WSIDLE_SHF)
+#define MSC01_PBC_CS0CFG_DTYP_SHF	16
+#define MSC01_PBC_CS0CFG_DTYP_MSK	(0x3 << MSC01_PBC_CS0CFG_DTYP_SHF)
+#define MSC01_PBC_CS0CFG_ADM_SHF	20
+#define MSC01_PBC_CS0CFG_ADM_MSK	(0x1 << MSC01_PBC_CS0CFG_ADM_SHF)
+
+#define MSC01_PBC_CS0TIM_CAT_SHF	0
+#define MSC01_PBC_CS0TIM_CAT_MSK	(0x1f << MSC01_PBC_CS0TIM_CAT_SHF)
+#define MSC01_PBC_CS0TIM_CDT_SHF	8
+#define MSC01_PBC_CS0TIM_CDT_MSK	(0x1f << MSC01_PBC_CS0TIM_CDT_SHF)
+
+#define MSC01_PBC_CS0RW_WAT_SHF		0
+#define MSC01_PBC_CS0RW_WAT_MSK		(0x1f << MSC01_PBC_CS0RW_WAT_SHF)
+#define MSC01_PBC_CS0RW_WDT_SHF		8
+#define MSC01_PBC_CS0RW_WDT_MSK		(0x1f << MSC01_PBC_CS0RW_WDT_SHF)
+#define MSC01_PBC_CS0RW_RAT_SHF		16
+#define MSC01_PBC_CS0RW_RAT_MSK		(0x1f << MSC01_PBC_CS0RW_RAT_SHF)
+#define MSC01_PBC_CS0RW_RDT_SHF		24
+#define MSC01_PBC_CS0RW_RDT_MSK		(0x1f << MSC01_PBC_CS0RW_RDT_SHF)
+
+#endif /* __MSC01_H__ */
diff --git a/include/pci.h b/include/pci.h
index d462479667702e9369a08e10ad360c13ba0983f6..461f17c058950d89f572545dbcd981e4b4eb6838 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -417,6 +417,8 @@
 
 #include <pci_ids.h>
 
+#ifndef __ASSEMBLY__
+
 #ifdef CONFIG_SYS_PCI_64BIT
 typedef u64 pci_addr_t;
 typedef u64 pci_size_t;
@@ -667,4 +669,6 @@ extern void pci_mpc824x_init (struct pci_controller *hose);
 #ifdef CONFIG_MPC85xx
 extern void pci_mpc85xx_init (struct pci_controller *hose);
 #endif
-#endif	/* _PCI_H */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _PCI_H */
diff --git a/include/pci_ids.h b/include/pci_ids.h
index 2c6dfd4044357dd403468bacfbc66040133ebf2c..6bab67744990ad34564c1d10cc4d0d554ba57def 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -2170,6 +2170,9 @@
 #define PCI_DEVICE_ID_ENE_720		0x1421
 #define PCI_DEVICE_ID_ENE_722		0x1422
 
+#define PCI_VENDOR_ID_MIPS		0x153f
+#define PCI_DEVICE_ID_MIPS_MSC01	0x0001
+
 #define PCI_SUBVENDOR_ID_PERLE          0x155f
 #define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
 #define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
diff --git a/include/pci_msc01.h b/include/pci_msc01.h
new file mode 100644
index 0000000000000000000000000000000000000000..54945a7a8f712cf8c62d9684f3aca728847e81d5
--- /dev/null
+++ b/include/pci_msc01.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __PCI_MSC01_H__
+#define __PCI_MSC01_H__
+
+extern void msc01_pci_init(void *base, unsigned long sys_bus,
+			   unsigned long sys_phys, unsigned long sys_size,
+			   unsigned long mem_bus, unsigned long mem_phys,
+			   unsigned long mem_size, unsigned long io_bus,
+			   unsigned long io_phys, unsigned long io_size);
+
+#endif /* __PCI_MSC01_H__ */