From cf678877a86e03302686d0364c982d573daa6e2c Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 3 Aug 2012 09:49:04 +0200
Subject: [PATCH 02/25] xway support

---
 .../mips/include/asm/mach-lantiq/xway/lantiq_irq.h |   31 +--
 .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   96 +++++++--
 arch/mips/lantiq/xway/Kconfig                      |   21 ++
 arch/mips/lantiq/xway/Makefile                     |    5 +-
 arch/mips/lantiq/xway/clk-ase.c                    |   48 -----
 arch/mips/lantiq/xway/clk-xway.c                   |  223 --------------------
 arch/mips/lantiq/xway/devices.c                    |   72 ++++---
 arch/mips/lantiq/xway/devices.h                    |    2 +
 arch/mips/lantiq/xway/dma.c                        |   27 +--
 arch/mips/lantiq/xway/ebu.c                        |   52 -----
 arch/mips/lantiq/xway/gpio.c                       |   92 +++++++--
 arch/mips/lantiq/xway/gpio_ebu.c                   |    3 +-
 arch/mips/lantiq/xway/gpio_stp.c                   |   49 +++--
 arch/mips/lantiq/xway/mach-easy50601.c             |   15 +-
 arch/mips/lantiq/xway/mach-easy50712.c             |   17 +-
 arch/mips/lantiq/xway/pmu.c                        |   69 ------
 arch/mips/lantiq/xway/prom-ase.c                   |   39 ----
 arch/mips/lantiq/xway/prom-xway.c                  |   54 -----
 arch/mips/lantiq/xway/reset.c                      |   92 ++++++---
 arch/mips/lantiq/xway/setup-ase.c                  |   19 --
 arch/mips/lantiq/xway/setup-xway.c                 |   20 --
 21 files changed, 349 insertions(+), 697 deletions(-)
 delete mode 100644 arch/mips/lantiq/xway/clk-ase.c
 delete mode 100644 arch/mips/lantiq/xway/clk-xway.c
 delete mode 100644 arch/mips/lantiq/xway/ebu.c
 delete mode 100644 arch/mips/lantiq/xway/pmu.c
 delete mode 100644 arch/mips/lantiq/xway/prom-ase.c
 delete mode 100644 arch/mips/lantiq/xway/prom-xway.c
 delete mode 100644 arch/mips/lantiq/xway/setup-ase.c
 delete mode 100644 arch/mips/lantiq/xway/setup-xway.c

diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
index b4465a8..4f69ff0 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -9,6 +9,8 @@
 #ifndef _LANTIQ_XWAY_IRQ_H__
 #define _LANTIQ_XWAY_IRQ_H__
 
+#define IM_NUM			5
+
 #define INT_NUM_IRQ0		8
 #define INT_NUM_IM0_IRL0	(INT_NUM_IRQ0 + 0)
 #define INT_NUM_IM1_IRL0	(INT_NUM_IRQ0 + 32)
@@ -27,37 +29,26 @@
 
 #define LTQ_SSC_TIR		(INT_NUM_IM0_IRL0 + 15)
 #define LTQ_SSC_RIR		(INT_NUM_IM0_IRL0 + 14)
+#define LTQ_SSC_TIR_AR9		(INT_NUM_IM0_IRL0 + 14)
+#define LTQ_SSC_RIR_AR9		(INT_NUM_IM0_IRL0 + 15)
 #define LTQ_SSC_EIR		(INT_NUM_IM0_IRL0 + 16)
+#define LTQ_SSC_RIR_ASE		(INT_NUM_IM0_IRL0 + 16)
+#define LTQ_SSC_TIR_ASE		(INT_NUM_IM0_IRL0 + 17)
+#define LTQ_SSC_EIR_ASE		(INT_NUM_IM0_IRL0 + 18)
+#define LTQ_SSC_FIR_ASE		(INT_NUM_IM0_IRL0 + 19)
 
 #define LTQ_MEI_DYING_GASP_INT	(INT_NUM_IM1_IRL0 + 21)
 #define LTQ_MEI_INT		(INT_NUM_IM1_IRL0 + 23)
 
 #define LTQ_TIMER6_INT		(INT_NUM_IM1_IRL0 + 23)
 #define LTQ_USB_INT		(INT_NUM_IM1_IRL0 + 22)
+#define LTQ_USB_ASE_INT		(INT_NUM_IM0_IRL0 + 31)
 #define LTQ_USB_OC_INT		(INT_NUM_IM4_IRL0 + 23)
 
 #define MIPS_CPU_TIMER_IRQ		7
 
