aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches-3.3/0002-xway-support.patch
diff options
context:
space:
mode:
authorblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-05 10:12:53 +0000
committerblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-05 10:12:53 +0000
commit5c105d9f3fd086aff195d3849dcf847d6b0bd927 (patch)
tree1229a11f725bfa58aa7c57a76898553bb5f6654a /target/linux/lantiq/patches-3.3/0002-xway-support.patch
downloadopenwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.tar.gz
openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.zip
branch Attitude Adjustment
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/lantiq/patches-3.3/0002-xway-support.patch')
-rw-r--r--target/linux/lantiq/patches-3.3/0002-xway-support.patch1586
1 files changed, 1586 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.3/0002-xway-support.patch b/target/linux/lantiq/patches-3.3/0002-xway-support.patch
new file mode 100644
index 000000000..b3b9599ee
--- /dev/null
+++ b/target/linux/lantiq/patches-3.3/0002-xway-support.patch
@@ -0,0 +1,1586 @@
+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
+