Merge branch '3.16-fixes' into mips-for-linux-next
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index c1b9aa8..ea4f2df 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -566,6 +566,12 @@
 			possible to determine what the correct size should be.
 			This option provides an override for these situations.
 
+	cca=		[MIPS] Override the kernel pages' cache coherency
+			algorithm.  Accepted values range from 0 to 7
+			inclusive. See arch/mips/include/asm/pgtable-bits.h
+			for platform specific values (SB1, Loongson3 and
+			others).
+
 	ccw_timeout_log [S390]
 			See Documentation/s390/CommonIO for details.
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4e238e6..0d3f935 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -72,6 +72,7 @@
 	select SYS_SUPPORTS_APM_EMULATION
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
+	select COMMON_CLK
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -130,6 +131,8 @@
 	select SYS_SUPPORTS_MIPS16
 	select SYS_HAS_EARLY_PRINTK
 	select USE_GENERIC_EARLY_PRINTK_8250
+	select GPIOLIB
+	select LEDS_GPIO_REGISTER
 	help
 	 Support for BCM47XX based boards
 
@@ -138,6 +141,7 @@
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
+	select SYNC_R4K
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select SYS_SUPPORTS_32BIT_KERNEL
@@ -2057,6 +2061,7 @@
 	  support is unavailable.
 
 config MIPS_CPS_PM
+	select MIPS_CPC
 	bool
 
 config MIPS_GIC_IPI
@@ -2110,9 +2115,9 @@
 	  microMIPS ISA
 
 config CPU_HAS_MSA
-	bool "Support for the MIPS SIMD Architecture"
+	bool "Support for the MIPS SIMD Architecture (EXPERIMENTAL)"
 	depends on CPU_SUPPORTS_MSA
-	default y
+	depends on 64BIT || MIPS_O32_FP64_SUPPORT
 	help
 	  MIPS SIMD Architecture (MSA) introduces 128 bit wide vector registers
 	  and a set of SIMD instructions to operate on them. When this option
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index a8521de..9336509 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -151,8 +151,10 @@
 			-Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)	+= $(call cc-option,-march=rm7000,-march=r5000) \
 			-Wa,--trap
-cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-march=sb1,-march=r5000) \
 			-Wa,--trap
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-mno-mdmx)
+cflags-$(CONFIG_CPU_SB1)	+= $(call cc-option,-mno-mips3d)
 cflags-$(CONFIG_CPU_R8000)	+= -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)	+= $(call cc-option,-march=r10000,-march=r8000) \
 			-Wa,--trap
diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c
index 25a59a2..1e3b102 100644
--- a/arch/mips/alchemy/board-mtx1.c
+++ b/arch/mips/alchemy/board-mtx1.c
@@ -85,10 +85,10 @@
 #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
 
 	/* Initialize sys_pinfunc */
-	au_writel(SYS_PF_NI2, SYS_PINFUNC);
+	alchemy_wrsys(SYS_PF_NI2, AU1000_SYS_PINFUNC);
 
 	/* Initialize GPIO */
-	au_writel(~0, KSEG1ADDR(AU1000_SYS_PHYS_ADDR) + SYS_TRIOUTCLR);
+	alchemy_wrsys(~0, AU1000_SYS_TRIOUTCLR);
 	alchemy_gpio_direction_output(0, 0);	/* Disable M66EN (PCI 66MHz) */
 	alchemy_gpio_direction_output(3, 1);	/* Disable PCI CLKRUN# */
 	alchemy_gpio_direction_output(1, 1);	/* Enable EXT_IO3 */
diff --git a/arch/mips/alchemy/board-xxs1500.c b/arch/mips/alchemy/board-xxs1500.c
index 3fb814b..0fc53e0 100644
--- a/arch/mips/alchemy/board-xxs1500.c
+++ b/arch/mips/alchemy/board-xxs1500.c
@@ -87,9 +87,9 @@
 	alchemy_gpio2_enable();
 
 	/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
-	pin_func  = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
+	pin_func  = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PF_UR3;
 	pin_func |= SYS_PF_UR3;
-	au_writel(pin_func, SYS_PINFUNC);
+	alchemy_wrsys(pin_func, AU1000_SYS_PINFUNC);
 
 	/* Enable UART */
 	alchemy_uart_enable(AU1000_UART3_PHYS_ADDR);
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index cb83d8d..f64744f 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -5,8 +5,8 @@
 # Makefile for the Alchemy Au1xx0 CPUs, generic files.
 #
 
-obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
-	sleeper.o dma.o dbdma.o vss.o irq.o usb.o
+obj-y += prom.o time.o clock.o platform.o power.o \
+	 setup.o sleeper.o dma.o dbdma.o vss.o irq.o usb.o
 
 # optional gpiolib support
 ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
new file mode 100644
index 0000000..d7557cd
--- /dev/null
+++ b/arch/mips/alchemy/common/clock.c
@@ -0,0 +1,1094 @@
+/*
+ * Alchemy clocks.
+ *
+ * Exposes all configurable internal clock sources to the clk framework.
+ *
+ * We have:
+ *  - Root source, usually 12MHz supplied by an external crystal
+ *  - 3 PLLs which generate multiples of root rate [AUX, CPU, AUX2]
+ *
+ * Dividers:
+ *  - 6 clock dividers with:
+ *   * selectable source [one of the PLLs],
+ *   * output divided between [2 .. 512 in steps of 2] (!Au1300)
+ *     or [1 .. 256 in steps of 1] (Au1300),
+ *   * can be enabled individually.
+ *
+ * - up to 6 "internal" (fixed) consumers which:
+ *   * take either AUXPLL or one of the above 6 dividers as input,
+ *   * divide this input by 1, 2, or 4 (and 3 on Au1300).
+ *   * can be disabled separately.
+ *
+ * Misc clocks:
+ * - sysbus clock: CPU core clock (CPUPLL) divided by 2, 3 or 4.
+ *    depends on board design and should be set by bootloader, read-only.
+ * - peripheral clock: half the rate of sysbus clock, source for a lot
+ *    of peripheral blocks, read-only.
+ * - memory clock: clk rate to main memory chips, depends on board
+ *    design and is read-only,
+ * - lrclk: the static bus clock signal for synchronous operation.
+ *    depends on board design, must be set by bootloader,
+ *    but may be required to correctly configure devices attached to
+ *    the static bus. The Au1000/1500/1100 manuals call it LCLK, on
+ *    later models it's called RCLK.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* Base clock: 12MHz is the default in all databooks, and I haven't
+ * found any board yet which uses a different rate.
+ */
+#define ALCHEMY_ROOTCLK_RATE	12000000
+
+/*
+ * the internal sources which can be driven by the PLLs and dividers.
+ * Names taken from the databooks, refer to them for more information,
+ * especially which ones are share a clock line.
+ */
+static const char * const alchemy_au1300_intclknames[] = {
+	"lcd_intclk", "gpemgp_clk", "maempe_clk", "maebsa_clk",
+	"EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1200_intclknames[] = {
+	"lcd_intclk", NULL, NULL, NULL, "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1550_intclknames[] = {
+	"usb_clk", "psc0_intclk", "psc1_intclk", "pci_clko",
+	"EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1100_intclknames[] = {
+	"usb_clk", "lcd_intclk", NULL, "i2s_clk", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1500_intclknames[] = {
+	NULL, "usbd_clk", "usbh_clk", "pci_clko", "EXTCLK0", "EXTCLK1"
+};
+
+static const char * const alchemy_au1000_intclknames[] = {
+	"irda_clk", "usbd_clk", "usbh_clk", "i2s_clk", "EXTCLK0",
+	"EXTCLK1"
+};
+
+/* aliases for a few on-chip sources which are either shared
+ * or have gone through name changes.
+ */
+static struct clk_aliastable {
+	char *alias;
+	char *base;
+	int cputype;
+} alchemy_clk_aliases[] __initdata = {
+	{ "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "irda_clk", "usb_clk",    ALCHEMY_CPU_AU1100 },
+	{ "usbh_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+	{ "usbd_clk", "usb_clk",    ALCHEMY_CPU_AU1550 },
+	{ "psc2_intclk", "usb_clk", ALCHEMY_CPU_AU1550 },
+	{ "psc3_intclk", "EXTCLK0", ALCHEMY_CPU_AU1550 },
+	{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1200 },
+	{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1200 },
+	{ "psc0_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+	{ "psc2_intclk", "EXTCLK0", ALCHEMY_CPU_AU1300 },
+	{ "psc1_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+	{ "psc3_intclk", "EXTCLK1", ALCHEMY_CPU_AU1300 },
+
+	{ NULL, NULL, 0 },
+};
+
+#define IOMEM(x)	((void __iomem *)(KSEG1ADDR(CPHYSADDR(x))))
+
+/* access locks to SYS_FREQCTRL0/1 and SYS_CLKSRC registers */
+static spinlock_t alchemy_clk_fg0_lock;
+static spinlock_t alchemy_clk_fg1_lock;
+static spinlock_t alchemy_clk_csrc_lock;
+
+/* CPU Core clock *****************************************************/
+
+static unsigned long alchemy_clk_cpu_recalc(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	unsigned long t;
+
+	/*
+	 * On early Au1000, sys_cpupll was write-only. Since these
+	 * silicon versions of Au1000 are not sold, we don't bend
+	 * over backwards trying to determine the frequency.
+	 */
+	if (unlikely(au1xxx_cpu_has_pll_wo()))
+		t = 396000000;
+	else {
+		t = alchemy_rdsys(AU1000_SYS_CPUPLL) & 0x7f;
+		t *= parent_rate;
+	}
+
+	return t;
+}
+
+static struct clk_ops alchemy_clkops_cpu = {
+	.recalc_rate	= alchemy_clk_cpu_recalc,
+};
+
+static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name,
+						int ctype)
+{
+	struct clk_init_data id;
+	struct clk_hw *h;
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return ERR_PTR(-ENOMEM);
+
+	id.name = ALCHEMY_CPU_CLK;
+	id.parent_names = &parent_name;
+	id.num_parents = 1;
+	id.flags = CLK_IS_BASIC;
+	id.ops = &alchemy_clkops_cpu;
+	h->init = &id;
+
+	return clk_register(NULL, h);
+}
+
+/* AUXPLLs ************************************************************/
+
+struct alchemy_auxpll_clk {
+	struct clk_hw hw;
+	unsigned long reg;	/* au1300 has also AUXPLL2 */
+	int maxmult;		/* max multiplier */
+};
+#define to_auxpll_clk(x) container_of(x, struct alchemy_auxpll_clk, hw)
+
+static unsigned long alchemy_clk_aux_recalc(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+
+	return (alchemy_rdsys(a->reg) & 0xff) * parent_rate;
+}
+
+static int alchemy_clk_aux_setr(struct clk_hw *hw,
+				unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+	unsigned long d = rate;
+
+	if (rate)
+		d /= parent_rate;
+	else
+		d = 0;
+
+	/* minimum is 84MHz, max is 756-1032 depending on variant */
+	if (((d < 7) && (d != 0)) || (d > a->maxmult))
+		return -EINVAL;
+
+	alchemy_wrsys(d, a->reg);
+	return 0;
+}
+
+static long alchemy_clk_aux_roundr(struct clk_hw *hw,
+					    unsigned long rate,
+					    unsigned long *parent_rate)
+{
+	struct alchemy_auxpll_clk *a = to_auxpll_clk(hw);
+	unsigned long mult;
+
+	if (!rate || !*parent_rate)
+		return 0;
+
+	mult = rate / (*parent_rate);
+
+	if (mult && (mult < 7))
+		mult = 7;
+	if (mult > a->maxmult)
+		mult = a->maxmult;
+
+	return (*parent_rate) * mult;
+}
+
+static struct clk_ops alchemy_clkops_aux = {
+	.recalc_rate	= alchemy_clk_aux_recalc,
+	.set_rate	= alchemy_clk_aux_setr,
+	.round_rate	= alchemy_clk_aux_roundr,
+};
+
+static struct clk __init *alchemy_clk_setup_aux(const char *parent_name,
+						char *name, int maxmult,
+						unsigned long reg)
+{
+	struct clk_init_data id;
+	struct clk *c;
+	struct alchemy_auxpll_clk *a;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return ERR_PTR(-ENOMEM);
+
+	id.name = name;
+	id.parent_names = &parent_name;
+	id.num_parents = 1;
+	id.flags = CLK_GET_RATE_NOCACHE;
+	id.ops = &alchemy_clkops_aux;
+
+	a->reg = reg;
+	a->maxmult = maxmult;
+	a->hw.init = &id;
+
+	c = clk_register(NULL, &a->hw);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, name, NULL);
+	else
+		kfree(a);
+
+	return c;
+}
+
+/* sysbus_clk *********************************************************/
+
+static struct clk __init  *alchemy_clk_setup_sysbus(const char *pn)
+{
+	unsigned long v = (alchemy_rdsys(AU1000_SYS_POWERCTRL) & 3) + 2;
+	struct clk *c;
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_SYSBUS_CLK,
+				      pn, 0, 1, v);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_SYSBUS_CLK, NULL);
+	return c;
+}
+
+/* Peripheral Clock ***************************************************/
+
+static struct clk __init *alchemy_clk_setup_periph(const char *pn)
+{
+	/* Peripheral clock runs at half the rate of sysbus clk */
+	struct clk *c;
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_PERIPH_CLK,
+				      pn, 0, 1, 2);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_PERIPH_CLK, NULL);
+	return c;
+}
+
+/* mem clock **********************************************************/
+
+static struct clk __init *alchemy_clk_setup_mem(const char *pn, int ct)
+{
+	void __iomem *addr = IOMEM(AU1000_MEM_PHYS_ADDR);
+	unsigned long v;
+	struct clk *c;
+	int div;
+
+	switch (ct) {
+	case ALCHEMY_CPU_AU1550:
+	case ALCHEMY_CPU_AU1200:
+		v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+		div = (v & (1 << 15)) ? 1 : 2;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		v = __raw_readl(addr + AU1550_MEM_SDCONFIGB);
+		div = (v & (1 << 31)) ? 1 : 2;
+		break;
+	case ALCHEMY_CPU_AU1000:
+	case ALCHEMY_CPU_AU1500:
+	case ALCHEMY_CPU_AU1100:
+	default:
+		div = 2;
+		break;
+	}
+
+	c = clk_register_fixed_factor(NULL, ALCHEMY_MEM_CLK, pn,
+				      0, 1, div);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_MEM_CLK, NULL);
+	return c;
+}
+
+/* lrclk: external synchronous static bus clock ***********************/
+
+static struct clk __init *alchemy_clk_setup_lrclk(const char *pn)
+{
+	/* MEM_STCFG0[15:13] = divisor.
+	 * L/RCLK = periph_clk / (divisor + 1)
+	 * On Au1000, Au1500, Au1100 it's called LCLK,
+	 * on later models it's called RCLK, but it's the same thing.
+	 */
+	struct clk *c;
+	unsigned long v = alchemy_rdsmem(AU1000_MEM_STCFG0) >> 13;
+
+	v = (v & 7) + 1;
+	c = clk_register_fixed_factor(NULL, ALCHEMY_LR_CLK,
+				      pn, 0, 1, v);
+	if (!IS_ERR(c))
+		clk_register_clkdev(c, ALCHEMY_LR_CLK, NULL);
+	return c;
+}
+
+/* Clock dividers and muxes *******************************************/
+
+/* data for fgen and csrc mux-dividers */
+struct alchemy_fgcs_clk {
+	struct clk_hw hw;
+	spinlock_t *reglock;	/* register lock		  */
+	unsigned long reg;	/* SYS_FREQCTRL0/1		  */
+	int shift;		/* offset in register		  */
+	int parent;		/* parent before disable [Au1300] */
+	int isen;		/* is it enabled?		  */
+	int *dt;		/* dividertable for csrc	  */
+};
+#define to_fgcs_clk(x) container_of(x, struct alchemy_fgcs_clk, hw)
+
+static long alchemy_calc_div(unsigned long rate, unsigned long prate,
+			       int scale, int maxdiv, unsigned long *rv)
+{
+	long div1, div2;
+
+	div1 = prate / rate;
+	if ((prate / div1) > rate)
+		div1++;
+
+	if (scale == 2) {	/* only div-by-multiple-of-2 possible */
+		if (div1 & 1)
+			div1++;	/* stay <=prate */
+	}
+
+	div2 = (div1 / scale) - 1;	/* value to write to register */
+
+	if (div2 > maxdiv)
+		div2 = maxdiv;
+	if (rv)
+		*rv = div2;
+
+	div1 = ((div2 + 1) * scale);
+	return div1;
+}
+
+static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk,
+					int scale, int maxdiv)
+{
+	struct clk *pc, *bpc, *free;
+	long tdv, tpr, pr, nr, br, bpr, diff, lastdiff;
+	int j;
+
+	lastdiff = INT_MAX;
+	bpr = 0;
+	bpc = NULL;
+	br = -EINVAL;
+	free = NULL;
+
+	/* look at the rates each enabled parent supplies and select
+	 * the one that gets closest to but not over the requested rate.
+	 */
+	for (j = 0; j < 7; j++) {
+		pc = clk_get_parent_by_index(hw->clk, j);
+		if (!pc)
+			break;
+
+		/* if this parent is currently unused, remember it.
+		 * XXX: I know it's a layering violation, but it works
+		 * so well.. (if (!clk_has_active_children(pc)) )
+		 */
+		if (pc->prepare_count == 0) {
+			if (!free)
+				free = pc;
+		}
+
+		pr = clk_get_rate(pc);
+		if (pr < rate)
+			continue;
+
+		/* what can hardware actually provide */
+		tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+		nr = pr / tdv;
+		diff = rate - nr;
+		if (nr > rate)
+			continue;
+
+		if (diff < lastdiff) {
+			lastdiff = diff;
+			bpr = pr;
+			bpc = pc;
+			br = nr;
+		}
+		if (diff == 0)
+			break;
+	}
+
+	/* if we couldn't get the exact rate we wanted from the enabled
+	 * parents, maybe we can tell an available disabled/inactive one
+	 * to give us a rate we can divide down to the requested rate.
+	 */
+	if (lastdiff && free) {
+		for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
+			tpr = rate * j;
+			if (tpr < 0)
+				break;
+			pr = clk_round_rate(free, tpr);
+
+			tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
+			nr = pr / tdv;
+			diff = rate - nr;
+			if (nr > rate)
+				continue;
+			if (diff < lastdiff) {
+				lastdiff = diff;
+				bpr = pr;
+				bpc = free;
+				br = nr;
+			}
+			if (diff == 0)
+				break;
+		}
+	}
+
+	*best_parent_rate = bpr;
+	*best_parent_clk = bpc;
+	return br;
+}
+
+static int alchemy_clk_fgv1_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v |= (1 << 1) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static int alchemy_clk_fgv1_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 1);
+
+	return v & 1;
+}
+
+static void alchemy_clk_fgv1_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~((1 << 1) << c->shift);
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv1_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	if (index)
+		v |= (1 << c->shift);
+	else
+		v &= ~(1 << c->shift);
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_fgv1_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return (alchemy_rdsys(c->reg) >> c->shift) & 1;
+}
+
+static int alchemy_clk_fgv1_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long div, v, flags, ret;
+	int sh = c->shift + 2;
+
+	if (!rate || !parent_rate || rate > (parent_rate / 2))
+		return -EINVAL;
+	ret = alchemy_calc_div(rate, parent_rate, 2, 512, &div);
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(0xff << sh);
+	v |= div << sh;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg) >> (c->shift + 2);
+
+	v = ((v & 0xff) + 1) * 2;
+	return parent_rate / v;
+}
+
+static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, 2, 512);
+}
+
+/* Au1000, Au1100, Au15x0, Au12x0 */
+static struct clk_ops alchemy_clkops_fgenv1 = {
+	.recalc_rate	= alchemy_clk_fgv1_recalc,
+	.determine_rate	= alchemy_clk_fgv1_detr,
+	.set_rate	= alchemy_clk_fgv1_setr,
+	.set_parent	= alchemy_clk_fgv1_setp,
+	.get_parent	= alchemy_clk_fgv1_getp,
+	.enable		= alchemy_clk_fgv1_en,
+	.disable	= alchemy_clk_fgv1_dis,
+	.is_enabled	= alchemy_clk_fgv1_isen,
+};
+
+static void __alchemy_clk_fgv2_en(struct alchemy_fgcs_clk *c)
+{
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	v &= ~(3 << c->shift);
+	v |= (c->parent & 3) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	c->isen = 1;
+}
+
+static int alchemy_clk_fgv2_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	/* enable by setting the previous parent clock */
+	spin_lock_irqsave(c->reglock, flags);
+	__alchemy_clk_fgv2_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static int alchemy_clk_fgv2_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return ((alchemy_rdsys(c->reg) >> c->shift) & 3) != 0;
+}
+
+static void alchemy_clk_fgv2_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(3 << c->shift);	/* set input mux to "disabled" state */
+	alchemy_wrsys(v, c->reg);
+	c->isen = 0;
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_fgv2_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	c->parent = index + 1;	/* value to write to register */
+	if (c->isen)
+		__alchemy_clk_fgv2_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_fgv2_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags, v;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = c->parent - 1;
+	spin_unlock_irqrestore(c->reglock, flags);
+	return v;
+}
+
+/* fg0-2 and fg4-6 share a "scale"-bit. With this bit cleared, the
+ * dividers behave exactly as on previous models (dividers are multiples
+ * of 2); with the bit set, dividers are multiples of 1, halving their
+ * range, but making them also much more flexible.
+ */
+static int alchemy_clk_fgv2_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int sh = c->shift + 2;
+	unsigned long div, v, flags, ret;
+
+	if (!rate || !parent_rate || rate > parent_rate)
+		return -EINVAL;
+
+	v = alchemy_rdsys(c->reg) & (1 << 30); /* test "scale" bit */
+	ret = alchemy_calc_div(rate, parent_rate, v ? 1 : 2,
+			       v ? 256 : 512, &div);
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(0xff << sh);
+	v |= (div & 0xff) << sh;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int sh = c->shift + 2;
+	unsigned long v, t;
+
+	v = alchemy_rdsys(c->reg);
+	t = parent_rate / (((v >> sh) & 0xff) + 1);
+	if ((v & (1 << 30)) == 0)		/* test scale bit */
+		t /= 2;
+
+	return t;
+}
+
+static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int scale, maxdiv;
+
+	if (alchemy_rdsys(c->reg) & (1 << 30)) {
+		scale = 1;
+		maxdiv = 256;
+	} else {
+		scale = 2;
+		maxdiv = 512;
+	}
+
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, scale, maxdiv);
+}
+
+/* Au1300 larger input mux, no separate disable bit, flexible divider */
+static struct clk_ops alchemy_clkops_fgenv2 = {
+	.recalc_rate	= alchemy_clk_fgv2_recalc,
+	.determine_rate	= alchemy_clk_fgv2_detr,
+	.set_rate	= alchemy_clk_fgv2_setr,
+	.set_parent	= alchemy_clk_fgv2_setp,
+	.get_parent	= alchemy_clk_fgv2_getp,
+	.enable		= alchemy_clk_fgv2_en,
+	.disable	= alchemy_clk_fgv2_dis,
+	.is_enabled	= alchemy_clk_fgv2_isen,
+};
+
+static const char * const alchemy_clk_fgv1_parents[] = {
+	ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgv2_parents[] = {
+	ALCHEMY_AUXPLL2_CLK, ALCHEMY_CPU_CLK, ALCHEMY_AUXPLL_CLK
+};
+
+static const char * const alchemy_clk_fgen_names[] = {
+	ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+	ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK };
+
+static int __init alchemy_clk_init_fgens(int ctype)
+{
+	struct clk *c;
+	struct clk_init_data id;
+	struct alchemy_fgcs_clk *a;
+	unsigned long v;
+	int i, ret;
+
+	switch (ctype) {
+	case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
+		id.ops = &alchemy_clkops_fgenv1;
+		id.parent_names = (const char **)alchemy_clk_fgv1_parents;
+		id.num_parents = 2;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		id.ops = &alchemy_clkops_fgenv2;
+		id.parent_names = (const char **)alchemy_clk_fgv2_parents;
+		id.num_parents = 3;
+		break;
+	default:
+		return -ENODEV;
+	}
+	id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+	a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	spin_lock_init(&alchemy_clk_fg0_lock);
+	spin_lock_init(&alchemy_clk_fg1_lock);
+	ret = 0;
+	for (i = 0; i < 6; i++) {
+		id.name = alchemy_clk_fgen_names[i];
+		a->shift = 10 * (i < 3 ? i : i - 3);
+		if (i > 2) {
+			a->reg = AU1000_SYS_FREQCTRL1;
+			a->reglock = &alchemy_clk_fg1_lock;
+		} else {
+			a->reg = AU1000_SYS_FREQCTRL0;
+			a->reglock = &alchemy_clk_fg0_lock;
+		}
+
+		/* default to first parent if bootloader has set
+		 * the mux to disabled state.
+		 */
+		if (ctype == ALCHEMY_CPU_AU1300) {
+			v = alchemy_rdsys(a->reg);
+			a->parent = (v >> a->shift) & 3;
+			if (!a->parent) {
+				a->parent = 1;
+				a->isen = 0;
+			} else
+				a->isen = 1;
+		}
+
+		a->hw.init = &id;
+		c = clk_register(NULL, &a->hw);
+		if (IS_ERR(c))
+			ret++;
+		else
+			clk_register_clkdev(c, id.name, NULL);
+		a++;
+	}
+
+	return ret;
+}
+
+/* internal sources muxes *********************************************/
+
+static int alchemy_clk_csrc_isen(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	return (((v >> c->shift) >> 2) & 7) != 0;
+}
+
+static void __alchemy_clk_csrc_en(struct alchemy_fgcs_clk *c)
+{
+	unsigned long v = alchemy_rdsys(c->reg);
+
+	v &= ~((7 << 2) << c->shift);
+	v |= ((c->parent & 7) << 2) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	c->isen = 1;
+}
+
+static int alchemy_clk_csrc_en(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	/* enable by setting the previous parent clock */
+	spin_lock_irqsave(c->reglock, flags);
+	__alchemy_clk_csrc_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static void alchemy_clk_csrc_dis(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v, flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~((3 << 2) << c->shift);	/* mux to "disabled" state */
+	alchemy_wrsys(v, c->reg);
+	c->isen = 0;
+	spin_unlock_irqrestore(c->reglock, flags);
+}
+
+static int alchemy_clk_csrc_setp(struct clk_hw *hw, u8 index)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(c->reglock, flags);
+	c->parent = index + 1;	/* value to write to register */
+	if (c->isen)
+		__alchemy_clk_csrc_en(c);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static u8 alchemy_clk_csrc_getp(struct clk_hw *hw)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+
+	return c->parent - 1;
+}
+
+static unsigned long alchemy_clk_csrc_recalc(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long v = (alchemy_rdsys(c->reg) >> c->shift) & 3;
+
+	return parent_rate / c->dt[v];
+}
+
+static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	unsigned long d, v, flags;
+	int i;
+
+	if (!rate || !parent_rate || rate > parent_rate)
+		return -EINVAL;
+
+	d = (parent_rate + (rate / 2)) / rate;
+	if (d > 4)
+		return -EINVAL;
+	if ((d == 3) && (c->dt[2] != 3))
+		d = 4;
+
+	for (i = 0; i < 4; i++)
+		if (c->dt[i] == d)
+			break;
+
+	if (i >= 4)
+		return -EINVAL;	/* oops */
+
+	spin_lock_irqsave(c->reglock, flags);
+	v = alchemy_rdsys(c->reg);
+	v &= ~(3 << c->shift);
+	v |= (i & 3) << c->shift;
+	alchemy_wrsys(v, c->reg);
+	spin_unlock_irqrestore(c->reglock, flags);
+
+	return 0;
+}
+
+static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long *best_parent_rate,
+					struct clk **best_parent_clk)
+{
+	struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
+	int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
+
+	return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
+				     best_parent_clk, scale, 4);
+}
+
+static struct clk_ops alchemy_clkops_csrc = {
+	.recalc_rate	= alchemy_clk_csrc_recalc,
+	.determine_rate	= alchemy_clk_csrc_detr,
+	.set_rate	= alchemy_clk_csrc_setr,
+	.set_parent	= alchemy_clk_csrc_setp,
+	.get_parent	= alchemy_clk_csrc_getp,
+	.enable		= alchemy_clk_csrc_en,
+	.disable	= alchemy_clk_csrc_dis,
+	.is_enabled	= alchemy_clk_csrc_isen,
+};
+
+static const char * const alchemy_clk_csrc_parents[] = {
+	/* disabled at index 0 */ ALCHEMY_AUXPLL_CLK,
+	ALCHEMY_FG0_CLK, ALCHEMY_FG1_CLK, ALCHEMY_FG2_CLK,
+	ALCHEMY_FG3_CLK, ALCHEMY_FG4_CLK, ALCHEMY_FG5_CLK
+};
+
+/* divider tables */
+static int alchemy_csrc_dt1[] = { 1, 4, 1, 2 };	/* rest */
+static int alchemy_csrc_dt2[] = { 1, 4, 3, 2 };	/* Au1300 */
+
+static int __init alchemy_clk_setup_imux(int ctype)
+{
+	struct alchemy_fgcs_clk *a;
+	const char * const *names;
+	struct clk_init_data id;
+	unsigned long v;
+	int i, ret, *dt;
+	struct clk *c;
+
+	id.ops = &alchemy_clkops_csrc;
+	id.parent_names = (const char **)alchemy_clk_csrc_parents;
+	id.num_parents = 7;
+	id.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+
+	dt = alchemy_csrc_dt1;
+	switch (ctype) {
+	case ALCHEMY_CPU_AU1000:
+		names = alchemy_au1000_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1500:
+		names = alchemy_au1500_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1100:
+		names = alchemy_au1100_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1550:
+		names = alchemy_au1550_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1200:
+		names = alchemy_au1200_intclknames;
+		break;
+	case ALCHEMY_CPU_AU1300:
+		dt = alchemy_csrc_dt2;
+		names = alchemy_au1300_intclknames;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	spin_lock_init(&alchemy_clk_csrc_lock);
+	ret = 0;
+
+	for (i = 0; i < 6; i++) {
+		id.name = names[i];
+		if (!id.name)
+			goto next;
+
+		a->shift = i * 5;
+		a->reg = AU1000_SYS_CLKSRC;
+		a->reglock = &alchemy_clk_csrc_lock;
+		a->dt = dt;
+
+		/* default to first parent clock if mux is initially
+		 * set to disabled state.
+		 */
+		v = alchemy_rdsys(a->reg);
+		a->parent = ((v >> a->shift) >> 2) & 7;
+		if (!a->parent) {
+			a->parent = 1;
+			a->isen = 0;
+		} else
+			a->isen = 1;
+
+		a->hw.init = &id;
+		c = clk_register(NULL, &a->hw);
+		if (IS_ERR(c))
+			ret++;
+		else
+			clk_register_clkdev(c, id.name, NULL);
+next:
+		a++;
+	}
+
+	return ret;
+}
+
+
+/**********************************************************************/
+
+
+#define ERRCK(x)						\
+	if (IS_ERR(x)) {					\
+		ret = PTR_ERR(x);				\
+		goto out;					\
+	}
+
+static int __init alchemy_clk_init(void)
+{
+	int ctype = alchemy_get_cputype(), ret, i;
+	struct clk_aliastable *t = alchemy_clk_aliases;
+	struct clk *c;
+
+	/* Root of the Alchemy clock tree: external 12MHz crystal osc */
+	c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
+					   CLK_IS_ROOT,
+					   ALCHEMY_ROOTCLK_RATE);
+	ERRCK(c)
+
+	/* CPU core clock */
+	c = alchemy_clk_setup_cpu(ALCHEMY_ROOT_CLK, ctype);
+	ERRCK(c)
+
+	/* AUXPLLs: max 1GHz on Au1300, 748MHz on older models */
+	i = (ctype == ALCHEMY_CPU_AU1300) ? 84 : 63;
+	c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK, ALCHEMY_AUXPLL_CLK,
+				  i, AU1000_SYS_AUXPLL);
+	ERRCK(c)
+
+	if (ctype == ALCHEMY_CPU_AU1300) {
+		c = alchemy_clk_setup_aux(ALCHEMY_ROOT_CLK,
+					  ALCHEMY_AUXPLL2_CLK, i,
+					  AU1300_SYS_AUXPLL2);
+		ERRCK(c)
+	}
+
+	/* sysbus clock: cpu core clock divided by 2, 3 or 4 */
+	c = alchemy_clk_setup_sysbus(ALCHEMY_CPU_CLK);
+	ERRCK(c)
+
+	/* peripheral clock: runs at half rate of sysbus clk */
+	c = alchemy_clk_setup_periph(ALCHEMY_SYSBUS_CLK);
+	ERRCK(c)
+
+	/* SDR/DDR memory clock */
+	c = alchemy_clk_setup_mem(ALCHEMY_SYSBUS_CLK, ctype);
+	ERRCK(c)
+
+	/* L/RCLK: external static bus clock for synchronous mode */
+	c = alchemy_clk_setup_lrclk(ALCHEMY_PERIPH_CLK);
+	ERRCK(c)
+
+	/* Frequency dividers 0-5 */
+	ret = alchemy_clk_init_fgens(ctype);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* diving muxes for internal sources */
+	ret = alchemy_clk_setup_imux(ctype);
+	if (ret) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* set up aliases drivers might look for */
+	while (t->base) {
+		if (t->cputype == ctype)
+			clk_add_alias(t->alias, NULL, t->base, NULL);
+		t++;
+	}
+
+	pr_info("Alchemy clocktree installed\n");
+	return 0;
+
+out:
+	return ret;
+}
+postcore_initcall(alchemy_clk_init);
diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c
deleted file mode 100644
index f38298a..0000000
--- a/arch/mips/alchemy/common/clocks.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *	Simple Au1xx0 clocks routines.
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute	 it and/or modify it
- *  under  the terms of	 the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the	License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
- *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
- *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/time.h>
-#include <asm/mach-au1x00/au1000.h>
-
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK	12000000
-
-static unsigned int au1x00_clock; /*  Hz */
-static unsigned long uart_baud_base;
-
-/*
- * Set the au1000_clock
- */
-void set_au1x00_speed(unsigned int new_freq)
-{
-	au1x00_clock = new_freq;
-}
-
-unsigned int get_au1x00_speed(void)
-{
-	return au1x00_clock;
-}
-EXPORT_SYMBOL(get_au1x00_speed);
-
-/*
- * The UART baud base is not known at compile time ... if
- * we want to be able to use the same code on different
- * speed CPUs.
- */
-unsigned long get_au1x00_uart_baud_base(void)
-{
-	return uart_baud_base;
-}
-
-void set_au1x00_uart_baud_base(unsigned long new_baud_base)
-{
-	uart_baud_base = new_baud_base;
-}
-
-/*
- * We read the real processor speed from the PLL.  This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists.  If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly.  This function is further convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register.			-- Dan
- */
-unsigned long au1xxx_calc_clock(void)
-{
-	unsigned long cpu_speed;
-
-	/*
-	 * On early Au1000, sys_cpupll was write-only. Since these
-	 * silicon versions of Au1000 are not sold by AMD, we don't bend
-	 * over backwards trying to determine the frequency.
-	 */
-	if (au1xxx_cpu_has_pll_wo())
-		cpu_speed = 396000000;
-	else
-		cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
-
-	/* On Alchemy CPU:counter ratio is 1:1 */
-	mips_hpt_frequency = cpu_speed;
-	/* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
-	set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
-							  & 0x03) + 2) * 16));
-
-	set_au1x00_speed(cpu_speed);
-
-	return cpu_speed;
-}
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 19d5642..745695d 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -341,7 +341,7 @@
 			(dtp->dev_flags & DEV_FLAGS_SYNC))
 				i |= DDMA_CFG_SYNC;
 		cp->ddma_cfg = i;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/*
 		 * Return a non-zero value that can be used to find the channel
@@ -631,7 +631,7 @@
 	 */
 	dma_cache_wback_inv((unsigned long)buf, nbytes);
 	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
 	ctp->chan_ptr->ddma_dbell = 0;
 
@@ -693,7 +693,7 @@
 	 */
 	dma_cache_inv((unsigned long)buf, nbytes);
 	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
 	ctp->chan_ptr->ddma_dbell = 0;
 
@@ -760,7 +760,7 @@
 
 	cp = ctp->chan_ptr;
 	cp->ddma_cfg &= ~DDMA_CFG_EN;	/* Disable channel */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	while (!(cp->ddma_stat & DDMA_STAT_H)) {
 		udelay(1);
 		halt_timeout++;
@@ -771,7 +771,7 @@
 	}
 	/* clear current desc valid and doorbell */
 	cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_stop);
 
@@ -789,9 +789,9 @@
 	cp = ctp->chan_ptr;
 	cp->ddma_desptr = virt_to_phys(ctp->cur_ptr);
 	cp->ddma_cfg |= DDMA_CFG_EN;	/* Enable channel */
-	au_sync();
+	wmb(); /* drain writebuffer */
 	cp->ddma_dbell = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 EXPORT_SYMBOL(au1xxx_dbdma_start);
 
@@ -832,7 +832,7 @@
 
 	/* This is only valid if the channel is stopped. */
 	rv = cp->ddma_bytecnt;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	return rv;
 }
@@ -868,7 +868,7 @@
 	au1x_dma_chan_t *cp;
 
 	intstat = dbdma_gptr->ddma_intstat;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	chan_index = __ffs(intstat);
 
 	ctp = chan_tab_ptr[chan_index];
@@ -877,7 +877,7 @@
 
 	/* Reset interrupt. */
 	cp->ddma_irq = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (ctp->chan_callback)
 		ctp->chan_callback(irq, ctp->chan_callparam);
@@ -1061,7 +1061,7 @@
 	dbdma_gptr->ddma_config = 0;
 	dbdma_gptr->ddma_throttle = 0;
 	dbdma_gptr->ddma_inten = 0xffff;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	ret = request_irq(irq, dbdma_interrupt, 0, "dbdma", (void *)dbdma_gptr);
 	if (ret)
diff --git a/arch/mips/alchemy/common/dma.c b/arch/mips/alchemy/common/dma.c
index 9b624e2..4fb6207 100644
--- a/arch/mips/alchemy/common/dma.c
+++ b/arch/mips/alchemy/common/dma.c
@@ -141,17 +141,17 @@
 
 	printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr);
 	printk(KERN_INFO "  mode = 0x%08x\n",
-	       au_readl(chan->io + DMA_MODE_SET));
+	       __raw_readl(chan->io + DMA_MODE_SET));
 	printk(KERN_INFO "  addr = 0x%08x\n",
-	       au_readl(chan->io + DMA_PERIPHERAL_ADDR));
+	       __raw_readl(chan->io + DMA_PERIPHERAL_ADDR));
 	printk(KERN_INFO "  start0 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER0_START));
+	       __raw_readl(chan->io + DMA_BUFFER0_START));
 	printk(KERN_INFO "  start1 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER1_START));
+	       __raw_readl(chan->io + DMA_BUFFER1_START));
 	printk(KERN_INFO "  count0 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER0_COUNT));
+	       __raw_readl(chan->io + DMA_BUFFER0_COUNT));
 	printk(KERN_INFO "  count1 = 0x%08x\n",
-	       au_readl(chan->io + DMA_BUFFER1_COUNT));
+	       __raw_readl(chan->io + DMA_BUFFER1_COUNT));
 }
 
 /*
@@ -204,7 +204,8 @@
 	}
 
 	/* fill it in */
-	chan->io = KSEG1ADDR(AU1000_DMA_PHYS_ADDR) + i * DMA_CHANNEL_LEN;
+	chan->io = (void __iomem *)(KSEG1ADDR(AU1000_DMA_PHYS_ADDR) +
+			i * DMA_CHANNEL_LEN);
 	chan->dev_id = dev_id;
 	chan->dev_str = dev_str;
 	chan->fifo_addr = dev->fifo_addr;
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c
index 63a7181..6cb60ab 100644
--- a/arch/mips/alchemy/common/irq.c
+++ b/arch/mips/alchemy/common/irq.c
@@ -389,13 +389,12 @@
 		return -EINVAL;
 
 	local_irq_save(flags);
-	wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
+	wakemsk = alchemy_rdsys(AU1000_SYS_WAKEMSK);
 	if (on)
 		wakemsk |= 1 << bit;
 	else
 		wakemsk &= ~(1 << bit);
-	__raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
-	wmb();
+	alchemy_wrsys(wakemsk, AU1000_SYS_WAKEMSK);
 	local_irq_restore(flags);
 
 	return 0;
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index 9837a13..d77a64f 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -99,10 +100,20 @@
 
 static void __init alchemy_setup_uarts(int ctype)
 {
-	unsigned int uartclk = get_au1x00_uart_baud_base() * 16;
+	long uartclk;
 	int s = sizeof(struct plat_serial8250_port);
 	int c = alchemy_get_uarts(ctype);
 	struct plat_serial8250_port *ports;
+	struct clk *clk = clk_get(NULL, ALCHEMY_PERIPH_CLK);
+
+	if (IS_ERR(clk))
+		return;
+	if (clk_prepare_enable(clk)) {
+		clk_put(clk);
+		return;
+	}
+	uartclk = clk_get_rate(clk);
+	clk_put(clk);
 
 	ports = kzalloc(s * (c + 1), GFP_KERNEL);
 	if (!ports) {
@@ -420,7 +431,7 @@
 		memcpy(au1xxx_eth1_platform_data.mac, ethaddr, 6);
 
 	/* Register second MAC if enabled in pinfunc */
-	if (!(au_readl(SYS_PINFUNC) & (u32)SYS_PF_NI2)) {
+	if (!(alchemy_rdsys(AU1000_SYS_PINFUNC) & SYS_PF_NI2)) {
 		ret = platform_device_register(&au1xxx_eth1_device);
 		if (ret)
 			printk(KERN_INFO "Alchemy: failed to register MAC1\n");
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index bdb28dee..921ed30 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -54,28 +54,28 @@
 static void save_core_regs(void)
 {
 	/* Clocks and PLLs. */
-	sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
-	sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
-	sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
-	sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
-	sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
+	sleep_sys_clocks[0] = alchemy_rdsys(AU1000_SYS_FREQCTRL0);
+	sleep_sys_clocks[1] = alchemy_rdsys(AU1000_SYS_FREQCTRL1);
+	sleep_sys_clocks[2] = alchemy_rdsys(AU1000_SYS_CLKSRC);
+	sleep_sys_clocks[3] = alchemy_rdsys(AU1000_SYS_CPUPLL);
+	sleep_sys_clocks[4] = alchemy_rdsys(AU1000_SYS_AUXPLL);
 
 	/* pin mux config */
-	sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
+	sleep_sys_pinfunc = alchemy_rdsys(AU1000_SYS_PINFUNC);
 
 	/* Save the static memory controller configuration. */
-	sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
-	sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0);
-	sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0);
-	sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1);
-	sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1);
-	sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1);
-	sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2);
-	sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2);
-	sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2);
-	sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
-	sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
-	sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+	sleep_static_memctlr[0][0] = alchemy_rdsmem(AU1000_MEM_STCFG0);
+	sleep_static_memctlr[0][1] = alchemy_rdsmem(AU1000_MEM_STTIME0);
+	sleep_static_memctlr[0][2] = alchemy_rdsmem(AU1000_MEM_STADDR0);
+	sleep_static_memctlr[1][0] = alchemy_rdsmem(AU1000_MEM_STCFG1);
+	sleep_static_memctlr[1][1] = alchemy_rdsmem(AU1000_MEM_STTIME1);
+	sleep_static_memctlr[1][2] = alchemy_rdsmem(AU1000_MEM_STADDR1);
+	sleep_static_memctlr[2][0] = alchemy_rdsmem(AU1000_MEM_STCFG2);
+	sleep_static_memctlr[2][1] = alchemy_rdsmem(AU1000_MEM_STTIME2);
+	sleep_static_memctlr[2][2] = alchemy_rdsmem(AU1000_MEM_STADDR2);
+	sleep_static_memctlr[3][0] = alchemy_rdsmem(AU1000_MEM_STCFG3);
+	sleep_static_memctlr[3][1] = alchemy_rdsmem(AU1000_MEM_STTIME3);
+	sleep_static_memctlr[3][2] = alchemy_rdsmem(AU1000_MEM_STADDR3);
 }
 
 static void restore_core_regs(void)
@@ -85,30 +85,28 @@
 	 * one of those Au1000 with a write-only PLL, where we dont
 	 * have a valid value)
 	 */
-	au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
-	au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
-	au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
-	au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+	alchemy_wrsys(sleep_sys_clocks[0], AU1000_SYS_FREQCTRL0);
+	alchemy_wrsys(sleep_sys_clocks[1], AU1000_SYS_FREQCTRL1);
+	alchemy_wrsys(sleep_sys_clocks[2], AU1000_SYS_CLKSRC);
+	alchemy_wrsys(sleep_sys_clocks[4], AU1000_SYS_AUXPLL);
 	if (!au1xxx_cpu_has_pll_wo())
-		au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
-	au_sync();
+		alchemy_wrsys(sleep_sys_clocks[3], AU1000_SYS_CPUPLL);
 
-	au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
-	au_sync();
+	alchemy_wrsys(sleep_sys_pinfunc, AU1000_SYS_PINFUNC);
 
 	/* Restore the static memory controller configuration. */
-	au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
-	au_writel(sleep_static_memctlr[0][1], MEM_STTIME0);
-	au_writel(sleep_static_memctlr[0][2], MEM_STADDR0);
-	au_writel(sleep_static_memctlr[1][0], MEM_STCFG1);
-	au_writel(sleep_static_memctlr[1][1], MEM_STTIME1);
-	au_writel(sleep_static_memctlr[1][2], MEM_STADDR1);
-	au_writel(sleep_static_memctlr[2][0], MEM_STCFG2);
-	au_writel(sleep_static_memctlr[2][1], MEM_STTIME2);
-	au_writel(sleep_static_memctlr[2][2], MEM_STADDR2);
-	au_writel(sleep_static_memctlr[3][0], MEM_STCFG3);
-	au_writel(sleep_static_memctlr[3][1], MEM_STTIME3);
-	au_writel(sleep_static_memctlr[3][2], MEM_STADDR3);
+	alchemy_wrsmem(sleep_static_memctlr[0][0], AU1000_MEM_STCFG0);
+	alchemy_wrsmem(sleep_static_memctlr[0][1], AU1000_MEM_STTIME0);
+	alchemy_wrsmem(sleep_static_memctlr[0][2], AU1000_MEM_STADDR0);
+	alchemy_wrsmem(sleep_static_memctlr[1][0], AU1000_MEM_STCFG1);
+	alchemy_wrsmem(sleep_static_memctlr[1][1], AU1000_MEM_STTIME1);
+	alchemy_wrsmem(sleep_static_memctlr[1][2], AU1000_MEM_STADDR1);
+	alchemy_wrsmem(sleep_static_memctlr[2][0], AU1000_MEM_STCFG2);
+	alchemy_wrsmem(sleep_static_memctlr[2][1], AU1000_MEM_STTIME2);
+	alchemy_wrsmem(sleep_static_memctlr[2][2], AU1000_MEM_STADDR2);
+	alchemy_wrsmem(sleep_static_memctlr[3][0], AU1000_MEM_STCFG3);
+	alchemy_wrsmem(sleep_static_memctlr[3][1], AU1000_MEM_STTIME3);
+	alchemy_wrsmem(sleep_static_memctlr[3][2], AU1000_MEM_STADDR3);
 }
 
 void au_sleep(void)
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index 8267e3c..ea8f418 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -27,12 +27,9 @@
 
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
 
 #include <asm/dma-coherence.h>
 #include <asm/mipsregs.h>
-#include <asm/time.h>
 
 #include <au1000.h>
 
@@ -41,18 +38,6 @@
 
 void __init plat_mem_setup(void)
 {
-	unsigned long est_freq;
-
-	/* determine core clock */
-	est_freq = au1xxx_calc_clock();
-	est_freq += 5000;    /* round */
-	est_freq -= est_freq % 10000;
-	printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
-	       est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
-
-	/* this is faster than wasting cycles trying to approximate it */
-	preset_lpj = (est_freq >> 1) / HZ;
-
 	if (au1xxx_cpu_needs_config_od())
 		/* Various early Au1xx0 errata corrected by this */
 		set_c0_config(1 << 19); /* Set Config[OD] */
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c
index 93fa586..50e17e1 100644
--- a/arch/mips/alchemy/common/time.c
+++ b/arch/mips/alchemy/common/time.c
@@ -46,7 +46,7 @@
 
 static cycle_t au1x_counter1_read(struct clocksource *cs)
 {
-	return au_readl(SYS_RTCREAD);
+	return alchemy_rdsys(AU1000_SYS_RTCREAD);
 }
 
 static struct clocksource au1x_counter1_clocksource = {
@@ -60,12 +60,11 @@
 static int au1x_rtcmatch2_set_next_event(unsigned long delta,
 					 struct clock_event_device *cd)
 {
-	delta += au_readl(SYS_RTCREAD);
+	delta += alchemy_rdsys(AU1000_SYS_RTCREAD);
 	/* wait for register access */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21)
 		;
-	au_writel(delta, SYS_RTCMATCH2);
-	au_sync();
+	alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2);
 
 	return 0;
 }
@@ -112,31 +111,29 @@
 	 * (the 32S bit seems to be stuck set to 1 once a single clock-
 	 * edge is detected, hence the timeouts).
 	 */
-	if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+	if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK))
 		goto cntr_err;
 
 	/*
 	 * setup counter 1 (RTC) to tick at full speed
 	 */
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
 
-	au_writel(0, SYS_RTCTRIM);	/* 32.768 kHz */
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_RTCTRIM);	/* 32.768 kHz */
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
-	au_writel(0, SYS_RTCWRITE);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_RTCWRITE);
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
+	while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c
index d193dbe..297805a 100644
--- a/arch/mips/alchemy/common/usb.c
+++ b/arch/mips/alchemy/common/usb.c
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -387,10 +388,25 @@
 	udelay(1000);
 }
 
-static inline void au1000_usb_init(unsigned long rb, int reg)
+static inline int au1000_usb_init(unsigned long rb, int reg)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
 	unsigned long r = __raw_readl(base);
+	struct clk *c;
+
+	/* 48MHz check. Don't init if no one can provide it */
+	c = clk_get(NULL, "usbh_clk");
+	if (IS_ERR(c))
+		return -ENODEV;
+	if (clk_round_rate(c, 48000000) != 48000000) {
+		clk_put(c);
+		return -ENODEV;
+	}
+	if (clk_set_rate(c, 48000000)) {
+		clk_put(c);
+		return -ENODEV;
+	}
+	clk_put(c);
 
 #if defined(__BIG_ENDIAN)
 	r |= USBHEN_BE;
@@ -400,6 +416,8 @@
 	__raw_writel(r, base);
 	wmb();
 	udelay(1000);
+
+	return 0;
 }
 
 
@@ -407,8 +425,15 @@
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
 	unsigned long r = __raw_readl(base + creg);
+	struct clk *c = clk_get(NULL, "usbh_clk");
+
+	if (IS_ERR(c))
+		return;
 
 	if (enable) {
+		if (clk_prepare_enable(c))
+			goto out;
+
 		__raw_writel(r | USBHEN_CE, base + creg);
 		wmb();
 		udelay(1000);
@@ -423,7 +448,10 @@
 	} else {
 		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
 		wmb();
+		clk_disable_unprepare(c);
 	}
+out:
+	clk_put(c);
 }
 
 static inline int au1000_usb_control(int block, int enable, unsigned long rb,
@@ -457,11 +485,11 @@
 	case ALCHEMY_CPU_AU1500:
 	case ALCHEMY_CPU_AU1100:
 		ret = au1000_usb_control(block, enable,
-				AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+			AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1550:
 		ret = au1000_usb_control(block, enable,
-				AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+			AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1200:
 		ret = au1200_usb_control(block, enable);
@@ -569,14 +597,18 @@
 
 static int __init alchemy_usb_init(void)
 {
+	int ret = 0;
+
 	switch (alchemy_get_cputype()) {
 	case ALCHEMY_CPU_AU1000:
 	case ALCHEMY_CPU_AU1500:
 	case ALCHEMY_CPU_AU1100:
-		au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
+		ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
+				      AU1000_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1550:
-		au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
+		ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
+				      AU1550_OHCICFG);
 		break;
 	case ALCHEMY_CPU_AU1200:
 		au1200_usb_init();
@@ -586,8 +618,9 @@
 		break;
 	}
 
-	register_syscore_ops(&alchemy_usb_pm_ops);
+	if (!ret)
+		register_syscore_ops(&alchemy_usb_pm_ops);
 
-	return 0;
+	return ret;
 }
 arch_initcall(alchemy_usb_init);
diff --git a/arch/mips/alchemy/devboards/db1000.c b/arch/mips/alchemy/devboards/db1000.c
index 92dd929..001102e 100644
--- a/arch/mips/alchemy/devboards/db1000.c
+++ b/arch/mips/alchemy/devboards/db1000.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
@@ -496,6 +497,7 @@
 	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
 	unsigned long pfc;
+	struct clk *c, *p;
 
 	if (board == BCSR_WHOAMI_DB1500) {
 		c0 = AU1500_GPIO2_INT;
@@ -518,14 +520,25 @@
 		gpio_direction_input(20);	/* sd1 cd# */
 
 		/* spi_gpio on SSI0 pins */
-		pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
+		pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
 		pfc |= (1 << 0);	/* SSI0 pins as GPIOs */
-		__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-		wmb();
+		alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
 		spi_register_board_info(db1100_spi_info,
 					ARRAY_SIZE(db1100_spi_info));
 
+		/* link LCD clock to AUXPLL */
+		p = clk_get(NULL, "auxpll_clk");
+		c = clk_get(NULL, "lcd_intclk");
+		if (!IS_ERR(c) && !IS_ERR(p)) {
+			clk_set_parent(c, p);
+			clk_set_rate(c, clk_get_rate(p));
+		}
+		if (!IS_ERR(c))
+			clk_put(c);
+		if (!IS_ERR(p))
+			clk_put(p);
+
 		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
 		platform_device_register(&db1100_spi_dev);
 	} else if (board == BCSR_WHOAMI_DB1000) {
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 9e46667..7761889 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -129,7 +130,6 @@
 
 int __init db1200_board_setup(void)
 {
-	unsigned long freq0, clksrc, div, pfc;
 	unsigned short whoami;
 
 	if (db1200_detect_board())
@@ -149,34 +149,6 @@
 		"  Board-ID %d	Daughtercard ID %d\n", get_system_type(),
 		(whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
 
-	/* SMBus/SPI on PSC0, Audio on PSC1 */
-	pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
-	pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
-	pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
-	pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
-	__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-	wmb();
-
-	/* Clock configurations: PSC0: ~50MHz via Clkgen0, derived from
-	 * CPU clock; all other clock generators off/unused.
-	 */
-	div = (get_au1x00_speed() + 25000000) / 50000000;
-	if (div & 1)
-		div++;
-	div = ((div >> 1) - 1) & 0xff;
-
-	freq0 = div << SYS_FC_FRDIV0_BIT;
-	__raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-	wmb();
-	freq0 |= SYS_FC_FE0;	/* enable F0 */
-	__raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
-	wmb();
-
-	/* psc0_intclk comes 1:1 from F0 */
-	clksrc = SYS_CS_MUX_FQ0 << SYS_CS_ME0_BIT;
-	__raw_writel(clksrc, (void __iomem *)SYS_CLKSRC);
-	wmb();
-
 	return 0;
 }
 
@@ -250,7 +222,7 @@
 
 static int au1200_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1200_nand_parts[] = {
@@ -847,6 +819,7 @@
 	unsigned long pfc;
 	unsigned short sw;
 	int swapped, bid;
+	struct clk *c;
 
 	bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 	if ((bid == BCSR_WHOAMI_PB1200_DDR1) ||
@@ -859,6 +832,24 @@
 	irq_set_irq_type(AU1200_GPIO7_INT, IRQ_TYPE_LEVEL_LOW);
 	bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
 
+	/* SMBus/SPI on PSC0, Audio on PSC1 */
+	pfc = alchemy_rdsys(AU1000_SYS_PINFUNC);
+	pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
+	pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
+	pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
+	alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
+
+	/* get 50MHz for I2C driver on PSC0 */
+	c = clk_get(NULL, "psc0_intclk");
+	if (!IS_ERR(c)) {
+		pfc = clk_round_rate(c, 50000000);
+		if ((pfc < 1) || (abs(50000000 - pfc) > 2500000))
+			pr_warn("DB1200: cant get I2C close to 50MHz\n");
+		else
+			clk_set_rate(c, pfc);
+		clk_put(c);
+	}
+
 	/* insert/eject pairs: one of both is always screaming.	 To avoid
 	 * issues they must not be automatically enabled when initially
 	 * requested.
@@ -886,7 +877,7 @@
 	 * As a result, in SPI mode, OTG simply won't work (PSC0 uses
 	 * it as an input pin which is pulled high on the boards).
 	 */
-	pfc = __raw_readl((void __iomem *)SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
+	pfc = alchemy_rdsys(AU1000_SYS_PINFUNC) & ~SYS_PINFUNC_P0A;
 
 	/* switch off OTG VBUS supply */
 	gpio_request(215, "otg-vbus");
@@ -912,8 +903,7 @@
 		printk(KERN_INFO " S6.8 ON : PSC0 mode SPI\n");
 		printk(KERN_INFO "   OTG port VBUS supply disabled\n");
 	}
-	__raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
-	wmb();
+	alchemy_wrsys(pfc, AU1000_SYS_PINFUNC);
 
 	/* Audio: DIP7 selects I2S(0)/AC97(1), but need I2C for I2S!
 	 * so: DIP7=1 || DIP8=0 => AC97, DIP7=0 && DIP8=1 => I2S
@@ -932,6 +922,11 @@
 	}
 
 	/* Audio PSC clock is supplied externally. (FIXME: platdata!!) */
+	c = clk_get(NULL, "psc1_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
 	__raw_writel(PSC_SEL_CLK_SERCLK,
 	    (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index 1aed6be..ef93ee3 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -4,6 +4,7 @@
  * (c) 2009 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
@@ -169,7 +170,7 @@
 
 static int au1300_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1300_nand_parts[] = {
@@ -731,6 +732,7 @@
 int __init db1300_dev_setup(void)
 {
 	int swapped, cpldirq;
+	struct clk *c;
 
 	/* setup CPLD IRQ muxer */
 	cpldirq = au1300_gpio_to_irq(AU1300_PIN_EXTCLK1);
@@ -761,6 +763,11 @@
 	    (void __iomem *)KSEG1ADDR(AU1300_PSC2_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
 	/* I2C uses internal 48MHz EXTCLK1 */
+	c = clk_get(NULL, "psc3_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
 	__raw_writel(PSC_SEL_CLK_INTCLK,
 	    (void __iomem *)KSEG1ADDR(AU1300_PSC3_PHYS_ADDR) + PSC_SEL_OFFSET);
 	wmb();
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index bbd8d98..7e89936 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -4,6 +4,7 @@
  * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
  */
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -31,16 +32,16 @@
 static void __init db1550_hw_setup(void)
 {
 	void __iomem *base;
+	unsigned long v;
 
 	/* complete SPI setup: link psc0_intclk to a 48MHz source,
 	 * and assign GPIO16 to PSC0_SYNC1 (SPI cs# line) as well as PSC1_SYNC
 	 * for AC97 on PB1550.
 	 */
-	base = (void __iomem *)SYS_CLKSRC;
-	__raw_writel(__raw_readl(base) | 0x000001e0, base);
-	base = (void __iomem *)SYS_PINFUNC;
-	__raw_writel(__raw_readl(base) | 1 | SYS_PF_PSC1_S1, base);
-	wmb();
+	v = alchemy_rdsys(AU1000_SYS_CLKSRC);
+	alchemy_wrsys(v | 0x000001e0, AU1000_SYS_CLKSRC);
+	v = alchemy_rdsys(AU1000_SYS_PINFUNC);
+	alchemy_wrsys(v | 1 | SYS_PF_PSC1_S1, AU1000_SYS_PINFUNC);
 
 	/* reset the AC97 codec now, the reset time in the psc-ac97 driver
 	 * is apparently too short although it's ridiculous as it is.
@@ -151,7 +152,7 @@
 
 static int au1550_nand_device_ready(struct mtd_info *mtd)
 {
-	return __raw_readl((void __iomem *)MEM_STSTAT) & 1;
+	return alchemy_rdsmem(AU1000_MEM_STSTAT) & 1;
 }
 
 static struct mtd_partition db1550_nand_parts[] = {
@@ -217,7 +218,7 @@
 
 static void __init pb1550_nand_setup(void)
 {
-	int boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) |
+	int boot_swapboot = (alchemy_rdsmem(AU1000_MEM_STSTAT) & (0x7 << 1)) |
 			    ((bcsr_read(BCSR_STATUS) >> 6) & 0x1);
 
 	gpio_direction_input(206);	/* de-assert NAND CS# */
@@ -574,6 +575,7 @@
 int __init db1550_dev_setup(void)
 {
 	int swapped, id;
+	struct clk *c;
 
 	id = (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) != BCSR_WHOAMI_DB1550);
 
@@ -582,6 +584,17 @@
 	spi_register_board_info(db1550_spi_devs,
 				ARRAY_SIZE(db1550_i2c_devs));
 
+	c = clk_get(NULL, "psc0_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
+	c = clk_get(NULL, "psc2_intclk");
+	if (!IS_ERR(c)) {
+		clk_prepare_enable(c);
+		clk_put(c);
+	}
+
 	/* Audio PSC clock is supplied by codecs (PSC1, 3) FIXME: platdata!! */
 	__raw_writel(PSC_SEL_CLK_SERCLK,
 	    (void __iomem *)KSEG1ADDR(AU1550_PSC1_PHYS_ADDR) + PSC_SEL_OFFSET);
diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c
index 61e90fe..bfeb8f3 100644
--- a/arch/mips/alchemy/devboards/pm.c
+++ b/arch/mips/alchemy/devboards/pm.c
@@ -45,23 +45,20 @@
 	alchemy_gpio1_input_enable();
 
 	/* clear and setup wake cause and source */
-	au_writel(0, SYS_WAKEMSK);
-	au_sync();
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 
-	au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
-	au_sync();
+	alchemy_wrsys(db1x_pm_wakemsk, AU1000_SYS_WAKEMSK);
 
 	/* setup 1Hz-timer-based wakeup: wait for reg access */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
 		asm volatile ("nop");
 
-	au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
-	au_sync();
+	alchemy_wrsys(alchemy_rdsys(AU1000_SYS_TOYREAD) + db1x_pm_sleep_secs,
+		      AU1000_SYS_TOYMATCH2);
 
 	/* wait for value to really hit the register */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M20)
 		asm volatile ("nop");
 
 	/* ...and now the sandman can come! */
@@ -102,12 +99,10 @@
 	/* read and store wakeup source, the clear the register. To
 	 * be able to clear it, WAKEMSK must be cleared first.
 	 */
-	db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+	db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
-	au_writel(0, SYS_WAKEMSK);
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
-
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
 }
 
 static const struct platform_suspend_ops db1x_pm_ops = {
@@ -242,17 +237,13 @@
 	 * for confirmation since there's plenty of time from here to
 	 * the next suspend cycle.
 	 */
-	if (au_readl(SYS_TOYTRIM) != 32767) {
-		au_writel(32767, SYS_TOYTRIM);
-		au_sync();
-	}
+	if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767)
+		alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
 
-	db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+	db1x_pm_last_wakesrc = alchemy_rdsys(AU1000_SYS_WAKESRC);
 
-	au_writel(0, SYS_WAKESRC);
-	au_sync();
-	au_writel(0, SYS_WAKEMSK);
-	au_sync();
+	alchemy_wrsys(0, AU1000_SYS_WAKESRC);
+	alchemy_wrsys(0, AU1000_SYS_WAKEMSK);
 
 	suspend_set_ops(&db1x_pm_ops);
 
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index 09cb6f7..fc21d36 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -11,8 +11,6 @@
 	select SSB_DRIVER_PCICORE if PCI
 	select SSB_PCICORE_HOSTMODE if PCI
 	select SSB_DRIVER_GPIO
-	select GPIOLIB
-	select LEDS_GPIO_REGISTER
 	default y
 	help
 	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -22,6 +20,7 @@
 config BCM47XX_BCMA
 	bool "BCMA Support for Broadcom BCM47XX"
 	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_HIGHMEM
 	select CPU_MIPSR2_IRQ_VI
 	select BCMA
 	select BCMA_HOST_SOC
@@ -29,8 +28,6 @@
 	select BCMA_HOST_PCI if PCI
 	select BCMA_DRIVER_PCI_HOSTMODE if PCI
 	select BCMA_DRIVER_GPIO
-	select GPIOLIB
-	select LEDS_GPIO_REGISTER
 	default y
 	help
 	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/bcm47xx/bcm47xx_private.h b/arch/mips/bcm47xx/bcm47xx_private.h
index 0194c3b..f1cc9d0 100644
--- a/arch/mips/bcm47xx/bcm47xx_private.h
+++ b/arch/mips/bcm47xx/bcm47xx_private.h
@@ -3,6 +3,9 @@
 
 #include <linux/kernel.h>
 
+/* prom.c */
+void __init bcm47xx_prom_highmem_init(void);
+
 /* buttons.c */
 int __init bcm47xx_buttons_register(void);
 
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
index 44ab1be..b3ae068 100644
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -58,6 +58,7 @@
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
 	{{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RTN10U"},
+	{{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RTN10D"},
 	{{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
 	{{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RTN12B1"},
 	{{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RTN12C1"},
@@ -80,6 +81,14 @@
 	{ {0}, NULL},
 };
 
+/* hardware_version, boardnum */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_hw_version_num[] __initconst = {
+	{{BCM47XX_BOARD_MICROSOFT_MN700, "Microsoft MN-700"}, "WL500-", "mn700"},
+	{{BCM47XX_BOARD_ASUS_WL500G, "Asus WL500G"}, "WL500-", "asusX"},
+	{ {0}, NULL},
+};
+
 /* productid */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
@@ -98,7 +107,7 @@
 /* ModelId */
 static const
 struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
-	{{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+	{{BCM47XX_BOARD_DELL_TM2300, "Dell TrueMobile 2300"}, "WX-5565"},
 	{{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
 	{{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
 	{{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
@@ -180,9 +189,9 @@
 	{{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
 	{{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
 	{{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "0x04CF", "3500", "02"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
-	{{BCM47XX_BOARD_LINKSYS_WRT54G, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, "Linksys WRT54G/GS/GL"}, "0x0101", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, "Linksys WRT54G/GS/GL"}, "0x0467", "42", "0x10"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708, "Linksys WRT54G/GS/GL"}, "0x0708", "42", "0x10"},
 	{ {0}, NULL},
 };
 
@@ -237,6 +246,15 @@
 		}
 	}
 
+	if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv("boardtype", buf2, sizeof(buf2)) >= 0) {
+		for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+			if (!strstarts(buf1, e2->value1) &&
+			    !strcmp(buf2, e2->value2))
+				return &e2->board;
+		}
+	}
+
 	if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
 		for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
 			if (!strcmp(buf1, e1->value1))
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 49a1ce0..913182b 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -56,6 +56,11 @@
 };
 
 static const struct gpio_keys_button
+bcm47xx_buttons_asus_wl500g[] __initconst = {
+	BCM47XX_GPIO_KEY(6, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
 bcm47xx_buttons_asus_wl500gd[] __initconst = {
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -265,7 +270,7 @@
 };
 
 static const struct gpio_keys_button
-bcm47xx_buttons_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_buttons_linksys_wrt54g_generic[] __initconst = {
 	BCM47XX_GPIO_KEY(4, KEY_WPS_BUTTON),
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -288,6 +293,13 @@
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
 
+/* Microsoft */
+
+static const struct gpio_keys_button
+bcm47xx_buttons_microsoft_nm700[] __initconst = {
+	BCM47XX_GPIO_KEY(7, KEY_RESTART),
+};
+
 /* Motorola */
 
 static const struct gpio_keys_button
@@ -329,6 +341,12 @@
 };
 
 static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
+	BCM47XX_GPIO_KEY(4, KEY_RESTART),
+	BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
+};
+
+static const struct gpio_keys_button
 bcm47xx_buttons_netgear_wnr834bv2[] __initconst = {
 	BCM47XX_GPIO_KEY(6, KEY_RESTART),
 };
@@ -395,6 +413,9 @@
 	case BCM47XX_BOARD_ASUS_WL330GE:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl330ge);
 		break;
+	case BCM47XX_BOARD_ASUS_WL500G:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500g);
+		break;
 	case BCM47XX_BOARD_ASUS_WL500GD:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_wl500gd);
 		break;
@@ -501,12 +522,14 @@
 	case BCM47XX_BOARD_LINKSYS_WRT310NV1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1);
 		break;
-	case BCM47XX_BOARD_LINKSYS_WRT54G:
-		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54gsv1);
-		break;
 	case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2);
 		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g_generic);
+		break;
 	case BCM47XX_BOARD_LINKSYS_WRT610NV1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt610nv1);
 		break;
@@ -517,6 +540,10 @@
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrtsl54gs);
 		break;
 
+	case BCM47XX_BOARD_MICROSOFT_MN700:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_microsoft_nm700);
+		break;
+
 	case BCM47XX_BOARD_MOTOROLA_WE800G:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_we800g);
 		break;
@@ -536,6 +563,9 @@
 	case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
 		break;
+	case BCM47XX_BOARD_NETGEAR_WNR3500L:
+		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
+		break;
 	case BCM47XX_BOARD_NETGEAR_WNR834BV2:
 		err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr834bv2);
 		break;
diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c
index adcb547..903a656 100644
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -35,6 +35,15 @@
 };
 
 static const struct gpio_led
+bcm47xx_leds_asus_rtn15u[] __initconst = {
+	/* TODO: Add "wlan" LED */
+	BCM47XX_GPIO_LED(3, "blue", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(4, "blue", "lan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(9, "blue", "usb", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
 bcm47xx_leds_asus_rtn16[] __initconst = {
 	BCM47XX_GPIO_LED(1, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(7, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -42,8 +51,8 @@
 
 static const struct gpio_led
 bcm47xx_leds_asus_rtn66u[] __initconst = {
-	BCM47XX_GPIO_LED(12, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
-	BCM47XX_GPIO_LED(15, "unk", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(12, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(15, "blue", "usb", 1, LEDS_GPIO_DEFSTATE_OFF),
 };
 
 static const struct gpio_led
@@ -64,6 +73,11 @@
 };
 
 static const struct gpio_led
+bcm47xx_leds_asus_wl500g[] __initconst = {
+	BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+};
+
+static const struct gpio_led
 bcm47xx_leds_asus_wl500gd[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 };
@@ -216,8 +230,8 @@
 
 static const struct gpio_led
 bcm47xx_leds_linksys_e1000v21[] __initconst = {
-	BCM47XX_GPIO_LED(5, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(6, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(5, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(6, "blue", "power", 1, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(7, "amber", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
 	BCM47XX_GPIO_LED(8, "blue", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
@@ -292,7 +306,7 @@
 };
 
 static const struct gpio_led
-bcm47xx_leds_linksys_wrt54gsv1[] __initconst = {
+bcm47xx_leds_linksys_wrt54g_generic[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
 	BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -306,6 +320,24 @@
 	BCM47XX_GPIO_LED(3, "blue", "3g", 0, LEDS_GPIO_DEFSTATE_OFF),
 };
 
+/* Verified on: WRT54GS V1.0 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0101[] __initconst = {
+	BCM47XX_GPIO_LED(0, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Verified on: WRT54GL V1.1 */
+static const struct gpio_led
+bcm47xx_leds_linksys_wrt54g_type_0467[] __initconst = {
+	BCM47XX_GPIO_LED(0, "green", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(7, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
 static const struct gpio_led
 bcm47xx_leds_linksys_wrt610nv1[] __initconst = {
 	BCM47XX_GPIO_LED(0, "unk", "usb",  1, LEDS_GPIO_DEFSTATE_OFF),
@@ -325,11 +357,17 @@
 
 static const struct gpio_led
 bcm47xx_leds_linksys_wrtsl54gs[] __initconst = {
-	BCM47XX_GPIO_LED(0, "unk", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
-	BCM47XX_GPIO_LED(2, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(3, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
-	BCM47XX_GPIO_LED(7, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(0, "green", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(5, "white", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(7, "orange", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+/* Microsoft */
+
+static const struct gpio_led
+bcm47xx_leds_microsoft_nm700[] __initconst = {
+	BCM47XX_GPIO_LED(6, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 };
 
 /* Motorola */
@@ -377,6 +415,15 @@
 };
 
 static const struct gpio_led
+bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
+	BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(2, "green", "wan", 1, LEDS_GPIO_DEFSTATE_OFF),
+	BCM47XX_GPIO_LED(3, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
+	BCM47XX_GPIO_LED(7, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
 bcm47xx_leds_netgear_wnr834bv2[] __initconst = {
 	BCM47XX_GPIO_LED(2, "green", "power", 0, LEDS_GPIO_DEFSTATE_ON),
 	BCM47XX_GPIO_LED(3, "amber", "power", 0, LEDS_GPIO_DEFSTATE_OFF),
@@ -417,6 +464,9 @@
 	case BCM47XX_BOARD_ASUS_RTN12:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12);
 		break;
+	case BCM47XX_BOARD_ASUS_RTN15U:
+		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn15u);
+		break;
 	case BCM47XX_BOARD_ASUS_RTN16:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_rtn16);
 		break;
@@ -432,6 +482,9 @@
 	case BCM47XX_BOARD_ASUS_WL330GE:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_wl330ge);
 		break;
+	case BCM47XX_BOARD_ASUS_WL500G:
+		bcm47xx_set_pdata(bcm47xx_leds_asus_wl500g);
+		break;
 	case BCM47XX_BOARD_ASUS_WL500GD:
 		bcm47xx_set_pdata(bcm47xx_leds_asus_wl500gd);
 		break;
@@ -538,12 +591,18 @@
 	case BCM47XX_BOARD_LINKSYS_WRT310NV1:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1);
 		break;
-	case BCM47XX_BOARD_LINKSYS_WRT54G:
-		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54gsv1);
-		break;
 	case BCM47XX_BOARD_LINKSYS_WRT54G3GV2:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2);
 		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0101);
+		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_type_0467);
+		break;
+	case BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708:
+		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g_generic);
+		break;
 	case BCM47XX_BOARD_LINKSYS_WRT610NV1:
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt610nv1);
 		break;
@@ -554,6 +613,10 @@
 		bcm47xx_set_pdata(bcm47xx_leds_linksys_wrtsl54gs);
 		break;
 
+	case BCM47XX_BOARD_MICROSOFT_MN700:
+		bcm47xx_set_pdata(bcm47xx_leds_microsoft_nm700);
+		break;
+
 	case BCM47XX_BOARD_MOTOROLA_WE800G:
 		bcm47xx_set_pdata(bcm47xx_leds_motorola_we800g);
 		break;
@@ -570,6 +633,9 @@
 	case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
 		bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
 		break;
+	case BCM47XX_BOARD_NETGEAR_WNR3500L:
+		bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
+		break;
 	case BCM47XX_BOARD_NETGEAR_WNR834BV2:
 		bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr834bv2);
 		break;
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index 1a03a2f..1b170bf 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -51,6 +51,8 @@
 		 chip_id);
 }
 
+static unsigned long lowmem __initdata;
+
 static __init void prom_init_mem(void)
 {
 	unsigned long mem;
@@ -87,6 +89,7 @@
 		if (!memcmp(prom_init, prom_init + mem, 32))
 			break;
 	}
+	lowmem = mem;
 
 	/* Ignoring the last page when ddr size is 128M. Cached
 	 * accesses to last page is causing the processor to prefetch
@@ -95,7 +98,6 @@
 	 */
 	if (c->cputype == CPU_74K && (mem == (128  << 20)))
 		mem -= 0x1000;
-
 	add_memory_region(0, mem, BOOT_MEM_RAM);
 }
 
@@ -114,3 +116,67 @@
 void __init prom_free_prom_memory(void)
 {
 }
+
+#if defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM)
+
+#define EXTVBASE	0xc0000000
+#define ENTRYLO(x)	((pte_val(pfn_pte((x) >> _PFN_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6) | 1)
+
+#include <asm/tlbflush.h>
+
+/* Stripped version of tlb_init, with the call to build_tlb_refill_handler
+ * dropped. Calling it at this stage causes a hang.
+ */
+void __cpuinit early_tlb_init(void)
+{
+	write_c0_pagemask(PM_DEFAULT_MASK);
+	write_c0_wired(0);
+	temp_tlb_entry = current_cpu_data.tlbsize - 1;
+	local_flush_tlb_all();
+}
+
+void __init bcm47xx_prom_highmem_init(void)
+{
+	unsigned long off = (unsigned long)prom_init;
+	unsigned long extmem = 0;
+	bool highmem_region = false;
+
+	if (WARN_ON(bcm47xx_bus_type != BCM47XX_BUS_TYPE_BCMA))
+		return;
+
+	if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
+		highmem_region = true;
+
+	if (lowmem != 128 << 20 || !highmem_region)
+		return;
+
+	early_tlb_init();
+
+	/* Add one temporary TLB entry to map SDRAM Region 2.
+	 *      Physical        Virtual
+	 *      0x80000000      0xc0000000      (1st: 256MB)
+	 *      0x90000000      0xd0000000      (2nd: 256MB)
+	 */
+	add_temporary_entry(ENTRYLO(0x80000000),
+			    ENTRYLO(0x80000000 + (256 << 20)),
+			    EXTVBASE, PM_256M);
+
+	off = EXTVBASE + __pa(off);
+	for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
+		if (!memcmp(prom_init, (void *)(off + extmem), 16))
+			break;
+	}
+	extmem -= lowmem;
+
+	early_tlb_init();
+
+	if (!extmem)
+		return;
+
+	pr_warn("Found %lu MiB of extra memory, but highmem is unsupported yet!\n",
+		extmem >> 20);
+
+	/* TODO: Register extra memory */
+}
+
+#endif /* defined(CONFIG_BCM47XX_BCMA) && defined(CONFIG_HIGHMEM) */
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 63a4b0e..2b63e7e 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -59,12 +59,12 @@
 	switch (bcm47xx_bus_type) {
 #ifdef CONFIG_BCM47XX_SSB
 	case BCM47XX_BUS_TYPE_SSB:
-		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 1);
+		ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 3);
 		break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
 	case BCM47XX_BUS_TYPE_BCMA:
-		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 1);
+		bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 3);
 		break;
 #endif
 	}
@@ -218,6 +218,9 @@
 		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
 		bcm47xx_register_bcma();
 		bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
+#ifdef CONFIG_HIGHMEM
+		bcm47xx_prom_highmem_init();
+#endif
 #endif
 	} else {
 		printk(KERN_INFO "bcm47xx: using ssb bus\n");
diff --git a/arch/mips/bcm47xx/sprom.c b/arch/mips/bcm47xx/sprom.c
index da4cdb1..41226b6 100644
--- a/arch/mips/bcm47xx/sprom.c
+++ b/arch/mips/bcm47xx/sprom.c
@@ -28,6 +28,8 @@
 
 #include <bcm47xx.h>
 #include <bcm47xx_nvram.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 static void create_key(const char *prefix, const char *postfix,
 		       const char *name, char *buf, int len)
@@ -631,6 +633,33 @@
 	}
 }
 
+static bool bcm47xx_is_valid_mac(u8 *mac)
+{
+	return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
+}
+
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
+{
+	u8 *oui = mac + ETH_ALEN/2 - 1;
+	u8 *p = mac + ETH_ALEN - 1;
+
+	do {
+		(*p) += num;
+		if (*p > num)
+			break;
+		p--;
+		num = 1;
+	} while (p != oui);
+
+	if (p == oui) {
+		pr_err("unable to fetch mac address\n");
+		return -ENOENT;
+	}
+	return 0;
+}
+
+static int mac_addr_used = 2;
+
 static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
 					const char *prefix, bool fallback)
 {
@@ -648,6 +677,25 @@
 
 	nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
 	nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+
+	/* The address prefix 00:90:4C is used by Broadcom in their initial
+	   configuration. When a mac address with the prefix 00:90:4C is used
+	   all devices from the same series are sharing the same mac address.
+	   To prevent mac address collisions we replace them with a mac address
+	   based on the base address. */
+	if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
+		u8 mac[6];
+
+		nvram_read_macaddr(NULL, "et0macaddr", mac, false);
+		if (bcm47xx_is_valid_mac(mac)) {
+			int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
+
+			if (!err) {
+				ether_addr_copy(sprom->il0mac, mac);
+				mac_addr_used++;
+			}
+		}
+	}
 }
 
 static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c
index fd4e76c..536f644 100644
--- a/arch/mips/bcm63xx/cpu.c
+++ b/arch/mips/bcm63xx/cpu.c
@@ -24,7 +24,9 @@
 const int *bcm63xx_irqs;
 EXPORT_SYMBOL(bcm63xx_irqs);
 
-static u16 bcm63xx_cpu_id;
+u16 bcm63xx_cpu_id __read_mostly;
+EXPORT_SYMBOL(bcm63xx_cpu_id);
+
 static u8 bcm63xx_cpu_rev;
 static unsigned int bcm63xx_cpu_freq;
 static unsigned int bcm63xx_memory_size;
@@ -97,13 +99,6 @@
 
 };
 
-u16 __bcm63xx_get_cpu_id(void)
-{
-	return bcm63xx_cpu_id;
-}
-
-EXPORT_SYMBOL(__bcm63xx_get_cpu_id);
-
 u8 bcm63xx_get_cpu_rev(void)
 {
 	return bcm63xx_cpu_rev;
diff --git a/arch/mips/bcm63xx/dev-enet.c b/arch/mips/bcm63xx/dev-enet.c
index 52bc01d..e828477 100644
--- a/arch/mips/bcm63xx/dev-enet.c
+++ b/arch/mips/bcm63xx/dev-enet.c
@@ -14,7 +14,6 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 static const unsigned long bcm6348_regs_enetdmac[] = {
 	[ENETDMAC_CHANCFG]	= ENETDMAC_CHANCFG_REG,
 	[ENETDMAC_IR]		= ENETDMAC_IR_REG,
@@ -43,9 +42,6 @@
 	else
 		bcm63xx_regs_enetdmac = bcm6348_regs_enetdmac;
 }
-#else
-static __init void bcm63xx_enetdmac_regs_init(void) { }
-#endif
 
 static struct resource shared_res[] = {
 	{
diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c
index d12daed..ad448e41 100644
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -18,7 +18,6 @@
 #include <bcm63xx_dev_spi.h>
 #include <bcm63xx_regs.h>
 
-#ifdef BCMCPU_RUNTIME_DETECT
 /*
  * register offsets
  */
@@ -41,9 +40,6 @@
 		BCMCPU_IS_6362() || BCMCPU_IS_6368())
 		bcm63xx_regs_spi = bcm6358_regs_spi;
 }
-#else
-static __init void bcm63xx_spi_regs_init(void) { }
-#endif
 
 static struct resource spi_resources[] = {
 	{
diff --git a/arch/mips/bcm63xx/gpio.c b/arch/mips/bcm63xx/gpio.c
index a6c2135..468bc7b 100644
--- a/arch/mips/bcm63xx/gpio.c
+++ b/arch/mips/bcm63xx/gpio.c
@@ -18,19 +18,6 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_regs.h>
 
-#ifndef BCMCPU_RUNTIME_DETECT
-#define gpio_out_low_reg	GPIO_DATA_LO_REG
-#ifdef CONFIG_BCM63XX_CPU_6345
-#ifdef gpio_out_low_reg
-#undef gpio_out_low_reg
-#define gpio_out_low_reg	GPIO_DATA_LO_REG_6345
-#endif /* gpio_out_low_reg */
-#endif /* CONFIG_BCM63XX_CPU_6345 */
-
-static inline void bcm63xx_gpio_out_low_reg_init(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
 static u32 gpio_out_low_reg;
 
 static void bcm63xx_gpio_out_low_reg_init(void)
@@ -44,7 +31,6 @@
 		break;
 	}
 }
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static DEFINE_SPINLOCK(bcm63xx_gpio_lock);
 static u32 gpio_out_low, gpio_out_high;
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index 1525f8a..37eb2d1 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/spinlock.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
 #include <bcm63xx_cpu.h>
@@ -19,222 +20,20 @@
 #include <bcm63xx_io.h>
 #include <bcm63xx_irq.h>
 
-static void __dispatch_internal(void) __maybe_unused;
-static void __dispatch_internal_64(void) __maybe_unused;
-static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
 
-#ifndef BCMCPU_RUNTIME_DETECT
-#ifdef CONFIG_BCM63XX_CPU_3368
-#define irq_stat_reg		PERF_IRQSTAT_3368_REG
-#define irq_mask_reg		PERF_IRQMASK_3368_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_3368
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-#define irq_stat_reg		PERF_IRQSTAT_6328_REG
-#define irq_mask_reg		PERF_IRQMASK_6328_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6328
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-#define irq_stat_reg		PERF_IRQSTAT_6338_REG
-#define irq_mask_reg		PERF_IRQMASK_6338_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6338
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-#define irq_stat_reg		PERF_IRQSTAT_6345_REG
-#define irq_mask_reg		PERF_IRQMASK_6345_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6345
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-#define irq_stat_reg		PERF_IRQSTAT_6348_REG
-#define irq_mask_reg		PERF_IRQMASK_6348_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	0
-#define ext_irq_start		0
-#define ext_irq_end		0
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6348
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-#define irq_stat_reg		PERF_IRQSTAT_6358_REG
-#define irq_mask_reg		PERF_IRQMASK_6358_REG
-#define irq_bits		32
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6358
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-#define irq_stat_reg		PERF_IRQSTAT_6362_REG
-#define irq_mask_reg		PERF_IRQMASK_6362_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		4
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6362
-#define ext_irq_cfg_reg2	0
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-#define irq_stat_reg		PERF_IRQSTAT_6368_REG
-#define irq_mask_reg		PERF_IRQMASK_6368_REG
-#define irq_bits		64
-#define is_ext_irq_cascaded	1
-#define ext_irq_start		(BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
-#define ext_irq_end		(BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE)
-#define ext_irq_count		6
-#define ext_irq_cfg_reg1	PERF_EXTIRQ_CFG_REG_6368
-#define ext_irq_cfg_reg2	PERF_EXTIRQ_CFG_REG2_6368
-#endif
+static DEFINE_SPINLOCK(ipic_lock);
+static DEFINE_SPINLOCK(epic_lock);
 
-#if irq_bits == 32
-#define dispatch_internal			__dispatch_internal
-#define internal_irq_mask			__internal_irq_mask_32
-#define internal_irq_unmask			__internal_irq_unmask_32
-#else
-#define dispatch_internal			__dispatch_internal_64
-#define internal_irq_mask			__internal_irq_mask_64
-#define internal_irq_unmask			__internal_irq_unmask_64
-#endif
-
-#define irq_stat_addr	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
-#define irq_mask_addr	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
-
-static inline void bcm63xx_init_irq(void)
-{
-}
-#else /* ! BCMCPU_RUNTIME_DETECT */
-
-static u32 irq_stat_addr, irq_mask_addr;
-static void (*dispatch_internal)(void);
+static u32 irq_stat_addr[2];
+static u32 irq_mask_addr[2];
+static void (*dispatch_internal)(int cpu);
 static int is_ext_irq_cascaded;
 static unsigned int ext_irq_count;
 static unsigned int ext_irq_start, ext_irq_end;
 static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
-static void (*internal_irq_mask)(unsigned int irq);
-static void (*internal_irq_unmask)(unsigned int irq);
+static void (*internal_irq_mask)(struct irq_data *d);
+static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m);
 
-static void bcm63xx_init_irq(void)
-{
-	int irq_bits;
-
-	irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
-	irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
-
-	switch (bcm63xx_get_cpu_id()) {
-	case BCM3368_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_3368_REG;
-		irq_mask_addr += PERF_IRQMASK_3368_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
-		break;
-	case BCM6328_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6328_REG;
-		irq_mask_addr += PERF_IRQMASK_6328_REG;
-		irq_bits = 64;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
-		break;
-	case BCM6338_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6338_REG;
-		irq_mask_addr += PERF_IRQMASK_6338_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
-		break;
-	case BCM6345_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6345_REG;
-		irq_mask_addr += PERF_IRQMASK_6345_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
-		break;
-	case BCM6348_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6348_REG;
-		irq_mask_addr += PERF_IRQMASK_6348_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
-		break;
-	case BCM6358_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6358_REG;
-		irq_mask_addr += PERF_IRQMASK_6358_REG;
-		irq_bits = 32;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
-		break;
-	case BCM6362_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6362_REG;
-		irq_mask_addr += PERF_IRQMASK_6362_REG;
-		irq_bits = 64;
-		ext_irq_count = 4;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
-		break;
-	case BCM6368_CPU_ID:
-		irq_stat_addr += PERF_IRQSTAT_6368_REG;
-		irq_mask_addr += PERF_IRQMASK_6368_REG;
-		irq_bits = 64;
-		ext_irq_count = 6;
-		is_ext_irq_cascaded = 1;
-		ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
-		ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
-		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
-		ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
-		break;
-	default:
-		BUG();
-	}
-
-	if (irq_bits == 32) {
-		dispatch_internal = __dispatch_internal;
-		internal_irq_mask = __internal_irq_mask_32;
-		internal_irq_unmask = __internal_irq_unmask_32;
-	} else {
-		dispatch_internal = __dispatch_internal_64;
-		internal_irq_mask = __internal_irq_mask_64;
-		internal_irq_unmask = __internal_irq_unmask_64;
-	}
-}
-#endif /* ! BCMCPU_RUNTIME_DETECT */
 
 static inline u32 get_ext_irq_perf_reg(int irq)
 {
@@ -252,53 +51,113 @@
 		do_IRQ(intbit + IRQ_INTERNAL_BASE);
 }
 
+static inline int enable_irq_for_cpu(int cpu, struct irq_data *d,
+				     const struct cpumask *m)
+{
+	bool enable = cpu_online(cpu);
+
+#ifdef CONFIG_SMP
+	if (m)
+		enable &= cpu_isset(cpu, *m);
+	else if (irqd_affinity_was_set(d))
+		enable &= cpu_isset(cpu, *d->affinity);
+#endif
+	return enable;
+}
+
 /*
  * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not
  * prioritize any interrupt relatively to another. the static counter
  * will resume the loop where it ended the last time we left this
  * function.
  */
-static void __dispatch_internal(void)
-{
-	u32 pending;
-	static int i;
 
-	pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
-
-	if (!pending)
-		return ;
-
-	while (1) {
-		int to_call = i;
-
-		i = (i + 1) & 0x1f;
-		if (pending & (1 << to_call)) {
-			handle_internal(to_call);
-			break;
-		}
-	}
+#define BUILD_IPIC_INTERNAL(width)					\
+void __dispatch_internal_##width(int cpu)				\
+{									\
+	u32 pending[width / 32];					\
+	unsigned int src, tgt;						\
+	bool irqs_pending = false;					\
+	static unsigned int i[2];					\
+	unsigned int *next = &i[cpu];					\
+	unsigned long flags;						\
+									\
+	/* read registers in reverse order */				\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+		u32 val;						\
+									\
+		val = bcm_readl(irq_stat_addr[cpu] + src * sizeof(u32)); \
+		val &= bcm_readl(irq_mask_addr[cpu] + src * sizeof(u32)); \
+		pending[--tgt] = val;					\
+									\
+		if (val)						\
+			irqs_pending = true;				\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
+									\
+	if (!irqs_pending)						\
+		return;							\
+									\
+	while (1) {							\
+		unsigned int to_call = *next;				\
+									\
+		*next = (*next + 1) & (width - 1);			\
+		if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {	\
+			handle_internal(to_call);			\
+			break;						\
+		}							\
+	}								\
+}									\
+									\
+static void __internal_irq_mask_##width(struct irq_data *d)		\
+{									\
+	u32 val;							\
+	unsigned irq = d->irq - IRQ_INTERNAL_BASE;			\
+	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+	unsigned bit = irq & 0x1f;					\
+	unsigned long flags;						\
+	int cpu;							\
+									\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for_each_present_cpu(cpu) {					\
+		if (!irq_mask_addr[cpu])				\
+			break;						\
+									\
+		val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+		val &= ~(1 << bit);					\
+		bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
+}									\
+									\
+static void __internal_irq_unmask_##width(struct irq_data *d,		\
+					  const struct cpumask *m)	\
+{									\
+	u32 val;							\
+	unsigned irq = d->irq - IRQ_INTERNAL_BASE;			\
+	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+	unsigned bit = irq & 0x1f;					\
+	unsigned long flags;						\
+	int cpu;							\
+									\
+	spin_lock_irqsave(&ipic_lock, flags);				\
+	for_each_present_cpu(cpu) {					\
+		if (!irq_mask_addr[cpu])				\
+			break;						\
+									\
+		val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+		if (enable_irq_for_cpu(cpu, d, m))			\
+			val |= (1 << bit);				\
+		else							\
+			val &= ~(1 << bit);				\
+		bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+	}								\
+	spin_unlock_irqrestore(&ipic_lock, flags);			\
 }
 
-static void __dispatch_internal_64(void)
-{
-	u64 pending;
-	static int i;
-
-	pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
-
-	if (!pending)
-		return ;
-
-	while (1) {
-		int to_call = i;
-
-		i = (i + 1) & 0x3f;
-		if (pending & (1ull << to_call)) {
-			handle_internal(to_call);
-			break;
-		}
-	}
-}
+BUILD_IPIC_INTERNAL(32);
+BUILD_IPIC_INTERNAL(64);
 
 asmlinkage void plat_irq_dispatch(void)
 {
@@ -317,8 +176,11 @@
 		if (cause & CAUSEF_IP1)
 			do_IRQ(1);
 		if (cause & CAUSEF_IP2)
-			dispatch_internal();
-		if (!is_ext_irq_cascaded) {
+			dispatch_internal(0);
+		if (is_ext_irq_cascaded) {
+			if (cause & CAUSEF_IP3)
+				dispatch_internal(1);
+		} else {
 			if (cause & CAUSEF_IP3)
 				do_IRQ(IRQ_EXT_0);
 			if (cause & CAUSEF_IP4)
@@ -335,50 +197,14 @@
  * internal IRQs operations: only mask/unmask on PERF irq mask
  * register.
  */
-static void __internal_irq_mask_32(unsigned int irq)
-{
-	u32 mask;
-
-	mask = bcm_readl(irq_mask_addr);
-	mask &= ~(1 << irq);
-	bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_mask_64(unsigned int irq)
-{
-	u64 mask;
-
-	mask = bcm_readq(irq_mask_addr);
-	mask &= ~(1ull << irq);
-	bcm_writeq(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_32(unsigned int irq)
-{
-	u32 mask;
-
-	mask = bcm_readl(irq_mask_addr);
-	mask |= (1 << irq);
-	bcm_writel(mask, irq_mask_addr);
-}
-
-static void __internal_irq_unmask_64(unsigned int irq)
-{
-	u64 mask;
-
-	mask = bcm_readq(irq_mask_addr);
-	mask |= (1ull << irq);
-	bcm_writeq(mask, irq_mask_addr);
-}
-
 static void bcm63xx_internal_irq_mask(struct irq_data *d)
 {
-	internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
+	internal_irq_mask(d);
 }
 
 static void bcm63xx_internal_irq_unmask(struct irq_data *d)
 {
-	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
+	internal_irq_unmask(d, NULL);
 }
 
 /*
@@ -389,8 +215,10 @@
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -399,16 +227,20 @@
 		reg &= ~EXTIRQ_CFG_MASK(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
+
 	if (is_ext_irq_cascaded)
-		internal_irq_mask(irq + ext_irq_start);
+		internal_irq_mask(irq_get_irq_data(irq + ext_irq_start));
 }
 
 static void bcm63xx_external_irq_unmask(struct irq_data *d)
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -417,17 +249,21 @@
 		reg |= EXTIRQ_CFG_MASK(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 
 	if (is_ext_irq_cascaded)
-		internal_irq_unmask(irq + ext_irq_start);
+		internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start),
+				    NULL);
 }
 
 static void bcm63xx_external_irq_clear(struct irq_data *d)
 {
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
+	unsigned long flags;
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 
 	if (BCMCPU_IS_6348())
@@ -436,6 +272,7 @@
 		reg |= EXTIRQ_CFG_CLEAR(irq % 4);
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 }
 
 static int bcm63xx_external_irq_set_type(struct irq_data *d,
@@ -444,6 +281,7 @@
 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
 	u32 reg, regaddr;
 	int levelsense, sense, bothedge;
+	unsigned long flags;
 
 	flow_type &= IRQ_TYPE_SENSE_MASK;
 
@@ -478,6 +316,7 @@
 	}
 
 	regaddr = get_ext_irq_perf_reg(irq);
+	spin_lock_irqsave(&epic_lock, flags);
 	reg = bcm_perf_readl(regaddr);
 	irq %= 4;
 
@@ -522,6 +361,7 @@
 	}
 
 	bcm_perf_writel(reg, regaddr);
+	spin_unlock_irqrestore(&epic_lock, flags);
 
 	irqd_set_trigger_type(d, flow_type);
 	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -532,6 +372,18 @@
 	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
+#ifdef CONFIG_SMP
+static int bcm63xx_internal_set_affinity(struct irq_data *data,
+					 const struct cpumask *dest,
+					 bool force)
+{
+	if (!irqd_irq_disabled(data))
+		internal_irq_unmask(data, dest);
+
+	return 0;
+}
+#endif
+
 static struct irq_chip bcm63xx_internal_irq_chip = {
 	.name		= "bcm63xx_ipic",
 	.irq_mask	= bcm63xx_internal_irq_mask,
@@ -554,12 +406,130 @@
 	.flags		= IRQF_NO_THREAD,
 };
 
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+	.handler	= no_action,
+	.name		= "cascade_ip3",
+	.flags		= IRQF_NO_THREAD,
+};
+#endif
+
 static struct irqaction cpu_ext_cascade_action = {
 	.handler	= no_action,
 	.name		= "cascade_extirq",
 	.flags		= IRQF_NO_THREAD,
 };
 
+static void bcm63xx_init_irq(void)
+{
+	int irq_bits;
+
+	irq_stat_addr[0] = bcm63xx_regset_address(RSET_PERF);
+	irq_mask_addr[0] = bcm63xx_regset_address(RSET_PERF);
+	irq_stat_addr[1] = bcm63xx_regset_address(RSET_PERF);
+	irq_mask_addr[1] = bcm63xx_regset_address(RSET_PERF);
+
+	switch (bcm63xx_get_cpu_id()) {
+	case BCM3368_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_3368_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_3368_REG;
+		irq_stat_addr[1] = 0;
+		irq_stat_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_3368;
+		break;
+	case BCM6328_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6328_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6328_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6328_REG(1);
+		irq_stat_addr[1] += PERF_IRQMASK_6328_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+		break;
+	case BCM6338_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6338_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6338_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+		break;
+	case BCM6345_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6345_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6345_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+		break;
+	case BCM6348_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6348_REG;
+		irq_mask_addr[0] += PERF_IRQMASK_6348_REG;
+		irq_stat_addr[1] = 0;
+		irq_mask_addr[1] = 0;
+		irq_bits = 32;
+		ext_irq_count = 4;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+		break;
+	case BCM6358_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6358_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6358_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6358_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6358_REG(1);
+		irq_bits = 32;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+		break;
+	case BCM6362_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6362_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6362_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6362_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6362_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 4;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+		break;
+	case BCM6368_CPU_ID:
+		irq_stat_addr[0] += PERF_IRQSTAT_6368_REG(0);
+		irq_mask_addr[0] += PERF_IRQMASK_6368_REG(0);
+		irq_stat_addr[1] += PERF_IRQSTAT_6368_REG(1);
+		irq_mask_addr[1] += PERF_IRQMASK_6368_REG(1);
+		irq_bits = 64;
+		ext_irq_count = 6;
+		is_ext_irq_cascaded = 1;
+		ext_irq_start = BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE;
+		ext_irq_end = BCM_6368_EXT_IRQ5 - IRQ_INTERNAL_BASE;
+		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6368;
+		ext_irq_cfg_reg2 = PERF_EXTIRQ_CFG_REG2_6368;
+		break;
+	default:
+		BUG();
+	}
+
+	if (irq_bits == 32) {
+		dispatch_internal = __dispatch_internal_32;
+		internal_irq_mask = __internal_irq_mask_32;
+		internal_irq_unmask = __internal_irq_unmask_32;
+	} else {
+		dispatch_internal = __dispatch_internal_64;
+		internal_irq_mask = __internal_irq_mask_64;
+		internal_irq_unmask = __internal_irq_unmask_64;
+	}
+}
+
 void __init arch_init_irq(void)
 {
 	int i;
@@ -580,4 +550,14 @@
 	}
 
 	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+	if (is_ext_irq_cascaded) {
+		setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+		bcm63xx_internal_irq_chip.irq_set_affinity =
+			bcm63xx_internal_set_affinity;
+
+		cpumask_clear(irq_default_affinity);
+		cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+	}
+#endif
 }
diff --git a/arch/mips/bcm63xx/reset.c b/arch/mips/bcm63xx/reset.c
index acbeb1f..d1fe51e 100644
--- a/arch/mips/bcm63xx/reset.c
+++ b/arch/mips/bcm63xx/reset.c
@@ -125,8 +125,6 @@
 #define BCM6368_RESET_PCIE	0
 #define BCM6368_RESET_PCIE_EXT	0
 
-#ifdef BCMCPU_RUNTIME_DETECT
-
 /*
  * core reset bits
  */
@@ -188,64 +186,6 @@
 
 	return 0;
 }
-#else
-
-#ifdef CONFIG_BCM63XX_CPU_3368
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(3368)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6328
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6328)
-};
-#define reset_reg PERF_SOFTRESET_6328_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6338
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6338)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6345
-static const u32 bcm63xx_reset_bits[] = { };
-#define reset_reg 0
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6348
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6348)
-};
-#define reset_reg PERF_SOFTRESET_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6358
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6358)
-};
-#define reset_reg PERF_SOFTRESET_6358_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6362
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6362)
-};
-#define reset_reg PERF_SOFTRESET_6362_REG
-#endif
-
-#ifdef CONFIG_BCM63XX_CPU_6368
-static const u32 bcm63xx_reset_bits[] = {
-	__GEN_RESET_BITS_TABLE(6368)
-};
-#define reset_reg PERF_SOFTRESET_6368_REG
-#endif
-
-static int __init bcm63xx_reset_bits_init(void) { return 0; }
-#endif
 
 static DEFINE_SPINLOCK(reset_mutex);
 
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index c00c4dd..b49c7ad 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -67,10 +67,24 @@
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
+unsigned long __stack_chk_guard;
+
+void __stack_chk_guard_setup(void)
+{
+	__stack_chk_guard = 0x000a0dff;
+}
+
+void __stack_chk_fail(void)
+{
+	error("stack-protector: Kernel stack is corrupted\n");
+}
+
 void decompress_kernel(unsigned long boot_heap_start)
 {
 	unsigned long zimage_start, zimage_size;
 
+	__stack_chk_guard_setup();
+
 	zimage_start = (unsigned long)(&__image_begin);
 	zimage_size = (unsigned long)(&__image_end) -
 	    (unsigned long)(&__image_begin);
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index b764df6..5dfef84 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -186,6 +186,15 @@
 			return 7 - ipd_port;
 		else
 			return -1;
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
+		/*
+		 * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1)
+		 * connect to a switch (BCM53115).
+		 */
+		if (ipd_port == 2)
+			return 8;
+		else
+			return -1;
 	}
 
 	/* Some unknown board. Somebody forgot to update this function... */
@@ -274,6 +283,18 @@
 			return result;
 		}
 		break;
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
+		if (ipd_port == 0 || ipd_port == 1) {
+			/* Ports 0 and 1 connect to a switch (BCM53115). */
+			result.s.link_up = 1;
+			result.s.full_duplex = 1;
+			result.s.speed = 1000;
+			return result;
+		} else {
+			/* Port 2 uses a Broadcom PHY (B5081). */
+			is_broadcom_phy = 1;
+		}
+		break;
 	}
 
 	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
@@ -738,6 +759,7 @@
 	case CVMX_BOARD_TYPE_LANAI2_G:
 	case CVMX_BOARD_TYPE_NIC10E_66:
 	case CVMX_BOARD_TYPE_UBNT_E100:
+	case CVMX_BOARD_TYPE_CUST_DSR1000N:
 		return USB_CLOCK_TYPE_CRYSTAL_12;
 	case CVMX_BOARD_TYPE_NIC10E:
 		return USB_CLOCK_TYPE_REF_12;
diff --git a/arch/mips/cavium-octeon/oct_ilm.c b/arch/mips/cavium-octeon/oct_ilm.c
index 71b213d..2d68a39 100644
--- a/arch/mips/cavium-octeon/oct_ilm.c
+++ b/arch/mips/cavium-octeon/oct_ilm.c
@@ -194,8 +194,7 @@
 static __exit void oct_ilm_module_exit(void)
 {
 	disable_timer(TIMER_NUM);
-	if (dir)
-		debugfs_remove_recursive(dir);
+	debugfs_remove_recursive(dir);
 	free_irq(OCTEON_IRQ_TIMER0 + TIMER_NUM, 0);
 }
 
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index a7b3ae1..ecd903d 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -84,9 +84,14 @@
 #ifdef CONFIG_HOTPLUG_CPU
 	struct linux_app_boot_info *labi;
 
+	if (!setup_max_cpus)
+		return;
+
 	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-	if (labi->labi_signature != LABI_SIGNATURE)
-		panic("The bootloader version on this board is incorrect.");
+	if (labi->labi_signature != LABI_SIGNATURE) {
+		pr_info("The bootloader on this board does not support HOTPLUG_CPU.");
+		return;
+	}
 
 	octeon_bootloader_entry_addr = labi->InitTLBStart_addr;
 #endif
@@ -129,7 +134,8 @@
 	 * will assign CPU numbers for possible cores as well.	Cores
 	 * are always consecutively numberd from 0.
 	 */
-	for (id = 0; id < num_cores && id < NR_CPUS; id++) {
+	for (id = 0; setup_max_cpus && octeon_bootloader_entry_addr &&
+		     id < num_cores && id < NR_CPUS; id++) {
 		if (!(core_mask & (1 << id))) {
 			set_cpu_possible(cpus, true);
 			__cpu_number_map[id] = cpus;
@@ -192,14 +198,6 @@
  */
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
-#ifdef CONFIG_HOTPLUG_CPU
-	struct linux_app_boot_info *labi;
-
-	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
-	if (labi->labi_signature != LABI_SIGNATURE)
-		panic("The bootloader version on this board is incorrect.");
-#endif
 	/*
 	 * Only the low order mailbox bits are used for IPIs, leave
 	 * the other bits alone.
@@ -237,6 +235,9 @@
 	if (cpu == 0)
 		return -EBUSY;
 
+	if (!octeon_bootloader_entry_addr)
+		return -ENOTSUPP;
+
 	set_cpu_online(cpu, false);
 	cpu_clear(cpu, cpu_callin_map);
 	local_irq_disable();
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
index ea1761f..130e31b 100644
--- a/arch/mips/configs/loongson3_defconfig
+++ b/arch/mips/configs/loongson3_defconfig
@@ -1,6 +1,6 @@
 CONFIG_MACH_LOONGSON=y
 CONFIG_SWIOTLB=y
-CONFIG_LEMOTE_MACH3A=y
+CONFIG_LOONGSON_MACH3X=y
 CONFIG_CPU_LOONGSON3=y
 CONFIG_64BIT=y
 CONFIG_PAGE_SIZE_16KB=y
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 0543918..335e529 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -15,4 +15,5 @@
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
+generic-y += user.h
 generic-y += xor.h
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 3f74545..3b0e51d 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -52,7 +52,7 @@
  */
 #define CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)
 #define XPHYSADDR(a)		((_ACAST64_(a)) &			\
-				 _CONST64_(0x000000ffffffffff))
+				 _CONST64_(0x0000ffffffffffff))
 
 #ifdef CONFIG_64BIT
 
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 935543f..cd9a98b 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -10,6 +10,7 @@
 
 #include <asm/hazards.h>
 #include <asm/asm-offsets.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_32BIT
 #include <asm/asmmacro-32.h>
@@ -378,9 +379,19 @@
 	st_d	29, THREAD_FPR29, \thread
 	st_d	30, THREAD_FPR30, \thread
 	st_d	31, THREAD_FPR31, \thread
+	.set	push
+	.set	noat
+	cfcmsa	$1, MSA_CSR
+	sw	$1, THREAD_MSA_CSR(\thread)
+	.set	pop
 	.endm
 
 	.macro	msa_restore_all	thread
+	.set	push
+	.set	noat
+	lw	$1, THREAD_MSA_CSR(\thread)
+	ctcmsa	MSA_CSR, $1
+	.set	pop
 	ld_d	0, THREAD_FPR0, \thread
 	ld_d	1, THREAD_FPR1, \thread
 	ld_d	2, THREAD_FPR2, \thread
@@ -415,4 +426,24 @@
 	ld_d	31, THREAD_FPR31, \thread
 	.endm
 
+	.macro	msa_init_upper wd
+#ifdef CONFIG_64BIT
+	insert_d \wd, 1
+#else
+	insert_w \wd, 2
+	insert_w \wd, 3
+#endif
+	.if	31-\wd
+	msa_init_upper	(\wd+1)
+	.endif
+	.endm
+
+	.macro	msa_init_all_upper
+	.set	push
+	.set	noat
+	not	$1, zero
+	msa_init_upper	0
+	.set	pop
+	.endm
+
 #endif /* _ASM_ASMMACRO_H */
diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h
index 7c8816f..bae6b0f 100644
--- a/arch/mips/include/asm/bitops.h
+++ b/arch/mips/include/asm/bitops.h
@@ -559,7 +559,13 @@
 	int r;
 
 	if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
-		__asm__("clz %0, %1" : "=r" (x) : "r" (x));
+		__asm__(
+		"	.set	push					\n"
+		"	.set	mips32					\n"
+		"	clz	%0, %1					\n"
+		"	.set	pop					\n"
+		: "=r" (x)
+		: "r" (x));
 
 		return 32 - x;
 	}
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
index c1516cc..d035298 100644
--- a/arch/mips/include/asm/cop2.h
+++ b/arch/mips/include/asm/cop2.h
@@ -32,6 +32,14 @@
 #define cop2_present		1
 #define cop2_lazy_restore	0
 
+#elif defined(CONFIG_CPU_LOONGSON3)
+
+#define cop2_save(r)
+#define cop2_restore(r)
+
+#define cop2_present		1
+#define cop2_lazy_restore	1
+
 #else
 
 #define cop2_present		0
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index c7d8c99..e079598 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -29,6 +29,15 @@
 #ifndef cpu_has_eva
 #define cpu_has_eva		(cpu_data[0].options & MIPS_CPU_EVA)
 #endif
+#ifndef cpu_has_htw
+#define cpu_has_htw		(cpu_data[0].options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_has_rixiex
+#define cpu_has_rixiex		(cpu_data[0].options & MIPS_CPU_RIXIEX)
+#endif
+#ifndef cpu_has_maar
+#define cpu_has_maar		(cpu_data[0].options & MIPS_CPU_MAAR)
+#endif
 
 /*
  * For the moment we don't consider R6000 and R8000 so we can assume that
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index 47d5967..d5f42c1 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -44,8 +44,8 @@
 	/*
 	 * Capability and feature descriptor structure for MIPS CPU
 	 */
-	unsigned long		options;
 	unsigned long		ases;
+	unsigned long long	options;
 	unsigned int		udelay_val;
 	unsigned int		processor_id;
 	unsigned int		fpu_id;
@@ -61,6 +61,7 @@
 	struct cache_desc	scache; /* Secondary cache */
 	struct cache_desc	tcache; /* Tertiary/split secondary cache */
 	int			srsets; /* Shadow register sets */
+	int			package;/* physical package number */
 	int			core;	/* physical core number */
 #ifdef CONFIG_64BIT
 	int			vmbits; /* Virtual memory size in bits */
@@ -115,7 +116,7 @@
 #ifdef CONFIG_MIPS_MT_SMP
 # define cpu_vpe_id(cpuinfo)	((cpuinfo)->vpe_id)
 #else
-# define cpu_vpe_id(cpuinfo)	0
+# define cpu_vpe_id(cpuinfo)	({ (void)cpuinfo; 0; })
 #endif
 
 #endif /* __ASM_CPU_INFO_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 129d087..dfdc77e 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -233,6 +233,8 @@
 #define PRID_REV_LOONGSON2E	0x0002
 #define PRID_REV_LOONGSON2F	0x0003
 #define PRID_REV_LOONGSON3A	0x0005
+#define PRID_REV_LOONGSON3B_R1	0x0006
+#define PRID_REV_LOONGSON3B_R2	0x0007
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -335,34 +337,37 @@
 /*
  * CPU Option encodings
  */
-#define MIPS_CPU_TLB		0x00000001 /* CPU has TLB */
-#define MIPS_CPU_4KEX		0x00000002 /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE	0x00000004 /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE	0x00000008 /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE	0x00000010 /* TX3900-style caches */
-#define MIPS_CPU_FPU		0x00000020 /* CPU has FPU */
-#define MIPS_CPU_32FPR		0x00000040 /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER	0x00000080 /* Cycle count/compare */
-#define MIPS_CPU_WATCH		0x00000100 /* watchpoint registers */
-#define MIPS_CPU_DIVEC		0x00000200 /* dedicated interrupt vector */
-#define MIPS_CPU_VCE		0x00000400 /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P	0x00000800 /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S	0x00001000 /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK		0x00002000 /* Machine check exception */
-#define MIPS_CPU_EJTAG		0x00004000 /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX	0x00008000 /* no FPU exception */
-#define MIPS_CPU_LLSC		0x00010000 /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES	0x00020000 /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH	0x00040000 /* CPU has usable prefetch */
-#define MIPS_CPU_VINT		0x00080000 /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC		0x00100000 /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI		0x00200000 /* CPU has ULRI feature */
-#define MIPS_CPU_PCI		0x00400000 /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI		0x00800000 /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS	0x01000000 /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV		0x02000000 /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS	0x04000000 /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA		0x80000000 /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_TLB		0x00000001ull /* CPU has TLB */
+#define MIPS_CPU_4KEX		0x00000002ull /* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE	0x00000004ull /* R3000-style caches */
+#define MIPS_CPU_4K_CACHE	0x00000008ull /* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE	0x00000010ull /* TX3900-style caches */
+#define MIPS_CPU_FPU		0x00000020ull /* CPU has FPU */
+#define MIPS_CPU_32FPR		0x00000040ull /* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER	0x00000080ull /* Cycle count/compare */
+#define MIPS_CPU_WATCH		0x00000100ull /* watchpoint registers */
+#define MIPS_CPU_DIVEC		0x00000200ull /* dedicated interrupt vector */
+#define MIPS_CPU_VCE		0x00000400ull /* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P	0x00000800ull /* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S	0x00001000ull /* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK		0x00002000ull /* Machine check exception */
+#define MIPS_CPU_EJTAG		0x00004000ull /* EJTAG exception */
+#define MIPS_CPU_NOFPUEX	0x00008000ull /* no FPU exception */
+#define MIPS_CPU_LLSC		0x00010000ull /* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES	0x00020000ull /* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH	0x00040000ull /* CPU has usable prefetch */
+#define MIPS_CPU_VINT		0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC		0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI		0x00200000ull /* CPU has ULRI feature */
+#define MIPS_CPU_PCI		0x00400000ull /* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI		0x00800000ull /* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS	0x01000000ull /* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV		0x02000000ull /* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS	0x04000000ull /* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA		0x80000000ull /* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW		0x100000000ull /* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX		0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR		0x400000000ull /* MAAR(I) registers are present */
 
 /*
  * CPU ASE encodings
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index d414405..1d38fe0 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -339,23 +339,6 @@
 
 #endif /* CONFIG_64BIT */
 
-struct pt_regs;
-struct task_struct;
-
-extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
-
-#ifndef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(elf_regs, regs)			\
-	elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
-#endif
-#ifndef ELF_CORE_COPY_TASK_REGS
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#endif
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
-	dump_task_fpu(tsk, elf_fpregs)
-
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index a939574..4d0aeda 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -21,6 +21,7 @@
 #include <asm/hazards.h>
 #include <asm/processor.h>
 #include <asm/current.h>
+#include <asm/msa.h>
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 #include <asm/mips_mt.h>
@@ -141,13 +142,21 @@
 static inline void lose_fpu(int save)
 {
 	preempt_disable();
-	if (is_fpu_owner()) {
+	if (is_msa_enabled()) {
+		if (save) {
+			save_msa(current);
+			asm volatile("cfc1 %0, $31"
+				: "=r"(current->thread.fpu.fcr31));
+		}
+		disable_msa();
+		clear_thread_flag(TIF_USEDMSA);
+	} else if (is_fpu_owner()) {
 		if (save)
 			_save_fp(current);
-		KSTK_STATUS(current) &= ~ST0_CU1;
-		clear_thread_flag(TIF_USEDFPU);
 		__disable_fpu();
 	}
+	KSTK_STATUS(current) &= ~ST0_CU1;
+	clear_thread_flag(TIF_USEDFPU);
 	preempt_enable();
 }
 
@@ -155,8 +164,6 @@
 {
 	int ret = 0;
 
-	preempt_disable();
-
 	if (cpu_has_fpu) {
 		ret = __own_fpu();
 		if (!ret)
@@ -164,8 +171,6 @@
 	} else
 		fpu_emulator_init_fpu();
 
-	preempt_enable();
-
 	return ret;
 }
 
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 10f6a99..3f20b21 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -14,6 +14,8 @@
 #include <linux/bitmap.h>
 #include <linux/threads.h>
 
+#include <irq.h>
+
 #undef	GICISBYTELITTLEENDIAN
 
 /* Constants */
@@ -22,8 +24,6 @@
 #define GIC_TRIG_EDGE			1
 #define GIC_TRIG_LEVEL			0
 
-#define GIC_NUM_INTRS			(24 + NR_CPUS * 2)
-
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)		(*(volatile unsigned int *) (addr))
 #define REG(base, offs)		REG32((unsigned long)(base) + offs##_##OFS)
@@ -43,18 +43,17 @@
 #ifdef GICISBYTELITTLEENDIAN
 #define GICREAD(reg, data)	((data) = (reg), (data) = le32_to_cpu(data))
 #define GICWRITE(reg, data)	((reg) = cpu_to_le32(data))
-#define GICBIS(reg, bits)			\
-	({unsigned int data;			\
-		GICREAD(reg, data);		\
-		data |= bits;			\
-		GICWRITE(reg, data);		\
-	})
-
 #else
 #define GICREAD(reg, data)	((data) = (reg))
 #define GICWRITE(reg, data)	((reg) = (data))
-#define GICBIS(reg, bits)	((reg) |= (bits))
 #endif
+#define GICBIS(reg, mask, bits)			\
+	do { u32 data;				\
+		GICREAD((reg), data);		\
+		data &= ~(mask);		\
+		data |= ((bits) & (mask));	\
+		GICWRITE((reg), data);		\
+	} while (0)
 
 
 /* GIC Address Space */
@@ -170,13 +169,15 @@
 #define GIC_SH_SET_POLARITY_OFS		0x0100
 #define GIC_SET_POLARITY(intr, pol) \
 	GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \
-		GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr))
+		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+		(pol) << GIC_INTR_BIT(intr))
 
 /* Triggering : Reset Value is always 0 */
 #define GIC_SH_SET_TRIGGER_OFS		0x0180
 #define GIC_SET_TRIGGER(intr, trig) \
 	GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \
-		GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr))
+		GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \
+		(trig) << GIC_INTR_BIT(intr))
 
 /* Mask manipulation */
 #define GIC_SH_SMASK_OFS		0x0380
@@ -306,18 +307,6 @@
 	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_VPE_REG_OFF(intr, vpe)), \
 		 GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
 
-struct gic_pcpu_mask {
-	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
-};
-
-struct gic_pending_regs {
-	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
-};
-
-struct gic_intrmask_regs {
-	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
-};
-
 /*
  * Interrupt Meta-data specification. The ipiflag helps
  * in building ipi_map.
@@ -329,8 +318,7 @@
 	unsigned int polarity;	/* Polarity : +/-	*/
 	unsigned int trigtype;	/* Trigger  : Edge/Levl */
 	unsigned int flags;	/* Misc flags	*/
-#define GIC_FLAG_IPI	       0x01
-#define GIC_FLAG_TRANSPARENT   0x02
+#define GIC_FLAG_TRANSPARENT   0x01
 };
 
 /*
@@ -386,6 +374,7 @@
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern void gic_bind_eic_interrupt(int irq, int set);
 extern unsigned int gic_get_timer_pending(void);
+extern void gic_get_int_mask(unsigned long *dst, const unsigned long *src);
 extern unsigned int gic_get_int(void);
 extern void gic_enable_interrupt(int irq_vec);
 extern void gic_disable_interrupt(int irq_vec);
diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h
new file mode 100644
index 0000000..6c62b0f
--- /dev/null
+++ b/arch/mips/include/asm/maar.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MIPS_ASM_MIPS_MAAR_H__
+#define __MIPS_ASM_MIPS_MAAR_H__
+
+#include <asm/hazards.h>
+#include <asm/mipsregs.h>
+
+/**
+ * platform_maar_init() - perform platform-level MAAR configuration
+ * @num_pairs:	The number of MAAR pairs present in the system.
+ *
+ * Platforms should implement this function such that it configures as many
+ * MAAR pairs as required, from 0 up to the maximum of num_pairs-1, and returns
+ * the number that were used. Any further MAARs will be configured to be
+ * invalid. The default implementation of this function will simply indicate
+ * that it has configured 0 MAAR pairs.
+ *
+ * Return:	The number of MAAR pairs configured.
+ */
+unsigned __weak platform_maar_init(unsigned num_pairs);
+
+/**
+ * write_maar_pair() - write to a pair of MAARs
+ * @idx:	The index of the pair (ie. use MAARs idx*2 & (idx*2)+1).
+ * @lower:	The lowest address that the MAAR pair will affect. Must be
+ *		aligned to a 2^16 byte boundary.
+ * @upper:	The highest address that the MAAR pair will affect. Must be
+ *		aligned to one byte before a 2^16 byte boundary.
+ * @attrs:	The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *		MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Program the pair of MAAR registers specified by idx to apply the attributes
+ * specified by attrs to the range of addresses from lower to higher.
+ */
+static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
+				   phys_addr_t upper, unsigned attrs)
+{
+	/* Addresses begin at bit 16, but are shifted right 4 bits */
+	BUG_ON(lower & (0xffff | ~(MIPS_MAAR_ADDR << 4)));
+	BUG_ON(((upper & 0xffff) != 0xffff)
+		|| ((upper & ~0xffffull) & ~(MIPS_MAAR_ADDR << 4)));
+
+	/* Automatically set MIPS_MAAR_V */
+	attrs |= MIPS_MAAR_V;
+
+	/* Write the upper address & attributes (only MIPS_MAAR_V matters) */
+	write_c0_maari(idx << 1);
+	back_to_back_c0_hazard();
+	write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
+	back_to_back_c0_hazard();
+
+	/* Write the lower address & attributes */
+	write_c0_maari((idx << 1) | 0x1);
+	back_to_back_c0_hazard();
+	write_c0_maar((lower >> 4) | attrs);
+	back_to_back_c0_hazard();
+}
+
+/**
+ * struct maar_config - MAAR configuration data
+ * @lower:	The lowest address that the MAAR pair will affect. Must be
+ *		aligned to a 2^16 byte boundary.
+ * @upper:	The highest address that the MAAR pair will affect. Must be
+ *		aligned to one byte before a 2^16 byte boundary.
+ * @attrs:	The accessibility attributes to program, eg. MIPS_MAAR_S. The
+ *		MIPS_MAAR_V attribute will automatically be set.
+ *
+ * Describes the configuration of a pair of Memory Accessibility Attribute
+ * Registers - applying attributes from attrs to the range of physical
+ * addresses from lower to upper inclusive.
+ */
+struct maar_config {
+	phys_addr_t lower;
+	phys_addr_t upper;
+	unsigned attrs;
+};
+
+/**
+ * maar_config() - configure MAARs according to provided data
+ * @cfg:	Pointer to an array of struct maar_config.
+ * @num_cfg:	The number of structs in the cfg array.
+ * @num_pairs:	The number of MAAR pairs present in the system.
+ *
+ * Configures as many MAARs as are present and specified in the cfg
+ * array with the values taken from the cfg array.
+ *
+ * Return:	The number of MAAR pairs configured.
+ */
+static inline unsigned maar_config(const struct maar_config *cfg,
+				   unsigned num_cfg, unsigned num_pairs)
+{
+	unsigned i;
+
+	for (i = 0; i < min(num_cfg, num_pairs); i++)
+		write_maar_pair(i, cfg[i].lower, cfg[i].upper, cfg[i].attrs);
+
+	return i;
+}
+
+#endif /* __MIPS_ASM_MIPS_MAAR_H__ */
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index b4c3ecb..a7eec33 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -34,6 +34,558 @@
 #ifndef _AU1000_H_
 #define _AU1000_H_
 
+/* SOC Interrupt numbers */
+/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
+#define AU1000_INTC0_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
+#define AU1000_INTC0_INT_LAST	(AU1000_INTC0_INT_BASE + 31)
+#define AU1000_INTC1_INT_BASE	(AU1000_INTC0_INT_LAST + 1)
+#define AU1000_INTC1_INT_LAST	(AU1000_INTC1_INT_BASE + 31)
+#define AU1000_MAX_INTR		AU1000_INTC1_INT_LAST
+
+/* Au1300-style (GPIC): 1 controller with up to 128 sources */
+#define ALCHEMY_GPIC_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
+#define ALCHEMY_GPIC_INT_NUM	128
+#define ALCHEMY_GPIC_INT_LAST	(ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
+
+/* common clock names, shared among all variants. AUXPLL2 is Au1300 */
+#define ALCHEMY_ROOT_CLK		"root_clk"
+#define ALCHEMY_CPU_CLK			"cpu_clk"
+#define ALCHEMY_AUXPLL_CLK		"auxpll_clk"
+#define ALCHEMY_AUXPLL2_CLK		"auxpll2_clk"
+#define ALCHEMY_SYSBUS_CLK		"sysbus_clk"
+#define ALCHEMY_PERIPH_CLK		"periph_clk"
+#define ALCHEMY_MEM_CLK			"mem_clk"
+#define ALCHEMY_LR_CLK			"lr_clk"
+#define ALCHEMY_FG0_CLK			"fg0_clk"
+#define ALCHEMY_FG1_CLK			"fg1_clk"
+#define ALCHEMY_FG2_CLK			"fg2_clk"
+#define ALCHEMY_FG3_CLK			"fg3_clk"
+#define ALCHEMY_FG4_CLK			"fg4_clk"
+#define ALCHEMY_FG5_CLK			"fg5_clk"
+
+/* Au1300 peripheral interrupt numbers */
+#define AU1300_FIRST_INT	(ALCHEMY_GPIC_INT_BASE)
+#define AU1300_UART1_INT	(AU1300_FIRST_INT + 17)
+#define AU1300_UART2_INT	(AU1300_FIRST_INT + 25)
+#define AU1300_UART3_INT	(AU1300_FIRST_INT + 27)
+#define AU1300_SD1_INT		(AU1300_FIRST_INT + 32)
+#define AU1300_SD2_INT		(AU1300_FIRST_INT + 38)
+#define AU1300_PSC0_INT		(AU1300_FIRST_INT + 48)
+#define AU1300_PSC1_INT		(AU1300_FIRST_INT + 52)
+#define AU1300_PSC2_INT		(AU1300_FIRST_INT + 56)
+#define AU1300_PSC3_INT		(AU1300_FIRST_INT + 60)
+#define AU1300_NAND_INT		(AU1300_FIRST_INT + 62)
+#define AU1300_DDMA_INT		(AU1300_FIRST_INT + 75)
+#define AU1300_MMU_INT		(AU1300_FIRST_INT + 76)
+#define AU1300_MPU_INT		(AU1300_FIRST_INT + 77)
+#define AU1300_GPU_INT		(AU1300_FIRST_INT + 78)
+#define AU1300_UDMA_INT		(AU1300_FIRST_INT + 79)
+#define AU1300_TOY_INT		(AU1300_FIRST_INT + 80)
+#define AU1300_TOY_MATCH0_INT	(AU1300_FIRST_INT + 81)
+#define AU1300_TOY_MATCH1_INT	(AU1300_FIRST_INT + 82)
+#define AU1300_TOY_MATCH2_INT	(AU1300_FIRST_INT + 83)
+#define AU1300_RTC_INT		(AU1300_FIRST_INT + 84)
+#define AU1300_RTC_MATCH0_INT	(AU1300_FIRST_INT + 85)
+#define AU1300_RTC_MATCH1_INT	(AU1300_FIRST_INT + 86)
+#define AU1300_RTC_MATCH2_INT	(AU1300_FIRST_INT + 87)
+#define AU1300_UART0_INT	(AU1300_FIRST_INT + 88)
+#define AU1300_SD0_INT		(AU1300_FIRST_INT + 89)
+#define AU1300_USB_INT		(AU1300_FIRST_INT + 90)
+#define AU1300_LCD_INT		(AU1300_FIRST_INT + 91)
+#define AU1300_BSA_INT		(AU1300_FIRST_INT + 92)
+#define AU1300_MPE_INT		(AU1300_FIRST_INT + 93)
+#define AU1300_ITE_INT		(AU1300_FIRST_INT + 94)
+#define AU1300_AES_INT		(AU1300_FIRST_INT + 95)
+#define AU1300_CIM_INT		(AU1300_FIRST_INT + 96)
+
+/**********************************************************************/
+
+/*
+ * Physical base addresses for integrated peripherals
+ * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
+ */
+
+#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
+#define AU1300_ROM_PHYS_ADDR		0x10000000 /* 5 */
+#define AU1300_OTP_PHYS_ADDR		0x10002000 /* 5 */
+#define AU1300_VSS_PHYS_ADDR		0x10003000 /* 5 */
+#define AU1300_UART0_PHYS_ADDR		0x10100000 /* 5 */
+#define AU1300_UART1_PHYS_ADDR		0x10101000 /* 5 */
+#define AU1300_UART2_PHYS_ADDR		0x10102000 /* 5 */
+#define AU1300_UART3_PHYS_ADDR		0x10103000 /* 5 */
+#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
+#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
+#define AU1300_GPIC_PHYS_ADDR		0x10200000 /* 5 */
+#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
+#define AU1200_AES_PHYS_ADDR		0x10300000 /* 45 */
+#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
+#define AU1300_GPU_PHYS_ADDR		0x10500000 /* 5 */
+#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
+#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
+#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
+#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 245 */
+#define AU1300_SD1_PHYS_ADDR		0x10601000 /* 5 */
+#define AU1300_SD2_PHYS_ADDR		0x10602000 /* 5 */
+#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
+#define AU1300_SYS_PHYS_ADDR		0x10900000 /* 5 */
+#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
+#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
+#define AU1300_PSC0_PHYS_ADDR		0x10A00000 /* 5 */
+#define AU1300_PSC1_PHYS_ADDR		0x10A01000 /* 5 */
+#define AU1300_PSC2_PHYS_ADDR		0x10A02000 /* 5 */
+#define AU1300_PSC3_PHYS_ADDR		0x10A03000 /* 5 */
+#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
+#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
+#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
+#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
+#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
+#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
+#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
+#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
+#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
+#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
+#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
+#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
+#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
+#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 012345 */
+#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
+#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
+#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
+#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
+#define AU1300_UDMA_PHYS_ADDR		0x14001800 /* 5 */
+#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
+#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 345 */
+#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 345 */
+#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
+#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
+#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 45 */
+#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
+#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
+#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
+#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
+#define AU1300_MAEITE_PHYS_ADDR		0x14010000 /* 5 */
+#define AU1300_MAEMPE_PHYS_ADDR		0x14014000 /* 5 */
+#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
+#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
+#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
+#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
+#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
+#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
+#define AU1300_USB_EHCI_PHYS_ADDR	0x14020000 /* 5 */
+#define AU1300_USB_OHCI0_PHYS_ADDR	0x14020400 /* 5 */
+#define AU1300_USB_OHCI1_PHYS_ADDR	0x14020800 /* 5 */
+#define AU1300_USB_CTL_PHYS_ADDR	0x14021000 /* 5 */
+#define AU1300_USB_OTG_PHYS_ADDR	0x14022000 /* 5 */
+#define AU1300_MAEBSA_PHYS_ADDR		0x14030000 /* 5 */
+#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
+#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 45 */
+#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
+#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
+#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
+#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
+#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 012345 */
+#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 012345 */
+#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 012345 */
+
+/**********************************************************************/
+
+
+/*
+ * Au1300 GPIO+INT controller (GPIC) register offsets and bits
+ * Registers are 128bits (0x10 bytes), divided into 4 "banks".
+ */
+#define AU1300_GPIC_PINVAL	0x0000
+#define AU1300_GPIC_PINVALCLR	0x0010
+#define AU1300_GPIC_IPEND	0x0020
+#define AU1300_GPIC_PRIENC	0x0030
+#define AU1300_GPIC_IEN		0x0040	/* int_mask in manual */
+#define AU1300_GPIC_IDIS	0x0050	/* int_maskclr in manual */
+#define AU1300_GPIC_DMASEL	0x0060
+#define AU1300_GPIC_DEVSEL	0x0080
+#define AU1300_GPIC_DEVCLR	0x0090
+#define AU1300_GPIC_RSTVAL	0x00a0
+/* pin configuration space. one 32bit register for up to 128 IRQs */
+#define AU1300_GPIC_PINCFG	0x1000
+
+#define GPIC_GPIO_TO_BIT(gpio)	\
+	(1 << ((gpio) & 0x1f))
+
+#define GPIC_GPIO_BANKOFF(gpio) \
+	(((gpio) >> 5) * 4)
+
+/* Pin Control bits: who owns the pin, what does it do */
+#define GPIC_CFG_PC_GPIN		0
+#define GPIC_CFG_PC_DEV			1
+#define GPIC_CFG_PC_GPOLOW		2
+#define GPIC_CFG_PC_GPOHIGH		3
+#define GPIC_CFG_PC_MASK		3
+
+/* assign pin to MIPS IRQ line */
+#define GPIC_CFG_IL_SET(x)	(((x) & 3) << 2)
+#define GPIC_CFG_IL_MASK	(3 << 2)
+
+/* pin interrupt type setup */
+#define GPIC_CFG_IC_OFF		(0 << 4)
+#define GPIC_CFG_IC_LEVEL_LOW	(1 << 4)
+#define GPIC_CFG_IC_LEVEL_HIGH	(2 << 4)
+#define GPIC_CFG_IC_EDGE_FALL	(5 << 4)
+#define GPIC_CFG_IC_EDGE_RISE	(6 << 4)
+#define GPIC_CFG_IC_EDGE_BOTH	(7 << 4)
+#define GPIC_CFG_IC_MASK	(7 << 4)
+
+/* allow interrupt to wake cpu from 'wait' */
+#define GPIC_CFG_IDLEWAKE	(1 << 7)
+
+/***********************************************************************/
+
+/* Au1000 SDRAM memory controller register offsets */
+#define AU1000_MEM_SDMODE0		0x0000
+#define AU1000_MEM_SDMODE1		0x0004
+#define AU1000_MEM_SDMODE2		0x0008
+#define AU1000_MEM_SDADDR0		0x000C
+#define AU1000_MEM_SDADDR1		0x0010
+#define AU1000_MEM_SDADDR2		0x0014
+#define AU1000_MEM_SDREFCFG		0x0018
+#define AU1000_MEM_SDPRECMD		0x001C
+#define AU1000_MEM_SDAUTOREF		0x0020
+#define AU1000_MEM_SDWRMD0		0x0024
+#define AU1000_MEM_SDWRMD1		0x0028
+#define AU1000_MEM_SDWRMD2		0x002C
+#define AU1000_MEM_SDSLEEP		0x0030
+#define AU1000_MEM_SDSMCKE		0x0034
+
+/* MEM_SDMODE register content definitions */
+#define MEM_SDMODE_F		(1 << 22)
+#define MEM_SDMODE_SR		(1 << 21)
+#define MEM_SDMODE_BS		(1 << 20)
+#define MEM_SDMODE_RS		(3 << 18)
+#define MEM_SDMODE_CS		(7 << 15)
+#define MEM_SDMODE_TRAS		(15 << 11)
+#define MEM_SDMODE_TMRD		(3 << 9)
+#define MEM_SDMODE_TWR		(3 << 7)
+#define MEM_SDMODE_TRP		(3 << 5)
+#define MEM_SDMODE_TRCD		(3 << 3)
+#define MEM_SDMODE_TCL		(7 << 0)
+
+#define MEM_SDMODE_BS_2Bank	(0 << 20)
+#define MEM_SDMODE_BS_4Bank	(1 << 20)
+#define MEM_SDMODE_RS_11Row	(0 << 18)
+#define MEM_SDMODE_RS_12Row	(1 << 18)
+#define MEM_SDMODE_RS_13Row	(2 << 18)
+#define MEM_SDMODE_RS_N(N)	((N) << 18)
+#define MEM_SDMODE_CS_7Col	(0 << 15)
+#define MEM_SDMODE_CS_8Col	(1 << 15)
+#define MEM_SDMODE_CS_9Col	(2 << 15)
+#define MEM_SDMODE_CS_10Col	(3 << 15)
+#define MEM_SDMODE_CS_11Col	(4 << 15)
+#define MEM_SDMODE_CS_N(N)	((N) << 15)
+#define MEM_SDMODE_TRAS_N(N)	((N) << 11)
+#define MEM_SDMODE_TMRD_N(N)	((N) << 9)
+#define MEM_SDMODE_TWR_N(N)	((N) << 7)
+#define MEM_SDMODE_TRP_N(N)	((N) << 5)
+#define MEM_SDMODE_TRCD_N(N)	((N) << 3)
+#define MEM_SDMODE_TCL_N(N)	((N) << 0)
+
+/* MEM_SDADDR register contents definitions */
+#define MEM_SDADDR_E		(1 << 20)
+#define MEM_SDADDR_CSBA		(0x03FF << 10)
+#define MEM_SDADDR_CSMASK	(0x03FF << 0)
+#define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
+#define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
+
+/* MEM_SDREFCFG register content definitions */
+#define MEM_SDREFCFG_TRC	(15 << 28)
+#define MEM_SDREFCFG_TRPM	(3 << 26)
+#define MEM_SDREFCFG_E		(1 << 25)
+#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
+#define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
+#define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
+#define MEM_SDREFCFG_REF_N(N)	(N)
+
+/* Au1550 SDRAM Register Offsets */
+#define AU1550_MEM_SDMODE0		0x0800
+#define AU1550_MEM_SDMODE1		0x0808
+#define AU1550_MEM_SDMODE2		0x0810
+#define AU1550_MEM_SDADDR0		0x0820
+#define AU1550_MEM_SDADDR1		0x0828
+#define AU1550_MEM_SDADDR2		0x0830
+#define AU1550_MEM_SDCONFIGA		0x0840
+#define AU1550_MEM_SDCONFIGB		0x0848
+#define AU1550_MEM_SDSTAT		0x0850
+#define AU1550_MEM_SDERRADDR		0x0858
+#define AU1550_MEM_SDSTRIDE0		0x0860
+#define AU1550_MEM_SDSTRIDE1		0x0868
+#define AU1550_MEM_SDSTRIDE2		0x0870
+#define AU1550_MEM_SDWRMD0		0x0880
+#define AU1550_MEM_SDWRMD1		0x0888
+#define AU1550_MEM_SDWRMD2		0x0890
+#define AU1550_MEM_SDPRECMD		0x08C0
+#define AU1550_MEM_SDAUTOREF		0x08C8
+#define AU1550_MEM_SDSREF		0x08D0
+#define AU1550_MEM_SDSLEEP		MEM_SDSREF
+
+/* Static Bus Controller register offsets */
+#define AU1000_MEM_STCFG0	0x000
+#define AU1000_MEM_STTIME0	0x004
+#define AU1000_MEM_STADDR0	0x008
+#define AU1000_MEM_STCFG1	0x010
+#define AU1000_MEM_STTIME1	0x014
+#define AU1000_MEM_STADDR1	0x018
+#define AU1000_MEM_STCFG2	0x020
+#define AU1000_MEM_STTIME2	0x024
+#define AU1000_MEM_STADDR2	0x028
+#define AU1000_MEM_STCFG3	0x030
+#define AU1000_MEM_STTIME3	0x034
+#define AU1000_MEM_STADDR3	0x038
+#define AU1000_MEM_STNDCTL	0x100
+#define AU1000_MEM_STSTAT	0x104
+
+#define MEM_STNAND_CMD		0x0
+#define MEM_STNAND_ADDR		0x4
+#define MEM_STNAND_DATA		0x20
+
+
+/* Programmable Counters 0 and 1 */
+#define AU1000_SYS_CNTRCTRL	0x14
+#  define SYS_CNTRL_E1S		(1 << 23)
+#  define SYS_CNTRL_T1S		(1 << 20)
+#  define SYS_CNTRL_M21		(1 << 19)
+#  define SYS_CNTRL_M11		(1 << 18)
+#  define SYS_CNTRL_M01		(1 << 17)
+#  define SYS_CNTRL_C1S		(1 << 16)
+#  define SYS_CNTRL_BP		(1 << 14)
+#  define SYS_CNTRL_EN1		(1 << 13)
+#  define SYS_CNTRL_BT1		(1 << 12)
+#  define SYS_CNTRL_EN0		(1 << 11)
+#  define SYS_CNTRL_BT0		(1 << 10)
+#  define SYS_CNTRL_E0		(1 << 8)
+#  define SYS_CNTRL_E0S		(1 << 7)
+#  define SYS_CNTRL_32S		(1 << 5)
+#  define SYS_CNTRL_T0S		(1 << 4)
+#  define SYS_CNTRL_M20		(1 << 3)
+#  define SYS_CNTRL_M10		(1 << 2)
+#  define SYS_CNTRL_M00		(1 << 1)
+#  define SYS_CNTRL_C0S		(1 << 0)
+
+/* Programmable Counter 0 Registers */
+#define AU1000_SYS_TOYTRIM	0x00
+#define AU1000_SYS_TOYWRITE	0x04
+#define AU1000_SYS_TOYMATCH0	0x08
+#define AU1000_SYS_TOYMATCH1	0x0c
+#define AU1000_SYS_TOYMATCH2	0x10
+#define AU1000_SYS_TOYREAD	0x40
+
+/* Programmable Counter 1 Registers */
+#define AU1000_SYS_RTCTRIM	0x44
+#define AU1000_SYS_RTCWRITE	0x48
+#define AU1000_SYS_RTCMATCH0	0x4c
+#define AU1000_SYS_RTCMATCH1	0x50
+#define AU1000_SYS_RTCMATCH2	0x54
+#define AU1000_SYS_RTCREAD	0x58
+
+
+/* GPIO */
+#define AU1000_SYS_PINFUNC	0x2C
+#  define SYS_PF_USB		(1 << 15)	/* 2nd USB device/host */
+#  define SYS_PF_U3		(1 << 14)	/* GPIO23/U3TXD */
+#  define SYS_PF_U2		(1 << 13)	/* GPIO22/U2TXD */
+#  define SYS_PF_U1		(1 << 12)	/* GPIO21/U1TXD */
+#  define SYS_PF_SRC		(1 << 11)	/* GPIO6/SROMCKE */
+#  define SYS_PF_CK5		(1 << 10)	/* GPIO3/CLK5 */
+#  define SYS_PF_CK4		(1 << 9)	/* GPIO2/CLK4 */
+#  define SYS_PF_IRF		(1 << 8)	/* GPIO15/IRFIRSEL */
+#  define SYS_PF_UR3		(1 << 7)	/* GPIO[14:9]/UART3 */
+#  define SYS_PF_I2D		(1 << 6)	/* GPIO8/I2SDI */
+#  define SYS_PF_I2S		(1 << 5)	/* I2S/GPIO[29:31] */
+#  define SYS_PF_NI2		(1 << 4)	/* NI2/GPIO[24:28] */
+#  define SYS_PF_U0		(1 << 3)	/* U0TXD/GPIO20 */
+#  define SYS_PF_RD		(1 << 2)	/* IRTXD/GPIO19 */
+#  define SYS_PF_A97		(1 << 1)	/* AC97/SSL1 */
+#  define SYS_PF_S0		(1 << 0)	/* SSI_0/GPIO[16:18] */
+
+/* Au1100 only */
+#  define SYS_PF_PC		(1 << 18)	/* PCMCIA/GPIO[207:204] */
+#  define SYS_PF_LCD		(1 << 17)	/* extern lcd/GPIO[203:200] */
+#  define SYS_PF_CS		(1 << 16)	/* EXTCLK0/32KHz to gpio2 */
+#  define SYS_PF_EX0		(1 << 9)	/* GPIO2/clock */
+
+/* Au1550 only.	 Redefines lots of pins */
+#  define SYS_PF_PSC2_MASK	(7 << 17)
+#  define SYS_PF_PSC2_AC97	0
+#  define SYS_PF_PSC2_SPI	0
+#  define SYS_PF_PSC2_I2S	(1 << 17)
+#  define SYS_PF_PSC2_SMBUS	(3 << 17)
+#  define SYS_PF_PSC2_GPIO	(7 << 17)
+#  define SYS_PF_PSC3_MASK	(7 << 20)
+#  define SYS_PF_PSC3_AC97	0
+#  define SYS_PF_PSC3_SPI	0
+#  define SYS_PF_PSC3_I2S	(1 << 20)
+#  define SYS_PF_PSC3_SMBUS	(3 << 20)
+#  define SYS_PF_PSC3_GPIO	(7 << 20)
+#  define SYS_PF_PSC1_S1	(1 << 1)
+#  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
+
+/* Au1200 only */
+#define SYS_PINFUNC_DMA		(1 << 31)
+#define SYS_PINFUNC_S0A		(1 << 30)
+#define SYS_PINFUNC_S1A		(1 << 29)
+#define SYS_PINFUNC_LP0		(1 << 28)
+#define SYS_PINFUNC_LP1		(1 << 27)
+#define SYS_PINFUNC_LD16	(1 << 26)
+#define SYS_PINFUNC_LD8		(1 << 25)
+#define SYS_PINFUNC_LD1		(1 << 24)
+#define SYS_PINFUNC_LD0		(1 << 23)
+#define SYS_PINFUNC_P1A		(3 << 21)
+#define SYS_PINFUNC_P1B		(1 << 20)
+#define SYS_PINFUNC_FS3		(1 << 19)
+#define SYS_PINFUNC_P0A		(3 << 17)
+#define SYS_PINFUNC_CS		(1 << 16)
+#define SYS_PINFUNC_CIM		(1 << 15)
+#define SYS_PINFUNC_P1C		(1 << 14)
+#define SYS_PINFUNC_U1T		(1 << 12)
+#define SYS_PINFUNC_U1R		(1 << 11)
+#define SYS_PINFUNC_EX1		(1 << 10)
+#define SYS_PINFUNC_EX0		(1 << 9)
+#define SYS_PINFUNC_U0R		(1 << 8)
+#define SYS_PINFUNC_MC		(1 << 7)
+#define SYS_PINFUNC_S0B		(1 << 6)
+#define SYS_PINFUNC_S0C		(1 << 5)
+#define SYS_PINFUNC_P0B		(1 << 4)
+#define SYS_PINFUNC_U0T		(1 << 3)
+#define SYS_PINFUNC_S1B		(1 << 2)
+
+/* Power Management */
+#define AU1000_SYS_SCRATCH0	0x18
+#define AU1000_SYS_SCRATCH1	0x1c
+#define AU1000_SYS_WAKEMSK	0x34
+#define AU1000_SYS_ENDIAN	0x38
+#define AU1000_SYS_POWERCTRL	0x3c
+#define AU1000_SYS_WAKESRC	0x5c
+#define AU1000_SYS_SLPPWR	0x78
+#define AU1000_SYS_SLEEP	0x7c
+
+#define SYS_WAKEMSK_D2		(1 << 9)
+#define SYS_WAKEMSK_M2		(1 << 8)
+#define SYS_WAKEMSK_GPIO(x)	(1 << (x))
+
+/* Clock Controller */
+#define AU1000_SYS_FREQCTRL0	0x20
+#define AU1000_SYS_FREQCTRL1	0x24
+#define AU1000_SYS_CLKSRC	0x28
+#define AU1000_SYS_CPUPLL	0x60
+#define AU1000_SYS_AUXPLL	0x64
+#define AU1300_SYS_AUXPLL2	0x68
+
+
+/**********************************************************************/
+
+
+/* The PCI chip selects are outside the 32bit space, and since we can't
+ * just program the 36bit addresses into BARs, we have to take a chunk
+ * out of the 32bit space and reserve it for PCI.  When these addresses
+ * are ioremap()ed, they'll be fixed up to the real 36bit address before
+ * being passed to the real ioremap function.
+ */
+#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
+#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
+
+/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
+ * adjust the device's resources.
+ */
+#define ALCHEMY_PCI_IOWIN_START		0x00001000
+#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
+
+#ifdef CONFIG_PCI
+
+#define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
+#define IOPORT_RESOURCE_END	0xffffffff
+#define IOMEM_RESOURCE_START	0x10000000
+#define IOMEM_RESOURCE_END	0xfffffffffULL
+
+#else
+
+/* Don't allow any legacy ports probing */
+#define IOPORT_RESOURCE_START	0x10000000
+#define IOPORT_RESOURCE_END	0xffffffff
+#define IOMEM_RESOURCE_START	0x10000000
+#define IOMEM_RESOURCE_END	0xfffffffffULL
+
+#endif
+
+/* PCI controller block register offsets */
+#define PCI_REG_CMEM		0x0000
+#define PCI_REG_CONFIG		0x0004
+#define PCI_REG_B2BMASK_CCH	0x0008
+#define PCI_REG_B2BBASE0_VID	0x000C
+#define PCI_REG_B2BBASE1_SID	0x0010
+#define PCI_REG_MWMASK_DEV	0x0014
+#define PCI_REG_MWBASE_REV_CCL	0x0018
+#define PCI_REG_ERR_ADDR	0x001C
+#define PCI_REG_SPEC_INTACK	0x0020
+#define PCI_REG_ID		0x0100
+#define PCI_REG_STATCMD		0x0104
+#define PCI_REG_CLASSREV	0x0108
+#define PCI_REG_PARAM		0x010C
+#define PCI_REG_MBAR		0x0110
+#define PCI_REG_TIMEOUT		0x0140
+
+/* PCI controller block register bits */
+#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
+#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
+#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
+#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
+#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
+#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
+#define PCI_CONFIG_EP		(1 << 24) /* parity error */
+#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
+#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
+#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
+#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
+#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
+#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
+#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
+#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
+#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
+#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
+#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
+#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
+#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
+#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
+#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
+#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
+#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
+#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
+#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
+#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
+#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
+#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
+#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
+#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
+#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
+#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
+#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
+#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
+#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
+#define PCI_MWBASEREVCCL_REV(x)	 (((x) & 0xff) << 8)
+#define PCI_MWBASEREVCCL_CCL(x)	 ((x) & 0xff)
+#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
+#define PCI_ID_VID(x)		((x) & 0xffff)
+#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
+#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
+#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
+#define PCI_CLASSREV_REV(x)	((x) & 0xff)
+#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
+#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
+#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
+#define PCI_PARAM_CLS(x)	((x) & 0xff)
+#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
+#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
+
+
+/**********************************************************************/
+
 
 #ifndef _LANGUAGE_ASSEMBLY
 
@@ -45,52 +597,36 @@
 
 #include <asm/cpu.h>
 
-/* cpu pipeline flush */
-void static inline au_sync(void)
+/* helpers to access the SYS_* registers */
+static inline unsigned long alchemy_rdsys(int regofs)
 {
-	__asm__ volatile ("sync");
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+
+	return __raw_readl(b + regofs);
 }
 
-void static inline au_sync_udelay(int us)
+static inline void alchemy_wrsys(unsigned long v, int regofs)
 {
-	__asm__ volatile ("sync");
-	udelay(us);
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
+
+	__raw_writel(v, b + regofs);
+	wmb(); /* drain writebuffer */
 }
 
-void static inline au_sync_delay(int ms)
+/* helpers to access static memctrl registers */
+static inline unsigned long alchemy_rdsmem(int regofs)
 {
-	__asm__ volatile ("sync");
-	mdelay(ms);
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
+
+	return __raw_readl(b + regofs);
 }
 
-void static inline au_writeb(u8 val, unsigned long reg)
+static inline void alchemy_wrsmem(unsigned long v, int regofs)
 {
-	*(volatile u8 *)reg = val;
-}
+	void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
 
-void static inline au_writew(u16 val, unsigned long reg)
-{
-	*(volatile u16 *)reg = val;
-}
-
-void static inline au_writel(u32 val, unsigned long reg)
-{
-	*(volatile u32 *)reg = val;
-}
-
-static inline u8 au_readb(unsigned long reg)
-{
-	return *(volatile u8 *)reg;
-}
-
-static inline u16 au_readw(unsigned long reg)
-{
-	return *(volatile u16 *)reg;
-}
-
-static inline u32 au_readl(unsigned long reg)
-{
-	return *(volatile u32 *)reg;
+	__raw_writel(v, b + regofs);
+	wmb(); /* drain writebuffer */
 }
 
 /* Early Au1000 have a write-only SYS_CPUPLL register. */
@@ -192,19 +728,20 @@
 	/* reset, enable clock, deassert reset */
 	if ((__raw_readl(addr + 0x100) & 3) != 3) {
 		__raw_writel(0, addr + 0x100);
-		wmb();
+		wmb(); /* drain writebuffer */
 		__raw_writel(1, addr + 0x100);
-		wmb();
+		wmb(); /* drain writebuffer */
 	}
 	__raw_writel(3, addr + 0x100);
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 static inline void alchemy_uart_disable(u32 uart_phys)
 {
 	void __iomem *addr = (void __iomem *)KSEG1ADDR(uart_phys);
+
 	__raw_writel(0, addr + 0x100);	/* UART_MOD_CNTRL */
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 static inline void alchemy_uart_putchar(u32 uart_phys, u8 c)
@@ -223,7 +760,7 @@
 	} while (--timeout);
 
 	__raw_writel(c, base + 0x04);	/* tx */
-	wmb();
+	wmb(); /* drain writebuffer */
 }
 
 /* return number of ethernet MACs on a given cputype */
@@ -240,20 +777,13 @@
 	return 0;
 }
 
-/* arch/mips/au1000/common/clocks.c */
-extern void set_au1x00_speed(unsigned int new_freq);
-extern unsigned int get_au1x00_speed(void);
-extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
-extern unsigned long get_au1x00_uart_baud_base(void);
-extern unsigned long au1xxx_calc_clock(void);
-
 /* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
 void alchemy_sleep_au1000(void);
 void alchemy_sleep_au1550(void);
 void alchemy_sleep_au1300(void);
 void au_sleep(void);
 
-/* USB: drivers/usb/host/alchemy-common.c */
+/* USB: arch/mips/alchemy/common/usb.c */
 enum alchemy_usb_block {
 	ALCHEMY_USB_OHCI0,
 	ALCHEMY_USB_UDC0,
@@ -272,6 +802,20 @@
 	unsigned long pci_cfg_clr;
 };
 
+/* The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's
+ * not used to select FIR/SIR mode on the transceiver but as a GPIO.
+ * Instead a CPLD has to be told about the mode.  The driver calls the
+ * set_phy_mode() function in addition to driving the IRFIRSEL pin.
+ */
+#define AU1000_IRDA_PHY_MODE_OFF	0
+#define AU1000_IRDA_PHY_MODE_SIR	1
+#define AU1000_IRDA_PHY_MODE_FIR	2
+
+struct au1k_irda_platform_data {
+	void (*set_phy_mode)(int mode);
+};
+
+
 /* Multifunction pins: Each of these pins can either be assigned to the
  * GPIO controller or a on-chip peripheral.
  * Call "au1300_pinfunc_to_dev()" or "au1300_pinfunc_to_gpio()" to
@@ -344,20 +888,6 @@
 
 extern void au1300_vss_block_control(int block, int enable);
 
-
-/* SOC Interrupt numbers */
-/* Au1000-style (IC0/1): 2 controllers with 32 sources each */
-#define AU1000_INTC0_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
-#define AU1000_INTC0_INT_LAST	(AU1000_INTC0_INT_BASE + 31)
-#define AU1000_INTC1_INT_BASE	(AU1000_INTC0_INT_LAST + 1)
-#define AU1000_INTC1_INT_LAST	(AU1000_INTC1_INT_BASE + 31)
-#define AU1000_MAX_INTR		AU1000_INTC1_INT_LAST
-
-/* Au1300-style (GPIC): 1 controller with up to 128 sources */
-#define ALCHEMY_GPIC_INT_BASE	(MIPS_CPU_IRQ_BASE + 8)
-#define ALCHEMY_GPIC_INT_NUM	128
-#define ALCHEMY_GPIC_INT_LAST	(ALCHEMY_GPIC_INT_BASE + ALCHEMY_GPIC_INT_NUM - 1)
-
 enum soc_au1000_ints {
 	AU1000_FIRST_INT	= AU1000_INTC0_INT_BASE,
 	AU1000_UART0_INT	= AU1000_FIRST_INT,
@@ -678,885 +1208,4 @@
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
-/* Au1300 peripheral interrupt numbers */
-#define AU1300_FIRST_INT	(ALCHEMY_GPIC_INT_BASE)
-#define AU1300_UART1_INT	(AU1300_FIRST_INT + 17)
-#define AU1300_UART2_INT	(AU1300_FIRST_INT + 25)
-#define AU1300_UART3_INT	(AU1300_FIRST_INT + 27)
-#define AU1300_SD1_INT		(AU1300_FIRST_INT + 32)
-#define AU1300_SD2_INT		(AU1300_FIRST_INT + 38)
-#define AU1300_PSC0_INT		(AU1300_FIRST_INT + 48)
-#define AU1300_PSC1_INT		(AU1300_FIRST_INT + 52)
-#define AU1300_PSC2_INT		(AU1300_FIRST_INT + 56)
-#define AU1300_PSC3_INT		(AU1300_FIRST_INT + 60)
-#define AU1300_NAND_INT		(AU1300_FIRST_INT + 62)
-#define AU1300_DDMA_INT		(AU1300_FIRST_INT + 75)
-#define AU1300_MMU_INT		(AU1300_FIRST_INT + 76)
-#define AU1300_MPU_INT		(AU1300_FIRST_INT + 77)
-#define AU1300_GPU_INT		(AU1300_FIRST_INT + 78)
-#define AU1300_UDMA_INT		(AU1300_FIRST_INT + 79)
-#define AU1300_TOY_INT		(AU1300_FIRST_INT + 80)
-#define AU1300_TOY_MATCH0_INT	(AU1300_FIRST_INT + 81)
-#define AU1300_TOY_MATCH1_INT	(AU1300_FIRST_INT + 82)
-#define AU1300_TOY_MATCH2_INT	(AU1300_FIRST_INT + 83)
-#define AU1300_RTC_INT		(AU1300_FIRST_INT + 84)
-#define AU1300_RTC_MATCH0_INT	(AU1300_FIRST_INT + 85)
-#define AU1300_RTC_MATCH1_INT	(AU1300_FIRST_INT + 86)
-#define AU1300_RTC_MATCH2_INT	(AU1300_FIRST_INT + 87)
-#define AU1300_UART0_INT	(AU1300_FIRST_INT + 88)
-#define AU1300_SD0_INT		(AU1300_FIRST_INT + 89)
-#define AU1300_USB_INT		(AU1300_FIRST_INT + 90)
-#define AU1300_LCD_INT		(AU1300_FIRST_INT + 91)
-#define AU1300_BSA_INT		(AU1300_FIRST_INT + 92)
-#define AU1300_MPE_INT		(AU1300_FIRST_INT + 93)
-#define AU1300_ITE_INT		(AU1300_FIRST_INT + 94)
-#define AU1300_AES_INT		(AU1300_FIRST_INT + 95)
-#define AU1300_CIM_INT		(AU1300_FIRST_INT + 96)
-
-/**********************************************************************/
-
-/*
- * Physical base addresses for integrated peripherals
- * 0..au1000 1..au1500 2..au1100 3..au1550 4..au1200 5..au1300
- */
-
-#define AU1000_AC97_PHYS_ADDR		0x10000000 /* 012 */
-#define AU1300_ROM_PHYS_ADDR		0x10000000 /* 5 */
-#define AU1300_OTP_PHYS_ADDR		0x10002000 /* 5 */
-#define AU1300_VSS_PHYS_ADDR		0x10003000 /* 5 */
-#define AU1300_UART0_PHYS_ADDR		0x10100000 /* 5 */
-#define AU1300_UART1_PHYS_ADDR		0x10101000 /* 5 */
-#define AU1300_UART2_PHYS_ADDR		0x10102000 /* 5 */
-#define AU1300_UART3_PHYS_ADDR		0x10103000 /* 5 */
-#define AU1000_USB_OHCI_PHYS_ADDR	0x10100000 /* 012 */
-#define AU1000_USB_UDC_PHYS_ADDR	0x10200000 /* 0123 */
-#define AU1300_GPIC_PHYS_ADDR		0x10200000 /* 5 */
-#define AU1000_IRDA_PHYS_ADDR		0x10300000 /* 02 */
-#define AU1200_AES_PHYS_ADDR		0x10300000 /* 45 */
-#define AU1000_IC0_PHYS_ADDR		0x10400000 /* 01234 */
-#define AU1300_GPU_PHYS_ADDR		0x10500000 /* 5 */
-#define AU1000_MAC0_PHYS_ADDR		0x10500000 /* 023 */
-#define AU1000_MAC1_PHYS_ADDR		0x10510000 /* 023 */
-#define AU1000_MACEN_PHYS_ADDR		0x10520000 /* 023 */
-#define AU1100_SD0_PHYS_ADDR		0x10600000 /* 245 */
-#define AU1300_SD1_PHYS_ADDR		0x10601000 /* 5 */
-#define AU1300_SD2_PHYS_ADDR		0x10602000 /* 5 */
-#define AU1100_SD1_PHYS_ADDR		0x10680000 /* 24 */
-#define AU1300_SYS_PHYS_ADDR		0x10900000 /* 5 */
-#define AU1550_PSC2_PHYS_ADDR		0x10A00000 /* 3 */
-#define AU1550_PSC3_PHYS_ADDR		0x10B00000 /* 3 */
-#define AU1300_PSC0_PHYS_ADDR		0x10A00000 /* 5 */
-#define AU1300_PSC1_PHYS_ADDR		0x10A01000 /* 5 */
-#define AU1300_PSC2_PHYS_ADDR		0x10A02000 /* 5 */
-#define AU1300_PSC3_PHYS_ADDR		0x10A03000 /* 5 */
-#define AU1000_I2S_PHYS_ADDR		0x11000000 /* 02 */
-#define AU1500_MAC0_PHYS_ADDR		0x11500000 /* 1 */
-#define AU1500_MAC1_PHYS_ADDR		0x11510000 /* 1 */
-#define AU1500_MACEN_PHYS_ADDR		0x11520000 /* 1 */
-#define AU1000_UART0_PHYS_ADDR		0x11100000 /* 01234 */
-#define AU1200_SWCNT_PHYS_ADDR		0x1110010C /* 4 */
-#define AU1000_UART1_PHYS_ADDR		0x11200000 /* 0234 */
-#define AU1000_UART2_PHYS_ADDR		0x11300000 /* 0 */
-#define AU1000_UART3_PHYS_ADDR		0x11400000 /* 0123 */
-#define AU1000_SSI0_PHYS_ADDR		0x11600000 /* 02 */
-#define AU1000_SSI1_PHYS_ADDR		0x11680000 /* 02 */
-#define AU1500_GPIO2_PHYS_ADDR		0x11700000 /* 1234 */
-#define AU1000_IC1_PHYS_ADDR		0x11800000 /* 01234 */
-#define AU1000_SYS_PHYS_ADDR		0x11900000 /* 012345 */
-#define AU1550_PSC0_PHYS_ADDR		0x11A00000 /* 34 */
-#define AU1550_PSC1_PHYS_ADDR		0x11B00000 /* 34 */
-#define AU1000_MEM_PHYS_ADDR		0x14000000 /* 01234 */
-#define AU1000_STATIC_MEM_PHYS_ADDR	0x14001000 /* 01234 */
-#define AU1300_UDMA_PHYS_ADDR		0x14001800 /* 5 */
-#define AU1000_DMA_PHYS_ADDR		0x14002000 /* 012 */
-#define AU1550_DBDMA_PHYS_ADDR		0x14002000 /* 345 */
-#define AU1550_DBDMA_CONF_PHYS_ADDR	0x14003000 /* 345 */
-#define AU1000_MACDMA0_PHYS_ADDR	0x14004000 /* 0123 */
-#define AU1000_MACDMA1_PHYS_ADDR	0x14004200 /* 0123 */
-#define AU1200_CIM_PHYS_ADDR		0x14004000 /* 45 */
-#define AU1500_PCI_PHYS_ADDR		0x14005000 /* 13 */
-#define AU1550_PE_PHYS_ADDR		0x14008000 /* 3 */
-#define AU1200_MAEBE_PHYS_ADDR		0x14010000 /* 4 */
-#define AU1200_MAEFE_PHYS_ADDR		0x14012000 /* 4 */
-#define AU1300_MAEITE_PHYS_ADDR		0x14010000 /* 5 */
-#define AU1300_MAEMPE_PHYS_ADDR		0x14014000 /* 5 */
-#define AU1550_USB_OHCI_PHYS_ADDR	0x14020000 /* 3 */
-#define AU1200_USB_CTL_PHYS_ADDR	0x14020000 /* 4 */
-#define AU1200_USB_OTG_PHYS_ADDR	0x14020020 /* 4 */
-#define AU1200_USB_OHCI_PHYS_ADDR	0x14020100 /* 4 */
-#define AU1200_USB_EHCI_PHYS_ADDR	0x14020200 /* 4 */
-#define AU1200_USB_UDC_PHYS_ADDR	0x14022000 /* 4 */
-#define AU1300_USB_EHCI_PHYS_ADDR	0x14020000 /* 5 */
-#define AU1300_USB_OHCI0_PHYS_ADDR	0x14020400 /* 5 */
-#define AU1300_USB_OHCI1_PHYS_ADDR	0x14020800 /* 5 */
-#define AU1300_USB_CTL_PHYS_ADDR	0x14021000 /* 5 */
-#define AU1300_USB_OTG_PHYS_ADDR	0x14022000 /* 5 */
-#define AU1300_MAEBSA_PHYS_ADDR		0x14030000 /* 5 */
-#define AU1100_LCD_PHYS_ADDR		0x15000000 /* 2 */
-#define AU1200_LCD_PHYS_ADDR		0x15000000 /* 45 */
-#define AU1500_PCI_MEM_PHYS_ADDR	0x400000000ULL /* 13 */
-#define AU1500_PCI_IO_PHYS_ADDR		0x500000000ULL /* 13 */
-#define AU1500_PCI_CONFIG0_PHYS_ADDR	0x600000000ULL /* 13 */
-#define AU1500_PCI_CONFIG1_PHYS_ADDR	0x680000000ULL /* 13 */
-#define AU1000_PCMCIA_IO_PHYS_ADDR	0xF00000000ULL /* 012345 */
-#define AU1000_PCMCIA_ATTR_PHYS_ADDR	0xF40000000ULL /* 012345 */
-#define AU1000_PCMCIA_MEM_PHYS_ADDR	0xF80000000ULL /* 012345 */
-
-/**********************************************************************/
-
-
-/*
- * Au1300 GPIO+INT controller (GPIC) register offsets and bits
- * Registers are 128bits (0x10 bytes), divided into 4 "banks".
- */
-#define AU1300_GPIC_PINVAL	0x0000
-#define AU1300_GPIC_PINVALCLR	0x0010
-#define AU1300_GPIC_IPEND	0x0020
-#define AU1300_GPIC_PRIENC	0x0030
-#define AU1300_GPIC_IEN		0x0040	/* int_mask in manual */
-#define AU1300_GPIC_IDIS	0x0050	/* int_maskclr in manual */
-#define AU1300_GPIC_DMASEL	0x0060
-#define AU1300_GPIC_DEVSEL	0x0080
-#define AU1300_GPIC_DEVCLR	0x0090
-#define AU1300_GPIC_RSTVAL	0x00a0
-/* pin configuration space. one 32bit register for up to 128 IRQs */
-#define AU1300_GPIC_PINCFG	0x1000
-
-#define GPIC_GPIO_TO_BIT(gpio)	\
-	(1 << ((gpio) & 0x1f))
-
-#define GPIC_GPIO_BANKOFF(gpio) \
-	(((gpio) >> 5) * 4)
-
-/* Pin Control bits: who owns the pin, what does it do */
-#define GPIC_CFG_PC_GPIN		0
-#define GPIC_CFG_PC_DEV			1
-#define GPIC_CFG_PC_GPOLOW		2
-#define GPIC_CFG_PC_GPOHIGH		3
-#define GPIC_CFG_PC_MASK		3
-
-/* assign pin to MIPS IRQ line */
-#define GPIC_CFG_IL_SET(x)	(((x) & 3) << 2)
-#define GPIC_CFG_IL_MASK	(3 << 2)
-
-/* pin interrupt type setup */
-#define GPIC_CFG_IC_OFF		(0 << 4)
-#define GPIC_CFG_IC_LEVEL_LOW	(1 << 4)
-#define GPIC_CFG_IC_LEVEL_HIGH	(2 << 4)
-#define GPIC_CFG_IC_EDGE_FALL	(5 << 4)
-#define GPIC_CFG_IC_EDGE_RISE	(6 << 4)
-#define GPIC_CFG_IC_EDGE_BOTH	(7 << 4)
-#define GPIC_CFG_IC_MASK	(7 << 4)
-
-/* allow interrupt to wake cpu from 'wait' */
-#define GPIC_CFG_IDLEWAKE	(1 << 7)
-
-/***********************************************************************/
-
-/* Au1000 SDRAM memory controller register offsets */
-#define AU1000_MEM_SDMODE0		0x0000
-#define AU1000_MEM_SDMODE1		0x0004
-#define AU1000_MEM_SDMODE2		0x0008
-#define AU1000_MEM_SDADDR0		0x000C
-#define AU1000_MEM_SDADDR1		0x0010
-#define AU1000_MEM_SDADDR2		0x0014
-#define AU1000_MEM_SDREFCFG		0x0018
-#define AU1000_MEM_SDPRECMD		0x001C
-#define AU1000_MEM_SDAUTOREF		0x0020
-#define AU1000_MEM_SDWRMD0		0x0024
-#define AU1000_MEM_SDWRMD1		0x0028
-#define AU1000_MEM_SDWRMD2		0x002C
-#define AU1000_MEM_SDSLEEP		0x0030
-#define AU1000_MEM_SDSMCKE		0x0034
-
-/* MEM_SDMODE register content definitions */
-#define MEM_SDMODE_F		(1 << 22)
-#define MEM_SDMODE_SR		(1 << 21)
-#define MEM_SDMODE_BS		(1 << 20)
-#define MEM_SDMODE_RS		(3 << 18)
-#define MEM_SDMODE_CS		(7 << 15)
-#define MEM_SDMODE_TRAS		(15 << 11)
-#define MEM_SDMODE_TMRD		(3 << 9)
-#define MEM_SDMODE_TWR		(3 << 7)
-#define MEM_SDMODE_TRP		(3 << 5)
-#define MEM_SDMODE_TRCD		(3 << 3)
-#define MEM_SDMODE_TCL		(7 << 0)
-
-#define MEM_SDMODE_BS_2Bank	(0 << 20)
-#define MEM_SDMODE_BS_4Bank	(1 << 20)
-#define MEM_SDMODE_RS_11Row	(0 << 18)
-#define MEM_SDMODE_RS_12Row	(1 << 18)
-#define MEM_SDMODE_RS_13Row	(2 << 18)
-#define MEM_SDMODE_RS_N(N)	((N) << 18)
-#define MEM_SDMODE_CS_7Col	(0 << 15)
-#define MEM_SDMODE_CS_8Col	(1 << 15)
-#define MEM_SDMODE_CS_9Col	(2 << 15)
-#define MEM_SDMODE_CS_10Col	(3 << 15)
-#define MEM_SDMODE_CS_11Col	(4 << 15)
-#define MEM_SDMODE_CS_N(N)	((N) << 15)
-#define MEM_SDMODE_TRAS_N(N)	((N) << 11)
-#define MEM_SDMODE_TMRD_N(N)	((N) << 9)
-#define MEM_SDMODE_TWR_N(N)	((N) << 7)
-#define MEM_SDMODE_TRP_N(N)	((N) << 5)
-#define MEM_SDMODE_TRCD_N(N)	((N) << 3)
-#define MEM_SDMODE_TCL_N(N)	((N) << 0)
-
-/* MEM_SDADDR register contents definitions */
-#define MEM_SDADDR_E		(1 << 20)
-#define MEM_SDADDR_CSBA		(0x03FF << 10)
-#define MEM_SDADDR_CSMASK	(0x03FF << 0)
-#define MEM_SDADDR_CSBA_N(N)	((N) & (0x03FF << 22) >> 12)
-#define MEM_SDADDR_CSMASK_N(N)	((N)&(0x03FF << 22) >> 22)
-
-/* MEM_SDREFCFG register content definitions */
-#define MEM_SDREFCFG_TRC	(15 << 28)
-#define MEM_SDREFCFG_TRPM	(3 << 26)
-#define MEM_SDREFCFG_E		(1 << 25)
-#define MEM_SDREFCFG_RE		(0x1ffffff << 0)
-#define MEM_SDREFCFG_TRC_N(N)	((N) << MEM_SDREFCFG_TRC)
-#define MEM_SDREFCFG_TRPM_N(N)	((N) << MEM_SDREFCFG_TRPM)
-#define MEM_SDREFCFG_REF_N(N)	(N)
-
-/* Au1550 SDRAM Register Offsets */
-#define AU1550_MEM_SDMODE0		0x0800
-#define AU1550_MEM_SDMODE1		0x0808
-#define AU1550_MEM_SDMODE2		0x0810
-#define AU1550_MEM_SDADDR0		0x0820
-#define AU1550_MEM_SDADDR1		0x0828
-#define AU1550_MEM_SDADDR2		0x0830
-#define AU1550_MEM_SDCONFIGA		0x0840
-#define AU1550_MEM_SDCONFIGB		0x0848
-#define AU1550_MEM_SDSTAT		0x0850
-#define AU1550_MEM_SDERRADDR		0x0858
-#define AU1550_MEM_SDSTRIDE0		0x0860
-#define AU1550_MEM_SDSTRIDE1		0x0868
-#define AU1550_MEM_SDSTRIDE2		0x0870
-#define AU1550_MEM_SDWRMD0		0x0880
-#define AU1550_MEM_SDWRMD1		0x0888
-#define AU1550_MEM_SDWRMD2		0x0890
-#define AU1550_MEM_SDPRECMD		0x08C0
-#define AU1550_MEM_SDAUTOREF		0x08C8
-#define AU1550_MEM_SDSREF		0x08D0
-#define AU1550_MEM_SDSLEEP		MEM_SDSREF
-
-/* Static Bus Controller */
-#define MEM_STCFG0		0xB4001000
-#define MEM_STTIME0		0xB4001004
-#define MEM_STADDR0		0xB4001008
-
-#define MEM_STCFG1		0xB4001010
-#define MEM_STTIME1		0xB4001014
-#define MEM_STADDR1		0xB4001018
-
-#define MEM_STCFG2		0xB4001020
-#define MEM_STTIME2		0xB4001024
-#define MEM_STADDR2		0xB4001028
-
-#define MEM_STCFG3		0xB4001030
-#define MEM_STTIME3		0xB4001034
-#define MEM_STADDR3		0xB4001038
-
-#define MEM_STNDCTL		0xB4001100
-#define MEM_STSTAT		0xB4001104
-
-#define MEM_STNAND_CMD		0x0
-#define MEM_STNAND_ADDR		0x4
-#define MEM_STNAND_DATA		0x20
-
-
-/* Programmable Counters 0 and 1 */
-#define SYS_BASE		0xB1900000
-#define SYS_COUNTER_CNTRL	(SYS_BASE + 0x14)
-#  define SYS_CNTRL_E1S		(1 << 23)
-#  define SYS_CNTRL_T1S		(1 << 20)
-#  define SYS_CNTRL_M21		(1 << 19)
-#  define SYS_CNTRL_M11		(1 << 18)
-#  define SYS_CNTRL_M01		(1 << 17)
-#  define SYS_CNTRL_C1S		(1 << 16)
-#  define SYS_CNTRL_BP		(1 << 14)
-#  define SYS_CNTRL_EN1		(1 << 13)
-#  define SYS_CNTRL_BT1		(1 << 12)
-#  define SYS_CNTRL_EN0		(1 << 11)
-#  define SYS_CNTRL_BT0		(1 << 10)
-#  define SYS_CNTRL_E0		(1 << 8)
-#  define SYS_CNTRL_E0S		(1 << 7)
-#  define SYS_CNTRL_32S		(1 << 5)
-#  define SYS_CNTRL_T0S		(1 << 4)
-#  define SYS_CNTRL_M20		(1 << 3)
-#  define SYS_CNTRL_M10		(1 << 2)
-#  define SYS_CNTRL_M00		(1 << 1)
-#  define SYS_CNTRL_C0S		(1 << 0)
-
-/* Programmable Counter 0 Registers */
-#define SYS_TOYTRIM		(SYS_BASE + 0)
-#define SYS_TOYWRITE		(SYS_BASE + 4)
-#define SYS_TOYMATCH0		(SYS_BASE + 8)
-#define SYS_TOYMATCH1		(SYS_BASE + 0xC)
-#define SYS_TOYMATCH2		(SYS_BASE + 0x10)
-#define SYS_TOYREAD		(SYS_BASE + 0x40)
-
-/* Programmable Counter 1 Registers */
-#define SYS_RTCTRIM		(SYS_BASE + 0x44)
-#define SYS_RTCWRITE		(SYS_BASE + 0x48)
-#define SYS_RTCMATCH0		(SYS_BASE + 0x4C)
-#define SYS_RTCMATCH1		(SYS_BASE + 0x50)
-#define SYS_RTCMATCH2		(SYS_BASE + 0x54)
-#define SYS_RTCREAD		(SYS_BASE + 0x58)
-
-/* I2S Controller */
-#define I2S_DATA		0xB1000000
-#  define I2S_DATA_MASK		0xffffff
-#define I2S_CONFIG		0xB1000004
-#  define I2S_CONFIG_XU		(1 << 25)
-#  define I2S_CONFIG_XO		(1 << 24)
-#  define I2S_CONFIG_RU		(1 << 23)
-#  define I2S_CONFIG_RO		(1 << 22)
-#  define I2S_CONFIG_TR		(1 << 21)
-#  define I2S_CONFIG_TE		(1 << 20)
-#  define I2S_CONFIG_TF		(1 << 19)
-#  define I2S_CONFIG_RR		(1 << 18)
-#  define I2S_CONFIG_RE		(1 << 17)
-#  define I2S_CONFIG_RF		(1 << 16)
-#  define I2S_CONFIG_PD		(1 << 11)
-#  define I2S_CONFIG_LB		(1 << 10)
-#  define I2S_CONFIG_IC		(1 << 9)
-#  define I2S_CONFIG_FM_BIT	7
-#  define I2S_CONFIG_FM_MASK	(0x3 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_I2S	(0x0 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_LJ	(0x1 << I2S_CONFIG_FM_BIT)
-#    define I2S_CONFIG_FM_RJ	(0x2 << I2S_CONFIG_FM_BIT)
-#  define I2S_CONFIG_TN		(1 << 6)
-#  define I2S_CONFIG_RN		(1 << 5)
-#  define I2S_CONFIG_SZ_BIT	0
-#  define I2S_CONFIG_SZ_MASK	(0x1F << I2S_CONFIG_SZ_BIT)
-
-#define I2S_CONTROL		0xB1000008
-#  define I2S_CONTROL_D		(1 << 1)
-#  define I2S_CONTROL_CE	(1 << 0)
-
-
-/* Ethernet Controllers  */
-
-/* 4 byte offsets from AU1000_ETH_BASE */
-#define MAC_CONTROL		0x0
-#  define MAC_RX_ENABLE		(1 << 2)
-#  define MAC_TX_ENABLE		(1 << 3)
-#  define MAC_DEF_CHECK		(1 << 5)
-#  define MAC_SET_BL(X)		(((X) & 0x3) << 6)
-#  define MAC_AUTO_PAD		(1 << 8)
-#  define MAC_DISABLE_RETRY	(1 << 10)
-#  define MAC_DISABLE_BCAST	(1 << 11)
-#  define MAC_LATE_COL		(1 << 12)
-#  define MAC_HASH_MODE		(1 << 13)
-#  define MAC_HASH_ONLY		(1 << 15)
-#  define MAC_PASS_ALL		(1 << 16)
-#  define MAC_INVERSE_FILTER	(1 << 17)
-#  define MAC_PROMISCUOUS	(1 << 18)
-#  define MAC_PASS_ALL_MULTI	(1 << 19)
-#  define MAC_FULL_DUPLEX	(1 << 20)
-#  define MAC_NORMAL_MODE	0
-#  define MAC_INT_LOOPBACK	(1 << 21)
-#  define MAC_EXT_LOOPBACK	(1 << 22)
-#  define MAC_DISABLE_RX_OWN	(1 << 23)
-#  define MAC_BIG_ENDIAN	(1 << 30)
-#  define MAC_RX_ALL		(1 << 31)
-#define MAC_ADDRESS_HIGH	0x4
-#define MAC_ADDRESS_LOW		0x8
-#define MAC_MCAST_HIGH		0xC
-#define MAC_MCAST_LOW		0x10
-#define MAC_MII_CNTRL		0x14
-#  define MAC_MII_BUSY		(1 << 0)
-#  define MAC_MII_READ		0
-#  define MAC_MII_WRITE		(1 << 1)
-#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
-#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
-#define MAC_MII_DATA		0x18
-#define MAC_FLOW_CNTRL		0x1C
-#  define MAC_FLOW_CNTRL_BUSY	(1 << 0)
-#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
-#  define MAC_PASS_CONTROL	(1 << 2)
-#  define MAC_SET_PAUSE(X)	(((X) & 0xffff) << 16)
-#define MAC_VLAN1_TAG		0x20
-#define MAC_VLAN2_TAG		0x24
-
-/* Ethernet Controller Enable */
-
-#  define MAC_EN_CLOCK_ENABLE	(1 << 0)
-#  define MAC_EN_RESET0		(1 << 1)
-#  define MAC_EN_TOSS		(0 << 2)
-#  define MAC_EN_CACHEABLE	(1 << 3)
-#  define MAC_EN_RESET1		(1 << 4)
-#  define MAC_EN_RESET2		(1 << 5)
-#  define MAC_DMA_RESET		(1 << 6)
-
-/* Ethernet Controller DMA Channels */
-
-#define MAC0_TX_DMA_ADDR	0xB4004000
-#define MAC1_TX_DMA_ADDR	0xB4004200
-/* offsets from MAC_TX_RING_ADDR address */
-#define MAC_TX_BUFF0_STATUS	0x0
-#  define TX_FRAME_ABORTED	(1 << 0)
-#  define TX_JAB_TIMEOUT	(1 << 1)
-#  define TX_NO_CARRIER		(1 << 2)
-#  define TX_LOSS_CARRIER	(1 << 3)
-#  define TX_EXC_DEF		(1 << 4)
-#  define TX_LATE_COLL_ABORT	(1 << 5)
-#  define TX_EXC_COLL		(1 << 6)
-#  define TX_UNDERRUN		(1 << 7)
-#  define TX_DEFERRED		(1 << 8)
-#  define TX_LATE_COLL		(1 << 9)
-#  define TX_COLL_CNT_MASK	(0xF << 10)
-#  define TX_PKT_RETRY		(1 << 31)
-#define MAC_TX_BUFF0_ADDR	0x4
-#  define TX_DMA_ENABLE		(1 << 0)
-#  define TX_T_DONE		(1 << 1)
-#  define TX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
-#define MAC_TX_BUFF0_LEN	0x8
-#define MAC_TX_BUFF1_STATUS	0x10
-#define MAC_TX_BUFF1_ADDR	0x14
-#define MAC_TX_BUFF1_LEN	0x18
-#define MAC_TX_BUFF2_STATUS	0x20
-#define MAC_TX_BUFF2_ADDR	0x24
-#define MAC_TX_BUFF2_LEN	0x28
-#define MAC_TX_BUFF3_STATUS	0x30
-#define MAC_TX_BUFF3_ADDR	0x34
-#define MAC_TX_BUFF3_LEN	0x38
-
-#define MAC0_RX_DMA_ADDR	0xB4004100
-#define MAC1_RX_DMA_ADDR	0xB4004300
-/* offsets from MAC_RX_RING_ADDR */
-#define MAC_RX_BUFF0_STATUS	0x0
-#  define RX_FRAME_LEN_MASK	0x3fff
-#  define RX_WDOG_TIMER		(1 << 14)
-#  define RX_RUNT		(1 << 15)
-#  define RX_OVERLEN		(1 << 16)
-#  define RX_COLL		(1 << 17)
-#  define RX_ETHER		(1 << 18)
-#  define RX_MII_ERROR		(1 << 19)
-#  define RX_DRIBBLING		(1 << 20)
-#  define RX_CRC_ERROR		(1 << 21)
-#  define RX_VLAN1		(1 << 22)
-#  define RX_VLAN2		(1 << 23)
-#  define RX_LEN_ERROR		(1 << 24)
-#  define RX_CNTRL_FRAME	(1 << 25)
-#  define RX_U_CNTRL_FRAME	(1 << 26)
-#  define RX_MCAST_FRAME	(1 << 27)
-#  define RX_BCAST_FRAME	(1 << 28)
-#  define RX_FILTER_FAIL	(1 << 29)
-#  define RX_PACKET_FILTER	(1 << 30)
-#  define RX_MISSED_FRAME	(1 << 31)
-
-#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
-		    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
-		    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
-#define MAC_RX_BUFF0_ADDR	0x4
-#  define RX_DMA_ENABLE		(1 << 0)
-#  define RX_T_DONE		(1 << 1)
-#  define RX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
-#  define RX_SET_BUFF_ADDR(X)	((X) & 0xffffffc0)
-#define MAC_RX_BUFF1_STATUS	0x10
-#define MAC_RX_BUFF1_ADDR	0x14
-#define MAC_RX_BUFF2_STATUS	0x20
-#define MAC_RX_BUFF2_ADDR	0x24
-#define MAC_RX_BUFF3_STATUS	0x30
-#define MAC_RX_BUFF3_ADDR	0x34
-
-/* SSIO */
-#define SSI0_STATUS		0xB1600000
-#  define SSI_STATUS_BF		(1 << 4)
-#  define SSI_STATUS_OF		(1 << 3)
-#  define SSI_STATUS_UF		(1 << 2)
-#  define SSI_STATUS_D		(1 << 1)
-#  define SSI_STATUS_B		(1 << 0)
-#define SSI0_INT		0xB1600004
-#  define SSI_INT_OI		(1 << 3)
-#  define SSI_INT_UI		(1 << 2)
-#  define SSI_INT_DI		(1 << 1)
-#define SSI0_INT_ENABLE		0xB1600008
-#  define SSI_INTE_OIE		(1 << 3)
-#  define SSI_INTE_UIE		(1 << 2)
-#  define SSI_INTE_DIE		(1 << 1)
-#define SSI0_CONFIG		0xB1600020
-#  define SSI_CONFIG_AO		(1 << 24)
-#  define SSI_CONFIG_DO		(1 << 23)
-#  define SSI_CONFIG_ALEN_BIT	20
-#  define SSI_CONFIG_ALEN_MASK	(0x7 << 20)
-#  define SSI_CONFIG_DLEN_BIT	16
-#  define SSI_CONFIG_DLEN_MASK	(0x7 << 16)
-#  define SSI_CONFIG_DD		(1 << 11)
-#  define SSI_CONFIG_AD		(1 << 10)
-#  define SSI_CONFIG_BM_BIT	8
-#  define SSI_CONFIG_BM_MASK	(0x3 << 8)
-#  define SSI_CONFIG_CE		(1 << 7)
-#  define SSI_CONFIG_DP		(1 << 6)
-#  define SSI_CONFIG_DL		(1 << 5)
-#  define SSI_CONFIG_EP		(1 << 4)
-#define SSI0_ADATA		0xB1600024
-#  define SSI_AD_D		(1 << 24)
-#  define SSI_AD_ADDR_BIT	16
-#  define SSI_AD_ADDR_MASK	(0xff << 16)
-#  define SSI_AD_DATA_BIT	0
-#  define SSI_AD_DATA_MASK	(0xfff << 0)
-#define SSI0_CLKDIV		0xB1600028
-#define SSI0_CONTROL		0xB1600100
-#  define SSI_CONTROL_CD	(1 << 1)
-#  define SSI_CONTROL_E		(1 << 0)
-
-/* SSI1 */
-#define SSI1_STATUS		0xB1680000
-#define SSI1_INT		0xB1680004
-#define SSI1_INT_ENABLE		0xB1680008
-#define SSI1_CONFIG		0xB1680020
-#define SSI1_ADATA		0xB1680024
-#define SSI1_CLKDIV		0xB1680028
-#define SSI1_ENABLE		0xB1680100
-
-/*
- * Register content definitions
- */
-#define SSI_STATUS_BF		(1 << 4)
-#define SSI_STATUS_OF		(1 << 3)
-#define SSI_STATUS_UF		(1 << 2)
-#define SSI_STATUS_D		(1 << 1)
-#define SSI_STATUS_B		(1 << 0)
-
-/* SSI_INT */
-#define SSI_INT_OI		(1 << 3)
-#define SSI_INT_UI		(1 << 2)
-#define SSI_INT_DI		(1 << 1)
-
-/* SSI_INTEN */
-#define SSI_INTEN_OIE		(1 << 3)
-#define SSI_INTEN_UIE		(1 << 2)
-#define SSI_INTEN_DIE		(1 << 1)
-
-#define SSI_CONFIG_AO		(1 << 24)
-#define SSI_CONFIG_DO		(1 << 23)
-#define SSI_CONFIG_ALEN		(7 << 20)
-#define SSI_CONFIG_DLEN		(15 << 16)
-#define SSI_CONFIG_DD		(1 << 11)
-#define SSI_CONFIG_AD		(1 << 10)
-#define SSI_CONFIG_BM		(3 << 8)
-#define SSI_CONFIG_CE		(1 << 7)
-#define SSI_CONFIG_DP		(1 << 6)
-#define SSI_CONFIG_DL		(1 << 5)
-#define SSI_CONFIG_EP		(1 << 4)
-#define SSI_CONFIG_ALEN_N(N)	((N-1) << 20)
-#define SSI_CONFIG_DLEN_N(N)	((N-1) << 16)
-#define SSI_CONFIG_BM_HI	(0 << 8)
-#define SSI_CONFIG_BM_LO	(1 << 8)
-#define SSI_CONFIG_BM_CY	(2 << 8)
-
-#define SSI_ADATA_D		(1 << 24)
-#define SSI_ADATA_ADDR		(0xFF << 16)
-#define SSI_ADATA_DATA		0x0FFF
-#define SSI_ADATA_ADDR_N(N)	(N << 16)
-
-#define SSI_ENABLE_CD		(1 << 1)
-#define SSI_ENABLE_E		(1 << 0)
-
-
-/*
- * The IrDA peripheral has an IRFIRSEL pin, but on the DB/PB boards it's not
- * used to select FIR/SIR mode on the transceiver but as a GPIO.  Instead a
- * CPLD has to be told about the mode.
- */
-#define AU1000_IRDA_PHY_MODE_OFF	0
-#define AU1000_IRDA_PHY_MODE_SIR	1
-#define AU1000_IRDA_PHY_MODE_FIR	2
-
-struct au1k_irda_platform_data {
-	void(*set_phy_mode)(int mode);
-};
-
-
-/* GPIO */
-#define SYS_PINFUNC		0xB190002C
-#  define SYS_PF_USB		(1 << 15)	/* 2nd USB device/host */
-#  define SYS_PF_U3		(1 << 14)	/* GPIO23/U3TXD */
-#  define SYS_PF_U2		(1 << 13)	/* GPIO22/U2TXD */
-#  define SYS_PF_U1		(1 << 12)	/* GPIO21/U1TXD */
-#  define SYS_PF_SRC		(1 << 11)	/* GPIO6/SROMCKE */
-#  define SYS_PF_CK5		(1 << 10)	/* GPIO3/CLK5 */
-#  define SYS_PF_CK4		(1 << 9)	/* GPIO2/CLK4 */
-#  define SYS_PF_IRF		(1 << 8)	/* GPIO15/IRFIRSEL */
-#  define SYS_PF_UR3		(1 << 7)	/* GPIO[14:9]/UART3 */
-#  define SYS_PF_I2D		(1 << 6)	/* GPIO8/I2SDI */
-#  define SYS_PF_I2S		(1 << 5)	/* I2S/GPIO[29:31] */
-#  define SYS_PF_NI2		(1 << 4)	/* NI2/GPIO[24:28] */
-#  define SYS_PF_U0		(1 << 3)	/* U0TXD/GPIO20 */
-#  define SYS_PF_RD		(1 << 2)	/* IRTXD/GPIO19 */
-#  define SYS_PF_A97		(1 << 1)	/* AC97/SSL1 */
-#  define SYS_PF_S0		(1 << 0)	/* SSI_0/GPIO[16:18] */
-
-/* Au1100 only */
-#  define SYS_PF_PC		(1 << 18)	/* PCMCIA/GPIO[207:204] */
-#  define SYS_PF_LCD		(1 << 17)	/* extern lcd/GPIO[203:200] */
-#  define SYS_PF_CS		(1 << 16)	/* EXTCLK0/32KHz to gpio2 */
-#  define SYS_PF_EX0		(1 << 9)	/* GPIO2/clock */
-
-/* Au1550 only.	 Redefines lots of pins */
-#  define SYS_PF_PSC2_MASK	(7 << 17)
-#  define SYS_PF_PSC2_AC97	0
-#  define SYS_PF_PSC2_SPI	0
-#  define SYS_PF_PSC2_I2S	(1 << 17)
-#  define SYS_PF_PSC2_SMBUS	(3 << 17)
-#  define SYS_PF_PSC2_GPIO	(7 << 17)
-#  define SYS_PF_PSC3_MASK	(7 << 20)
-#  define SYS_PF_PSC3_AC97	0
-#  define SYS_PF_PSC3_SPI	0
-#  define SYS_PF_PSC3_I2S	(1 << 20)
-#  define SYS_PF_PSC3_SMBUS	(3 << 20)
-#  define SYS_PF_PSC3_GPIO	(7 << 20)
-#  define SYS_PF_PSC1_S1	(1 << 1)
-#  define SYS_PF_MUST_BE_SET	((1 << 5) | (1 << 2))
-
-/* Au1200 only */
-#define SYS_PINFUNC_DMA		(1 << 31)
-#define SYS_PINFUNC_S0A		(1 << 30)
-#define SYS_PINFUNC_S1A		(1 << 29)
-#define SYS_PINFUNC_LP0		(1 << 28)
-#define SYS_PINFUNC_LP1		(1 << 27)
-#define SYS_PINFUNC_LD16	(1 << 26)
-#define SYS_PINFUNC_LD8		(1 << 25)
-#define SYS_PINFUNC_LD1		(1 << 24)
-#define SYS_PINFUNC_LD0		(1 << 23)
-#define SYS_PINFUNC_P1A		(3 << 21)
-#define SYS_PINFUNC_P1B		(1 << 20)
-#define SYS_PINFUNC_FS3		(1 << 19)
-#define SYS_PINFUNC_P0A		(3 << 17)
-#define SYS_PINFUNC_CS		(1 << 16)
-#define SYS_PINFUNC_CIM		(1 << 15)
-#define SYS_PINFUNC_P1C		(1 << 14)
-#define SYS_PINFUNC_U1T		(1 << 12)
-#define SYS_PINFUNC_U1R		(1 << 11)
-#define SYS_PINFUNC_EX1		(1 << 10)
-#define SYS_PINFUNC_EX0		(1 << 9)
-#define SYS_PINFUNC_U0R		(1 << 8)
-#define SYS_PINFUNC_MC		(1 << 7)
-#define SYS_PINFUNC_S0B		(1 << 6)
-#define SYS_PINFUNC_S0C		(1 << 5)
-#define SYS_PINFUNC_P0B		(1 << 4)
-#define SYS_PINFUNC_U0T		(1 << 3)
-#define SYS_PINFUNC_S1B		(1 << 2)
-
-/* Power Management */
-#define SYS_SCRATCH0		0xB1900018
-#define SYS_SCRATCH1		0xB190001C
-#define SYS_WAKEMSK		0xB1900034
-#define SYS_ENDIAN		0xB1900038
-#define SYS_POWERCTRL		0xB190003C
-#define SYS_WAKESRC		0xB190005C
-#define SYS_SLPPWR		0xB1900078
-#define SYS_SLEEP		0xB190007C
-
-#define SYS_WAKEMSK_D2		(1 << 9)
-#define SYS_WAKEMSK_M2		(1 << 8)
-#define SYS_WAKEMSK_GPIO(x)	(1 << (x))
-
-/* Clock Controller */
-#define SYS_FREQCTRL0		0xB1900020
-#  define SYS_FC_FRDIV2_BIT	22
-#  define SYS_FC_FRDIV2_MASK	(0xff << SYS_FC_FRDIV2_BIT)
-#  define SYS_FC_FE2		(1 << 21)
-#  define SYS_FC_FS2		(1 << 20)
-#  define SYS_FC_FRDIV1_BIT	12
-#  define SYS_FC_FRDIV1_MASK	(0xff << SYS_FC_FRDIV1_BIT)
-#  define SYS_FC_FE1		(1 << 11)
-#  define SYS_FC_FS1		(1 << 10)
-#  define SYS_FC_FRDIV0_BIT	2
-#  define SYS_FC_FRDIV0_MASK	(0xff << SYS_FC_FRDIV0_BIT)
-#  define SYS_FC_FE0		(1 << 1)
-#  define SYS_FC_FS0		(1 << 0)
-#define SYS_FREQCTRL1		0xB1900024
-#  define SYS_FC_FRDIV5_BIT	22
-#  define SYS_FC_FRDIV5_MASK	(0xff << SYS_FC_FRDIV5_BIT)
-#  define SYS_FC_FE5		(1 << 21)
-#  define SYS_FC_FS5		(1 << 20)
-#  define SYS_FC_FRDIV4_BIT	12
-#  define SYS_FC_FRDIV4_MASK	(0xff << SYS_FC_FRDIV4_BIT)
-#  define SYS_FC_FE4		(1 << 11)
-#  define SYS_FC_FS4		(1 << 10)
-#  define SYS_FC_FRDIV3_BIT	2
-#  define SYS_FC_FRDIV3_MASK	(0xff << SYS_FC_FRDIV3_BIT)
-#  define SYS_FC_FE3		(1 << 1)
-#  define SYS_FC_FS3		(1 << 0)
-#define SYS_CLKSRC		0xB1900028
-#  define SYS_CS_ME1_BIT	27
-#  define SYS_CS_ME1_MASK	(0x7 << SYS_CS_ME1_BIT)
-#  define SYS_CS_DE1		(1 << 26)
-#  define SYS_CS_CE1		(1 << 25)
-#  define SYS_CS_ME0_BIT	22
-#  define SYS_CS_ME0_MASK	(0x7 << SYS_CS_ME0_BIT)
-#  define SYS_CS_DE0		(1 << 21)
-#  define SYS_CS_CE0		(1 << 20)
-#  define SYS_CS_MI2_BIT	17
-#  define SYS_CS_MI2_MASK	(0x7 << SYS_CS_MI2_BIT)
-#  define SYS_CS_DI2		(1 << 16)
-#  define SYS_CS_CI2		(1 << 15)
-
-#  define SYS_CS_ML_BIT		7
-#  define SYS_CS_ML_MASK	(0x7 << SYS_CS_ML_BIT)
-#  define SYS_CS_DL		(1 << 6)
-#  define SYS_CS_CL		(1 << 5)
-
-#  define SYS_CS_MUH_BIT	12
-#  define SYS_CS_MUH_MASK	(0x7 << SYS_CS_MUH_BIT)
-#  define SYS_CS_DUH		(1 << 11)
-#  define SYS_CS_CUH		(1 << 10)
-#  define SYS_CS_MUD_BIT	7
-#  define SYS_CS_MUD_MASK	(0x7 << SYS_CS_MUD_BIT)
-#  define SYS_CS_DUD		(1 << 6)
-#  define SYS_CS_CUD		(1 << 5)
-
-#  define SYS_CS_MIR_BIT	2
-#  define SYS_CS_MIR_MASK	(0x7 << SYS_CS_MIR_BIT)
-#  define SYS_CS_DIR		(1 << 1)
-#  define SYS_CS_CIR		(1 << 0)
-
-#  define SYS_CS_MUX_AUX	0x1
-#  define SYS_CS_MUX_FQ0	0x2
-#  define SYS_CS_MUX_FQ1	0x3
-#  define SYS_CS_MUX_FQ2	0x4
-#  define SYS_CS_MUX_FQ3	0x5
-#  define SYS_CS_MUX_FQ4	0x6
-#  define SYS_CS_MUX_FQ5	0x7
-#define SYS_CPUPLL		0xB1900060
-#define SYS_AUXPLL		0xB1900064
-
-/* AC97 Controller */
-#define AC97C_CONFIG		0xB0000000
-#  define AC97C_RECV_SLOTS_BIT	13
-#  define AC97C_RECV_SLOTS_MASK (0x3ff << AC97C_RECV_SLOTS_BIT)
-#  define AC97C_XMIT_SLOTS_BIT	3
-#  define AC97C_XMIT_SLOTS_MASK (0x3ff << AC97C_XMIT_SLOTS_BIT)
-#  define AC97C_SG		(1 << 2)
-#  define AC97C_SYNC		(1 << 1)
-#  define AC97C_RESET		(1 << 0)
-#define AC97C_STATUS		0xB0000004
-#  define AC97C_XU		(1 << 11)
-#  define AC97C_XO		(1 << 10)
-#  define AC97C_RU		(1 << 9)
-#  define AC97C_RO		(1 << 8)
-#  define AC97C_READY		(1 << 7)
-#  define AC97C_CP		(1 << 6)
-#  define AC97C_TR		(1 << 5)
-#  define AC97C_TE		(1 << 4)
-#  define AC97C_TF		(1 << 3)
-#  define AC97C_RR		(1 << 2)
-#  define AC97C_RE		(1 << 1)
-#  define AC97C_RF		(1 << 0)
-#define AC97C_DATA		0xB0000008
-#define AC97C_CMD		0xB000000C
-#  define AC97C_WD_BIT		16
-#  define AC97C_READ		(1 << 7)
-#  define AC97C_INDEX_MASK	0x7f
-#define AC97C_CNTRL		0xB0000010
-#  define AC97C_RS		(1 << 1)
-#  define AC97C_CE		(1 << 0)
-
-
-/* The PCI chip selects are outside the 32bit space, and since we can't
- * just program the 36bit addresses into BARs, we have to take a chunk
- * out of the 32bit space and reserve it for PCI.  When these addresses
- * are ioremap()ed, they'll be fixed up to the real 36bit address before
- * being passed to the real ioremap function.
- */
-#define ALCHEMY_PCI_MEMWIN_START	(AU1500_PCI_MEM_PHYS_ADDR >> 4)
-#define ALCHEMY_PCI_MEMWIN_END		(ALCHEMY_PCI_MEMWIN_START + 0x0FFFFFFF)
-
-/* for PCI IO it's simpler because we get to do the ioremap ourselves and then
- * adjust the device's resources.
- */
-#define ALCHEMY_PCI_IOWIN_START		0x00001000
-#define ALCHEMY_PCI_IOWIN_END		0x0000FFFF
-
-#ifdef CONFIG_PCI
-
-#define IOPORT_RESOURCE_START	0x00001000	/* skip legacy probing */
-#define IOPORT_RESOURCE_END	0xffffffff
-#define IOMEM_RESOURCE_START	0x10000000
-#define IOMEM_RESOURCE_END	0xfffffffffULL
-
-#else
-
-/* Don't allow any legacy ports probing */
-#define IOPORT_RESOURCE_START	0x10000000
-#define IOPORT_RESOURCE_END	0xffffffff
-#define IOMEM_RESOURCE_START	0x10000000
-#define IOMEM_RESOURCE_END	0xfffffffffULL
-
-#endif
-
-/* PCI controller block register offsets */
-#define PCI_REG_CMEM		0x0000
-#define PCI_REG_CONFIG		0x0004
-#define PCI_REG_B2BMASK_CCH	0x0008
-#define PCI_REG_B2BBASE0_VID	0x000C
-#define PCI_REG_B2BBASE1_SID	0x0010
-#define PCI_REG_MWMASK_DEV	0x0014
-#define PCI_REG_MWBASE_REV_CCL	0x0018
-#define PCI_REG_ERR_ADDR	0x001C
-#define PCI_REG_SPEC_INTACK	0x0020
-#define PCI_REG_ID		0x0100
-#define PCI_REG_STATCMD		0x0104
-#define PCI_REG_CLASSREV	0x0108
-#define PCI_REG_PARAM		0x010C
-#define PCI_REG_MBAR		0x0110
-#define PCI_REG_TIMEOUT		0x0140
-
-/* PCI controller block register bits */
-#define PCI_CMEM_E		(1 << 28)	/* enable cacheable memory */
-#define PCI_CMEM_CMBASE(x)	(((x) & 0x3fff) << 14)
-#define PCI_CMEM_CMMASK(x)	((x) & 0x3fff)
-#define PCI_CONFIG_ERD		(1 << 27) /* pci error during R/W */
-#define PCI_CONFIG_ET		(1 << 26) /* error in target mode */
-#define PCI_CONFIG_EF		(1 << 25) /* fatal error */
-#define PCI_CONFIG_EP		(1 << 24) /* parity error */
-#define PCI_CONFIG_EM		(1 << 23) /* multiple errors */
-#define PCI_CONFIG_BM		(1 << 22) /* bad master error */
-#define PCI_CONFIG_PD		(1 << 20) /* PCI Disable */
-#define PCI_CONFIG_BME		(1 << 19) /* Byte Mask Enable for reads */
-#define PCI_CONFIG_NC		(1 << 16) /* mark mem access non-coherent */
-#define PCI_CONFIG_IA		(1 << 15) /* INTA# enabled (target mode) */
-#define PCI_CONFIG_IP		(1 << 13) /* int on PCI_PERR# */
-#define PCI_CONFIG_IS		(1 << 12) /* int on PCI_SERR# */
-#define PCI_CONFIG_IMM		(1 << 11) /* int on master abort */
-#define PCI_CONFIG_ITM		(1 << 10) /* int on target abort (as master) */
-#define PCI_CONFIG_ITT		(1 << 9)  /* int on target abort (as target) */
-#define PCI_CONFIG_IPB		(1 << 8)  /* int on PERR# in bus master acc */
-#define PCI_CONFIG_SIC_NO	(0 << 6)  /* no byte mask changes */
-#define PCI_CONFIG_SIC_BA_ADR	(1 << 6)  /* on byte/hw acc, invert adr bits */
-#define PCI_CONFIG_SIC_HWA_DAT	(2 << 6)  /* on halfword acc, swap data */
-#define PCI_CONFIG_SIC_ALL	(3 << 6)  /* swap data bytes on all accesses */
-#define PCI_CONFIG_ST		(1 << 5)  /* swap data by target transactions */
-#define PCI_CONFIG_SM		(1 << 4)  /* swap data from PCI ctl */
-#define PCI_CONFIG_AEN		(1 << 3)  /* enable internal arbiter */
-#define PCI_CONFIG_R2H		(1 << 2)  /* REQ2# to hi-prio arbiter */
-#define PCI_CONFIG_R1H		(1 << 1)  /* REQ1# to hi-prio arbiter */
-#define PCI_CONFIG_CH		(1 << 0)  /* PCI ctl to hi-prio arbiter */
-#define PCI_B2BMASK_B2BMASK(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BMASK_CCH(x)	((x) & 0xffff) /* 16 upper bits of class code */
-#define PCI_B2BBASE0_VID_B0(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BBASE0_VID_SV(x)	((x) & 0xffff)
-#define PCI_B2BBASE1_SID_B1(x)	(((x) & 0xffff) << 16)
-#define PCI_B2BBASE1_SID_SI(x)	((x) & 0xffff)
-#define PCI_MWMASKDEV_MWMASK(x) (((x) & 0xffff) << 16)
-#define PCI_MWMASKDEV_DEVID(x)	((x) & 0xffff)
-#define PCI_MWBASEREVCCL_BASE(x) (((x) & 0xffff) << 16)
-#define PCI_MWBASEREVCCL_REV(x)	 (((x) & 0xff) << 8)
-#define PCI_MWBASEREVCCL_CCL(x)	 ((x) & 0xff)
-#define PCI_ID_DID(x)		(((x) & 0xffff) << 16)
-#define PCI_ID_VID(x)		((x) & 0xffff)
-#define PCI_STATCMD_STATUS(x)	(((x) & 0xffff) << 16)
-#define PCI_STATCMD_CMD(x)	((x) & 0xffff)
-#define PCI_CLASSREV_CLASS(x)	(((x) & 0x00ffffff) << 8)
-#define PCI_CLASSREV_REV(x)	((x) & 0xff)
-#define PCI_PARAM_BIST(x)	(((x) & 0xff) << 24)
-#define PCI_PARAM_HT(x)		(((x) & 0xff) << 16)
-#define PCI_PARAM_LT(x)		(((x) & 0xff) << 8)
-#define PCI_PARAM_CLS(x)	((x) & 0xff)
-#define PCI_TIMEOUT_RETRIES(x)	(((x) & 0xff) << 8)	/* max retries */
-#define PCI_TIMEOUT_TO(x)	((x) & 0xff)	/* target ready timeout */
-
 #endif
diff --git a/arch/mips/include/asm/mach-au1x00/au1000_dma.h b/arch/mips/include/asm/mach-au1x00/au1000_dma.h
index 7cedca5..0a0cd42 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000_dma.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000_dma.h
@@ -106,7 +106,7 @@
 struct dma_chan {
 	int dev_id;		/* this channel is allocated if >= 0, */
 				/* free otherwise */
-	unsigned int io;
+	void __iomem *io;
 	const char *dev_str;
 	int irq;
 	void *irq_dev;
@@ -157,7 +157,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE0, chan->io + DMA_MODE_SET);
 }
 
 static inline void enable_dma_buffer1(unsigned int dmanr)
@@ -166,7 +166,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE1, chan->io + DMA_MODE_SET);
 }
 static inline void enable_dma_buffers(unsigned int dmanr)
 {
@@ -174,7 +174,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_BE0 | DMA_BE1, chan->io + DMA_MODE_SET);
 }
 
 static inline void start_dma(unsigned int dmanr)
@@ -183,7 +183,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_GO, chan->io + DMA_MODE_SET);
+	__raw_writel(DMA_GO, chan->io + DMA_MODE_SET);
 }
 
 #define DMA_HALT_POLL 0x5000
@@ -195,11 +195,11 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
 
 	/* Poll the halt bit */
 	for (i = 0; i < DMA_HALT_POLL; i++)
-		if (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
+		if (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT)
 			break;
 	if (i == DMA_HALT_POLL)
 		printk(KERN_INFO "halt_dma: HALT poll expired!\n");
@@ -215,7 +215,7 @@
 	halt_dma(dmanr);
 
 	/* Now we can disable the buffers */
-	au_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(~DMA_GO, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline int dma_halted(unsigned int dmanr)
@@ -224,7 +224,7 @@
 
 	if (!chan)
 		return 1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
+	return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_HALT) ? 1 : 0;
 }
 
 /* Initialize a DMA channel. */
@@ -239,14 +239,14 @@
 	disable_dma(dmanr);
 
 	/* Set device FIFO address */
-	au_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
+	__raw_writel(CPHYSADDR(chan->fifo_addr), chan->io + DMA_PERIPHERAL_ADDR);
 
 	mode = chan->mode | (chan->dev_id << DMA_DID_BIT);
 	if (chan->irq)
 		mode |= DMA_IE;
 
-	au_writel(~mode, chan->io + DMA_MODE_CLEAR);
-	au_writel(mode,	 chan->io + DMA_MODE_SET);
+	__raw_writel(~mode, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(mode,	 chan->io + DMA_MODE_SET);
 }
 
 /*
@@ -283,7 +283,7 @@
 
 	if (!chan)
 		return -1;
-	return (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
+	return (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? 1 : 0;
 }
 
 /*
@@ -304,7 +304,7 @@
 	if (chan->dev_id != DMA_ID_GP04 && chan->dev_id != DMA_ID_GP05)
 		return;
 
-	au_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
+	__raw_writel(CPHYSADDR(a), chan->io + DMA_PERIPHERAL_ADDR);
 }
 
 /*
@@ -316,7 +316,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
 }
 
 static inline void clear_dma_done1(unsigned int dmanr)
@@ -325,7 +325,7 @@
 
 	if (!chan)
 		return;
-	au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
+	__raw_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
 }
 
 /*
@@ -344,7 +344,7 @@
 
 	if (!chan)
 		return;
-	au_writel(a, chan->io + DMA_BUFFER0_START);
+	__raw_writel(a, chan->io + DMA_BUFFER0_START);
 }
 
 /*
@@ -356,7 +356,7 @@
 
 	if (!chan)
 		return;
-	au_writel(a, chan->io + DMA_BUFFER1_START);
+	__raw_writel(a, chan->io + DMA_BUFFER1_START);
 }
 
 
@@ -370,7 +370,7 @@
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
 }
 
 /*
@@ -383,7 +383,7 @@
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -396,8 +396,8 @@
 	if (!chan)
 		return;
 	count &= DMA_COUNT_MASK;
-	au_writel(count, chan->io + DMA_BUFFER0_COUNT);
-	au_writel(count, chan->io + DMA_BUFFER1_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER0_COUNT);
+	__raw_writel(count, chan->io + DMA_BUFFER1_COUNT);
 }
 
 /*
@@ -410,7 +410,7 @@
 
 	if (!chan)
 		return 0;
-	return au_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
+	return __raw_readl(chan->io + DMA_MODE_READ) & (DMA_D0 | DMA_D1);
 }
 
 
@@ -437,10 +437,10 @@
 	if (!chan)
 		return 0;
 
-	curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
+	curBufCntReg = (__raw_readl(chan->io + DMA_MODE_READ) & DMA_AB) ?
 	    DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
 
-	count = au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
+	count = __raw_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
 
 	if ((chan->mode & DMA_DW_MASK) == DMA_DW16)
 		count <<= 1;
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
index 796afd0..9785e4e 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio-au1000.h
@@ -25,20 +25,20 @@
 #define MAKE_IRQ(intc, off)	(AU1000_INTC##intc##_INT_BASE + (off))
 
 /* GPIO1 registers within SYS_ area */
-#define SYS_TRIOUTRD		0x100
-#define SYS_TRIOUTCLR		0x100
-#define SYS_OUTPUTRD		0x108
-#define SYS_OUTPUTSET		0x108
-#define SYS_OUTPUTCLR		0x10C
-#define SYS_PINSTATERD		0x110
-#define SYS_PININPUTEN		0x110
+#define AU1000_SYS_TRIOUTRD	0x100
+#define AU1000_SYS_TRIOUTCLR	0x100
+#define AU1000_SYS_OUTPUTRD	0x108
+#define AU1000_SYS_OUTPUTSET	0x108
+#define AU1000_SYS_OUTPUTCLR	0x10C
+#define AU1000_SYS_PINSTATERD	0x110
+#define AU1000_SYS_PININPUTEN	0x110
 
 /* register offsets within GPIO2 block */
-#define GPIO2_DIR		0x00
-#define GPIO2_OUTPUT		0x08
-#define GPIO2_PINSTATE		0x0C
-#define GPIO2_INTENABLE		0x10
-#define GPIO2_ENABLE		0x14
+#define AU1000_GPIO2_DIR	0x00
+#define AU1000_GPIO2_OUTPUT	0x08
+#define AU1000_GPIO2_PINSTATE	0x0C
+#define AU1000_GPIO2_INTENABLE	0x10
+#define AU1000_GPIO2_ENABLE	0x14
 
 struct gpio;
 
@@ -217,26 +217,21 @@
  */
 static inline void alchemy_gpio1_set_value(int gpio, int v)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	unsigned long r = v ? SYS_OUTPUTSET : SYS_OUTPUTCLR;
-	__raw_writel(mask, base + r);
-	wmb();
+	unsigned long r = v ? AU1000_SYS_OUTPUTSET : AU1000_SYS_OUTPUTCLR;
+	alchemy_wrsys(mask, r);
 }
 
 static inline int alchemy_gpio1_get_value(int gpio)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	return __raw_readl(base + SYS_PINSTATERD) & mask;
+	return alchemy_rdsys(AU1000_SYS_PINSTATERD) & mask;
 }
 
 static inline int alchemy_gpio1_direction_input(int gpio)
 {
-	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO1_BASE);
-	__raw_writel(mask, base + SYS_TRIOUTCLR);
-	wmb();
+	alchemy_wrsys(mask, AU1000_SYS_TRIOUTCLR);
 	return 0;
 }
 
@@ -279,13 +274,13 @@
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
 	unsigned long mask = 1 << (gpio - ALCHEMY_GPIO2_BASE);
-	unsigned long d = __raw_readl(base + GPIO2_DIR);
+	unsigned long d = __raw_readl(base + AU1000_GPIO2_DIR);
 
 	if (to_out)
 		d |= mask;
 	else
 		d &= ~mask;
-	__raw_writel(d, base + GPIO2_DIR);
+	__raw_writel(d, base + AU1000_GPIO2_DIR);
 	wmb();
 }
 
@@ -294,14 +289,15 @@
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
 	unsigned long mask;
 	mask = ((v) ? 0x00010001 : 0x00010000) << (gpio - ALCHEMY_GPIO2_BASE);
-	__raw_writel(mask, base + GPIO2_OUTPUT);
+	__raw_writel(mask, base + AU1000_GPIO2_OUTPUT);
 	wmb();
 }
 
 static inline int alchemy_gpio2_get_value(int gpio)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	return __raw_readl(base + GPIO2_PINSTATE) & (1 << (gpio - ALCHEMY_GPIO2_BASE));
+	return __raw_readl(base + AU1000_GPIO2_PINSTATE) &
+				(1 << (gpio - ALCHEMY_GPIO2_BASE));
 }
 
 static inline int alchemy_gpio2_direction_input(int gpio)
@@ -352,12 +348,12 @@
 static inline void __alchemy_gpio2_mod_int(int gpio2, int en)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	unsigned long r = __raw_readl(base + GPIO2_INTENABLE);
+	unsigned long r = __raw_readl(base + AU1000_GPIO2_INTENABLE);
 	if (en)
 		r |= 1 << gpio2;
 	else
 		r &= ~(1 << gpio2);
-	__raw_writel(r, base + GPIO2_INTENABLE);
+	__raw_writel(r, base + AU1000_GPIO2_INTENABLE);
 	wmb();
 }
 
@@ -434,9 +430,9 @@
 static inline void alchemy_gpio2_enable(void)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	__raw_writel(3, base + GPIO2_ENABLE);	/* reset, clock enabled */
+	__raw_writel(3, base + AU1000_GPIO2_ENABLE);	/* reset, clock enabled */
 	wmb();
-	__raw_writel(1, base + GPIO2_ENABLE);	/* clock enabled */
+	__raw_writel(1, base + AU1000_GPIO2_ENABLE);	/* clock enabled */
 	wmb();
 }
 
@@ -448,7 +444,7 @@
 static inline void alchemy_gpio2_disable(void)
 {
 	void __iomem *base = (void __iomem *)KSEG1ADDR(AU1500_GPIO2_PHYS_ADDR);
-	__raw_writel(2, base + GPIO2_ENABLE);	/* reset, clock disabled */
+	__raw_writel(2, base + AU1000_GPIO2_ENABLE);	/* reset, clock disabled */
 	wmb();
 }
 
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
index bba7399..1f5643b 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -18,6 +18,7 @@
 	BCM47XX_BOARD_ASUS_WL300G,
 	BCM47XX_BOARD_ASUS_WL320GE,
 	BCM47XX_BOARD_ASUS_WL330GE,
+	BCM47XX_BOARD_ASUS_WL500G,
 	BCM47XX_BOARD_ASUS_WL500GD,
 	BCM47XX_BOARD_ASUS_WL500GPV1,
 	BCM47XX_BOARD_ASUS_WL500GPV2,
@@ -70,11 +71,15 @@
 	BCM47XX_BOARD_LINKSYS_WRT310NV1,
 	BCM47XX_BOARD_LINKSYS_WRT310NV2,
 	BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
-	BCM47XX_BOARD_LINKSYS_WRT54G,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467,
+	BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0708,
 	BCM47XX_BOARD_LINKSYS_WRT610NV1,
 	BCM47XX_BOARD_LINKSYS_WRT610NV2,
 	BCM47XX_BOARD_LINKSYS_WRTSL54GS,
 
+	BCM47XX_BOARD_MICROSOFT_MN700,
+
 	BCM47XX_BOARD_MOTOROLA_WE800G,
 	BCM47XX_BOARD_MOTOROLA_WR850GP,
 	BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
index 3112f08..56bb192 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
@@ -19,118 +19,68 @@
 #define BCM6368_CPU_ID		0x6368
 
 void __init bcm63xx_cpu_init(void);
-u16 __bcm63xx_get_cpu_id(void);
 u8 bcm63xx_get_cpu_rev(void);
 unsigned int bcm63xx_get_cpu_freq(void);
 
+static inline u16 __pure __bcm63xx_get_cpu_id(const u16 cpu_id)
+{
+	switch (cpu_id) {
 #ifdef CONFIG_BCM63XX_CPU_3368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM3368_CPU_ID
-# endif
-# define BCMCPU_IS_3368()	(bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
-#else
-# define BCMCPU_IS_3368()	(0)
+		case BCM3368_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6328
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6328_CPU_ID
-# endif
-# define BCMCPU_IS_6328()	(bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
-#else
-# define BCMCPU_IS_6328()	(0)
+		case BCM6328_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6338
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6338_CPU_ID
-# endif
-# define BCMCPU_IS_6338()	(bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
-#else
-# define BCMCPU_IS_6338()	(0)
+		case BCM6338_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6345
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6345_CPU_ID
-# endif
-# define BCMCPU_IS_6345()	(bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
-#else
-# define BCMCPU_IS_6345()	(0)
+		case BCM6345_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6348
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6348_CPU_ID
-# endif
-# define BCMCPU_IS_6348()	(bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
-#else
-# define BCMCPU_IS_6348()	(0)
+		case BCM6348_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6358
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6358_CPU_ID
-# endif
-# define BCMCPU_IS_6358()	(bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
-#else
-# define BCMCPU_IS_6358()	(0)
+		case BCM6358_CPU_ID:
 #endif
 
 #ifdef CONFIG_BCM63XX_CPU_6362
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6362_CPU_ID
-# endif
-# define BCMCPU_IS_6362()	(bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
-#else
-# define BCMCPU_IS_6362()	(0)
+		case BCM6362_CPU_ID:
 #endif
 
-
 #ifdef CONFIG_BCM63XX_CPU_6368
-# ifdef bcm63xx_get_cpu_id
-#  undef bcm63xx_get_cpu_id
-#  define bcm63xx_get_cpu_id()	__bcm63xx_get_cpu_id()
-#  define BCMCPU_RUNTIME_DETECT
-# else
-#  define bcm63xx_get_cpu_id()	BCM6368_CPU_ID
-# endif
-# define BCMCPU_IS_6368()	(bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
-#else
-# define BCMCPU_IS_6368()	(0)
+		case BCM6368_CPU_ID:
 #endif
+		break;
+	default:
+		unreachable();
+	}
 
-#ifndef bcm63xx_get_cpu_id
-#error "No CPU support configured"
-#endif
+	return cpu_id;
+}
+
+extern u16 bcm63xx_cpu_id;
+
+static inline u16 __pure bcm63xx_get_cpu_id(void)
+{
+	const u16 cpu_id = bcm63xx_cpu_id;
+
+	return __bcm63xx_get_cpu_id(cpu_id);
+}
+
+#define BCMCPU_IS_3368()	(bcm63xx_get_cpu_id() == BCM3368_CPU_ID)
+#define BCMCPU_IS_6328()	(bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
+#define BCMCPU_IS_6338()	(bcm63xx_get_cpu_id() == BCM6338_CPU_ID)
+#define BCMCPU_IS_6345()	(bcm63xx_get_cpu_id() == BCM6345_CPU_ID)
+#define BCMCPU_IS_6348()	(bcm63xx_get_cpu_id() == BCM6348_CPU_ID)
+#define BCMCPU_IS_6358()	(bcm63xx_get_cpu_id() == BCM6358_CPU_ID)
+#define BCMCPU_IS_6362()	(bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
+#define BCMCPU_IS_6368()	(bcm63xx_get_cpu_id() == BCM6368_CPU_ID)
 
 /*
  * While registers sets are (mostly) the same across 63xx CPU, base
@@ -598,55 +548,6 @@
 
 extern const unsigned long *bcm63xx_regs_base;
 
-#define __GEN_RSET_BASE(__cpu, __rset)					\
-	case RSET_## __rset :						\
-		return BCM_## __cpu ##_## __rset ##_BASE;
-
-#define __GEN_RSET(__cpu)						\
-	switch (set) {							\
-	__GEN_RSET_BASE(__cpu, DSL_LMEM)				\
-	__GEN_RSET_BASE(__cpu, PERF)					\
-	__GEN_RSET_BASE(__cpu, TIMER)					\
-	__GEN_RSET_BASE(__cpu, WDT)					\
-	__GEN_RSET_BASE(__cpu, UART0)					\
-	__GEN_RSET_BASE(__cpu, UART1)					\
-	__GEN_RSET_BASE(__cpu, GPIO)					\
-	__GEN_RSET_BASE(__cpu, SPI)					\
-	__GEN_RSET_BASE(__cpu, HSSPI)					\
-	__GEN_RSET_BASE(__cpu, UDC0)					\
-	__GEN_RSET_BASE(__cpu, OHCI0)					\
-	__GEN_RSET_BASE(__cpu, OHCI_PRIV)				\
-	__GEN_RSET_BASE(__cpu, USBH_PRIV)				\
-	__GEN_RSET_BASE(__cpu, USBD)					\
-	__GEN_RSET_BASE(__cpu, USBDMA)					\
-	__GEN_RSET_BASE(__cpu, MPI)					\
-	__GEN_RSET_BASE(__cpu, PCMCIA)					\
-	__GEN_RSET_BASE(__cpu, PCIE)					\
-	__GEN_RSET_BASE(__cpu, DSL)					\
-	__GEN_RSET_BASE(__cpu, ENET0)					\
-	__GEN_RSET_BASE(__cpu, ENET1)					\
-	__GEN_RSET_BASE(__cpu, ENETDMA)					\
-	__GEN_RSET_BASE(__cpu, ENETDMAC)				\
-	__GEN_RSET_BASE(__cpu, ENETDMAS)				\
-	__GEN_RSET_BASE(__cpu, ENETSW)					\
-	__GEN_RSET_BASE(__cpu, EHCI0)					\
-	__GEN_RSET_BASE(__cpu, SDRAM)					\
-	__GEN_RSET_BASE(__cpu, MEMC)					\
-	__GEN_RSET_BASE(__cpu, DDR)					\
-	__GEN_RSET_BASE(__cpu, M2M)					\
-	__GEN_RSET_BASE(__cpu, ATM)					\
-	__GEN_RSET_BASE(__cpu, XTM)					\
-	__GEN_RSET_BASE(__cpu, XTMDMA)					\
-	__GEN_RSET_BASE(__cpu, XTMDMAC)					\
-	__GEN_RSET_BASE(__cpu, XTMDMAS)					\
-	__GEN_RSET_BASE(__cpu, PCM)					\
-	__GEN_RSET_BASE(__cpu, PCMDMA)					\
-	__GEN_RSET_BASE(__cpu, PCMDMAC)					\
-	__GEN_RSET_BASE(__cpu, PCMDMAS)					\
-	__GEN_RSET_BASE(__cpu, RNG)					\
-	__GEN_RSET_BASE(__cpu, MISC)					\
-	}
-
 #define __GEN_CPU_REGS_TABLE(__cpu)					\
 	[RSET_DSL_LMEM]		= BCM_## __cpu ##_DSL_LMEM_BASE,	\
 	[RSET_PERF]		= BCM_## __cpu ##_PERF_BASE,		\
@@ -693,36 +594,7 @@
 
 static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	return bcm63xx_regs_base[set];
-#else
-#ifdef CONFIG_BCM63XX_CPU_3368
-	__GEN_RSET(3368)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6328
-	__GEN_RSET(6328)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6338
-	__GEN_RSET(6338)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6345
-	__GEN_RSET(6345)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6348
-	__GEN_RSET(6348)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6358
-	__GEN_RSET(6358)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6362
-	__GEN_RSET(6362)
-#endif
-#ifdef CONFIG_BCM63XX_CPU_6368
-	__GEN_RSET(6368)
-#endif
-#endif
-	/* unreached */
-	return 0;
 }
 
 /*
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
index 753953e..466fc85 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
@@ -112,55 +112,9 @@
 
 static inline unsigned long bcm63xx_enetdmacreg(enum bcm63xx_regs_enetdmac reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	extern const unsigned long *bcm63xx_regs_enetdmac;
 
 	return bcm63xx_regs_enetdmac[reg];
-#else
-#ifdef CONFIG_BCM63XX_CPU_6345
-	switch (reg) {
-	case ENETDMAC_CHANCFG:
-		return ENETDMA_6345_CHANCFG_REG;
-	case ENETDMAC_IR:
-		return ENETDMA_6345_IR_REG;
-	case ENETDMAC_IRMASK:
-		return ENETDMA_6345_IRMASK_REG;
-	case ENETDMAC_MAXBURST:
-		return ENETDMA_6345_MAXBURST_REG;
-	case ENETDMAC_BUFALLOC:
-		return ENETDMA_6345_BUFALLOC_REG;
-	case ENETDMAC_RSTART:
-		return ENETDMA_6345_RSTART_REG;
-	case ENETDMAC_FC:
-		return ENETDMA_6345_FC_REG;
-	case ENETDMAC_LEN:
-		return ENETDMA_6345_LEN_REG;
-	}
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6328) || \
-	defined(CONFIG_BCM63XX_CPU_6338) || \
-	defined(CONFIG_BCM63XX_CPU_6348) || \
-	defined(CONFIG_BCM63XX_CPU_6358) || \
-	defined(CONFIG_BCM63XX_CPU_6362) || \
-	defined(CONFIG_BCM63XX_CPU_6368)
-	switch (reg) {
-	case ENETDMAC_CHANCFG:
-		return ENETDMAC_CHANCFG_REG;
-	case ENETDMAC_IR:
-		return ENETDMAC_IR_REG;
-	case ENETDMAC_IRMASK:
-		return ENETDMAC_IRMASK_REG;
-	case ENETDMAC_MAXBURST:
-		return ENETDMAC_MAXBURST_REG;
-	case ENETDMAC_BUFALLOC:
-	case ENETDMAC_RSTART:
-	case ENETDMAC_FC:
-	case ENETDMAC_LEN:
-		return 0;
-	}
-#endif
-#endif
-	return 0;
 }
 
 
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
index c426cab..2573765 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
@@ -30,26 +30,6 @@
 	SPI_RX_DATA,
 };
 
-#define __GEN_SPI_RSET_BASE(__cpu, __rset)				\
-	case SPI_## __rset:						\
-		return SPI_## __cpu ##_## __rset;
-
-#define __GEN_SPI_RSET(__cpu)						\
-	switch (reg) {							\
-	__GEN_SPI_RSET_BASE(__cpu, CMD)					\
-	__GEN_SPI_RSET_BASE(__cpu, INT_STATUS)				\
-	__GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST)				\
-	__GEN_SPI_RSET_BASE(__cpu, INT_MASK)				\
-	__GEN_SPI_RSET_BASE(__cpu, ST)					\
-	__GEN_SPI_RSET_BASE(__cpu, CLK_CFG)				\
-	__GEN_SPI_RSET_BASE(__cpu, FILL_BYTE)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_TAIL)				\
-	__GEN_SPI_RSET_BASE(__cpu, RX_TAIL)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_CTL)				\
-	__GEN_SPI_RSET_BASE(__cpu, MSG_DATA)				\
-	__GEN_SPI_RSET_BASE(__cpu, RX_DATA)				\
-	}
-
 #define __GEN_SPI_REGS_TABLE(__cpu)					\
 	[SPI_CMD]		= SPI_## __cpu ##_CMD,			\
 	[SPI_INT_STATUS]	= SPI_## __cpu ##_INT_STATUS,		\
@@ -66,20 +46,9 @@
 
 static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
 {
-#ifdef BCMCPU_RUNTIME_DETECT
 	extern const unsigned long *bcm63xx_regs_spi;
 
 	return bcm63xx_regs_spi[reg];
-#else
-#if defined(CONFIG_BCM63XX_CPU_6338) || defined(CONFIG_BCM63XX_CPU_6348)
-	__GEN_SPI_RSET(6348)
-#endif
-#if defined(CONFIG_BCM63XX_CPU_6358) || defined(CONFIG_BCM63XX_CPU_6362) || \
-	defined(CONFIG_BCM63XX_CPU_6368)
-	__GEN_SPI_RSET(6358)
-#endif
-#endif
-	return 0;
 }
 
 #endif /* BCM63XX_DEV_SPI_H */
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index ab427f8..4794067 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -215,23 +215,23 @@
 
 /* Interrupt Mask register */
 #define PERF_IRQMASK_3368_REG		0xc
-#define PERF_IRQMASK_6328_REG		0x20
+#define PERF_IRQMASK_6328_REG(x)	(0x20 + (x) * 0x10)
 #define PERF_IRQMASK_6338_REG		0xc
 #define PERF_IRQMASK_6345_REG		0xc
 #define PERF_IRQMASK_6348_REG		0xc
-#define PERF_IRQMASK_6358_REG		0xc
-#define PERF_IRQMASK_6362_REG		0x20
-#define PERF_IRQMASK_6368_REG		0x20
+#define PERF_IRQMASK_6358_REG(x)	(0xc + (x) * 0x2c)
+#define PERF_IRQMASK_6362_REG(x)	(0x20 + (x) * 0x10)
+#define PERF_IRQMASK_6368_REG(x)	(0x20 + (x) * 0x10)
 
 /* Interrupt Status register */
 #define PERF_IRQSTAT_3368_REG		0x10
-#define PERF_IRQSTAT_6328_REG		0x28
+#define PERF_IRQSTAT_6328_REG(x)	(0x28 + (x) * 0x10)
 #define PERF_IRQSTAT_6338_REG		0x10
 #define PERF_IRQSTAT_6345_REG		0x10
 #define PERF_IRQSTAT_6348_REG		0x10
-#define PERF_IRQSTAT_6358_REG		0x10
-#define PERF_IRQSTAT_6362_REG		0x28
-#define PERF_IRQSTAT_6368_REG		0x28
+#define PERF_IRQSTAT_6358_REG(x)	(0x10 + (x) * 0x2c)
+#define PERF_IRQSTAT_6362_REG(x)	(0x28 + (x) * 0x10)
+#define PERF_IRQSTAT_6368_REG(x)	(0x28 + (x) * 0x10)
 
 /* External Interrupt Configuration register */
 #define PERF_EXTIRQ_CFG_REG_3368	0x14
diff --git a/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h b/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
index e9c408e..bc1167d 100644
--- a/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-bcm63xx/cpu-feature-overrides.h
@@ -24,7 +24,7 @@
 #define cpu_has_smartmips		0
 #define cpu_has_vtag_icache		0
 
-#if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCM63XX_CPU_6348) || defined(CONFIG_BCM63XX_CPU_6345) || defined(CONFIG_BCM63XX_CPU_6338))
+#if !defined(CONFIG_SYS_HAS_CPU_BMIPS4350)
 #define cpu_has_dc_aliases		0
 #endif
 
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 829a7ec..3388fc5 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -146,6 +146,9 @@
 
 struct loongson_system_configuration {
 	u32 nr_cpus;
+	u32 nr_nodes;
+	int cores_per_node;
+	int cores_per_package;
 	enum loongson_cpu_type cputype;
 	u64 ht_control_base;
 	u64 pci_mem_start_addr;
@@ -160,4 +163,5 @@
 
 extern struct efi_memory_map_loongson *loongson_memmap;
 extern struct loongson_system_configuration loongson_sysconf;
+extern int cpuhotplug_workaround;
 #endif
diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
new file mode 100644
index 0000000..df5fca8
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
+ */
+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
+
+/*
+ * Override macros used in arch/mips/kernel/head.S.
+ */
+	.macro	kernel_entry_setup
+#ifdef CONFIG_CPU_LOONGSON3
+	.set	push
+	.set	mips64
+	/* Set LPA on LOONGSON3 config3 */
+	mfc0	t0, $16, 3
+	or	t0, (0x1 << 7)
+	mtc0	t0, $16, 3
+	/* Set ELPA on LOONGSON3 pagegrain */
+	li	t0, (0x1 << 29)
+	mtc0	t0, $5, 1
+	_ehb
+	.set	pop
+#endif
+	.endm
+
+/*
+ * Do SMP slave processor setup.
+ */
+	.macro	smp_slave_setup
+#ifdef CONFIG_CPU_LOONGSON3
+	.set	push
+	.set	mips64
+	/* Set LPA on LOONGSON3 config3 */
+	mfc0	t0, $16, 3
+	or	t0, (0x1 << 7)
+	mtc0	t0, $16, 3
+	/* Set ELPA on LOONGSON3 pagegrain */
+	li	t0, (0x1 << 29)
+	mtc0	t0, $5, 1
+	_ehb
+	.set	pop
+#endif
+	.endm
+
+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index f3fd1eb..92bf76c 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -249,8 +249,15 @@
 #define LOONGSON_PXARB_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x68)
 #define LOONGSON_PXARB_STATUS		LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
 
-/* Chip Config */
-#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#define MAX_PACKAGES 4
+
+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */
+extern u64 loongson_chipcfg[MAX_PACKAGES];
+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id]))
+
+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */
+extern u64 loongson_freqctrl[MAX_PACKAGES];
+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id]))
 
 /* pcimap */
 
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 1b1f592..228e3784 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -24,10 +24,10 @@
 
 #endif
 
-#ifdef CONFIG_LEMOTE_MACH3A
+#ifdef CONFIG_LOONGSON_MACH3X
 
 #define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
 
-#endif /* CONFIG_LEMOTE_MACH3A */
+#endif /* CONFIG_LOONGSON_MACH3X */
 
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h
new file mode 100644
index 0000000..37c08a2
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/mmzone.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_MACH_MMZONE_H
+#define _ASM_MACH_MMZONE_H
+
+#include <boot_param.h>
+#define NODE_ADDRSPACE_SHIFT 44
+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
+
+#define pa_to_nid(addr)  (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
+
+#define LEVELS_PER_SLICE 128
+
+struct slice_data {
+	unsigned long irq_enable_mask[2];
+	int level_to_irq[LEVELS_PER_SLICE];
+};
+
+struct hub_data {
+	cpumask_t	h_cpus;
+	unsigned long slice_map;
+	unsigned long irq_alloc_mask[2];
+	struct slice_data slice[2];
+};
+
+struct node_data {
+	struct pglist_data pglist;
+	struct hub_data hub;
+	cpumask_t cpumask;
+};
+
+extern struct node_data *__node_data[];
+
+#define NODE_DATA(n)		(&__node_data[(n)]->pglist)
+#define hub_data(n)		(&__node_data[(n)]->hub)
+
+extern void setup_zero_pages(void);
+extern void __init prom_init_numa_memory(void);
+
+#endif /* _ASM_MACH_MMZONE_H */
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
new file mode 100644
index 0000000..5598ba7
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/topology.h
@@ -0,0 +1,23 @@
+#ifndef _ASM_MACH_TOPOLOGY_H
+#define _ASM_MACH_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#define cpu_to_node(cpu)	((cpu) >> 2)
+#define parent_node(node)	(node)
+#define cpumask_of_node(node)	(&__node_data[(node)]->cpumask)
+
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *);
+
+#define cpumask_of_pcibus(bus)	(cpu_online_mask)
+
+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+
+#define node_distance(from, to)	(__node_distances[(from)][(to)])
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_MACH_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/mach-malta/irq.h b/arch/mips/include/asm/mach-malta/irq.h
index 47cfe64..f2c13d2 100644
--- a/arch/mips/include/asm/mach-malta/irq.h
+++ b/arch/mips/include/asm/mach-malta/irq.h
@@ -2,6 +2,7 @@
 #define __ASM_MACH_MIPS_IRQ_H
 
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 #include_next <irq.h>
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h
index 5d154cf..d8106f7 100644
--- a/arch/mips/include/asm/mach-sead3/irq.h
+++ b/arch/mips/include/asm/mach-sead3/irq.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
+#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
 #define NR_IRQS 256
 
 
diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h
index b2048d1..5368891 100644
--- a/arch/mips/include/asm/mips-boards/bonito64.h
+++ b/arch/mips/include/asm/mips-boards/bonito64.h
@@ -414,7 +414,6 @@
 
 
 #define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)	 ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
-#define BONITO_PCIMEMBASECFG_ADDRMASK(WIN, CFG)	 ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_MASK_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 #define BONITO_PCIMEMBASECFG_ADDRTRANS(WIN, CFG) ((((CFG) & BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS) >> BONITO_PCIMEMBASECFG_MEMBASE##WIN##_TRANS_SHIFT) << BONITO_PCIMEMBASECFG_ASHIFT)
 
 #define BONITO_PCITOPHYS(WIN, ADDR, CFG)	  ( \
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 98e9754..cf3b580 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -265,6 +265,7 @@
 #define PG_XIE		(_ULCAST_(1) <<	 30)
 #define PG_ELPA		(_ULCAST_(1) <<	 29)
 #define PG_ESP		(_ULCAST_(1) <<	 28)
+#define PG_IEC		(_ULCAST_(1) <<  27)
 
 /*
  * R4x00 interrupt enable / cause bits
@@ -630,7 +631,6 @@
 #define MIPS_CONF4_MMUSIZEEXT_SHIFT	(0)
 #define MIPS_CONF4_MMUSIZEEXT	(_ULCAST_(255) << 0)
 #define MIPS_CONF4_FTLBSETS_SHIFT	(0)
-#define MIPS_CONF4_FTLBSETS_SHIFT	(0)
 #define MIPS_CONF4_FTLBSETS	(_ULCAST_(15) << MIPS_CONF4_FTLBSETS_SHIFT)
 #define MIPS_CONF4_FTLBWAYS_SHIFT	(4)
 #define MIPS_CONF4_FTLBWAYS	(_ULCAST_(15) << MIPS_CONF4_FTLBWAYS_SHIFT)
@@ -652,6 +652,7 @@
 
 #define MIPS_CONF5_NF		(_ULCAST_(1) << 0)
 #define MIPS_CONF5_UFR		(_ULCAST_(1) << 2)
+#define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA		(_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV		(_ULCAST_(1) << 29)
@@ -668,6 +669,12 @@
 #define MIPS_CONF7_IAR		(_ULCAST_(1) << 10)
 #define MIPS_CONF7_AR		(_ULCAST_(1) << 16)
 
+/* MAAR bit definitions */
+#define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
+#define MIPS_MAAR_ADDR_SHIFT	12
+#define MIPS_MAAR_S		(_ULCAST_(1) << 1)
+#define MIPS_MAAR_V		(_ULCAST_(1) << 0)
+
 /*  EntryHI bit definition */
 #define MIPS_ENTRYHI_EHINV	(_ULCAST_(1) << 10)
 
@@ -706,6 +713,37 @@
 #define MIPS_SEGCFG_MK		_ULCAST_(1)
 #define MIPS_SEGCFG_UK		_ULCAST_(0)
 
+#define MIPS_PWFIELD_GDI_SHIFT	24
+#define MIPS_PWFIELD_GDI_MASK	0x3f000000
+#define MIPS_PWFIELD_UDI_SHIFT	18
+#define MIPS_PWFIELD_UDI_MASK	0x00fc0000
+#define MIPS_PWFIELD_MDI_SHIFT	12
+#define MIPS_PWFIELD_MDI_MASK	0x0003f000
+#define MIPS_PWFIELD_PTI_SHIFT	6
+#define MIPS_PWFIELD_PTI_MASK	0x00000fc0
+#define MIPS_PWFIELD_PTEI_SHIFT	0
+#define MIPS_PWFIELD_PTEI_MASK	0x0000003f
+
+#define MIPS_PWSIZE_GDW_SHIFT	24
+#define MIPS_PWSIZE_GDW_MASK	0x3f000000
+#define MIPS_PWSIZE_UDW_SHIFT	18
+#define MIPS_PWSIZE_UDW_MASK	0x00fc0000
+#define MIPS_PWSIZE_MDW_SHIFT	12
+#define MIPS_PWSIZE_MDW_MASK	0x0003f000
+#define MIPS_PWSIZE_PTW_SHIFT	6
+#define MIPS_PWSIZE_PTW_MASK	0x00000fc0
+#define MIPS_PWSIZE_PTEW_SHIFT	0
+#define MIPS_PWSIZE_PTEW_MASK	0x0000003f
+
+#define MIPS_PWCTL_PWEN_SHIFT	31
+#define MIPS_PWCTL_PWEN_MASK	0x80000000
+#define MIPS_PWCTL_DPH_SHIFT	7
+#define MIPS_PWCTL_DPH_MASK	0x00000080
+#define MIPS_PWCTL_HUGEPG_SHIFT	6
+#define MIPS_PWCTL_HUGEPG_MASK	0x00000060
+#define MIPS_PWCTL_PSN_SHIFT	0
+#define MIPS_PWCTL_PSN_MASK	0x0000003f
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -1044,6 +1082,11 @@
 #define write_c0_config6(val)	__write_32bit_c0_register($16, 6, val)
 #define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
+#define read_c0_maar()		__read_ulong_c0_register($17, 1)
+#define write_c0_maar(val)	__write_ulong_c0_register($17, 1, val)
+#define read_c0_maari()		__read_32bit_c0_register($17, 2)
+#define write_c0_maari(val)	__write_32bit_c0_register($17, 2, val)
+
 /*
  * The WatchLo register.  There may be up to 8 of them.
  */
@@ -1201,6 +1244,19 @@
 #define read_c0_segctl2()	__read_32bit_c0_register($5, 4)
 #define write_c0_segctl2(val)	__write_32bit_c0_register($5, 4, val)
 
+/* Hardware Page Table Walker */
+#define read_c0_pwbase()	__read_ulong_c0_register($5, 5)
+#define write_c0_pwbase(val)	__write_ulong_c0_register($5, 5, val)
+
+#define read_c0_pwfield()	__read_ulong_c0_register($5, 6)
+#define write_c0_pwfield(val)	__write_ulong_c0_register($5, 6, val)
+
+#define read_c0_pwsize()	__read_ulong_c0_register($5, 7)
+#define write_c0_pwsize(val)	__write_ulong_c0_register($5, 7, val)
+
+#define read_c0_pwctl()		__read_32bit_c0_register($6, 6)
+#define write_c0_pwctl(val)	__write_32bit_c0_register($6, 6, val)
+
 /* Cavium OCTEON (cnMIPS) */
 #define read_c0_cvmcount()	__read_ulong_c0_register($9, 6)
 #define write_c0_cvmcount(val)	__write_ulong_c0_register($9, 6, val)
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 2e373da..2f82568 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -20,10 +20,20 @@
 #include <asm/tlbflush.h>
 #include <asm-generic/mm_hooks.h>
 
+#define htw_set_pwbase(pgd)						\
+do {									\
+	if (cpu_has_htw) {						\
+		write_c0_pwbase(pgd);					\
+		back_to_back_c0_hazard();				\
+		htw_reset();						\
+	}								\
+} while (0)
+
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
 do {									\
 	extern void tlbmiss_handler_setup_pgd(unsigned long);		\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd));		\
+	htw_set_pwbase((unsigned long)pgd);				\
 } while (0)
 
 #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index 538f6d4..af5638b 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -12,8 +12,11 @@
 
 #include <asm/mipsregs.h>
 
+#ifndef __ASSEMBLY__
+
 extern void _save_msa(struct task_struct *);
 extern void _restore_msa(struct task_struct *);
+extern void _init_msa_upper(void);
 
 static inline void enable_msa(void)
 {
@@ -112,10 +115,10 @@
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
 	"	.insn\n"					\
-	"	.word	#CFC_MSA_INSN | (" #cs " << 11)\n"	\
+	"	.word	%1 | (" #cs " << 11)\n"			\
 	"	move	%0, $1\n"				\
 	"	.set	pop\n"					\
-	: "=r"(reg));						\
+	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
 	return reg;						\
 }								\
 								\
@@ -126,22 +129,13 @@
 	"	.set	noat\n"					\
 	"	move	$1, %0\n"				\
 	"	.insn\n"					\
-	"	.word	#CTC_MSA_INSN | (" #cs " << 6)\n"	\
+	"	.word	%1 | (" #cs " << 6)\n"			\
 	"	.set	pop\n"					\
-	: : "r"(val));						\
+	: : "r"(val), "i"(CTC_MSA_INSN));			\
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
 
-#define MSA_IR		0
-#define MSA_CSR		1
-#define MSA_ACCESS	2
-#define MSA_SAVE	3
-#define MSA_MODIFY	4
-#define MSA_REQUEST	5
-#define MSA_MAP		6
-#define MSA_UNMAP	7
-
 __BUILD_MSA_CTL_REG(ir, 0)
 __BUILD_MSA_CTL_REG(csr, 1)
 __BUILD_MSA_CTL_REG(access, 2)
@@ -151,6 +145,17 @@
 __BUILD_MSA_CTL_REG(map, 6)
 __BUILD_MSA_CTL_REG(unmap, 7)
 
+#endif /* !__ASSEMBLY__ */
+
+#define MSA_IR		0
+#define MSA_CSR		1
+#define MSA_ACCESS	2
+#define MSA_SAVE	3
+#define MSA_MODIFY	4
+#define MSA_REQUEST	5
+#define MSA_MAP		6
+#define MSA_UNMAP	7
+
 /* MSA Implementation Register (MSAIR) */
 #define MSA_IR_REVB		0
 #define MSA_IR_REVF		(_ULCAST_(0xff) << MSA_IR_REVB)
diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
index 7b7818d..2298199 100644
--- a/arch/mips/include/asm/octeon/cvmx-bootinfo.h
+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
@@ -228,6 +228,7 @@
 	 */
 	CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
 	CVMX_BOARD_TYPE_UBNT_E100 = 20002,
+	CVMX_BOARD_TYPE_CUST_DSR1000N = 20006,
 	CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
 
 	/* The remaining range is reserved for future use. */
@@ -327,6 +328,7 @@
 		    /* Customer private range */
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_UBNT_E100)
+		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DSR1000N)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
 	}
 	return "Unsupported Board";
diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/pgtable-32.h
index b4204c1..cd7d606 100644
--- a/arch/mips/include/asm/pgtable-32.h
+++ b/arch/mips/include/asm/pgtable-32.h
@@ -18,6 +18,18 @@
 
 #include <asm-generic/pgtable-nopmd.h>
 
+extern int temp_tlb_entry __cpuinitdata;
+
+/*
+ * - add_temporary_entry() add a temporary TLB entry. We use TLB entries
+ *	starting at the top and working down. This is for populating the
+ *	TLB before trap_init() puts the TLB miss handler in place. It
+ *	should be used only for entries matching the actual page tables,
+ *	to prevent inconsistencies.
+ */
+extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+			       unsigned long entryhi, unsigned long pagemask);
+
 /*
  * Basically we have the same two-level (which is the logical three level
  * Linux page table layout folded) page tables as the i386.  Some day
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 539ddd1..027c74d 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -97,6 +97,31 @@
 
 #define pmd_page_vaddr(pmd)	pmd_val(pmd)
 
+#define htw_stop()							\
+do {									\
+	if (cpu_has_htw)						\
+		write_c0_pwctl(read_c0_pwctl() &			\
+			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));		\
+} while(0)
+
+#define htw_start()							\
+do {									\
+	if (cpu_has_htw)						\
+		write_c0_pwctl(read_c0_pwctl() |			\
+			       (1 << MIPS_PWCTL_PWEN_SHIFT));		\
+} while(0)
+
+
+#define htw_reset()							\
+do {									\
+	if (cpu_has_htw) {						\
+		htw_stop();						\
+		back_to_back_c0_hazard();				\
+		htw_start();						\
+		back_to_back_c0_hazard();				\
+	}								\
+} while(0)
+
 #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
 
 #define pte_none(pte)		(!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
@@ -131,6 +156,7 @@
 		null.pte_low = null.pte_high = _PAGE_GLOBAL;
 
 	set_pte_at(mm, addr, ptep, null);
+	htw_reset();
 }
 #else
 
@@ -168,6 +194,7 @@
 	else
 #endif
 		set_pte_at(mm, addr, ptep, __pte(0));
+	htw_reset();
 }
 #endif
 
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index ad70cba..5733fab 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -238,7 +238,13 @@
 	unsigned long seg;
 } mm_segment_t;
 
-#define ARCH_MIN_TASKALIGN	8
+#ifdef CONFIG_CPU_HAS_MSA
+# define ARCH_MIN_TASKALIGN	16
+# define FPU_ALIGN		__aligned(16)
+#else
+# define ARCH_MIN_TASKALIGN	8
+# define FPU_ALIGN
+#endif
 
 struct mips_abi;
 
@@ -255,7 +261,7 @@
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	struct mips_fpu_struct fpu;
+	struct mips_fpu_struct fpu FPU_ALIGN;
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* Emulated instruction count */
 	unsigned long emulated_fp;
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 7e6e682a..fc783f8 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -23,7 +23,7 @@
 struct pt_regs {
 #ifdef CONFIG_32BIT
 	/* Pad bytes for argument save space on the stack. */
-	unsigned long pad0[6];
+	unsigned long pad0[8];
 #endif
 
 	/* Saved main processor registers. */
@@ -47,8 +47,10 @@
 
 struct task_struct;
 
-extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
-extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
+extern int ptrace_getregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
+extern int ptrace_setregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
 
 extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
 extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index 910e71a..84dc7e2 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -1,128 +1 @@
-/*
- * Various register offset definitions for debuggers, core file
- * examiners and whatnot.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1999 Ralf Baechle
- * Copyright (C) 1995, 1999 Silicon Graphics
- */
-#ifndef __ASM_MIPS_REG_H
-#define __ASM_MIPS_REG_H
-
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			6
-#define EF_R1			7
-#define EF_R2			8
-#define EF_R3			9
-#define EF_R4			10
-#define EF_R5			11
-#define EF_R6			12
-#define EF_R7			13
-#define EF_R8			14
-#define EF_R9			15
-#define EF_R10			16
-#define EF_R11			17
-#define EF_R12			18
-#define EF_R13			19
-#define EF_R14			20
-#define EF_R15			21
-#define EF_R16			22
-#define EF_R17			23
-#define EF_R18			24
-#define EF_R19			25
-#define EF_R20			26
-#define EF_R21			27
-#define EF_R22			28
-#define EF_R23			29
-#define EF_R24			30
-#define EF_R25			31
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26			32
-#define EF_R27			33
-
-#define EF_R28			34
-#define EF_R29			35
-#define EF_R30			36
-#define EF_R31			37
-
-/*
- * Saved special registers
- */
-#define EF_LO			38
-#define EF_HI			39
-
-#define EF_CP0_EPC		40
-#define EF_CP0_BADVADDR		41
-#define EF_CP0_STATUS		42
-#define EF_CP0_CAUSE		43
-#define EF_UNUSED0		44
-
-#define EF_SIZE			180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			 0
-#define EF_R1			 1
-#define EF_R2			 2
-#define EF_R3			 3
-#define EF_R4			 4
-#define EF_R5			 5
-#define EF_R6			 6
-#define EF_R7			 7
-#define EF_R8			 8
-#define EF_R9			 9
-#define EF_R10			10
-#define EF_R11			11
-#define EF_R12			12
-#define EF_R13			13
-#define EF_R14			14
-#define EF_R15			15
-#define EF_R16			16
-#define EF_R17			17
-#define EF_R18			18
-#define EF_R19			19
-#define EF_R20			20
-#define EF_R21			21
-#define EF_R22			22
-#define EF_R23			23
-#define EF_R24			24
-#define EF_R25			25
-
-/*
- * k0/k1 unsaved
- */
-#define EF_R26			26
-#define EF_R27			27
-
-
-#define EF_R28			28
-#define EF_R29			29
-#define EF_R30			30
-#define EF_R31			31
-
-/*
- * Saved special registers
- */
-#define EF_LO			32
-#define EF_HI			33
-
-#define EF_CP0_EPC		34
-#define EF_CP0_BADVADDR		35
-#define EF_CP0_STATUS		36
-#define EF_CP0_CAUSE		37
-
-#define EF_SIZE			304	/* size in bytes */
-
-#endif /* CONFIG_64BIT */
-
-#endif /* __ASM_MIPS_REG_H */
+#include <uapi/asm/reg.h>
diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h
index a06a08a..326c16e 100644
--- a/arch/mips/include/asm/smp-cps.h
+++ b/arch/mips/include/asm/smp-cps.h
@@ -31,11 +31,19 @@
 
 extern struct vpe_boot_config *mips_cps_boot_vpes(void);
 
-extern bool mips_cps_smp_in_use(void);
-
 extern void mips_cps_pm_save(void);
 extern void mips_cps_pm_restore(void);
 
+#ifdef CONFIG_MIPS_CPS
+
+extern bool mips_cps_smp_in_use(void);
+
+#else /* !CONFIG_MIPS_CPS */
+
+static inline bool mips_cps_smp_in_use(void) { return false; }
+
+#endif /* !CONFIG_MIPS_CPS */
+
 #else /* __ASSEMBLY__ */
 
 .extern mips_cps_bootcfg;
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index b037334..1e0f20a 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -22,6 +22,7 @@
 
 extern int smp_num_siblings;
 extern cpumask_t cpu_sibling_map[];
+extern cpumask_t cpu_core_map[];
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
@@ -36,6 +37,11 @@
 
 #define NO_PROC_ID	(-1)
 
+#define topology_physical_package_id(cpu)	(cpu_data[cpu].package)
+#define topology_core_id(cpu)			(cpu_data[cpu].core)
+#define topology_core_cpumask(cpu)		(&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu)		(&cpu_sibling_map[cpu])
+
 #define SMP_RESCHEDULE_YOURSELF 0x1	/* XXX braindead */
 #define SMP_CALL_FUNCTION	0x2
 /* Octeon - Tell another core to flush its icache */
diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
index d2da53c..b1071c1 100644
--- a/arch/mips/include/asm/sparsemem.h
+++ b/arch/mips/include/asm/sparsemem.h
@@ -11,7 +11,7 @@
 #else
 # define SECTION_SIZE_BITS	28
 #endif
-#define MAX_PHYSMEM_BITS	35
+#define MAX_PHYSMEM_BITS	48
 
 #endif /* CONFIG_SPARSEMEM */
 #endif /* _MIPS_SPARSEMEM_H */
diff --git a/arch/mips/include/asm/user.h b/arch/mips/include/asm/user.h
deleted file mode 100644
index 6bad61b..0000000
--- a/arch/mips/include/asm/user.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
- */
-#ifndef _ASM_USER_H
-#define _ASM_USER_H
-
-#include <asm/page.h>
-#include <asm/reg.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the irix-core).  The file
- * contents are as follows:
- *
- *  upage: 1 page consisting of a user struct that tells gdb
- *	what is present in the file.  Directly after this is a
- *	copy of the task_struct, which is currently not used by gdb,
- *	but it may come in handy at some point.	 All of the registers
- *	are stored as part of the upage.  The upage should always be
- *	only one page long.
- *  data: The data segment follows next.  We use current->end_text to
- *	current->brk to pick up all of the user variables, plus any memory
- *	that may have been sbrk'ed.  No attempt is made to determine if a
- *	page is demand-zero or if a page is totally unused, we just cover
- *	the entire range.  All of the addresses are rounded in such a way
- *	that an integral number of pages is written.
- *  stack: We need the stack information in order to get a meaningful
- *	backtrace.  We need to write the data from usp to
- *	current->start_stack, so we round each of these in order to be able
- *	to write an integer number of pages.
- */
-struct user {
-	unsigned long	regs[EF_SIZE /		/* integer and fp regs */
-			sizeof(unsigned long) + 64];
-	size_t		u_tsize;		/* text size (pages) */
-	size_t		u_dsize;		/* data size (pages) */
-	size_t		u_ssize;		/* stack size (pages) */
-	unsigned long	start_code;		/* text starting address */
-	unsigned long	start_data;		/* data starting address */
-	unsigned long	start_stack;		/* stack starting address */
-	long int	signal;			/* signal causing core dump */
-	unsigned long	u_ar0;			/* help gdb find registers */
-	unsigned long	magic;			/* identifies a core file */
-	char		u_comm[32];		/* user command name */
-};
-
-#define NBPG			PAGE_SIZE
-#define UPAGES			1
-#define HOST_TEXT_START_ADDR	(u.start_code)
-#define HOST_DATA_START_ADDR	(u.start_data)
-#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _ASM_USER_H */
diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
index b26f7e3..bbcfb8b 100644
--- a/arch/mips/include/uapi/asm/ptrace.h
+++ b/arch/mips/include/uapi/asm/ptrace.h
@@ -22,24 +22,27 @@
 #define DSP_CONTROL	77
 #define ACX		78
 
-#ifndef __KERNEL__
 /*
- * This struct defines the way the registers are stored on the stack during a
- * system call/exception. As usual the registers k0/k1 aren't being saved.
+ * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
+ * format is the same for both 32- and 64-bit processes. Registers for 32-bit
+ * processes are sign extended.
  */
+#ifdef __KERNEL__
+struct user_pt_regs {
+#else
 struct pt_regs {
+#endif
 	/* Saved main processor registers. */
-	unsigned long regs[32];
+	__u64 regs[32];
 
 	/* Saved special registers. */
-	unsigned long cp0_status;
-	unsigned long hi;
-	unsigned long lo;
-	unsigned long cp0_badvaddr;
-	unsigned long cp0_cause;
-	unsigned long cp0_epc;
+	__u64 lo;
+	__u64 hi;
+	__u64 cp0_epc;
+	__u64 cp0_badvaddr;
+	__u64 cp0_status;
+	__u64 cp0_cause;
 } __attribute__ ((aligned (8)));
-#endif /* __KERNEL__ */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS		12
diff --git a/arch/mips/include/uapi/asm/reg.h b/arch/mips/include/uapi/asm/reg.h
new file mode 100644
index 0000000..081e377
--- /dev/null
+++ b/arch/mips/include/uapi/asm/reg.h
@@ -0,0 +1,206 @@
+/*
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999 Silicon Graphics
+ */
+#ifndef __UAPI_ASM_MIPS_REG_H
+#define __UAPI_ASM_MIPS_REG_H
+
+#define MIPS32_EF_R0		6
+#define MIPS32_EF_R1		7
+#define MIPS32_EF_R2		8
+#define MIPS32_EF_R3		9
+#define MIPS32_EF_R4		10
+#define MIPS32_EF_R5		11
+#define MIPS32_EF_R6		12
+#define MIPS32_EF_R7		13
+#define MIPS32_EF_R8		14
+#define MIPS32_EF_R9		15
+#define MIPS32_EF_R10		16
+#define MIPS32_EF_R11		17
+#define MIPS32_EF_R12		18
+#define MIPS32_EF_R13		19
+#define MIPS32_EF_R14		20
+#define MIPS32_EF_R15		21
+#define MIPS32_EF_R16		22
+#define MIPS32_EF_R17		23
+#define MIPS32_EF_R18		24
+#define MIPS32_EF_R19		25
+#define MIPS32_EF_R20		26
+#define MIPS32_EF_R21		27
+#define MIPS32_EF_R22		28
+#define MIPS32_EF_R23		29
+#define MIPS32_EF_R24		30
+#define MIPS32_EF_R25		31
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS32_EF_R26		32
+#define MIPS32_EF_R27		33
+
+#define MIPS32_EF_R28		34
+#define MIPS32_EF_R29		35
+#define MIPS32_EF_R30		36
+#define MIPS32_EF_R31		37
+
+/*
+ * Saved special registers
+ */
+#define MIPS32_EF_LO		38
+#define MIPS32_EF_HI		39
+
+#define MIPS32_EF_CP0_EPC	40
+#define MIPS32_EF_CP0_BADVADDR	41
+#define MIPS32_EF_CP0_STATUS	42
+#define MIPS32_EF_CP0_CAUSE	43
+#define MIPS32_EF_UNUSED0	44
+
+#define MIPS32_EF_SIZE		180
+
+#define MIPS64_EF_R0		0
+#define MIPS64_EF_R1		1
+#define MIPS64_EF_R2		2
+#define MIPS64_EF_R3		3
+#define MIPS64_EF_R4		4
+#define MIPS64_EF_R5		5
+#define MIPS64_EF_R6		6
+#define MIPS64_EF_R7		7
+#define MIPS64_EF_R8		8
+#define MIPS64_EF_R9		9
+#define MIPS64_EF_R10		10
+#define MIPS64_EF_R11		11
+#define MIPS64_EF_R12		12
+#define MIPS64_EF_R13		13
+#define MIPS64_EF_R14		14
+#define MIPS64_EF_R15		15
+#define MIPS64_EF_R16		16
+#define MIPS64_EF_R17		17
+#define MIPS64_EF_R18		18
+#define MIPS64_EF_R19		19
+#define MIPS64_EF_R20		20
+#define MIPS64_EF_R21		21
+#define MIPS64_EF_R22		22
+#define MIPS64_EF_R23		23
+#define MIPS64_EF_R24		24
+#define MIPS64_EF_R25		25
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS64_EF_R26		26
+#define MIPS64_EF_R27		27
+
+
+#define MIPS64_EF_R28		28
+#define MIPS64_EF_R29		29
+#define MIPS64_EF_R30		30
+#define MIPS64_EF_R31		31
+
+/*
+ * Saved special registers
+ */
+#define MIPS64_EF_LO		32
+#define MIPS64_EF_HI		33
+
+#define MIPS64_EF_CP0_EPC	34
+#define MIPS64_EF_CP0_BADVADDR	35
+#define MIPS64_EF_CP0_STATUS	36
+#define MIPS64_EF_CP0_CAUSE	37
+
+#define MIPS64_EF_SIZE		304	/* size in bytes */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+#define EF_R0			MIPS32_EF_R0
+#define EF_R1			MIPS32_EF_R1
+#define EF_R2			MIPS32_EF_R2
+#define EF_R3			MIPS32_EF_R3
+#define EF_R4			MIPS32_EF_R4
+#define EF_R5			MIPS32_EF_R5
+#define EF_R6			MIPS32_EF_R6
+#define EF_R7			MIPS32_EF_R7
+#define EF_R8			MIPS32_EF_R8
+#define EF_R9			MIPS32_EF_R9
+#define EF_R10			MIPS32_EF_R10
+#define EF_R11			MIPS32_EF_R11
+#define EF_R12			MIPS32_EF_R12
+#define EF_R13			MIPS32_EF_R13
+#define EF_R14			MIPS32_EF_R14
+#define EF_R15			MIPS32_EF_R15
+#define EF_R16			MIPS32_EF_R16
+#define EF_R17			MIPS32_EF_R17
+#define EF_R18			MIPS32_EF_R18
+#define EF_R19			MIPS32_EF_R19
+#define EF_R20			MIPS32_EF_R20
+#define EF_R21			MIPS32_EF_R21
+#define EF_R22			MIPS32_EF_R22
+#define EF_R23			MIPS32_EF_R23
+#define EF_R24			MIPS32_EF_R24
+#define EF_R25			MIPS32_EF_R25
+#define EF_R26			MIPS32_EF_R26
+#define EF_R27			MIPS32_EF_R27
+#define EF_R28			MIPS32_EF_R28
+#define EF_R29			MIPS32_EF_R29
+#define EF_R30			MIPS32_EF_R30
+#define EF_R31			MIPS32_EF_R31
+#define EF_LO			MIPS32_EF_LO
+#define EF_HI			MIPS32_EF_HI
+#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0		MIPS32_EF_UNUSED0
+#define EF_SIZE			MIPS32_EF_SIZE
+
+#elif _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+
+#define EF_R0			MIPS64_EF_R0
+#define EF_R1			MIPS64_EF_R1
+#define EF_R2			MIPS64_EF_R2
+#define EF_R3			MIPS64_EF_R3
+#define EF_R4			MIPS64_EF_R4
+#define EF_R5			MIPS64_EF_R5
+#define EF_R6			MIPS64_EF_R6
+#define EF_R7			MIPS64_EF_R7
+#define EF_R8			MIPS64_EF_R8
+#define EF_R9			MIPS64_EF_R9
+#define EF_R10			MIPS64_EF_R10
+#define EF_R11			MIPS64_EF_R11
+#define EF_R12			MIPS64_EF_R12
+#define EF_R13			MIPS64_EF_R13
+#define EF_R14			MIPS64_EF_R14
+#define EF_R15			MIPS64_EF_R15
+#define EF_R16			MIPS64_EF_R16
+#define EF_R17			MIPS64_EF_R17
+#define EF_R18			MIPS64_EF_R18
+#define EF_R19			MIPS64_EF_R19
+#define EF_R20			MIPS64_EF_R20
+#define EF_R21			MIPS64_EF_R21
+#define EF_R22			MIPS64_EF_R22
+#define EF_R23			MIPS64_EF_R23
+#define EF_R24			MIPS64_EF_R24
+#define EF_R25			MIPS64_EF_R25
+#define EF_R26			MIPS64_EF_R26
+#define EF_R27			MIPS64_EF_R27
+#define EF_R28			MIPS64_EF_R28
+#define EF_R29			MIPS64_EF_R29
+#define EF_R30			MIPS64_EF_R30
+#define EF_R31			MIPS64_EF_R31
+#define EF_LO			MIPS64_EF_LO
+#define EF_HI			MIPS64_EF_HI
+#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
+#define EF_SIZE			MIPS64_EF_SIZE
+
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#endif /* __UAPI_ASM_MIPS_REG_H */
diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c
index a8acdef..325422d0 100644
--- a/arch/mips/jz4740/clock-debugfs.c
+++ b/arch/mips/jz4740/clock-debugfs.c
@@ -87,8 +87,7 @@
 /* TODO: Locking */
 void jz4740_clock_debugfs_update_parent(struct clk *clk)
 {
-	if (clk->debugfs_parent_entry)
-		debugfs_remove(clk->debugfs_parent_entry);
+	debugfs_remove(clk->debugfs_parent_entry);
 
 	if (clk->parent) {
 		char parent_path[100];
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 4bb5107..b1d84bd 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -234,6 +234,7 @@
 	       thread.fpu.fpr[31].val64[FPR_IDX(64, 0)]);
 
 	OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+	OFFSET(THREAD_MSA_CSR, task_struct, thread.fpu.msacsr);
 	BLANK();
 }
 
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 7faf5f2..9287678 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -72,22 +72,6 @@
 
 #include <asm/processor.h>
 
-/*
- * When this file is selected, we are definitely running a 64bit kernel.
- * So using the right regs define in asm/reg.h
- */
-#define WANT_COMPAT_REG_H
-
-/* These MUST be defined before elf.h gets included */
-extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)				\
-({									\
-	int __res = 1;							\
-	elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));		\
-	__res;								\
-})
-
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -145,28 +129,6 @@
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < EF_R0; i++)
-		grp[i] = 0;
-	grp[EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
-	grp[EF_R26] = 0;
-	grp[EF_R27] = 0;
-	grp[EF_LO] = (elf_greg_t) regs->lo;
-	grp[EF_HI] = (elf_greg_t) regs->hi;
-	grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-	grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-	grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-	grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
-	grp[EF_UNUSED0] = 0;
-#endif
-}
-
 MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
 MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index d74f957..e34b10b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -54,6 +54,20 @@
 
 __setup("nodsp", dsp_disable);
 
+static int mips_htw_disabled;
+
+static int __init htw_disable(char *s)
+{
+	mips_htw_disabled = 1;
+	cpu_data[0].options &= ~MIPS_CPU_HTW;
+	write_c0_pwctl(read_c0_pwctl() &
+		       ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+
+	return 1;
+}
+
+__setup("nohtw", htw_disable);
+
 static inline void check_errata(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -130,14 +144,13 @@
 
 static inline unsigned long cpu_get_msa_id(void)
 {
-	unsigned long status, conf5, msa_id;
+	unsigned long status, msa_id;
 
 	status = read_c0_status();
 	__enable_fpu(FPU_64BIT);
-	conf5 = read_c0_config5();
 	enable_msa();
 	msa_id = read_msa_ir();
-	write_c0_config5(conf5);
+	disable_msa();
 	write_c0_status(status);
 	return msa_id;
 }
@@ -321,6 +334,9 @@
 		c->options |= MIPS_CPU_SEGMENTS;
 	if (config3 & MIPS_CONF3_MSA)
 		c->ases |= MIPS_ASE_MSA;
+	/* Only tested on 32-bit cores */
+	if ((config3 & MIPS_CONF3_PW) && config_enabled(CONFIG_32BIT))
+		c->options |= MIPS_CPU_HTW;
 
 	return config3 & MIPS_CONF_M;
 }
@@ -389,6 +405,8 @@
 
 	if (config5 & MIPS_CONF5_EVA)
 		c->options |= MIPS_CPU_EVA;
+	if (config5 & MIPS_CONF5_MRP)
+		c->options |= MIPS_CPU_MAAR;
 
 	return config5 & MIPS_CONF_M;
 }
@@ -421,6 +439,15 @@
 
 	mips_probe_watch_registers(c);
 
+	if (cpu_has_rixi) {
+		/* Enable the RIXI exceptions */
+		write_c0_pagegrain(read_c0_pagegrain() | PG_IEC);
+		back_to_back_c0_hazard();
+		/* Verify the IEC bit is set */
+		if (read_c0_pagegrain() & PG_IEC)
+			c->options |= MIPS_CPU_RIXIEX;
+	}
+
 #ifndef CONFIG_MIPS_CPS
 	if (cpu_has_mips_r2) {
 		c->core = get_ebase_cpunum();
@@ -740,6 +767,12 @@
 			__cpu_name[cpu] = "ICT Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
 			break;
+		case PRID_REV_LOONGSON3B_R1:
+		case PRID_REV_LOONGSON3B_R2:
+			c->cputype = CPU_LOONGSON3;
+			__cpu_name[cpu] = "ICT Loongson-3";
+			set_elf_platform(cpu, "loongson3b");
+			break;
 		}
 
 		set_isa(c, MIPS_CPU_ISA_III);
@@ -1187,6 +1220,12 @@
 	if (mips_dsp_disabled)
 		c->ases &= ~(MIPS_ASE_DSP | MIPS_ASE_DSP2P);
 
+	if (mips_htw_disabled) {
+		c->options &= ~MIPS_CPU_HTW;
+		write_c0_pwctl(read_c0_pwctl() &
+			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));
+	}
+
 	if (c->options & MIPS_CPU_FPU) {
 		c->fpu_id = cpu_get_fpu_id();
 
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index d5e59b8..9e9d8b9 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -28,6 +28,18 @@
 /* The index into this array is the vector # of the interrupt. */
 struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
 
+struct gic_pcpu_mask {
+	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
+};
+
+struct gic_pending_regs {
+	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
+};
+
+struct gic_intrmask_regs {
+	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
+};
+
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static struct gic_pending_regs pending_regs[NR_CPUS];
 static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
@@ -177,7 +189,7 @@
 		return 0;
 }
 
-unsigned int gic_get_int(void)
+void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
 {
 	unsigned int i;
 	unsigned long *pending, *intrmask, *pcpu_mask;
@@ -202,8 +214,17 @@
 
 	bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
 	bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
+	bitmap_and(dst, src, pending, GIC_NUM_INTRS);
+}
 
-	return find_first_bit(pending, GIC_NUM_INTRS);
+unsigned int gic_get_int(void)
+{
+	DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);
+
+	bitmap_fill(interrupts, GIC_NUM_INTRS);
+	gic_get_int_mask(interrupts, interrupts);
+
+	return find_first_bit(interrupts, GIC_NUM_INTRS);
 }
 
 static void gic_mask_irq(struct irq_data *d)
@@ -301,9 +322,10 @@
 
 	/* Init Intr Masks */
 	GIC_CLR_INTR_MASK(intr);
+
 	/* Initialise per-cpu Interrupt software masks */
-	if (flags & GIC_FLAG_IPI)
-		set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+	set_bit(intr, pcpu_masks[cpu].pcpu_mask);
+
 	if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
 		GIC_SET_INTR_MASK(intr);
 	if (trigtype == GIC_TRIG_EDGE)
@@ -342,8 +364,6 @@
 		cpu = intrmap[i].cpunum;
 		if (cpu == GIC_UNUSED)
 			continue;
-		if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
-			continue;
 		gic_setup_intr(i,
 			intrmap[i].cpunum,
 			intrmap[i].pin + pin_offset,
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 4f2d9de..14bf74b 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1386,6 +1386,9 @@
 /* proAptiv */
 #define IS_BOTH_COUNTERS_PROAPTIV_EVENT(b)				\
 	((b) == 0 || (b) == 1)
+/* P5600 */
+#define IS_BOTH_COUNTERS_P5600_EVENT(b)					\
+	((b) == 0 || (b) == 1)
 
 /* 1004K */
 #define IS_BOTH_COUNTERS_1004K_EVENT(b)					\
@@ -1420,20 +1423,23 @@
 
 
 /*
- * User can use 0-255 raw events, where 0-127 for the events of even
- * counters, and 128-255 for odd counters. Note that bit 7 is used to
- * indicate the parity. So, for example, when user wants to take the
- * Event Num of 15 for odd counters (by referring to the user manual),
- * then 128 needs to be added to 15 as the input for the event config,
- * i.e., 143 (0x8F) to be used.
+ * For most cores the user can use 0-255 raw events, where 0-127 for the events
+ * of even counters, and 128-255 for odd counters. Note that bit 7 is used to
+ * indicate the even/odd bank selector. So, for example, when user wants to take
+ * the Event Num of 15 for odd counters (by referring to the user manual), then
+ * 128 needs to be added to 15 as the input for the event config, i.e., 143 (0x8F)
+ * to be used.
+ *
+ * Some newer cores have even more events, in which case the user can use raw
+ * events 0-511, where 0-255 are for the events of even counters, and 256-511
+ * are for odd counters, so bit 8 is used to indicate the even/odd bank selector.
  */
 static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
 {
+	/* currently most cores have 7-bit event numbers */
 	unsigned int raw_id = config & 0xff;
 	unsigned int base_id = raw_id & 0x7f;
 
-	raw_event.event_id = base_id;
-
 	switch (current_cpu_type()) {
 	case CPU_24K:
 		if (IS_BOTH_COUNTERS_24K_EVENT(base_id))
@@ -1485,6 +1491,19 @@
 		raw_event.range = P;
 #endif
 		break;
+	case CPU_P5600:
+		/* 8-bit event numbers */
+		raw_id = config & 0x1ff;
+		base_id = raw_id & 0xff;
+		if (IS_BOTH_COUNTERS_P5600_EVENT(base_id))
+			raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+		else
+			raw_event.cntr_mask =
+				raw_id > 255 ? CNTR_ODD : CNTR_EVEN;
+#ifdef CONFIG_MIPS_MT_SMP
+		raw_event.range = P;
+#endif
+		break;
 	case CPU_1004K:
 		if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
 			raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
@@ -1523,6 +1542,8 @@
 				raw_id > 127 ? CNTR_ODD : CNTR_EVEN;
 	}
 
+	raw_event.event_id = base_id;
+
 	return &raw_event;
 }
 
@@ -1633,6 +1654,11 @@
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
+	case CPU_P5600:
+		mipspmu.name = "mips/P5600";
+		mipspmu.general_event_map = &mipsxxcore_event_map2;
+		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
+		break;
 	case CPU_1004K:
 		mipspmu.name = "mips/1004K";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index c4c2069..0614717 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -149,8 +149,12 @@
 
 	/* Setup the VPE to run mips_cps_pm_restore when started again */
 	if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+		/* Power gating relies upon CPS SMP */
+		if (!mips_cps_smp_in_use())
+			return -EINVAL;
+
 		core_cfg = &mips_cps_core_bootcfg[core];
-		vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id];
+		vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(&current_cpu_data)];
 		vpe_cfg->pc = (unsigned long)mips_cps_pm_restore;
 		vpe_cfg->gp = (unsigned long)current_thread_info();
 		vpe_cfg->sp = 0;
@@ -376,6 +380,10 @@
 	memset(relocs, 0, sizeof(relocs));
 
 	if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+		/* Power gating relies upon CPS SMP */
+		if (!mips_cps_smp_in_use())
+			goto out_err;
+
 		/*
 		 * Save CPU state. Note the non-standard calling convention
 		 * with the return address placed in v0 to avoid clobbering
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 037a44d..097fc8d 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -113,6 +113,7 @@
 	if (cpu_has_vz)		seq_printf(m, "%s", " vz");
 	if (cpu_has_msa)	seq_printf(m, "%s", " msa");
 	if (cpu_has_eva)	seq_printf(m, "%s", " eva");
+	if (cpu_has_htw)	seq_printf(m, "%s", " htw");
 	seq_printf(m, "\n");
 
 	if (cpu_has_mmips) {
@@ -123,6 +124,7 @@
 		      cpu_data[n].srsets);
 	seq_printf(m, "kscratch registers\t: %d\n",
 		      hweight8(cpu_data[n].kscratch_mask));
+	seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package);
 	seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 0a1ec0f..636b074 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -21,7 +21,6 @@
 #include <linux/mman.h>
 #include <linux/personality.h>
 #include <linux/sys.h>
-#include <linux/user.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
@@ -36,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
@@ -66,6 +66,7 @@
 	clear_used_math();
 	clear_fpu_owner();
 	init_dsp();
+	clear_thread_flag(TIF_USEDMSA);
 	clear_thread_flag(TIF_MSA_CTX_LIVE);
 	disable_msa();
 	regs->cp0_epc = pc;
@@ -141,6 +142,8 @@
 	childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
 
 	clear_tsk_thread_flag(p, TIF_USEDFPU);
+	clear_tsk_thread_flag(p, TIF_USEDMSA);
+	clear_tsk_thread_flag(p, TIF_MSA_CTX_LIVE);
 
 #ifdef CONFIG_MIPS_MT_FPAFF
 	clear_tsk_thread_flag(p, TIF_FPUBOUND);
@@ -152,61 +155,6 @@
 	return 0;
 }
 
-/* Fill in the fpu structure for a core dump.. */
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
-
-	memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
-	       sizeof(current->thread.fpu.fcr31));
-
-	return 1;
-}
-
-void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < EF_R0; i++)
-		gp[i] = 0;
-	gp[EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		gp[EF_R0 + i] = regs->regs[i];
-	gp[EF_R26] = 0;
-	gp[EF_R27] = 0;
-	gp[EF_LO] = regs->lo;
-	gp[EF_HI] = regs->hi;
-	gp[EF_CP0_EPC] = regs->cp0_epc;
-	gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
-	gp[EF_CP0_STATUS] = regs->cp0_status;
-	gp[EF_CP0_CAUSE] = regs->cp0_cause;
-#ifdef EF_UNUSED0
-	gp[EF_UNUSED0] = 0;
-#endif
-}
-
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-	elf_dump_regs(*regs, task_pt_regs(tsk));
-	return 1;
-}
-
-int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
-
-	memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
-	       sizeof(t->thread.fpu.fcr31));
-
-	return 1;
-}
-
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
 unsigned long __stack_chk_guard __read_mostly;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 3a7f7dd..645b3c4 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -24,7 +24,6 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 #include <linux/tracehook.h>
 #include <linux/audit.h>
@@ -63,7 +62,7 @@
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
  */
-int ptrace_getregs(struct task_struct *child, __s64 __user *data)
+int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -74,13 +73,13 @@
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__put_user((long)regs->regs[i], data + i);
-	__put_user((long)regs->lo, data + EF_LO - EF_R0);
-	__put_user((long)regs->hi, data + EF_HI - EF_R0);
-	__put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
-	__put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
-	__put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
-	__put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+		__put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__put_user((long)regs->lo, (__s64 __user *)&data->lo);
+	__put_user((long)regs->hi, (__s64 __user *)&data->hi);
+	__put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
+	__put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
+	__put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
+	__put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
 
 	return 0;
 }
@@ -90,7 +89,7 @@
  * the 64-bit format.  On a 32-bit kernel only the lower order half
  * (according to endianness) will be used.
  */
-int ptrace_setregs(struct task_struct *child, __s64 __user *data)
+int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -101,10 +100,10 @@
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__get_user(regs->regs[i], data + i);
-	__get_user(regs->lo, data + EF_LO - EF_R0);
-	__get_user(regs->hi, data + EF_HI - EF_R0);
-	__get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+		__get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__get_user(regs->lo, (__s64 __user *)&data->lo);
+	__get_user(regs->hi, (__s64 __user *)&data->hi);
+	__get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
 
 	/* badvaddr, status, and cause may not be written.  */
 
@@ -129,7 +128,7 @@
 	}
 
 	__put_user(child->thread.fpu.fcr31, data + 64);
-	__put_user(current_cpu_data.fpu_id, data + 65);
+	__put_user(boot_cpu_data.fpu_id, data + 65);
 
 	return 0;
 }
@@ -247,36 +246,160 @@
 
 /* regset get/set implementations */
 
-static int gpr_get(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
 {
 	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG] = {};
+	unsigned i;
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   regs, 0, sizeof(*regs));
+	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS32_EF_R0];
+	}
+
+	uregs[MIPS32_EF_LO] = regs->lo;
+	uregs[MIPS32_EF_HI] = regs->hi;
+	uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
 }
 
-static int gpr_set(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
 {
-	struct pt_regs newregs;
-	int ret;
+	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
 
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &newregs,
-				 0, sizeof(newregs));
-	if (ret)
-		return ret;
+	start = pos / sizeof(u32);
+	num_regs = count / sizeof(u32);
 
-	*task_pt_regs(target) = newregs;
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		/*
+		 * Cast all values to signed here so that if this is a 64-bit
+		 * kernel, the supplied 32-bit values will be sign extended.
+		 */
+		switch (i) {
+		case MIPS32_EF_R1 ... MIPS32_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS32_EF_R28 ... MIPS32_EF_R31:
+			regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+			break;
+		case MIPS32_EF_LO:
+			regs->lo = (s32)uregs[i];
+			break;
+		case MIPS32_EF_HI:
+			regs->hi = (s32)uregs[i];
+			break;
+		case MIPS32_EF_CP0_EPC:
+			regs->cp0_epc = (s32)uregs[i];
+			break;
+		}
+	}
 
 	return 0;
 }
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS64_EF_R0];
+	}
+
+	uregs[MIPS64_EF_LO] = regs->lo;
+	uregs[MIPS64_EF_HI] = regs->hi;
+	uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
+}
+
+static int gpr64_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u64);
+	num_regs = count / sizeof(u64);
+
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		switch (i) {
+		case MIPS64_EF_R1 ... MIPS64_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS64_EF_R28 ... MIPS64_EF_R31:
+			regs->regs[i - MIPS64_EF_R0] = uregs[i];
+			break;
+		case MIPS64_EF_LO:
+			regs->lo = uregs[i];
+			break;
+		case MIPS64_EF_HI:
+			regs->hi = uregs[i];
+			break;
+		case MIPS64_EF_CP0_EPC:
+			regs->cp0_epc = uregs[i];
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_64BIT */
+
 static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -338,14 +461,16 @@
 	REGSET_FPR,
 };
 
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
 static const struct user_regset mips_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned int),
 		.align		= sizeof(unsigned int),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr32_get,
+		.set		= gpr32_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -365,14 +490,18 @@
 	.n		= ARRAY_SIZE(mips_regsets),
 };
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
 static const struct user_regset mips64_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned long),
 		.align		= sizeof(unsigned long),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr64_get,
+		.set		= gpr64_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -385,25 +514,26 @@
 };
 
 static const struct user_regset_view user_mips64_view = {
-	.name		= "mips",
+	.name		= "mips64",
 	.e_machine	= ELF_ARCH,
 	.ei_osabi	= ELF_OSABI,
 	.regsets	= mips64_regsets,
-	.n		= ARRAY_SIZE(mips_regsets),
+	.n		= ARRAY_SIZE(mips64_regsets),
 };
 
+#endif /* CONFIG_64BIT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_32BIT
 	return &user_mips_view;
-#endif
-
+#else
 #ifdef CONFIG_MIPS32_O32
-		if (test_thread_flag(TIF_32BIT_REGS))
-			return &user_mips_view;
+	if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+		return &user_mips_view;
 #endif
-
 	return &user_mips64_view;
+#endif
 }
 
 long arch_ptrace(struct task_struct *child, long request,
@@ -481,7 +611,7 @@
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index b40c3ca..283b5a1 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 
 #include <asm/cpu.h>
@@ -32,6 +31,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
@@ -129,7 +129,7 @@
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
@@ -256,11 +256,13 @@
 		}
 
 	case PTRACE_GETREGS:
-		ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_getregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_SETREGS:
-		ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_setregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_GETFPREGS:
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 81ca3f7..4c4ec18 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -64,8 +64,10 @@
 	/* Check whether we're saving scalar or vector context. */
 	bgtz	a3, 1f
 
-	/* Save 128b MSA vector context. */
+	/* Save 128b MSA vector context + scalar FP control & status. */
+	cfc1	t1, fcr31
 	msa_save_all	a0
+	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
 1:	/* Save 32b/64b scalar FP context. */
@@ -142,6 +144,11 @@
 	jr	ra
 	END(_restore_msa)
 
+LEAF(_init_msa_upper)
+	msa_init_all_upper
+	jr	ra
+	END(_init_msa_upper)
+
 #endif
 
 /*
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 3245474..94a490d 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -67,8 +67,6 @@
 
 	/*
 	 * Ok, copy the args from the luser stack to the kernel stack.
-	 * t3 is the precomputed number of instruction bytes needed to
-	 * load or store arguments 6-8.
 	 */
 
 	.set    push
@@ -495,8 +493,8 @@
 	PTR	sys_tgkill
 	PTR	sys_utimes
 	PTR	sys_mbind
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	sys_get_mempolicy
+	PTR	sys_set_mempolicy		/* 4270 */
 	PTR	sys_mq_open
 	PTR	sys_mq_unlink
 	PTR	sys_mq_timedsend
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be2fedd..0952139 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -347,8 +347,8 @@
 	PTR	sys_tgkill			/* 5225 */
 	PTR	sys_utimes
 	PTR	sys_mbind
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* sys_set_mempolicy */
+	PTR	sys_get_mempolicy
+	PTR	sys_set_mempolicy
 	PTR	sys_mq_open			/* 5230 */
 	PTR	sys_mq_unlink
 	PTR	sys_mq_timedsend
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index e543861..03dec5a 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -339,9 +339,9 @@
 	PTR	compat_sys_clock_nanosleep
 	PTR	sys_tgkill
 	PTR	compat_sys_utimes		/* 6230 */
-	PTR	sys_ni_syscall			/* sys_mbind */
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* sys_set_mempolicy */
+	PTR	compat_sys_mbind
+	PTR	compat_sys_get_mempolicy
+	PTR	compat_sys_set_mempolicy
 	PTR	compat_sys_mq_open
 	PTR	sys_mq_unlink			/* 6235 */
 	PTR	compat_sys_mq_timedsend
@@ -358,7 +358,7 @@
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch
 	PTR	sys_inotify_rm_watch
-	PTR	sys_migrate_pages		/* 6250 */
+	PTR	compat_sys_migrate_pages	/* 6250 */
 	PTR	sys_openat
 	PTR	sys_mkdirat
 	PTR	sys_mknodat
@@ -379,7 +379,7 @@
 	PTR	sys_sync_file_range
 	PTR	sys_tee
 	PTR	compat_sys_vmsplice		/* 6270 */
-	PTR	sys_move_pages
+	PTR	compat_sys_move_pages
 	PTR	compat_sys_set_robust_list
 	PTR	compat_sys_get_robust_list
 	PTR	compat_sys_kexec_load
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index f1343cc..18cfa11 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -473,9 +473,9 @@
 	PTR	compat_sys_clock_nanosleep	/* 4265 */
 	PTR	sys_tgkill
 	PTR	compat_sys_utimes
-	PTR	sys_ni_syscall			/* sys_mbind */
-	PTR	sys_ni_syscall			/* sys_get_mempolicy */
-	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	compat_sys_mbind
+	PTR	compat_sys_get_mempolicy
+	PTR	compat_sys_set_mempolicy	/* 4270 */
 	PTR	compat_sys_mq_open
 	PTR	sys_mq_unlink
 	PTR	compat_sys_mq_timedsend
@@ -492,7 +492,7 @@
 	PTR	sys_inotify_init
 	PTR	sys_inotify_add_watch		/* 4285 */
 	PTR	sys_inotify_rm_watch
-	PTR	sys_migrate_pages
+	PTR	compat_sys_migrate_pages
 	PTR	compat_sys_openat
 	PTR	sys_mkdirat
 	PTR	sys_mknodat			/* 4290 */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index a842154..7c1fe2b 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -282,7 +282,7 @@
  * Initialize the bootmem allocator. It also setup initrd related data
  * if needed.
  */
-#ifdef CONFIG_SGI_IP27
+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
 
 static void __init bootmem_init(void)
 {
@@ -729,6 +729,25 @@
 	}
 }
 
+#ifdef CONFIG_SMP
+static void __init prefill_possible_map(void)
+{
+	int i, possible = num_possible_cpus();
+
+	if (possible > nr_cpu_ids)
+		possible = nr_cpu_ids;
+
+	for (i = 0; i < possible; i++)
+		set_cpu_possible(i, true);
+	for (; i < NR_CPUS; i++)
+		set_cpu_possible(i, false);
+
+	nr_cpu_ids = possible;
+}
+#else
+static inline void prefill_possible_map(void) {}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
 	cpu_probe();
@@ -752,6 +771,7 @@
 
 	resource_init();
 	plat_smp_setup();
+	prefill_possible_map();
 
 	cpu_cache_init();
 }
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 949f2c6..e6e16a1 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -14,13 +14,14 @@
 #include <linux/smp.h>
 #include <linux/types.h>
 
-#include <asm/cacheflush.h>
+#include <asm/bcache.h>
 #include <asm/gic.h>
 #include <asm/mips-cm.h>
 #include <asm/mips-cpc.h>
 #include <asm/mips_mt.h>
 #include <asm/mipsregs.h>
 #include <asm/pm-cps.h>
+#include <asm/r4kcache.h>
 #include <asm/smp-cps.h>
 #include <asm/time.h>
 #include <asm/uasm.h>
@@ -132,8 +133,11 @@
 	entry_code = (u32 *)&mips_cps_core_entry;
 	UASM_i_LA(&entry_code, 3, (long)mips_cm_base);
 	uasm_i_addiu(&entry_code, 16, 0, cca);
-	dma_cache_wback_inv((unsigned long)&mips_cps_core_entry,
-			    (void *)entry_code - (void *)&mips_cps_core_entry);
+	blast_dcache_range((unsigned long)&mips_cps_core_entry,
+			   (unsigned long)entry_code);
+	bc_wback_inv((unsigned long)&mips_cps_core_entry,
+		     (void *)entry_code - (void *)&mips_cps_core_entry);
+	__sync();
 
 	/* Allocate core boot configuration structs */
 	mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg),
@@ -360,7 +364,7 @@
 static void wait_for_sibling_halt(void *ptr_cpu)
 {
 	unsigned cpu = (unsigned)ptr_cpu;
-	unsigned vpe_id = cpu_data[cpu].vpe_id;
+	unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
 	unsigned halted;
 	unsigned long flags;
 
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9bad52e..c94c4e9 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -59,9 +59,16 @@
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_sibling_map);
 
+/* representing the core map of multi-core chips of each logical CPU */
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(cpu_core_map);
+
 /* representing cpus for which sibling maps can be computed */
 static cpumask_t cpu_sibling_setup_map;
 
+/* representing cpus for which core maps can be computed */
+static cpumask_t cpu_core_setup_map;
+
 cpumask_t cpu_coherent_mask;
 
 static inline void set_cpu_sibling_map(int cpu)
@@ -72,7 +79,8 @@
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (cpu_data[cpu].core == cpu_data[i].core) {
+			if (cpu_data[cpu].package == cpu_data[i].package &&
+				    cpu_data[cpu].core == cpu_data[i].core) {
 				cpu_set(i, cpu_sibling_map[cpu]);
 				cpu_set(cpu, cpu_sibling_map[i]);
 			}
@@ -81,6 +89,20 @@
 		cpu_set(cpu, cpu_sibling_map[cpu]);
 }
 
+static inline void set_cpu_core_map(int cpu)
+{
+	int i;
+
+	cpu_set(cpu, cpu_core_setup_map);
+
+	for_each_cpu_mask(i, cpu_core_setup_map) {
+		if (cpu_data[cpu].package == cpu_data[i].package) {
+			cpu_set(i, cpu_core_map[cpu]);
+			cpu_set(cpu, cpu_core_map[i]);
+		}
+	}
+}
+
 struct plat_smp_ops *mp_ops;
 EXPORT_SYMBOL(mp_ops);
 
@@ -122,6 +144,7 @@
 	set_cpu_online(cpu, true);
 
 	set_cpu_sibling_map(cpu);
+	set_cpu_core_map(cpu);
 
 	cpu_set(cpu, cpu_callin_map);
 
@@ -175,6 +198,7 @@
 	current_thread_info()->cpu = 0;
 	mp_ops->prepare_cpus(max_cpus);
 	set_cpu_sibling_map(0);
+	set_cpu_core_map(0);
 #ifndef CONFIG_HOTPLUG_CPU
 	init_cpu_present(cpu_possible_mask);
 #endif
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 51706d6..22b19c2 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -90,6 +90,7 @@
 extern asmlinkage void handle_dsp(void);
 extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
+extern void tlb_do_page_fault_0(void);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -1088,13 +1089,19 @@
 
 static int enable_restore_fp_context(int msa)
 {
-	int err, was_fpu_owner;
+	int err, was_fpu_owner, prior_msa;
 
 	if (!used_math()) {
 		/* First time FP context user. */
+		preempt_disable();
 		err = init_fpu();
-		if (msa && !err)
+		if (msa && !err) {
 			enable_msa();
+			_init_msa_upper();
+			set_thread_flag(TIF_USEDMSA);
+			set_thread_flag(TIF_MSA_CTX_LIVE);
+		}
+		preempt_enable();
 		if (!err)
 			set_used_math();
 		return err;
@@ -1134,10 +1141,11 @@
 	 * This task is using or has previously used MSA. Thus we require
 	 * that Status.FR == 1.
 	 */
+	preempt_disable();
 	was_fpu_owner = is_fpu_owner();
-	err = own_fpu(0);
+	err = own_fpu_inatomic(0);
 	if (err)
-		return err;
+		goto out;
 
 	enable_msa();
 	write_msa_csr(current->thread.fpu.msacsr);
@@ -1146,13 +1154,42 @@
 	/*
 	 * If this is the first time that the task is using MSA and it has
 	 * previously used scalar FP in this time slice then we already nave
-	 * FP context which we shouldn't clobber.
+	 * FP context which we shouldn't clobber. We do however need to clear
+	 * the upper 64b of each vector register so that this task has no
+	 * opportunity to see data left behind by another.
 	 */
-	if (!test_and_set_thread_flag(TIF_MSA_CTX_LIVE) && was_fpu_owner)
-		return 0;
+	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
+	if (!prior_msa && was_fpu_owner) {
+		_init_msa_upper();
 
-	/* We need to restore the vector context. */
-	restore_msa(current);
+		goto out;
+	}
+
+	if (!prior_msa) {
+		/*
+		 * Restore the least significant 64b of each vector register
+		 * from the existing scalar FP context.
+		 */
+		_restore_fp(current);
+
+		/*
+		 * The task has not formerly used MSA, so clear the upper 64b
+		 * of each vector register such that it cannot see data left
+		 * behind by another task.
+		 */
+		_init_msa_upper();
+	} else {
+		/* We need to restore the vector context. */
+		restore_msa(current);
+
+		/* Restore the scalar FP control & status register */
+		if (!was_fpu_owner)
+			asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+	}
+
+out:
+	preempt_enable();
+
 	return 0;
 }
 
@@ -2114,6 +2151,12 @@
 		set_except_vector(15, handle_fpe);
 
 	set_except_vector(16, handle_ftlb);
+
+	if (cpu_has_rixiex) {
+		set_except_vector(19, tlb_do_page_fault_0);
+		set_except_vector(20, tlb_do_page_fault_0);
+	}
+
 	set_except_vector(21, handle_msa);
 	set_except_vector(22, handle_mdmx);
 
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index e6a86ccc..1b91fc6 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -60,8 +60,8 @@
 	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
 	  LingLoong allinone PC and so forth.
 
-config LEMOTE_MACH3A
-	bool "Lemote Loongson 3A family machines"
+config LOONGSON_MACH3X
+	bool "Generic Loongson 3 family machines"
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
 	select BOOT_ELF32
@@ -79,6 +79,7 @@
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_HOTPLUG_CPU
+	select SYS_SUPPORTS_NUMA
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -86,8 +87,8 @@
 	select ZONE_DMA32
 	select LEFI_FIRMWARE_INTERFACE
 	help
-		Lemote Loongson 3A family machines utilize the 3A revision of
-		Loongson processor and RS780/SBX00 chipset.
+		Generic Loongson 3 family machines utilize the 3A/3B revision
+		of Loongson processor and RS780/SBX00 chipset.
 endchoice
 
 config CS5536
diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
index 6205372..0ac20eb 100644
--- a/arch/mips/loongson/Platform
+++ b/arch/mips/loongson/Platform
@@ -30,4 +30,4 @@
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
 load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
-load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000
+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index 0c543ea..f152285 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -27,6 +27,12 @@
 struct efi_memory_map_loongson *loongson_memmap;
 struct loongson_system_configuration loongson_sysconf;
 
+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
+u64 loongson_freqctrl[MAX_PACKAGES];
+
+unsigned long long smp_group[4];
+int cpuhotplug_workaround = 0;
+
 #define parse_even_earlier(res, option, p)				\
 do {									\
 	unsigned int tmp __maybe_unused;				\
@@ -77,9 +83,47 @@
 
 	cpu_clock_freq = ecpu->cpu_clock_freq;
 	loongson_sysconf.cputype = ecpu->cputype;
+	if (ecpu->cputype == Loongson_3A) {
+		loongson_sysconf.cores_per_node = 4;
+		loongson_sysconf.cores_per_package = 4;
+		smp_group[0] = 0x900000003ff01000;
+		smp_group[1] = 0x900010003ff01000;
+		smp_group[2] = 0x900020003ff01000;
+		smp_group[3] = 0x900030003ff01000;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+		loongson_chipcfg[1] = 0x900010001fe00180;
+		loongson_chipcfg[2] = 0x900020001fe00180;
+		loongson_chipcfg[3] = 0x900030001fe00180;
+		loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+	} else if (ecpu->cputype == Loongson_3B) {
+		loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
+		loongson_sysconf.cores_per_package = 8;
+		smp_group[0] = 0x900000003ff01000;
+		smp_group[1] = 0x900010003ff05000;
+		smp_group[2] = 0x900020003ff09000;
+		smp_group[3] = 0x900030003ff0d000;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+		loongson_chipcfg[1] = 0x900020001fe00180;
+		loongson_chipcfg[2] = 0x900040001fe00180;
+		loongson_chipcfg[3] = 0x900060001fe00180;
+		loongson_freqctrl[0] = 0x900000001fe001d0;
+		loongson_freqctrl[1] = 0x900020001fe001d0;
+		loongson_freqctrl[2] = 0x900040001fe001d0;
+		loongson_freqctrl[3] = 0x900060001fe001d0;
+		loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
+		cpuhotplug_workaround = 1;
+	} else {
+		loongson_sysconf.cores_per_node = 1;
+		loongson_sysconf.cores_per_package = 1;
+		loongson_chipcfg[0] = 0x900000001fe00180;
+	}
+
 	loongson_sysconf.nr_cpus = ecpu->nr_cpus;
 	if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
 		loongson_sysconf.nr_cpus = NR_CPUS;
+	loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
+		loongson_sysconf.cores_per_node - 1) /
+		loongson_sysconf.cores_per_node;
 
 	loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
 	loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
@@ -93,7 +137,6 @@
 	loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
 	loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
 
-	loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
 	loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
 	pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
 		loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
@@ -111,6 +154,10 @@
 		case PRID_REV_LOONGSON3A:
 			cpu_clock_freq = 900000000;
 			break;
+		case PRID_REV_LOONGSON3B_R1:
+		case PRID_REV_LOONGSON3B_R2:
+			cpu_clock_freq = 1000000000;
+			break;
 		default:
 			cpu_clock_freq = 100000000;
 			break;
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index f37fe54..f6af3ab 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -30,7 +30,11 @@
 	set_io_port_base((unsigned long)
 		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+#ifdef CONFIG_NUMA
+	prom_init_numa_memory();
+#else
 	prom_init_memory();
+#endif
 
 	/*init the uart base address */
 	prom_init_uart_base();
diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c
index f55e07a..a6b67cc 100644
--- a/arch/mips/loongson/common/pm.c
+++ b/arch/mips/loongson/common/pm.c
@@ -79,7 +79,7 @@
 static void wait_for_wakeup_events(void)
 {
 	while (!wakeup_loongson())
-		LOONGSON_CHIPCFG0 &= ~0x7;
+		LOONGSON_CHIPCFG(0) &= ~0x7;
 }
 
 /*
@@ -102,15 +102,15 @@
 
 	stop_perf_counters();
 
-	cached_cpu_freq = LOONGSON_CHIPCFG0;
+	cached_cpu_freq = LOONGSON_CHIPCFG(0);
 
 	/* Put CPU into wait mode */
-	LOONGSON_CHIPCFG0 &= ~0x7;
+	LOONGSON_CHIPCFG(0) &= ~0x7;
 
 	/* wait for the given events to wakeup cpu from wait mode */
 	wait_for_wakeup_events();
 
-	LOONGSON_CHIPCFG0 = cached_cpu_freq;
+	LOONGSON_CHIPCFG(0) = cached_cpu_freq;
 	mmiowb();
 }
 
diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c
index 1eed38e..a217061 100644
--- a/arch/mips/loongson/lemote-2f/clock.c
+++ b/arch/mips/loongson/lemote-2f/clock.c
@@ -114,9 +114,9 @@
 
 	clk->rate = rate;
 
-	regval = LOONGSON_CHIPCFG0;
+	regval = LOONGSON_CHIPCFG(0);
 	regval = (regval & ~0x7) | (pos->driver_data - 1);
-	LOONGSON_CHIPCFG0 = regval;
+	LOONGSON_CHIPCFG(0) = regval;
 
 	return ret;
 }
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c
index 90962a3..79ac694 100644
--- a/arch/mips/loongson/lemote-2f/reset.c
+++ b/arch/mips/loongson/lemote-2f/reset.c
@@ -28,7 +28,7 @@
 	 * reset cpu to full speed, this is needed when enabling cpu frequency
 	 * scalling
 	 */
-	LOONGSON_CHIPCFG0 |= 0x7;
+	LOONGSON_CHIPCFG(0) |= 0x7;
 }
 
 /* reset support for fuloong2f */
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index 70152b2..b4df775 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -1,6 +1,8 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y			+= irq.o
+obj-y			+= irq.o cop2-ex.o
 
 obj-$(CONFIG_SMP)	+= smp.o
+
+obj-$(CONFIG_NUMA)	+= numa.o
diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c
new file mode 100644
index 0000000..9182e8d
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/cop2-ex.c
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2014 Lemote Corporation.
+ *   written by Huacai Chen <chenhc@lemote.com>
+ *
+ * based on arch/mips/cavium-octeon/cpu.c
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+
+#include <asm/fpu.h>
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+
+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action,
+	void *data)
+{
+	int fpu_enabled;
+	int fr = !test_thread_flag(TIF_32BIT_FPREGS);
+
+	switch (action) {
+	case CU2_EXCEPTION:
+		preempt_disable();
+		fpu_enabled = read_c0_status() & ST0_CU1;
+		if (!fr)
+			set_c0_status(ST0_CU1 | ST0_CU2);
+		else
+			set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR);
+		enable_fpu_hazard();
+		KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2);
+		if (fr)
+			KSTK_STATUS(current) |= ST0_FR;
+		else
+			KSTK_STATUS(current) &= ~ST0_FR;
+		/* If FPU is enabled, we needn't init or restore fp */
+		if(!fpu_enabled) {
+			set_thread_flag(TIF_USEDFPU);
+			if (!used_math()) {
+				_init_fpu();
+				set_used_math();
+			} else
+				_restore_fp(current);
+		}
+		preempt_enable();
+
+		return NOTIFY_STOP;	/* Don't call default notifier */
+	}
+
+	return NOTIFY_OK;		/* Let default notifier send signals */
+}
+
+static int __init loongson_cu2_setup(void)
+{
+	return cu2_notifier(loongson_cu2_call, 0);
+}
+early_initcall(loongson_cu2_setup);
diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c
index f240828..ca1c62a 100644
--- a/arch/mips/loongson/loongson-3/irq.c
+++ b/arch/mips/loongson/loongson-3/irq.c
@@ -7,6 +7,8 @@
 #include <asm/i8259.h>
 #include <asm/mipsregs.h>
 
+#include "smp.h"
+
 unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
 
 static void ht_irqdispatch(void)
@@ -53,9 +55,15 @@
 	/* Workaround: UART IRQ may deliver to any core */
 	if (d->irq == LOONGSON_UART_IRQ) {
 		int cpu = smp_processor_id();
+		int node_id = cpu / loongson_sysconf.cores_per_node;
+		int core_id = cpu % loongson_sysconf.cores_per_node;
+		u64 intenclr_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_INTENCLR);
+		u64 introuter_lpc_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_LPC);
 
-		LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
-		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+		*(volatile u32 *)intenclr_addr = 1 << 10;
+		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
 	}
 }
 
@@ -64,9 +72,15 @@
 	/* Workaround: UART IRQ may deliver to any core */
 	if (d->irq == LOONGSON_UART_IRQ) {
 		int cpu = smp_processor_id();
+		int node_id = cpu / loongson_sysconf.cores_per_node;
+		int core_id = cpu % loongson_sysconf.cores_per_node;
+		u64 intenset_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_INTENSET);
+		u64 introuter_lpc_addr = smp_group[node_id] |
+			(u64)(&LOONGSON_INT_ROUTER_LPC);
 
-		LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
-		LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
+		*(volatile u32 *)intenset_addr = 1 << 10;
+		*(volatile u8 *)introuter_lpc_addr = 0x10 + (1<<core_id);
 	}
 
 	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
new file mode 100644
index 0000000..ca025a6
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/numa.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
+ *                    Insititute of Computing Technology
+ * Author:  Xiang Gao, gaoxiang@ict.ac.cn
+ *          Huacai Chen, chenhc@lemote.com
+ *          Xiaofu Meng, Shuangshuang Zhang
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/highmem.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+#include <boot_param.h>
+
+static struct node_data prealloc__node_data[MAX_NUMNODES];
+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
+struct node_data *__node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(__node_data);
+
+static void enable_lpa(void)
+{
+	unsigned long value;
+
+	value = __read_32bit_c0_register($16, 3);
+	value |= 0x00000080;
+	__write_32bit_c0_register($16, 3, value);
+	value = __read_32bit_c0_register($16, 3);
+	pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
+
+	value = __read_32bit_c0_register($5, 1);
+	value |= 0x20000000;
+	__write_32bit_c0_register($5, 1, value);
+	value = __read_32bit_c0_register($5, 1);
+	pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
+}
+
+static void cpu_node_probe(void)
+{
+	int i;
+
+	nodes_clear(node_possible_map);
+	nodes_clear(node_online_map);
+	for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
+		node_set_state(num_online_nodes(), N_POSSIBLE);
+		node_set_online(num_online_nodes());
+	}
+
+	pr_info("NUMA: Discovered %d cpus on %d nodes\n",
+		loongson_sysconf.nr_cpus, num_online_nodes());
+}
+
+static int __init compute_node_distance(int row, int col)
+{
+	int package_row = row * loongson_sysconf.cores_per_node /
+				loongson_sysconf.cores_per_package;
+	int package_col = col * loongson_sysconf.cores_per_node /
+				loongson_sysconf.cores_per_package;
+
+	if (col == row)
+		return 0;
+	else if (package_row == package_col)
+		return 40;
+	else
+		return 100;
+}
+
+static void __init init_topology_matrix(void)
+{
+	int row, col;
+
+	for (row = 0; row < MAX_NUMNODES; row++)
+		for (col = 0; col < MAX_NUMNODES; col++)
+			__node_distances[row][col] = -1;
+
+	for_each_online_node(row) {
+		for_each_online_node(col) {
+			__node_distances[row][col] =
+				compute_node_distance(row, col);
+		}
+	}
+}
+
+static unsigned long nid_to_addroffset(unsigned int nid)
+{
+	unsigned long result;
+	switch (nid) {
+	case 0:
+	default:
+		result = NODE0_ADDRSPACE_OFFSET;
+		break;
+	case 1:
+		result = NODE1_ADDRSPACE_OFFSET;
+		break;
+	case 2:
+		result = NODE2_ADDRSPACE_OFFSET;
+		break;
+	case 3:
+		result = NODE3_ADDRSPACE_OFFSET;
+		break;
+	}
+	return result;
+}
+
+static void __init szmem(unsigned int node)
+{
+	u32 i, mem_type;
+	static unsigned long num_physpages = 0;
+	u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+
+	/* Parse memory information and activate */
+	for (i = 0; i < loongson_memmap->nr_map; i++) {
+		node_id = loongson_memmap->map[i].node_id;
+		if (node_id != node)
+			continue;
+
+		mem_type = loongson_memmap->map[i].mem_type;
+		mem_size = loongson_memmap->map[i].mem_size;
+		mem_start = loongson_memmap->map[i].mem_start;
+
+		switch (mem_type) {
+		case SYSTEM_RAM_LOW:
+			start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+			node_psize = (mem_size << 20) >> PAGE_SHIFT;
+			end_pfn  = start_pfn + node_psize;
+			num_physpages += node_psize;
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+				start_pfn, end_pfn, num_physpages);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RAM);
+			memblock_add_node(PFN_PHYS(start_pfn),
+				PFN_PHYS(end_pfn - start_pfn), node);
+			break;
+		case SYSTEM_RAM_HIGH:
+			start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
+			node_psize = (mem_size << 20) >> PAGE_SHIFT;
+			end_pfn  = start_pfn + node_psize;
+			num_physpages += node_psize;
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
+				start_pfn, end_pfn, num_physpages);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RAM);
+			memblock_add_node(PFN_PHYS(start_pfn),
+				PFN_PHYS(end_pfn - start_pfn), node);
+			break;
+		case MEM_RESERVED:
+			pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
+				(u32)node_id, mem_type, mem_start, mem_size);
+			add_memory_region((node_id << 44) + mem_start,
+				(u64)mem_size << 20, BOOT_MEM_RESERVED);
+			memblock_reserve(((node_id << 44) + mem_start),
+				mem_size << 20);
+			break;
+		}
+	}
+}
+
+static void __init node_mem_init(unsigned int node)
+{
+	unsigned long bootmap_size;
+	unsigned long node_addrspace_offset;
+	unsigned long start_pfn, end_pfn, freepfn;
+
+	node_addrspace_offset = nid_to_addroffset(node);
+	pr_info("Node%d's addrspace_offset is 0x%lx\n",
+			node, node_addrspace_offset);
+
+	get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+	freepfn = start_pfn;
+	if (node == 0)
+		freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
+	pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
+		node, start_pfn, end_pfn, freepfn);
+
+	__node_data[node] = prealloc__node_data + node;
+
+	NODE_DATA(node)->bdata = &bootmem_node_data[node];
+	NODE_DATA(node)->node_start_pfn = start_pfn;
+	NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
+
+	bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
+					start_pfn, end_pfn);
+	free_bootmem_with_active_regions(node, end_pfn);
+	if (node == 0) /* used by finalize_initrd() */
+		max_low_pfn = end_pfn;
+
+	/* This is reserved for the kernel and bdata->node_bootmem_map */
+	reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
+		((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
+		BOOTMEM_DEFAULT);
+
+	if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
+		/* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+		reserve_bootmem_node(NODE_DATA(node),
+				(node_addrspace_offset | 0xff800000),
+				8 << 20, BOOTMEM_DEFAULT);
+	}
+
+	sparse_memory_present_with_active_regions(node);
+}
+
+static __init void prom_meminit(void)
+{
+	unsigned int node, cpu;
+
+	cpu_node_probe();
+	init_topology_matrix();
+
+	for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
+		if (node_online(node)) {
+			szmem(node);
+			node_mem_init(node);
+			cpus_clear(__node_data[(node)]->cpumask);
+		}
+	}
+	for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
+		node = cpu / loongson_sysconf.cores_per_node;
+		if (node >= num_online_nodes())
+			node = 0;
+		pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
+		cpu_set(cpu, __node_data[(node)]->cpumask);
+	}
+}
+
+void __init paging_init(void)
+{
+	unsigned node;
+	unsigned long zones_size[MAX_NR_ZONES] = {0, };
+
+	pagetable_init();
+
+	for_each_online_node(node) {
+		unsigned long  start_pfn, end_pfn;
+
+		get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
+
+		if (end_pfn > max_low_pfn)
+			max_low_pfn = end_pfn;
+	}
+#ifdef CONFIG_ZONE_DMA32
+	zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
+#endif
+	zones_size[ZONE_NORMAL] = max_low_pfn;
+	free_area_init_nodes(zones_size);
+}
+
+void __init mem_init(void)
+{
+	high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
+	free_all_bootmem();
+	setup_zero_pages();	/* This comes from node 0 */
+	mem_init_print_info(NULL);
+}
+
+/* All PCI device belongs to logical Node-0 */
+int pcibus_to_node(struct pci_bus *bus)
+{
+	return 0;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+
+void __init prom_init_numa_memory(void)
+{
+	enable_lpa();
+	prom_meminit();
+}
+EXPORT_SYMBOL(prom_init_numa_memory);
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index 1e88940..74e827b 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -31,6 +31,12 @@
 DEFINE_PER_CPU(int, cpu_state);
 DEFINE_PER_CPU(uint32_t, core0_c0count);
 
+static void *ipi_set0_regs[16];
+static void *ipi_clear0_regs[16];
+static void *ipi_status0_regs[16];
+static void *ipi_en0_regs[16];
+static void *ipi_mailbox_buf[16];
+
 /* read a 32bit value from ipi register */
 #define loongson3_ipi_read32(addr) readl(addr)
 /* read a 64bit value from ipi register */
@@ -48,100 +54,185 @@
 		__wbflush();			\
 	} while (0)
 
-static void *ipi_set0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0),
-};
+static void ipi_set0_regs_init(void)
+{
+	ipi_set0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0);
+	ipi_set0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0);
+	ipi_set0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0);
+	ipi_set0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0);
+	ipi_set0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0);
+}
 
-static void *ipi_clear0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0),
-};
+static void ipi_clear0_regs_init(void)
+{
+	ipi_clear0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0);
+	ipi_clear0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0);
+	ipi_clear0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0);
+	ipi_clear0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0);
+	ipi_clear0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0);
+}
 
-static void *ipi_status0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0),
-};
+static void ipi_status0_regs_init(void)
+{
+	ipi_status0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0);
+	ipi_status0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0);
+	ipi_status0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0);
+	ipi_status0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0);
+	ipi_status0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0);
+}
 
-static void *ipi_en0_regs[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0),
-};
+static void ipi_en0_regs_init(void)
+{
+	ipi_en0_regs[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0);
+	ipi_en0_regs[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0);
+	ipi_en0_regs[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0);
+	ipi_en0_regs[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0);
+	ipi_en0_regs[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0);
+}
 
-static void *ipi_mailbox_buf[] = {
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF),
-	(void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF),
-};
+static void ipi_mailbox_buf_init(void)
+{
+	ipi_mailbox_buf[0] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[1] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[2] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[3] = (void *)
+		(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[4] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[5] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[6] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[7] = (void *)
+		(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[8] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[9] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[10] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[11] = (void *)
+		(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF);
+	ipi_mailbox_buf[12] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF);
+	ipi_mailbox_buf[13] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF);
+	ipi_mailbox_buf[14] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF);
+	ipi_mailbox_buf[15] = (void *)
+		(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF);
+}
 
 /*
  * Simple enough, just poke the appropriate ipi register
@@ -203,6 +294,8 @@
 	for (i = 0; i < loongson_sysconf.nr_cpus; i++)
 		loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
 
+	cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
+	cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
 	per_cpu(cpu_state, cpu) = CPU_ONLINE;
 
 	i = 0;
@@ -246,6 +339,11 @@
 		__cpu_number_map[i] = ++num;
 		__cpu_logical_map[num] = i;
 	}
+	ipi_set0_regs_init();
+	ipi_clear0_regs_init();
+	ipi_status0_regs_init();
+	ipi_en0_regs_init();
+	ipi_mailbox_buf_init();
 	pr_info("Detected %i available secondary CPU(s)\n", num);
 }
 
@@ -313,7 +411,7 @@
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
  * called via CKSEG1 (uncached and unmmaped) */
-static void loongson3_play_dead(int *state_addr)
+static void loongson3a_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -375,6 +473,70 @@
 		: "a1");
 }
 
+static void loongson3b_play_dead(int *state_addr)
+{
+	register int val;
+	register long cpuid, core, node, count;
+	register void *addr, *base, *initfunc;
+
+	__asm__ __volatile__(
+		"   .set push                     \n"
+		"   .set noreorder                \n"
+		"   li %[addr], 0x80000000        \n" /* KSEG0 */
+		"1: cache 0, 0(%[addr])           \n" /* flush L1 ICache */
+		"   cache 0, 1(%[addr])           \n"
+		"   cache 0, 2(%[addr])           \n"
+		"   cache 0, 3(%[addr])           \n"
+		"   cache 1, 0(%[addr])           \n" /* flush L1 DCache */
+		"   cache 1, 1(%[addr])           \n"
+		"   cache 1, 2(%[addr])           \n"
+		"   cache 1, 3(%[addr])           \n"
+		"   addiu %[sets], %[sets], -1    \n"
+		"   bnez  %[sets], 1b             \n"
+		"   addiu %[addr], %[addr], 0x20  \n"
+		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
+		"   sw    %[val], (%[state_addr]) \n"
+		"   sync                          \n"
+		"   cache 21, (%[state_addr])     \n" /* flush entry of *state_addr */
+		"   .set pop                      \n"
+		: [addr] "=&r" (addr), [val] "=&r" (val)
+		: [state_addr] "r" (state_addr),
+		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets));
+
+	__asm__ __volatile__(
+		"   .set push                         \n"
+		"   .set noreorder                    \n"
+		"   .set mips64                       \n"
+		"   mfc0  %[cpuid], $15, 1            \n"
+		"   andi  %[cpuid], 0x3ff             \n"
+		"   dli   %[base], 0x900000003ff01000 \n"
+		"   andi  %[core], %[cpuid], 0x3      \n"
+		"   sll   %[core], 8                  \n" /* get core id */
+		"   or    %[base], %[base], %[core]   \n"
+		"   andi  %[node], %[cpuid], 0xc      \n"
+		"   dsll  %[node], 42                 \n" /* get node id */
+		"   or    %[base], %[base], %[node]   \n"
+		"   dsrl  %[node], 30                 \n" /* 15:14 */
+		"   or    %[base], %[base], %[node]   \n"
+		"1: li    %[count], 0x100             \n" /* wait for init loop */
+		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
+		"   addiu %[count], -1                \n"
+		"   ld    %[initfunc], 0x20(%[base])  \n" /* get PC via mailbox */
+		"   beqz  %[initfunc], 1b             \n"
+		"   nop                               \n"
+		"   ld    $sp, 0x28(%[base])          \n" /* get SP via mailbox */
+		"   ld    $gp, 0x30(%[base])          \n" /* get GP via mailbox */
+		"   ld    $a1, 0x38(%[base])          \n"
+		"   jr    %[initfunc]                 \n" /* jump to initial PC */
+		"   nop                               \n"
+		"   .set pop                          \n"
+		: [core] "=&r" (core), [node] "=&r" (node),
+		  [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+		  [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+		: /* No Input */
+		: "a1");
+}
+
 void play_dead(void)
 {
 	int *state_addr;
@@ -382,13 +544,48 @@
 	void (*play_dead_at_ckseg1)(int *);
 
 	idle_task_exit();
-	play_dead_at_ckseg1 =
-		(void *)CKSEG1ADDR((unsigned long)loongson3_play_dead);
+	switch (loongson_sysconf.cputype) {
+	case Loongson_3A:
+	default:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+		break;
+	case Loongson_3B:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
+		break;
+	}
 	state_addr = &per_cpu(cpu_state, cpu);
 	mb();
 	play_dead_at_ckseg1(state_addr);
 }
 
+void loongson3_disable_clock(int cpu)
+{
+	uint64_t core_id = cpu_data[cpu].core;
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if (loongson_sysconf.cputype == Loongson_3A) {
+		LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
+	} else if (loongson_sysconf.cputype == Loongson_3B) {
+		if (!cpuhotplug_workaround)
+			LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
+	}
+}
+
+void loongson3_enable_clock(int cpu)
+{
+	uint64_t core_id = cpu_data[cpu].core;
+	uint64_t package_id = cpu_data[cpu].package;
+
+	if (loongson_sysconf.cputype == Loongson_3A) {
+		LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
+	} else if (loongson_sysconf.cputype == Loongson_3B) {
+		if (!cpuhotplug_workaround)
+			LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
+	}
+}
+
 #define CPU_POST_DEAD_FROZEN	(CPU_POST_DEAD | CPU_TASKS_FROZEN)
 static int loongson3_cpu_callback(struct notifier_block *nfb,
 	unsigned long action, void *hcpu)
@@ -399,12 +596,12 @@
 	case CPU_POST_DEAD:
 	case CPU_POST_DEAD_FROZEN:
 		pr_info("Disable clock for CPU#%d\n", cpu);
-		LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu));
+		loongson3_disable_clock(cpu);
 		break;
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
 		pr_info("Enable clock for CPU#%d\n", cpu);
-		LOONGSON_CHIPCFG0 |= 1 << (12 + cpu);
+		loongson3_enable_clock(cpu);
 		break;
 	}
 
diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h
index 3453e8c..d98ff65 100644
--- a/arch/mips/loongson/loongson-3/smp.h
+++ b/arch/mips/loongson/loongson-3/smp.h
@@ -1,29 +1,30 @@
 #ifndef __LOONGSON_SMP_H_
 #define __LOONGSON_SMP_H_
 
-/* for Loongson-3A smp support */
+/* for Loongson-3 smp support */
+extern unsigned long long smp_group[4];
 
 /* 4 groups(nodes) in maximum in numa case */
-#define  SMP_CORE_GROUP0_BASE    0x900000003ff01000
-#define  SMP_CORE_GROUP1_BASE    0x900010003ff01000
-#define  SMP_CORE_GROUP2_BASE    0x900020003ff01000
-#define  SMP_CORE_GROUP3_BASE    0x900030003ff01000
+#define SMP_CORE_GROUP0_BASE	(smp_group[0])
+#define SMP_CORE_GROUP1_BASE	(smp_group[1])
+#define SMP_CORE_GROUP2_BASE	(smp_group[2])
+#define SMP_CORE_GROUP3_BASE	(smp_group[3])
 
 /* 4 cores in each group(node) */
-#define  SMP_CORE0_OFFSET  0x000
-#define  SMP_CORE1_OFFSET  0x100
-#define  SMP_CORE2_OFFSET  0x200
-#define  SMP_CORE3_OFFSET  0x300
+#define SMP_CORE0_OFFSET  0x000
+#define SMP_CORE1_OFFSET  0x100
+#define SMP_CORE2_OFFSET  0x200
+#define SMP_CORE3_OFFSET  0x300
 
 /* ipi registers offsets */
-#define  STATUS0  0x00
-#define  EN0      0x04
-#define  SET0     0x08
-#define  CLEAR0   0x0c
-#define  STATUS1  0x10
-#define  MASK1    0x14
-#define  SET1     0x18
-#define  CLEAR1   0x1c
-#define  BUF      0x20
+#define STATUS0  0x00
+#define EN0      0x04
+#define SET0     0x08
+#define CLEAR0   0x0c
+#define STATUS1  0x10
+#define MASK1    0x14
+#define SET1     0x18
+#define CLEAR1   0x1c
+#define BUF      0x20
 
 #endif
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index f2e8302..fbcd867 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1230,19 +1230,19 @@
 	case CPU_R14000:
 		break;
 
+	case CPU_74K:
+	case CPU_1074K:
+		alias_74k_erratum(c);
+		/* Fall through. */
 	case CPU_M14KC:
 	case CPU_M14KEC:
 	case CPU_24K:
 	case CPU_34K:
-	case CPU_74K:
 	case CPU_1004K:
-	case CPU_1074K:
 	case CPU_INTERAPTIV:
 	case CPU_P5600:
 	case CPU_PROAPTIV:
 	case CPU_M5150:
-		if ((c->cputype == CPU_74K) || (c->cputype == CPU_1074K))
-			alias_74k_erratum(c);
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 6e44133..571aab0 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -325,6 +325,38 @@
 #endif
 }
 
+unsigned __weak platform_maar_init(unsigned num_maars)
+{
+	return 0;
+}
+
+static void maar_init(void)
+{
+	unsigned num_maars, used, i;
+
+	if (!cpu_has_maar)
+		return;
+
+	/* Detect the number of MAARs */
+	write_c0_maari(~0);
+	back_to_back_c0_hazard();
+	num_maars = read_c0_maari() + 1;
+
+	/* MAARs should be in pairs */
+	WARN_ON(num_maars % 2);
+
+	/* Configure the required MAARs */
+	used = platform_maar_init(num_maars / 2);
+
+	/* Disable any further MAARs */
+	for (i = (used * 2); i < num_maars; i++) {
+		write_c0_maari(i);
+		back_to_back_c0_hazard();
+		write_c0_maar(0);
+		back_to_back_c0_hazard();
+	}
+}
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
@@ -337,6 +369,7 @@
 #endif
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
+	maar_init();
 	free_all_bootmem();
 	setup_zero_pages();	/* Setup zeroed pages.  */
 	mem_init_free_highmem();
diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
index d657493..4094bbd 100644
--- a/arch/mips/mm/tlb-r3k.c
+++ b/arch/mips/mm/tlb-r3k.c
@@ -158,7 +158,7 @@
 {
 	int cpu = smp_processor_id();
 
-	if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+	if (cpu_context(cpu, vma->vm_mm) != 0) {
 		unsigned long flags;
 		int oldpid, newpid, idx;
 
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 3914e27..fa6ebd4 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -57,6 +57,7 @@
 	local_irq_save(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
+	htw_stop();
 	write_c0_entrylo0(0);
 	write_c0_entrylo1(0);
 
@@ -90,6 +91,7 @@
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
+	htw_start();
 	flush_itlb();
 	local_irq_restore(flags);
 }
@@ -131,6 +133,7 @@
 			int oldpid = read_c0_entryhi();
 			int newpid = cpu_asid(cpu, mm);
 
+			htw_stop();
 			while (start < end) {
 				int idx;
 
@@ -151,6 +154,7 @@
 			}
 			tlbw_use_hazard();
 			write_c0_entryhi(oldpid);
+			htw_start();
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
@@ -174,6 +178,7 @@
 		start &= (PAGE_MASK << 1);
 		end += ((PAGE_SIZE << 1) - 1);
 		end &= (PAGE_MASK << 1);
+		htw_stop();
 
 		while (start < end) {
 			int idx;
@@ -195,6 +200,7 @@
 		}
 		tlbw_use_hazard();
 		write_c0_entryhi(pid);
+		htw_start();
 	} else {
 		local_flush_tlb_all();
 	}
@@ -214,6 +220,7 @@
 		page &= (PAGE_MASK << 1);
 		local_irq_save(flags);
 		oldpid = read_c0_entryhi();
+		htw_stop();
 		write_c0_entryhi(page | newpid);
 		mtc0_tlbw_hazard();
 		tlb_probe();
@@ -231,6 +238,7 @@
 
 	finish:
 		write_c0_entryhi(oldpid);
+		htw_start();
 		flush_itlb_vm(vma);
 		local_irq_restore(flags);
 	}
@@ -247,6 +255,7 @@
 
 	local_irq_save(flags);
 	oldpid = read_c0_entryhi();
+	htw_stop();
 	page &= (PAGE_MASK << 1);
 	write_c0_entryhi(page);
 	mtc0_tlbw_hazard();
@@ -263,6 +272,7 @@
 		tlbw_use_hazard();
 	}
 	write_c0_entryhi(oldpid);
+	htw_start();
 	flush_itlb();
 	local_irq_restore(flags);
 }
@@ -351,6 +361,7 @@
 	local_irq_save(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = read_c0_entryhi();
+	htw_stop();
 	old_pagemask = read_c0_pagemask();
 	wired = read_c0_wired();
 	write_c0_wired(wired + 1);
@@ -366,6 +377,7 @@
 
 	write_c0_entryhi(old_ctx);
 	tlbw_use_hazard();	/* What is the hazard here? */
+	htw_start();
 	write_c0_pagemask(old_pagemask);
 	local_flush_tlb_all();
 	local_irq_restore(flags);
@@ -391,6 +403,51 @@
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
 
+/*
+ * Used for loading TLB entries before trap_init() has started, when we
+ * don't actually want to add a wired entry which remains throughout the
+ * lifetime of the system
+ */
+
+int temp_tlb_entry __cpuinitdata;
+
+__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
+			       unsigned long entryhi, unsigned long pagemask)
+{
+	int ret = 0;
+	unsigned long flags;
+	unsigned long wired;
+	unsigned long old_pagemask;
+	unsigned long old_ctx;
+
+	local_irq_save(flags);
+	/* Save old context and create impossible VPN2 value */
+	old_ctx = read_c0_entryhi();
+	old_pagemask = read_c0_pagemask();
+	wired = read_c0_wired();
+	if (--temp_tlb_entry < wired) {
+		printk(KERN_WARNING
+		       "No TLB space left for add_temporary_entry\n");
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	write_c0_index(temp_tlb_entry);
+	write_c0_pagemask(pagemask);
+	write_c0_entryhi(entryhi);
+	write_c0_entrylo0(entrylo0);
+	write_c0_entrylo1(entrylo1);
+	mtc0_tlbw_hazard();
+	tlb_write_indexed();
+	tlbw_use_hazard();
+
+	write_c0_entryhi(old_ctx);
+	write_c0_pagemask(old_pagemask);
+out:
+	local_irq_restore(flags);
+	return ret;
+}
+
 static int ntlb;
 static int __init set_ntlb(char *str)
 {
@@ -431,6 +488,8 @@
 		write_c0_pagegrain(pg);
 	}
 
+	temp_tlb_entry = current_cpu_data.tlbsize - 1;
+
 	/* From this point on the ARC firmware is dead.	 */
 	local_flush_tlb_all();
 
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index cf8a952..a08dd53 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -1922,7 +1922,7 @@
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 
-	if (cpu_has_rixi) {
+	if (cpu_has_rixi && !cpu_has_rixiex) {
 		/*
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
@@ -1989,7 +1989,7 @@
 	build_pte_present(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbl);
 	build_tlb_probe_entry(&p);
 
-	if (cpu_has_rixi) {
+	if (cpu_has_rixi && !cpu_has_rixiex) {
 		/*
 		 * If the page is not _PAGE_VALID, RI or XI could not
 		 * have triggered it.  Skip the expensive test..
@@ -2197,6 +2197,94 @@
 			   (unsigned long)tlbmiss_handler_setup_pgd_end);
 }
 
+static void print_htw_config(void)
+{
+	unsigned long config;
+	unsigned int pwctl;
+	const int field = 2 * sizeof(unsigned long);
+
+	config = read_c0_pwfield();
+	pr_debug("PWField (0x%0*lx): GDI: 0x%02lx  UDI: 0x%02lx  MDI: 0x%02lx  PTI: 0x%02lx  PTEI: 0x%02lx\n",
+		field, config,
+		(config & MIPS_PWFIELD_GDI_MASK) >> MIPS_PWFIELD_GDI_SHIFT,
+		(config & MIPS_PWFIELD_UDI_MASK) >> MIPS_PWFIELD_UDI_SHIFT,
+		(config & MIPS_PWFIELD_MDI_MASK) >> MIPS_PWFIELD_MDI_SHIFT,
+		(config & MIPS_PWFIELD_PTI_MASK) >> MIPS_PWFIELD_PTI_SHIFT,
+		(config & MIPS_PWFIELD_PTEI_MASK) >> MIPS_PWFIELD_PTEI_SHIFT);
+
+	config = read_c0_pwsize();
+	pr_debug("PWSize  (0x%0*lx): GDW: 0x%02lx  UDW: 0x%02lx  MDW: 0x%02lx  PTW: 0x%02lx  PTEW: 0x%02lx\n",
+		field, config,
+		(config & MIPS_PWSIZE_GDW_MASK) >> MIPS_PWSIZE_GDW_SHIFT,
+		(config & MIPS_PWSIZE_UDW_MASK) >> MIPS_PWSIZE_UDW_SHIFT,
+		(config & MIPS_PWSIZE_MDW_MASK) >> MIPS_PWSIZE_MDW_SHIFT,
+		(config & MIPS_PWSIZE_PTW_MASK) >> MIPS_PWSIZE_PTW_SHIFT,
+		(config & MIPS_PWSIZE_PTEW_MASK) >> MIPS_PWSIZE_PTEW_SHIFT);
+
+	pwctl = read_c0_pwctl();
+	pr_debug("PWCtl   (0x%x): PWEn: 0x%x  DPH: 0x%x  HugePg: 0x%x  Psn: 0x%x\n",
+		pwctl,
+		(pwctl & MIPS_PWCTL_PWEN_MASK) >> MIPS_PWCTL_PWEN_SHIFT,
+		(pwctl & MIPS_PWCTL_DPH_MASK) >> MIPS_PWCTL_DPH_SHIFT,
+		(pwctl & MIPS_PWCTL_HUGEPG_MASK) >> MIPS_PWCTL_HUGEPG_SHIFT,
+		(pwctl & MIPS_PWCTL_PSN_MASK) >> MIPS_PWCTL_PSN_SHIFT);
+}
+
+static void config_htw_params(void)
+{
+	unsigned long pwfield, pwsize, ptei;
+	unsigned int config;
+
+	/*
+	 * We are using 2-level page tables, so we only need to
+	 * setup GDW and PTW appropriately. UDW and MDW will remain 0.
+	 * The default value of GDI/UDI/MDI/PTI is 0xc. It is illegal to
+	 * write values less than 0xc in these fields because the entire
+	 * write will be dropped. As a result of which, we must preserve
+	 * the original reset values and overwrite only what we really want.
+	 */
+
+	pwfield = read_c0_pwfield();
+	/* re-initialize the GDI field */
+	pwfield &= ~MIPS_PWFIELD_GDI_MASK;
+	pwfield |= PGDIR_SHIFT << MIPS_PWFIELD_GDI_SHIFT;
+	/* re-initialize the PTI field including the even/odd bit */
+	pwfield &= ~MIPS_PWFIELD_PTI_MASK;
+	pwfield |= PAGE_SHIFT << MIPS_PWFIELD_PTI_SHIFT;
+	/* Set the PTEI right shift */
+	ptei = _PAGE_GLOBAL_SHIFT << MIPS_PWFIELD_PTEI_SHIFT;
+	pwfield |= ptei;
+	write_c0_pwfield(pwfield);
+	/* Check whether the PTEI value is supported */
+	back_to_back_c0_hazard();
+	pwfield = read_c0_pwfield();
+	if (((pwfield & MIPS_PWFIELD_PTEI_MASK) << MIPS_PWFIELD_PTEI_SHIFT)
+		!= ptei) {
+		pr_warn("Unsupported PTEI field value: 0x%lx. HTW will not be enabled",
+			ptei);
+		/*
+		 * Drop option to avoid HTW being enabled via another path
+		 * (eg htw_reset())
+		 */
+		current_cpu_data.options &= ~MIPS_CPU_HTW;
+		return;
+	}
+
+	pwsize = ilog2(PTRS_PER_PGD) << MIPS_PWSIZE_GDW_SHIFT;
+	pwsize |= ilog2(PTRS_PER_PTE) << MIPS_PWSIZE_PTW_SHIFT;
+	write_c0_pwsize(pwsize);
+
+	/* Make sure everything is set before we enable the HTW */
+	back_to_back_c0_hazard();
+
+	/* Enable HTW and disable the rest of the pwctl fields */
+	config = 1 << MIPS_PWCTL_PWEN_SHIFT;
+	write_c0_pwctl(config);
+	pr_info("Hardware Page Table Walker enabled\n");
+
+	print_htw_config();
+}
+
 void build_tlb_refill_handler(void)
 {
 	/*
@@ -2261,5 +2349,8 @@
 		}
 		if (cpu_has_local_ebase)
 			build_r4000_tlb_refill_handler();
+		if (cpu_has_htw)
+			config_htw_params();
+
 	}
 }
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index ecc2785..e4f43ba 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -42,6 +42,10 @@
 
 static DEFINE_RAW_SPINLOCK(mips_irq_lock);
 
+#ifdef CONFIG_MIPS_GIC_IPI
+DECLARE_BITMAP(ipi_ints, GIC_NUM_INTRS);
+#endif
+
 static inline int mips_pcibios_iack(void)
 {
 	int irq;
@@ -125,16 +129,22 @@
 
 static void malta_ipi_irqdispatch(void)
 {
-	int irq;
+#ifdef CONFIG_MIPS_GIC_IPI
+	unsigned long irq;
+	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
 
+	gic_get_int_mask(pending, ipi_ints);
+
+	irq = find_first_bit(pending, GIC_NUM_INTRS);
+
+	while (irq < GIC_NUM_INTRS) {
+		do_IRQ(MIPS_GIC_IRQ_BASE + irq);
+
+		irq = find_next_bit(pending, GIC_NUM_INTRS, irq + 1);
+	}
+#endif
 	if (gic_compare_int())
 		do_IRQ(MIPS_GIC_IRQ_BASE);
-
-	irq = gic_get_int();
-	if (irq < 0)
-		return;	 /* interrupt has already been cleared */
-
-	do_IRQ(MIPS_GIC_IRQ_BASE + irq);
 }
 
 static void corehi_irqdispatch(void)
@@ -427,8 +437,9 @@
 	gic_intr_map[intr].pin = cpupin;
 	gic_intr_map[intr].polarity = GIC_POL_POS;
 	gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
-	gic_intr_map[intr].flags = GIC_FLAG_IPI;
+	gic_intr_map[intr].flags = 0;
 	ipi_map[cpu] |= (1 << (cpupin + 2));
+	bitmap_set(ipi_ints, intr, 1);
 }
 
 static void __init fill_ipi_map(void)
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 6d97730..0c35dee0 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -16,6 +16,7 @@
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/maar.h>
 #include <asm/sections.h>
 #include <asm/fw/fw.h>
 
@@ -164,3 +165,28 @@
 				addr, addr + boot_mem_map.map[i].size);
 	}
 }
+
+unsigned platform_maar_init(unsigned num_pairs)
+{
+	phys_addr_t mem_end = (physical_memsize & ~0xffffull) - 1;
+	struct maar_config cfg[] = {
+		/* DRAM preceding I/O */
+		{ 0x00000000, 0x0fffffff, MIPS_MAAR_S },
+
+		/* DRAM following I/O */
+		{ 0x20000000, mem_end, MIPS_MAAR_S },
+
+		/* DRAM alias in upper half of physical */
+		{ 0x80000000, 0x80000000 + mem_end, MIPS_MAAR_S },
+	};
+	unsigned i, num_cfg = ARRAY_SIZE(cfg);
+
+	/* If DRAM fits before I/O, drop the region following it */
+	if (physical_memsize <= 0x10000000) {
+		num_cfg--;
+		for (i = 1; i < num_cfg; i++)
+			cfg[i] = cfg[i + 1];
+	}
+
+	return maar_config(cfg, num_cfg, num_pairs);
+}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index ff8a553..6523d55 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -29,7 +29,7 @@
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
 obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
 obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_LEMOTE_MACH3A)	+= fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_LOONGSON_MACH3X)	+= fixup-loongson3.o ops-loongson3.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o pci-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 0e046d8..d54ea93 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -199,8 +199,6 @@
 
 char *tx4927_pcibios_setup(char *str)
 {
-	unsigned long val;
-
 	if (!strncmp(str, "trdyto=", 7)) {
 		u8 val = 0;
 		if (kstrtou8(str + 7, 0, &val) == 0)
diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index 563d1f6..c19600a 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -7,6 +7,7 @@
  * Support for all devices (greater than 16) added by David Gathright.
  */
 
+#include <linux/clk.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -364,6 +365,7 @@
 	void __iomem *virt_io;
 	unsigned long val;
 	struct resource *r;
+	struct clk *c;
 	int ret;
 
 	/* need at least PCI IRQ mapping table */
@@ -393,11 +395,24 @@
 		goto out1;
 	}
 
+	c = clk_get(&pdev->dev, "pci_clko");
+	if (IS_ERR(c)) {
+		dev_err(&pdev->dev, "unable to find PCI clock\n");
+		ret = PTR_ERR(c);
+		goto out2;
+	}
+
+	ret = clk_prepare_enable(c);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot enable PCI clock\n");
+		goto out6;
+	}
+
 	ctx->regs = ioremap_nocache(r->start, resource_size(r));
 	if (!ctx->regs) {
 		dev_err(&pdev->dev, "cannot map pci regs\n");
 		ret = -ENODEV;
-		goto out2;
+		goto out5;
 	}
 
 	/* map parts of the PCI IO area */
@@ -465,12 +480,19 @@
 	register_syscore_ops(&alchemy_pci_pmops);
 	register_pci_controller(&ctx->alchemy_pci_ctrl);
 
+	dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
+		 clk_get_rate(c) / 1000000);
+
 	return 0;
 
 out4:
 	iounmap(virt_io);
 out3:
 	iounmap(ctx->regs);
+out5:
+	clk_disable_unprepare(c);
+out6:
+	clk_put(c);
 out2:
 	release_mem_region(r->start, resource_size(r));
 out1:
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index 2513952..7c4598c 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -81,7 +81,7 @@
 		panic("device tree not present");
 
 	strlcpy(of_ids[0].compatible, soc_info.compatible, len);
-	strncpy(of_ids[1].compatible, "palmbus", len);
+	strlcpy(of_ids[1].compatible, "palmbus", len);
 
 	if (of_platform_populate(NULL, of_ids, NULL, NULL))
 		panic("failed to populate DT");
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index ba61268..e31e8cd 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -251,28 +251,6 @@
 	&rb532_wdt
 };
 
-static void __init parse_mac_addr(char *macstr)
-{
-	int i, h, l;
-
-	for (i = 0; i < 6; i++) {
-		if (i != 5 && *(macstr + 2) != ':')
-			return;
-
-		h = hex_to_bin(*macstr++);
-		if (h == -1)
-			return;
-
-		l = hex_to_bin(*macstr++);
-		if (l == -1)
-			return;
-
-		macstr++;
-		korina_dev0_data.mac[i] = (h << 4) + l;
-	}
-}
-
-
 /* NAND definitions */
 #define NAND_CHIP_DELAY 25
 
@@ -334,7 +312,10 @@
 static int __init setup_kmac(char *s)
 {
 	printk(KERN_INFO "korina mac = %s\n", s);
-	parse_mac_addr(s);
+	if (!mac_pton(s, korina_dev0_data.mac)) {
+		printk(KERN_ERR "Invalid mac\n");
+		return -EINVAL;
+	}
 	return 0;
 }
 
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 2871327..a77698f 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -268,7 +268,7 @@
 	return err;
 }
 
-static void quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __init_refok quirk_slc90e66_bridge(struct pci_dev *dev)
 {
 	int irq;	/* PCI/ISA Bridge interrupt */
 	u8 reg_64;
@@ -331,7 +331,7 @@
 	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
 	 */
 	dat |= 0x01;
-	pci_write_config_byte(dev, regs[i], dat);
+	pci_write_config_byte(dev, 0x5c, dat);
 	pci_read_config_byte(dev, 0x5c, &dat);
 	printk(KERN_CONT " REG5C %02x", dat);
 	printk(KERN_CONT "\n");
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index d4add86..9fa1772 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -148,9 +148,9 @@
 	u32 cpu_freq;
 
 	spin_lock_irqsave(&loongson2_wait_lock, flags);
-	cpu_freq = LOONGSON_CHIPCFG0;
-	LOONGSON_CHIPCFG0 &= ~0x7;	/* Put CPU into wait mode */
-	LOONGSON_CHIPCFG0 = cpu_freq;	/* Restore CPU state */
+	cpu_freq = LOONGSON_CHIPCFG(0);
+	LOONGSON_CHIPCFG(0) &= ~0x7;	/* Put CPU into wait mode */
+	LOONGSON_CHIPCFG(0) = cpu_freq;	/* Restore CPU state */
 	spin_unlock_irqrestore(&loongson2_wait_lock, flags);
 	local_irq_enable();
 }
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f5443a6..9c9f6af 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -32,6 +32,7 @@
  * (the low to high transition will not occur).
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -90,7 +91,7 @@
 	struct mmc_request *mrq;
 
 	u32 flags;
-	u32 iobase;
+	void __iomem *iobase;
 	u32 clock;
 	u32 bus_width;
 	u32 power_mode;
@@ -118,6 +119,7 @@
 	struct au1xmmc_platform_data *platdata;
 	struct platform_device *pdev;
 	struct resource *ioarea;
+	struct clk *clk;
 };
 
 /* Status flags used by the host structure */
@@ -162,32 +164,33 @@
 
 static inline void IRQ_ON(struct au1xmmc_host *host, u32 mask)
 {
-	u32 val = au_readl(HOST_CONFIG(host));
+	u32 val = __raw_readl(HOST_CONFIG(host));
 	val |= mask;
-	au_writel(val, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void FLUSH_FIFO(struct au1xmmc_host *host)
 {
-	u32 val = au_readl(HOST_CONFIG2(host));
+	u32 val = __raw_readl(HOST_CONFIG2(host));
 
-	au_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
-	au_sync_delay(1);
+	__raw_writel(val | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
 	/* SEND_STOP will turn off clock control - this re-enables it */
 	val &= ~SD_CONFIG2_DF;
 
-	au_writel(val, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void IRQ_OFF(struct au1xmmc_host *host, u32 mask)
 {
-	u32 val = au_readl(HOST_CONFIG(host));
+	u32 val = __raw_readl(HOST_CONFIG(host));
 	val &= ~mask;
-	au_writel(val, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(val, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static inline void SEND_STOP(struct au1xmmc_host *host)
@@ -197,12 +200,13 @@
 	WARN_ON(host->status != HOST_S_DATA);
 	host->status = HOST_S_STOP;
 
-	config2 = au_readl(HOST_CONFIG2(host));
-	au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
-	au_sync();
+	config2 = __raw_readl(HOST_CONFIG2(host));
+	__raw_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	/* Send the stop command */
-	au_writel(STOP_CMD, HOST_CMD(host));
+	__raw_writel(STOP_CMD, HOST_CMD(host));
+	wmb(); /* drain writebuffer */
 }
 
 static void au1xmmc_set_power(struct au1xmmc_host *host, int state)
@@ -296,28 +300,28 @@
 		}
 	}
 
-	au_writel(cmd->arg, HOST_CMDARG(host));
-	au_sync();
+	__raw_writel(cmd->arg, HOST_CMDARG(host));
+	wmb(); /* drain writebuffer */
 
 	if (wait)
 		IRQ_OFF(host, SD_CONFIG_CR);
 
-	au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
-	au_sync();
+	__raw_writel((mmccmd | SD_CMD_GO), HOST_CMD(host));
+	wmb(); /* drain writebuffer */
 
 	/* Wait for the command to go on the line */
-	while (au_readl(HOST_CMD(host)) & SD_CMD_GO)
+	while (__raw_readl(HOST_CMD(host)) & SD_CMD_GO)
 		/* nop */;
 
 	/* Wait for the command to come back */
 	if (wait) {
-		u32 status = au_readl(HOST_STATUS(host));
+		u32 status = __raw_readl(HOST_STATUS(host));
 
 		while (!(status & SD_STATUS_CR))
-			status = au_readl(HOST_STATUS(host));
+			status = __raw_readl(HOST_STATUS(host));
 
 		/* Clear the CR status */
-		au_writel(SD_STATUS_CR, HOST_STATUS(host));
+		__raw_writel(SD_STATUS_CR, HOST_STATUS(host));
 
 		IRQ_ON(host, SD_CONFIG_CR);
 	}
@@ -339,11 +343,11 @@
 	data = mrq->cmd->data;
 
 	if (status == 0)
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 	/* The transaction is really over when the SD_STATUS_DB bit is clear */
 	while ((host->flags & HOST_F_XMIT) && (status & SD_STATUS_DB))
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 	data->error = 0;
 	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma.dir);
@@ -357,7 +361,7 @@
 		data->error = -EILSEQ;
 
 	/* Clear the CRC bits */
-	au_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
+	__raw_writel(SD_STATUS_WC | SD_STATUS_RC, HOST_STATUS(host));
 
 	data->bytes_xfered = 0;
 
@@ -380,7 +384,7 @@
 {
 	struct au1xmmc_host *host = (struct au1xmmc_host *)param;
 
-	u32 status = au_readl(HOST_STATUS(host));
+	u32 status = __raw_readl(HOST_STATUS(host));
 	au1xmmc_data_complete(host, status);
 }
 
@@ -412,15 +416,15 @@
 		max = AU1XMMC_MAX_TRANSFER;
 
 	for (count = 0; count < max; count++) {
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_TH))
 			break;
 
 		val = *sg_ptr++;
 
-		au_writel((unsigned long)val, HOST_TXPORT(host));
-		au_sync();
+		__raw_writel((unsigned long)val, HOST_TXPORT(host));
+		wmb(); /* drain writebuffer */
 	}
 
 	host->pio.len -= count;
@@ -472,7 +476,7 @@
 		max = AU1XMMC_MAX_TRANSFER;
 
 	for (count = 0; count < max; count++) {
-		status = au_readl(HOST_STATUS(host));
+		status = __raw_readl(HOST_STATUS(host));
 
 		if (!(status & SD_STATUS_NE))
 			break;
@@ -494,7 +498,7 @@
 			break;
 		}
 
-		val = au_readl(HOST_RXPORT(host));
+		val = __raw_readl(HOST_RXPORT(host));
 
 		if (sg_ptr)
 			*sg_ptr++ = (unsigned char)(val & 0xFF);
@@ -537,10 +541,10 @@
 
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136) {
-			r[0] = au_readl(host->iobase + SD_RESP3);
-			r[1] = au_readl(host->iobase + SD_RESP2);
-			r[2] = au_readl(host->iobase + SD_RESP1);
-			r[3] = au_readl(host->iobase + SD_RESP0);
+			r[0] = __raw_readl(host->iobase + SD_RESP3);
+			r[1] = __raw_readl(host->iobase + SD_RESP2);
+			r[2] = __raw_readl(host->iobase + SD_RESP1);
+			r[3] = __raw_readl(host->iobase + SD_RESP0);
 
 			/* The CRC is omitted from the response, so really
 			 * we only got 120 bytes, but the engine expects
@@ -559,7 +563,7 @@
 			 * that means that the OSR data starts at bit 31,
 			 * so we can just read RESP0 and return that.
 			 */
-			cmd->resp[0] = au_readl(host->iobase + SD_RESP0);
+			cmd->resp[0] = __raw_readl(host->iobase + SD_RESP0);
 		}
 	}
 
@@ -586,7 +590,7 @@
 			u32 mask = SD_STATUS_DB | SD_STATUS_NE;
 
 			while((status & mask) != mask)
-				status = au_readl(HOST_STATUS(host));
+				status = __raw_readl(HOST_STATUS(host));
 		}
 
 		au1xxx_dbdma_start(channel);
@@ -595,24 +599,17 @@
 
 static void au1xmmc_set_clock(struct au1xmmc_host *host, int rate)
 {
-	unsigned int pbus = get_au1x00_speed();
-	unsigned int divisor;
+	unsigned int pbus = clk_get_rate(host->clk);
+	unsigned int divisor = ((pbus / rate) / 2) - 1;
 	u32 config;
 
-	/* From databook:
-	 * divisor = ((((cpuclock / sbus_divisor) / 2) / mmcclock) / 2) - 1
-	 */
-	pbus /= ((au_readl(SYS_POWERCTRL) & 0x3) + 2);
-	pbus /= 2;
-	divisor = ((pbus / rate) / 2) - 1;
-
-	config = au_readl(HOST_CONFIG(host));
+	config = __raw_readl(HOST_CONFIG(host));
 
 	config &= ~(SD_CONFIG_DIV);
 	config |= (divisor & SD_CONFIG_DIV) | SD_CONFIG_DE;
 
-	au_writel(config, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(config, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 static int au1xmmc_prepare_data(struct au1xmmc_host *host,
@@ -636,7 +633,7 @@
 	if (host->dma.len == 0)
 		return -ETIMEDOUT;
 
-	au_writel(data->blksz - 1, HOST_BLKSIZE(host));
+	__raw_writel(data->blksz - 1, HOST_BLKSIZE(host));
 
 	if (host->flags & (HOST_F_DMA | HOST_F_DBDMA)) {
 		int i;
@@ -723,31 +720,34 @@
 static void au1xmmc_reset_controller(struct au1xmmc_host *host)
 {
 	/* Apply the clock */
-	au_writel(SD_ENABLE_CE, HOST_ENABLE(host));
-        au_sync_delay(1);
+	__raw_writel(SD_ENABLE_CE, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
-	au_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
-	au_sync_delay(5);
+	__raw_writel(SD_ENABLE_R | SD_ENABLE_CE, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
+	mdelay(5);
 
-	au_writel(~0, HOST_STATUS(host));
-	au_sync();
+	__raw_writel(~0, HOST_STATUS(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(0, HOST_BLKSIZE(host));
-	au_writel(0x001fffff, HOST_TIMEOUT(host));
-	au_sync();
+	__raw_writel(0, HOST_BLKSIZE(host));
+	__raw_writel(0x001fffff, HOST_TIMEOUT(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-        au_sync();
+	__raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
-	au_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
-	au_sync_delay(1);
+	__raw_writel(SD_CONFIG2_EN | SD_CONFIG2_FF, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
+	mdelay(1);
 
-	au_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(SD_CONFIG2_EN, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	/* Configure interrupts */
-	au_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
-	au_sync();
+	__raw_writel(AU1XMMC_INTERRUPTS, HOST_CONFIG(host));
+	wmb(); /* drain writebuffer */
 }
 
 
@@ -767,7 +767,7 @@
 		host->clock = ios->clock;
 	}
 
-	config2 = au_readl(HOST_CONFIG2(host));
+	config2 = __raw_readl(HOST_CONFIG2(host));
 	switch (ios->bus_width) {
 	case MMC_BUS_WIDTH_8:
 		config2 |= SD_CONFIG2_BB;
@@ -780,8 +780,8 @@
 		config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
 		break;
 	}
-	au_writel(config2, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(config2, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 }
 
 #define STATUS_TIMEOUT (SD_STATUS_RAT | SD_STATUS_DT)
@@ -793,7 +793,7 @@
 	struct au1xmmc_host *host = dev_id;
 	u32 status;
 
-	status = au_readl(HOST_STATUS(host));
+	status = __raw_readl(HOST_STATUS(host));
 
 	if (!(status & SD_STATUS_I))
 		return IRQ_NONE;	/* not ours */
@@ -839,8 +839,8 @@
 				status);
 	}
 
-	au_writel(status, HOST_STATUS(host));
-	au_sync();
+	__raw_writel(status, HOST_STATUS(host));
+	wmb(); /* drain writebuffer */
 
 	return IRQ_HANDLED;
 }
@@ -976,7 +976,7 @@
 		goto out1;
 	}
 
-	host->iobase = (unsigned long)ioremap(r->start, 0x3c);
+	host->iobase = ioremap(r->start, 0x3c);
 	if (!host->iobase) {
 		dev_err(&pdev->dev, "cannot remap mmio\n");
 		goto out2;
@@ -1025,6 +1025,16 @@
 		goto out3;
 	}
 
+	host->clk = clk_get(&pdev->dev, ALCHEMY_PERIPH_CLK);
+	if (IS_ERR(host->clk)) {
+		dev_err(&pdev->dev, "cannot find clock\n");
+		goto out_irq;
+	}
+	if (clk_prepare_enable(host->clk)) {
+		dev_err(&pdev->dev, "cannot enable clock\n");
+		goto out_clk;
+	}
+
 	host->status = HOST_S_IDLE;
 
 	/* board-specific carddetect setup, if any */
@@ -1075,7 +1085,7 @@
 
 	platform_set_drvdata(pdev, host);
 
-	pr_info(DRIVER_NAME ": MMC Controller %d set up at %8.8X"
+	pr_info(DRIVER_NAME ": MMC Controller %d set up at %p"
 		" (mode=%s)\n", pdev->id, host->iobase,
 		host->flags & HOST_F_DMA ? "dma" : "pio");
 
@@ -1087,10 +1097,10 @@
 		led_classdev_unregister(host->platdata->led);
 out5:
 #endif
-	au_writel(0, HOST_ENABLE(host));
-	au_writel(0, HOST_CONFIG(host));
-	au_writel(0, HOST_CONFIG2(host));
-	au_sync();
+	__raw_writel(0, HOST_ENABLE(host));
+	__raw_writel(0, HOST_CONFIG(host));
+	__raw_writel(0, HOST_CONFIG2(host));
+	wmb(); /* drain writebuffer */
 
 	if (host->flags & HOST_F_DBDMA)
 		au1xmmc_dbdma_shutdown(host);
@@ -1101,7 +1111,10 @@
 	if (host->platdata && host->platdata->cd_setup &&
 	    !(mmc->caps & MMC_CAP_NEEDS_POLL))
 		host->platdata->cd_setup(mmc, 0);
-
+out_clk:
+	clk_disable_unprepare(host->clk);
+	clk_put(host->clk);
+out_irq:
 	free_irq(host->irq, host);
 out3:
 	iounmap((void *)host->iobase);
@@ -1130,10 +1143,10 @@
 		    !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
 			host->platdata->cd_setup(host->mmc, 0);
 
-		au_writel(0, HOST_ENABLE(host));
-		au_writel(0, HOST_CONFIG(host));
-		au_writel(0, HOST_CONFIG2(host));
-		au_sync();
+		__raw_writel(0, HOST_ENABLE(host));
+		__raw_writel(0, HOST_CONFIG(host));
+		__raw_writel(0, HOST_CONFIG2(host));
+		wmb(); /* drain writebuffer */
 
 		tasklet_kill(&host->data_task);
 		tasklet_kill(&host->finish_task);
@@ -1143,6 +1156,9 @@
 
 		au1xmmc_set_power(host, 0);
 
+		clk_disable_unprepare(host->clk);
+		clk_put(host->clk);
+
 		free_irq(host->irq, host);
 		iounmap((void *)host->iobase);
 		release_resource(host->ioarea);
@@ -1158,11 +1174,11 @@
 {
 	struct au1xmmc_host *host = platform_get_drvdata(pdev);
 
-	au_writel(0, HOST_CONFIG2(host));
-	au_writel(0, HOST_CONFIG(host));
-	au_writel(0xffffffff, HOST_STATUS(host));
-	au_writel(0, HOST_ENABLE(host));
-	au_sync();
+	__raw_writel(0, HOST_CONFIG2(host));
+	__raw_writel(0, HOST_CONFIG(host));
+	__raw_writel(0xffffffff, HOST_STATUS(host));
+	__raw_writel(0, HOST_ENABLE(host));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index bc5c518..77d6c17 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -41,7 +41,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	u_char ret = readb(this->IO_ADDR_R);
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -56,7 +56,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	writeb(byte, this->IO_ADDR_W);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 /**
@@ -69,7 +69,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -84,7 +84,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 /**
@@ -97,7 +97,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	u16 ret = readw(this->IO_ADDR_R);
-	au_sync();
+	wmb(); /* drain writebuffer */
 	return ret;
 }
 
@@ -116,7 +116,7 @@
 
 	for (i = 0; i < len; i++) {
 		writeb(buf[i], this->IO_ADDR_W);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -135,7 +135,7 @@
 
 	for (i = 0; i < len; i++) {
 		buf[i] = readb(this->IO_ADDR_R);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -156,7 +156,7 @@
 
 	for (i = 0; i < len; i++) {
 		writew(p[i], this->IO_ADDR_W);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 
 }
@@ -178,7 +178,7 @@
 
 	for (i = 0; i < len; i++) {
 		p[i] = readw(this->IO_ADDR_R);
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 }
 
@@ -223,26 +223,23 @@
 
 	case NAND_CTL_SETNCE:
 		/* assert (force assert) chip enable */
-		au_writel((1 << (4 + ctx->cs)), MEM_STNDCTL);
+		alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
 		break;
 
 	case NAND_CTL_CLRNCE:
 		/* deassert chip enable */
-		au_writel(0, MEM_STNDCTL);
+		alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
 		break;
 	}
 
 	this->IO_ADDR_R = this->IO_ADDR_W;
 
-	/* Drain the writebuffer */
-	au_sync();
+	wmb(); /* Drain the writebuffer */
 }
 
 int au1550_device_ready(struct mtd_info *mtd)
 {
-	int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
-	au_sync();
-	return ret;
+	return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
 }
 
 /**
diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c
index a78e4c1..31c48a7 100644
--- a/drivers/net/ethernet/amd/au1000_eth.c
+++ b/drivers/net/ethernet/amd/au1000_eth.c
@@ -89,6 +89,124 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+/* AU1000 MAC registers and bits */
+#define MAC_CONTROL		0x0
+#  define MAC_RX_ENABLE		(1 << 2)
+#  define MAC_TX_ENABLE		(1 << 3)
+#  define MAC_DEF_CHECK		(1 << 5)
+#  define MAC_SET_BL(X)		(((X) & 0x3) << 6)
+#  define MAC_AUTO_PAD		(1 << 8)
+#  define MAC_DISABLE_RETRY	(1 << 10)
+#  define MAC_DISABLE_BCAST	(1 << 11)
+#  define MAC_LATE_COL		(1 << 12)
+#  define MAC_HASH_MODE		(1 << 13)
+#  define MAC_HASH_ONLY		(1 << 15)
+#  define MAC_PASS_ALL		(1 << 16)
+#  define MAC_INVERSE_FILTER	(1 << 17)
+#  define MAC_PROMISCUOUS	(1 << 18)
+#  define MAC_PASS_ALL_MULTI	(1 << 19)
+#  define MAC_FULL_DUPLEX	(1 << 20)
+#  define MAC_NORMAL_MODE	0
+#  define MAC_INT_LOOPBACK	(1 << 21)
+#  define MAC_EXT_LOOPBACK	(1 << 22)
+#  define MAC_DISABLE_RX_OWN	(1 << 23)
+#  define MAC_BIG_ENDIAN	(1 << 30)
+#  define MAC_RX_ALL		(1 << 31)
+#define MAC_ADDRESS_HIGH	0x4
+#define MAC_ADDRESS_LOW		0x8
+#define MAC_MCAST_HIGH		0xC
+#define MAC_MCAST_LOW		0x10
+#define MAC_MII_CNTRL		0x14
+#  define MAC_MII_BUSY		(1 << 0)
+#  define MAC_MII_READ		0
+#  define MAC_MII_WRITE		(1 << 1)
+#  define MAC_SET_MII_SELECT_REG(X) (((X) & 0x1f) << 6)
+#  define MAC_SET_MII_SELECT_PHY(X) (((X) & 0x1f) << 11)
+#define MAC_MII_DATA		0x18
+#define MAC_FLOW_CNTRL		0x1C
+#  define MAC_FLOW_CNTRL_BUSY	(1 << 0)
+#  define MAC_FLOW_CNTRL_ENABLE (1 << 1)
+#  define MAC_PASS_CONTROL	(1 << 2)
+#  define MAC_SET_PAUSE(X)	(((X) & 0xffff) << 16)
+#define MAC_VLAN1_TAG		0x20
+#define MAC_VLAN2_TAG		0x24
+
+/* Ethernet Controller Enable */
+#  define MAC_EN_CLOCK_ENABLE	(1 << 0)
+#  define MAC_EN_RESET0		(1 << 1)
+#  define MAC_EN_TOSS		(0 << 2)
+#  define MAC_EN_CACHEABLE	(1 << 3)
+#  define MAC_EN_RESET1		(1 << 4)
+#  define MAC_EN_RESET2		(1 << 5)
+#  define MAC_DMA_RESET		(1 << 6)
+
+/* Ethernet Controller DMA Channels */
+/* offsets from MAC_TX_RING_ADDR address */
+#define MAC_TX_BUFF0_STATUS	0x0
+#  define TX_FRAME_ABORTED	(1 << 0)
+#  define TX_JAB_TIMEOUT	(1 << 1)
+#  define TX_NO_CARRIER		(1 << 2)
+#  define TX_LOSS_CARRIER	(1 << 3)
+#  define TX_EXC_DEF		(1 << 4)
+#  define TX_LATE_COLL_ABORT	(1 << 5)
+#  define TX_EXC_COLL		(1 << 6)
+#  define TX_UNDERRUN		(1 << 7)
+#  define TX_DEFERRED		(1 << 8)
+#  define TX_LATE_COLL		(1 << 9)
+#  define TX_COLL_CNT_MASK	(0xF << 10)
+#  define TX_PKT_RETRY		(1 << 31)
+#define MAC_TX_BUFF0_ADDR	0x4
+#  define TX_DMA_ENABLE		(1 << 0)
+#  define TX_T_DONE		(1 << 1)
+#  define TX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
+#define MAC_TX_BUFF0_LEN	0x8
+#define MAC_TX_BUFF1_STATUS	0x10
+#define MAC_TX_BUFF1_ADDR	0x14
+#define MAC_TX_BUFF1_LEN	0x18
+#define MAC_TX_BUFF2_STATUS	0x20
+#define MAC_TX_BUFF2_ADDR	0x24
+#define MAC_TX_BUFF2_LEN	0x28
+#define MAC_TX_BUFF3_STATUS	0x30
+#define MAC_TX_BUFF3_ADDR	0x34
+#define MAC_TX_BUFF3_LEN	0x38
+
+/* offsets from MAC_RX_RING_ADDR */
+#define MAC_RX_BUFF0_STATUS	0x0
+#  define RX_FRAME_LEN_MASK	0x3fff
+#  define RX_WDOG_TIMER		(1 << 14)
+#  define RX_RUNT		(1 << 15)
+#  define RX_OVERLEN		(1 << 16)
+#  define RX_COLL		(1 << 17)
+#  define RX_ETHER		(1 << 18)
+#  define RX_MII_ERROR		(1 << 19)
+#  define RX_DRIBBLING		(1 << 20)
+#  define RX_CRC_ERROR		(1 << 21)
+#  define RX_VLAN1		(1 << 22)
+#  define RX_VLAN2		(1 << 23)
+#  define RX_LEN_ERROR		(1 << 24)
+#  define RX_CNTRL_FRAME	(1 << 25)
+#  define RX_U_CNTRL_FRAME	(1 << 26)
+#  define RX_MCAST_FRAME	(1 << 27)
+#  define RX_BCAST_FRAME	(1 << 28)
+#  define RX_FILTER_FAIL	(1 << 29)
+#  define RX_PACKET_FILTER	(1 << 30)
+#  define RX_MISSED_FRAME	(1 << 31)
+
+#  define RX_ERROR (RX_WDOG_TIMER | RX_RUNT | RX_OVERLEN |  \
+		    RX_COLL | RX_MII_ERROR | RX_CRC_ERROR | \
+		    RX_LEN_ERROR | RX_U_CNTRL_FRAME | RX_MISSED_FRAME)
+#define MAC_RX_BUFF0_ADDR	0x4
+#  define RX_DMA_ENABLE		(1 << 0)
+#  define RX_T_DONE		(1 << 1)
+#  define RX_GET_DMA_BUFFER(X)	(((X) >> 2) & 0x3)
+#  define RX_SET_BUFF_ADDR(X)	((X) & 0xffffffc0)
+#define MAC_RX_BUFF1_STATUS	0x10
+#define MAC_RX_BUFF1_ADDR	0x14
+#define MAC_RX_BUFF2_STATUS	0x20
+#define MAC_RX_BUFF2_ADDR	0x24
+#define MAC_RX_BUFF3_STATUS	0x30
+#define MAC_RX_BUFF3_ADDR	0x34
+
 /*
  * Theory of operation
  *
@@ -152,10 +270,12 @@
 
 	if (force_reset || (!aup->mac_enabled)) {
 		writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-		au_sync_delay(2);
+		wmb(); /* drain writebuffer */
+		mdelay(2);
 		writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
 				| MAC_EN_CLOCK_ENABLE), aup->enable);
-		au_sync_delay(2);
+		wmb(); /* drain writebuffer */
+		mdelay(2);
 
 		aup->mac_enabled = 1;
 	}
@@ -273,7 +393,8 @@
 	reg = readl(&aup->mac->control);
 	reg &= ~(MAC_RX_ENABLE | MAC_TX_ENABLE);
 	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
+	wmb(); /* drain writebuffer */
+	mdelay(10);
 }
 
 static void au1000_enable_rx_tx(struct net_device *dev)
@@ -286,7 +407,8 @@
 	reg = readl(&aup->mac->control);
 	reg |= (MAC_RX_ENABLE | MAC_TX_ENABLE);
 	writel(reg, &aup->mac->control);
-	au_sync_delay(10);
+	wmb(); /* drain writebuffer */
+	mdelay(10);
 }
 
 static void
@@ -336,7 +458,8 @@
 			reg |= MAC_DISABLE_RX_OWN;
 		}
 		writel(reg, &aup->mac->control);
-		au_sync_delay(1);
+		wmb(); /* drain writebuffer */
+		mdelay(1);
 
 		au1000_enable_rx_tx(dev);
 		aup->old_duplex = phydev->duplex;
@@ -500,9 +623,11 @@
 	au1000_hard_stop(dev);
 
 	writel(MAC_EN_CLOCK_ENABLE, aup->enable);
-	au_sync_delay(2);
+	wmb(); /* drain writebuffer */
+	mdelay(2);
 	writel(0, aup->enable);
-	au_sync_delay(2);
+	wmb(); /* drain writebuffer */
+	mdelay(2);
 
 	aup->tx_full = 0;
 	for (i = 0; i < NUM_RX_DMA; i++) {
@@ -652,7 +777,7 @@
 	for (i = 0; i < NUM_RX_DMA; i++)
 		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
 
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
@@ -669,7 +794,7 @@
 
 	writel(control, &aup->mac->control);
 	writel(0x8100, &aup->mac->vlan1_tag); /* activate vlan support */
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	spin_unlock_irqrestore(&aup->lock, flags);
 	return 0;
@@ -760,7 +885,7 @@
 		}
 		prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE);
 		aup->rx_head = (aup->rx_head + 1) & (NUM_RX_DMA - 1);
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/* next descriptor */
 		prxd = aup->rx_dma_ring[aup->rx_head];
@@ -808,7 +933,7 @@
 		au1000_update_tx_stats(dev, ptxd->status);
 		ptxd->buff_stat &= ~TX_T_DONE;
 		ptxd->len = 0;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		aup->tx_tail = (aup->tx_tail + 1) & (NUM_TX_DMA - 1);
 		ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -939,7 +1064,7 @@
 	ps->tx_bytes += ptxd->len;
 
 	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	dev_kfree_skb(skb);
 	aup->tx_head = (aup->tx_head + 1) & (NUM_TX_DMA - 1);
 	return NETDEV_TX_OK;
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 5f91e3e..aab2cf7 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -18,6 +18,7 @@
  *  with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/interrupt.h>
@@ -175,6 +176,7 @@
 
 	struct resource *ioarea;
 	struct au1k_irda_platform_data *platdata;
+	struct clk *irda_clk;
 };
 
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -514,9 +516,39 @@
 static int au1k_init(struct net_device *dev)
 {
 	struct au1k_private *aup = netdev_priv(dev);
-	u32 enable, ring_address;
+	u32 enable, ring_address, phyck;
+	struct clk *c;
 	int i;
 
+	c = clk_get(NULL, "irda_clk");
+	if (IS_ERR(c))
+		return PTR_ERR(c);
+	i = clk_prepare_enable(c);
+	if (i) {
+		clk_put(c);
+		return i;
+	}
+
+	switch (clk_get_rate(c)) {
+	case 40000000:
+		phyck = IR_PHYCLK_40MHZ;
+		break;
+	case 48000000:
+		phyck = IR_PHYCLK_48MHZ;
+		break;
+	case 56000000:
+		phyck = IR_PHYCLK_56MHZ;
+		break;
+	case 64000000:
+		phyck = IR_PHYCLK_64MHZ;
+		break;
+	default:
+		clk_disable_unprepare(c);
+		clk_put(c);
+		return -EINVAL;
+	}
+	aup->irda_clk = c;
+
 	enable = IR_HC | IR_CE | IR_C;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
 	enable |= IR_BE;
@@ -545,7 +577,7 @@
 	irda_write(aup, IR_RING_SIZE,
 				(RING_SIZE_64 << 8) | (RING_SIZE_64 << 12));
 
-	irda_write(aup, IR_CONFIG_2, IR_PHYCLK_48MHZ | IR_ONE_PIN);
+	irda_write(aup, IR_CONFIG_2, phyck | IR_ONE_PIN);
 	irda_write(aup, IR_RING_ADDR_CMPR, 0);
 
 	au1k_irda_set_speed(dev, 9600);
@@ -619,6 +651,9 @@
 	free_irq(aup->irq_tx, dev);
 	free_irq(aup->irq_rx, dev);
 
+	clk_disable_unprepare(aup->irda_clk);
+	clk_put(aup->irda_clk);
+
 	return 0;
 }
 
@@ -853,6 +888,7 @@
 	struct au1k_private *aup;
 	struct net_device *dev;
 	struct resource *r;
+	struct clk *c;
 	int err;
 
 	dev = alloc_irdadev(sizeof(struct au1k_private));
@@ -886,6 +922,14 @@
 	if (!aup->ioarea)
 		goto out;
 
+	/* bail out early if clock doesn't exist */
+	c = clk_get(NULL, "irda_clk");
+	if (IS_ERR(c)) {
+		err = PTR_ERR(c);
+		goto out;
+	}
+	clk_put(c);
+
 	aup->iobase = ioremap_nocache(r->start, resource_size(r));
 	if (!aup->iobase)
 		goto out2;
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c
index ed526a1..fd25e23 100644
--- a/drivers/rtc/rtc-au1xxx.c
+++ b/drivers/rtc/rtc-au1xxx.c
@@ -32,7 +32,7 @@
 {
 	unsigned long t;
 
-	t = au_readl(SYS_TOYREAD);
+	t = alchemy_rdsys(AU1000_SYS_TOYREAD);
 
 	rtc_time_to_tm(t, tm);
 
@@ -45,13 +45,12 @@
 
 	rtc_tm_to_time(tm, &t);
 
-	au_writel(t, SYS_TOYWRITE);
-	au_sync();
+	alchemy_wrsys(t, AU1000_SYS_TOYWRITE);
 
 	/* wait for the pending register write to succeed.  This can
 	 * take up to 6 seconds...
 	 */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
 		msleep(1);
 
 	return 0;
@@ -68,7 +67,7 @@
 	unsigned long t;
 	int ret;
 
-	t = au_readl(SYS_COUNTER_CNTRL);
+	t = alchemy_rdsys(AU1000_SYS_CNTRCTRL);
 	if (!(t & CNTR_OK)) {
 		dev_err(&pdev->dev, "counters not working; aborting.\n");
 		ret = -ENODEV;
@@ -78,10 +77,10 @@
 	ret = -ETIMEDOUT;
 
 	/* set counter0 tickrate to 1Hz if necessary */
-	if (au_readl(SYS_TOYTRIM) != 32767) {
+	if (alchemy_rdsys(AU1000_SYS_TOYTRIM) != 32767) {
 		/* wait until hardware gives access to TRIM register */
 		t = 0x00100000;
-		while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && --t)
+		while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T0S) && --t)
 			msleep(1);
 
 		if (!t) {
@@ -93,12 +92,11 @@
 		}
 
 		/* set 1Hz TOY tick rate */
-		au_writel(32767, SYS_TOYTRIM);
-		au_sync();
+		alchemy_wrsys(32767, AU1000_SYS_TOYTRIM);
 	}
 
 	/* wait until the hardware allows writes to the counter reg */
-	while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+	while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C0S)
 		msleep(1);
 
 	rtcdev = devm_rtc_device_register(&pdev->dev, "rtc-au1xxx",
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index 67375a1..ffb42f1 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -141,13 +141,13 @@
 		  PSC_SPIMSK_MM | PSC_SPIMSK_RR | PSC_SPIMSK_RO
 		| PSC_SPIMSK_RU | PSC_SPIMSK_TR | PSC_SPIMSK_TO
 		| PSC_SPIMSK_TU | PSC_SPIMSK_SD | PSC_SPIMSK_MD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_spievent =
 		  PSC_SPIEVNT_MM | PSC_SPIEVNT_RR | PSC_SPIEVNT_RO
 		| PSC_SPIEVNT_RU | PSC_SPIEVNT_TR | PSC_SPIEVNT_TO
 		| PSC_SPIEVNT_TU | PSC_SPIEVNT_SD | PSC_SPIEVNT_MD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static void au1550_spi_reset_fifos(struct au1550_spi *hw)
@@ -155,10 +155,10 @@
 	u32 pcr;
 
 	hw->regs->psc_spipcr = PSC_SPIPCR_RC | PSC_SPIPCR_TC;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	do {
 		pcr = hw->regs->psc_spipcr;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while (pcr != 0);
 }
 
@@ -188,9 +188,9 @@
 		au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
 		cfg = hw->regs->psc_spicfg;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		if (spi->mode & SPI_CPOL)
 			cfg |= PSC_SPICFG_BI;
@@ -218,10 +218,10 @@
 		cfg |= au1550_spi_baudcfg(hw, spi->max_speed_hz);
 
 		hw->regs->psc_spicfg = cfg | PSC_SPICFG_DE_ENABLE;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		do {
 			stat = hw->regs->psc_spistat;
-			au_sync();
+			wmb(); /* drain writebuffer */
 		} while ((stat & PSC_SPISTAT_DR) == 0);
 
 		if (hw->pdata->activate_cs)
@@ -252,9 +252,9 @@
 	au1550_spi_bits_handlers_set(hw, spi->bits_per_word);
 
 	cfg = hw->regs->psc_spicfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	hw->regs->psc_spicfg = cfg & ~PSC_SPICFG_DE_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (hw->usedma && bpw <= 8)
 		cfg &= ~PSC_SPICFG_DD_DISABLE;
@@ -268,12 +268,12 @@
 	cfg |= au1550_spi_baudcfg(hw, hz);
 
 	hw->regs->psc_spicfg = cfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	if (cfg & PSC_SPICFG_DE_ENABLE) {
 		do {
 			stat = hw->regs->psc_spistat;
-			au_sync();
+			wmb(); /* drain writebuffer */
 		} while ((stat & PSC_SPISTAT_DR) == 0);
 	}
 
@@ -396,11 +396,11 @@
 
 	/* by default enable nearly all events interrupt */
 	hw->regs->psc_spimsk = PSC_SPIMSK_SD;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* start the transfer */
 	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	wait_for_completion(&hw->master_done);
 
@@ -429,7 +429,7 @@
 
 	stat = hw->regs->psc_spistat;
 	evnt = hw->regs->psc_spievent;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	if ((stat & PSC_SPISTAT_DI) == 0) {
 		dev_err(hw->dev, "Unexpected IRQ!\n");
 		return IRQ_NONE;
@@ -484,7 +484,7 @@
 static void au1550_spi_rx_word_##size(struct au1550_spi *hw)		\
 {									\
 	u32 fifoword = hw->regs->psc_spitxrx & (u32)(mask);		\
-	au_sync();							\
+	wmb(); /* drain writebuffer */					\
 	if (hw->rx) {							\
 		*(u##size *)hw->rx = (u##size)fifoword;			\
 		hw->rx += (size) / 8;					\
@@ -504,7 +504,7 @@
 	if (hw->tx_count >= hw->len)					\
 		fifoword |= PSC_SPITXRX_LC;				\
 	hw->regs->psc_spitxrx = fifoword;				\
-	au_sync();							\
+	wmb(); /* drain writebuffer */					\
 }
 
 AU1550_SPI_RX_WORD(8,0xff)
@@ -539,18 +539,18 @@
 		}
 
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		if (stat & PSC_SPISTAT_TF)
 			break;
 	}
 
 	/* enable event interrupts */
 	hw->regs->psc_spimsk = mask;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* start the transfer */
 	hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	wait_for_completion(&hw->master_done);
 
@@ -564,7 +564,7 @@
 
 	stat = hw->regs->psc_spistat;
 	evnt = hw->regs->psc_spievent;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	if ((stat & PSC_SPISTAT_DI) == 0) {
 		dev_err(hw->dev, "Unexpected IRQ!\n");
 		return IRQ_NONE;
@@ -594,7 +594,7 @@
 	do {
 		busy = 0;
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		/*
 		 * Take care to not let the Rx FIFO overflow.
@@ -615,7 +615,7 @@
 	} while (busy);
 
 	hw->regs->psc_spievent = PSC_SPIEVNT_RR | PSC_SPIEVNT_TR;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/*
 	 * Restart the SPI transmission in case of a transmit underflow.
@@ -634,9 +634,9 @@
 	 */
 	if (evnt & PSC_SPIEVNT_TU) {
 		hw->regs->psc_spievent = PSC_SPIEVNT_TU | PSC_SPIEVNT_MD;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		hw->regs->psc_spipcr = PSC_SPIPCR_MS;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	}
 
 	if (hw->rx_count >= hw->len) {
@@ -690,19 +690,19 @@
 
 	/* set up the PSC for SPI mode */
 	hw->regs->psc_ctrl = PSC_CTRL_DISABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	hw->regs->psc_sel = PSC_SEL_PS_SPIMODE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_spicfg = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	hw->regs->psc_ctrl = PSC_CTRL_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	do {
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while ((stat & PSC_SPISTAT_SR) == 0);
 
 
@@ -717,16 +717,16 @@
 #endif
 
 	hw->regs->psc_spicfg = cfg;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	au1550_spi_mask_ack_all(hw);
 
 	hw->regs->psc_spicfg |= PSC_SPICFG_DE_ENABLE;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	do {
 		stat = hw->regs->psc_spistat;
-		au_sync();
+		wmb(); /* drain writebuffer */
 	} while ((stat & PSC_SPISTAT_DR) == 0);
 
 	au1550_spi_reset_fifos(hw);
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 372d4ae..0676746e 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -41,6 +41,7 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -113,7 +114,7 @@
 	case VESA_NO_BLANKING:
 		/* Turn on panel */
 		fbdev->regs->lcd_control |= LCD_CONTROL_GO;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		break;
 
 	case VESA_VSYNC_SUSPEND:
@@ -121,7 +122,7 @@
 	case VESA_POWERDOWN:
 		/* Turn off panel */
 		fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
-		au_sync();
+		wmb(); /* drain writebuffer */
 		break;
 	default:
 		break;
@@ -434,7 +435,7 @@
 	struct au1100fb_device *fbdev = NULL;
 	struct resource *regs_res;
 	unsigned long page;
-	u32 sys_clksrc;
+	struct clk *c;
 
 	/* Allocate new device private */
 	fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
@@ -473,6 +474,13 @@
 	print_dbg("Register memory map at %p", fbdev->regs);
 	print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len);
 
+	c = clk_get(NULL, "lcd_intclk");
+	if (!IS_ERR(c)) {
+		fbdev->lcdclk = c;
+		clk_set_rate(c, 48000000);
+		clk_prepare_enable(c);
+	}
+
 	/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
 	fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
 		  	(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
@@ -506,10 +514,6 @@
 	print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
 	print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
 
-	/* Setup LCD clock to AUX (48 MHz) */
-	sys_clksrc = au_readl(SYS_CLKSRC) & ~(SYS_CS_ML_MASK | SYS_CS_DL | SYS_CS_CL);
-	au_writel((sys_clksrc | (1 << SYS_CS_ML_BIT)), SYS_CLKSRC);
-
 	/* load the panel info into the var struct */
 	au1100fb_var.bits_per_pixel = fbdev->panel->bpp;
 	au1100fb_var.xres = fbdev->panel->xres;
@@ -546,6 +550,10 @@
 	return 0;
 
 failed:
+	if (fbdev->lcdclk) {
+		clk_disable_unprepare(fbdev->lcdclk);
+		clk_put(fbdev->lcdclk);
+	}
 	if (fbdev->fb_mem) {
 		dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
 				     fbdev->fb_phys);
@@ -576,11 +584,15 @@
 
 	fb_dealloc_cmap(&fbdev->info.cmap);
 
+	if (fbdev->lcdclk) {
+		clk_disable_unprepare(fbdev->lcdclk);
+		clk_put(fbdev->lcdclk);
+	}
+
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static u32 sys_clksrc;
 static struct au1100fb_regs fbregs;
 
 int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state)
@@ -590,14 +602,11 @@
 	if (!fbdev)
 		return 0;
 
-	/* Save the clock source state */
-	sys_clksrc = au_readl(SYS_CLKSRC);
-
 	/* Blank the LCD */
 	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
 
-	/* Stop LCD clocking */
-	au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC);
+	if (fbdev->lcdclk)
+		clk_disable(fbdev->lcdclk);
 
 	memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs));
 
@@ -613,8 +622,8 @@
 
 	memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs));
 
-	/* Restart LCD clocking */
-	au_writel(sys_clksrc, SYS_CLKSRC);
+	if (fbdev->lcdclk)
+		clk_enable(fbdev->lcdclk);
 
 	/* Unblank the LCD */
 	au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info);
diff --git a/drivers/video/fbdev/au1100fb.h b/drivers/video/fbdev/au1100fb.h
index 12d9642d..9af1993 100644
--- a/drivers/video/fbdev/au1100fb.h
+++ b/drivers/video/fbdev/au1100fb.h
@@ -109,6 +109,7 @@
 	size_t	      		fb_len;
 	dma_addr_t    		fb_phys;
 	int			panel_idx;
+	struct clk		*lcdclk;
 };
 
 /********************************************************************/
diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c
index 4cfba78..40494db 100644
--- a/drivers/video/fbdev/au1200fb.c
+++ b/drivers/video/fbdev/au1200fb.c
@@ -30,6 +30,7 @@
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
@@ -330,9 +331,8 @@
 	uint32 mode_pwmhi;
 	uint32 mode_outmask;
 	uint32 mode_fifoctrl;
-	uint32 mode_toyclksrc;
 	uint32 mode_backlight;
-	uint32 mode_auxpll;
+	uint32 lcdclk;
 #define Xres min_xres
 #define Yres min_yres
 	u32	min_xres;		/* Minimum horizontal resolution */
@@ -379,9 +379,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		320, 320,
 		240, 240,
 	},
@@ -407,9 +406,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		640, 480,
 		640, 480,
 	},
@@ -435,9 +433,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		800, 800,
 		600, 600,
 	},
@@ -463,9 +460,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 6, /* 72MHz AUXPLL */
+		.lcdclk		= 72,
 		1024, 1024,
 		768, 768,
 	},
@@ -491,9 +487,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 10, /* 120MHz AUXPLL */
+		.lcdclk		= 120,
 		1280, 1280,
 		1024, 1024,
 	},
@@ -519,9 +514,8 @@
 		.mode_pwmhi		= 0x03400000, /* SCB 0x0 */
 		.mode_outmask	= 0x00FFFFFF,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		1024, 1024,
 		768, 768,
 	},
@@ -550,9 +544,8 @@
 		.mode_pwmhi		= 0x03400000,
 		.mode_outmask	= 0x00fcfcfc,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		640, 480,
 		640, 480,
 	},
@@ -581,9 +574,8 @@
 		.mode_pwmhi		= 0x03400000,
 		.mode_outmask	= 0x00fcfcfc,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96, /* 96MHz AUXPLL */
 		320, 320,
 		240, 240,
 	},
@@ -612,9 +604,8 @@
 		.mode_pwmhi		= 0x03400000,
 		.mode_outmask	= 0x00fcfcfc,
 		.mode_fifoctrl	= 0x2f2f2f2f,
-		.mode_toyclksrc	= 0x00000004, /* AUXPLL directly */
 		.mode_backlight	= 0x00000000,
-		.mode_auxpll		= 8, /* 96MHz AUXPLL */
+		.lcdclk		= 96,
 		856, 856,
 		480, 480,
 	},
@@ -646,9 +637,8 @@
 		.mode_pwmhi		= 0x00000000,
 		.mode_outmask		= 0x00FFFFFF,
 		.mode_fifoctrl		= 0x2f2f2f2f,
-		.mode_toyclksrc		= 0x00000004, /* AUXPLL directly */
 		.mode_backlight		= 0x00000000,
-		.mode_auxpll		= (48/12) * 2,
+		.lcdclk			= 96,
 		800, 800,
 		480, 480,
 	},
@@ -764,7 +754,7 @@
 
 	/* Disable the window while making changes, then restore WINEN */
 	winenable = lcd->winenable & (1 << plane);
-	au_sync();
+	wmb(); /* drain writebuffer */
 	lcd->winenable &= ~(1 << plane);
 	lcd->window[plane].winctrl0 = winctrl0;
 	lcd->window[plane].winctrl1 = winctrl1;
@@ -772,7 +762,7 @@
 	lcd->window[plane].winbuf1 = fbdev->fb_phys;
 	lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
 	lcd->winenable |= winenable;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
@@ -788,22 +778,21 @@
 	/* Make sure all windows disabled */
 	winenable = lcd->winenable;
 	lcd->winenable = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 	/*
 	 * Ensure everything is disabled before reconfiguring
 	 */
 	if (lcd->screen & LCD_SCREEN_SEN) {
 		/* Wait for vertical sync period */
 		lcd->intstatus = LCD_INT_SS;
-		while ((lcd->intstatus & LCD_INT_SS) == 0) {
-			au_sync();
-		}
+		while ((lcd->intstatus & LCD_INT_SS) == 0)
+			;
 
 		lcd->screen &= ~LCD_SCREEN_SEN;	/*disable the controller*/
 
 		do {
 			lcd->intstatus = lcd->intstatus; /*clear interrupts*/
-			au_sync();
+			wmb(); /* drain writebuffer */
 		/*wait for controller to shut down*/
 		} while ((lcd->intstatus & LCD_INT_SD) == 0);
 
@@ -829,11 +818,17 @@
 	 */
 	if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
 	{
-		uint32 sys_clksrc;
-		au_writel(panel->mode_auxpll, SYS_AUXPLL);
-		sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
-		sys_clksrc |= panel->mode_toyclksrc;
-		au_writel(sys_clksrc, SYS_CLKSRC);
+		struct clk *c = clk_get(NULL, "lcd_intclk");
+		long r, pc = panel->lcdclk * 1000000;
+
+		if (!IS_ERR(c)) {
+			r = clk_round_rate(c, pc);
+			if ((pc - r) < (pc / 10)) {	/* 10% slack */
+				clk_set_rate(c, r);
+				clk_prepare_enable(c);
+			}
+			clk_put(c);
+		}
 	}
 
 	/*
@@ -847,7 +842,7 @@
 	lcd->pwmhi = panel->mode_pwmhi;
 	lcd->outmask = panel->mode_outmask;
 	lcd->fifoctrl = panel->mode_fifoctrl;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* fixme: Check window settings to make sure still valid
 	 * for new geometry */
@@ -863,7 +858,7 @@
 	 * Re-enable screen now that it is configured
 	 */
 	lcd->screen |= LCD_SCREEN_SEN;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	/* Call init of panel */
 	if (pd->panel_init)
@@ -956,7 +951,7 @@
 		| LCD_WINCTRL2_SCY_1
 		) ;
 	lcd->winenable |= win->w[plane].mode_winenable;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 
@@ -1270,7 +1265,7 @@
 
 	if (pdata->flags & SCREEN_MASK)
 		lcd->colorkeymsk = pdata->mask;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
@@ -1288,7 +1283,7 @@
 	hi1 = (lcd->pwmhi >> 16) + 1;
 	divider = (lcd->pwmdiv & 0x3FFFF) + 1;
 	pdata->brightness = ((hi1 << 8) / divider) - 1;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static void set_window(unsigned int plane,
@@ -1387,7 +1382,7 @@
 		val |= (pdata->enable & 1) << plane;
 		lcd->winenable = val;
 	}
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static void get_window(unsigned int plane,
@@ -1414,7 +1409,7 @@
 	pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
 
 	pdata->enable = (lcd->winenable >> plane) & 1;
-	au_sync();
+	wmb(); /* drain writebuffer */
 }
 
 static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
@@ -1511,7 +1506,7 @@
 {
 	/* Nothing to do for now, just clear any pending interrupt */
 	lcd->intstatus = lcd->intstatus;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	return IRQ_HANDLED;
 }
@@ -1809,7 +1804,7 @@
 	au1200_setpanel(NULL, pd);
 
 	lcd->outmask = 0;
-	au_sync();
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 4baf2d7..8453531 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -145,35 +145,39 @@
 
 	uasm_i_mfc0(&p, K0, C0_STATUS);
 #ifdef CONFIG_HOTPLUG_CPU
-	uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
+	if (octeon_bootloader_entry_addr)
+		uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI),
+			      label_enter_bootloader);
 #endif
 	/* Force 64-bit addressing enabled */
 	uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
 	uasm_i_mtc0(&p, K0, C0_STATUS);
 
 #ifdef CONFIG_HOTPLUG_CPU
-	uasm_i_mfc0(&p, K0, C0_EBASE);
-	/* Coreid number in K0 */
-	uasm_i_andi(&p, K0, K0, 0xf);
-	/* 8 * coreid in bits 16-31 */
-	uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
-	uasm_i_ori(&p, K0, K0, 0x8001);
-	uasm_i_dsll_safe(&p, K0, K0, 16);
-	uasm_i_ori(&p, K0, K0, 0x0700);
-	uasm_i_drotr_safe(&p, K0, K0, 32);
-	/*
-	 * Should result in: 0x8001,0700,0000,8*coreid which is
-	 * CVMX_CIU_WDOGX(coreid) - 0x0500
-	 *
-	 * Now ld K0, CVMX_CIU_WDOGX(coreid)
-	 */
-	uasm_i_ld(&p, K0, 0x500, K0);
-	/*
-	 * If bit one set handle the NMI as a watchdog event.
-	 * otherwise transfer control to bootloader.
-	 */
-	uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
-	uasm_i_nop(&p);
+	if (octeon_bootloader_entry_addr) {
+		uasm_i_mfc0(&p, K0, C0_EBASE);
+		/* Coreid number in K0 */
+		uasm_i_andi(&p, K0, K0, 0xf);
+		/* 8 * coreid in bits 16-31 */
+		uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
+		uasm_i_ori(&p, K0, K0, 0x8001);
+		uasm_i_dsll_safe(&p, K0, K0, 16);
+		uasm_i_ori(&p, K0, K0, 0x0700);
+		uasm_i_drotr_safe(&p, K0, K0, 32);
+		/*
+		 * Should result in: 0x8001,0700,0000,8*coreid which is
+		 * CVMX_CIU_WDOGX(coreid) - 0x0500
+		 *
+		 * Now ld K0, CVMX_CIU_WDOGX(coreid)
+		 */
+		uasm_i_ld(&p, K0, 0x500, K0);
+		/*
+		 * If bit one set handle the NMI as a watchdog event.
+		 * otherwise transfer control to bootloader.
+		 */
+		uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
+		uasm_i_nop(&p);
+	}
 #endif
 
 	/* Clear Dcache so cvmseg works right. */
@@ -194,11 +198,13 @@
 	uasm_i_dmfc0(&p, K0, C0_DESAVE);
 
 #ifdef CONFIG_HOTPLUG_CPU
-	uasm_build_label(&l, p, label_enter_bootloader);
-	/* Jump to the bootloader and restore K0 */
-	UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
-	uasm_i_jr(&p, K0);
-	uasm_i_dmfc0(&p, K0, C0_DESAVE);
+	if (octeon_bootloader_entry_addr) {
+		uasm_build_label(&l, p, label_enter_bootloader);
+		/* Jump to the bootloader and restore K0 */
+		UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
+		uasm_i_jr(&p, K0);
+		uasm_i_dmfc0(&p, K0, C0_DESAVE);
+	}
 #endif
 	uasm_resolve_relocs(relocs, labels);
 
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 986dcec..84f31e1 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -79,28 +79,28 @@
 	unsigned short retry, tmo;
 	unsigned long data;
 
-	au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-	au_sync();
+	__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+	wmb(); /* drain writebuffer */
 
 	retry = AC97_RW_RETRIES;
 	do {
 		mutex_lock(&pscdata->lock);
 
-		au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
+		__raw_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
 			  AC97_CDC(pscdata));
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		tmo = 20;
 		do {
 			udelay(21);
-			if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+			if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
 				break;
 		} while (--tmo);
 
-		data = au_readl(AC97_CDC(pscdata));
+		data = __raw_readl(AC97_CDC(pscdata));
 
-		au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-		au_sync();
+		__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+		wmb(); /* drain writebuffer */
 
 		mutex_unlock(&pscdata->lock);
 
@@ -119,26 +119,26 @@
 	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
 	unsigned int tmo, retry;
 
-	au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-	au_sync();
+	__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+	wmb(); /* drain writebuffer */
 
 	retry = AC97_RW_RETRIES;
 	do {
 		mutex_lock(&pscdata->lock);
 
-		au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
+		__raw_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
 			  AC97_CDC(pscdata));
-		au_sync();
+		wmb(); /* drain writebuffer */
 
 		tmo = 20;
 		do {
 			udelay(21);
-			if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
+			if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
 				break;
 		} while (--tmo);
 
-		au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-		au_sync();
+		__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+		wmb(); /* drain writebuffer */
 
 		mutex_unlock(&pscdata->lock);
 	} while (--retry && !tmo);
@@ -149,11 +149,11 @@
 {
 	struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
 
-	au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
-	au_sync();
+	__raw_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
+	wmb(); /* drain writebuffer */
 	msleep(10);
-	au_writel(0, AC97_RST(pscdata));
-	au_sync();
+	__raw_writel(0, AC97_RST(pscdata));
+	wmb(); /* drain writebuffer */
 }
 
 static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
@@ -162,25 +162,25 @@
 	int i;
 
 	/* disable PSC during cold reset */
-	au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
-	au_sync();
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
-	au_sync();
+	__raw_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* issue cold reset */
-	au_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
-	au_sync();
+	__raw_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
+	wmb(); /* drain writebuffer */
 	msleep(500);
-	au_writel(0, AC97_RST(pscdata));
-	au_sync();
+	__raw_writel(0, AC97_RST(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* enable PSC */
-	au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
-	au_sync();
+	__raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* wait for PSC to indicate it's ready */
 	i = 1000;
-	while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
+	while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
 		msleep(1);
 
 	if (i == 0) {
@@ -189,12 +189,12 @@
 	}
 
 	/* enable the ac97 function */
-	au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-	au_sync();
+	__raw_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* wait for AC97 core to become ready */
 	i = 1000;
-	while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
+	while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
 		msleep(1);
 	if (i == 0)
 		printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
@@ -218,8 +218,8 @@
 
 	chans = params_channels(params);
 
-	r = ro = au_readl(AC97_CFG(pscdata));
-	stat = au_readl(AC97_STAT(pscdata));
+	r = ro = __raw_readl(AC97_CFG(pscdata));
+	stat = __raw_readl(AC97_STAT(pscdata));
 
 	/* already active? */
 	if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
@@ -252,28 +252,28 @@
 		mutex_lock(&pscdata->lock);
 
 		/* disable AC97 device controller first... */
-		au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-		au_sync();
+		__raw_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+		wmb(); /* drain writebuffer */
 
 		/* ...wait for it... */
 		t = 100;
-		while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
+		while ((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
 			msleep(1);
 
 		if (!t)
 			printk(KERN_ERR "PSC-AC97: can't disable!\n");
 
 		/* ...write config... */
-		au_writel(r, AC97_CFG(pscdata));
-		au_sync();
+		__raw_writel(r, AC97_CFG(pscdata));
+		wmb(); /* drain writebuffer */
 
 		/* ...enable the AC97 controller again... */
-		au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-		au_sync();
+		__raw_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+		wmb(); /* drain writebuffer */
 
 		/* ...and wait for ready bit */
 		t = 100;
-		while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
+		while ((!(__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
 			msleep(1);
 
 		if (!t)
@@ -300,21 +300,21 @@
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
-		au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
-		au_sync();
-		au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
-		au_sync();
+		__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+		wmb(); /* drain writebuffer */
+		__raw_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
+		wmb(); /* drain writebuffer */
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
-		au_sync();
+		__raw_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
+		wmb(); /* drain writebuffer */
 
-		while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
+		while (__raw_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
 			asm volatile ("nop");
 
-		au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
-		au_sync();
+		__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+		wmb(); /* drain writebuffer */
 
 		break;
 	default:
@@ -398,13 +398,13 @@
 		  PSC_AC97CFG_DE_ENABLE;
 
 	/* preserve PSC clock source set up by platform	 */
-	sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
-	au_writel(0, PSC_SEL(wd));
-	au_sync();
-	au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
-	au_sync();
+	sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(0, PSC_SEL(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
+	wmb(); /* drain writebuffer */
 
 	/* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
 	memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
@@ -433,10 +433,10 @@
 	snd_soc_unregister_component(&pdev->dev);
 
 	/* disable PSC completely */
-	au_writel(0, AC97_CFG(wd));
-	au_sync();
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
+	__raw_writel(0, AC97_CFG(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
 
 	au1xpsc_ac97_workdata = NULL;	/* MDEV */
 
@@ -449,12 +449,12 @@
 	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
 	/* save interesting registers and disable PSC */
-	wd->pm[0] = au_readl(PSC_SEL(wd));
+	wd->pm[0] = __raw_readl(PSC_SEL(wd));
 
-	au_writel(0, AC97_CFG(wd));
-	au_sync();
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
+	__raw_writel(0, AC97_CFG(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
@@ -464,8 +464,8 @@
 	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
 	/* restore PSC clock config */
-	au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
-	au_sync();
+	__raw_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
+	wmb(); /* drain writebuffer */
 
 	/* after this point the ac97 core will cold-reset the codec.
 	 * During cold-reset the PSC is reinitialized and the last
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index fe923a7..814beff 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -120,10 +120,10 @@
 	unsigned long stat;
 
 	/* check if the PSC is already streaming data */
-	stat = au_readl(I2S_STAT(pscdata));
+	stat = __raw_readl(I2S_STAT(pscdata));
 	if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) {
 		/* reject parameters not currently set up in hardware */
-		cfgbits = au_readl(I2S_CFG(pscdata));
+		cfgbits = __raw_readl(I2S_CFG(pscdata));
 		if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) ||
 		    (params_rate(params) != pscdata->rate))
 			return -EINVAL;
@@ -149,33 +149,33 @@
 	unsigned long tmo;
 
 	/* bring PSC out of sleep, and configure I2S unit */
-	au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
-	au_sync();
+	__raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+	wmb(); /* drain writebuffer */
 
 	tmo = 1000000;
-	while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
+	while (!(__raw_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
 		tmo--;
 
 	if (!tmo)
 		goto psc_err;
 
-	au_writel(0, I2S_CFG(pscdata));
-	au_sync();
-	au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
-	au_sync();
+	__raw_writel(0, I2S_CFG(pscdata));
+	wmb(); /* drain writebuffer */
+	__raw_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* wait for I2S controller to become ready */
 	tmo = 1000000;
-	while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
+	while (!(__raw_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
 		tmo--;
 
 	if (tmo)
 		return 0;
 
 psc_err:
-	au_writel(0, I2S_CFG(pscdata));
-	au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
-	au_sync();
+	__raw_writel(0, I2S_CFG(pscdata));
+	__raw_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+	wmb(); /* drain writebuffer */
 	return -ETIMEDOUT;
 }
 
@@ -187,26 +187,26 @@
 	ret = 0;
 
 	/* if both TX and RX are idle, configure the PSC  */
-	stat = au_readl(I2S_STAT(pscdata));
+	stat = __raw_readl(I2S_STAT(pscdata));
 	if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
 		ret = au1xpsc_i2s_configure(pscdata);
 		if (ret)
 			goto out;
 	}
 
-	au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
-	au_sync();
-	au_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
-	au_sync();
+	__raw_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
+	wmb(); /* drain writebuffer */
+	__raw_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* wait for start confirmation */
 	tmo = 1000000;
-	while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+	while (!(__raw_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
 		tmo--;
 
 	if (!tmo) {
-		au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
-		au_sync();
+		__raw_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+		wmb(); /* drain writebuffer */
 		ret = -ETIMEDOUT;
 	}
 out:
@@ -217,21 +217,21 @@
 {
 	unsigned long tmo, stat;
 
-	au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
-	au_sync();
+	__raw_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+	wmb(); /* drain writebuffer */
 
 	/* wait for stop confirmation */
 	tmo = 1000000;
-	while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+	while ((__raw_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
 		tmo--;
 
 	/* if both TX and RX are idle, disable PSC */
-	stat = au_readl(I2S_STAT(pscdata));
+	stat = __raw_readl(I2S_STAT(pscdata));
 	if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
-		au_writel(0, I2S_CFG(pscdata));
-		au_sync();
-		au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
-		au_sync();
+		__raw_writel(0, I2S_CFG(pscdata));
+		wmb(); /* drain writebuffer */
+		__raw_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+		wmb(); /* drain writebuffer */
 	}
 	return 0;
 }
@@ -332,12 +332,12 @@
 	/* preserve PSC clock source set up by platform (dev.platform_data
 	 * is already occupied by soc layer)
 	 */
-	sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
-	au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
-	au_writel(0, I2S_CFG(wd));
-	au_sync();
+	sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
+	__raw_writel(0, I2S_CFG(wd));
+	wmb(); /* drain writebuffer */
 
 	/* preconfigure: set max rx/tx fifo depths */
 	wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
@@ -364,10 +364,10 @@
 
 	snd_soc_unregister_component(&pdev->dev);
 
-	au_writel(0, I2S_CFG(wd));
-	au_sync();
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
+	__raw_writel(0, I2S_CFG(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
@@ -378,12 +378,12 @@
 	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
 	/* save interesting register and disable PSC */
-	wd->pm[0] = au_readl(PSC_SEL(wd));
+	wd->pm[0] = __raw_readl(PSC_SEL(wd));
 
-	au_writel(0, I2S_CFG(wd));
-	au_sync();
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
+	__raw_writel(0, I2S_CFG(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
@@ -393,12 +393,12 @@
 	struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
 
 	/* select I2S mode and PSC clock */
-	au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
-	au_sync();
-	au_writel(0, PSC_SEL(wd));
-	au_sync();
-	au_writel(wd->pm[0], PSC_SEL(wd));
-	au_sync();
+	__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(0, PSC_SEL(wd));
+	wmb(); /* drain writebuffer */
+	__raw_writel(wd->pm[0], PSC_SEL(wd));
+	wmb(); /* drain writebuffer */
 
 	return 0;
 }
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index b16b2e0..74dffeb 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -27,16 +27,16 @@
 };
 
 /* easy access macros */
-#define PSC_CTRL(x)	((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
-#define PSC_SEL(x)	((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
-#define I2S_STAT(x)	((unsigned long)((x)->mmio) + PSC_I2SSTAT_OFFSET)
-#define I2S_CFG(x)	((unsigned long)((x)->mmio) + PSC_I2SCFG_OFFSET)
-#define I2S_PCR(x)	((unsigned long)((x)->mmio) + PSC_I2SPCR_OFFSET)
-#define AC97_CFG(x)	((unsigned long)((x)->mmio) + PSC_AC97CFG_OFFSET)
-#define AC97_CDC(x)	((unsigned long)((x)->mmio) + PSC_AC97CDC_OFFSET)
-#define AC97_EVNT(x)	((unsigned long)((x)->mmio) + PSC_AC97EVNT_OFFSET)
-#define AC97_PCR(x)	((unsigned long)((x)->mmio) + PSC_AC97PCR_OFFSET)
-#define AC97_RST(x)	((unsigned long)((x)->mmio) + PSC_AC97RST_OFFSET)
-#define AC97_STAT(x)	((unsigned long)((x)->mmio) + PSC_AC97STAT_OFFSET)
+#define PSC_CTRL(x)	((x)->mmio + PSC_CTRL_OFFSET)
+#define PSC_SEL(x)	((x)->mmio + PSC_SEL_OFFSET)
+#define I2S_STAT(x)	((x)->mmio + PSC_I2SSTAT_OFFSET)
+#define I2S_CFG(x)	((x)->mmio + PSC_I2SCFG_OFFSET)
+#define I2S_PCR(x)	((x)->mmio + PSC_I2SPCR_OFFSET)
+#define AC97_CFG(x)	((x)->mmio + PSC_AC97CFG_OFFSET)
+#define AC97_CDC(x)	((x)->mmio + PSC_AC97CDC_OFFSET)
+#define AC97_EVNT(x)	((x)->mmio + PSC_AC97EVNT_OFFSET)
+#define AC97_PCR(x)	((x)->mmio + PSC_AC97PCR_OFFSET)
+#define AC97_RST(x)	((x)->mmio + PSC_AC97RST_OFFSET)
+#define AC97_STAT(x)	((x)->mmio + PSC_AC97STAT_OFFSET)
 
 #endif