-#define LTQ_DMA_CH0_INT		(INT_NUM_IM2_IRL0)
-#define LTQ_DMA_CH1_INT		(INT_NUM_IM2_IRL0 + 1)
-#define LTQ_DMA_CH2_INT		(INT_NUM_IM2_IRL0 + 2)
-#define LTQ_DMA_CH3_INT		(INT_NUM_IM2_IRL0 + 3)
-#define LTQ_DMA_CH4_INT		(INT_NUM_IM2_IRL0 + 4)
-#define LTQ_DMA_CH5_INT		(INT_NUM_IM2_IRL0 + 5)
-#define LTQ_DMA_CH6_INT		(INT_NUM_IM2_IRL0 + 6)
-#define LTQ_DMA_CH7_INT		(INT_NUM_IM2_IRL0 + 7)
-#define LTQ_DMA_CH8_INT		(INT_NUM_IM2_IRL0 + 8)
-#define LTQ_DMA_CH9_INT		(INT_NUM_IM2_IRL0 + 9)
-#define LTQ_DMA_CH10_INT	(INT_NUM_IM2_IRL0 + 10)
-#define LTQ_DMA_CH11_INT	(INT_NUM_IM2_IRL0 + 11)
-#define LTQ_DMA_CH12_INT	(INT_NUM_IM2_IRL0 + 25)
-#define LTQ_DMA_CH13_INT	(INT_NUM_IM2_IRL0 + 26)
-#define LTQ_DMA_CH14_INT	(INT_NUM_IM2_IRL0 + 27)
-#define LTQ_DMA_CH15_INT	(INT_NUM_IM2_IRL0 + 28)
-#define LTQ_DMA_CH16_INT	(INT_NUM_IM2_IRL0 + 29)
-#define LTQ_DMA_CH17_INT	(INT_NUM_IM2_IRL0 + 30)
-#define LTQ_DMA_CH18_INT	(INT_NUM_IM2_IRL0 + 16)
-#define LTQ_DMA_CH19_INT	(INT_NUM_IM2_IRL0 + 21)
+#define LTQ_DMA_ETOP		((ltq_is_ase()) ? \
+				(INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
 
 #define LTQ_PPE_MBOX_INT	(INT_NUM_IM2_IRL0 + 24)
 
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 8a3c6be..1ec8f2a 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -17,23 +17,44 @@
 #define SOC_ID_DANUBE1		0x129
 #define SOC_ID_DANUBE2		0x12B
 #define SOC_ID_TWINPASS		0x12D
-#define SOC_ID_AMAZON_SE	0x152
+#define SOC_ID_AMAZON_SE_1	0x152 /* 50601 */
+#define SOC_ID_AMAZON_SE_2	0x153 /* 50600 */
 #define SOC_ID_ARX188		0x16C
-#define SOC_ID_ARX168		0x16D
+#define SOC_ID_ARX168_1		0x16D
+#define SOC_ID_ARX168_2		0x16E
 #define SOC_ID_ARX182		0x16F
+#define SOC_ID_GRX188		0x170
+#define SOC_ID_GRX168		0x171
+
+#define SOC_ID_VRX288		0x1C0 /* v1.1 */
+#define SOC_ID_VRX282		0x1C1 /* v1.1 */
+#define SOC_ID_VRX268		0x1C2 /* v1.1 */
+#define SOC_ID_GRX268		0x1C8 /* v1.1 */
+#define SOC_ID_GRX288		0x1C9 /* v1.1 */
+#define SOC_ID_VRX288_2		0x00B /* v1.2 */
+#define SOC_ID_VRX268_2		0x00C /* v1.2 */
+#define SOC_ID_GRX288_2		0x00D /* v1.2 */
+#define SOC_ID_GRX282_2		0x00E /* v1.2 */
 
 /* SoC Types */
 #define SOC_TYPE_DANUBE		0x01
 #define SOC_TYPE_TWINPASS	0x02
 #define SOC_TYPE_AR9		0x03
-#define SOC_TYPE_VR9		0x04
-#define SOC_TYPE_AMAZON_SE	0x05
+#define SOC_TYPE_VR9_1		0x04 /* v1.1 */
+#define SOC_TYPE_VR9_2		0x05 /* v1.2 */
+#define SOC_TYPE_AMAZON_SE	0x06
 
 /* ASC0/1 - serial port */
 #define LTQ_ASC0_BASE_ADDR	0x1E100400
 #define LTQ_ASC1_BASE_ADDR	0x1E100C00
 #define LTQ_ASC_SIZE		0x400
 
+/*
+ * during early_printk no ioremap is possible
+ * lets use KSEG1 instead
+ */
+#define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
+
 /* RCU - reset control unit */
 #define LTQ_RCU_BASE_ADDR	0x1F203000
 #define LTQ_RCU_SIZE		0x1000
@@ -61,6 +82,8 @@
 #define LTQ_CGU_BASE_ADDR	0x1F103000
 #define LTQ_CGU_SIZE		0x1000
 
+#define CGU_EPHY		0x10
+
 /* ICU - interrupt control unit */
 #define LTQ_ICU_BASE_ADDR	0x1F880200
 #define LTQ_ICU_SIZE		0x100
@@ -73,18 +96,14 @@
 #define LTQ_PMU_BASE_ADDR	0x1F102000
 #define LTQ_PMU_SIZE		0x1000
 
-#define PMU_DMA			0x0020
-#define PMU_USB			0x8041
-#define PMU_LED			0x0800
-#define PMU_GPT			0x1000
-#define PMU_PPE			0x2000
-#define PMU_FPI			0x4000
-#define PMU_SWITCH		0x10000000
-
 /* ETOP - ethernet */
 #define LTQ_ETOP_BASE_ADDR	0x1E180000
 #define LTQ_ETOP_SIZE		0x40000
 
+/* GBIT - gigabit switch */
+#define LTQ_GBIT_BASE_ADDR	0x1E108000
+#define LTQ_GBIT_SIZE		0x4000
+
 /* DMA */
 #define LTQ_DMA_BASE_ADDR	0x1E104100
 #define LTQ_DMA_SIZE		0x800
@@ -97,6 +116,8 @@
 #define LTQ_WDT_BASE_ADDR	0x1F8803F0
 #define LTQ_WDT_SIZE		0x10
 
+#define LTQ_RST_CAUSE_WDTRST	0x20
+
 /* STP - serial to parallel conversion unit */
 #define LTQ_STP_BASE_ADDR	0x1E100BB0
 #define LTQ_STP_SIZE		0x40
@@ -105,7 +126,9 @@
 #define LTQ_GPIO0_BASE_ADDR	0x1E100B10
 #define LTQ_GPIO1_BASE_ADDR	0x1E100B40
 #define LTQ_GPIO2_BASE_ADDR	0x1E100B70
+#define LTQ_GPIO3_BASE_ADDR	0x1E100BA0
 #define LTQ_GPIO_SIZE		0x30
+#define LTQ_GPIO3_SIZE		0x10
 
 /* SSC */
 #define LTQ_SSC_BASE_ADDR	0x1e100800
@@ -121,20 +144,57 @@
 #define LTQ_MPS_BASE_ADDR	(KSEG1 + 0x1F107000)
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
-/* request a non-gpio and set the PIO config */
-extern int  ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name);
-extern void ltq_pmu_enable(unsigned int module);
-extern void ltq_pmu_disable(unsigned int module);
+/* BOOT_SEL - find what boot media we have */
+#define BS_EXT_ROM	0x0
+#define BS_FLASH	0x1
+#define BS_MII0		0x2
+#define BS_PCI		0x3
+#define BS_UART1	0x4
+#define BS_SPI		0x5
+#define BS_NAND		0x6
+#define BS_RMII0	0x7
+
+extern unsigned char ltq_boot_select(void);
+
+/* register access macros for EBU and CGU */
+#define ltq_ebu_w32(x, y)	ltq_w32((x), ltq_ebu_membase + (y))
+#define ltq_ebu_r32(x)		ltq_r32(ltq_ebu_membase + (x))
+#define ltq_ebu_w32_mask(x, y, z) \
+	ltq_w32_mask(x, y, ltq_ebu_membase + (z))
+#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
+#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
+
+extern __iomem void *ltq_ebu_membase;
+extern __iomem void *ltq_cgu_membase;
+
+static inline int ltq_is_ase(void)
+{
+	return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
+}
 
 static inline int ltq_is_ar9(void)
 {
 	return (ltq_get_soc_type() == SOC_TYPE_AR9);
 }
 
+static inline int ltq_is_vr9_1(void)
+{
+	return (ltq_get_soc_type() == SOC_TYPE_VR9_1);
+}
+
+static inline int ltq_is_vr9_2(void)
+{
+	return (ltq_get_soc_type() == SOC_TYPE_VR9_2);
+}
+
 static inline int ltq_is_vr9(void)
 {
-	return (ltq_get_soc_type() == SOC_TYPE_VR9);
+	return (ltq_is_vr9_1() || ltq_is_vr9_2());
+}
+
+static inline int ltq_is_falcon(void)
+{
+	return 0;
 }
 
 #endif /* CONFIG_SOC_TYPE_XWAY */
diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
index 2b857de..54a51ff 100644
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -8,6 +8,27 @@ config LANTIQ_MACH_EASY50712
 
 endmenu
 
+choice
+	prompt "PCI"
+	default PCI_LANTIQ_NONE
+
+config PCI_LANTIQ_NONE
+	bool "None"
+
+config PCI_LANTIQ
+	bool "PCI Support"
+	depends on PCI
+
+config PCIE_LANTIQ
+	bool "PCIE Support"
+	select ARCH_SUPPORTS_MSI
+
+endchoice
+
+config PCIE_LANTIQ_MSI
+	bool
+	depends on PCIE_LANTIQ && PCI_MSI
+	default y
 endif
 
 if SOC_AMAZON_SE
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index c517f2e..c9baf91 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1,4 @@
-obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
-
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o timer.o dev-ifxhcd.o
 
 obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
 obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
deleted file mode 100644
index 6522583..0000000
--- a/arch/mips/lantiq/xway/clk-ase.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include <lantiq_soc.h>
-
-/* cgu registers */
-#define LTQ_CGU_SYS	0x0010
-
-unsigned int ltq_get_io_region_clock(void)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_io_region_clock);
-
-unsigned int ltq_get_fpi_bus_clock(int fpi)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
-
-unsigned int ltq_get_cpu_hz(void)
-{
-	if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
-		return CLOCK_266M;
-	else
-		return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_cpu_hz);
-
-unsigned int ltq_get_fpi_hz(void)
-{
-	return CLOCK_133M;
-}
-EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
deleted file mode 100644
index 696b1a3..0000000
--- a/arch/mips/lantiq/xway/clk-xway.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/io.h>
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/div64.h>
-
-#include <lantiq_soc.h>
-
-static unsigned int ltq_ram_clocks[] = {
-	CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
-#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
-
-#define BASIC_FREQUENCY_1	35328000
-#define BASIC_FREQUENCY_2	36000000
-#define BASIS_REQUENCY_USB	12000000
-
-#define GET_BITS(x, msb, lsb) \
-	(((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
-
-#define LTQ_CGU_PLL0_CFG	0x0004
-#define LTQ_CGU_PLL1_CFG	0x0008
-#define LTQ_CGU_PLL2_CFG	0x000C
-#define LTQ_CGU_SYS		0x0010
-#define LTQ_CGU_UPDATE		0x0014
-#define LTQ_CGU_IF_CLK		0x0018
-#define LTQ_CGU_OSC_CON		0x001C
-#define LTQ_CGU_SMD		0x0020
-#define LTQ_CGU_CT1SR		0x0028
-#define LTQ_CGU_CT2SR		0x002C
-#define LTQ_CGU_PCMCR		0x0030
-#define LTQ_CGU_PCI_CR		0x0034
-#define LTQ_CGU_PD_PC		0x0038
-#define LTQ_CGU_FMR		0x003C
-
-#define CGU_PLL0_PHASE_DIVIDER_ENABLE	\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
-#define CGU_PLL0_BYPASS			\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
-#define CGU_PLL0_CFG_DSMSEL		\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
-#define CGU_PLL0_CFG_FRAC_EN		\
-	(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
-#define CGU_PLL1_SRC			\
-	(ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
-#define CGU_PLL2_PHASE_DIVIDER_ENABLE	\
-	(ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
-#define CGU_SYS_FPI_SEL			(1 << 6)
-#define CGU_SYS_DDR_SEL			0x3
-#define CGU_PLL0_SRC			(1 << 29)
-
-#define CGU_PLL0_CFG_PLLK	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
-#define CGU_PLL0_CFG_PLLN	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
-#define CGU_PLL0_CFG_PLLM	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
-#define CGU_PLL2_SRC		GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
-#define CGU_PLL2_CFG_INPUT_DIV	GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
-
-static unsigned int ltq_get_pll0_fdiv(void);
-
-static inline unsigned int get_input_clock(int pll)
-{
-	switch (pll) {
-	case 0:
-		if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
-			return BASIS_REQUENCY_USB;
-		else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			return BASIC_FREQUENCY_1;
-		else
-			return BASIC_FREQUENCY_2;
-	case 1:
-		if (CGU_PLL1_SRC)
-			return BASIS_REQUENCY_USB;
-		else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			return BASIC_FREQUENCY_1;
-		else
-			return BASIC_FREQUENCY_2;
-	case 2:
-		switch (CGU_PLL2_SRC) {
-		case 0:
-			return ltq_get_pll0_fdiv();
-		case 1:
-			return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
-				BASIC_FREQUENCY_1 :
-				BASIC_FREQUENCY_2;
-		case 2:
-			return BASIS_REQUENCY_USB;
-		}
-	default:
-		return 0;
-	}
-}
-
-static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
-{
-	u64 res, clock = get_input_clock(pll);
-
-	res = num * clock;
-	do_div(res, den);
-	return res;
-}
-
-static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = ((N + 1) << 10) + K;
-	unsigned int den = (M + 1) << 10;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = ((N + 1) << 11) + K + 512;
-	unsigned int den = (M + 1) << 11;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
-	unsigned int K)
-{
-	unsigned int num = K >= 512 ?
-		((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
-	unsigned int den = (M + 1) << 12;
-
-	return cal_dsm(pll, num, den);
-}
-
-static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
-	unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
-{
-	if (!dsmsel)
-		return mash_dsm(pll, M, N, K);
-	else if (!phase_div_en)
-		return mash_dsm(pll, M, N, K);
-	else
-		return ssff_dsm_2(pll, M, N, K);
-}
-
-static inline unsigned int ltq_get_pll0_fosc(void)
-{
-	if (CGU_PLL0_BYPASS)
-		return get_input_clock(0);
-	else
-		return !CGU_PLL0_CFG_FRAC_EN
-			? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
-				CGU_PLL0_CFG_DSMSEL,
-				CGU_PLL0_PHASE_DIVIDER_ENABLE)
-			: dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
-				CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
-				CGU_PLL0_PHASE_DIVIDER_ENABLE);
-}
-
-static unsigned int ltq_get_pll0_fdiv(void)
-{
-	unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
-
-	return (ltq_get_pll0_fosc() + (div >> 1)) / div;
-}
-
-unsigned int ltq_get_io_region_clock(void)
-{
-	unsigned int ret = ltq_get_pll0_fosc();
-
-	switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
-	default:
-	case 0:
-		return (ret + 1) / 2;
-	case 1:
-		return (ret * 2 + 2) / 5;
-	case 2:
-		return (ret + 1) / 3;
-	case 3:
-		return (ret + 2) / 4;
-	}
-}
-EXPORT_SYMBOL(ltq_get_io_region_clock);
-
-unsigned int ltq_get_fpi_bus_clock(int fpi)
-{
-	unsigned int ret = ltq_get_io_region_clock();
-
-	if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
-		ret >>= 1;
-	return ret;
-}
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
-
-unsigned int ltq_get_cpu_hz(void)
-{
-	switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
-	case 0:
-		return CLOCK_333M;
-	case 4:
-		return DDR_HZ;
-	case 8:
-		return DDR_HZ << 1;
-	default:
-		return DDR_HZ >> 1;
-	}
-}
-EXPORT_SYMBOL(ltq_get_cpu_hz);
-
-unsigned int ltq_get_fpi_hz(void)
-{
-	unsigned int ddr_clock = DDR_HZ;
-
-	if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
-		return ddr_clock >> 1;
-	return ddr_clock;
-}
-EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
index d614aa7..5d4650d 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -31,22 +31,10 @@
 
 /* gpio */
 static struct resource ltq_gpio_resource[] = {
-	{
-		.name	= "gpio0",
-		.start  = LTQ_GPIO0_BASE_ADDR,
-		.end    = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio1",
-		.start  = LTQ_GPIO1_BASE_ADDR,
-		.end    = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio2",
-		.start  = LTQ_GPIO2_BASE_ADDR,
-		.end    = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}
+	MEM_RES("gpio0", LTQ_GPIO0_BASE_ADDR, LTQ_GPIO_SIZE),
+	MEM_RES("gpio1", LTQ_GPIO1_BASE_ADDR, LTQ_GPIO_SIZE),
+	MEM_RES("gpio2", LTQ_GPIO2_BASE_ADDR, LTQ_GPIO_SIZE),
+	MEM_RES("gpio3", LTQ_GPIO3_BASE_ADDR, LTQ_GPIO3_SIZE),
 };
 
 void __init ltq_register_gpio(void)
@@ -60,30 +48,23 @@ void __init ltq_register_gpio(void)
 	if (ltq_is_ar9() || ltq_is_vr9()) {
 		platform_device_register_simple("ltq_gpio", 2,
 			&ltq_gpio_resource[2], 1);
+		platform_device_register_simple("ltq_gpio", 3,
+			&ltq_gpio_resource[3], 1);
 	}
 }
 
 /* serial to parallel conversion */
-static struct resource ltq_stp_resource = {
-	.name   = "stp",
-	.start  = LTQ_STP_BASE_ADDR,
-	.end    = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_stp_resource =
+	MEM_RES("stp", LTQ_STP_BASE_ADDR, LTQ_STP_SIZE);
 
 void __init ltq_register_gpio_stp(void)
 {
-	platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
+	platform_device_register_simple("ltq_stp", -1, &ltq_stp_resource, 1);
 }
 
 /* asc ports - amazon se has its own serial mapping */
 static struct resource ltq_ase_asc_resources[] = {
-	{
-		.name	= "asc0",
-		.start  = LTQ_ASC1_BASE_ADDR,
-		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	MEM_RES("asc0", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE),
 	IRQ_RES(tx, LTQ_ASC_ASE_TIR),
 	IRQ_RES(rx, LTQ_ASC_ASE_RIR),
 	IRQ_RES(err, LTQ_ASC_ASE_EIR),
@@ -96,24 +77,45 @@ void __init ltq_register_ase_asc(void)
 }
 
 /* ethernet */
-static struct resource ltq_etop_resources = {
-	.name	= "etop",
-	.start	= LTQ_ETOP_BASE_ADDR,
-	.end	= LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
+static struct resource ltq_etop_resources[] = {
+	MEM_RES("etop", LTQ_ETOP_BASE_ADDR, LTQ_ETOP_SIZE),
+	MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
 };
 
 static struct platform_device ltq_etop = {
 	.name		= "ltq_etop",
-	.resource	= &ltq_etop_resources,
+	.resource	= ltq_etop_resources,
 	.num_resources	= 1,
+	.id		= -1,
 };
 
 void __init
 ltq_register_etop(struct ltq_eth_data *eth)
 {
+	/* only register the gphy on socs that have one */
+	if (ltq_is_ar9() | ltq_is_vr9())
+		ltq_etop.num_resources = 2;
 	if (eth) {
 		ltq_etop.dev.platform_data = eth;
 		platform_device_register(&ltq_etop);
 	}
 }
+
+/* ethernet */
+static struct resource ltq_vrx200_resources[] = {
+	MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
+};
+
+static struct platform_device ltq_vrx200 = {
+	.name		= "ltq_vrx200",
+	.resource	= ltq_vrx200_resources,
+	.num_resources	= 1,
+	.id = -1,
+};
+
+void __init
+ltq_register_vrx200(struct ltq_eth_data *eth)
+{
+	ltq_vrx200.dev.platform_data = eth;
+	platform_device_register(&ltq_vrx200);
+}
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
index e904934..08befd9 100644
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -16,5 +16,7 @@ extern void ltq_register_gpio(void);
 extern void ltq_register_gpio_stp(void);
 extern void ltq_register_ase_asc(void);
 extern void ltq_register_etop(struct ltq_eth_data *eth);
+extern void xway_register_nand(struct mtd_partition *parts, int count);
+extern void ltq_register_vrx200(struct ltq_eth_data *eth);
 
 #endif
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index b210e93..ce86529 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -20,10 +20,13 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
+#include <linux/clk.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
 
+#include "../devices.h"
+
 #define LTQ_DMA_CTRL		0x10
 #define LTQ_DMA_CPOLL		0x14
 #define LTQ_DMA_CS		0x18
@@ -55,12 +58,8 @@
 #define ltq_dma_w32_mask(x, y, z)	ltq_w32_mask(x, y, \
 						ltq_dma_membase + (z))
 
-static struct resource ltq_dma_resource = {
-	.name	= "dma",
-	.start	= LTQ_DMA_BASE_ADDR,
-	.end	= LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_dma_resource =
+	MEM_RES("dma", LTQ_DMA_BASE_ADDR, LTQ_DMA_SIZE);
 
 static void __iomem *ltq_dma_membase;
 
@@ -218,24 +217,18 @@ EXPORT_SYMBOL_GPL(ltq_dma_init_port);
 int __init
 ltq_dma_init(void)
 {
+	struct clk *clk;
 	int i;
 
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
-		panic("Failed to insert dma memory");
-
-	if (request_mem_region(ltq_dma_resource.start,
-			resource_size(&ltq_dma_resource), "dma") < 0)
-		panic("Failed to request dma memory");
-
 	/* remap dma register range */
-	ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
-				resource_size(&ltq_dma_resource));
+	ltq_dma_membase = ltq_remap_resource(&ltq_dma_resource);
 	if (!ltq_dma_membase)
 		panic("Failed to remap dma memory");
 
 	/* power up and reset the dma engine */
-	ltq_pmu_enable(PMU_DMA);
+	clk = clk_get_sys("ltq_dma", NULL);
+	WARN_ON(!clk);
+	clk_enable(clk);
 	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
 
 	/* disable all interrupts */
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
deleted file mode 100644
index 862e3e8..0000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  EBU - the external bus unit attaches PCI, NOR and NAND
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-/* all access to the ebu must be locked */
-DEFINE_SPINLOCK(ebu_lock);
-EXPORT_SYMBOL_GPL(ebu_lock);
-
-static struct resource ltq_ebu_resource = {
-	.name	= "ebu",
-	.start	= LTQ_EBU_BASE_ADDR,
-	.end	= LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-/* remapped base addr of the clock unit and external bus unit */
-void __iomem *ltq_ebu_membase;
-
-static int __init lantiq_ebu_init(void)
-{
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
-		panic("Failed to insert ebu memory");
-
-	if (request_mem_region(ltq_ebu_resource.start,
-			resource_size(&ltq_ebu_resource), "ebu") < 0)
-		panic("Failed to request ebu memory");
-
-	/* remap ebu register range */
-	ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
-				resource_size(&ltq_ebu_resource));
-	if (!ltq_ebu_membase)
-		panic("Failed to remap ebu memory");
-
-	/* make sure to unprotect the memory region where flash is located */
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
-	return 0;
-}
-
-postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
index d2fa98f..375329b 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -21,9 +21,19 @@
 #define LTQ_GPIO_ALTSEL0	0x0C
 #define LTQ_GPIO_ALTSEL1	0x10
 #define LTQ_GPIO_OD		0x14
-
+#define LTQ_GPIO_PUDSEL		0x1C
+#define LTQ_GPIO_PUDEN		0x20
+#define LTQ_GPIO3_OD		0x24
+#define LTQ_GPIO3_ALTSEL1	0x24
+#define LTQ_GPIO3_PUDSEL	0x28
+#define LTQ_GPIO3_PUDEN		0x2C
+
+/* PORT3 only has 8 pins and its register layout
+   is slightly different */
 #define PINS_PER_PORT		16
-#define MAX_PORTS		3
+#define PINS_PORT3		8
+#define MAX_PORTS		4
+#define MAX_PIN			56
 
 #define ltq_gpio_getbit(m, r, p)	(!!(ltq_r32(m + r) & (1 << p)))
 #define ltq_gpio_setbit(m, r, p)	ltq_w32_mask(0, (1 << p), m + r)
@@ -48,14 +58,14 @@ int irq_to_gpio(unsigned int gpio)
 }
 EXPORT_SYMBOL(irq_to_gpio);
 
-int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name)
+int ltq_gpio_request(struct device *dev, unsigned int pin, unsigned int mux,
+			unsigned int dir, const char *name)
 {
 	int id = 0;
 
-	if (pin >= (MAX_PORTS * PINS_PER_PORT))
+	if (pin >= MAX_PIN)
 		return -EINVAL;
-	if (gpio_request(pin, name)) {
+	if (devm_gpio_request(dev, pin, name)) {
 		pr_err("failed to setup lantiq gpio: %s\n", name);
 		return -EBUSY;
 	}
@@ -67,18 +77,27 @@ int ltq_gpio_request(unsigned int pin, unsigned int alt0,
 		pin -= PINS_PER_PORT;
 		id++;
 	}
-	if (alt0)
+	if (mux & 0x2)
 		ltq_gpio_setbit(ltq_gpio_port[id].membase,
 			LTQ_GPIO_ALTSEL0, pin);
 	else
 		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
 			LTQ_GPIO_ALTSEL0, pin);
-	if (alt1)
-		ltq_gpio_setbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
-	else
-		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
-			LTQ_GPIO_ALTSEL1, pin);
+	if (id == 3) {
+		if (mux & 0x1)
+			ltq_gpio_setbit(ltq_gpio_port[1].membase,
+				LTQ_GPIO3_ALTSEL1, pin);
+		else
+			ltq_gpio_clearbit(ltq_gpio_port[1].membase,
+				LTQ_GPIO3_ALTSEL1, pin);
+	} else {
+		if (mux & 0x1)
+			ltq_gpio_setbit(ltq_gpio_port[id].membase,
+				LTQ_GPIO_ALTSEL1, pin);
+		else
+			ltq_gpio_clearbit(ltq_gpio_port[id].membase,
+				LTQ_GPIO_ALTSEL1, pin);
+	}
 	return 0;
 }
 EXPORT_SYMBOL(ltq_gpio_request);
@@ -104,7 +123,18 @@ static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
 	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
 
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+	if (chip->ngpio == PINS_PORT3) {
+		ltq_gpio_clearbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_OD, offset);
+		ltq_gpio_setbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_PUDSEL, offset);
+		ltq_gpio_setbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_PUDEN, offset);
+	} else {
+		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
+	}
 	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
 
 	return 0;
@@ -115,7 +145,18 @@ static int ltq_gpio_direction_output(struct gpio_chip *chip,
 {
 	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
 
-	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+	if (chip->ngpio == PINS_PORT3) {
+		ltq_gpio_setbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_OD, offset);
+		ltq_gpio_clearbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_PUDSEL, offset);
+		ltq_gpio_clearbit(ltq_gpio_port[0].membase,
+				LTQ_GPIO3_PUDEN, offset);
+	} else {
+		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
+		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
+	}
 	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
 	ltq_gpio_set(chip, offset, value);
 
@@ -127,7 +168,11 @@ static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
 	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
 
 	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
-	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
+	if (chip->ngpio == PINS_PORT3)
+		ltq_gpio_clearbit(ltq_gpio_port[1].membase,
+				LTQ_GPIO3_ALTSEL1, offset);
+	else
+		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
 	return 0;
 }
 
@@ -140,6 +185,16 @@ static int ltq_gpio_probe(struct platform_device *pdev)
 			pdev->id);
 		return -EINVAL;
 	}
+
+	/* dirty hack - The registers of port3 are not mapped linearly.
+	   Port 3 may only load if Port 1/2 are mapped */
+	if ((pdev->id == 3) && (!ltq_gpio_port[1].membase
+					|| !ltq_gpio_port[2].membase)) {
+		dev_err(&pdev->dev,
+			"ports 1/2 need to be loaded before port 3 works\n");
+		return -ENOMEM;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
@@ -169,7 +224,10 @@ static int ltq_gpio_probe(struct platform_device *pdev)
 	ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
 	ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
 	ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
-	ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
+	if (pdev->id == 3)
+		ltq_gpio_port[pdev->id].chip.ngpio = PINS_PORT3;
+	else
+		ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
 	platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
 	return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
 }
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
index b91c7f1..bc5696b 100644
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ b/arch/mips/lantiq/xway/gpio_ebu.c
@@ -61,9 +61,8 @@ static struct gpio_chip ltq_ebu_chip = {
 	.label = "ltq_ebu",
 	.direction_output = ltq_ebu_direction_output,
 	.set = ltq_ebu_set,
-	.base = 72,
+	.base = 100,
 	.ngpio = 16,
-	.can_sleep = 1,
 	.owner = THIS_MODULE,
 };
 
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
index ff9991c..791beeb 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -15,6 +15,8 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
 
 #include <lantiq_soc.h>
 
@@ -25,6 +27,7 @@
 #define LTQ_STP_AR		0x10
 
 #define LTQ_STP_CON_SWU		(1 << 31)
+#define LTQ_STP_SWU_MASK	(1 << 31)
 #define LTQ_STP_2HZ		0
 #define LTQ_STP_4HZ		(1 << 23)
 #define LTQ_STP_8HZ		(2 << 23)
@@ -35,6 +38,8 @@
 #define LTQ_STP_ADSL_SRC	(3 << 24)
 
 #define LTQ_STP_GROUP0		(1 << 0)
+#define LTQ_STP_GROUP1		(1 << 1)
+#define LTQ_STP_GROUP2		(1 << 2)
 
 #define LTQ_STP_RISING		0
 #define LTQ_STP_FALLING		(1 << 26)
@@ -56,6 +61,12 @@ static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
 	else
 		ltq_stp_shadow &= ~(1 << offset);
 	ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
+	ltq_stp_w32_mask(LTQ_STP_SWU_MASK, LTQ_STP_CON_SWU, LTQ_STP_CON0);
+}
+
+static int ltq_stp_get(struct gpio_chip *chip, unsigned offset)
+{
+	return !!(ltq_stp_r32(LTQ_STP_CPU0) & (1<<offset));
 }
 
 static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
@@ -70,18 +81,15 @@ static struct gpio_chip ltq_stp_chip = {
 	.label = "ltq_stp",
 	.direction_output = ltq_stp_direction_output,
 	.set = ltq_stp_set,
-	.base = 48,
+	.get = ltq_stp_get,
+	.base = 200,
 	.ngpio = 24,
-	.can_sleep = 1,
 	.owner = THIS_MODULE,
 };
 
-static int ltq_stp_hw_init(void)
+static int ltq_stp_hw_init(struct device *dev)
 {
-	/* the 3 pins used to control the external stp */
-	ltq_gpio_request(4, 1, 0, 1, "stp-st");
-	ltq_gpio_request(5, 1, 0, 1, "stp-d");
-	ltq_gpio_request(6, 1, 0, 1, "stp-sh");
+	struct clk *clk;
 
 	/* sane defaults */
 	ltq_stp_w32(0, LTQ_STP_AR);
@@ -93,21 +101,18 @@ static int ltq_stp_hw_init(void)
 	/* rising or falling edge */
 	ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
 
-	/* per default stp 15-0 are set */
-	ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
-
-	/* stp are update periodically by the FPI bus */
-	ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
-
-	/* set stp update speed */
-	ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
+	/* enable all three led groups */
+	ltq_stp_w32_mask(0, LTQ_STP_GROUP0 | LTQ_STP_GROUP1 | LTQ_STP_GROUP2,
+		LTQ_STP_CON1);
 
 	/* tell the hardware that pin (led) 0 and 1 are controlled
 	 *  by the dsl arc
 	 */
 	ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
 
-	ltq_pmu_enable(PMU_LED);
+	clk = clk_get(dev, NULL);
+	WARN_ON(IS_ERR(clk));
+	clk_enable(clk);
 	return 0;
 }
 
@@ -115,6 +120,7 @@ static int __devinit ltq_stp_probe(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int ret = 0;
+	int pin;
 
 	if (!res)
 		return -ENOENT;
@@ -130,9 +136,18 @@ static int __devinit ltq_stp_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to remap STP memory\n");
 		return -ENOMEM;
 	}
+
+	/* the 3 pins used to control the external stp */
+	pin = ltq_is_ase() ? 1 : 4;
+	if (ltq_gpio_request(&pdev->dev, pin, 2, 1, "stp-st") ||
+			ltq_gpio_request(&pdev->dev, pin+1, 2, 1, "stp-d") ||
+			ltq_gpio_request(&pdev->dev, pin+2, 2, 1, "stp-sh")) {
+		dev_err(&pdev->dev, "failed to request needed gpios\n");
+		return -EBUSY;
+	}
 	ret = gpiochip_add(&ltq_stp_chip);
 	if (!ret)
-		ret = ltq_stp_hw_init();
+		ret = ltq_stp_hw_init(&pdev->dev);
 
 	return ret;
 }
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
index d5aaf63..e76c29a 100644
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ b/arch/mips/lantiq/xway/mach-easy50601.c
@@ -32,12 +32,7 @@ static struct mtd_partition easy50601_partitions[] = {
 	{
 		.name	= "linux",
 		.offset	= 0x20000,
-		.size	= 0xE0000,
-	},
-	{
-		.name	= "rootfs",
-		.offset	= 0x100000,
-		.size	= 0x300000,
+		.size	= 0x3d0000,
 	},
 };
 
@@ -46,9 +41,15 @@ static struct physmap_flash_data easy50601_flash_data = {
 	.parts		= easy50601_partitions,
 };
 
-static void __init easy50601_init(void)
+static struct ltq_eth_data ltq_eth_data = {
+	.mii_mode = -1, /* use EPHY */
+};
+
+static void __init
+easy50601_init(void)
 {
 	ltq_register_nor(&easy50601_flash_data);
+	ltq_register_etop(&ltq_eth_data);
 }
 
 MIPS_MACHINE(LTQ_MACH_EASY50601,
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
index ea5027b..581aa76 100644
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ b/arch/mips/lantiq/xway/mach-easy50712.c
@@ -34,12 +34,7 @@ static struct mtd_partition easy50712_partitions[] = {
 	{
 		.name	= "linux",
 		.offset	= 0x20000,
-		.size	= 0xe0000,
-	},
-	{
-		.name	= "rootfs",
-		.offset	= 0x100000,
-		.size	= 0x300000,
+		.size	= 0x3d0000,
 	},
 };
 
@@ -60,15 +55,17 @@ static struct ltq_eth_data ltq_eth_data = {
 	.mii_mode = PHY_INTERFACE_MODE_MII,
 };
 
-static void __init easy50712_init(void)
+static void __init
+easy50712_init(void)
 {
 	ltq_register_gpio_stp();
 	ltq_register_nor(&easy50712_flash_data);
 	ltq_register_pci(&ltq_pci_data);
 	ltq_register_etop(&ltq_eth_data);
+	ltq_register_tapi();
 }
 
 MIPS_MACHINE(LTQ_MACH_EASY50712,
-	     "EASY50712",
-	     "EASY50712 Eval Board",
-	      easy50712_init);
+			"EASY50712",
+			"EASY50712 Eval Board",
+			easy50712_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
deleted file mode 100644
index fe85361..0000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-/* PMU - the power management unit allows us to turn part of the core
- * on and off
- */
-
-/* the enable / disable registers */
-#define LTQ_PMU_PWDCR	0x1C
-#define LTQ_PMU_PWDSR	0x20
-
-#define ltq_pmu_w32(x, y)	ltq_w32((x), ltq_pmu_membase + (y))
-#define ltq_pmu_r32(x)		ltq_r32(ltq_pmu_membase + (x))
-
-static struct resource ltq_pmu_resource = {
-	.name	= "pmu",
-	.start	= LTQ_PMU_BASE_ADDR,
-	.end	= LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static void __iomem *ltq_pmu_membase;
-
-void ltq_pmu_enable(unsigned int module)
-{
-	int err = 1000000;
-
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
-	do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
-
-	if (!err)
-		panic("activating PMU module failed!");
-}
-EXPORT_SYMBOL(ltq_pmu_enable);
-
-void ltq_pmu_disable(unsigned int module)
-{
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
-}
-EXPORT_SYMBOL(ltq_pmu_disable);
-
-int __init ltq_pmu_init(void)
-{
-	if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
-		panic("Failed to insert pmu memory");
-
-	if (request_mem_region(ltq_pmu_resource.start,
-			resource_size(&ltq_pmu_resource), "pmu") < 0)
-		panic("Failed to request pmu memory");
-
-	ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
-				resource_size(&ltq_pmu_resource));
-	if (!ltq_pmu_membase)
-		panic("Failed to remap pmu memory");
-	return 0;
-}
-
-core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
deleted file mode 100644
index ae4959a..0000000
--- a/arch/mips/lantiq/xway/prom-ase.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/export.h>
-#include <linux/clk.h>
-#include <asm/bootinfo.h>
-#include <asm/time.h>
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-
-#define SOC_AMAZON_SE	"Amazon_SE"
-
-#define PART_SHIFT	12
-#define PART_MASK	0x0FFFFFFF
-#define REV_SHIFT	28
-#define REV_MASK	0xF0000000
-
-void __init ltq_soc_detect(struct ltq_soc_info *i)
-{
-	i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
-	i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
-	switch (i->partnum) {
-	case SOC_ID_AMAZON_SE:
-		i->name = SOC_AMAZON_SE;
-		i->type = SOC_TYPE_AMAZON_SE;
-		break;
-
-	default:
-		unreachable();
-		break;
-	}
-}
diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
deleted file mode 100644
index 2228133..0000000
--- a/arch/mips/lantiq/xway/prom-xway.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/export.h>
-#include <linux/clk.h>
-#include <asm/bootinfo.h>
-#include <asm/time.h>
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-
-#define SOC_DANUBE	"Danube"
-#define SOC_TWINPASS	"Twinpass"
-#define SOC_AR9		"AR9"
-
-#define PART_SHIFT	12
-#define PART_MASK	0x0FFFFFFF
-#define REV_SHIFT	28
-#define REV_MASK	0xF0000000
-
-void __init ltq_soc_detect(struct ltq_soc_info *i)
-{
-	i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
-	i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
-	switch (i->partnum) {
-	case SOC_ID_DANUBE1:
-	case SOC_ID_DANUBE2:
-		i->name = SOC_DANUBE;
-		i->type = SOC_TYPE_DANUBE;
-		break;
-
-	case SOC_ID_TWINPASS:
-		i->name = SOC_TWINPASS;
-		i->type = SOC_TYPE_DANUBE;
-		break;
-
-	case SOC_ID_ARX188:
-	case SOC_ID_ARX168:
-	case SOC_ID_ARX182:
-		i->name = SOC_AR9;
-		i->type = SOC_TYPE_AR9;
-		break;
-
-	default:
-		unreachable();
-		break;
-	}
-}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 8b66bd8..970ca17 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -11,26 +11,62 @@
 #include <linux/ioport.h>
 #include <linux/pm.h>
 #include <linux/export.h>
+#include <linux/delay.h>
 #include <asm/reboot.h>
 
 #include <lantiq_soc.h>
 
+#include "../devices.h"
+
 #define ltq_rcu_w32(x, y)	ltq_w32((x), ltq_rcu_membase + (y))
 #define ltq_rcu_r32(x)		ltq_r32(ltq_rcu_membase + (x))
 
-/* register definitions */
-#define LTQ_RCU_RST		0x0010
-#define LTQ_RCU_RST_ALL		0x40000000
-
-#define LTQ_RCU_RST_STAT	0x0014
-#define LTQ_RCU_STAT_SHIFT	26
-
-static struct resource ltq_rcu_resource = {
-	.name   = "rcu",
-	.start  = LTQ_RCU_BASE_ADDR,
-	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+/* reset request register */
+#define RCU_RST_REQ	0x0010
+/* reset status register */
+#define RCU_RST_STAT	0x0014
+
+/* reset cause */
+#define RCU_STAT_SHIFT		26
+/* boot selection */
+#define RCU_BOOT_SEL_SHIFT	26
+#define RCU_BOOT_SEL_MASK	0x7
+
+/* Global SW Reset */
+#define RCU_RD_SRST		BIT(30)
+/* Memory Controller */
+#define RCU_RD_MC		BIT(14)
+/* PCI core */
+#define RCU_RD_PCI		BIT(13)
+/* Voice DFE/AFE */
+#define RCU_RD_DFE_AFE		BIT(12)
+/* DSL AFE */
+#define RCU_RD_DSL_AFE		BIT(11)
+/* SDIO core */
+#define RCU_RD_SDIO		BIT(10)
+/* DMA core */
+#define RCU_RD_DMA		BIT(9)
+/* PPE core */
+#define RCU_RD_PPE		BIT(8)
+/* ARC/DFE core */
+#define RCU_RD_ARC_DFE		BIT(7)
+/* AHB bus */
+#define RCU_RD_AHB		BIT(6)
+/* Ethernet MAC1 */
+#define RCU_RD_ENET_MAC1	BIT(5)
+/* USB and Phy core */
+#define RCU_RD_USB		BIT(4)
+/* CPU1 subsystem */
+#define RCU_RD_CPU1		BIT(3)
+/* FPI bus */
+#define RCU_RD_FPI		BIT(2)
+/* CPU0 subsystem */
+#define RCU_RD_CPU0		BIT(1)
+/* HW reset via HRST pin */
+#define RCU_RD_HRST		BIT(0)
+
+static struct resource ltq_rcu_resource =
+	MEM_RES("rcu", LTQ_RCU_BASE_ADDR, LTQ_RCU_SIZE);
 
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
@@ -38,16 +74,29 @@ static void __iomem *ltq_rcu_membase;
 /* This function is used by the watchdog driver */
 int ltq_reset_cause(void)
 {
-	u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
-	return val >> LTQ_RCU_STAT_SHIFT;
+	u32 val = ltq_rcu_r32(RCU_RST_STAT);
+	return val >> RCU_STAT_SHIFT;
 }
 EXPORT_SYMBOL_GPL(ltq_reset_cause);
 
+unsigned char ltq_boot_select(void)
+{
+	u32 val = ltq_rcu_r32(RCU_RST_STAT);
+	return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
+}
+
+void ltq_reset_once(unsigned int module, ulong usec)
+{
+	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
+	udelay(usec);
+	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
+}
+
 static void ltq_machine_restart(char *command)
 {
 	pr_notice("System restart\n");
 	local_irq_disable();
-	ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
+	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ);
 	unreachable();
 }
 
@@ -67,17 +116,8 @@ static void ltq_machine_power_off(void)
 
 static int __init mips_reboot_setup(void)
 {
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
-		panic("Failed to insert rcu memory");
-
-	if (request_mem_region(ltq_rcu_resource.start,
-			resource_size(&ltq_rcu_resource), "rcu") < 0)
-		panic("Failed to request rcu memory");
-
 	/* remap rcu register range */
-	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
-				resource_size(&ltq_rcu_resource));
+	ltq_rcu_membase = ltq_remap_resource(&ltq_rcu_resource);
 	if (!ltq_rcu_membase)
 		panic("Failed to remap rcu memory");
 
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
deleted file mode 100644
index f6f3267..0000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_ase_asc();
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
deleted file mode 100644
index c292f64..0000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_asc(0);
-	ltq_register_asc(1);
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
-- 
1.7.9.1