import: Apply ar71xx patches from qsdk.

for i in $(ls <qsdk>/target/linux/ar71xx/patches-3.3/*|sort); do
	patch -p1 <$i;
done

Change-Id: I2e035a3a34acc3dcafcd424888e6bb3dd6423454
diff --git a/Documentation/devicetree/bindings/net/qcom-ag71xx.txt b/Documentation/devicetree/bindings/net/qcom-ag71xx.txt
new file mode 100644
index 0000000..7998459
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/qcom-ag71xx.txt
@@ -0,0 +1,110 @@
+* Qualcomm MDIO IO device
+
+Required properties:
+- compatible : Should be "qcom,ag71xx-mdio"
+- reg : Address and length of the register set for the device
+- reg-names : Resource name
+
+Optional properties:
+- bi-phy-addr : phy address
+- bi-port0-cfg : <force_link speed txpause rxpause duplex>
+		force_link: 0 disable, 1 enable
+		speed: 0 10M, 1 100M, 2 1000M
+		txpause: 0 disable, 1 enable
+		rxpause: 0 disable, 1 enable
+		duplex: 0 half, 1 full
+- bi-port5-cfg : <force_link speed txpause rxpause duplex>
+		Definition is same as bi-port0-cfg.
+- bi-port6-cfg : <force_link speed txpause rxpause duplex>
+		Definition is same as bi-port0-cfg.
+- bi-led-cfg : <led_ctrl0 led_ctrl1 led_ctrl2 led_ctrl3 open_drain>
+		led_ctrl0: value of LED control Register 0
+		led_ctrl1: value of LED control Register 1
+		led_ctrl2: value of LED control Register 2
+		led_ctrl3: value of LED control Register 3
+		open_drain: 0 disable, 1 enable
+- bi-pad0-cfg : <mode rxclk_sel txclk_sel pipe_rxclk_sel txclk_delay_en
+		rxclk_delay_en txclk_delay_sel rxclk_delay_sel
+		sgmii_txclk_phase_sel sgmii_rxclk_phase_sel>
+		mode: 0 invalid, 1 MAC2MAC_MII, 2 MAC2MAC_GMII, 3 MAC_SGMII,
+		      4 MAC2PHY_MII, 5 MAC2PHY_GMII, 6 MAC_RGMII, 7 PHY_GMII,
+		      8 PHY_RGMII, 9 PHY_MII
+		rxclk_sel: 0 disable, 1 enable
+		txclk_sel: 0 disable, 1 enable
+		pipe_rxclk_sel: 0 disable, 1 enable
+		txclk_delay_en: 0 disable, 1 enable
+		rxclk_delay_en: 0 disable, 1 enable
+		txclk_delay_sel: 0 disable, 1 enable
+		rxclk_delay_sel: 0 disable, 1 enable
+		sgmii_txclk_phase_sel: Valid value should be 0, 1, 2, 3, refer to
+				       the user manul of ar8327 for detail.
+		sgmii_rxclk_phase_sel: Valid value should be 0, 1, 2, 3, refer to
+				       the user manul of ar8327 for detail.
+- bi-pad5-cfg : <mode rxclk_sel txclk_sel pipe_rxclk_sel txclk_delay_en
+		rxclk_delay_en txclk_delay_sel rxclk_delay_sel
+		sgmii_txclk_phase_sel sgmii_rxclk_phase_sel>
+		Definition is same as bi-pad0-cfg.
+- bi-pad6-cfg : <mode rxclk_sel txclk_sel pipe_rxclk_sel txclk_delay_en
+		rxclk_delay_en txclk_delay_sel rxclk_delay_sel
+		sgmii_txclk_phase_sel sgmii_rxclk_phase_sel>
+		Definition is same as bi-pad0-cfg.
+
+Example:
+
+MDIO0: mdio@19000000 {
+	compatible = "qcom,ag71xx-mdio";
+	reg = <0x19000000 0x200>;
+	reg-names = "mdio_base";
+
+	bi-phy-addr = <0>;
+	bi-port0-cfg = <1 2 1 1 1>;
+	bi-led-cfg = <0 0xc737c737 0 0x00c30c00 1>;
+	bi-pad0-cfg = <6 0 0 0 1 1 1 2 0 0>;
+};
+
+* Qualcomm ag71xx Ethernet driver
+
+Required properties:
+- compatible : Should be "qcom,ag71xx-eth"
+- reg : Address and length of the register set for the device
+- reg-names : Memory resource name
+- interrupts : Interrupt resourse
+- interrupt-names : Interrupt resource name
+- interrupt-parent : The phandle of the interrupt controller
+- mdio-handle : The phandle for the PHY connected to this ethernet controller
+
+Optional properties:
+- eth-cfg : The value is to configure GMAC Register(ETH_CFG), the bit definition
+	    is different of platforms, refer to the user manual for detail.
+- eth-phy-cfg : < phy_if_mode phy_mask speed duplex>
+	    phy_if_mode: 0 invalid, 1 MII, 2 GMII, 3 SGMII, 4 TBI, 5 RMII, 6 RGMII,
+	    		 7 RGMII_ID, 8 RGMII_RXID, 9 RGMII_TXID, 10 RTBI, 11 SMII
+	    phy_mask: Phy mask
+	    speed:  10 10M, 100 100M, 1000 1000M
+	    duplex: 0 half, 1 full
+- eth-fifo-cfg : <fifo_cfg1 fifo_cfg2 fifo_cfg3>
+	    The values of fifo Registers, refer to user manual for detail.
+- eth-pll-data : <pll_10 pll_100 pll_1000>
+	    The values of pll Registers, refer to user manual for detail.
+- eth-sw-cfg :  <phy4_mii_en phy_poll_mask>
+	    phy4_mii_en: Enable phy4 MII
+	    phy_poll_mask: Phy polling mask
+
+Example:
+
+ETH0: ethernet@19000000 {
+	compatible = "qcom,ag71xx-eth";
+	reg = <0x19000000 0x200>,
+	    <0x18070000 0x14>;
+	reg-names = "mac_base",
+		"cfg_base";
+	interrupts = <4>;
+	interrupt-names = "mac_irq";
+	interrupt-parent = <&vic>;
+	mdio-handle = <&MDIO0>;
+
+	eth-cfg = <0x00000041>;
+	eth-phy-cfg = <6 1 1000 1>;
+	eth-fifo-cfg = <0 0 0>;
+	eth-pll-data = <0 0 0x06000000>;
+};
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index cffcae6..1ae3d3d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -981,6 +981,9 @@
 config MIPS_DISABLE_OBSOLETE_IDE
 	bool
 
+config MYLOADER
+	bool
+
 config SYNC_R4K
 	bool
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index a5a427b..a05273b 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -175,6 +175,7 @@
 #
 libs-$(CONFIG_ARC)		+= arch/mips/fw/arc/
 libs-$(CONFIG_CFE)		+= arch/mips/fw/cfe/
+libs-$(CONFIG_MYLOADER)		+= arch/mips/fw/myloader/
 libs-$(CONFIG_SNIPROM)		+= arch/mips/fw/sni/
 libs-y				+= arch/mips/fw/lib/
 
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
index e0fae8f..160d67c 100644
--- a/arch/mips/ath79/Kconfig
+++ b/arch/mips/ath79/Kconfig
@@ -1,22 +1,79 @@
+# Copyright (c) 2013 The Linux Foundation. All rights reserved.
 if ATH79
 
 menu "Atheros AR71XX/AR724X/AR913X machine selection"
 
+config ATH79_MACH_ALFA_AP96
+	bool "ALFA Network AP96 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+
+config ATH79_MACH_HORNET_UB
+	bool "ALFA Network Hornet-UB board support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_ALFA_NX
+	bool "ALFA Network N2/N5 board support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_ALL0258N
+	bool "Allnet ALL0258N support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_ALL0315N
+	bool "Allnet ALL0315N support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_AP113
+	bool "Atheros AP113 board support"
+	select SOC_AR724X
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_PB9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_USB
+	select ATH79_DEV_ETH
+
 config ATH79_MACH_AP121
 	bool "Atheros AP121 reference board"
 	select SOC_AR933X
+	select ATH79_DEV_ETH
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
-	select ATH79_DEV_SPI
+	select ATH79_DEV_M25P80
 	select ATH79_DEV_USB
 	select ATH79_DEV_WMAC
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros AP121 reference board.
 
-config ATH79_MACH_AP81
-	bool "Atheros AP81 reference board"
-	select SOC_AR913X
+config ATH79_MACH_AP135
+	bool "Atheros AP135 reference board"
+	select SOC_QCA955X
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
 	select ATH79_DEV_SPI
@@ -24,11 +81,176 @@
 	select ATH79_DEV_WMAC
 	help
 	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP135 reference board.
+
+config ATH79_MACH_AP135_DUAL
+	bool "Atheros AP135 Dual reference board"
+	select SOC_QCA955X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_NAND
+	select ATH79_DEV_WMAC
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP135 Dual reference board.
+
+config ATH79_MACH_AP136
+	bool "Atheros AP136 reference board"
+	select SOC_QCA955X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP136 reference board.
+
+config ATH79_MACH_AP143
+	bool "Atheros AP143 reference board"
+	select SOC_QCA953X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_ETH
+	select ATH79_DEV_M25P80
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP143 reference board.
+
+config ATH79_MACH_AP151
+	bool "Atheros AP151 reference board"
+	select SOC_QCA956X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_ETH
+	select ATH79_DEV_M25P80
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP151 reference board.
+
+config ATH79_MACH_AP147
+	bool "Atheros AP147 reference board"
+	select SOC_QCA953X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_ETH
+	select ATH79_DEV_M25P80
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP147 reference board.
+
+config ATH79_MACH_AP152
+	bool "Atheros AP152 reference board"
+	select SOC_QCA956X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_SPI
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_ETH
+	select ATH79_DEV_M25P80
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros AP152 reference board.
+
+config ATH79_MACH_AP81
+	bool "Atheros AP81 reference board"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select USE_OF
+	help
+	  Say 'Y' here if you want your kernel to support the
 	  Atheros AP81 reference board.
 
+config ATH79_MACH_AP83
+	bool "Atheros AP83 board support"
+	select SOC_AR913X
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_AP96
+	bool "Atheros AP96 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_CUS227
+	bool "Qualcomm Atheros CUS227 support"
+	select SOC_AR934X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_NAND
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_I2C
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Qualcomm Atheros CUS227 board.
+
+config ATH79_MACH_DB120
+	bool "Atheros DB120 reference board"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_NFC
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros DB120 reference board.
+
+config ATH79_MACH_DB120_TB388
+	bool "Atheros DB120 reference board with TB388 extension"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_AUDIO
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Atheros DB120 reference board with TB388 extension.
+
+config ATH79_MACH_PB42
+	bool "Atheros PB42 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_M25P80
+
 config ATH79_MACH_PB44
 	bool "Atheros PB44 reference board"
 	select SOC_AR71XX
+	select ATH79_DEV_ETH
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
 	select ATH79_DEV_SPI
@@ -37,27 +259,546 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Atheros PB44 reference board.
 
-config ATH79_MACH_UBNT_XM
-	bool "Ubiquiti Networks XM (rev 1.0) board"
+config ATH79_MACH_PB92
+	bool "Atheros PB92 board support"
 	select SOC_AR724X
+	select ATH79_DEV_ETH
 	select ATH79_DEV_GPIO_BUTTONS
 	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_PB9X_PCI if PCI
+	select ATH79_DEV_USB
+
+config ATH79_MACH_RUBBERDUCK
+	bool "Qualcomm-Atheros RubberDuck board support"
+	select SOC_QCA955X
 	select ATH79_DEV_SPI
 	help
 	  Say 'Y' here if you want your kernel to support the
+	  RubberDuck custom design support.
+
+config ATH79_MACH_GENERIC_DT
+	bool "Qualcomm Atheros reference boards with device tree"
+	select SOC_AR913X
+	select SOC_AR933X
+	select SOC_AR934X
+	select SOC_QCA955X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_NFC
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Qualcomm Atheros reference boards with device tree.
+
+config ATH79_MACH_AW_NR580
+	bool "AzureWave AW-NR580 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_WHR_HP_G300N
+	bool "Buffalo WHR-HP-G300N board support"
+	select SOC_AR724X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_WLAE_AG300N
+	bool "Buffalo WLAE-AG300N board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_WZR_HP_AG300H
+	bool "Buffalo WZR-HP-AG300H board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_WZR_HP_G300NH
+	bool "Buffalo WZR-HP-G300NH board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select RTL8366_SMI
+
+config ATH79_MACH_WZR_HP_G300NH2
+	bool "Buffalo WZR-HP-G300NH2 board support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_WZR_HP_G450H
+	bool "Buffalo WZR-HP-G450H board support"
+	select SOC_AR724X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_WP543
+	bool "Compex WP543/WPJ543 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select MYLOADER
+
+config ATH79_MACH_WPE72
+	bool "Compex WPE72/WPE72NX board support"
+	select SOC_AR724X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select MYLOADER
+
+config ATH79_MACH_DIR_600_A1
+	bool "D-Link DIR-600 A1/DIR-615 E4 support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_NVRAM
+
+config ATH79_MACH_DIR_615_C1
+	bool "D-Link DIR-615 rev. C1 support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+	select ATH79_NVRAM
+
+config ATH79_MACH_DIR_825_B1
+	bool "D-Link DIR-825 rev. B1 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_EW_DORIN
+	bool "embedded wireless Dorin Platform support"
+	select SOC_AR933X
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_WMAC
+	select ATH79_DEV_ETH
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Dorin Platform from www.80211.de .
+
+config ATH79_MACH_JA76PF
+	bool "jjPlus JA76PF board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_JWAP003
+	bool "jjPlus JWAP003 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_WRT160NL
+	bool "Linksys WRT160NL board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+	select ATH79_NVRAM
+
+config ATH79_MACH_WRT400N
+	bool "Linksys WRT400N board support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_RB4XX
+	bool "MikroTik RouterBOARD 4xx series support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_USB
+
+config ATH79_MACH_RB750
+	bool "MikroTik RouterBOARD 750 support"
+	select SOC_AR724X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_USB
+	select ATH79_ROUTERBOOT
+	select RLE_DECOMPRESS
+
+config ATH79_MACH_RB2011
+	bool "MikroTik RouterBOARD 2011 support"
+	select SOC_AR934x
+	select ATH79_DEV_ETH
+	select ATH79_DEV_NFC
+	select ATH79_DEV_WMAC
+	select ATH79_ROUTERBOOT
+
+config ATH79_MACH_WNDR3700
+	bool "NETGEAR WNDR3700 board support"
+	select SOC_AR71XX
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_WNR2000
+	bool "NETGEAR WNR2000 board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_OM2P
+	bool "OpenMesh OM2P board support"
+	select SOC_AR724X
+	select SOC_AR933X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_MR600
+	bool "OpenMesh MR600 board support"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_MZK_W04NU
+	bool "Planex MZK-W04NU board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_MZK_W300NH
+	bool "Planex MZK-W300NH board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_RW2458N
+	bool "Redwave RW2458N board support"
+	select SOC_AR724X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_CAP4200AG
+	bool "Senao CAP4200AG support"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_EAP7660D
+	bool "Senao EAP7660D support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_TL_MR11U
+	bool "TP-LINK TL-MR11U/TL-MR3040 support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_MR3020
+	bool "TP-LINK TL-MR3020 support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_MR3X20
+	bool "TP-LINK TL-MR3220/3420 support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_TL_WA901ND
+	bool "TP-LINK TL-WA901ND/TL-WA7510N support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_TL_WA901ND_V2
+	bool "TP-LINK TL-WA901ND v2 support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WDR4300
+	bool "TP-LINK TL-WDR3600/4300/4310 board support"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR703N
+	bool "TP-LINK TL-WR703N support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR741ND
+	bool "TP-LINK TL-WR741ND support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_TL_WR741ND_V4
+	bool "TP-LINK TL-WR741ND v4 support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR841N_V1
+	bool "TP-LINK TL-WR841N v1 support"
+	select SOC_AR71XX
+	select ATH79_DEV_DSA
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_TL_WR841N_V8
+	bool "TP-LINK TL-WR841N/ND v8 support"
+	select SOC_AR934X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR941ND
+	bool "TP-LINK TL-WR941ND support"
+	select SOC_AR913X
+	select ATH79_DEV_DSA
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR1041N_V2
+	bool "TP-LINK TL-WR1041N v2 support"
+	select SOC_AR934X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR1043ND
+	bool "TP-LINK TL-WR1043ND support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_DEV_WMAC
+
+config ATH79_MACH_TL_WR2543N
+	bool "TP-LINK TL-WR2543N/ND support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_TEW_632BRP
+	bool "TRENDnet TEW-632BRP support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+	select ATH79_NVRAM
+
+config ATH79_MACH_TEW_673GRU
+	bool "TRENDnet TEW-673GRU support"
+	select SOC_AR71XX
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	select ATH79_NVRAM
+
+config ATH79_MACH_TEW_712BR
+	bool "TRENDnet TEW-712BR support"
+	select SOC_AR933X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+	select ATH79_NVRAM
+
+config ATH79_MACH_UBNT
+	bool "Ubiquiti AR71xx based boards support"
+	select SOC_AR71XX
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+
+config ATH79_MACH_UBNT_XM
+	bool "Ubiquiti Networks XM (rev 1.0) board"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_USB
+	help
+	  Say 'Y' here if you want your kernel to support the
 	  Ubiquiti Networks XM (rev 1.0) board.
 
+config ATH79_MACH_ZCN_1523H
+	bool "Zcomax ZCN-1523H support"
+	select SOC_AR724X
+	select ATH79_DEV_AP9X_PCI if PCI
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+
+config ATH79_MACH_NBG460N
+	bool "Zyxel NBG460N/550N/550NH board support"
+	select SOC_AR913X
+	select ATH79_DEV_ETH
+	select ATH79_DEV_GPIO_BUTTONS
+	select ATH79_DEV_LEDS_GPIO
+	select ATH79_DEV_M25P80
+	select ATH79_DEV_WMAC
+
 endmenu
 
 config SOC_AR71XX
 	select USB_ARCH_HAS_EHCI
 	select USB_ARCH_HAS_OHCI
+	select HW_HAS_PCI
 	def_bool n
 
 config SOC_AR724X
 	select USB_ARCH_HAS_EHCI
 	select USB_ARCH_HAS_OHCI
 	select HW_HAS_PCI
+	select PCI_AR724X if PCI
 	def_bool n
 
 config SOC_AR913X
@@ -68,20 +809,93 @@
 	select USB_ARCH_HAS_EHCI
 	def_bool n
 
+config SOC_AR934X
+	select USB_ARCH_HAS_EHCI
+	select HW_HAS_PCI
+	select PCI_AR724X if PCI
+	def_bool n
+
+config SOC_QCA953X
+	select USB_ARCH_HAS_EHCI
+	select HW_HAS_PCI
+	select PCI_AR724X if PCI
+	def_bool n
+
+config SOC_QCA955X
+	select USB_ARCH_HAS_EHCI
+	select HW_HAS_PCI
+	select PCI_AR724X if PCI
+	def_bool n
+
+config SOC_QCA956X
+	select USB_ARCH_HAS_EHCI
+	select HW_HAS_PCI
+	select PCI_AR724X if PCI
+	def_bool n
+
+config ATH79_DEV_AP9X_PCI
+	select ATH79_PCI_ATH9K_FIXUP
+	def_bool n
+
+config ATH79_DEV_AUDIO
+	def_bool n
+
+config ATH79_DEV_DSA
+	def_bool n
+
+config ATH79_DEV_ETH
+	def_bool n
+
+config ATH79_DEV_M25P80
+	select ATH79_DEV_SPI
+	def_bool n
+
+config ATH79_DEV_DSA
+	def_bool n
+
+config ATH79_DEV_ETH
+	def_bool n
+
 config ATH79_DEV_GPIO_BUTTONS
 	def_bool n
 
 config ATH79_DEV_LEDS_GPIO
 	def_bool n
 
+config ATH79_DEV_NFC
+	depends on (SOC_AR934X)
+	def_bool n
+
+config ATH79_DEV_NAND
+	select ATH79_NAND_CALDATA_FIXUP
+	def_bool n
+
 config ATH79_DEV_SPI
 	def_bool n
 
+config ATH79_DEV_I2C
+	def_bool n
+
 config ATH79_DEV_USB
 	def_bool n
 
 config ATH79_DEV_WMAC
-	depends on (SOC_AR913X || SOC_AR933X)
+	depends on (SOC_AR913X || SOC_AR933X || SOC_AR934X || SOC_QCA953X || SOC_QCA955X || SOC_QCA956X)
+	def_bool n
+
+config ATH79_NAND_CALDATA_FIXUP
+	def_bool n
+
+config ATH79_NVRAM
+	def_bool n
+
+config ATH79_PCI_ATH9K_FIXUP
+	def_bool n
+
+config ATH79_ROUTERBOOT
+	def_bool n
+
+config PCI_AR724X
 	def_bool n
 
 endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
index 3b911e09..75ec26a 100644
--- a/arch/mips/ath79/Makefile
+++ b/arch/mips/ath79/Makefile
@@ -1,6 +1,7 @@
 #
 # Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel
 #
+# Copyright (c) 2013 The Linux Foundation. All rights reserved.
 # Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
 # Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
 #
@@ -11,21 +12,111 @@
 obj-y	:= prom.o setup.o irq.o common.o clock.o gpio.o
 
 obj-$(CONFIG_EARLY_PRINTK)		+= early_printk.o
+obj-$(CONFIG_PCI)			+= pci.o
 
 #
 # Devices
 #
 obj-y					+= dev-common.o
+obj-$(CONFIG_ATH79_DEV_AP9X_PCI)	+= dev-ap9x-pci.o
+obj-$(CONFIG_ATH79_DEV_AUDIO)		+= dev-audio.o
+obj-$(CONFIG_ATH79_DEV_DSA)		+= dev-dsa.o
+obj-$(CONFIG_ATH79_DEV_ETH)		+= dev-eth.o
 obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS)	+= dev-gpio-buttons.o
 obj-$(CONFIG_ATH79_DEV_LEDS_GPIO)	+= dev-leds-gpio.o
+obj-$(CONFIG_ATH79_DEV_M25P80)		+= dev-m25p80.o
+obj-$(CONFIG_ATH79_DEV_NAND)		+= dev-nand.o
+obj-$(CONFIG_ATH79_DEV_NFC)		+= dev-nfc.o
 obj-$(CONFIG_ATH79_DEV_SPI)		+= dev-spi.o
+obj-$(CONFIG_ATH79_DEV_I2C)		+= dev-i2c.o
 obj-$(CONFIG_ATH79_DEV_USB)		+= dev-usb.o
 obj-$(CONFIG_ATH79_DEV_WMAC)		+= dev-wmac.o
 
 #
+# Miscellaneous objects
+#
+obj-$(CONFIG_ATH79_NAND_CALDATA_FIXUP)	+= nand-caldata-fixup.o
+obj-$(CONFIG_ATH79_NVRAM)		+= nvram.o
+obj-$(CONFIG_ATH79_PCI_ATH9K_FIXUP)	+= pci-ath9k-fixup.o
+obj-$(CONFIG_ATH79_ROUTERBOOT)		+= routerboot.o
+
+#
 # Machines
 #
+obj-$(CONFIG_ATH79_MACH_ALFA_AP96)	+= mach-alfa-ap96.o
+obj-$(CONFIG_ATH79_MACH_ALFA_NX)	+= mach-alfa-nx.o
+obj-$(CONFIG_ATH79_MACH_ALL0258N)	+= mach-all0258n.o
+obj-$(CONFIG_ATH79_MACH_ALL0315N)	+= mach-all0315n.o
+obj-$(CONFIG_ATH79_MACH_AP113)		+= mach-ap113.o
 obj-$(CONFIG_ATH79_MACH_AP121)		+= mach-ap121.o
+obj-$(CONFIG_ATH79_MACH_AP135)		+= mach-ap135.o
+obj-$(CONFIG_ATH79_MACH_AP135_DUAL)	+= mach-ap135.o
+obj-$(CONFIG_ATH79_MACH_AP136)		+= mach-ap136.o
+obj-$(CONFIG_ATH79_MACH_AP143)		+= mach-ap143.o
+obj-$(CONFIG_ATH79_MACH_AP147)		+= mach-ap147.o
+obj-$(CONFIG_ATH79_MACH_AP151)		+= mach-ap151.o
+obj-$(CONFIG_ATH79_MACH_AP152)		+= mach-ap152.o
 obj-$(CONFIG_ATH79_MACH_AP81)		+= mach-ap81.o
+obj-$(CONFIG_ATH79_MACH_AP83)		+= mach-ap83.o
+obj-$(CONFIG_ATH79_MACH_AP96)		+= mach-ap96.o
+obj-$(CONFIG_ATH79_MACH_AW_NR580)	+= mach-aw-nr580.o
+obj-$(CONFIG_ATH79_MACH_CAP4200AG)	+= mach-cap4200ag.o
+obj-$(CONFIG_ATH79_MACH_CUS227)		+= mach-cus227.o
+obj-$(CONFIG_ATH79_MACH_DB120)		+= mach-db120.o
+obj-$(CONFIG_ATH79_MACH_DB120_TB388)	+= mach-db120-tb388.o
+obj-$(CONFIG_ATH79_MACH_DIR_600_A1)	+= mach-dir-600-a1.o
+obj-$(CONFIG_ATH79_MACH_DIR_615_C1)	+= mach-dir-615-c1.o
+obj-$(CONFIG_ATH79_MACH_DIR_825_B1)	+= mach-dir-825-b1.o
+obj-$(CONFIG_ATH79_MACH_EW_DORIN)	+= mach-ew-dorin.o
+obj-$(CONFIG_ATH79_MACH_EAP7660D)	+= mach-eap7660d.o
+obj-$(CONFIG_ATH79_MACH_GENERIC_DT)	+= mach-generic-dt.o
+obj-$(CONFIG_ATH79_MACH_JA76PF)		+= mach-ja76pf.o
+obj-$(CONFIG_ATH79_MACH_JWAP003)	+= mach-jwap003.o
+obj-$(CONFIG_ATH79_MACH_HORNET_UB)	+= mach-hornet-ub.o
+obj-$(CONFIG_ATH79_MACH_MR600)		+= mach-mr600.o
+obj-$(CONFIG_ATH79_MACH_MZK_W04NU)	+= mach-mzk-w04nu.o
+obj-$(CONFIG_ATH79_MACH_MZK_W300NH)	+= mach-mzk-w300nh.o
+obj-$(CONFIG_ATH79_MACH_NBG460N)	+= mach-nbg460n.o
+obj-$(CONFIG_ATH79_MACH_OM2P)		+= mach-om2p.o
+obj-$(CONFIG_ATH79_MACH_PB42)		+= mach-pb42.o
 obj-$(CONFIG_ATH79_MACH_PB44)		+= mach-pb44.o
+obj-$(CONFIG_ATH79_MACH_PB92)		+= mach-pb92.o
+obj-$(CONFIG_ATH79_MACH_RB4XX)		+= mach-rb4xx.o
+obj-$(CONFIG_ATH79_MACH_RB750)		+= mach-rb750.o
+obj-$(CONFIG_ATH79_MACH_RB2011)		+= mach-rb2011.o
+obj-$(CONFIG_ATH79_MACH_RUBBERDUCK)	+= mach-rubberduck.o
+obj-$(CONFIG_ATH79_MACH_RW2458N)	+= mach-rw2458n.o
+obj-$(CONFIG_ATH79_MACH_TEW_632BRP)	+= mach-tew-632brp.o
+obj-$(CONFIG_ATH79_MACH_TEW_673GRU)	+= mach-tew-673gru.o
+obj-$(CONFIG_ATH79_MACH_TEW_712BR)	+= mach-tew-712br.o
+obj-$(CONFIG_ATH79_MACH_TL_MR11U)	+= mach-tl-mr11u.o
+obj-$(CONFIG_ATH79_MACH_TL_MR3020)	+= mach-tl-mr3020.o
+obj-$(CONFIG_ATH79_MACH_TL_MR3X20)	+= mach-tl-mr3x20.o
+obj-$(CONFIG_ATH79_MACH_TL_WA901ND)	+= mach-tl-wa901nd.o
+obj-$(CONFIG_ATH79_MACH_TL_WA901ND_V2)	+= mach-tl-wa901nd-v2.o
+obj-$(CONFIG_ATH79_MACH_TL_WDR4300)     += mach-tl-wdr4300.o
+obj-$(CONFIG_ATH79_MACH_TL_WR741ND)	+= mach-tl-wr741nd.o
+obj-$(CONFIG_ATH79_MACH_TL_WR741ND_V4)	+= mach-tl-wr741nd-v4.o
+obj-$(CONFIG_ATH79_MACH_TL_WR841N_V1)	+= mach-tl-wr841n.o
+obj-$(CONFIG_ATH79_MACH_TL_WR841N_V8)	+= mach-tl-wr841n-v8.o
+obj-$(CONFIG_ATH79_MACH_TL_WR941ND)	+= mach-tl-wr941nd.o
+obj-$(CONFIG_ATH79_MACH_TL_WR1041N_V2)	+= mach-tl-wr1041n-v2.o
+obj-$(CONFIG_ATH79_MACH_TL_WR1043ND)	+= mach-tl-wr1043nd.o
+obj-$(CONFIG_ATH79_MACH_TL_WR2543N)	+= mach-tl-wr2543n.o
+obj-$(CONFIG_ATH79_MACH_TL_WR703N)	+= mach-tl-wr703n.o
+obj-$(CONFIG_ATH79_MACH_UBNT)		+= mach-ubnt.o
 obj-$(CONFIG_ATH79_MACH_UBNT_XM)	+= mach-ubnt-xm.o
+obj-$(CONFIG_ATH79_MACH_WHR_HP_G300N)	+= mach-whr-hp-g300n.o
+obj-$(CONFIG_ATH79_MACH_WLAE_AG300N)	+= mach-wlae-ag300n.o
+obj-$(CONFIG_ATH79_MACH_WNDR3700)	+= mach-wndr3700.o
+obj-$(CONFIG_ATH79_MACH_WNR2000)	+= mach-wnr2000.o
+obj-$(CONFIG_ATH79_MACH_WP543)		+= mach-wp543.o
+obj-$(CONFIG_ATH79_MACH_WPE72)		+= mach-wpe72.o
+obj-$(CONFIG_ATH79_MACH_WRT160NL)	+= mach-wrt160nl.o
+obj-$(CONFIG_ATH79_MACH_WRT400N)	+= mach-wrt400n.o
+obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH)	+= mach-wzr-hp-g300nh.o
+obj-$(CONFIG_ATH79_MACH_WZR_HP_G300NH2)	+= mach-wzr-hp-g300nh2.o
+obj-$(CONFIG_ATH79_MACH_WZR_HP_AG300H)	+= mach-wzr-hp-ag300h.o
+obj-$(CONFIG_ATH79_MACH_WZR_HP_G450H)	+= mach-wzr-hp-g450h.o
+obj-$(CONFIG_ATH79_MACH_ZCN_1523H)	+= mach-zcn-1523h.o
+
diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c
index 54d0eb4..57035d7 100644
--- a/arch/mips/ath79/clock.c
+++ b/arch/mips/ath79/clock.c
@@ -1,8 +1,11 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X common routines
  *
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
  *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
  *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
  *  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.
@@ -14,6 +17,8 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
+#include <asm/div64.h>
+
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
@@ -163,6 +168,370 @@
 	ath79_uart_clk.rate = ath79_ref_clk.rate;
 }
 
+static u32 __init ar9xxx_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
+				      u32 frac, u32 out_div)
+{
+	u64 t;
+	u32 ret;
+
+	t = ath79_ref_clk.rate;
+	t *= nint;
+	do_div(t, ref_div);
+	ret = t;
+
+	t = ath79_ref_clk.rate;
+	t *= nfrac;
+	do_div(t, ref_div * frac);
+	ret += t;
+
+	ret /= (1 << out_div);
+	return ret;
+}
+
+static void __init ar934x_clocks_init(void)
+{
+	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
+	u32 cpu_pll, ddr_pll;
+	u32 bootstrap;
+	void __iomem *dpll_base;
+
+	dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE);
+
+	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+	if (bootstrap &	AR934X_BOOTSTRAP_REF_CLK_40)
+		ath79_ref_clk.rate = 40 * 1000 * 1000;
+	else
+		ath79_ref_clk.rate = 25 * 1000 * 1000;
+
+	pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
+		frac = 1 << 6;
+	}
+
+	cpu_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+			  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+			   AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_DDR_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
+		frac = 1 << 10;
+	}
+
+	ddr_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
+
+	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+		  AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
+
+	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
+		ath79_cpu_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
+		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
+	else
+		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+		  AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
+
+	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
+		ath79_ddr_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
+		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+		  AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
+
+	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
+		ath79_ahb_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
+
+	ath79_wdt_clk.rate = ath79_ref_clk.rate;
+	ath79_uart_clk.rate = ath79_ref_clk.rate;
+
+	iounmap(dpll_base);
+}
+
+static void __init qca953x_clocks_init(void)
+{
+	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
+	u32 cpu_pll, ddr_pll;
+	u32 bootstrap;
+
+	bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP);
+	if (bootstrap &	QCA953X_BOOTSTRAP_REF_CLK_40)
+		ath79_ref_clk.rate = 40 * 1000 * 1000;
+	else
+		ath79_ref_clk.rate = 25 * 1000 * 1000;
+
+	pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG);
+	out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+		QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+		QCA953X_PLL_CPU_CONFIG_REFDIV_MASK;
+	nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) &
+		QCA953X_PLL_CPU_CONFIG_NINT_MASK;
+	nfrac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
+		QCA953X_PLL_CPU_CONFIG_NFRAC_MASK;
+	frac = 1 << 6;
+
+	cpu_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	pll = ath79_pll_rr(QCA953X_PLL_DDR_CONFIG_REG);
+	out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+		QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+		QCA953X_PLL_DDR_CONFIG_REFDIV_MASK;
+	nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) &
+		QCA953X_PLL_DDR_CONFIG_NINT_MASK;
+	nfrac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
+		QCA953X_PLL_DDR_CONFIG_NFRAC_MASK;
+	frac = 1 << 10;
+
+	ddr_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	clk_ctrl = ath79_pll_rr(QCA953X_PLL_CPU_DDR_CLK_CTRL_REG);
+
+	postdiv = (clk_ctrl >> QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+		  QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
+		ath79_cpu_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
+		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
+	else
+		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+		  QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
+		ath79_ddr_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
+		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+		  QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
+		ath79_ahb_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA953X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
+
+	ath79_wdt_clk.rate = ath79_ref_clk.rate;
+	ath79_uart_clk.rate = ath79_ref_clk.rate;
+}
+
+static void __init qca955x_clocks_init(void)
+{
+	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
+	u32 cpu_pll, ddr_pll;
+	u32 bootstrap;
+
+	bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP);
+	if (bootstrap &	QCA955X_BOOTSTRAP_REF_CLK_40)
+		ath79_ref_clk.rate = 40 * 1000 * 1000;
+	else
+		ath79_ref_clk.rate = 25 * 1000 * 1000;
+
+	pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG);
+	out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+		  QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+		  QCA955X_PLL_CPU_CONFIG_REFDIV_MASK;
+	nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) &
+	       QCA955X_PLL_CPU_CONFIG_NINT_MASK;
+	nfrac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
+	       QCA955X_PLL_CPU_CONFIG_NFRAC_MASK;
+	frac = 1 << 6;
+
+	cpu_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG);
+	out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+		  QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+		  QCA955X_PLL_DDR_CONFIG_REFDIV_MASK;
+	nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) &
+	       QCA955X_PLL_DDR_CONFIG_NINT_MASK;
+	nfrac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
+	       QCA955X_PLL_DDR_CONFIG_NFRAC_MASK;
+	frac = 1 << 10;
+
+	ddr_pll = ar9xxx_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG);
+
+	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+		  QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
+		ath79_cpu_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
+		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+		  QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
+		ath79_ddr_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
+		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
+	else
+		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+		  QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
+		ath79_ahb_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
+
+	ath79_wdt_clk.rate = ath79_ref_clk.rate;
+	ath79_uart_clk.rate = ath79_ref_clk.rate;
+}
+
+static void __init qca956x_clocks_init(void)
+{
+	u32 pll, out_div, ref_div, nint, hfrac, lfrac, clk_ctrl, postdiv;
+	u32 cpu_pll, ddr_pll;
+	u32 bootstrap;
+
+	bootstrap = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP);
+	if (bootstrap &	QCA956X_BOOTSTRAP_REF_CLK_40)
+		ath79_ref_clk.rate = 40 * 1000 * 1000;
+	else
+		ath79_ref_clk.rate = 25 * 1000 * 1000;
+
+	pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG_REG);
+	out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+		  QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+		  QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
+
+	pll = ath79_pll_rr(QCA956X_PLL_CPU_CONFIG1_REG);
+	nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
+	       QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
+	hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
+	       QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK;
+	lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) &
+	       QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK;
+
+	cpu_pll = nint * ath79_ref_clk.rate / ref_div;
+	cpu_pll += (lfrac * ath79_ref_clk.rate) / ((ref_div * 25) << 13);
+	cpu_pll += (hfrac >> 13) * ath79_ref_clk.rate / ref_div;
+	cpu_pll /= (1 << out_div);
+
+	pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG_REG);
+	out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+		  QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+		  QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
+	pll = ath79_pll_rr(QCA956X_PLL_DDR_CONFIG1_REG);
+	nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
+	       QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
+	hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
+	       QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK;
+	lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) &
+	       QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK;
+
+	ddr_pll = nint * ath79_ref_clk.rate / ref_div;
+	ddr_pll += (lfrac * ath79_ref_clk.rate) / ((ref_div * 25) << 13);
+	ddr_pll += (hfrac >> 13) * ath79_ref_clk.rate / ref_div;
+	ddr_pll /= (1 << out_div);
+
+	clk_ctrl = ath79_pll_rr(QCA956X_PLL_CLK_CTRL_REG);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
+		ath79_cpu_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL)
+		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
+		ath79_ddr_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL)
+		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
+	else
+		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
+		ath79_ahb_clk.rate = ath79_ref_clk.rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
+	else
+		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
+
+	ath79_wdt_clk.rate = ath79_ref_clk.rate;
+	ath79_uart_clk.rate = ath79_ref_clk.rate;
+}
+
 void __init ath79_clocks_init(void)
 {
 	if (soc_is_ar71xx())
@@ -173,6 +542,14 @@
 		ar913x_clocks_init();
 	else if (soc_is_ar933x())
 		ar933x_clocks_init();
+	else if (soc_is_ar934x())
+		ar934x_clocks_init();
+	else if (soc_is_qca953x())
+		qca953x_clocks_init();
+	else if (soc_is_qca955x())
+		qca955x_clocks_init();
+	else if (soc_is_qca956x())
+		qca956x_clocks_init();
 	else
 		BUG();
 
diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
index f0fda98..2a5f7f8 100644
--- a/arch/mips/ath79/common.c
+++ b/arch/mips/ath79/common.c
@@ -1,9 +1,13 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X common routines
  *
- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
  *  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.
@@ -19,6 +23,7 @@
 #include "common.h"
 
 static DEFINE_SPINLOCK(ath79_device_reset_lock);
+static DEFINE_MUTEX(ath79_flash_mutex);
 
 u32 ath79_cpu_freq;
 EXPORT_SYMBOL_GPL(ath79_cpu_freq);
@@ -33,6 +38,7 @@
 unsigned int ath79_soc_rev;
 
 void __iomem *ath79_pll_base;
+EXPORT_SYMBOL_GPL(ath79_pll_base);
 void __iomem *ath79_reset_base;
 EXPORT_SYMBOL_GPL(ath79_reset_base);
 void __iomem *ath79_ddr_base;
@@ -67,6 +73,11 @@
 		reg = AR913X_RESET_REG_RESET_MODULE;
 	else if (soc_is_ar933x())
 		reg = AR933X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar934x() ||
+		soc_is_qca953x() ||
+		soc_is_qca955x() ||
+		soc_is_qca956x())
+		reg = AR934X_RESET_REG_RESET_MODULE;
 	else
 		BUG();
 
@@ -91,6 +102,11 @@
 		reg = AR913X_RESET_REG_RESET_MODULE;
 	else if (soc_is_ar933x())
 		reg = AR933X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar934x() ||
+		soc_is_qca953x() ||
+		soc_is_qca955x() ||
+        soc_is_qca956x())
+		reg = AR934X_RESET_REG_RESET_MODULE;
 	else
 		BUG();
 
@@ -100,3 +116,46 @@
 	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
 }
 EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
+
+u32 ath79_device_reset_get(u32 mask)
+{
+	unsigned long flags;
+	u32 reg;
+	u32 ret;
+
+	if (soc_is_ar71xx())
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x())
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x())
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar933x())
+		reg = AR933X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar934x())
+		reg = AR934X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca953x())
+		reg = QCA953X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca956x())
+		reg = QCA953X_RESET_REG_RESET_MODULE;
+	else
+		BUG();
+
+	spin_lock_irqsave(&ath79_device_reset_lock, flags);
+	ret = ath79_reset_rr(reg);
+	spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ath79_device_reset_get);
+
+void ath79_flash_acquire(void)
+{
+	mutex_lock(&ath79_flash_mutex);
+}
+EXPORT_SYMBOL_GPL(ath79_flash_acquire);
+
+void ath79_flash_release(void)
+{
+	mutex_unlock(&ath79_flash_mutex);
+}
+EXPORT_SYMBOL_GPL(ath79_flash_release);
+
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
index 561906c..2d6a514 100644
--- a/arch/mips/ath79/common.h
+++ b/arch/mips/ath79/common.h
@@ -1,6 +1,7 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X common definitions
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
@@ -18,7 +19,7 @@
 #include <linux/init.h>
 
 #define ATH79_MEM_SIZE_MIN	(2 * 1024 * 1024)
-#define ATH79_MEM_SIZE_MAX	(128 * 1024 * 1024)
+#define ATH79_MEM_SIZE_MAX	(256 * 1024 * 1024)
 
 void ath79_clocks_init(void);
 void ath79_ddr_wb_flush(unsigned int reg);
@@ -26,6 +27,9 @@
 void ath79_gpio_function_enable(u32 mask);
 void ath79_gpio_function_disable(u32 mask);
 void ath79_gpio_function_setup(u32 set, u32 clear);
+void ath79_gpio_input_select(unsigned gpio, u8 val);
+void ath79_gpio_output_select(unsigned gpio, u8 val);
+int ath79_gpio_direction_select(unsigned gpio, bool oe);
 void ath79_gpio_init(void);
 
 #endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
index f4956f8..72c01c5 100644
--- a/arch/mips/ath79/dev-common.c
+++ b/arch/mips/ath79/dev-common.c
@@ -87,9 +87,22 @@
 	if (IS_ERR(clk))
 		panic("unable to get UART clock, err=%ld", PTR_ERR(clk));
 
+	if (soc_is_ar71xx())
+		ath79_gpio_function_enable(AR71XX_GPIO_FUNC_UART_EN);
+	else if (soc_is_ar724x())
+		ath79_gpio_function_enable(AR724X_GPIO_FUNC_UART_EN);
+	else if (soc_is_ar913x())
+		ath79_gpio_function_enable(AR913X_GPIO_FUNC_UART_EN);
+	else if (soc_is_ar933x())
+		ath79_gpio_function_enable(AR933X_GPIO_FUNC_UART_EN);
+
 	if (soc_is_ar71xx() ||
 	    soc_is_ar724x() ||
-	    soc_is_ar913x()) {
+	    soc_is_ar913x() ||
+	    soc_is_ar934x() ||
+	    soc_is_qca953x() ||
+	    soc_is_qca955x() ||
+        soc_is_qca956x()) {
 		ath79_uart_data[0].uartclk = clk_get_rate(clk);
 		platform_device_register(&ath79_uart_device);
 	} else if (soc_is_ar933x()) {
diff --git a/arch/mips/ath79/dev-eth.c b/arch/mips/ath79/dev-eth.c
index 63d56ef..03e3718 100644
--- a/arch/mips/ath79/dev-eth.c
+++ b/arch/mips/ath79/dev-eth.c
@@ -197,7 +197,7 @@
 	case ATH79_SOC_AR9330:
 	case ATH79_SOC_AR9331:
 	case ATH79_SOC_QCA9531:
-	case ATH79_SOC_QCA9561:
+	case ATH79_SOC_QCA956X:
 		mdio_dev = &ath79_mdio1_device;
 		mdio_data = &ath79_mdio1_data;
 		break;
@@ -241,7 +241,7 @@
 		/* fall through */
 	case ATH79_SOC_AR9331:
 	case ATH79_SOC_QCA9531:
-	case ATH79_SOC_QCA9561:
+	case ATH79_SOC_QCA956X:
 		mdio_data->builtin_switch = 1;
 		break;
 
@@ -549,7 +549,7 @@
 	case ATH79_SOC_AR9344:
 	case ATH79_SOC_QCA9531:
 	case ATH79_SOC_QCA9558:
-	case ATH79_SOC_QCA9561:
+	case ATH79_SOC_QCA956X:
 		pll_10 = AR934X_PLL_VAL_10;
 		pll_100 = AR934X_PLL_VAL_100;
 		pll_1000 = AR934X_PLL_VAL_1000;
@@ -629,7 +629,7 @@
 		case ATH79_SOC_AR9330:
 		case ATH79_SOC_AR9331:
 		case ATH79_SOC_QCA9531:
-	    case ATH79_SOC_QCA9561:
+		case ATH79_SOC_QCA956X:
 			pdata->phy_if_mode = PHY_INTERFACE_MODE_MII;
 			break;
 
@@ -700,7 +700,7 @@
 		case ATH79_SOC_AR9342:
 		case ATH79_SOC_AR9344:
 		case ATH79_SOC_QCA9531:
-	    case ATH79_SOC_QCA9561:
+		case ATH79_SOC_QCA956X:
 			switch (pdata->phy_if_mode) {
 			case PHY_INTERFACE_MODE_MII:
 			case PHY_INTERFACE_MODE_GMII:
@@ -942,11 +942,12 @@
 			pdata->fifo_cfg3 = 0x01f00140;
 		break;
 
+	case ATH79_SOC_QCA9531:
+	case ATH79_SOC_QCA956X:
+		pdata->is_qca956x = 1;
 	case ATH79_SOC_AR9341:
 	case ATH79_SOC_AR9342:
 	case ATH79_SOC_AR9344:
-	case ATH79_SOC_QCA9531:
-	case ATH79_SOC_QCA9561:
 		if (id == 1) {
 			pdata->switch_data = &ath79_switch_data;
 
@@ -1017,7 +1018,7 @@
 		case ATH79_SOC_AR9330:
 		case ATH79_SOC_AR9331:
 		case ATH79_SOC_QCA9531:
-	    case ATH79_SOC_QCA9561:
+		case ATH79_SOC_QCA956X:
 			pdata->mii_bus_dev = &ath79_mdio1_device.dev;
 			break;
 
diff --git a/arch/mips/ath79/dev-usb.c b/arch/mips/ath79/dev-usb.c
index 002d6d2..cc936ed 100644
--- a/arch/mips/ath79/dev-usb.c
+++ b/arch/mips/ath79/dev-usb.c
@@ -17,60 +17,90 @@
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
 #include "dev-usb.h"
 
-static struct resource ath79_ohci_resources[] = {
-	[0] = {
-		/* .start and .end fields are filled dynamically */
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= ATH79_MISC_IRQ_OHCI,
-		.end	= ATH79_MISC_IRQ_OHCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
+static struct resource ath79_ohci_resources[2];
 
 static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct usb_ohci_pdata ath79_ohci_pdata = {
+};
+
 static struct platform_device ath79_ohci_device = {
-	.name		= "ath79-ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
 	.resource	= ath79_ohci_resources,
 	.num_resources	= ARRAY_SIZE(ath79_ohci_resources),
 	.dev = {
 		.dma_mask		= &ath79_ohci_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource ath79_ehci_resources[] = {
-	[0] = {
-		/* .start and .end fields are filled dynamically */
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= ATH79_CPU_IRQ_USB,
-		.end	= ATH79_CPU_IRQ_USB,
-		.flags	= IORESOURCE_IRQ,
+		.platform_data		= &ath79_ohci_pdata,
 	},
 };
 
 static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32);
-static struct platform_device ath79_ehci_device = {
-	.name		= "ath79-ehci",
-	.id		= -1,
-	.resource	= ath79_ehci_resources,
-	.num_resources	= ARRAY_SIZE(ath79_ehci_resources),
+
+static struct usb_ehci_pdata ath79_ehci_pdata_v1 = {
+	.has_synopsys_hc_bug	= 1,
+	.port_power_off		= 1,
+};
+
+static struct resource ath79_ehci0_resources[2];
+struct usb_ehci_pdata ath79_ehci0_pdata_v2 = {
+	.caps_offset		= 0x100,
+	.has_tt			= 1,
+	.port_power_off		= 1,
+};
+static struct platform_device ath79_ehci0_device = {
+	.name		= "ehci-platform",
+	.id		= 0,
+	.resource	= ath79_ehci0_resources,
+	.num_resources	= ARRAY_SIZE(ath79_ehci0_resources),
 	.dev = {
 		.dma_mask		= &ath79_ehci_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 };
 
+static struct resource ath79_ehci1_resources[2];
+struct usb_ehci_pdata ath79_ehci1_pdata_v2 = {
+	.caps_offset		= 0x100,
+	.has_tt			= 1,
+	.port_power_off		= 1,
+};
+static struct platform_device ath79_ehci1_device = {
+	.name		= "ehci-platform",
+	.id		= 1,
+	.resource	= ath79_ehci1_resources,
+	.num_resources	= ARRAY_SIZE(ath79_ehci1_resources),
+	.dev = {
+		.dma_mask		= &ath79_ehci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static void __init ath79_usb_init_resource(struct resource res[2],
+					   unsigned long base,
+					   unsigned long size,
+					   int irq)
+{
+	memset(res, 0, sizeof(res));
+
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = base;
+	res[0].end = base + size - 1;
+
+	res[1].flags = IORESOURCE_IRQ;
+	res[1].start = irq;
+	res[1].end = irq;
+}
+
 #define AR71XX_USB_RESET_MASK	(AR71XX_RESET_USB_HOST | \
 				 AR71XX_RESET_USB_PHY | \
 				 AR71XX_RESET_USB_OHCI_DLL)
@@ -95,14 +125,14 @@
 
 	mdelay(900);
 
-	ath79_ohci_resources[0].start = AR71XX_OHCI_BASE;
-	ath79_ohci_resources[0].end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1;
+	ath79_usb_init_resource(ath79_ohci_resources, AR71XX_OHCI_BASE,
+				AR71XX_OHCI_SIZE, ATH79_MISC_IRQ_OHCI);
 	platform_device_register(&ath79_ohci_device);
 
-	ath79_ehci_resources[0].start = AR71XX_EHCI_BASE;
-	ath79_ehci_resources[0].end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar71xx-ehci";
-	platform_device_register(&ath79_ehci_device);
+	ath79_usb_init_resource(ath79_ehci0_resources, AR71XX_EHCI_BASE,
+				AR71XX_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci_pdata_v1;
+	platform_device_register(&ath79_ehci0_device);
 }
 
 static void __init ar7240_usb_setup(void)
@@ -124,8 +154,8 @@
 
 	iounmap(usb_ctrl_base);
 
-	ath79_ohci_resources[0].start = AR7240_OHCI_BASE;
-	ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1;
+	ath79_usb_init_resource(ath79_ohci_resources, AR7240_OHCI_BASE,
+				AR7240_OHCI_SIZE, ATH79_CPU_IRQ_USB);
 	platform_device_register(&ath79_ohci_device);
 }
 
@@ -140,10 +170,9 @@
 	ath79_device_reset_clear(AR724X_RESET_USB_PHY);
 	mdelay(10);
 
-	ath79_ehci_resources[0].start = AR724X_EHCI_BASE;
-	ath79_ehci_resources[0].end = AR724X_EHCI_BASE + AR724X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar724x-ehci";
-	platform_device_register(&ath79_ehci_device);
+	ath79_usb_init_resource(ath79_ehci0_resources, AR724X_EHCI_BASE,
+				AR724X_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
 }
 
 static void __init ar913x_usb_setup(void)
@@ -157,10 +186,9 @@
 	ath79_device_reset_clear(AR913X_RESET_USB_PHY);
 	mdelay(10);
 
-	ath79_ehci_resources[0].start = AR913X_EHCI_BASE;
-	ath79_ehci_resources[0].end = AR913X_EHCI_BASE + AR913X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar913x-ehci";
-	platform_device_register(&ath79_ehci_device);
+	ath79_usb_init_resource(ath79_ehci0_resources, AR913X_EHCI_BASE,
+				AR913X_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
 }
 
 static void __init ar933x_usb_setup(void)
@@ -174,10 +202,109 @@
 	ath79_device_reset_clear(AR933X_RESET_USB_PHY);
 	mdelay(10);
 
-	ath79_ehci_resources[0].start = AR933X_EHCI_BASE;
-	ath79_ehci_resources[0].end = AR933X_EHCI_BASE + AR933X_EHCI_SIZE - 1;
-	ath79_ehci_device.name = "ar933x-ehci";
-	platform_device_register(&ath79_ehci_device);
+	ath79_usb_init_resource(ath79_ehci0_resources, AR933X_EHCI_BASE,
+				AR933X_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
+}
+
+static void __init ar934x_usb_setup(void)
+{
+	u32 bootstrap;
+
+	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+	if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
+		return;
+
+	ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE);
+	udelay(1000);
+
+	ath79_device_reset_clear(AR934X_RESET_USB_PHY);
+	udelay(1000);
+
+	ath79_device_reset_clear(AR934X_RESET_USB_PHY_ANALOG);
+	udelay(1000);
+
+	ath79_device_reset_clear(AR934X_RESET_USB_HOST);
+	udelay(1000);
+
+	ath79_usb_init_resource(ath79_ehci0_resources, AR934X_EHCI_BASE,
+				AR934X_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
+}
+
+static void __init qca953x_usb_setup(void)
+{
+	u32 bootstrap;
+
+	bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP);
+
+	ath79_device_reset_set(QCA953X_RESET_USBSUS_OVERRIDE);
+	udelay(1000);
+
+	ath79_device_reset_clear(QCA953X_RESET_USB_PHY);
+	udelay(1000);
+
+	ath79_device_reset_clear(QCA953X_RESET_USB_PHY_ANALOG);
+	udelay(1000);
+
+	ath79_device_reset_clear(QCA953X_RESET_USB_HOST);
+	udelay(1000);
+
+	ath79_usb_init_resource(ath79_ehci0_resources, QCA953X_EHCI_BASE,
+				QCA953X_EHCI_SIZE, ATH79_CPU_IRQ_USB);
+	ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
+}
+
+static void __init qca955x_usb_setup(u32 id)
+{
+	if (!id) {
+		ath79_usb_init_resource(ath79_ehci0_resources,
+				QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE,
+				ATH79_IP3_IRQ(0));
+		ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
+	} else {
+		ath79_usb_init_resource(ath79_ehci1_resources,
+				QCA955X_EHCI1_BASE, QCA955X_EHCI_SIZE,
+				ATH79_IP3_IRQ(1));
+		ath79_ehci1_device.dev.platform_data = &ath79_ehci1_pdata_v2;
+	}
+}
+
+static void __init qca956x_usb_setup(u32 id)
+{
+	if (!id) {
+		ath79_usb_init_resource(ath79_ehci0_resources,
+				QCA956X_EHCI0_BASE, QCA956X_EHCI_SIZE,
+				ATH79_IP3_IRQ(0));
+		ath79_ehci0_device.dev.platform_data = &ath79_ehci0_pdata_v2;
+	} else {
+		ath79_usb_init_resource(ath79_ehci1_resources,
+				QCA956X_EHCI1_BASE, QCA956X_EHCI_SIZE,
+				ATH79_IP3_IRQ(1));
+		ath79_ehci1_device.dev.platform_data = &ath79_ehci1_pdata_v2;
+	}
+}
+
+void ath79_init_usb_pdata(void)
+{
+	if (soc_is_ar7241() || soc_is_ar7242())
+		ar724x_usb_setup();
+	else if (soc_is_ar913x())
+		ar913x_usb_setup();
+	else if (soc_is_ar933x())
+		ar933x_usb_setup();
+	else if (soc_is_ar934x())
+		ar934x_usb_setup();
+	else if (soc_is_qca953x())
+		qca953x_usb_setup();
+	else if (soc_is_qca955x()) {
+		qca955x_usb_setup(0);
+		qca955x_usb_setup(1);
+	} else if (soc_is_qca956x()) {
+		qca956x_usb_setup(0);
+		qca956x_usb_setup(1);
+	} else
+		BUG();
 }
 
 void __init ath79_register_usb(void)
@@ -186,12 +313,11 @@
 		ath79_usb_setup();
 	else if (soc_is_ar7240())
 		ar7240_usb_setup();
-	else if (soc_is_ar7241() || soc_is_ar7242())
-		ar724x_usb_setup();
-	else if (soc_is_ar913x())
-		ar913x_usb_setup();
-	else if (soc_is_ar933x())
-		ar933x_usb_setup();
-	else
-		BUG();
+	else {
+		ath79_init_usb_pdata();
+		platform_device_register(&ath79_ehci0_device);
+
+		if (soc_is_qca955x() || soc_is_qca956x())
+			platform_device_register(&ath79_ehci1_device);
+	}
 }
diff --git a/arch/mips/ath79/dev-usb.h b/arch/mips/ath79/dev-usb.h
index 4b86a69..062d55c 100644
--- a/arch/mips/ath79/dev-usb.h
+++ b/arch/mips/ath79/dev-usb.h
@@ -12,6 +12,12 @@
 #ifndef _ATH79_DEV_USB_H
 #define _ATH79_DEV_USB_H
 
+#include <linux/usb/ehci_pdriver.h>
+
+extern struct usb_ehci_pdata ath79_ehci0_pdata_v2;
+extern struct usb_ehci_pdata ath79_ehci1_pdata_v2;
+
 void ath79_register_usb(void);
+void ath79_init_usb_pdata(void);
 
 #endif /* _ATH79_DEV_USB_H */
diff --git a/arch/mips/ath79/dev-wmac.c b/arch/mips/ath79/dev-wmac.c
index 9c717bf..70e71a0 100644
--- a/arch/mips/ath79/dev-wmac.c
+++ b/arch/mips/ath79/dev-wmac.c
@@ -1,9 +1,12 @@
 /*
  *  Atheros AR913X/AR933X SoC built-in WMAC device support
  *
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
+ *  Parts of this file are based on Atheros 2.6.15/2.6.31 BSP
+ *
  *  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.
@@ -12,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
+#include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/ath9k_platform.h>
 
@@ -19,15 +23,22 @@
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "dev-wmac.h"
 
-static struct ath9k_platform_data ath79_wmac_data;
+#ifdef CONFIG_OF
+#include <linux/of_platform.h>
+#endif
+
+static u8 ath79_wmac_mac[ETH_ALEN];
+
+struct ath9k_platform_data ath79_wmac_data = {
+	.led_pin = -1,
+};
 
 static struct resource ath79_wmac_resources[] = {
 	{
 		/* .start and .end fields are filled dynamically */
 		.flags	= IORESOURCE_MEM,
 	}, {
-		.start	= ATH79_CPU_IRQ_IP2,
-		.end	= ATH79_CPU_IRQ_IP2,
+		/* .start and .end fields are filled dynamically */
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -53,18 +64,37 @@
 
 	ath79_wmac_resources[0].start = AR913X_WMAC_BASE;
 	ath79_wmac_resources[0].end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2;
+	ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2;
 }
 
 
 static int ar933x_wmac_reset(void)
 {
+	int retries = 20;
+
 	ath79_device_reset_set(AR933X_RESET_WMAC);
 	ath79_device_reset_clear(AR933X_RESET_WMAC);
 
-	return 0;
+	while (1) {
+		u32 bootstrap;
+
+		bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+		if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
+			return 0;
+
+		if (retries-- == 0)
+			break;
+
+		udelay(10000);
+		retries++;
+	}
+
+	pr_err("ar933x: WMAC reset timed out");
+	return -ETIMEDOUT;
 }
 
-static int ar933x_r1_get_wmac_revision(void)
+static int ar93xx_get_soc_revision(void)
 {
 	return ath79_soc_rev;
 }
@@ -79,6 +109,8 @@
 
 	ath79_wmac_resources[0].start = AR933X_WMAC_BASE;
 	ath79_wmac_resources[0].end = AR933X_WMAC_BASE + AR933X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_CPU_IRQ_IP2;
+	ath79_wmac_resources[1].end = ATH79_CPU_IRQ_IP2;
 
 	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
 	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
@@ -87,17 +119,245 @@
 		ath79_wmac_data.is_clk_25mhz = true;
 
 	if (ath79_soc_rev == 1)
-		ath79_wmac_data.get_mac_revision = ar933x_r1_get_wmac_revision;
+		ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision;
 
 	ath79_wmac_data.external_reset = ar933x_wmac_reset;
 }
 
-void __init ath79_register_wmac(u8 *cal_data)
+static void ar934x_wmac_setup(void)
+{
+	u32 t;
+
+	ath79_wmac_device.name = "ar934x_wmac";
+
+	ath79_wmac_resources[0].start = AR934X_WMAC_BASE;
+	ath79_wmac_resources[0].end = AR934X_WMAC_BASE + AR934X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+
+	t = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+	if (t & AR934X_BOOTSTRAP_REF_CLK_40)
+		ath79_wmac_data.is_clk_25mhz = false;
+	else
+		ath79_wmac_data.is_clk_25mhz = true;
+}
+
+static void qca953x_wmac_setup(void)
+{
+	u32 t;
+
+	ath79_wmac_device.name = "qca953x_wmac";
+
+	ath79_wmac_resources[0].start = QCA953X_WMAC_BASE;
+	ath79_wmac_resources[0].end = QCA953X_WMAC_BASE + QCA953X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+
+	t = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP);
+	if (t & QCA953X_BOOTSTRAP_REF_CLK_40)
+		ath79_wmac_data.is_clk_25mhz = false;
+	else
+		ath79_wmac_data.is_clk_25mhz = true;
+
+	ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision;
+}
+
+static void qca955x_wmac_setup(void)
+{
+	u32 t;
+
+	ath79_wmac_device.name = "qca955x_wmac";
+
+	ath79_wmac_resources[0].start = QCA955X_WMAC_BASE;
+	ath79_wmac_resources[0].end = QCA955X_WMAC_BASE + QCA955X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+
+	t = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP);
+	if (t & QCA955X_BOOTSTRAP_REF_CLK_40)
+		ath79_wmac_data.is_clk_25mhz = false;
+	else
+		ath79_wmac_data.is_clk_25mhz = true;
+}
+
+static void qca956x_wmac_setup(void)
+{
+	u32 t;
+
+	ath79_wmac_device.name = "qca956x_wmac";
+
+	ath79_wmac_resources[0].start = QCA956X_WMAC_BASE;
+	ath79_wmac_resources[0].end = QCA956X_WMAC_BASE + QCA956X_WMAC_SIZE - 1;
+	ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1);
+	ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1);
+
+	t = ath79_reset_rr(QCA956X_RESET_REG_BOOTSTRAP);
+	if (t & QCA956X_BOOTSTRAP_REF_CLK_40)
+		ath79_wmac_data.is_clk_25mhz = false;
+	else
+		ath79_wmac_data.is_clk_25mhz = true;
+}
+
+static bool __init
+ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data)
+{
+	int timeout = 1000;
+	u32 val;
+
+	__raw_readl(base + AR9300_OTP_BASE + (4 * addr));
+	while (timeout--) {
+		val = __raw_readl(base + AR9300_OTP_STATUS);
+		if ((val & AR9300_OTP_STATUS_TYPE) == AR9300_OTP_STATUS_VALID)
+			break;
+
+		udelay(10);
+	}
+
+	if (!timeout)
+		return false;
+
+	*data = __raw_readl(base + AR9300_OTP_READ_DATA);
+	return true;
+}
+
+static bool __init
+ar93xx_wmac_otp_read(void __iomem *base, int addr, u8 *dest, int len)
+{
+	u32 data;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		int offset = 8 * ((addr - i) % 4);
+
+		if (!ar93xx_wmac_otp_read_word(base, (addr - i) / 4, &data))
+			return false;
+
+		dest[i] = (data >> offset) & 0xff;
+	}
+
+	return true;
+}
+
+static bool __init
+ar93xx_wmac_otp_uncompress(void __iomem *base, int addr, int len, u8 *dest,
+			   int dest_start, int dest_len)
+{
+	int dest_bytes = 0;
+	int offset = 0;
+	int end = addr - len;
+	u8 hdr[2];
+
+	while (addr > end) {
+		if (!ar93xx_wmac_otp_read(base, addr, hdr, 2))
+			return false;
+
+		addr -= 2;
+		offset += hdr[0];
+
+		if (offset <= dest_start + dest_len &&
+		    offset + len >= dest_start) {
+			int data_offset = 0;
+			int dest_offset = 0;
+			int copy_len;
+
+			if (offset < dest_start)
+				data_offset = dest_start - offset;
+			else
+				dest_offset = offset - dest_start;
+
+			copy_len = len - data_offset;
+			if (copy_len > dest_len - dest_offset)
+				copy_len = dest_len - dest_offset;
+
+			ar93xx_wmac_otp_read(base, addr - data_offset,
+					     dest + dest_offset,
+					     copy_len);
+
+			dest_bytes += copy_len;
+		}
+		addr -= hdr[1];
+	}
+	return !!dest_bytes;
+}
+
+bool __init ar93xx_wmac_read_mac_address(u8 *dest)
+{
+	void __iomem *base;
+	bool ret = false;
+	int addr = 0x1ff;
+	unsigned int len;
+	u32 hdr_u32;
+	u8 *hdr = (u8 *) &hdr_u32;
+	u8 mac[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 };
+	int mac_start = 2, mac_end = 8;
+
+	BUG_ON(!soc_is_ar933x() && !soc_is_ar934x() && !soc_is_qca953x());
+	base = ioremap_nocache(AR933X_WMAC_BASE, AR933X_WMAC_SIZE);
+	while (addr > sizeof(hdr)) {
+		if (!ar93xx_wmac_otp_read(base, addr, hdr, sizeof(hdr)))
+			break;
+
+		if (hdr_u32 == 0 || hdr_u32 == ~0)
+			break;
+
+		len = (hdr[1] << 4) | (hdr[2] >> 4);
+		addr -= 4;
+
+		switch (hdr[0] >> 5) {
+		case 0:
+			if (len < mac_end)
+				break;
+
+			ar93xx_wmac_otp_read(base, addr - mac_start, mac, 6);
+			ret = true;
+			break;
+		case 3:
+			ret |= ar93xx_wmac_otp_uncompress(base, addr, len, mac,
+							  mac_start, 6);
+			break;
+		default:
+			break;
+		}
+
+		addr -= len + 2;
+	}
+
+	iounmap(base);
+	if (ret)
+		memcpy(dest, mac, 6);
+
+	return ret;
+}
+
+void __init ath79_wmac_disable_2ghz(void)
+{
+	ath79_wmac_data.disable_2ghz = true;
+}
+
+void __init ath79_wmac_disable_5ghz(void)
+{
+	ath79_wmac_data.disable_5ghz = true;
+}
+
+__init struct ath9k_platform_data *ath79_get_wmac_data(void)
+{
+	return &ath79_wmac_data;
+}
+
+void ath79_init_wmac_pdata(u8 *cal_data, u8 *mac_addr)
 {
 	if (soc_is_ar913x())
 		ar913x_wmac_setup();
 	else if (soc_is_ar933x())
 		ar933x_wmac_setup();
+	else if (soc_is_ar934x())
+		ar934x_wmac_setup();
+	else if (soc_is_qca953x())
+		qca953x_wmac_setup();
+	else if (soc_is_qca955x())
+		qca955x_wmac_setup();
+	else if (soc_is_qca956x())
+		qca956x_wmac_setup();
 	else
 		BUG();
 
@@ -105,5 +365,25 @@
 		memcpy(ath79_wmac_data.eeprom_data, cal_data,
 		       sizeof(ath79_wmac_data.eeprom_data));
 
+	if (mac_addr) {
+		memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac));
+		ath79_wmac_data.macaddr = ath79_wmac_mac;
+	}
+}
+
+#ifdef CONFIG_OF
+void ath79_wmac_dt_fixup(void *auxdata)
+{
+	struct of_dev_auxdata *of_auxdata = (struct of_dev_auxdata *)auxdata;
+	of_auxdata->name = (char *)ath79_wmac_device.name;
+	of_auxdata->phys_addr = ath79_wmac_resources[0].start;
+}
+#else
+void ath79_wmac_dt_fixup(void *auxdata) {}
+#endif
+
+void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr)
+{
+	ath79_init_wmac_pdata(cal_data, mac_addr);
 	platform_device_register(&ath79_wmac_device);
 }
diff --git a/arch/mips/ath79/dev-wmac.h b/arch/mips/ath79/dev-wmac.h
index c9cd870..28ccbb4 100644
--- a/arch/mips/ath79/dev-wmac.h
+++ b/arch/mips/ath79/dev-wmac.h
@@ -12,6 +12,17 @@
 #ifndef _ATH79_DEV_WMAC_H
 #define _ATH79_DEV_WMAC_H
 
-void ath79_register_wmac(u8 *cal_data);
+#include <linux/ath9k_platform.h>
+
+extern struct ath9k_platform_data ath79_wmac_data;
+
+void ath79_init_wmac_pdata(u8 *cal_data, u8 *mac_addr);
+void ath79_wmac_dt_fixup(void *auxdata);
+void ath79_register_wmac(u8 *cal_data, u8 *mac_addr);
+void ath79_wmac_disable_2ghz(void);
+void ath79_wmac_disable_5ghz(void);
+
+bool ar93xx_wmac_read_mac_address(u8 *dest);
+struct ath9k_platform_data *ath79_get_wmac_data(void);
 
 #endif /* _ATH79_DEV_WMAC_H */
diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
index 6a51ced..c60d384 100644
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -56,6 +56,46 @@
 	/* nothing to do */
 }
 
+static void prom_enable_uart(u32 id)
+{
+	void __iomem *gpio_base;
+	u32 uart_en;
+	u32 t;
+
+	switch (id) {
+	case REV_ID_MAJOR_AR71XX:
+		uart_en = AR71XX_GPIO_FUNC_UART_EN;
+		break;
+
+	case REV_ID_MAJOR_AR7240:
+	case REV_ID_MAJOR_AR7241:
+	case REV_ID_MAJOR_AR7242:
+		uart_en = AR724X_GPIO_FUNC_UART_EN;
+		break;
+
+	case REV_ID_MAJOR_AR913X:
+		uart_en = AR913X_GPIO_FUNC_UART_EN;
+		break;
+
+	case REV_ID_MAJOR_AR9330:
+	case REV_ID_MAJOR_AR9331:
+		uart_en = AR933X_GPIO_FUNC_UART_EN;
+		break;
+
+	case REV_ID_MAJOR_AR9341:
+	case REV_ID_MAJOR_AR9342:
+	case REV_ID_MAJOR_AR9344:
+		/* TODO */
+	default:
+		return;
+	}
+
+	gpio_base = (void __iomem *)(KSEG1ADDR(AR71XX_GPIO_BASE));
+	t = __raw_readl(gpio_base + AR71XX_GPIO_REG_FUNC);
+	t |= uart_en;
+	__raw_writel(t, gpio_base + AR71XX_GPIO_REG_FUNC);
+}
+
 static void prom_putchar_init(void)
 {
 	void __iomem *base;
@@ -71,6 +111,13 @@
 	case REV_ID_MAJOR_AR7241:
 	case REV_ID_MAJOR_AR7242:
 	case REV_ID_MAJOR_AR913X:
+	case REV_ID_MAJOR_AR9341:
+	case REV_ID_MAJOR_AR9342:
+	case REV_ID_MAJOR_AR9344:
+	case REV_ID_MAJOR_QCA9531_V1:
+	case REV_ID_MAJOR_QCA9531_V2:
+	case REV_ID_MAJOR_QCA9558:
+	case REV_ID_MAJOR_QCA956X:
 		_prom_putchar = prom_putchar_ar71xx;
 		break;
 
@@ -81,8 +128,10 @@
 
 	default:
 		_prom_putchar = prom_putchar_dummy;
-		break;
+		return;
 	}
+
+	prom_enable_uart(id);
 }
 
 void prom_putchar(unsigned char ch)
diff --git a/arch/mips/ath79/gpio.c b/arch/mips/ath79/gpio.c
index a2f8ca6..a4deeb3 100644
--- a/arch/mips/ath79/gpio.c
+++ b/arch/mips/ath79/gpio.c
@@ -1,9 +1,13 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X GPIO API support
  *
- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
  *  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.
@@ -17,15 +21,29 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <linux/of.h>
 
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/irq.h>
 #include "common.h"
 
-static void __iomem *ath79_gpio_base;
+void __iomem *ath79_gpio_base;
+EXPORT_SYMBOL_GPL(ath79_gpio_base);
+
 static unsigned long ath79_gpio_count;
 static DEFINE_SPINLOCK(ath79_gpio_lock);
 
+/*
+ * gpio_both_edge is a bitmask of which gpio pins need to have
+ * the detect priority flipped from the interrupt handler to
+ * emulate IRQ_TYPE_EDGE_BOTH.
+ */
+static unsigned long gpio_both_edge = 0;
+
 static void __ath79_gpio_set_value(unsigned gpio, int value)
 {
 	void __iomem *base = ath79_gpio_base;
@@ -89,6 +107,68 @@
 	return 0;
 }
 
+static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int value)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	if (value)
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
+	else
+		__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
+		     base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
+int ath79_gpio_direction_select(unsigned gpio, bool oe)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+	bool ieq_1 = (soc_is_ar934x() ||
+			soc_is_qca953x() ||
+			soc_is_qca955x() ||
+			soc_is_qca956x());
+
+	if (gpio >= ath79_gpio_count)
+		return -1;
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	if ((ieq_1 && oe) || (!ieq_1 && !oe))
+		__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << gpio),
+				base + AR71XX_GPIO_REG_OE);
+	else
+		__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << gpio),
+				base + AR71XX_GPIO_REG_OE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+
+	return 0;
+}
+
 static struct gpio_chip ath79_gpio_chip = {
 	.label			= "ath79",
 	.get			= ath79_gpio_get_value,
@@ -98,51 +178,252 @@
 	.base			= 0,
 };
 
+static void __iomem *ath79_gpio_get_function_reg(void)
+{
+	u32 reg = 0;
+
+	if (soc_is_ar71xx() ||
+	    soc_is_ar724x() ||
+	    soc_is_ar913x() ||
+	    soc_is_ar933x())
+		reg = AR71XX_GPIO_REG_FUNC;
+	else if (soc_is_ar934x() || soc_is_qca953x() || soc_is_qca956x())
+		reg = AR934X_GPIO_REG_FUNC;
+	else
+		BUG();
+
+	return ath79_gpio_base + reg;
+}
+
 void ath79_gpio_function_enable(u32 mask)
 {
-	void __iomem *base = ath79_gpio_base;
+	void __iomem *reg = ath79_gpio_get_function_reg();
 	unsigned long flags;
 
 	spin_lock_irqsave(&ath79_gpio_lock, flags);
 
-	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
-		     base + AR71XX_GPIO_REG_FUNC);
+	__raw_writel(__raw_readl(reg) | mask, reg);
 	/* flush write */
-	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+	__raw_readl(reg);
 
 	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
 }
 
 void ath79_gpio_function_disable(u32 mask)
 {
-	void __iomem *base = ath79_gpio_base;
+	void __iomem *reg = ath79_gpio_get_function_reg();
 	unsigned long flags;
 
 	spin_lock_irqsave(&ath79_gpio_lock, flags);
 
-	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
-		     base + AR71XX_GPIO_REG_FUNC);
+	__raw_writel(__raw_readl(reg) & ~mask, reg);
 	/* flush write */
-	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+	__raw_readl(reg);
 
 	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
 }
 
 void ath79_gpio_function_setup(u32 set, u32 clear)
 {
-	void __iomem *base = ath79_gpio_base;
+	void __iomem *reg = ath79_gpio_get_function_reg();
 	unsigned long flags;
 
 	spin_lock_irqsave(&ath79_gpio_lock, flags);
 
-	__raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
-		     base + AR71XX_GPIO_REG_FUNC);
+	__raw_writel((__raw_readl(reg) & ~clear) | set, reg);
 	/* flush write */
-	__raw_readl(base + AR71XX_GPIO_REG_FUNC);
+	__raw_readl(reg);
 
 	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
 }
 
+void __init ath79_gpio_input_select(unsigned gpio, u8 val)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+	unsigned int reg;
+	u32 t, s;
+
+	BUG_ON(!soc_is_ar934x());
+
+	if (gpio >= ath79_gpio_count)
+		return;
+
+	reg = AR934X_GPIO_REG_IN_ENABLE0 + 4 * (val / 4);
+	s = 8 * (val % 4);
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	t = __raw_readl(base + reg);
+	t &= ~(0xff << s);
+	t |= gpio << s;
+	__raw_writel(t, base + reg);
+
+	/* flush write */
+	(void) __raw_readl(base + reg);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+void __init ath79_gpio_output_select(unsigned gpio, u8 val)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+	unsigned int reg;
+	u32 t, s;
+
+	BUG_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x());
+
+	if (gpio >= ath79_gpio_count)
+		return;
+
+	reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4);
+	s = 8 * (gpio % 4);
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	t = __raw_readl(base + reg);
+	t &= ~(0xff << s);
+	t |= val << s;
+	__raw_writel(t, base + reg);
+
+	/* flush write */
+	(void) __raw_readl(base + reg);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+}
+
+static int ath79_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+	int offset = d->irq - ATH79_GPIO_IRQ_BASE;
+	void __iomem *base = ath79_gpio_base;
+	unsigned long flags;
+	unsigned long int_type;
+	unsigned long int_polarity;
+	unsigned long bit = (1 << offset);
+
+	spin_lock_irqsave(&ath79_gpio_lock, flags);
+
+	int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE);
+	int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY);
+
+	gpio_both_edge &= ~bit;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		int_type &= ~bit;
+		int_polarity |= bit;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		int_type &= ~bit;
+		int_polarity &= ~bit;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		int_type |= bit;
+		int_polarity |= bit;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		int_type |= bit;
+		int_polarity &= ~bit;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		int_type |= bit;
+		/* set polarity based on current value */
+		if (gpio_get_value(offset)) {
+			int_polarity &= ~bit;
+		} else {
+			int_polarity |= bit;
+		}
+		/* flip this gpio in the interrupt handler */
+		gpio_both_edge |= bit;
+		break;
+
+	default:
+		spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+		return -EINVAL;
+	}
+
+	__raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE);
+	__raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << offset),
+		     base + AR71XX_GPIO_REG_INT_MODE);
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
+		     base + AR71XX_GPIO_REG_INT_ENABLE);
+
+	spin_unlock_irqrestore(&ath79_gpio_lock, flags);
+	return 0;
+}
+
+static void ath79_gpio_irq_enable(struct irq_data *d)
+{
+	int offset = d->irq - ATH79_GPIO_IRQ_BASE;
+	void __iomem *base = ath79_gpio_base;
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << offset),
+		     base + AR71XX_GPIO_REG_INT_ENABLE);
+}
+
+static void ath79_gpio_irq_disable(struct irq_data *d)
+{
+	int offset = d->irq - ATH79_GPIO_IRQ_BASE;
+	void __iomem *base = ath79_gpio_base;
+
+	__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
+		     base + AR71XX_GPIO_REG_INT_ENABLE);
+}
+
+static struct irq_chip ath79_gpio_irqchip = {
+	.name = "GPIO",
+	.irq_enable = ath79_gpio_irq_enable,
+	.irq_disable = ath79_gpio_irq_disable,
+	.irq_set_type = ath79_gpio_irq_type,
+};
+
+static irqreturn_t ath79_gpio_irq(int irq, void *dev)
+{
+	void __iomem *base = ath79_gpio_base;
+	unsigned int stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING);
+
+	int irq_base = ATH79_GPIO_IRQ_BASE;
+
+	while (stat) {
+		int bit_num = __ffs(stat);
+		unsigned long bit = (1<<bit_num);
+
+		if (bit & gpio_both_edge) {
+			__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY) ^ bit,
+				base + AR71XX_GPIO_REG_INT_POLARITY);
+		}
+
+		handle_nested_irq(irq_base + bit_num);
+		stat &= ~bit;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit ath79_gpio_irq_init(struct gpio_chip *chip)
+{
+	int irq;
+	int irq_base = ATH79_GPIO_IRQ_BASE;
+
+	for (irq = irq_base; irq < irq_base + chip->ngpio; irq++) {
+		irq_set_chip_data(irq, chip);
+		irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, handle_simple_irq);
+		irq_set_nested_thread(irq, 1);
+		irq_set_noprobe(irq);
+	}
+
+	return 0;
+}
+
+
 void __init ath79_gpio_init(void)
 {
 	int err;
@@ -155,15 +436,34 @@
 		ath79_gpio_count = AR913X_GPIO_COUNT;
 	else if (soc_is_ar933x())
 		ath79_gpio_count = AR933X_GPIO_COUNT;
+	else if (soc_is_ar934x())
+		ath79_gpio_count = AR934X_GPIO_COUNT;
+	else if (soc_is_qca953x())
+		ath79_gpio_count = QCA953X_GPIO_COUNT;
+	else if (soc_is_qca955x())
+		ath79_gpio_count = QCA955X_GPIO_COUNT;
+	else if (soc_is_qca956x())
+		ath79_gpio_count = QCA956X_GPIO_COUNT;
 	else
 		BUG();
 
 	ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
 	ath79_gpio_chip.ngpio = ath79_gpio_count;
+	if (soc_is_ar934x() || soc_is_qca953x() || soc_is_qca955x() ||
+	    soc_is_qca956x()) {
+		ath79_gpio_chip.direction_input = ar934x_gpio_direction_input;
+		ath79_gpio_chip.direction_output = ar934x_gpio_direction_output;
+	}
+
+	ath79_gpio_chip.of_node = of_find_node_by_path("/ath79-gpio");
 
 	err = gpiochip_add(&ath79_gpio_chip);
 	if (err)
 		panic("cannot add AR71xx GPIO chip, error=%d", err);
+
+	ath79_gpio_irq_init(&ath79_gpio_chip);
+
+	request_threaded_irq(ATH79_MISC_IRQ_GPIO, NULL, ath79_gpio_irq, IRQF_ONESHOT, "ath79-gpio", NULL);
 }
 
 int gpio_get_value(unsigned gpio)
@@ -186,14 +486,22 @@
 
 int gpio_to_irq(unsigned gpio)
 {
-	/* FIXME */
-	return -EINVAL;
+	if (gpio > ath79_gpio_count) {
+		return -EINVAL;
+	}
+
+	return ATH79_GPIO_IRQ_BASE + gpio;
 }
 EXPORT_SYMBOL(gpio_to_irq);
 
 int irq_to_gpio(unsigned irq)
 {
-	/* FIXME */
-	return -EINVAL;
+	unsigned gpio = irq - ATH79_GPIO_IRQ_BASE;
+
+	if (gpio > ath79_gpio_count) {
+		return -EINVAL;
+	}
+
+	return gpio;
 }
 EXPORT_SYMBOL(irq_to_gpio);
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
index 1b073de..cea67db 100644
--- a/arch/mips/ath79/irq.c
+++ b/arch/mips/ath79/irq.c
@@ -1,10 +1,11 @@
 /*
  *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
  *
- *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
  *
  *  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
@@ -23,8 +24,8 @@
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
 
-static unsigned int ath79_ip2_flush_reg;
-static unsigned int ath79_ip3_flush_reg;
+static void (*ath79_ip2_handler)(void);
+static void (*ath79_ip3_handler)(void);
 
 static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
@@ -34,44 +35,17 @@
 	pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
 		  __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 
-	if (pending & MISC_INT_UART)
-		generic_handle_irq(ATH79_MISC_IRQ_UART);
-
-	else if (pending & MISC_INT_DMA)
-		generic_handle_irq(ATH79_MISC_IRQ_DMA);
-
-	else if (pending & MISC_INT_PERFC)
-		generic_handle_irq(ATH79_MISC_IRQ_PERFC);
-
-	else if (pending & MISC_INT_TIMER)
-		generic_handle_irq(ATH79_MISC_IRQ_TIMER);
-
-	else if (pending & MISC_INT_TIMER2)
-		generic_handle_irq(ATH79_MISC_IRQ_TIMER2);
-
-	else if (pending & MISC_INT_TIMER3)
-		generic_handle_irq(ATH79_MISC_IRQ_TIMER3);
-
-	else if (pending & MISC_INT_TIMER4)
-		generic_handle_irq(ATH79_MISC_IRQ_TIMER4);
-
-	else if (pending & MISC_INT_OHCI)
-		generic_handle_irq(ATH79_MISC_IRQ_OHCI);
-
-	else if (pending & MISC_INT_ERROR)
-		generic_handle_irq(ATH79_MISC_IRQ_ERROR);
-
-	else if (pending & MISC_INT_GPIO)
-		generic_handle_irq(ATH79_MISC_IRQ_GPIO);
-
-	else if (pending & MISC_INT_WDOG)
-		generic_handle_irq(ATH79_MISC_IRQ_WDOG);
-
-	else if (pending & MISC_INT_ETHSW)
-		generic_handle_irq(ATH79_MISC_IRQ_ETHSW);
-
-	else
+	if (!pending) {
 		spurious_interrupt();
+		return;
+	}
+
+	while (pending) {
+		int bit = __ffs(pending);
+
+		generic_handle_irq(ATH79_MISC_IRQ(bit));
+		pending &= ~BIT(bit);
+	}
 }
 
 static void ar71xx_misc_irq_unmask(struct irq_data *d)
@@ -129,7 +103,12 @@
 
 	if (soc_is_ar71xx() || soc_is_ar913x())
 		ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
-	else if (soc_is_ar724x() || soc_is_ar933x())
+	else if (soc_is_ar724x() ||
+		 soc_is_ar933x() ||
+		 soc_is_ar934x() ||
+		 soc_is_qca953x() ||
+		 soc_is_qca955x() ||
+		 soc_is_qca956x())
 		ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
 	else
 		BUG();
@@ -143,6 +122,247 @@
 	irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
 }
 
+static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS);
+
+	if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) {
+		ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE);
+		generic_handle_irq(ATH79_IP2_IRQ(0));
+	} else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) {
+		ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC);
+		generic_handle_irq(ATH79_IP2_IRQ(1));
+	} else {
+		spurious_interrupt();
+	}
+
+	enable_irq(irq);
+}
+
+static void ar934x_ip2_irq_init(void)
+{
+	int i;
+
+	for (i = ATH79_IP2_IRQ_BASE;
+	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch);
+}
+
+static void qca953x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS);
+
+	if (status & QCA953X_PCIE_WMAC_INT_PCIE_ALL) {
+		ath79_ddr_wb_flush(QCA953X_DDR_REG_FLUSH_PCIE);
+		generic_handle_irq(ATH79_IP2_IRQ(0));
+	} else if (status & QCA953X_PCIE_WMAC_INT_WMAC_ALL) {
+		ath79_ddr_wb_flush(QCA953X_DDR_REG_FLUSH_WMAC);
+		generic_handle_irq(ATH79_IP2_IRQ(1));
+	} else {
+		spurious_interrupt();
+	}
+
+	enable_irq(irq);
+}
+
+static void qca953x_irq_init(void)
+{
+	int i;
+
+	for (i = ATH79_IP2_IRQ_BASE;
+	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, qca953x_ip2_irq_dispatch);
+}
+
+static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
+	status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL;
+
+	if (status == 0) {
+		spurious_interrupt();
+		goto enable;
+	}
+
+	if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP2_IRQ(0));
+	}
+
+	if (status & QCA955X_EXT_INT_WMAC_ALL) {
+		/* TODO: flsuh DDR? */
+		generic_handle_irq(ATH79_IP2_IRQ(1));
+	}
+
+enable:
+	enable_irq(irq);
+}
+
+static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS);
+	status &= QCA955X_EXT_INT_PCIE_RC2_ALL |
+		  QCA955X_EXT_INT_USB1 |
+		  QCA955X_EXT_INT_USB2;
+
+	if (status == 0) {
+		spurious_interrupt();
+		goto enable;
+	}
+
+	if (status & QCA955X_EXT_INT_USB1) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(0));
+	}
+
+	if (status & QCA955X_EXT_INT_USB2) {
+		/* TODO: flsuh DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(1));
+	}
+
+	if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(2));
+	}
+
+enable:
+	enable_irq(irq);
+}
+
+static void qca955x_irq_init(void)
+{
+	int i;
+
+	for (i = ATH79_IP2_IRQ_BASE;
+	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, qca955x_ip2_irq_dispatch);
+
+	for (i = ATH79_IP3_IRQ_BASE;
+	     i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP3, qca955x_ip3_irq_dispatch);
+}
+
+static void qca956x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS);
+	status &= QCA956X_EXT_INT_PCIE_RC1_ALL | QCA956X_EXT_INT_WMAC_ALL;
+
+	if (status == 0) {
+		spurious_interrupt();
+		goto enable;
+	}
+
+	if (status & QCA956X_EXT_INT_PCIE_RC1_ALL) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP2_IRQ(0));
+	}
+
+	if (status & QCA956X_EXT_INT_WMAC_ALL) {
+		/* TODO: flsuh DDR? */
+		generic_handle_irq(ATH79_IP2_IRQ(1));
+	}
+
+enable:
+	enable_irq(irq);
+}
+
+static void qca956x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+{
+	u32 status;
+
+	disable_irq_nosync(irq);
+
+	status = ath79_reset_rr(QCA956X_RESET_REG_EXT_INT_STATUS);
+	status &= QCA956X_EXT_INT_PCIE_RC2_ALL |
+		  QCA956X_EXT_INT_USB1 | QCA956X_EXT_INT_USB2;
+
+	if (status == 0) {
+		spurious_interrupt();
+		goto enable;
+	}
+
+	if (status & QCA956X_EXT_INT_USB1) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(0));
+	}
+
+	if (status & QCA956X_EXT_INT_USB2) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(1));
+	}
+
+	if (status & QCA956X_EXT_INT_PCIE_RC2_ALL) {
+		/* TODO: flush DDR? */
+		generic_handle_irq(ATH79_IP3_IRQ(2));
+	}
+
+enable:
+	enable_irq(irq);
+}
+
+static void qca956x_enable_timer_cb(void) {
+	u32 misc;
+
+	misc = ath79_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
+	misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
+	ath79_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, misc);
+}
+
+static void qca956x_irq_init(void)
+{
+	int i;
+
+	for (i = ATH79_IP2_IRQ_BASE;
+	     i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP2, qca956x_ip2_irq_dispatch);
+
+	for (i = ATH79_IP3_IRQ_BASE;
+	     i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(ATH79_CPU_IRQ_IP3, qca956x_ip3_irq_dispatch);
+
+	/* QCA956x timer init workaround has to be applied right before setting
+	 * up the clock. Else, there will be no jiffies */
+	late_time_init = &qca956x_enable_timer_cb;
+}
+
 asmlinkage void plat_irq_dispatch(void)
 {
 	unsigned long pending;
@@ -152,10 +372,8 @@
 	if (pending & STATUSF_IP7)
 		do_IRQ(ATH79_CPU_IRQ_TIMER);
 
-	else if (pending & STATUSF_IP2) {
-		ath79_ddr_wb_flush(ath79_ip2_flush_reg);
-		do_IRQ(ATH79_CPU_IRQ_IP2);
-	}
+	else if (pending & STATUSF_IP2)
+		ath79_ip2_handler();
 
 	else if (pending & STATUSF_IP4)
 		do_IRQ(ATH79_CPU_IRQ_GE0);
@@ -163,10 +381,8 @@
 	else if (pending & STATUSF_IP5)
 		do_IRQ(ATH79_CPU_IRQ_GE1);
 
-	else if (pending & STATUSF_IP3) {
-		ath79_ddr_wb_flush(ath79_ip3_flush_reg);
-		do_IRQ(ATH79_CPU_IRQ_USB);
-	}
+	else if (pending & STATUSF_IP3)
+		ath79_ip3_handler();
 
 	else if (pending & STATUSF_IP6)
 		do_IRQ(ATH79_CPU_IRQ_MISC);
@@ -175,24 +391,125 @@
 		spurious_interrupt();
 }
 
+/*
+ * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
+ * these devices typically allocate coherent DMA memory, however the
+ * DMA controller may still have some unsynchronized data in the FIFO.
+ * Issue a flush in the handlers to ensure that the driver sees
+ * the update.
+ */
+
+static void ath79_default_ip2_handler(void)
+{
+	do_IRQ(ATH79_CPU_IRQ_IP2);
+}
+
+static void ath79_default_ip3_handler(void)
+{
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void ar71xx_ip2_handler(void)
+{
+	ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI);
+	do_IRQ(ATH79_CPU_IRQ_IP2);
+}
+
+static void ar724x_ip2_handler(void)
+{
+	ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE);
+	do_IRQ(ATH79_CPU_IRQ_IP2);
+}
+
+static void ar913x_ip2_handler(void)
+{
+	ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC);
+	do_IRQ(ATH79_CPU_IRQ_IP2);
+}
+
+static void ar933x_ip2_handler(void)
+{
+	ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC);
+	do_IRQ(ATH79_CPU_IRQ_IP2);
+}
+
+static void ar71xx_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void ar724x_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void ar913x_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void ar933x_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void ar934x_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
+static void qca953x_ip3_handler(void)
+{
+	ath79_ddr_wb_flush(QCA953X_DDR_REG_FLUSH_USB);
+	do_IRQ(ATH79_CPU_IRQ_USB);
+}
+
 void __init arch_init_irq(void)
 {
 	if (soc_is_ar71xx()) {
-		ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
-		ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
+		ath79_ip2_handler = ar71xx_ip2_handler;
+		ath79_ip3_handler = ar71xx_ip3_handler;
 	} else if (soc_is_ar724x()) {
-		ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
-		ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
+		ath79_ip2_handler = ar724x_ip2_handler;
+		ath79_ip3_handler = ar724x_ip3_handler;
 	} else if (soc_is_ar913x()) {
-		ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
-		ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
+		ath79_ip2_handler = ar913x_ip2_handler;
+		ath79_ip3_handler = ar913x_ip3_handler;
 	} else if (soc_is_ar933x()) {
-		ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC;
-		ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB;
-	} else
+		ath79_ip2_handler = ar933x_ip2_handler;
+		ath79_ip3_handler = ar933x_ip3_handler;
+	} else if (soc_is_ar934x()) {
+		ath79_ip2_handler = ath79_default_ip2_handler;
+		ath79_ip3_handler = ar934x_ip3_handler;
+	} else if (soc_is_qca953x()) {
+		ath79_ip2_handler = ath79_default_ip2_handler;
+		ath79_ip3_handler = qca953x_ip3_handler;
+	} else if (soc_is_qca955x()) {
+		ath79_ip2_handler = ath79_default_ip2_handler;
+		ath79_ip3_handler = ath79_default_ip3_handler;
+	} else if (soc_is_qca956x()) {
+		ath79_ip2_handler = ath79_default_ip2_handler;
+		ath79_ip3_handler = ath79_default_ip3_handler;
+	} else {
 		BUG();
+	}
 
 	cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
 	mips_cpu_irq_init();
 	ath79_misc_irq_init();
+
+	if (soc_is_ar934x())
+		ar934x_ip2_irq_init();
+	else if (soc_is_qca953x())
+		qca953x_irq_init();
+	else if (soc_is_qca955x())
+		qca955x_irq_init();
+	else if (soc_is_qca956x()) {
+		qca956x_irq_init();
+	}
 }
diff --git a/arch/mips/ath79/mach-ap121.c b/arch/mips/ath79/mach-ap121.c
index 4c20200..46a6a5f 100644
--- a/arch/mips/ath79/mach-ap121.c
+++ b/arch/mips/ath79/mach-ap121.c
@@ -1,19 +1,21 @@
 /*
  *  Atheros AP121 board support
  *
- *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
  *
  *  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.
  */
 
-#include "machtypes.h"
+#include "dev-eth.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
+#include "dev-m25p80.h"
 #include "dev-spi.h"
 #include "dev-usb.h"
 #include "dev-wmac.h"
+#include "machtypes.h"
 
 #define AP121_GPIO_LED_WLAN		0
 #define AP121_GPIO_LED_USB		1
@@ -24,7 +26,14 @@
 #define AP121_KEYS_POLL_INTERVAL	20	/* msecs */
 #define AP121_KEYS_DEBOUNCE_INTERVAL	(3 * AP121_KEYS_POLL_INTERVAL)
 
-#define AP121_CAL_DATA_ADDR	0x1fff1000
+#define AP121_MAC0_OFFSET		0x0000
+#define AP121_MAC1_OFFSET		0x0006
+#define AP121_CALDATA_OFFSET		0x1000
+#define AP121_WMAC_MAC_OFFSET		0x1002
+
+#define AP121_MINI_GPIO_LED_WLAN	0
+#define AP121_MINI_GPIO_BTN_JUMPSTART	12
+#define AP121_MINI_GPIO_BTN_RESET	11
 
 static struct gpio_led ap121_leds_gpio[] __initdata = {
 	{
@@ -58,35 +67,85 @@
 	}
 };
 
-static struct spi_board_info ap121_spi_info[] = {
+static struct gpio_led ap121_mini_leds_gpio[] __initdata = {
 	{
-		.bus_num	= 0,
-		.chip_select	= 0,
-		.max_speed_hz	= 25000000,
-		.modalias	= "mx25l1606e",
+		.name		= "ap121:green:wlan",
+		.gpio		= AP121_MINI_GPIO_LED_WLAN,
+		.active_low	= 0,
+	},
+};
+
+static struct gpio_keys_button ap121_mini_gpio_keys[] __initdata = {
+	{
+		.desc		= "jumpstart button",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP121_MINI_GPIO_BTN_JUMPSTART,
+		.active_low	= 1,
+	},
+	{
+		.desc		= "reset button",
+		.type		= EV_KEY,
+		.code		= KEY_RESTART,
+		.debounce_interval = AP121_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP121_MINI_GPIO_BTN_RESET,
+		.active_low	= 1,
 	}
 };
 
-static struct ath79_spi_platform_data ap121_spi_data = {
-	.bus_num	= 0,
-	.num_chipselect	= 1,
-};
+static void __init ap121_common_setup(void)
+{
+	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+
+	ath79_register_m25p80(NULL);
+	ath79_register_wmac(art + AP121_CALDATA_OFFSET,
+			    art + AP121_WMAC_MAC_OFFSET);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, art + AP121_MAC0_OFFSET, 0);
+	ath79_init_mac(ath79_eth1_data.mac_addr, art + AP121_MAC1_OFFSET, 0);
+
+	ath79_register_mdio(0, 0x0);
+	ath79_register_mdio(1, 0x0);
+
+	/* LAN ports */
+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
+	ath79_eth1_data.speed = SPEED_100;
+	ath79_eth1_data.duplex = DUPLEX_FULL;
+	ath79_register_eth(1);
+
+	/* WAN port */
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	ath79_eth0_data.phy_mask = BIT(0);
+	ath79_eth0_pll_data.pll_1000 = 0x06000000;
+	ath79_register_eth(0);
+}
 
 static void __init ap121_setup(void)
 {
-	u8 *cal_data = (u8 *) KSEG1ADDR(AP121_CAL_DATA_ADDR);
+	ap121_common_setup();
 
 	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121_leds_gpio),
 				 ap121_leds_gpio);
 	ath79_register_gpio_keys_polled(-1, AP121_KEYS_POLL_INTERVAL,
 					ARRAY_SIZE(ap121_gpio_keys),
 					ap121_gpio_keys);
-
-	ath79_register_spi(&ap121_spi_data, ap121_spi_info,
-			   ARRAY_SIZE(ap121_spi_info));
 	ath79_register_usb();
-	ath79_register_wmac(cal_data);
 }
 
 MIPS_MACHINE(ATH79_MACH_AP121, "AP121", "Atheros AP121 reference board",
 	     ap121_setup);
+
+static void __init ap121_mini_setup(void)
+{
+	ap121_common_setup();
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap121_mini_leds_gpio),
+				 ap121_mini_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, AP121_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(ap121_mini_gpio_keys),
+					ap121_mini_gpio_keys);
+}
+
+MIPS_MACHINE(ATH79_MACH_AP121_MINI, "AP121-MINI", "Atheros AP121-MINI",
+	     ap121_mini_setup);
diff --git a/arch/mips/ath79/mach-ap136.c b/arch/mips/ath79/mach-ap136.c
new file mode 100644
index 0000000..b9c46a0
--- /dev/null
+++ b/arch/mips/ath79/mach-ap136.c
@@ -0,0 +1,198 @@
+/*
+ * Atheros AP136 reference board support
+ *
+ * Copyright (c) 2012 Qualcomm Atheros
+ * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/ar8216_platform.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#include "common.h"
+#include "dev-ap9x-pci.h"
+#include "dev-gpio-buttons.h"
+#include "dev-eth.h"
+#include "dev-leds-gpio.h"
+#include "dev-m25p80.h"
+#include "dev-usb.h"
+#include "dev-wmac.h"
+#include "machtypes.h"
+
+#define AP136_GPIO_LED_USB		4
+#define AP136_GPIO_LED_WLAN_5G		12
+#define AP136_GPIO_LED_WLAN_2G		13
+#define AP136_GPIO_LED_STATUS_RED	14
+#define AP136_GPIO_LED_WPS_RED		15
+#define AP136_GPIO_LED_STATUS_GREEN	19
+#define AP136_GPIO_LED_WPS_GREEN	20
+
+#define AP136_GPIO_BTN_WPS		16
+#define AP136_GPIO_BTN_RFKILL		21
+
+#define AP136_KEYS_POLL_INTERVAL	20	/* msecs */
+#define AP136_KEYS_DEBOUNCE_INTERVAL	(3 * AP136_KEYS_POLL_INTERVAL)
+
+#define AP136_MAC0_OFFSET		0
+#define AP136_MAC1_OFFSET		6
+#define AP136_WMAC_CALDATA_OFFSET	0x1000
+#define AP136_PCIE_CALDATA_OFFSET	0x5000
+
+static struct gpio_led ap136_leds_gpio[] __initdata = {
+	{
+		.name		= "ap136:green:status",
+		.gpio		= AP136_GPIO_LED_STATUS_GREEN,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap136:red:status",
+		.gpio		= AP136_GPIO_LED_STATUS_RED,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap136:green:wps",
+		.gpio		= AP136_GPIO_LED_WPS_GREEN,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap136:red:wps",
+		.gpio		= AP136_GPIO_LED_WPS_RED,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap136:red:wlan-2g",
+		.gpio		= AP136_GPIO_LED_WLAN_2G,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap136:red:usb",
+		.gpio		= AP136_GPIO_LED_USB,
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_button ap136_gpio_keys[] __initdata = {
+	{
+		.desc		= "WPS button",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP136_GPIO_BTN_WPS,
+		.active_low	= 1,
+	},
+	{
+		.desc		= "RFKILL button",
+		.type		= EV_KEY,
+		.code		= KEY_RFKILL,
+		.debounce_interval = AP136_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP136_GPIO_BTN_RFKILL,
+		.active_low	= 1,
+	},
+};
+
+static struct ar8327_pad_cfg ap136_ar8327_pad0_cfg = {
+	.mode = AR8327_PAD_MAC_RGMII,
+	.txclk_delay_en = true,
+	.rxclk_delay_en = true,
+	.txclk_delay_sel = AR8327_CLK_DELAY_SEL1,
+	.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2,
+};
+
+static struct ar8327_pad_cfg ap136_ar8327_pad6_cfg = {
+	.mode = AR8327_PAD_MAC_SGMII,
+	.txclk_delay_en = false,
+	.rxclk_delay_en = true,
+	.txclk_delay_sel = AR8327_CLK_DELAY_SEL0,
+	.rxclk_delay_sel = AR8327_CLK_DELAY_SEL0,
+};
+
+static struct ar8327_platform_data ap136_ar8327_data = {
+	.pad0_cfg = &ap136_ar8327_pad0_cfg,
+	.pad6_cfg = &ap136_ar8327_pad6_cfg,
+	.cpuport_cfg = {
+		.force_link = 1,
+		.speed = AR8327_PORT_SPEED_1000,
+		.duplex = 1,
+		.txpause = 1,
+		.rxpause = 1,
+	}
+};
+
+static struct mdio_board_info ap136_mdio0_info[] = {
+	{
+		.bus_id = "ag71xx-mdio.0",
+		.phy_addr = 0,
+		.platform_data = &ap136_ar8327_data,
+	},
+};
+
+static void __init ap136_gmac_setup(void)
+{
+	void __iomem *base;
+	u32 t;
+
+	base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE);
+
+	t = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG);
+
+	t &= ~(QCA955X_ETH_CFG_RGMII_GMAC0 | QCA955X_ETH_CFG_SGMII_GMAC0);
+	t |= QCA955X_ETH_CFG_RGMII_GMAC0;
+
+	__raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG);
+
+	iounmap(base);
+}
+
+static void __init ap136_setup(void)
+{
+	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+
+	ath79_register_m25p80(NULL);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap136_leds_gpio),
+				 ap136_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, AP136_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(ap136_gpio_keys),
+					ap136_gpio_keys);
+
+	ath79_register_usb();
+	ath79_register_wmac(art + AP136_WMAC_CALDATA_OFFSET, NULL);
+	ap91_pci_init(art + AP136_PCIE_CALDATA_OFFSET, NULL);
+
+	ap136_gmac_setup();
+
+	ath79_register_mdio(0, 0x0);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, art + AP136_MAC0_OFFSET, 0);
+
+	mdiobus_register_board_info(ap136_mdio0_info,
+				    ARRAY_SIZE(ap136_mdio0_info));
+
+	/* GMAC0 is connected to an AR8327 switch */
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	ath79_eth0_data.phy_mask = BIT(0);
+	ath79_eth0_data.speed = SPEED_1000;
+	ath79_eth0_data.duplex = DUPLEX_FULL;
+	ath79_eth0_data.force_link = 1;
+	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
+	ath79_eth0_pll_data.pll_1000 = 0xa6000000;
+
+	ath79_register_eth(0);
+}
+
+MIPS_MACHINE(ATH79_MACH_AP136, "AP136", "Atheros AP136 reference board",
+	     ap136_setup);
diff --git a/arch/mips/ath79/mach-ap143.c b/arch/mips/ath79/mach-ap143.c
new file mode 100644
index 0000000..5f0cd58
--- /dev/null
+++ b/arch/mips/ath79/mach-ap143.c
@@ -0,0 +1,141 @@
+/*
+ * Atheros AP143 reference board support
+ *
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+#include <linux/ar8216_platform.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#include "common.h"
+#include "dev-eth.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-m25p80.h"
+#include "dev-spi.h"
+#include "dev-usb.h"
+#include "dev-wmac.h"
+#include "machtypes.h"
+
+#define AP143_GPIO_LED_WLAN		12
+#define AP143_GPIO_LED_WPS		13
+#define AP143_GPIO_LED_STATUS		13
+
+#define AP143_GPIO_LED_WAN		4
+#define AP143_GPIO_LED_LAN1		16
+#define AP143_GPIO_LED_LAN2		15
+#define AP143_GPIO_LED_LAN3		14
+#define AP143_GPIO_LED_LAN4		11
+
+#define AP143_GPIO_BTN_WPS		17
+
+#define AP143_KEYS_POLL_INTERVAL	20	/* msecs */
+#define AP143_KEYS_DEBOUNCE_INTERVAL	(3 * AP143_KEYS_POLL_INTERVAL)
+
+#define AP143_MAC0_OFFSET		0
+#define AP143_MAC1_OFFSET		6
+#define AP143_WMAC_CALDATA_OFFSET	0x1000
+
+static struct gpio_led ap143_leds_gpio[] __initdata = {
+	{
+		.name		= "ap143:green:status",
+		.gpio		= AP143_GPIO_LED_STATUS,
+		.active_low	= 1,
+	},
+	{
+		.name		= "ap143:green:wlan",
+		.gpio		= AP143_GPIO_LED_WLAN,
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_button ap143_gpio_keys[] __initdata = {
+	{
+		.desc		= "WPS button",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = AP143_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= AP143_GPIO_BTN_WPS,
+		.active_low	= 1,
+	},
+};
+
+static void __init ap143_gpio_led_setup(void)
+{
+	ath79_gpio_direction_select(AP143_GPIO_LED_WAN, true);
+	ath79_gpio_direction_select(AP143_GPIO_LED_LAN1, true);
+	ath79_gpio_direction_select(AP143_GPIO_LED_LAN2, true);
+	ath79_gpio_direction_select(AP143_GPIO_LED_LAN3, true);
+	ath79_gpio_direction_select(AP143_GPIO_LED_LAN4, true);
+
+	ath79_gpio_output_select(AP143_GPIO_LED_WAN,
+			QCA953X_GPIO_OUT_MUX_LED_LINK5);
+	ath79_gpio_output_select(AP143_GPIO_LED_LAN1,
+			QCA953X_GPIO_OUT_MUX_LED_LINK1);
+	ath79_gpio_output_select(AP143_GPIO_LED_LAN2,
+			QCA953X_GPIO_OUT_MUX_LED_LINK2);
+	ath79_gpio_output_select(AP143_GPIO_LED_LAN3,
+			QCA953X_GPIO_OUT_MUX_LED_LINK3);
+	ath79_gpio_output_select(AP143_GPIO_LED_LAN4,
+			QCA953X_GPIO_OUT_MUX_LED_LINK4);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ap143_leds_gpio),
+			ap143_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, AP143_KEYS_POLL_INTERVAL,
+			ARRAY_SIZE(ap143_gpio_keys),
+			ap143_gpio_keys);
+}
+
+static void __init ap143_setup(void)
+{
+	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+
+	ath79_register_m25p80(NULL);
+
+	ap143_gpio_led_setup();
+
+	ath79_register_usb();
+
+	ath79_register_wmac(art + AP143_WMAC_CALDATA_OFFSET, NULL);
+
+	ath79_register_mdio(0, 0x0);
+	ath79_register_mdio(1, 0x0);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, art + AP143_MAC0_OFFSET, 0);
+	ath79_init_mac(ath79_eth1_data.mac_addr, art + AP143_MAC1_OFFSET, 0);
+
+	/* WAN port */
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII;
+	ath79_eth0_data.speed = SPEED_100;
+	ath79_eth0_data.duplex = DUPLEX_FULL;
+	ath79_eth0_data.phy_mask = BIT(4);
+	ath79_register_eth(0);
+
+	/* LAN ports */
+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
+	ath79_eth1_data.speed = SPEED_1000;
+	ath79_eth1_data.duplex = DUPLEX_FULL;
+	ath79_switch_data.phy_poll_mask |= BIT(4);
+	ath79_switch_data.phy4_mii_en = 1;
+	ath79_register_eth(1);
+}
+
+MIPS_MACHINE(ATH79_MACH_AP143, "AP143", "Qualcomm Atheros AP143 reference board",
+	     ap143_setup);
diff --git a/arch/mips/ath79/mach-ap81.c b/arch/mips/ath79/mach-ap81.c
index abe1983..a703e19 100644
--- a/arch/mips/ath79/mach-ap81.c
+++ b/arch/mips/ath79/mach-ap81.c
@@ -9,12 +9,16 @@
  *  by the Free Software Foundation.
  */
 
-#include "machtypes.h"
-#include "dev-wmac.h"
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include "dev-eth.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
-#include "dev-spi.h"
+#include "dev-m25p80.h"
 #include "dev-usb.h"
+#include "dev-wmac.h"
+#include "machtypes.h"
 
 #define AP81_GPIO_LED_STATUS	1
 #define AP81_GPIO_LED_AOSS	3
@@ -29,6 +33,37 @@
 
 #define AP81_CAL_DATA_ADDR	0x1fff1000
 
+static struct mtd_partition ap81_partitions[] = {
+	{
+		.name		= "u-boot",
+		.offset		= 0,
+		.size		= 0x040000,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "u-boot-env",
+		.offset		= 0x040000,
+		.size		= 0x010000,
+	}, {
+		.name		= "rootfs",
+		.offset		= 0x050000,
+		.size		= 0x500000,
+	}, {
+		.name		= "uImage",
+		.offset		= 0x550000,
+		.size		= 0x100000,
+	}, {
+		.name		= "ART",
+		.offset		= 0x650000,
+		.size		= 0x1b0000,
+		.mask_flags	= MTD_WRITEABLE,
+	}
+};
+
+static struct flash_platform_data ap81_flash_data = {
+	.parts		= ap81_partitions,
+	.nr_parts	= ARRAY_SIZE(ap81_partitions),
+};
+
 static struct gpio_led ap81_leds_gpio[] __initdata = {
 	{
 		.name		= "ap81:green:status",
@@ -67,20 +102,6 @@
 	}
 };
 
-static struct spi_board_info ap81_spi_info[] = {
-	{
-		.bus_num	= 0,
-		.chip_select	= 0,
-		.max_speed_hz	= 25000000,
-		.modalias	= "m25p64",
-	}
-};
-
-static struct ath79_spi_platform_data ap81_spi_data = {
-	.bus_num	= 0,
-	.num_chipselect	= 1,
-};
-
 static void __init ap81_setup(void)
 {
 	u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR);
@@ -90,10 +111,24 @@
 	ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
 					ARRAY_SIZE(ap81_gpio_keys),
 					ap81_gpio_keys);
-	ath79_register_spi(&ap81_spi_data, ap81_spi_info,
-			   ARRAY_SIZE(ap81_spi_info));
-	ath79_register_wmac(cal_data);
+	ath79_register_m25p80(&ap81_flash_data);
+	ath79_register_wmac(cal_data, NULL);
 	ath79_register_usb();
+
+	ath79_register_mdio(0, 0x0);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, cal_data, 0);
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII;
+	ath79_eth0_data.speed = SPEED_100;
+	ath79_eth0_data.duplex = DUPLEX_FULL;
+	ath79_eth0_data.has_ar8216 = 1;
+
+	ath79_init_mac(ath79_eth1_data.mac_addr, cal_data, 1);
+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII;
+	ath79_eth1_data.phy_mask = 0x10;
+
+	ath79_register_eth(0);
+	ath79_register_eth(1);
 }
 
 MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
diff --git a/arch/mips/ath79/mach-cus227.c b/arch/mips/ath79/mach-cus227.c
index ee2cf29..6ce4950 100644
--- a/arch/mips/ath79/mach-cus227.c
+++ b/arch/mips/ath79/mach-cus227.c
@@ -16,10 +16,14 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
 
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include <asm/mach-ath79/ath79.h>
 
+#include <linux/of_platform.h>
+
 #include "common.h"
 #include "dev-ap9x-pci.h"
 #include "dev-audio.h"
@@ -31,6 +35,7 @@
 #include "dev-spi.h"
 #include "dev-usb.h"
 #include "dev-wmac.h"
+#include "dev-i2c.h"
 #include "machtypes.h"
 #include "nand-caldata-fixup.h"
 
@@ -38,6 +43,8 @@
 #define CUS227_GPIO_S2			13
 #define CUS227_GPIO_S3			14
 #define CUS227_GPIO_S4			15
+#define CUS227_GPIO_I2C_SDA		16
+#define CUS227_GPIO_I2C_SCL		17
 
 #define CUS227_KEYS_POLL_INTERVAL	20	/* msecs */
 #define CUS227_KEYS_DEBOUNCE_INTERVAL	(3 * CUS227_KEYS_POLL_INTERVAL)
@@ -64,38 +71,20 @@
 	.mac_addr = { FIXUP_UNDEFINED, CUS227_MAC0_OFFSET },
 };
 
-static struct gpio_led cus227_leds_gpio[] __initdata = {
-	{
-		.name		= "cus227:green:s3",
-		.gpio		= CUS227_GPIO_S3,
-		.active_low	= 1,
-	},
-	{
-		.name		= "cus227:green:s4",
-		.gpio		= CUS227_GPIO_S4,
-		.active_low	= 1,
-	},
+static struct of_device_id __initdata cus227_common_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "gpio-keys", },
+	{ .compatible = "gpio-leds", },
+	{},
 };
 
-static struct gpio_keys_button cus227_gpio_keys[] __initdata = {
-	{
-		.desc		= "WPS button",
-		.type		= EV_KEY,
-		.code		= KEY_WPS_BUTTON,
-		.debounce_interval = CUS227_KEYS_DEBOUNCE_INTERVAL,
-		.gpio		= CUS227_GPIO_S1,
-		.active_low	= 1,
-	},
-	{
-		.desc		= "s2",
-		.type		= EV_KEY,
-		.code		= BTN_2,
-		.debounce_interval = CUS227_KEYS_DEBOUNCE_INTERVAL,
-		.gpio		= CUS227_GPIO_S2,
-		.active_low	= 1,
-	},
+/* There is no H/W I2C controller in ATH79 SoCs, so use GPIO based S/W I2C master */
+static struct i2c_gpio_platform_data ath79_i2c_gpio_data = {
+	.sda_pin	= CUS227_GPIO_I2C_SDA,
+	.scl_pin	= CUS227_GPIO_I2C_SCL,
 };
 
+
 /* Because CUS227 doesn't have a NOR flash on the SPI bus, we cannot
  * reuse the routines from dev-m25p80.c to instanciate it.
  * That's also the reason why the first device on the bus is 1 and not 0 */
@@ -158,6 +147,11 @@
 	ath79_audio_setup();
 }
 
+static void __init cus227_register_i2c_devices(
+			struct i2c_board_info const *info)
+{
+	ath79_register_i2c(&ath79_i2c_gpio_data, info, info?1:0);
+}
 
 static void __init cus227_register_spi_devices(
 			struct spi_board_info const *info)
@@ -188,16 +182,17 @@
 
 static void __init cus227_setup(void)
 {
-	ath79_register_leds_gpio(-1, ARRAY_SIZE(cus227_leds_gpio),
-				 cus227_leds_gpio);
-	ath79_register_gpio_keys_polled(-1, CUS227_KEYS_POLL_INTERVAL,
-					ARRAY_SIZE(cus227_gpio_keys),
-					cus227_gpio_keys);
+	of_platform_bus_probe(NULL, cus227_common_ids, NULL);
+
 	ath79_register_usb();
 
 	ath79_register_nand();
 	ath79_mtd_caldata_fixup(&cus227_caldata);
 
+	/* just define GPIO based S/W I2C master device now */
+	/* later I2C slave devices can be added per platform defined */
+	cus227_register_i2c_devices(NULL);
+
 	cus227_register_spi_devices(cus227_spi_info);
 
 	ath79_register_wmac(NULL, NULL);
@@ -212,6 +207,7 @@
 	/* Audio initialization: PCM/I2S and CODEC */
 	cus227_audio_setup();
 	ath79_audio_device_register();
+
 }
 MIPS_MACHINE(ATH79_MACH_CUS227, "CUS227", "Qualcomm Atheros CUS227",
 	     cus227_setup);
diff --git a/arch/mips/ath79/mach-db120.c b/arch/mips/ath79/mach-db120.c
new file mode 100644
index 0000000..baa6b5d
--- /dev/null
+++ b/arch/mips/ath79/mach-db120.c
@@ -0,0 +1,178 @@
+/*
+ * Atheros DB120 reference board support
+ *
+ * Copyright (c) 2011 Qualcomm Atheros
+ * Copyright (c) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/ath9k_platform.h>
+#include <linux/ar8216_platform.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#include "common.h"
+#include "dev-ap9x-pci.h"
+#include "dev-eth.h"
+#include "dev-gpio-buttons.h"
+#include "dev-leds-gpio.h"
+#include "dev-m25p80.h"
+#include "dev-nfc.h"
+#include "dev-spi.h"
+#include "dev-usb.h"
+#include "dev-wmac.h"
+#include "machtypes.h"
+
+#define DB120_GPIO_LED_USB		11
+#define DB120_GPIO_LED_WLAN_5G		12
+#define DB120_GPIO_LED_WLAN_2G		13
+#define DB120_GPIO_LED_STATUS		14
+#define DB120_GPIO_LED_WPS		15
+
+#define DB120_GPIO_BTN_WPS		16
+
+#define DB120_KEYS_POLL_INTERVAL	20	/* msecs */
+#define DB120_KEYS_DEBOUNCE_INTERVAL	(3 * DB120_KEYS_POLL_INTERVAL)
+
+#define DB120_MAC0_OFFSET		0
+#define DB120_MAC1_OFFSET		6
+#define DB120_WMAC_CALDATA_OFFSET	0x1000
+#define DB120_PCIE_CALDATA_OFFSET	0x5000
+
+static struct gpio_led db120_leds_gpio[] __initdata = {
+	{
+		.name		= "db120:green:status",
+		.gpio		= DB120_GPIO_LED_STATUS,
+		.active_low	= 1,
+	},
+	{
+		.name		= "db120:green:wps",
+		.gpio		= DB120_GPIO_LED_WPS,
+		.active_low	= 1,
+	},
+	{
+		.name		= "db120:green:wlan-5g",
+		.gpio		= DB120_GPIO_LED_WLAN_5G,
+		.active_low	= 1,
+	},
+	{
+		.name		= "db120:green:wlan-2g",
+		.gpio		= DB120_GPIO_LED_WLAN_2G,
+		.active_low	= 1,
+	},
+	{
+		.name		= "db120:green:usb",
+		.gpio		= DB120_GPIO_LED_USB,
+		.active_low	= 1,
+	}
+};
+
+static struct gpio_keys_button db120_gpio_keys[] __initdata = {
+	{
+		.desc		= "WPS button",
+		.type		= EV_KEY,
+		.code		= KEY_WPS_BUTTON,
+		.debounce_interval = DB120_KEYS_DEBOUNCE_INTERVAL,
+		.gpio		= DB120_GPIO_BTN_WPS,
+		.active_low	= 1,
+	},
+};
+
+static struct ar8327_pad_cfg db120_ar8327_pad0_cfg = {
+	.mode = AR8327_PAD_MAC_RGMII,
+	.txclk_delay_en = true,
+	.rxclk_delay_en = true,
+	.txclk_delay_sel = AR8327_CLK_DELAY_SEL1,
+	.rxclk_delay_sel = AR8327_CLK_DELAY_SEL2,
+};
+
+static struct ar8327_led_cfg db120_ar8327_led_cfg = {
+	.led_ctrl0 = 0x00000000,
+	.led_ctrl1 = 0xc737c737,
+	.led_ctrl2 = 0x00000000,
+	.led_ctrl3 = 0x00c30c00,
+	.open_drain = true,
+};
+
+static struct ar8327_platform_data db120_ar8327_data = {
+	.pad0_cfg = &db120_ar8327_pad0_cfg,
+	.cpuport_cfg = {
+		.force_link = 1,
+		.speed = AR8327_PORT_SPEED_1000,
+		.duplex = 1,
+		.txpause = 1,
+		.rxpause = 1,
+	},
+	.led_cfg = &db120_ar8327_led_cfg,
+};
+
+static struct mdio_board_info db120_mdio0_info[] = {
+	{
+		.bus_id = "ag71xx-mdio.0",
+		.phy_addr = 0,
+		.platform_data = &db120_ar8327_data,
+	},
+};
+
+static void __init db120_setup(void)
+{
+	u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
+
+	ath79_gpio_output_select(DB120_GPIO_LED_USB, AR934X_GPIO_OUT_GPIO);
+	ath79_register_m25p80(NULL);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(db120_leds_gpio),
+				 db120_leds_gpio);
+	ath79_register_gpio_keys_polled(-1, DB120_KEYS_POLL_INTERVAL,
+					ARRAY_SIZE(db120_gpio_keys),
+					db120_gpio_keys);
+	ath79_register_usb();
+	ath79_register_wmac(art + DB120_WMAC_CALDATA_OFFSET, NULL);
+	ap91_pci_init(art + DB120_PCIE_CALDATA_OFFSET, NULL);
+
+	ath79_setup_ar934x_eth_cfg(AR934X_ETH_CFG_RGMII_GMAC0 |
+				   AR934X_ETH_CFG_SW_ONLY_MODE);
+
+	ath79_register_mdio(1, 0x0);
+	ath79_register_mdio(0, 0x0);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, art + DB120_MAC0_OFFSET, 0);
+
+	mdiobus_register_board_info(db120_mdio0_info,
+				    ARRAY_SIZE(db120_mdio0_info));
+
+	/* GMAC0 is connected to an AR8327 switch */
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	ath79_eth0_data.phy_mask = BIT(0);
+	ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev;
+	ath79_eth0_pll_data.pll_1000 = 0x06000000;
+	ath79_register_eth(0);
+
+	/* GMAC1 is connected to the internal switch */
+	ath79_init_mac(ath79_eth1_data.mac_addr, art + DB120_MAC1_OFFSET, 0);
+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII;
+	ath79_eth1_data.speed = SPEED_1000;
+	ath79_eth1_data.duplex = DUPLEX_FULL;
+
+	ath79_register_eth(1);
+
+	ath79_register_nfc();
+}
+
+MIPS_MACHINE(ATH79_MACH_DB120, "DB120", "Atheros DB120 reference board",
+	     db120_setup);
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index fe9701a..136f4dc 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -8,22 +8,48 @@
  *  by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/vsc7385.h>
 
-#include "machtypes.h"
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79.h>
+
+#include "dev-eth.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
 #include "dev-spi.h"
 #include "dev-usb.h"
+#include "machtypes.h"
+#include "pci.h"
 
 #define PB44_GPIO_I2C_SCL	0
 #define PB44_GPIO_I2C_SDA	1
 
+#define PB44_PCF8757_VSC7395_CS	0
+#define PB44_PCF8757_STEREO_CS	1
+#define PB44_PCF8757_SLIC_CS0	2
+#define PB44_PCF8757_SLIC_TEST	3
+#define PB44_PCF8757_SLIC_INT0	4
+#define PB44_PCF8757_SLIC_INT1	5
+#define PB44_PCF8757_SW_RESET	6
+#define PB44_PCF8757_SW_JUMP	8
+#define PB44_PCF8757_LED_JUMP1	9
+#define PB44_PCF8757_LED_JUMP2	10
+#define PB44_PCF8757_TP24	11
+#define PB44_PCF8757_TP25	12
+#define PB44_PCF8757_TP26	13
+#define PB44_PCF8757_TP27	14
+#define PB44_PCF8757_TP28	15
+
 #define PB44_GPIO_EXP_BASE	16
+#define PB44_GPIO_VSC7395_CS	(PB44_GPIO_EXP_BASE + PB44_PCF8757_VSC7395_CS)
 #define PB44_GPIO_SW_RESET	(PB44_GPIO_EXP_BASE + 6)
 #define PB44_GPIO_SW_JUMP	(PB44_GPIO_EXP_BASE + 8)
 #define PB44_GPIO_LED_JUMP1	(PB44_GPIO_EXP_BASE + 9)
@@ -86,20 +112,71 @@
 	}
 };
 
+static struct ath79_spi_controller_data pb44_spi0_data = {
+	.cs_type = ATH79_SPI_CS_TYPE_INTERNAL,
+	.cs_line = 0,
+};
+
+static struct ath79_spi_controller_data pb44_spi1_data = {
+	.cs_type = ATH79_SPI_CS_TYPE_GPIO,
+	.cs_line = PB44_GPIO_VSC7395_CS,
+};
+
+static void pb44_vsc7395_reset(void)
+{
+	ath79_device_reset_set(AR71XX_RESET_GE1_PHY);
+	udelay(10);
+	ath79_device_reset_clear(AR71XX_RESET_GE1_PHY);
+	mdelay(50);
+}
+
+static struct vsc7385_platform_data pb44_vsc7395_data = {
+	.reset		= pb44_vsc7395_reset,
+	.ucode_name	= "vsc7395_ucode_pb44.bin",
+	.mac_cfg = {
+		.tx_ipg		= 6,
+		.bit2		= 1,
+		.clk_sel	= 0,
+	},
+};
+
+static const char *pb44_part_probes[] = {
+	"RedBoot",
+	NULL,
+};
+
+static struct flash_platform_data pb44_flash_data = {
+	.part_probes	= pb44_part_probes,
+};
+
 static struct spi_board_info pb44_spi_info[] = {
 	{
 		.bus_num	= 0,
 		.chip_select	= 0,
 		.max_speed_hz	= 25000000,
 		.modalias	= "m25p64",
+		.platform_data	= &pb44_flash_data,
+		.controller_data = &pb44_spi0_data,
 	},
+	{
+		.bus_num	= 0,
+		.chip_select	= 1,
+		.max_speed_hz	= 25000000,
+		.modalias	= "spi-vsc7385",
+		.platform_data	= &pb44_vsc7395_data,
+		.controller_data = &pb44_spi1_data,
+	}
 };
 
 static struct ath79_spi_platform_data pb44_spi_data = {
 	.bus_num		= 0,
-	.num_chipselect		= 1,
+	.num_chipselect		= 2,
 };
 
+#define PB44_WAN_PHYMASK	BIT(0)
+#define PB44_LAN_PHYMASK	0
+#define PB44_MDIO_PHYMASK	(PB44_LAN_PHYMASK | PB44_WAN_PHYMASK)
+
 static void __init pb44_init(void)
 {
 	i2c_register_board_info(0, pb44_i2c_board_info,
@@ -114,6 +191,23 @@
 	ath79_register_spi(&pb44_spi_data, pb44_spi_info,
 			   ARRAY_SIZE(pb44_spi_info));
 	ath79_register_usb();
+	ath79_register_pci();
+
+	ath79_register_mdio(0, ~PB44_MDIO_PHYMASK);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, ath79_mac_base, 0);
+	ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	ath79_eth0_data.phy_mask = PB44_WAN_PHYMASK;
+
+	ath79_register_eth(0);
+
+	ath79_init_mac(ath79_eth1_data.mac_addr, ath79_mac_base, 1);
+	ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
+	ath79_eth1_data.speed = SPEED_1000;
+	ath79_eth1_data.duplex = DUPLEX_FULL;
+	ath79_eth1_pll_data.pll_1000 = 0x110000;
+
+	ath79_register_eth(1);
 }
 
 MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c
index 3c311a5..f94d016 100644
--- a/arch/mips/ath79/mach-ubnt-xm.c
+++ b/arch/mips/ath79/mach-ubnt-xm.c
@@ -12,16 +12,18 @@
 
 #include <linux/init.h>
 #include <linux/pci.h>
-
-#ifdef CONFIG_PCI
 #include <linux/ath9k_platform.h>
-#include <asm/mach-ath79/pci-ath724x.h>
-#endif /* CONFIG_PCI */
+#include <linux/etherdevice.h>
 
-#include "machtypes.h"
+#include <asm/mach-ath79/irq.h>
+
+#include "dev-ap9x-pci.h"
+#include "dev-eth.h"
 #include "dev-gpio-buttons.h"
 #include "dev-leds-gpio.h"
-#include "dev-spi.h"
+#include "dev-m25p80.h"
+#include "dev-usb.h"
+#include "machtypes.h"
 
 #define UBNT_XM_GPIO_LED_L1		0
 #define UBNT_XM_GPIO_LED_L2		1
@@ -33,24 +35,23 @@
 #define UBNT_XM_KEYS_POLL_INTERVAL	20
 #define UBNT_XM_KEYS_DEBOUNCE_INTERVAL	(3 * UBNT_XM_KEYS_POLL_INTERVAL)
 
-#define UBNT_XM_PCI_IRQ			48
-#define UBNT_XM_EEPROM_ADDR		(u8 *) KSEG1ADDR(0x1fff1000)
+#define UBNT_XM_EEPROM_ADDR		0x1fff1000
 
 static struct gpio_led ubnt_xm_leds_gpio[] __initdata = {
 	{
-		.name		= "ubnt-xm:red:link1",
+		.name		= "ubnt:red:link1",
 		.gpio		= UBNT_XM_GPIO_LED_L1,
 		.active_low	= 0,
 	}, {
-		.name		= "ubnt-xm:orange:link2",
+		.name		= "ubnt:orange:link2",
 		.gpio		= UBNT_XM_GPIO_LED_L2,
 		.active_low	= 0,
 	}, {
-		.name		= "ubnt-xm:green:link3",
+		.name		= "ubnt:green:link3",
 		.gpio		= UBNT_XM_GPIO_LED_L3,
 		.active_low	= 0,
 	}, {
-		.name		= "ubnt-xm:green:link4",
+		.name		= "ubnt:green:link4",
 		.gpio		= UBNT_XM_GPIO_LED_L4,
 		.active_low	= 0,
 	},
@@ -67,33 +68,14 @@
 	}
 };
 
-static struct spi_board_info ubnt_xm_spi_info[] = {
-	{
-		.bus_num	= 0,
-		.chip_select	= 0,
-		.max_speed_hz	= 25000000,
-		.modalias	= "mx25l6405d",
-	}
-};
-
-static struct ath79_spi_platform_data ubnt_xm_spi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 1,
-};
-
-#ifdef CONFIG_PCI
-static struct ath9k_platform_data ubnt_xm_eeprom_data;
-
-static struct ath724x_pci_data ubnt_xm_pci_data[] = {
-	{
-		.irq	= UBNT_XM_PCI_IRQ,
-		.pdata	= &ubnt_xm_eeprom_data,
-	},
-};
-#endif /* CONFIG_PCI */
+#define UBNT_M_WAN_PHYMASK	BIT(4)
 
 static void __init ubnt_xm_init(void)
 {
+	u8 *eeprom = (u8 *) KSEG1ADDR(UBNT_XM_EEPROM_ADDR);
+	u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000);
+	u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN);
+
 	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_xm_leds_gpio),
 				 ubnt_xm_leds_gpio);
 
@@ -101,19 +83,157 @@
 					ARRAY_SIZE(ubnt_xm_gpio_keys),
 					ubnt_xm_gpio_keys);
 
-	ath79_register_spi(&ubnt_xm_spi_data, ubnt_xm_spi_info,
-			   ARRAY_SIZE(ubnt_xm_spi_info));
+	ath79_register_m25p80(NULL);
+	ap91_pci_init(eeprom, NULL);
 
-#ifdef CONFIG_PCI
-	memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR,
-	       sizeof(ubnt_xm_eeprom_data.eeprom_data));
-
-	ath724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data));
-#endif /* CONFIG_PCI */
-
+	ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK);
+	ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0);
+	ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0);
+	ath79_register_eth(0);
 }
 
 MIPS_MACHINE(ATH79_MACH_UBNT_XM,
 	     "UBNT-XM",
 	     "Ubiquiti Networks XM (rev 1.0) board",
 	     ubnt_xm_init);
+
+MIPS_MACHINE(ATH79_MACH_UBNT_BULLET_M, "UBNT-BM", "Ubiquiti Bullet M",
+	     ubnt_xm_init);
+
+static void __init ubnt_rocket_m_setup(void)
+{
+	ubnt_xm_init();
+	ath79_register_usb();
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_ROCKET_M, "UBNT-RM", "Ubiquiti Rocket M",
+	     ubnt_rocket_m_setup);
+
+static void __init ubnt_nano_m_setup(void)
+{
+	ubnt_xm_init();
+	ath79_register_eth(1);
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_NANO_M, "UBNT-NM", "Ubiquiti Nanostation M",
+	     ubnt_nano_m_setup);
+
+static struct gpio_led ubnt_airrouter_leds_gpio[] __initdata = {
+	{
+		.name		= "ubnt:green:globe",
+		.gpio		= 0,
+		.active_low	= 1,
+	}, {
+	        .name		= "ubnt:green:power",
+		.gpio		= 11,
+		.active_low	= 1,
+		.default_state  = LEDS_GPIO_DEFSTATE_ON,
+	}
+};
+
+static void __init ubnt_airrouter_setup(void)
+{
+	u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000);
+	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
+
+	ath79_register_m25p80(NULL);
+	ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0);
+	ath79_init_local_mac(ath79_eth1_data.mac_addr, mac1);
+
+	ath79_register_eth(1);
+	ath79_register_eth(0);
+	ath79_register_usb();
+
+	ap91_pci_init(ee, NULL);
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_airrouter_leds_gpio),
+				 ubnt_airrouter_leds_gpio);
+
+	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
+                                        ARRAY_SIZE(ubnt_xm_gpio_keys),
+                                        ubnt_xm_gpio_keys);
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_AIRROUTER, "UBNT-AR", "Ubiquiti AirRouter",
+	     ubnt_airrouter_setup);
+
+static struct gpio_led ubnt_unifi_leds_gpio[] __initdata = {
+	{
+		.name		= "ubnt:orange:dome",
+		.gpio		= 1,
+		.active_low	= 0,
+	}, {
+		.name		= "ubnt:green:dome",
+		.gpio		= 0,
+		.active_low	= 0,
+	}
+};
+
+static struct gpio_led ubnt_unifi_outdoor_leds_gpio[] __initdata = {
+	{
+		.name		= "ubnt:orange:front",
+		.gpio		= 1,
+		.active_low	= 0,
+	}, {
+		.name		= "ubnt:green:front",
+		.gpio		= 0,
+		.active_low	= 0,
+	}
+};
+
+
+static void __init ubnt_unifi_setup(void)
+{
+	u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000);
+	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
+
+	ath79_register_m25p80(NULL);
+
+	ath79_register_mdio(0, ~UBNT_M_WAN_PHYMASK);
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0);
+	ath79_register_eth(0);
+
+	ap91_pci_init(ee, NULL);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_leds_gpio),
+				 ubnt_unifi_leds_gpio);
+
+	ath79_register_gpio_keys_polled(-1, UBNT_XM_KEYS_POLL_INTERVAL,
+                                        ARRAY_SIZE(ubnt_xm_gpio_keys),
+                                        ubnt_xm_gpio_keys);
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI, "UBNT-UF", "Ubiquiti UniFi",
+	     ubnt_unifi_setup);
+
+
+#define UBNT_UNIFIOD_PRI_PHYMASK	BIT(4)
+#define UBNT_UNIFIOD_2ND_PHYMASK	(BIT(0) | BIT(1) | BIT(2) | BIT(3))
+
+static void __init ubnt_unifi_outdoor_setup(void)
+{
+	u8 *mac1 = (u8 *) KSEG1ADDR(0x1fff0000);
+	u8 *mac2 = (u8 *) KSEG1ADDR(0x1fff0000 + ETH_ALEN);
+	u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000);
+
+	ath79_register_m25p80(NULL);
+
+	ath79_register_mdio(0, ~(UBNT_UNIFIOD_PRI_PHYMASK |
+				 UBNT_UNIFIOD_2ND_PHYMASK));
+
+	ath79_init_mac(ath79_eth0_data.mac_addr, mac1, 0);
+	ath79_init_mac(ath79_eth1_data.mac_addr, mac2, 0);
+	ath79_register_eth(0);
+	ath79_register_eth(1);
+
+	ap91_pci_init(ee, NULL);
+
+	ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_leds_gpio),
+				 ubnt_unifi_outdoor_leds_gpio);
+}
+
+MIPS_MACHINE(ATH79_MACH_UBNT_UNIFI_OUTDOOR, "UBNT-U20",
+	     "Ubiquiti UniFiAP Outdoor",
+	     ubnt_unifi_outdoor_setup);
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
index 9a1f382..425fd77 100644
--- a/arch/mips/ath79/machtypes.h
+++ b/arch/mips/ath79/machtypes.h
@@ -1,6 +1,7 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X machine type definitions
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
@@ -16,10 +17,117 @@
 
 enum ath79_mach_type {
 	ATH79_MACH_GENERIC = 0,
+	ATH79_MACH_ALFA_AP96,		/* ALFA Network AP96 board */
+	ATH79_MACH_ALFA_NX,		/* ALFA Network N2/N5 board */
+	ATH79_MACH_ALL0258N,		/* Allnet ALL0258N */
+	ATH79_MACH_ALL0305,		/* Allnet ALL0305 */
+	ATH79_MACH_ALL0315N,		/* Allnet ALL0315N */
+	ATH79_MACH_AP113,		/* Atheros AP113 reference board */
 	ATH79_MACH_AP121,		/* Atheros AP121 reference board */
+	ATH79_MACH_AP121_MINI,		/* Atheros AP121-MINI reference board */
+	ATH79_MACH_AP135,		/* Atheros AP135 reference board */
+	ATH79_MACH_AP135_DUAL,		/* Atheros AP135 Dual reference board */
+	ATH79_MACH_AP136,		/* Atheros AP136 reference board */
+	ATH79_MACH_AP143,		/* Atheros AP143 reference board */
+	ATH79_MACH_AP147,		/* Atheros AP147 reference board */
+	ATH79_MACH_AP151,		/* Atheros AP151 reference board */
+	ATH79_MACH_AP152,		/* Atheros AP152 reference board */
 	ATH79_MACH_AP81,		/* Atheros AP81 reference board */
+	ATH79_MACH_AP83,		/* Atheros AP83 */
+	ATH79_MACH_AP96,		/* Atheros AP96 */
+	ATH79_MACH_AW_NR580,		/* AzureWave AW-NR580 */
+	ATH79_MACH_CAP4200AG,		/* Senao CAP4200AG */
+	ATH79_MACH_CUS227,		/* Qualcomm Atheros CUS227 board */
+	ATH79_MACH_DB120,		/* Atheros DB120 reference board */
+	ATH79_MACH_DB120_TB388,		/* Atheros DB120/TB388 ref board */
 	ATH79_MACH_PB44,		/* Atheros PB44 reference board */
+	ATH79_MACH_DIR_600_A1,		/* D-Link DIR-600 rev. A1 */
+	ATH79_MACH_DIR_615_C1,		/* D-Link DIR-615 rev. C1 */
+	ATH79_MACH_DIR_615_E4,		/* D-Link DIR-615 rev. E4 */
+	ATH79_MACH_DIR_825_B1,		/* D-Link DIR-825 rev. B1 */
+	ATH79_MACH_EW_DORIN,		/* embedded wireless Dorin Platform */
+	ATH79_MACH_EW_DORIN_ROUTER,	/* embedded wireless Dorin Router Platform */
+	ATH79_MACH_EAP7660D,		/* Senao EAP7660D */
+	ATH79_MACH_GENERIC_DT,		/* Qualcomm Atheros boards with device tree */
+	ATH79_MACH_JA76PF,		/* jjPlus JA76PF */
+	ATH79_MACH_JA76PF2,		/* jjPlus JA76PF2 */
+	ATH79_MACH_JWAP003,		/* jjPlus JWAP003 */
+	ATH79_MACH_HORNET_UB,		/* ALFA Networks Hornet-UB */
+	ATH79_MACH_MR600,		/* OpenMesh MR600 */
+	ATH79_MACH_MZK_W04NU,		/* Planex MZK-W04NU */
+	ATH79_MACH_MZK_W300NH,		/* Planex MZK-W300NH */
+	ATH79_MACH_NBG460N,		/* Zyxel NBG460N/550N/550NH */
+	ATH79_MACH_OM2P_HS,		/* OpenMesh OM2P-HS */
+	ATH79_MACH_OM2P_LC,		/* OpenMesh OM2P-LC */
+	ATH79_MACH_OM2P,		/* OpenMesh OM2P */
+	ATH79_MACH_PB42,		/* Atheros PB42 */
+	ATH79_MACH_PB92,		/* Atheros PB92 */
+	ATH79_MACH_RB_411,		/* MikroTik RouterBOARD 411/411A/411AH */
+	ATH79_MACH_RB_411U,		/* MikroTik RouterBOARD 411U */
+	ATH79_MACH_RB_433,		/* MikroTik RouterBOARD 433/433AH */
+	ATH79_MACH_RB_433U,		/* MikroTik RouterBOARD 433UAH */
+	ATH79_MACH_RB_435G,		/* MikroTik RouterBOARD 435G */
+	ATH79_MACH_RB_450G,		/* MikroTik RouterBOARD 450G */
+	ATH79_MACH_RB_450,		/* MikroTik RouterBOARD 450 */
+	ATH79_MACH_RB_493,		/* Mikrotik RouterBOARD 493/493AH */
+	ATH79_MACH_RB_493G,		/* Mikrotik RouterBOARD 493G */
+	ATH79_MACH_RB_750,		/* MikroTik RouterBOARD 750 */
+	ATH79_MACH_RB_750G_R3,		/* MikroTik RouterBOARD 750GL */
+	ATH79_MACH_RB_751,		/* MikroTik RouterBOARD 751 */
+	ATH79_MACH_RB_751G,		/* Mikrotik RouterBOARD 751G */
+	ATH79_MACH_RB_2011G,		/* Mikrotik RouterBOARD 2011UAS-2HnD */
+	ATH79_MACH_RB_2011L,		/* Mikrotik RouterBOARD 2011L */
+	ATH79_MACH_RUBBERDUCK,		/* Qualcomm-Atheros RubberDuck */
+	ATH79_MACH_RW2458N,		/* Redwave RW2458N */
+	ATH79_MACH_TEW_632BRP,		/* TRENDnet TEW-632BRP */
+	ATH79_MACH_TEW_673GRU,		/* TRENDnet TEW-673GRU */
+	ATH79_MACH_TEW_712BR,		/* TRENDnet TEW-712BR */
+	ATH79_MACH_TL_MR11U,		/* TP-LINK TL-MR11U */
+	ATH79_MACH_TL_MR3020,		/* TP-LINK TL-MR3020 */
+	ATH79_MACH_TL_MR3040,		/* TP-LINK TL-MR3040 */
+	ATH79_MACH_TL_MR3220,		/* TP-LINK TL-MR3220 */
+	ATH79_MACH_TL_MR3420,		/* TP-LINK TL-MR3420 */
+	ATH79_MACH_TL_WA7510N_V1,	/* TP-LINK TL-WA7510N v1*/
+	ATH79_MACH_TL_WA901ND,		/* TP-LINK TL-WA901ND */
+	ATH79_MACH_TL_WA901ND_V2,	/* TP-LINK TL-WA901ND v2 */
+	ATH79_MACH_TL_WDR4300,		/* TP-LINK TL-WDR4300 */
+	ATH79_MACH_TL_WR1041N_V2,	/* TP-LINK TL-WR1041N v2 */
+	ATH79_MACH_TL_WR1043ND,		/* TP-LINK TL-WR1043ND */
+	ATH79_MACH_TL_WR2543N,		/* TP-LINK TL-WR2543N/ND */
+	ATH79_MACH_TL_WR703N,		/* TP-LINK TL-WR703N */
+	ATH79_MACH_TL_WR741ND,		/* TP-LINK TL-WR741ND */
+	ATH79_MACH_TL_WR741ND_V4,	/* TP-LINK TL-WR741ND  v4*/
+	ATH79_MACH_TL_WR841N_V1,	/* TP-LINK TL-WR841N v1 */
+	ATH79_MACH_TL_WR841N_V7,	/* TP-LINK TL-WR841N/ND v7 */
+	ATH79_MACH_TL_WR841N_V8,	/* TP-LINK TL-WR841N/ND v8 */
+	ATH79_MACH_TL_WR941ND,		/* TP-LINK TL-WR941ND */
+	ATH79_MACH_UBNT_AIRROUTER,	/* Ubiquiti AirRouter */
+	ATH79_MACH_UBNT_BULLET_M,	/* Ubiquiti Bullet M */
+	ATH79_MACH_UBNT_LSSR71,		/* Ubiquiti LS-SR71 */
+	ATH79_MACH_UBNT_LSX,		/* Ubiquiti LSX */
+	ATH79_MACH_UBNT_NANO_M, 	/* Ubiquiti NanoStation M */
+	ATH79_MACH_UBNT_ROCKET_M,	/* Ubiquiti Rocket M */
+	ATH79_MACH_UBNT_RSPRO,		/* Ubiquiti RouterStation Pro */
+	ATH79_MACH_UBNT_RS,		/* Ubiquiti RouterStation */
+	ATH79_MACH_UBNT_UNIFI, 		/* Ubiquiti Unifi */
+	ATH79_MACH_UBNT_UNIFI_OUTDOOR,	/* Ubiquiti UnifiAP Outdoor */
 	ATH79_MACH_UBNT_XM,		/* Ubiquiti Networks XM board rev 1.0 */
+	ATH79_MACH_WHR_G301N,		/* Buffalo WHR-G301N */
+	ATH79_MACH_WHR_HP_G300N,	/* Buffalo WHR-HP-G300N */
+	ATH79_MACH_WHR_HP_GN,		/* Buffalo WHR-HP-GN */
+	ATH79_MACH_WLAE_AG300N,		/* Buffalo WLAE-AG300N */
+	ATH79_MACH_WNDR3700,		/* NETGEAR WNDR3700/WNDR3800/WNDRMAC */
+	ATH79_MACH_WNR2000,		/* NETGEAR WNR2000 */
+	ATH79_MACH_WP543,		/* Compex WP543 */
+	ATH79_MACH_WPE72,		/* Compex WPE72 */
+	ATH79_MACH_WRT160NL,		/* Linksys WRT160NL */
+	ATH79_MACH_WRT400N,		/* Linksys WRT400N */
+	ATH79_MACH_WZR_HP_AG300H,	/* Buffalo WZR-HP-AG300H */
+	ATH79_MACH_WZR_HP_G300NH,	/* Buffalo WZR-HP-G300NH */
+	ATH79_MACH_WZR_HP_G300NH2,	/* Buffalo WZR-HP-G300NH2 */
+	ATH79_MACH_WZR_HP_G450H,	/* Buffalo WZR-HP-G450H */
+	ATH79_MACH_ZCN_1523H_2,		/* Zcomax ZCN-1523H-2-xx */
+	ATH79_MACH_ZCN_1523H_5,		/* Zcomax ZCN-1523H-5-xx */
 };
 
 #endif /* _ATH79_MACHTYPE_H */
diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c
new file mode 100644
index 0000000..e5cb82d
--- /dev/null
+++ b/arch/mips/ath79/pci.c
@@ -0,0 +1,353 @@
+/*
+ *  Atheros AR71XX/AR724X specific PCI setup code
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  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.
+ */
+
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/pci.h>
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/irq.h>
+#include "pci.h"
+
+static int (*ath79_pci_plat_dev_init)(struct pci_dev *dev);
+static const struct ath79_pci_irq *ath79_pci_irq_map __initdata;
+static unsigned ath79_pci_nr_irqs __initdata;
+
+static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port);
+static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port);
+
+static const struct ath79_pci_irq ar71xx_pci_irq_map[] __initconst = {
+	{
+		.slot	= 17,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	}, {
+		.slot	= 18,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(1),
+	}, {
+		.slot	= 19,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(2),
+	}
+};
+
+static const struct ath79_pci_irq ar724x_pci_irq_map[] __initconst = {
+	{
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	}
+};
+
+static const struct ath79_pci_irq qca955x_pci_irq_map[] __initconst = {
+	{
+		.bus	= 0,
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	},
+	{
+		.bus	= 1,
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(1),
+	},
+};
+
+static const struct ath79_pci_irq qca953x_pci_irq_map[] __initconst = {
+	{
+		.bus	= 0,
+		.slot	= 0,
+		.pin	= 1,
+		.irq	= ATH79_PCI_IRQ(0),
+	}
+};
+
+static const struct ath79_pci_irq qca956x_pci_irq_map[] __initconst = {
+        {
+                .bus    = 0,
+                .slot   = 0,
+                .pin    = 1,
+                .irq    = ATH79_PCI_IRQ(0),
+        },
+        {
+                .bus    = 1,
+                .slot   = 0,
+                .pin    = 1,
+                .irq    = ATH79_PCI_IRQ(1),
+        },
+};
+
+int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
+{
+	int irq = -1;
+	int i;
+
+	if (ath79_pci_nr_irqs == 0 ||
+	    ath79_pci_irq_map == NULL) {
+		if (soc_is_ar71xx()) {
+			ath79_pci_irq_map = ar71xx_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(ar71xx_pci_irq_map);
+		} else if (soc_is_ar724x() ||
+			   soc_is_ar9342() ||
+			   soc_is_ar9344()) {
+			ath79_pci_irq_map = ar724x_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(ar724x_pci_irq_map);
+		} else if (soc_is_qca955x()) {
+			ath79_pci_irq_map = qca955x_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map);
+		} else if (soc_is_qca953x()) {
+			ath79_pci_irq_map = qca953x_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(qca953x_pci_irq_map);
+		} else if (soc_is_qca956x()) {
+			ath79_pci_irq_map = qca956x_pci_irq_map;
+			ath79_pci_nr_irqs = ARRAY_SIZE(qca956x_pci_irq_map);
+		} else {
+			pr_crit("pci %s: invalid irq map\n",
+				pci_name((struct pci_dev *) dev));
+			return irq;
+		}
+	}
+
+	for (i = 0; i < ath79_pci_nr_irqs; i++) {
+		const struct ath79_pci_irq *entry;
+
+		entry = &ath79_pci_irq_map[i];
+		if (entry->bus == dev->bus->number &&
+		    entry->slot == slot &&
+		    entry->pin == pin) {
+			irq = entry->irq;
+			break;
+		}
+	}
+
+	if (irq < 0)
+		pr_crit("pci %s: no irq found for pin %u\n",
+			pci_name((struct pci_dev *) dev), pin);
+	else
+		pr_info("pci %s: using irq %d for pin %u\n",
+			pci_name((struct pci_dev *) dev), irq, pin);
+
+	return irq;
+}
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	if (ath79_pci_plat_dev_init)
+		return ath79_pci_plat_dev_init(dev);
+
+	return 0;
+}
+
+void __init ath79_pci_set_irq_map(unsigned nr_irqs,
+				  const struct ath79_pci_irq *map)
+{
+	ath79_pci_nr_irqs = nr_irqs;
+	ath79_pci_irq_map = map;
+}
+
+void __init ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev))
+{
+	ath79_pci_plat_dev_init = func;
+}
+
+static struct platform_device *
+ath79_register_pci_ar71xx(void)
+{
+	struct platform_device *pdev;
+	struct resource res[2];
+
+	memset(res, 0, sizeof(res));
+
+	res[0].name = "cfg_base";
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = AR71XX_PCI_CFG_BASE;
+	res[0].end = AR71XX_PCI_CFG_BASE + AR71XX_PCI_CFG_SIZE - 1;
+
+	res[1].flags = IORESOURCE_IRQ;
+	res[1].start = ATH79_CPU_IRQ_IP2;
+	res[1].end = ATH79_CPU_IRQ_IP2;
+
+	pdev = platform_device_register_simple("ar71xx-pci", -1,
+					       res, ARRAY_SIZE(res));
+	return pdev;
+}
+
+static struct platform_device *
+ath79_register_pci_ar724x(int id,
+			  unsigned long cfg_base,
+			  unsigned long ctrl_base,
+			  unsigned long crp_base,
+			  unsigned long mem_base,
+			  unsigned long mem_size,
+			  unsigned long io_base,
+			  int irq)
+{
+	struct platform_device *pdev;
+	struct resource res[6];
+
+	memset(res, 0, sizeof(res));
+
+	res[0].name = "cfg_base";
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = cfg_base;
+	res[0].end = cfg_base + AR724X_PCI_CFG_SIZE - 1;
+
+	res[1].name = "ctrl_base";
+	res[1].flags = IORESOURCE_MEM;
+	res[1].start = ctrl_base;
+	res[1].end = ctrl_base + AR724X_PCI_CTRL_SIZE - 1;
+
+	res[2].flags = IORESOURCE_IRQ;
+	res[2].start = irq;
+	res[2].end = irq;
+
+	res[3].name = "mem_base";
+	res[3].flags = IORESOURCE_MEM;
+	res[3].start = mem_base;
+	res[3].end = mem_base + mem_size - 1;
+
+	res[4].name = "io_base";
+	res[4].flags = IORESOURCE_IO;
+	res[4].start = io_base;
+	res[4].end = io_base;
+
+	res[5].name = "crp_base";
+	res[5].flags = IORESOURCE_MEM;
+	res[5].start = crp_base;
+	res[5].end = crp_base + AR724X_PCI_CRP_SIZE - 1;
+
+	pdev = platform_device_register_simple("ar724x-pci", id,
+					       res, ARRAY_SIZE(res));
+	return pdev;
+}
+
+static inline bool ar71xx_is_pci_addr(unsigned long port)
+{
+	unsigned long phys = CPHYSADDR(port);
+
+	return (phys >= AR71XX_PCI_MEM_BASE &&
+		phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE);
+}
+
+static unsigned long ar71xx_pci_swizzle_b(unsigned long port)
+{
+	return ar71xx_is_pci_addr(port) ? port ^ 3 : port;
+}
+
+static unsigned long ar71xx_pci_swizzle_w(unsigned long port)
+{
+	return ar71xx_is_pci_addr(port) ? port ^ 2 : port;
+}
+
+unsigned long ath79_pci_swizzle_b(unsigned long port)
+{
+	if (__ath79_pci_swizzle_b)
+		return __ath79_pci_swizzle_b(port);
+
+	return port;
+}
+EXPORT_SYMBOL(ath79_pci_swizzle_b);
+
+unsigned long ath79_pci_swizzle_w(unsigned long port)
+{
+	if (__ath79_pci_swizzle_w)
+		return __ath79_pci_swizzle_w(port);
+
+	return port;
+}
+EXPORT_SYMBOL(ath79_pci_swizzle_w);
+
+int __init ath79_register_pci(void)
+{
+	struct platform_device *pdev = NULL;
+
+	if (soc_is_ar71xx()) {
+		pdev = ath79_register_pci_ar71xx();
+		__ath79_pci_swizzle_b = ar71xx_pci_swizzle_b;
+		__ath79_pci_swizzle_w = ar71xx_pci_swizzle_w;
+	} else if (soc_is_ar724x()) {
+		pdev = ath79_register_pci_ar724x(-1,
+						 AR724X_PCI_CFG_BASE,
+						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_CRP_BASE,
+						 AR724X_PCI_MEM_BASE,
+						 AR724X_PCI_MEM_SIZE,
+						 0,
+						 ATH79_CPU_IRQ_IP2);
+	} else if (soc_is_ar9342() ||
+		   soc_is_ar9344()) {
+		u32 bootstrap;
+
+		bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
+		if ((bootstrap & AR934X_BOOTSTRAP_PCIE_RC) == 0)
+			return -ENODEV;
+
+		pdev = ath79_register_pci_ar724x(-1,
+						 AR724X_PCI_CFG_BASE,
+						 AR724X_PCI_CTRL_BASE,
+						 AR724X_PCI_CRP_BASE,
+						 AR724X_PCI_MEM_BASE,
+						 AR724X_PCI_MEM_SIZE,
+						 0,
+						 ATH79_IP2_IRQ(0));
+	} else if (soc_is_qca9558()) {
+		pdev = ath79_register_pci_ar724x(0,
+						 QCA955X_PCI_CFG_BASE0,
+						 QCA955X_PCI_CTRL_BASE0,
+						 QCA955X_PCI_CRP_BASE0,
+						 QCA955X_PCI_MEM_BASE0,
+						 QCA955X_PCI_MEM_SIZE,
+						 0,
+						 ATH79_IP2_IRQ(0));
+
+		pdev = ath79_register_pci_ar724x(1,
+						 QCA955X_PCI_CFG_BASE1,
+						 QCA955X_PCI_CTRL_BASE1,
+						 QCA955X_PCI_CRP_BASE1,
+						 QCA955X_PCI_MEM_BASE1,
+						 QCA955X_PCI_MEM_SIZE,
+						 1,
+						 ATH79_IP3_IRQ(2));
+	} else if (soc_is_qca953x()) {
+		pdev = ath79_register_pci_ar724x(0,
+						 QCA953X_PCI_CFG_BASE0,
+						 QCA953X_PCI_CTRL_BASE0,
+						 QCA953X_PCI_CRP_BASE0,
+						 QCA953X_PCI_MEM_BASE0,
+						 QCA953X_PCI_MEM_SIZE,
+						 0,
+						 ATH79_IP2_IRQ(0));
+	} else if (soc_is_qca956x()) {
+		pdev = ath79_register_pci_ar724x(0,
+						 QCA956X_PCI_CFG_BASE1,
+						 QCA956X_PCI_CTRL_BASE1,
+						 QCA956X_PCI_CRP_BASE1,
+						 QCA956X_PCI_MEM_BASE1,
+						 QCA956X_PCI_MEM_SIZE,
+						 1,
+						 ATH79_IP3_IRQ(2));
+	} else {
+		/* No PCI support */
+		return -ENODEV;
+	}
+
+	if (!pdev)
+		pr_err("unable to register PCI controller device\n");
+
+	return pdev ? 0 : -ENODEV;
+}
diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h
new file mode 100644
index 0000000..1d00a38
--- /dev/null
+++ b/arch/mips/ath79/pci.h
@@ -0,0 +1,35 @@
+/*
+ *  Atheros AR71XX/AR724X PCI support
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  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.
+ */
+
+#ifndef _ATH79_PCI_H
+#define _ATH79_PCI_H
+
+struct ath79_pci_irq {
+	int	bus;
+	u8	slot;
+	u8	pin;
+	int	irq;
+};
+
+#ifdef CONFIG_PCI
+void ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map);
+void ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *dev));
+int ath79_register_pci(void);
+#else
+static inline void
+ath79_pci_set_irq_map(unsigned nr_irqs, const struct ath79_pci_irq *map) {}
+static inline void
+ath79_pci_set_plat_dev_init(int (*func)(struct pci_dev *)) {}
+static inline int ath79_register_pci(void) { return 0; }
+#endif
+
+#endif /* _ATH79_PCI_H */
diff --git a/arch/mips/ath79/prom.c b/arch/mips/ath79/prom.c
index e9cbd7c..2102df8 100644
--- a/arch/mips/ath79/prom.c
+++ b/arch/mips/ath79/prom.c
@@ -16,9 +16,12 @@
 
 #include <asm/bootinfo.h>
 #include <asm/addrspace.h>
+#include <asm/fw/myloader/myloader.h>
 
 #include "common.h"
 
+static char ath79_cmdline_buf[COMMAND_LINE_SIZE] __initdata;
+
 static inline int is_valid_ram_addr(void *addr)
 {
 	if (((u32) addr > KSEG0) &&
@@ -32,10 +35,110 @@
 	return 0;
 }
 
+static void __init ath79_prom_append_cmdline(const char *name,
+					      const char *value)
+{
+	snprintf(ath79_cmdline_buf, sizeof(ath79_cmdline_buf),
+		 " %s=%s", name, value);
+	strlcat(arcs_cmdline, ath79_cmdline_buf, sizeof(arcs_cmdline));
+}
+
+static const char * __init ath79_prom_find_env(char **envp, const char *name)
+{
+	const char *ret = NULL;
+	int len;
+	char **p;
+
+	if (!is_valid_ram_addr(envp))
+		return NULL;
+
+	len = strlen(name);
+	for (p = envp; is_valid_ram_addr(*p); p++) {
+		if (strncmp(name, *p, len) == 0 && (*p)[len] == '=') {
+			ret = *p + len + 1;
+			break;
+		}
+
+		/* RedBoot env comes in pointer pairs - key, value */
+		if (strncmp(name, *p, len) == 0 && (*p)[len] == 0)
+			if (is_valid_ram_addr(*(++p))) {
+				ret = *p;
+				break;
+			}
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
+extern char __image_cmdline[];
+
+static int __init ath79_use_image_cmdline(void)
+{
+	char *p = __image_cmdline;
+	int replace = 0;
+
+	if (*p == '-') {
+		replace = 1;
+		p++;
+	}
+
+	if (*p == '\0')
+		return 0;
+
+	if (replace) {
+		strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline));
+	} else {
+		strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+		strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+	}
+
+	return 1;
+}
+#else
+static inline int ath79_use_image_cmdline(void) { return 0; }
+#endif
+
+static int __init ath79_prom_init_myloader(void)
+{
+	struct myloader_info *mylo;
+	char mac_buf[32];
+	unsigned char *mac;
+
+	mylo = myloader_get_info();
+	if (!mylo)
+		return 0;
+
+	switch (mylo->did) {
+	case DEVID_COMPEX_WP543:
+		ath79_prom_append_cmdline("board", "WP543");
+		break;
+	case DEVID_COMPEX_WPE72:
+		ath79_prom_append_cmdline("board", "WPE72");
+		break;
+	default:
+		pr_warn("prom: unknown device id: %x\n", mylo->did);
+		return 0;
+	}
+
+	mac = mylo->macs[0];
+	snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x",
+		 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+	ath79_prom_append_cmdline("ethaddr", mac_buf);
+
+	ath79_use_image_cmdline();
+
+	return 1;
+}
+
 static __init void ath79_prom_init_cmdline(int argc, char **argv)
 {
 	int i;
 
+	if (ath79_use_image_cmdline())
+		return;
+
 	if (!is_valid_ram_addr(argv))
 		return;
 
@@ -48,7 +151,39 @@
 
 void __init prom_init(void)
 {
+	const char *env;
+	char **envp;
+
+	if (ath79_prom_init_myloader())
+		return;
+
 	ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1);
+
+	envp = (char **)fw_arg2;
+	if (!strstr(arcs_cmdline, "ethaddr=")) {
+		env = ath79_prom_find_env(envp, "ethaddr");
+		if (env)
+			ath79_prom_append_cmdline("ethaddr", env);
+	}
+
+	if (!strstr(arcs_cmdline, "board=")) {
+		env = ath79_prom_find_env(envp, "board");
+		if (env) {
+			/* Workaround for buggy bootloaders */
+			if (strcmp(env, "RouterStation") == 0 ||
+			    strcmp(env, "Ubiquiti AR71xx-based board") == 0)
+				env = "UBNT-RS";
+
+			if (strcmp(env, "RouterStation PRO") == 0)
+				env = "UBNT-RSPRO";
+
+			ath79_prom_append_cmdline("board", env);
+		}
+	}
+
+	if (strstr(arcs_cmdline, "board=750Gr3") ||
+	    strstr(arcs_cmdline, "board=2011L"))
+		ath79_prom_append_cmdline("console", "ttyS0,115200");
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 80a7d40..3c40b13 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -1,10 +1,11 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X specific setup
  *
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
  *
  *  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
@@ -116,18 +117,6 @@
 		rev = id & AR724X_REV_ID_REVISION_MASK;
 		break;
 
-	case REV_ID_MAJOR_AR9330:
-		ath79_soc = ATH79_SOC_AR9330;
-		chip = "9330";
-		rev = id & AR933X_REV_ID_REVISION_MASK;
-		break;
-
-	case REV_ID_MAJOR_AR9331:
-		ath79_soc = ATH79_SOC_AR9331;
-		chip = "9331";
-		rev = id & AR933X_REV_ID_REVISION_MASK;
-		break;
-
 	case REV_ID_MAJOR_AR913X:
 		minor = id & AR913X_REV_ID_MINOR_MASK;
 		rev = id >> AR913X_REV_ID_REVISION_SHIFT;
@@ -145,13 +134,66 @@
 		}
 		break;
 
-	default:
+	case REV_ID_MAJOR_AR9330:
+		ath79_soc = ATH79_SOC_AR9330;
+		chip = "9330";
+		rev = id & AR933X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_AR9331:
+		ath79_soc = ATH79_SOC_AR9331;
+		chip = "9331";
+		rev = id & AR933X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_AR9341:
+		ath79_soc = ATH79_SOC_AR9341;
+		chip = "9341";
+		rev = id & AR934X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_AR9342:
+		ath79_soc = ATH79_SOC_AR9342;
+		chip = "9342";
+		rev = id & AR934X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_AR9344:
+		ath79_soc = ATH79_SOC_AR9344;
+		chip = "9344";
+		rev = id & AR934X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_QCA9558:
+		ath79_soc = ATH79_SOC_QCA9558;
+		chip = "9558";
+		rev = id & AR944X_REV_ID_REVISION_MASK;
+		break;
+
+	case REV_ID_MAJOR_QCA9531_V1:
+	case REV_ID_MAJOR_QCA9531_V2:
+		ath79_soc = ATH79_SOC_QCA9531;
+		chip = "9531";
+		rev = id & QCA953X_REV_ID_REVISION_MASK;
+		if (major == REV_ID_MAJOR_QCA9531_V2)
+			rev = 2;
+		break;
+	case REV_ID_MAJOR_QCA956X:
+		ath79_soc = ATH79_SOC_QCA956X;
+		chip = "956X";
+		rev = id & QCA956X_REV_ID_REVISION_MASK;
+		break;
+    default:
 		panic("ath79: unknown SoC, id:0x%08x", id);
 	}
 
 	ath79_soc_rev = rev;
 
-	sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
+	if (soc_is_qca955x() || soc_is_qca953x() || soc_is_qca956x())
+		sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s rev %u",
+			chip, rev);
+	else
+		sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
 	pr_info("SoC: %s\n", ath79_sys_type);
 }
 
@@ -196,6 +238,8 @@
 	mips_hpt_frequency = clk_get_rate(clk) / 2;
 }
 
+__setup("board=", mips_machtype_setup);
+
 static int __init ath79_setup(void)
 {
 	ath79_gpio_init();
diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h
index f2f7c6c..9be4201 100644
--- a/arch/mips/include/asm/checksum.h
+++ b/arch/mips/include/asm/checksum.h
@@ -12,6 +12,7 @@
 #define _ASM_CHECKSUM_H
 
 #include <linux/in6.h>
+#include <linux/unaligned/packed_struct.h>
 
 #include <asm/uaccess.h>
 
@@ -104,26 +105,30 @@
 	const unsigned int *stop = word + ihl;
 	unsigned int csum;
 	int carry;
+	unsigned int w;
 
-	csum = word[0];
-	csum += word[1];
-	carry = (csum < word[1]);
+	csum = __get_unaligned_cpu32(word++);
+
+	w = __get_unaligned_cpu32(word++);
+	csum += w;
+	carry = (csum < w);
 	csum += carry;
 
-	csum += word[2];
-	carry = (csum < word[2]);
+	w = __get_unaligned_cpu32(word++);
+	csum += w;
+	carry = (csum < w);
 	csum += carry;
 
-	csum += word[3];
-	carry = (csum < word[3]);
+	w = __get_unaligned_cpu32(word++);
+	csum += w;
+	carry = (csum < w);
 	csum += carry;
 
-	word += 4;
 	do {
-		csum += *word;
-		carry = (csum < *word);
+		w = __get_unaligned_cpu32(word++);
+		csum += w;
+		carry = (csum < w);
 		csum += carry;
-		word++;
 	} while (word != stop);
 
 	return csum_fold(csum);
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index 2f0becb..0559488 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -1,10 +1,12 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X SoC register definitions
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
  *
  *  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
@@ -20,8 +22,13 @@
 #include <linux/bitops.h>
 
 #define AR71XX_APB_BASE		0x18000000
+#define AR71XX_GE0_BASE		0x19000000
+#define AR71XX_GE0_SIZE		0x10000
+#define AR71XX_GE1_BASE		0x1a000000
+#define AR71XX_GE1_SIZE		0x10000
 #define AR71XX_EHCI_BASE	0x1b000000
-#define AR71XX_EHCI_SIZE	0x1000
+#define AR71XX_NAND_BASE	0x1b800000
+#define AR71XX_EHCI_SIZE	0x200
 #define AR71XX_OHCI_BASE	0x1c000000
 #define AR71XX_OHCI_SIZE	0x1000
 #define AR71XX_SPI_BASE		0x1f000000
@@ -39,26 +46,145 @@
 #define AR71XX_PLL_SIZE		0x100
 #define AR71XX_RESET_BASE	(AR71XX_APB_BASE + 0x00060000)
 #define AR71XX_RESET_SIZE	0x100
+#define AR71XX_MII_BASE		(AR71XX_APB_BASE + 0x00070000)
+#define AR71XX_MII_SIZE		0x100
+#define AR71XX_NAND_CTRL_BASE	(AR71XX_NAND_BASE + 0x00000200)
+#define AR71XX_NAND_CTRL_SIZE	0x0b8
+
+#define AR71XX_PCI_MEM_BASE	0x10000000
+#define AR71XX_PCI_MEM_SIZE	0x07000000
+
+#define AR71XX_PCI_WIN0_OFFS	0x10000000
+#define AR71XX_PCI_WIN1_OFFS	0x11000000
+#define AR71XX_PCI_WIN2_OFFS	0x12000000
+#define AR71XX_PCI_WIN3_OFFS	0x13000000
+#define AR71XX_PCI_WIN4_OFFS	0x14000000
+#define AR71XX_PCI_WIN5_OFFS	0x15000000
+#define AR71XX_PCI_WIN6_OFFS	0x16000000
+#define AR71XX_PCI_WIN7_OFFS	0x07000000
+
+#define AR71XX_PCI_CFG_BASE	\
+	(AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000)
+#define AR71XX_PCI_CFG_SIZE	0x100
 
 #define AR7240_USB_CTRL_BASE	(AR71XX_APB_BASE + 0x00030000)
 #define AR7240_USB_CTRL_SIZE	0x100
 #define AR7240_OHCI_BASE	0x1b000000
 #define AR7240_OHCI_SIZE	0x1000
 
+#define AR724X_PCI_MEM_BASE	0x10000000
+#define AR724X_PCI_MEM_SIZE	0x04000000
+
+#define AR724X_PCI_CFG_BASE	0x14000000
+#define AR724X_PCI_CFG_SIZE	0x1000
+#define AR724X_PCI_CRP_BASE	(AR71XX_APB_BASE + 0x000c0000)
+#define AR724X_PCI_CRP_SIZE	0x1000
+#define AR724X_PCI_CTRL_BASE	(AR71XX_APB_BASE + 0x000f0000)
+#define AR724X_PCI_CTRL_SIZE	0x100
+
 #define AR724X_EHCI_BASE	0x1b000000
-#define AR724X_EHCI_SIZE	0x1000
+#define AR724X_EHCI_SIZE	0x200
 
 #define AR913X_EHCI_BASE	0x1b000000
-#define AR913X_EHCI_SIZE	0x1000
+#define AR913X_EHCI_SIZE	0x200
 #define AR913X_WMAC_BASE	(AR71XX_APB_BASE + 0x000C0000)
 #define AR913X_WMAC_SIZE	0x30000
 
 #define AR933X_UART_BASE	(AR71XX_APB_BASE + 0x00020000)
 #define AR933X_UART_SIZE	0x14
+#define AR933X_GMAC_BASE	(AR71XX_APB_BASE + 0x00070000)
+#define AR933X_GMAC_SIZE	0x04
 #define AR933X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
 #define AR933X_WMAC_SIZE	0x20000
 #define AR933X_EHCI_BASE	0x1b000000
-#define AR933X_EHCI_SIZE	0x1000
+#define AR933X_EHCI_SIZE	0x200
+
+#define AR934X_GMAC_BASE	(AR71XX_APB_BASE + 0x00070000)
+#define AR934X_GMAC_SIZE	0x14
+#define AR934X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
+#define AR934X_WMAC_SIZE	0x20000
+#define AR934X_AUD_DPLL_BASE	(AR71XX_APB_BASE + 0x00116200)
+#define AR934X_AUD_DPLL_SIZE	0x10
+#define AR934X_EHCI_BASE	0x1b000000
+#define AR934X_EHCI_SIZE	0x200
+#define AR934X_DMA_BASE		(AR71XX_APB_BASE + 0x000A0000)
+#define AR934X_DMA_SIZE		0x6C
+#define AR934X_STEREO_BASE	(AR71XX_APB_BASE + 0x000B0000)
+#define AR934X_STEREO_SIZE	0x18
+#define AR934X_SRIF_BASE	(AR71XX_APB_BASE + 0x00116000)
+#define AR934X_SRIF_SIZE	0x1000
+#define AR934X_NFC_BASE		0x1b000200
+#define AR934X_NFC_SIZE		0xb8
+
+#define QCA953X_GMAC_BASE	(AR71XX_APB_BASE + 0x00070000)
+#define QCA953X_GMAC_SIZE	0x14
+#define QCA953X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
+#define QCA953X_WMAC_SIZE	0x20000
+#define QCA953X_EHCI_BASE	0x1b000000
+#define QCA953X_EHCI_SIZE	0x200
+#define QCA953X_SRIF_BASE	(AR71XX_APB_BASE + 0x00116000)
+#define QCA953X_SRIF_SIZE	0x1000
+
+#define QCA953X_PCI_CFG_BASE0	0x14000000
+#define QCA953X_PCI_CTRL_BASE0	(AR71XX_APB_BASE + 0x000f0000)
+#define QCA953X_PCI_CRP_BASE0	(AR71XX_APB_BASE + 0x000c0000)
+#define QCA953X_PCI_MEM_BASE0	0x10000000
+#define QCA953X_PCI_MEM_SIZE	0x02000000
+
+#define QCA955X_PCI_MEM_BASE0	0x10000000
+#define QCA955X_PCI_MEM_BASE1	0x12000000
+#define QCA955X_PCI_MEM_SIZE	0x02000000
+#define QCA955X_PCI_CFG_BASE0	0x14000000
+#define QCA955X_PCI_CFG_BASE1	0x16000000
+#define QCA955X_PCI_CFG_SIZE	0x1000
+#define QCA955X_PCI_CRP_BASE0	(AR71XX_APB_BASE + 0x000c0000)
+#define QCA955X_PCI_CRP_BASE1	(AR71XX_APB_BASE + 0x00250000)
+#define QCA955X_PCI_CRP_SIZE	0x1000
+#define QCA955X_PCI_CTRL_BASE0	(AR71XX_APB_BASE + 0x000f0000)
+#define QCA955X_PCI_CTRL_BASE1	(AR71XX_APB_BASE + 0x00280000)
+#define QCA955X_PCI_CTRL_SIZE	0x100
+
+#define QCA955X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
+#define QCA955X_WMAC_SIZE	0x20000
+#define QCA955X_EHCI0_BASE	0x1b000000
+#define QCA955X_EHCI1_BASE	0x1b400000
+#define QCA955X_EHCI_SIZE	0x200
+#define QCA955X_GMAC_BASE	(AR71XX_APB_BASE + 0x00070000)
+#define QCA955X_GMAC_SIZE	0x40
+#define QCA955X_NFC_BASE	0x1b000200
+#define QCA955X_NFC_SIZE	0xb8
+
+#define QCA956X_PCI_MEM_BASE1	0x12000000
+#define QCA956X_PCI_MEM_SIZE	0x02000000
+#define QCA956X_PCI_CFG_BASE1	0x16000000
+#define QCA956X_PCI_CFG_SIZE	0x1000
+#define QCA956X_PCI_CRP_BASE1	(AR71XX_APB_BASE + 0x00250000)
+#define QCA956X_PCI_CRP_SIZE	0x1000
+#define QCA956X_PCI_CTRL_BASE1	(AR71XX_APB_BASE + 0x00280000)
+#define QCA956X_PCI_CTRL_SIZE	0x100
+
+#define QCA956X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
+#define QCA956X_WMAC_SIZE	0x20000
+#define QCA956X_EHCI0_BASE	0x1b000000
+#define QCA956X_EHCI1_BASE	0x1b400000
+#define QCA956X_EHCI_SIZE	0x200
+#define QCA956X_GMAC_BASE	(AR71XX_APB_BASE + 0x00070000)
+#define QCA956X_GMAC_SIZE	0x64
+
+#define AR9300_OTP_BASE		0x14000
+#define AR9300_OTP_STATUS	0x15f18
+#define AR9300_OTP_STATUS_TYPE		0x7
+#define AR9300_OTP_STATUS_VALID		0x4
+#define AR9300_OTP_STATUS_ACCESS_BUSY	0x2
+#define AR9300_OTP_STATUS_SM_BUSY	0x1
+#define AR9300_OTP_READ_DATA	0x15f1c
+
+/*
+ * Hidden Registers
+ */
+#define QCA956X_DAM_RESET_OFFSET	0xb90001bc
+#define QCA956X_DAM_RESET_SIZE		0x4
+#define QCA956X_INLINE_CHKSUM_ENG	BIT(27)
 
 /*
  * DDR_CTRL block
@@ -91,6 +217,18 @@
 #define AR933X_DDR_REG_FLUSH_USB	0x84
 #define AR933X_DDR_REG_FLUSH_WMAC	0x88
 
+#define AR934X_DDR_REG_FLUSH_GE0	0x9c
+#define AR934X_DDR_REG_FLUSH_GE1	0xa0
+#define AR934X_DDR_REG_FLUSH_USB	0xa4
+#define AR934X_DDR_REG_FLUSH_PCIE	0xa8
+#define AR934X_DDR_REG_FLUSH_WMAC	0xac
+
+#define QCA953X_DDR_REG_FLUSH_GE0	0x9c
+#define QCA953X_DDR_REG_FLUSH_GE1	0xa0
+#define QCA953X_DDR_REG_FLUSH_USB	0xa4
+#define QCA953X_DDR_REG_FLUSH_PCIE	0xa8
+#define QCA953X_DDR_REG_FLUSH_WMAC	0xac
+
 /*
  * PLL block
  */
@@ -108,6 +246,9 @@
 #define AR71XX_AHB_DIV_SHIFT		20
 #define AR71XX_AHB_DIV_MASK		0x7
 
+#define AR71XX_ETH0_PLL_SHIFT		17
+#define AR71XX_ETH1_PLL_SHIFT		19
+
 #define AR724X_PLL_REG_CPU_CONFIG	0x00
 #define AR724X_PLL_REG_PCIE_CONFIG	0x18
 
@@ -120,6 +261,8 @@
 #define AR724X_DDR_DIV_SHIFT		22
 #define AR724X_DDR_DIV_MASK		0x3
 
+#define AR7242_PLL_REG_ETH0_INT_CLOCK	0x2c
+
 #define AR913X_PLL_REG_CPU_CONFIG	0x00
 #define AR913X_PLL_REG_ETH_CONFIG	0x04
 #define AR913X_PLL_REG_ETH0_INT_CLOCK	0x14
@@ -132,6 +275,9 @@
 #define AR913X_AHB_DIV_SHIFT		19
 #define AR913X_AHB_DIV_MASK		0x1
 
+#define AR913X_ETH0_PLL_SHIFT		20
+#define AR913X_ETH1_PLL_SHIFT		22
+
 #define AR933X_PLL_CPU_CONFIG_REG	0x00
 #define AR933X_PLL_CLOCK_CTRL_REG	0x08
 
@@ -150,6 +296,178 @@
 #define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT	15
 #define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK	0x7
 
+#define AR934X_PLL_CPU_CONFIG_REG		0x00
+#define AR934X_PLL_DDR_CONFIG_REG		0x04
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_REG		0x08
+#define AR934X_PLL_SWITCH_CLOCK_CONTROL_REG	0x24
+#define AR934X_PLL_ETH_XMII_CONTROL_REG		0x2c
+#define AR934X_PLL_AUDIO_CONFIG_REG		0x30
+#define AR934X_PLL_AUDIO_MOD_REG		0x34
+
+#define AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT	0
+#define AR934X_PLL_CPU_CONFIG_NFRAC_MASK	0x3f
+#define AR934X_PLL_CPU_CONFIG_NINT_SHIFT	6
+#define AR934X_PLL_CPU_CONFIG_NINT_MASK		0x3f
+#define AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT	12
+#define AR934X_PLL_CPU_CONFIG_REFDIV_MASK	0x1f
+#define AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT	19
+#define AR934X_PLL_CPU_CONFIG_OUTDIV_MASK	0x3
+
+#define AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT	0
+#define AR934X_PLL_DDR_CONFIG_NFRAC_MASK	0x3ff
+#define AR934X_PLL_DDR_CONFIG_NINT_SHIFT	10
+#define AR934X_PLL_DDR_CONFIG_NINT_MASK		0x3f
+#define AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT	16
+#define AR934X_PLL_DDR_CONFIG_REFDIV_MASK	0x1f
+#define AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT	23
+#define AR934X_PLL_DDR_CONFIG_OUTDIV_MASK	0x7
+
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS	BIT(2)
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS	BIT(3)
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS	BIT(4)
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT	5
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK	0x1f
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT	10
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK	0x1f
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT	15
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK	0x1f
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL	BIT(20)
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL	BIT(21)
+#define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL	BIT(24)
+
+#define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL	BIT(6)
+
+#define QCA953X_PLL_CPU_CONFIG_REG		0x00
+#define QCA953X_PLL_DDR_CONFIG_REG		0x04
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_REG	0x08
+#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG	0x24
+#define QCA953X_PLL_ETH_XMII_CONTROL_REG	0x2c
+
+#define QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT	0
+#define QCA953X_PLL_CPU_CONFIG_NFRAC_MASK	0x3f
+#define QCA953X_PLL_CPU_CONFIG_NINT_SHIFT	6
+#define QCA953X_PLL_CPU_CONFIG_NINT_MASK	0x3f
+#define QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT	12
+#define QCA953X_PLL_CPU_CONFIG_REFDIV_MASK	0x1f
+#define QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT	19
+#define QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK	0x7
+
+#define QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT	0
+#define QCA953X_PLL_DDR_CONFIG_NFRAC_MASK	0x3ff
+#define QCA953X_PLL_DDR_CONFIG_NINT_SHIFT	10
+#define QCA953X_PLL_DDR_CONFIG_NINT_MASK	0x3f
+#define QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT	16
+#define QCA953X_PLL_DDR_CONFIG_REFDIV_MASK	0x1f
+#define QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT	23
+#define QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK	0x7
+
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS	BIT(2)
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS	BIT(3)
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS	BIT(4)
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT	5
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK	0x1f
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT	10
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK	0x1f
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT	15
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK	0x1f
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL	BIT(20)
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL	BIT(21)
+#define QCA953X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL	BIT(24)
+
+#define QCA953X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL	BIT(6)
+
+#define QCA955X_PLL_CPU_CONFIG_REG		0x00
+#define QCA955X_PLL_DDR_CONFIG_REG		0x04
+#define QCA955X_PLL_CLK_CTRL_REG		0x08
+
+#define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT	0
+#define QCA955X_PLL_CPU_CONFIG_NFRAC_MASK	0x3f
+#define QCA955X_PLL_CPU_CONFIG_NINT_SHIFT	6
+#define QCA955X_PLL_CPU_CONFIG_NINT_MASK	0x3f
+#define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT	12
+#define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK	0x1f
+#define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT	19
+#define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK	0x3
+
+#define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT	0
+#define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK	0x3ff
+#define QCA955X_PLL_DDR_CONFIG_NINT_SHIFT	10
+#define QCA955X_PLL_DDR_CONFIG_NINT_MASK	0x3f
+#define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT	16
+#define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK	0x1f
+#define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT	23
+#define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK	0x7
+
+#define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS		BIT(2)
+#define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS		BIT(3)
+#define QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS		BIT(4)
+#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT		5
+#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK		0x1f
+#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT		10
+#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK		0x1f
+#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT		15
+#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK		0x1f
+#define QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL		BIT(20)
+#define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL		BIT(21)
+#define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24)
+
+#define QCA956X_PLL_CPU_CONFIG_REG		0x00
+#define QCA956X_PLL_CPU_CONFIG1_REG		0x04
+#define QCA956X_PLL_DDR_CONFIG_REG		0x08
+#define QCA956X_PLL_DDR_CONFIG1_REG		0x0c
+#define QCA956X_PLL_CLK_CTRL_REG		0x10
+
+#define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT	12
+#define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK	0x1f
+#define QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT	19
+#define QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK	0x7
+
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT	0
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK	0x1f
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT	5
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK	0x1fff
+#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT	18
+#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK	0x1ff
+
+#define QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT	16
+#define QCA956X_PLL_DDR_CONFIG_REFDIV_MASK	0x1f
+#define QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT	23
+#define QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK	0x7
+
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT	0
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK	0x1f
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT	5
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK	0x1fff
+#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT	18
+#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK	0x1ff
+
+#define QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS		BIT(2)
+#define QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS		BIT(3)
+#define QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS		BIT(4)
+#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT		5
+#define QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK		0x1f
+#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT		10
+#define QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK		0x1f
+#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT		15
+#define QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK		0x1f
+#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL	BIT(20)
+#define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL	BIT(21)
+#define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24)
+
+#define AR934X_PLL_AUDIO_CONFIG_EXT_DIV_SHIFT		12
+#define AR934X_PLL_AUDIO_CONFIG_EXT_DIV_MASK		0x7
+#define AR934X_PLL_AUDIO_CONFIG_POSTPLLPWD_SHIFT	7
+#define AR934X_PLL_AUDIO_CONFIG_POSTPLLPWD_MASK		0x7
+#define AR934X_PLL_AUDIO_CONFIG_PLLPWD			BIT(5)
+#define AR934X_PLL_AUDIO_CONFIG_BYPASS			BIT(4)
+#define AR934X_PLL_AUDIO_CONFIG_REFDIV_SHIFT		0
+#define AR934X_PLL_AUDIO_CONFIG_REFDIV_MASK		0xf
+
+#define AR934X_PLL_AUDIO_MOD_TGT_DIV_FRAC_SHIFT	11
+#define AR934X_PLL_AUDIO_MOD_TGT_DIV_FRAC_MASK	0x3ffff
+#define AR934X_PLL_AUDIO_MOD_TGT_DIV_INT_SHIFT	1
+#define AR934X_PLL_AUDIO_MOD_TGT_DIV_INT_MASK	0x3f
+
 /*
  * USB_CONFIG block
  */
@@ -185,6 +503,21 @@
 #define AR933X_RESET_REG_RESET_MODULE		0x1c
 #define AR933X_RESET_REG_BOOTSTRAP		0xac
 
+#define AR934X_RESET_REG_RESET_MODULE		0x1c
+#define AR934X_RESET_REG_BOOTSTRAP		0xb0
+#define AR934X_RESET_REG_PCIE_WMAC_INT_STATUS	0xac
+
+#define QCA953X_RESET_REG_RESET_MODULE		0x1c
+#define QCA953X_RESET_REG_BOOTSTRAP		0xb0
+#define QCA953X_RESET_REG_PCIE_WMAC_INT_STATUS	0xac
+
+#define QCA955X_RESET_REG_BOOTSTRAP		0xb0
+#define QCA955X_RESET_REG_EXT_INT_STATUS	0xac
+
+#define QCA956X_RESET_REG_BOOTSTRAP		0xb0
+#define QCA956X_RESET_REG_EXT_INT_STATUS	0xac
+
+#define MISC_INT_MIPS_SI_TIMERINT_MASK	BIT(28)
 #define MISC_INT_ETHSW			BIT(12)
 #define MISC_INT_TIMER4			BIT(10)
 #define MISC_INT_TIMER3			BIT(9)
@@ -234,13 +567,198 @@
 #define AR913X_RESET_USB_HOST		BIT(5)
 #define AR913X_RESET_USB_PHY		BIT(4)
 
+#define AR933X_RESET_GE1_MDIO		BIT(23)
+#define AR933X_RESET_GE0_MDIO		BIT(22)
+#define AR933X_RESET_GE1_MAC		BIT(13)
 #define AR933X_RESET_WMAC		BIT(11)
+#define AR933X_RESET_GE0_MAC		BIT(9)
 #define AR933X_RESET_USB_HOST		BIT(5)
 #define AR933X_RESET_USB_PHY		BIT(4)
 #define AR933X_RESET_USBSUS_OVERRIDE	BIT(3)
 
+#define AR934X_RESET_HOST		BIT(31)
+#define AR934X_RESET_SLIC		BIT(30)
+#define AR934X_RESET_HDMA		BIT(29)
+#define AR934X_RESET_EXTERNAL		BIT(28)
+#define AR934X_RESET_RTC		BIT(27)
+#define AR934X_RESET_PCIE_EP_INT	BIT(26)
+#define AR934X_RESET_CHKSUM_ACC		BIT(25)
+#define AR934X_RESET_FULL_CHIP		BIT(24)
+#define AR934X_RESET_GE1_MDIO		BIT(23)
+#define AR934X_RESET_GE0_MDIO		BIT(22)
+#define AR934X_RESET_CPU_NMI		BIT(21)
+#define AR934X_RESET_CPU_COLD		BIT(20)
+#define AR934X_RESET_HOST_RESET_INT	BIT(19)
+#define AR934X_RESET_PCIE_EP		BIT(18)
+#define AR934X_RESET_UART1		BIT(17)
+#define AR934X_RESET_DDR		BIT(16)
+#define AR934X_RESET_USB_PHY_PLL_PWD_EXT BIT(15)
+#define AR934X_RESET_NANDF		BIT(14)
+#define AR934X_RESET_GE1_MAC		BIT(13)
+#define AR934X_RESET_ETH_SWITCH_ANALOG	BIT(12)
+#define AR934X_RESET_USB_PHY_ANALOG	BIT(11)
+#define AR934X_RESET_HOST_DMA_INT	BIT(10)
+#define AR934X_RESET_GE0_MAC		BIT(9)
+#define AR934X_RESET_ETH_SWITCH		BIT(8)
+#define AR934X_RESET_PCIE_PHY		BIT(7)
+#define AR934X_RESET_PCIE		BIT(6)
+#define AR934X_RESET_USB_HOST		BIT(5)
+#define AR934X_RESET_USB_PHY		BIT(4)
+#define AR934X_RESET_USBSUS_OVERRIDE	BIT(3)
+#define AR934X_RESET_LUT		BIT(2)
+#define AR934X_RESET_MBOX		BIT(1)
+#define AR934X_RESET_I2S		BIT(0)
+
+#define QCA953X_RESET_USB_EXT_PWR	BIT(29)
+#define QCA953X_RESET_EXTERNAL		BIT(28)
+#define QCA953X_RESET_RTC		BIT(27)
+#define QCA953X_RESET_FULL_CHIP		BIT(24)
+#define QCA953X_RESET_GE1_MDIO		BIT(23)
+#define QCA953X_RESET_GE0_MDIO		BIT(22)
+#define QCA953X_RESET_CPU_NMI		BIT(21)
+#define QCA953X_RESET_CPU_COLD		BIT(20)
+#define QCA953X_RESET_DDR		BIT(16)
+#define QCA953X_RESET_USB_PHY_PLL_PWD_EXT BIT(15)
+#define QCA953X_RESET_GE1_MAC		BIT(13)
+#define QCA953X_RESET_ETH_SWITCH_ANALOG	BIT(12)
+#define QCA953X_RESET_USB_PHY_ANALOG	BIT(11)
+#define QCA953X_RESET_GE0_MAC		BIT(9)
+#define QCA953X_RESET_ETH_SWITCH	BIT(8)
+#define QCA953X_RESET_PCIE_PHY		BIT(7)
+#define QCA953X_RESET_PCIE		BIT(6)
+#define QCA953X_RESET_USB_HOST		BIT(5)
+#define QCA953X_RESET_USB_PHY		BIT(4)
+#define QCA953X_RESET_USBSUS_OVERRIDE	BIT(3)
+
+#define AR933X_BOOTSTRAP_MDIO_GPIO_EN	BIT(18)
+#define AR933X_BOOTSTRAP_EEPBUSY	BIT(4)
 #define AR933X_BOOTSTRAP_REF_CLK_40	BIT(0)
 
+#define AR934X_BOOTSTRAP_SW_OPTION8	BIT(23)
+#define AR934X_BOOTSTRAP_SW_OPTION7	BIT(22)
+#define AR934X_BOOTSTRAP_SW_OPTION6	BIT(21)
+#define AR934X_BOOTSTRAP_SW_OPTION5	BIT(20)
+#define AR934X_BOOTSTRAP_SW_OPTION4	BIT(19)
+#define AR934X_BOOTSTRAP_SW_OPTION3	BIT(18)
+#define AR934X_BOOTSTRAP_SW_OPTION2	BIT(17)
+#define AR934X_BOOTSTRAP_SW_OPTION1	BIT(16)
+#define AR934X_BOOTSTRAP_USB_MODE_DEVICE BIT(7)
+#define AR934X_BOOTSTRAP_PCIE_RC	BIT(6)
+#define AR934X_BOOTSTRAP_EJTAG_MODE	BIT(5)
+#define AR934X_BOOTSTRAP_REF_CLK_40	BIT(4)
+#define AR934X_BOOTSTRAP_BOOT_FROM_SPI	BIT(2)
+#define AR934X_BOOTSTRAP_SDRAM_DISABLED	BIT(1)
+#define AR934X_BOOTSTRAP_DDR1		BIT(0)
+
+#define QCA953X_BOOTSTRAP_SW_OPTION2	BIT(12)
+#define QCA953X_BOOTSTRAP_SW_OPTION1	BIT(11)
+#define QCA953X_BOOTSTRAP_EJTAG_MODE	BIT(5)
+#define QCA953X_BOOTSTRAP_REF_CLK_40	BIT(4)
+#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1)
+#define QCA953X_BOOTSTRAP_DDR1		BIT(0)
+
+#define QCA955X_BOOTSTRAP_REF_CLK_40	BIT(4)
+
+#define QCA956X_BOOTSTRAP_REF_CLK_40	BIT(2)
+
+#define AR934X_PCIE_WMAC_INT_WMAC_MISC		BIT(0)
+#define AR934X_PCIE_WMAC_INT_WMAC_TX		BIT(1)
+#define AR934X_PCIE_WMAC_INT_WMAC_RXLP		BIT(2)
+#define AR934X_PCIE_WMAC_INT_WMAC_RXHP		BIT(3)
+#define AR934X_PCIE_WMAC_INT_PCIE_RC		BIT(4)
+#define AR934X_PCIE_WMAC_INT_PCIE_RC0		BIT(5)
+#define AR934X_PCIE_WMAC_INT_PCIE_RC1		BIT(6)
+#define AR934X_PCIE_WMAC_INT_PCIE_RC2		BIT(7)
+#define AR934X_PCIE_WMAC_INT_PCIE_RC3		BIT(8)
+#define AR934X_PCIE_WMAC_INT_WMAC_ALL \
+	(AR934X_PCIE_WMAC_INT_WMAC_MISC | AR934X_PCIE_WMAC_INT_WMAC_TX | \
+	 AR934X_PCIE_WMAC_INT_WMAC_RXLP | AR934X_PCIE_WMAC_INT_WMAC_RXHP)
+
+#define AR934X_PCIE_WMAC_INT_PCIE_ALL \
+	(AR934X_PCIE_WMAC_INT_PCIE_RC | AR934X_PCIE_WMAC_INT_PCIE_RC0 | \
+	 AR934X_PCIE_WMAC_INT_PCIE_RC1 | AR934X_PCIE_WMAC_INT_PCIE_RC2 | \
+	 AR934X_PCIE_WMAC_INT_PCIE_RC3)
+
+#define QCA953X_PCIE_WMAC_INT_WMAC_MISC		BIT(0)
+#define QCA953X_PCIE_WMAC_INT_WMAC_TX		BIT(1)
+#define QCA953X_PCIE_WMAC_INT_WMAC_RXLP		BIT(2)
+#define QCA953X_PCIE_WMAC_INT_WMAC_RXHP		BIT(3)
+#define QCA953X_PCIE_WMAC_INT_PCIE_RC		BIT(4)
+#define QCA953X_PCIE_WMAC_INT_PCIE_RC0		BIT(5)
+#define QCA953X_PCIE_WMAC_INT_PCIE_RC1		BIT(6)
+#define QCA953X_PCIE_WMAC_INT_PCIE_RC2		BIT(7)
+#define QCA953X_PCIE_WMAC_INT_PCIE_RC3		BIT(8)
+#define QCA953X_PCIE_WMAC_INT_WMAC_ALL \
+	(QCA953X_PCIE_WMAC_INT_WMAC_MISC | QCA953X_PCIE_WMAC_INT_WMAC_TX | \
+	 QCA953X_PCIE_WMAC_INT_WMAC_RXLP | QCA953X_PCIE_WMAC_INT_WMAC_RXHP)
+
+#define QCA953X_PCIE_WMAC_INT_PCIE_ALL \
+	(QCA953X_PCIE_WMAC_INT_PCIE_RC | QCA953X_PCIE_WMAC_INT_PCIE_RC0 | \
+	 QCA953X_PCIE_WMAC_INT_PCIE_RC1 | QCA953X_PCIE_WMAC_INT_PCIE_RC2 | \
+	 QCA953X_PCIE_WMAC_INT_PCIE_RC3)
+ 
+#define QCA955X_EXT_INT_WMAC_MISC		BIT(0)
+#define QCA955X_EXT_INT_WMAC_TX			BIT(1)
+#define QCA955X_EXT_INT_WMAC_RXLP		BIT(2)
+#define QCA955X_EXT_INT_WMAC_RXHP		BIT(3)
+#define QCA955X_EXT_INT_PCIE_RC1		BIT(4)
+#define QCA955X_EXT_INT_PCIE_RC1_INT0		BIT(5)
+#define QCA955X_EXT_INT_PCIE_RC1_INT1		BIT(6)
+#define QCA955X_EXT_INT_PCIE_RC1_INT2		BIT(7)
+#define QCA955X_EXT_INT_PCIE_RC1_INT3		BIT(8)
+#define QCA955X_EXT_INT_PCIE_RC2		BIT(12)
+#define QCA955X_EXT_INT_PCIE_RC2_INT0		BIT(13)
+#define QCA955X_EXT_INT_PCIE_RC2_INT1		BIT(14)
+#define QCA955X_EXT_INT_PCIE_RC2_INT2		BIT(15)
+#define QCA955X_EXT_INT_PCIE_RC2_INT3		BIT(16)
+#define QCA955X_EXT_INT_USB1			BIT(24)
+#define QCA955X_EXT_INT_USB2			BIT(28)
+
+#define QCA955X_EXT_INT_WMAC_ALL \
+	(QCA955X_EXT_INT_WMAC_MISC | QCA955X_EXT_INT_WMAC_TX | \
+	 QCA955X_EXT_INT_WMAC_RXLP | QCA955X_EXT_INT_WMAC_RXHP)
+
+#define QCA955X_EXT_INT_PCIE_RC1_ALL \
+	(QCA955X_EXT_INT_PCIE_RC1 | QCA955X_EXT_INT_PCIE_RC1_INT0 | \
+	 QCA955X_EXT_INT_PCIE_RC1_INT1 | QCA955X_EXT_INT_PCIE_RC1_INT2 | \
+	 QCA955X_EXT_INT_PCIE_RC1_INT3)
+
+#define QCA955X_EXT_INT_PCIE_RC2_ALL \
+	(QCA955X_EXT_INT_PCIE_RC2 | QCA955X_EXT_INT_PCIE_RC2_INT0 | \
+	 QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \
+	 QCA955X_EXT_INT_PCIE_RC2_INT3)
+
+#define QCA956X_EXT_INT_WMAC_MISC		BIT(0)
+#define QCA956X_EXT_INT_WMAC_TX			BIT(1)
+#define QCA956X_EXT_INT_WMAC_RXLP		BIT(2)
+#define QCA956X_EXT_INT_WMAC_RXHP		BIT(3)
+#define QCA956X_EXT_INT_PCIE_RC1		BIT(4)
+#define QCA956X_EXT_INT_PCIE_RC1_INT0		BIT(5)
+#define QCA956X_EXT_INT_PCIE_RC1_INT1		BIT(6)
+#define QCA956X_EXT_INT_PCIE_RC1_INT2		BIT(7)
+#define QCA956X_EXT_INT_PCIE_RC1_INT3		BIT(8)
+#define QCA956X_EXT_INT_PCIE_RC2		BIT(12)
+#define QCA956X_EXT_INT_PCIE_RC2_INT0		BIT(13)
+#define QCA956X_EXT_INT_PCIE_RC2_INT1		BIT(14)
+#define QCA956X_EXT_INT_PCIE_RC2_INT2		BIT(15)
+#define QCA956X_EXT_INT_PCIE_RC2_INT3		BIT(16)
+#define QCA956X_EXT_INT_USB1			BIT(24)
+#define QCA956X_EXT_INT_USB2			BIT(28)
+
+#define QCA956X_EXT_INT_WMAC_ALL \
+	(QCA956X_EXT_INT_WMAC_MISC | QCA956X_EXT_INT_WMAC_TX | \
+	 QCA956X_EXT_INT_WMAC_RXLP | QCA956X_EXT_INT_WMAC_RXHP)
+
+#define QCA956X_EXT_INT_PCIE_RC1_ALL \
+	(QCA956X_EXT_INT_PCIE_RC1 | QCA956X_EXT_INT_PCIE_RC1_INT0 | \
+	 QCA956X_EXT_INT_PCIE_RC1_INT1 | QCA956X_EXT_INT_PCIE_RC1_INT2 | \
+	 QCA956X_EXT_INT_PCIE_RC1_INT3)
+
+#define QCA956X_EXT_INT_PCIE_RC2_ALL \
+	(QCA956X_EXT_INT_PCIE_RC2 | QCA956X_EXT_INT_PCIE_RC2_INT0 | \
+	 QCA956X_EXT_INT_PCIE_RC2_INT1 | QCA956X_EXT_INT_PCIE_RC2_INT2 | \
+	 QCA956X_EXT_INT_PCIE_RC2_INT3)
+
 #define REV_ID_MAJOR_MASK		0xfff0
 #define REV_ID_MAJOR_AR71XX		0x00a0
 #define REV_ID_MAJOR_AR913X		0x00b0
@@ -249,6 +767,13 @@
 #define REV_ID_MAJOR_AR7242		0x1100
 #define REV_ID_MAJOR_AR9330		0x0110
 #define REV_ID_MAJOR_AR9331		0x1110
+#define REV_ID_MAJOR_AR9341		0x0120
+#define REV_ID_MAJOR_AR9342		0x1120
+#define REV_ID_MAJOR_AR9344		0x2120
+#define REV_ID_MAJOR_QCA9531_V1	0x0140
+#define REV_ID_MAJOR_QCA9531_V2	0x0160
+#define REV_ID_MAJOR_QCA9558		0x1130
+#define REV_ID_MAJOR_QCA956X		0x1150
 
 #define AR71XX_REV_ID_MINOR_MASK	0x3
 #define AR71XX_REV_ID_MINOR_AR7130	0x0
@@ -264,8 +789,11 @@
 #define AR913X_REV_ID_REVISION_SHIFT	2
 
 #define AR933X_REV_ID_REVISION_MASK	0x3
-
 #define AR724X_REV_ID_REVISION_MASK	0x3
+#define AR934X_REV_ID_REVISION_MASK     0xf
+#define AR944X_REV_ID_REVISION_MASK	0xf
+#define QCA953X_REV_ID_REVISION_MASK	0xf
+#define QCA956X_REV_ID_REVISION_MASK	0xf
 
 /*
  * SPI block
@@ -304,9 +832,486 @@
 #define AR71XX_GPIO_REG_INT_ENABLE	0x24
 #define AR71XX_GPIO_REG_FUNC		0x28
 
+#define AR934X_GPIO_REG_OUT_FUNC0	0x2c
+#define AR934X_GPIO_REG_OUT_FUNC1	0x30
+#define AR934X_GPIO_REG_OUT_FUNC2	0x34
+#define AR934X_GPIO_REG_OUT_FUNC3	0x38
+#define AR934X_GPIO_REG_OUT_FUNC4	0x3c
+#define AR934X_GPIO_REG_OUT_FUNC5	0x40
+#define AR934X_GPIO_REG_IN_ENABLE0	0x44
+#define AR934X_GPIO_REG_IN_ENABLE1	0x48
+#define AR934X_GPIO_REG_IN_ENABLE2	0x4C
+#define AR934X_GPIO_REG_IN_ENABLE3	0x50
+#define AR934X_GPIO_REG_IN_ENABLE4	0x54
+#define AR934X_GPIO_REG_IN_ENABLE9	0x68
+#define AR934X_GPIO_REG_FUNC		0x6c
+
+#define AR934X_GPIO_OUT_MUX_SPI_CS1		7
+#define AR934X_GPIO_OUT_MUX_SPI_CS2		8
+#define AR934X_GPIO_OUT_MUX_SPI_CS0		9
+#define AR934X_GPIO_OUT_MUX_SPI_CLK		10
+#define AR934X_GPIO_OUT_MUX_SPI_MOSI		11
+#define AR934X_GPIO_OUT_MUX_I2S_CLK		12
+#define AR934X_GPIO_OUT_MUX_I2S_WS		13
+#define AR934X_GPIO_OUT_MUX_I2S_SD		14
+#define AR934X_GPIO_OUT_MUX_I2S_MCK		15
+#define AR934X_GPIO_OUT_MUX_SPDIF_OUT		25
+#define AR934X_GPIO_IN_MUX_SPI_MISO		0
+#define AR934X_GPIO_IN_MUX_UART0_SIN		1
+#define AR934X_GPIO_IN_MUX_I2S_WS		4
+#define AR934X_GPIO_IN_MUX_I2S_MIC_SD		5
+#define AR934X_GPIO_IN_MUX_I2S_CLK		6
+#define AR934X_GPIO_IN_MUX_I2S_MCK		7
+#define AR934X_GPIO_IN_MUX_I2S_ETH_RX_ERR	8
+#define AR934X_GPIO_IN_MUX_I2S_ETH_RX_COL	9
+#define AR934X_GPIO_IN_MUX_I2S_ETH_RX_CRS	10
+
+#define QCA953X_GPIO_REG_OUT_FUNC0	0x2c
+#define QCA953X_GPIO_REG_OUT_FUNC1	0x30
+#define QCA953X_GPIO_REG_OUT_FUNC2	0x34
+#define QCA953X_GPIO_REG_OUT_FUNC3	0x38
+#define QCA953X_GPIO_REG_OUT_FUNC4	0x3c
+#define QCA953X_GPIO_REG_IN_ENABLE0	0x44
+#define QCA953X_GPIO_REG_FUNC		0x6c
+
+#define QCA953X_GPIO_OUT_MUX_SPI_CS1		10
+#define QCA953X_GPIO_OUT_MUX_SPI_CS2		11
+#define QCA953X_GPIO_OUT_MUX_SPI_CS0		9
+#define QCA953X_GPIO_OUT_MUX_SPI_CLK		8
+#define QCA953X_GPIO_OUT_MUX_SPI_MOSI		12
+#define QCA953X_GPIO_OUT_MUX_LED_LINK1		41
+#define QCA953X_GPIO_OUT_MUX_LED_LINK2		42
+#define QCA953X_GPIO_OUT_MUX_LED_LINK3		43
+#define QCA953X_GPIO_OUT_MUX_LED_LINK4		44
+#define QCA953X_GPIO_OUT_MUX_LED_LINK5		45
+
+#define QCA956X_GPIO_REG_OUT_FUNC0	0x2c
+#define QCA956X_GPIO_REG_OUT_FUNC1	0x30
+#define QCA956X_GPIO_REG_OUT_FUNC2	0x34
+#define QCA956X_GPIO_REG_OUT_FUNC3	0x38
+#define QCA956X_GPIO_REG_OUT_FUNC4	0x3c
+#define QCA956X_GPIO_REG_OUT_FUNC5	0x40
+#define QCA956X_GPIO_REG_IN_ENABLE0	0x44
+#define QCA956X_GPIO_REG_IN_ENABLE3	0x50
+#define QCA956X_GPIO_REG_FUNC		0x6c
+
+#define QCA956X_GPIO_OUT_MUX_GE0_MDO	32
+#define QCA956X_GPIO_OUT_MUX_GE0_MDC	33
+
 #define AR71XX_GPIO_COUNT		16
 #define AR724X_GPIO_COUNT		18
 #define AR913X_GPIO_COUNT		22
 #define AR933X_GPIO_COUNT		30
+#define AR934X_GPIO_COUNT		23
+#define QCA953X_GPIO_COUNT		18
+#define QCA955X_GPIO_COUNT		24
+#define QCA956X_GPIO_COUNT		23
+
+/*
+ * SRIF block
+ */
+#define AR934X_SRIF_CPU_DPLL1_REG	0x1c0
+#define AR934X_SRIF_CPU_DPLL2_REG	0x1c4
+#define AR934X_SRIF_CPU_DPLL3_REG	0x1c8
+
+#define AR934X_SRIF_DDR_DPLL1_REG	0x240
+#define AR934X_SRIF_DDR_DPLL2_REG	0x244
+#define AR934X_SRIF_DDR_DPLL3_REG	0x248
+
+#define AR934X_SRIF_DPLL1_REFDIV_SHIFT	27
+#define AR934X_SRIF_DPLL1_REFDIV_MASK	0x1f
+#define AR934X_SRIF_DPLL1_NINT_SHIFT	18
+#define AR934X_SRIF_DPLL1_NINT_MASK	0x1ff
+#define AR934X_SRIF_DPLL1_NFRAC_MASK	0x0003ffff
+
+#define AR934X_SRIF_DPLL2_LOCAL_PLL	BIT(30)
+#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT	13
+#define AR934X_SRIF_DPLL2_OUTDIV_MASK	0x7
+
+#define QCA953X_SRIF_CPU_DPLL1_REG	0x1c0
+#define QCA953X_SRIF_CPU_DPLL2_REG	0x1c4
+#define QCA953X_SRIF_CPU_DPLL3_REG	0x1c8
+
+#define QCA953X_SRIF_DDR_DPLL1_REG	0x240
+#define QCA953X_SRIF_DDR_DPLL2_REG	0x244
+#define QCA953X_SRIF_DDR_DPLL3_REG	0x248
+
+#define QCA953X_SRIF_DPLL1_REFDIV_SHIFT	27
+#define QCA953X_SRIF_DPLL1_REFDIV_MASK	0x1f
+#define QCA953X_SRIF_DPLL1_NINT_SHIFT	18
+#define QCA953X_SRIF_DPLL1_NINT_MASK	0x1ff
+#define QCA953X_SRIF_DPLL1_NFRAC_MASK	0x0003ffff
+
+#define QCA953X_SRIF_DPLL2_LOCAL_PLL	BIT(30)
+#define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT	13
+#define QCA953X_SRIF_DPLL2_OUTDIV_MASK	0x7
+
+#define AR71XX_GPIO_FUNC_STEREO_EN		BIT(17)
+#define AR71XX_GPIO_FUNC_SLIC_EN		BIT(16)
+#define AR71XX_GPIO_FUNC_SPI_CS2_EN		BIT(13)
+#define AR71XX_GPIO_FUNC_SPI_CS1_EN		BIT(12)
+#define AR71XX_GPIO_FUNC_UART_EN		BIT(8)
+#define AR71XX_GPIO_FUNC_USB_OC_EN		BIT(4)
+#define AR71XX_GPIO_FUNC_USB_CLK_EN		BIT(0)
+
+#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN		BIT(19)
+#define AR724X_GPIO_FUNC_SPI_EN			BIT(18)
+#define AR724X_GPIO_FUNC_SPI_CS_EN2		BIT(14)
+#define AR724X_GPIO_FUNC_SPI_CS_EN1		BIT(13)
+#define AR724X_GPIO_FUNC_CLK_OBS5_EN		BIT(12)
+#define AR724X_GPIO_FUNC_CLK_OBS4_EN		BIT(11)
+#define AR724X_GPIO_FUNC_CLK_OBS3_EN		BIT(10)
+#define AR724X_GPIO_FUNC_CLK_OBS2_EN		BIT(9)
+#define AR724X_GPIO_FUNC_CLK_OBS1_EN		BIT(8)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN	BIT(7)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN	BIT(6)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN	BIT(5)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN	BIT(4)
+#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN	BIT(3)
+#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN	BIT(2)
+#define AR724X_GPIO_FUNC_UART_EN		BIT(1)
+#define AR724X_GPIO_FUNC_JTAG_DISABLE		BIT(0)
+
+#define AR913X_GPIO_FUNC_WMAC_LED_EN		BIT(22)
+#define AR913X_GPIO_FUNC_EXP_PORT_CS_EN		BIT(21)
+#define AR913X_GPIO_FUNC_I2S_REFCLKEN		BIT(20)
+#define AR913X_GPIO_FUNC_I2S_MCKEN		BIT(19)
+#define AR913X_GPIO_FUNC_I2S1_EN		BIT(18)
+#define AR913X_GPIO_FUNC_I2S0_EN		BIT(17)
+#define AR913X_GPIO_FUNC_SLIC_EN		BIT(16)
+#define AR913X_GPIO_FUNC_UART_RTSCTS_EN		BIT(9)
+#define AR913X_GPIO_FUNC_UART_EN		BIT(8)
+#define AR913X_GPIO_FUNC_USB_CLK_EN		BIT(4)
+
+#define AR933X_GPIO_FUNC_SPDIF2TCK		BIT(31)
+#define AR933X_GPIO_FUNC_SPDIF_EN		BIT(30)
+#define AR933X_GPIO_FUNC_I2SO_22_18_EN		BIT(29)
+#define AR933X_GPIO_FUNC_I2S_MCK_EN		BIT(27)
+#define AR933X_GPIO_FUNC_I2SO_EN		BIT(26)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_DUPL	BIT(25)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_COLL	BIT(24)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED_ACT	BIT(23)
+#define AR933X_GPIO_FUNC_SPI_EN			BIT(18)
+#define AR933X_GPIO_FUNC_SPI_CS_EN2		BIT(14)
+#define AR933X_GPIO_FUNC_SPI_CS_EN1		BIT(13)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED4_EN	BIT(7)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED3_EN	BIT(6)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED2_EN	BIT(5)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED1_EN	BIT(4)
+#define AR933X_GPIO_FUNC_ETH_SWITCH_LED0_EN	BIT(3)
+#define AR933X_GPIO_FUNC_UART_RTS_CTS_EN	BIT(2)
+#define AR933X_GPIO_FUNC_UART_EN		BIT(1)
+#define AR933X_GPIO_FUNC_JTAG_DISABLE		BIT(0)
+
+#define AR934X_GPIO_FUNC_CLK_OBS7_EN		BIT(9)
+#define AR934X_GPIO_FUNC_CLK_OBS6_EN		BIT(8)
+#define AR934X_GPIO_FUNC_CLK_OBS5_EN		BIT(7)
+#define AR934X_GPIO_FUNC_CLK_OBS4_EN		BIT(6)
+#define AR934X_GPIO_FUNC_CLK_OBS3_EN		BIT(5)
+#define AR934X_GPIO_FUNC_CLK_OBS2_EN		BIT(4)
+#define AR934X_GPIO_FUNC_CLK_OBS1_EN		BIT(3)
+#define AR934X_GPIO_FUNC_CLK_OBS0_EN		BIT(2)
+#define AR934X_GPIO_FUNC_JTAG_DISABLE		BIT(1)
+
+#define AR934X_GPIO_OUT_GPIO		0x00
+
+/*
+ * MII_CTRL block
+ */
+#define AR71XX_MII_REG_MII0_CTRL	0x00
+#define AR71XX_MII_REG_MII1_CTRL	0x04
+
+#define AR71XX_MII_CTRL_IF_MASK		3
+#define AR71XX_MII_CTRL_SPEED_SHIFT	4
+#define AR71XX_MII_CTRL_SPEED_MASK	3
+#define AR71XX_MII_CTRL_SPEED_10	0
+#define AR71XX_MII_CTRL_SPEED_100	1
+#define AR71XX_MII_CTRL_SPEED_1000	2
+
+#define AR71XX_MII0_CTRL_IF_GMII	0
+#define AR71XX_MII0_CTRL_IF_MII		1
+#define AR71XX_MII0_CTRL_IF_RGMII	2
+#define AR71XX_MII0_CTRL_IF_RMII	3
+
+#define AR71XX_MII1_CTRL_IF_RGMII	0
+#define AR71XX_MII1_CTRL_IF_RMII	1
+
+/*
+ * AR933X GMAC interface
+ */
+#define AR933X_GMAC_REG_ETH_CFG		0x00
+
+#define AR933X_ETH_CFG_RGMII_GE0	BIT(0)
+#define AR933X_ETH_CFG_MII_GE0		BIT(1)
+#define AR933X_ETH_CFG_GMII_GE0		BIT(2)
+#define AR933X_ETH_CFG_MII_GE0_MASTER	BIT(3)
+#define AR933X_ETH_CFG_MII_GE0_SLAVE	BIT(4)
+#define AR933X_ETH_CFG_MII_GE0_ERR_EN	BIT(5)
+#define AR933X_ETH_CFG_SW_PHY_SWAP	BIT(7)
+#define AR933X_ETH_CFG_SW_PHY_ADDR_SWAP	BIT(8)
+#define AR933X_ETH_CFG_RMII_GE0		BIT(9)
+#define AR933X_ETH_CFG_RMII_GE0_SPD_10	0
+#define AR933X_ETH_CFG_RMII_GE0_SPD_100	BIT(10)
+
+/*
+ * AR934X GMAC Interface
+ */
+#define AR934X_GMAC_REG_ETH_CFG		0x00
+
+#define AR934X_ETH_CFG_RGMII_GMAC0	BIT(0)
+#define AR934X_ETH_CFG_MII_GMAC0	BIT(1)
+#define AR934X_ETH_CFG_GMII_GMAC0	BIT(2)
+#define AR934X_ETH_CFG_MII_GMAC0_MASTER	BIT(3)
+#define AR934X_ETH_CFG_MII_GMAC0_SLAVE	BIT(4)
+#define AR934X_ETH_CFG_MII_GMAC0_ERR_EN	BIT(5)
+#define AR934X_ETH_CFG_SW_ONLY_MODE	BIT(6)
+#define AR934X_ETH_CFG_SW_PHY_SWAP	BIT(7)
+#define AR934X_ETH_CFG_SW_APB_ACCESS	BIT(9)
+#define AR934X_ETH_CFG_RMII_GMAC0	BIT(10)
+#define AR934X_ETH_CFG_MII_CNTL_SPEED	BIT(11)
+#define AR934X_ETH_CFG_RMII_GMAC0_MASTER BIT(12)
+#define AR934X_ETH_CFG_SW_ACC_MSB_FIRST	BIT(13)
+
+/*
+ * QCA953X GMAC Interface
+ */
+#define QCA953X_GMAC_REG_ETH_CFG		0x00
+
+#define QCA953X_ETH_CFG_SW_ONLY_MODE		BIT(6)
+#define QCA953X_ETH_CFG_SW_PHY_SWAP		BIT(7)
+#define QCA953X_ETH_CFG_SW_APB_ACCESS		BIT(9)
+#define QCA953X_ETH_CFG_SW_ACC_MSB_FIRST	BIT(13)
+
+/*
+ * QCA955X GMAC Interface
+ */
+
+#define QCA955X_GMAC_REG_ETH_CFG	0x00
+
+#define QCA955X_ETH_CFG_RGMII_GMAC0	BIT(0)
+#define QCA955X_ETH_CFG_SGMII_GMAC0	BIT(6)
+
+/*
+ * DPLL block
+ */
+
+#define AR934X_DPLL_REG_1		0x00
+#define AR934X_DPLL_REG_2		0x04
+
+#define AR934X_DPLL_2_RANGE		BIT(31)
+#define AR934X_DPLL_2_KI_SHIFT		26
+#define AR934X_DPLL_2_KI_MASK		0xf
+#define AR934X_DPLL_2_KD_SHIFT		19
+#define AR934X_DPLL_2_KD_MASK		0x7f
+
+#define AR934X_DPLL_REG_3		0x08
+
+#define AR934X_DPLL_3_DO_MEAS		BIT(30)
+#define AR934X_DPLL_3_PHASESH_SHIFT	23
+#define AR934X_DPLL_3_PHASESH_MASK	0x7f
+#define AR934X_DPLL_3_SQSUM_DVC_SHIFT	3
+#define AR934X_DPLL_3_SQSUM_DVC_MASK	0xfffff
+
+#define AR934X_DPLL_REG_4		0x0c
+
+#define AR934X_DPLL_4_MEAS_DONE		BIT(3)
+
+
+/*
+ * DMA block (MBOX/PCM)
+ */
+#define AR934X_DMA_REG_MBOX_FIFO			0x00
+#define AR934X_DMA_REG_MBOX_FIFO_STATUS			0x08
+#define AR934X_DMA_REG_SLIC_MBOX_FIFO_STATUS		0x0c
+#define AR934X_DMA_REG_MBOX_DMA_POLICY			0x10
+
+#define AR934X_DMA_MBOX_DMA_POLICY_TX_FIFO_THRESH_SHIFT	4
+#define AR934X_DMA_MBOX_DMA_POLICY_TX_FIFO_THRESH_MASK	0xf
+#define AR934X_DMA_MBOX_DMA_POLICY_TX_QUANTUM		BIT(3)
+#define AR934X_DMA_MBOX_DMA_POLICY_RX_QUANTUM		BIT(1)
+
+#define AR934X_DMA_REG_SLIC_MBOX_DMA_POLICY		0x14
+#define AR934X_DMA_REG_MBOX0_DMA_RX_DESCRIPTOR_BASE	0x18
+#define AR934X_DMA_REG_MBOX0_DMA_RX_CONTROL		0x1c
+#define AR934X_DMA_REG_MBOX0_DMA_TX_DESCRIPTOR_BASE	0x20
+#define AR934X_DMA_REG_MBOX0_DMA_TX_CONTROL		0x24
+#define AR934X_DMA_REG_MBOX1_DMA_RX_DESCRIPTOR_BASE	0x28
+#define AR934X_DMA_REG_MBOX1_DMA_RX_CONTROL		0x2c
+#define AR934X_DMA_REG_MBOX1_DMA_TX_DESCRIPTOR_BASE	0x30
+#define AR934X_DMA_REG_MBOX1_DMA_TX_CONTROL		0x34
+
+#define AR934X_DMA_MBOX_DMA_CONTROL_RESUME		BIT(2)
+#define AR934X_DMA_MBOX_DMA_CONTROL_START		BIT(1)
+#define AR934X_DMA_MBOX_DMA_CONTROL_STOP		BIT(0)
+
+#define AR934X_DMA_REG_MBOX_FRAME			0x38
+#define AR934X_DMA_REG_SLIC_MBOX_FRAME			0x3c
+#define AR934X_DMA_REG_FIFO_TIMEOUT			0x40
+#define AR934X_DMA_REG_MBOX_INT_STATUS			0x44
+#define AR934X_DMA_REG_SLIC_MBOX_INT_STATUS		0x48
+
+#define AR934X_DMA_MBOX_INT_STATUS_RX_DMA_COMPLETE	BIT(10)
+#define AR934X_DMA_MBOX_INT_STATUS_TX_DMA_COMPLETE	BIT(6)
+
+#define AR934X_DMA_REG_MBOX_INT_ENABLE			0x4c
+#define AR934X_DMA_REG_SLIC_MBOX_INT_ENABLE		0x50
+
+#define AR934X_DMA_MBOX1_INT_RX_COMPLETE		BIT(11)
+#define AR934X_DMA_MBOX0_INT_RX_COMPLETE		BIT(10)
+#define AR934X_DMA_MBOX1_INT_TX_EOM_COMPLETE		BIT(9)
+#define AR934X_DMA_MBOX0_INT_TX_EOM_COMPLETE		BIT(8)
+#define AR934X_DMA_MBOX1_INT_TX_COMPLETE		BIT(7)
+#define AR934X_DMA_MBOX0_INT_TX_COMPLETE		BIT(6)
+
+#define AR934X_DMA_REG_MBOX_FIFO_RESET			0x58
+#define AR934X_DMA_REG_SLIC_MBOX_FIFO_RESET		0x5c
+
+#define AR934X_DMA_MBOX_FIFO_RESET_ALL			0xff
+#define AR934X_DMA_MBOX1_FIFO_RESET_RX			BIT(3)
+#define AR934X_DMA_MBOX0_FIFO_RESET_RX			BIT(2)
+#define AR934X_DMA_MBOX1_FIFO_RESET_TX			BIT(1)
+#define AR934X_DMA_MBOX0_FIFO_RESET_TX			BIT(0)
+
+/*
+ * STEREO block
+ */
+#define	AR934X_STEREO_REG_CONFIG			0x00
+
+#define	AR934X_STEREO_CONFIG_SPDIF_ENABLE		BIT(23)
+#define AR934X_STEREO_CONFIG_I2S_ENABLE			BIT(21)
+#define AR934X_STEREO_CONFIG_MIC_RESET			BIT(20)
+#define AR934X_STEREO_CONFIG_RESET			BIT(19)
+#define AR934X_STEREO_CONFIG_I2S_DELAY			BIT(18)
+#define AR934X_STEREO_CONFIG_PCM_SWAP			BIT(17)
+#define AR934X_STEREO_CONFIG_MIC_WORD_SIZE		BIT(16)
+#define AR934X_STEREO_CONFIG_STEREO_MONO_SHIFT		14
+#define AR934X_STEREO_CONFIG_STEREO_MONO_MASK		0x03
+#define AR934X_STEREO_CONFIG_STEREO_MONO_STEREO		0
+#define AR934X_STEREO_CONFIG_STEREO_MONO_CH0		1
+#define AR934X_STEREO_CONFIG_STEREO_MONO_CH1		2
+
+#define AR934X_STEREO_CONFIG_DATA_WORD_SIZE_SHIFT	12
+#define AR934X_STEREO_CONFIG_DATA_WORD_SIZE_MASK	0x03
+#define AR934X_STEREO_CONFIG_DATA_WORD_8		0
+#define AR934X_STEREO_CONFIG_DATA_WORD_16		1
+#define AR934X_STEREO_CONFIG_DATA_WORD_24		2
+#define AR934X_STEREO_CONFIG_DATA_WORD_32		3
+
+#define AR934X_STEREO_CONFIG_I2S_WORD_SIZE		BIT(11)
+#define AR934X_STEREO_CONFIG_MCK_SEL			BIT(10)
+#define AR934X_STEREO_CONFIG_SAMPLE_CNT_CLEAR_TYPE	BIT(9)
+#define AR934X_STEREO_CONFIG_MASTER			BIT(8)
+#define AR934X_STEREO_CONFIG_POSEDGE_SHIFT		0
+#define AR934X_STEREO_CONFIG_POSEDGE_MASK		0xff
+
+#define	AR934X_STEREO_REG_VOLUME			0x04
+
+#define AR934X_STEREO_VOLUME_CH0			8
+#define AR934X_STEREO_VOLUME_CH1			0
+#define AR934X_STEREO_VOLUME_MASK			0x1f
+
+#define	AR934X_STEREO_REG_MASTER_CLOCK			0x08
+#define	AR934X_STEREO_REG_TX_SAMPLE_CNT_LSB		0x0c
+#define	AR934X_STEREO_REG_TX_SAMPLE_CNT_MSB		0x10
+#define	AR934X_STEREO_REG_RX_SAMPLE_CNT_LSB		0x14
+#define	AR934X_STEREO_REG_RX_SAMPLE_CNT_MSB 		0x18
+
+/*
+ * NAND controller
+ */
+#define AR934X_NAND_REG_COMMAND          0x00
+#define AR934X_NAND_REG_CTRL             0x04
+#define AR934X_NAND_REG_STATUS           0x08
+#define AR934X_NAND_REG_INT_MASK         0x0c
+#define AR934X_NAND_REG_INT_STATUS       0x10
+#define AR934X_NAND_REG_ECC_CTRL         0x14
+#define AR934X_NAND_REG_ECC_OFFSET       0x18
+#define AR934X_NAND_REG_ADDR0_0          0x1c
+#define AR934X_NAND_REG_ADDR1_0          0x20
+#define AR934X_NAND_REG_ADDR0_1          0x24
+#define AR934X_NAND_REG_ADDR1_1          0x28
+#define AR934X_NAND_REG_SPARE_SIZE       0x30
+#define AR934X_NAND_REG_PROTECT          0x38
+#define AR934X_NAND_REG_LOOKUP_EN        0x40
+#define AR934X_NAND_REG_LOOKUP0          0x44
+#define AR934X_NAND_REG_LOOKUP1          0x48
+#define AR934X_NAND_REG_LOOKUP2          0x4c
+#define AR934X_NAND_REG_LOOKUP3          0x50
+#define AR934X_NAND_REG_LOOKUP4          0x54
+#define AR934X_NAND_REG_LOOKUP5          0x58
+#define AR934X_NAND_REG_LOOKUP6          0x5c
+#define AR934X_NAND_REG_LOOKUP7          0x60
+#define AR934X_NAND_REG_DMA_ADDR         0x64
+#define AR934X_NAND_REG_DMA_COUNT        0x68
+#define AR934X_NAND_REG_DMA_CTRL         0x6c
+#define AR934X_NAND_REG_MEM_CTRL         0x80
+#define AR934X_NAND_REG_PG_SIZE          0x84
+#define AR934X_NAND_REG_RD_STATUS        0x88
+#define AR934X_NAND_REG_TIME_SEQ         0x8c
+#define AR934X_NAND_REG_TIMINGS_ASYN     0x90
+#define AR934X_NAND_REG_TIMINGS_SYN      0x94
+#define AR934X_NAND_REG_FIFO_DATA        0x98
+#define AR934X_NAND_REG_TIME_MODE        0x9c
+#define AR934X_NAND_REG_DMA_ADDR_OFFSET  0xa0
+#define AR934X_NAND_REG_DMA_ADDR_OFFSET  0xa0
+#define AR934X_NAND_REG_FIFO_INIT        0xb0
+#define AR934X_NAND_REG_GENERIC_SEQ_CTRL 0xb4
+
+#define AR934X_NAND_DMA_DESCR_SIZE		8
+
+#define AR934X_NAND_TIMING_ASYN_SETTING		0x11
+#define AR934X_NAND_TIME_SEQ_SETTING		0x7fff
+#define AR934X_NAND_CTRL_CUSTOM_SIZE_EN		BIT(11)
+
+#define AR934X_NAND_CTRL_PAGE_SIZE_256		(0 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_512		BIT(8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_1024		(2 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_2048		(3 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_4096		(4 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_8192		(5 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_16384	(6 <<  8)
+#define AR934X_NAND_CTRL_PAGE_SIZE_0		(7 <<  8)
+
+#define AR934X_NAND_CTRL_BLOCK_SIZE_32		(0 <<  6)
+#define AR934X_NAND_CTRL_BLOCK_SIZE_64		BIT(6)
+#define AR934X_NAND_CTRL_BLOCK_SIZE_128		(2 <<  6)
+#define AR934X_NAND_CTRL_BLOCK_SIZE_256		(3 <<  6)
+
+#define AR934X_NAND_CTRL_ECC_EN			BIT(5)
+#define AR934X_NAND_CTRL_INT_EN			BIT(4)
+#define AR934X_NAND_CTRL_SPARE_EN		BIT(3)
+
+#define AR934X_NAND_CTRL_ADDR_CYCLE0(c)		((c) << 0)
+
+#define AR934X_NAND_DMA_CTRL_DMA_START		BIT(7)
+#define AR934X_NAND_DMA_CTRL_DMA_DIR_WRITE	(0 << 6)
+#define AR934X_NAND_DMA_CTRL_DMA_DIR_READ	BIT(6)
+#define AR934X_NAND_DMA_CTRL_DMA_MODE_SG	BIT(5)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_0	(0 << 2)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_1	BIT(2)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_2	(2 << 2)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_3	(3 << 2)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_4	(4 << 2)
+#define AR934X_NAND_DMA_CTRL_DMA_BURST_5	(5 << 2)
+#define AR934X_NAND_DMA_CTRL_ERR_FLAG		BIT(1)
+#define AR934X_NAND_DMA_CTRL_DMA_READY		BIT(0)
+
+#define AR934X_NAND_ECC_CTRL_ERR_THRESH(x)	(((x) << 8) & (0x1fu << 8))
+#define AR934X_NAND_ECC_CTRL_ECC_CAP(x)		(((x) << 5) & (0x07u << 5))
+#define AR934X_NAND_ECC_CTRL_ECC_2_BITS		AR934X_NAND_ECC_CTRL_ECC_CAP(0)
+#define AR934X_NAND_ECC_CTRL_ECC_4_BITS		AR934X_NAND_ECC_CTRL_ECC_CAP(1)
+#define AR934X_NAND_ECC_CTRL_ECC_6_BITS		AR934X_NAND_ECC_CTRL_ECC_CAP(2)
+#define AR934X_NAND_ECC_CTRL_ECC_8_BITS		AR934X_NAND_ECC_CTRL_ECC_CAP(3)
+#define AR934X_NAND_ECC_CTRL_ECC_10_BITS	AR934X_NAND_ECC_CTRL_ECC_CAP(4)
+#define AR934X_NAND_ECC_CTRL_ECC_12_BITS	AR934X_NAND_ECC_CTRL_ECC_CAP(5)
+#define AR934X_NAND_ECC_CTRL_ECC_14_BITS	AR934X_NAND_ECC_CTRL_ECC_CAP(6)
+#define AR934X_NAND_ECC_CTRL_ECC_16_BITS	AR934X_NAND_ECC_CTRL_ECC_CAP(7)
+#define AR934X_NAND_ECC_CORR_BITS(x)		(AR934X_NAND_ECC_CTRL_ERR_THRESH(x) | AR934X_NAND_ECC_CTRL_ECC_CAP(((x) / 2) - 1))
+#define AR934X_NAND_ECC_CTRL_ERR_OVER		BIT(2)
+#define AR934X_NAND_ECC_CTRL_ERR_UNCORR		BIT(1)
+#define AR934X_NAND_ECC_CTRL_ERR_CORR		BIT(0)
+#define AR934X_NAND_ECC_ERROR			(AR934X_NAND_ECC_CTRL_ERR_UNCORR | AR934X_NAND_ECC_CTRL_ERR_OVER)
+
+#define AR934X_NAND_CMD_END_INT		BIT(1)
 
 #endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
index 6d0c6c9..861c74a 100644
--- a/arch/mips/include/asm/mach-ath79/ath79.h
+++ b/arch/mips/include/asm/mach-ath79/ath79.h
@@ -1,6 +1,7 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X common definitions
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
@@ -29,6 +30,12 @@
 	ATH79_SOC_AR9132,
 	ATH79_SOC_AR9330,
 	ATH79_SOC_AR9331,
+	ATH79_SOC_AR9341,
+	ATH79_SOC_AR9342,
+	ATH79_SOC_AR9344,
+	ATH79_SOC_QCA9531,
+	ATH79_SOC_QCA9558,
+	ATH79_SOC_QCA956X,
 };
 
 extern enum ath79_soc_type ath79_soc;
@@ -75,9 +82,68 @@
 		ath79_soc == ATH79_SOC_AR9331);
 }
 
+static inline int soc_is_ar9341(void)
+{
+	return (ath79_soc == ATH79_SOC_AR9341);
+}
+
+static inline int soc_is_ar9342(void)
+{
+	return (ath79_soc == ATH79_SOC_AR9342);
+}
+
+static inline int soc_is_ar9344(void)
+{
+	return (ath79_soc == ATH79_SOC_AR9344);
+}
+
+static inline int soc_is_qca9531(void)
+{
+	return ath79_soc == ATH79_SOC_QCA9531;
+}
+
+static inline int soc_is_qca953x(void)
+{
+	return soc_is_qca9531();
+}
+
+static inline int soc_is_ar934x(void)
+{
+	return soc_is_ar9341() || soc_is_ar9342() || soc_is_ar9344();
+}
+
+static inline int soc_is_qca9558(void)
+{
+	return ath79_soc == ATH79_SOC_QCA9558;
+}
+
+static inline int soc_is_qca955x(void)
+{
+	return soc_is_qca9558();
+}
+
+static inline int soc_is_qca9561(void)
+{
+	return ath79_soc == ATH79_SOC_QCA956X;
+}
+
+static inline int soc_is_qca9563(void)
+{
+	return ath79_soc == ATH79_SOC_QCA956X;
+}
+
+static inline int soc_is_qca956x(void)
+{
+	return soc_is_qca9563();
+}
+
 extern void __iomem *ath79_ddr_base;
+extern void __iomem *ath79_gpio_base;
 extern void __iomem *ath79_pll_base;
 extern void __iomem *ath79_reset_base;
+extern void __iomem *ath79_dma_base;
+extern void __iomem *ath79_stereo_base;
+extern void __iomem *ath79_audio_dpll_base;
 
 static inline void ath79_pll_wr(unsigned reg, u32 val)
 {
@@ -101,5 +167,39 @@
 
 void ath79_device_reset_set(u32 mask);
 void ath79_device_reset_clear(u32 mask);
+u32 ath79_device_reset_get(u32 mask);
+
+static inline void ath79_dma_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_dma_base + reg);
+}
+
+static inline u32 ath79_dma_rr(unsigned reg)
+{
+	return __raw_readl(ath79_dma_base + reg);
+}
+
+static inline void ath79_stereo_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_stereo_base + reg);
+}
+
+static inline u32 ath79_stereo_rr(unsigned reg)
+{
+	return __raw_readl(ath79_stereo_base + reg);
+}
+
+static inline void ath79_audio_dpll_wr(unsigned reg, u32 val)
+{
+	__raw_writel(val, ath79_audio_dpll_base + reg);
+}
+
+static inline u32 ath79_audio_dpll_rr(unsigned reg)
+{
+	return __raw_readl(ath79_audio_dpll_base + reg);
+}
+
+void ath79_flash_acquire(void);
+void ath79_flash_release(void);
 
 #endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
index aa2283e..424f062 100644
--- a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
+++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
@@ -1,6 +1,7 @@
 /*
  *  Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -14,10 +15,18 @@
 struct ath79_spi_platform_data {
 	unsigned	bus_num;
 	unsigned	num_chipselect;
+	unsigned	miso_line;
+};
+
+enum ath79_spi_cs_type {
+	ATH79_SPI_CS_TYPE_INTERNAL,
+	ATH79_SPI_CS_TYPE_GPIO,
 };
 
 struct ath79_spi_controller_data {
-	unsigned	gpio;
+	enum ath79_spi_cs_type cs_type;
+	unsigned cs_line;
+	bool is_flash;
 };
 
 #endif /* _ATH79_SPI_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
index 4476fa0..17871db 100644
--- a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
@@ -1,6 +1,7 @@
 /*
  *  Atheros AR71XX/AR724X/AR913X specific CPU feature overrides
  *
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
@@ -16,41 +17,41 @@
 #ifndef __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
 
-#define cpu_has_tlb		1
-#define cpu_has_4kex		1
-#define cpu_has_3k_cache	0
-#define cpu_has_4k_cache	1
-#define cpu_has_tx39_cache	0
-#define cpu_has_sb1_cache	0
-#define cpu_has_fpu		0
-#define cpu_has_32fpr		0
-#define cpu_has_counter		1
-#define cpu_has_watch		1
-#define cpu_has_divec		1
+#define cpu_has_tlb			1
+#define cpu_has_4kex			1
+#define cpu_has_3k_cache		0
+#define cpu_has_4k_cache		1
+#define cpu_has_tx39_cache		0
+#define cpu_has_sb1_cache		0
+#define cpu_has_inclusive_pcaches	0
+#define cpu_has_fpu			0
+#define cpu_has_32fpr			0
+#define cpu_has_counter			1
+#define cpu_has_watch			1
+#define cpu_has_divec			1
 
-#define cpu_has_prefetch	1
-#define cpu_has_ejtag		1
-#define cpu_has_llsc		1
+#define cpu_has_prefetch		1
+#define cpu_has_ejtag			1
+#define cpu_has_llsc			1
 
-#define cpu_has_mips16		1
-#define cpu_has_mdmx		0
-#define cpu_has_mips3d		0
-#define cpu_has_smartmips	0
+#define cpu_has_mips16			1
+#define cpu_has_mdmx			0
+#define cpu_has_mips3d			0
+#define cpu_has_smartmips		0
 
-#define cpu_has_mips32r1	1
-#define cpu_has_mips32r2	1
-#define cpu_has_mips64r1	0
-#define cpu_has_mips64r2	0
+#define cpu_has_mips32r1		1
+#define cpu_has_mips32r2		1
+#define cpu_has_mips64r1		0
+#define cpu_has_mips64r2		0
 
-#define cpu_has_dsp		0
-#define cpu_has_mipsmt		0
+#define cpu_has_mipsmt			0
 
-#define cpu_has_64bits		0
-#define cpu_has_64bit_zero_reg	0
-#define cpu_has_64bit_gp_regs	0
-#define cpu_has_64bit_addresses	0
+#define cpu_has_64bits			0
+#define cpu_has_64bit_zero_reg		0
+#define cpu_has_64bit_gp_regs		0
+#define cpu_has_64bit_addresses		0
 
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
+#define cpu_dcache_line_size()		32
+#define cpu_icache_line_size()		32
 
 #endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h
index 519958f..be87b54 100644
--- a/arch/mips/include/asm/mach-ath79/irq.h
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -1,4 +1,5 @@
 /*
+ *  Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
@@ -10,13 +11,31 @@
 #define __ASM_MACH_ATH79_IRQ_H
 
 #define MIPS_CPU_IRQ_BASE	0
-#define NR_IRQS			40
+#define NR_IRQS			83
 
 #define ATH79_MISC_IRQ_BASE	8
 #define ATH79_MISC_IRQ_COUNT	32
+#define ATH79_MISC_IRQ(_x)	(ATH79_MISC_IRQ_BASE + (_x))
+
+#define ATH79_PCI_IRQ_BASE	(ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT)
+#define ATH79_PCI_IRQ_COUNT	6
+#define ATH79_PCI_IRQ(_x)	(ATH79_PCI_IRQ_BASE + (_x))
+
+#define ATH79_IP2_IRQ_BASE	(ATH79_PCI_IRQ_BASE + ATH79_PCI_IRQ_COUNT)
+#define ATH79_IP2_IRQ_COUNT	2
+#define ATH79_IP2_IRQ(_x)	(ATH79_IP2_IRQ_BASE + (_x))
+
+#define ATH79_IP3_IRQ_BASE	(ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT)
+#define ATH79_IP3_IRQ_COUNT     3
+#define ATH79_IP3_IRQ(_x)       (ATH79_IP3_IRQ_BASE + (_x))
+
+#define ATH79_GPIO_IRQ_BASE	(ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT)
+#define ATH79_GPIO_IRQ_COUNT	32
+#define ATH79_GPIO_IRQ(_x)	(ATH79_GPIO_IRQ_BASE + (_x))
 
 #define ATH79_CPU_IRQ_IP2	(MIPS_CPU_IRQ_BASE + 2)
-#define ATH79_CPU_IRQ_USB	(MIPS_CPU_IRQ_BASE + 3)
+#define ATH79_CPU_IRQ_IP3	(MIPS_CPU_IRQ_BASE + 3)
+#define ATH79_CPU_IRQ_USB	ATH79_CPU_IRQ_IP3
 #define ATH79_CPU_IRQ_GE0	(MIPS_CPU_IRQ_BASE + 4)
 #define ATH79_CPU_IRQ_GE1	(MIPS_CPU_IRQ_BASE + 5)
 #define ATH79_CPU_IRQ_MISC	(MIPS_CPU_IRQ_BASE + 6)
diff --git a/arch/mips/include/asm/mach-ath79/mangle-port.h b/arch/mips/include/asm/mach-ath79/mangle-port.h
new file mode 100644
index 0000000..ffd4e20
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/mangle-port.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h
+ *      Copyright (C) 2003, 2004 Ralf Baechle
+ *
+ *  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.
+ */
+
+#ifndef __ASM_MACH_ATH79_MANGLE_PORT_H
+#define __ASM_MACH_ATH79_MANGLE_PORT_H
+
+#ifdef CONFIG_PCI
+extern unsigned long (ath79_pci_swizzle_b)(unsigned long port);
+extern unsigned long (ath79_pci_swizzle_w)(unsigned long port);
+#else
+#define ath79_pci_swizzle_b(port) (port)
+#define ath79_pci_swizzle_w(port) (port)
+#endif
+
+#define __swizzle_addr_b(port)	ath79_pci_swizzle_b(port)
+#define __swizzle_addr_w(port)	ath79_pci_swizzle_w(port)
+#define __swizzle_addr_l(port)	(port)
+#define __swizzle_addr_q(port)	(port)
+
+# define ioswabb(a, x)           (x)
+# define __mem_ioswabb(a, x)     (x)
+# define ioswabw(a, x)           (x)
+# define __mem_ioswabw(a, x)     cpu_to_le16(x)
+# define ioswabl(a, x)           (x)
+# define __mem_ioswabl(a, x)     cpu_to_le32(x)
+# define ioswabq(a, x)           (x)
+# define __mem_ioswabq(a, x)     cpu_to_le64(x)
+
+#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */
diff --git a/arch/mips/include/asm/mach-ath79/pci-ath724x.h b/arch/mips/include/asm/mach-ath79/pci-ath724x.h
deleted file mode 100644
index 454885f..0000000
--- a/arch/mips/include/asm/mach-ath79/pci-ath724x.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  Atheros 724x PCI support
- *
- *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
- *
- *  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.
- */
-
-#ifndef __ASM_MACH_ATH79_PCI_ATH724X_H
-#define __ASM_MACH_ATH79_PCI_ATH724X_H
-
-struct ath724x_pci_data {
-	int irq;
-	void *pdata;
-};
-
-void ath724x_pci_add_data(struct ath724x_pci_data *data, int size);
-
-#endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 54ea47d..d48e127 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -417,16 +417,48 @@
 						    unsigned long end)	\
 {									\
 	unsigned long lsize = cpu_##desc##_line_size();			\
+	unsigned long lsize_2 = lsize * 2;				\
+	unsigned long lsize_3 = lsize * 3;				\
+	unsigned long lsize_4 = lsize * 4;				\
+	unsigned long lsize_5 = lsize * 5;				\
+	unsigned long lsize_6 = lsize * 6;				\
+	unsigned long lsize_7 = lsize * 7;				\
+	unsigned long lsize_8 = lsize * 8;				\
 	unsigned long addr = start & ~(lsize - 1);			\
-	unsigned long aend = (end - 1) & ~(lsize - 1);			\
+	unsigned long aend = (end + lsize - 1) & ~(lsize - 1);		\
+	int lines = (aend - addr) / lsize;				\
 									\
 	__##pfx##flush_prologue						\
 									\
-	while (1) {							\
+	while (lines >= 8) {						\
 		prot##cache_op(hitop, addr);				\
-		if (addr == aend)					\
-			break;						\
-		addr += lsize;						\
+		prot##cache_op(hitop, addr + lsize);			\
+		prot##cache_op(hitop, addr + lsize_2);			\
+		prot##cache_op(hitop, addr + lsize_3);			\
+		prot##cache_op(hitop, addr + lsize_4);			\
+		prot##cache_op(hitop, addr + lsize_5);			\
+		prot##cache_op(hitop, addr + lsize_6);			\
+		prot##cache_op(hitop, addr + lsize_7);			\
+		addr += lsize_8;					\
+		lines -= 8;						\
+	}								\
+									\
+	if (lines & 0x4) {						\
+		prot##cache_op(hitop, addr);				\
+		prot##cache_op(hitop, addr + lsize);			\
+		prot##cache_op(hitop, addr + lsize_2);			\
+		prot##cache_op(hitop, addr + lsize_3);			\
+		addr += lsize_4;					\
+	}								\
+									\
+	if (lines & 0x2) {						\
+		prot##cache_op(hitop, addr);				\
+		prot##cache_op(hitop, addr + lsize);			\
+		addr += lsize_2;					\
+	}								\
+									\
+	if (lines & 0x1) {						\
+		prot##cache_op(hitop, addr);				\
 	}								\
 									\
 	__##pfx##flush_epilogue						\
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8bec715..29268c2 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -9,6 +9,7 @@
  * Copyright (C) 1996 Stoned Elipot
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2000, 2001, 2002, 2007  Maciej W. Rozycki
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  */
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -35,6 +36,8 @@
 #include <asm/system.h>
 #include <asm/prom.h>
 
+#include <linux/of_fdt.h>
+
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
@@ -467,6 +470,24 @@
 }
 early_param("mem", early_parse_mem);
 
+static int __init fdt_early(char *p)
+{
+	unsigned long fdtp = memparse(p, &p);
+	struct boot_param_header *devtree = (void *)fdtp;
+
+	printk("fdt addr: %p\n", devtree);
+
+	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
+		printk("not a devtree @ %p\n", devtree);
+		return 0;
+	}
+
+	initial_boot_params = (void *)devtree;
+
+	return 0;
+}
+early_param("fdt", fdt_early);
+
 static void __init arch_mem_init(char **cmdline_p)
 {
 	phys_t init_mem, init_end, init_size;
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index c3ac4b0..43c5138 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -19,7 +19,8 @@
 obj-$(CONFIG_BCM63XX)		+= pci-bcm63xx.o fixup-bcm63xx.o \
 					ops-bcm63xx.o
 obj-$(CONFIG_MIPS_ALCHEMY)	+= pci-alchemy.o
-obj-$(CONFIG_SOC_AR724X)	+= pci-ath724x.o
+obj-$(CONFIG_SOC_AR71XX)	+= pci-ar71xx.o
+obj-$(CONFIG_PCI_AR724X)	+= pci-ar724x.o
 
 #
 # These are still pretty much in the old state, watch, go blind.
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
new file mode 100644
index 0000000..03d36e3
--- /dev/null
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -0,0 +1,405 @@
+/*
+ *  Atheros AR71xx PCI host controller driver
+ *
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ *  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.
+ */
+
+#include <linux/resource.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <asm/mach-ath79/ar71xx_regs.h>
+#include <asm/mach-ath79/ath79.h>
+
+#define AR71XX_PCI_REG_CRP_AD_CBE	0x00
+#define AR71XX_PCI_REG_CRP_WRDATA	0x04
+#define AR71XX_PCI_REG_CRP_RDDATA	0x08
+#define AR71XX_PCI_REG_CFG_AD		0x0c
+#define AR71XX_PCI_REG_CFG_CBE		0x10
+#define AR71XX_PCI_REG_CFG_WRDATA	0x14
+#define AR71XX_PCI_REG_CFG_RDDATA	0x18
+#define AR71XX_PCI_REG_PCI_ERR		0x1c
+#define AR71XX_PCI_REG_PCI_ERR_ADDR	0x20
+#define AR71XX_PCI_REG_AHB_ERR		0x24
+#define AR71XX_PCI_REG_AHB_ERR_ADDR	0x28
+
+#define AR71XX_PCI_CRP_CMD_WRITE	0x00010000
+#define AR71XX_PCI_CRP_CMD_READ		0x00000000
+#define AR71XX_PCI_CFG_CMD_READ		0x0000000a
+#define AR71XX_PCI_CFG_CMD_WRITE	0x0000000b
+
+#define AR71XX_PCI_INT_CORE		BIT(4)
+#define AR71XX_PCI_INT_DEV2		BIT(2)
+#define AR71XX_PCI_INT_DEV1		BIT(1)
+#define AR71XX_PCI_INT_DEV0		BIT(0)
+
+#define AR71XX_PCI_IRQ_COUNT		5
+
+struct ar71xx_pci_controller {
+	void __iomem *cfg_base;
+	spinlock_t lock;
+	int irq;
+	struct pci_controller pci_ctrl;
+	struct resource io_res;
+	struct resource mem_res;
+};
+
+/* Byte lane enable bits */
+static const u8 ar71xx_pci_ble_table[4][4] = {
+	{0x0, 0xf, 0xf, 0xf},
+	{0xe, 0xd, 0xb, 0x7},
+	{0xc, 0xf, 0x3, 0xf},
+	{0xf, 0xf, 0xf, 0xf},
+};
+
+static const u32 ar71xx_pci_read_mask[8] = {
+	0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0
+};
+
+static inline u32 ar71xx_pci_get_ble(int where, int size, int local)
+{
+	u32 t;
+
+	t = ar71xx_pci_ble_table[size & 3][where & 3];
+	BUG_ON(t == 0xf);
+	t <<= (local) ? 20 : 4;
+
+	return t;
+}
+
+static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn,
+				      int where)
+{
+	u32 ret;
+
+	if (!bus->number) {
+		/* type 0 */
+		ret = (1 << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) |
+		      (where & ~3);
+	} else {
+		/* type 1 */
+		ret = (bus->number << 16) | (PCI_SLOT(devfn) << 11) |
+		      (PCI_FUNC(devfn) << 8) | (where & ~3) | 1;
+	}
+
+	return ret;
+}
+
+static inline struct ar71xx_pci_controller *
+pci_bus_to_ar71xx_controller(struct pci_bus *bus)
+{
+	struct pci_controller *hose;
+
+	hose = (struct pci_controller *) bus->sysdata;
+	return container_of(hose, struct ar71xx_pci_controller, pci_ctrl);
+}
+
+static int ar71xx_pci_check_error(struct ar71xx_pci_controller *apc, int quiet)
+{
+	void __iomem *base = apc->cfg_base;
+	u32 pci_err;
+	u32 ahb_err;
+
+	pci_err = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR) & 3;
+	if (pci_err) {
+		if (!quiet) {
+			u32 addr;
+
+			addr = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR_ADDR);
+			pr_crit("ar71xx: %s bus error %d at addr 0x%x\n",
+				"PCI", pci_err, addr);
+		}
+
+		/* clear PCI error status */
+		__raw_writel(pci_err, base + AR71XX_PCI_REG_PCI_ERR);
+	}
+
+	ahb_err = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR) & 1;
+	if (ahb_err) {
+		if (!quiet) {
+			u32 addr;
+
+			addr = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR_ADDR);
+			pr_crit("ar71xx: %s bus error %d at addr 0x%x\n",
+				"AHB", ahb_err, addr);
+		}
+
+		/* clear AHB error status */
+		__raw_writel(ahb_err, base + AR71XX_PCI_REG_AHB_ERR);
+	}
+
+	return !!(ahb_err | pci_err);
+}
+
+static inline void ar71xx_pci_local_write(struct ar71xx_pci_controller *apc,
+					  int where, int size, u32 value)
+{
+	void __iomem *base = apc->cfg_base;
+	u32 ad_cbe;
+
+	value = value << (8 * (where & 3));
+
+	ad_cbe = AR71XX_PCI_CRP_CMD_WRITE | (where & ~3);
+	ad_cbe |= ar71xx_pci_get_ble(where, size, 1);
+
+	__raw_writel(ad_cbe, base + AR71XX_PCI_REG_CRP_AD_CBE);
+	__raw_writel(value, base + AR71XX_PCI_REG_CRP_WRDATA);
+}
+
+static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus,
+					 unsigned int devfn,
+					 int where, int size, u32 cmd)
+{
+	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus);
+	void __iomem *base = apc->cfg_base;
+	u32 addr;
+
+	addr = ar71xx_pci_bus_addr(bus, devfn, where);
+
+	__raw_writel(addr, base + AR71XX_PCI_REG_CFG_AD);
+	__raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0),
+		     base + AR71XX_PCI_REG_CFG_CBE);
+
+	return ar71xx_pci_check_error(apc, 1);
+}
+
+static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 *value)
+{
+	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus);
+	void __iomem *base = apc->cfg_base;
+	unsigned long flags;
+	u32 data;
+	int err;
+	int ret;
+
+	ret = PCIBIOS_SUCCESSFUL;
+	data = ~0;
+
+	spin_lock_irqsave(&apc->lock, flags);
+
+	err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size,
+				     AR71XX_PCI_CFG_CMD_READ);
+	if (err)
+		ret = PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA);
+
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	*value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7];
+
+	return ret;
+}
+
+static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+				   int where, int size, u32 value)
+{
+	struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus);
+	void __iomem *base = apc->cfg_base;
+	unsigned long flags;
+	int err;
+	int ret;
+
+	value = value << (8 * (where & 3));
+	ret = PCIBIOS_SUCCESSFUL;
+
+	spin_lock_irqsave(&apc->lock, flags);
+
+	err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size,
+				     AR71XX_PCI_CFG_CMD_WRITE);
+	if (err)
+		ret = PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		__raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA);
+
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	return ret;
+}
+
+static struct pci_ops ar71xx_pci_ops = {
+	.read	= ar71xx_pci_read_config,
+	.write	= ar71xx_pci_write_config,
+};
+
+static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	void __iomem *base = ath79_reset_base;
+	u32 pending;
+
+	pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) &
+		  __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+
+	if (pending & AR71XX_PCI_INT_DEV0)
+		generic_handle_irq(ATH79_PCI_IRQ(0));
+
+	else if (pending & AR71XX_PCI_INT_DEV1)
+		generic_handle_irq(ATH79_PCI_IRQ(1));
+
+	else if (pending & AR71XX_PCI_INT_DEV2)
+		generic_handle_irq(ATH79_PCI_IRQ(2));
+
+	else if (pending & AR71XX_PCI_INT_CORE)
+		generic_handle_irq(ATH79_PCI_IRQ(4));
+
+	else
+		spurious_interrupt();
+}
+
+static void ar71xx_pci_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE;
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+}
+
+static void ar71xx_pci_irq_mask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE;
+	void __iomem *base = ath79_reset_base;
+	u32 t;
+
+	t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+
+	/* flush write */
+	__raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+}
+
+static struct irq_chip ar71xx_pci_irq_chip = {
+	.name		= "AR71XX PCI",
+	.irq_mask	= ar71xx_pci_irq_mask,
+	.irq_unmask	= ar71xx_pci_irq_unmask,
+	.irq_mask_ack	= ar71xx_pci_irq_mask,
+};
+
+static __devinit void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc)
+{
+	void __iomem *base = ath79_reset_base;
+	int i;
+
+	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE);
+	__raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS);
+
+	BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT);
+
+	for (i = ATH79_PCI_IRQ_BASE;
+	     i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++)
+		irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(apc->irq, ar71xx_pci_irq_handler);
+}
+
+static __devinit void ar71xx_pci_reset(void)
+{
+	void __iomem *ddr_base = ath79_ddr_base;
+
+	ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
+	mdelay(100);
+
+	ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE);
+	mdelay(100);
+
+	__raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0);
+	__raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1);
+	__raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2);
+	__raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3);
+	__raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4);
+	__raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5);
+	__raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6);
+	__raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7);
+
+	mdelay(100);
+}
+
+static int __devinit ar71xx_pci_probe(struct platform_device *pdev)
+{
+	struct ar71xx_pci_controller *apc;
+	struct resource *res;
+	u32 t;
+
+	apc = kzalloc(sizeof(struct ar71xx_pci_controller), GFP_KERNEL);
+	if (!apc)
+		return -ENOMEM;
+
+	spin_lock_init(&apc->lock);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->cfg_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!apc->cfg_base)
+		return -ENOMEM;
+
+	apc->irq = platform_get_irq(pdev, 0);
+	if (apc->irq < 0)
+		return -EINVAL;
+
+	apc->io_res.name = "PCI IO space";
+	apc->io_res.start = 0;
+	apc->io_res.end = 0;
+	apc->io_res.flags = IORESOURCE_IO;
+
+	apc->mem_res.name = "PCI memory space";
+	apc->mem_res.start = AR71XX_PCI_MEM_BASE;
+	apc->mem_res.end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1;
+	apc->mem_res.flags = IORESOURCE_MEM;
+
+	ar71xx_pci_reset();
+
+	/* setup COMMAND register */
+	t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+	  | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK;
+	ar71xx_pci_local_write(apc, PCI_COMMAND, 4, t);
+
+	/* clear bus errors */
+	ar71xx_pci_check_error(apc, 1);
+
+	ar71xx_pci_irq_init(apc);
+
+	apc->pci_ctrl.pci_ops = &ar71xx_pci_ops;
+	apc->pci_ctrl.mem_resource = &apc->mem_res;
+	apc->pci_ctrl.io_resource = &apc->io_res;
+
+	register_pci_controller(&apc->pci_ctrl);
+
+	return 0;
+}
+
+static struct platform_driver ar71xx_pci_driver = {
+	.probe = ar71xx_pci_probe,
+	.driver = {
+		.name = "ar71xx-pci",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init ar71xx_pci_init(void)
+{
+	return platform_driver_register(&ar71xx_pci_driver);
+}
+
+postcore_initcall(ar71xx_pci_init);
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
new file mode 100644
index 0000000..cda198a
--- /dev/null
+++ b/arch/mips/pci/pci-ar724x.c
@@ -0,0 +1,444 @@
+/*
+ *  Atheros AR724X PCI host controller driver
+ *
+ *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
+ *  Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  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.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/mach-ath79/ath79.h>
+#include <asm/mach-ath79/ar71xx_regs.h>
+
+#define AR724X_PCI_REG_RESET		0x18
+#define AR724X_PCI_REG_INT_STATUS	0x4c
+#define AR724X_PCI_REG_INT_MASK		0x50
+
+#define AR724X_PCI_RESET_LINK_UP	BIT(0)
+
+#define AR724X_PCI_INT_DEV0		BIT(14)
+
+#define AR724X_PCI_IRQ_COUNT		1
+
+#define AR7240_BAR0_WAR_VALUE	0xffff
+
+#define AR724X_PCI_CMD_INIT	(PCI_COMMAND_MEMORY |		\
+				 PCI_COMMAND_MASTER |		\
+				 PCI_COMMAND_INVALIDATE |	\
+				 PCI_COMMAND_PARITY |		\
+				 PCI_COMMAND_SERR |		\
+				 PCI_COMMAND_FAST_BACK)
+
+struct ar724x_pci_controller {
+	void __iomem *devcfg_base;
+	void __iomem *ctrl_base;
+	void __iomem *crp_base;
+
+	int irq;
+	int irq_base;
+
+	bool link_up;
+	bool bar0_is_cached;
+	u32  bar0_value;
+
+	spinlock_t lock;
+
+	struct pci_controller pci_controller;
+	struct resource io_res;
+	struct resource mem_res;
+};
+
+static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc)
+{
+	u32 reset;
+
+	reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET);
+	return reset & AR724X_PCI_RESET_LINK_UP;
+}
+
+static inline struct ar724x_pci_controller *
+pci_bus_to_ar724x_controller(struct pci_bus *bus)
+{
+	struct pci_controller *hose;
+
+	hose = (struct pci_controller *) bus->sysdata;
+	return container_of(hose, struct ar724x_pci_controller, pci_controller);
+}
+
+static int ar724x_pci_local_write(struct ar724x_pci_controller *apc,
+				  int where, int size, u32 value)
+{
+	unsigned long flags;
+	void __iomem *base;
+	u32 data;
+	int s;
+
+	WARN_ON(where & (size - 1));
+
+	if (!apc->link_up)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = apc->crp_base;
+
+	spin_lock_irqsave(&apc->lock, flags);
+	data = __raw_readl(base + (where & ~3));
+
+	switch (size) {
+	case 1:
+		s = ((where & 3) * 8);
+		data &= ~(0xff << s);
+		data |= ((value & 0xff) << s);
+		break;
+	case 2:
+		s = ((where & 2) * 8);
+		data &= ~(0xffff << s);
+		data |= ((value & 0xffff) << s);
+		break;
+	case 4:
+		data = value;
+		break;
+	default:
+		spin_unlock_irqrestore(&apc->lock, flags);
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	__raw_writel(data, base + (where & ~3));
+	/* flush write */
+	__raw_readl(base + (where & ~3));
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+			    int size, uint32_t *value)
+{
+	struct ar724x_pci_controller *apc;
+	unsigned long flags;
+	void __iomem *base;
+	u32 data;
+
+	apc = pci_bus_to_ar724x_controller(bus);
+	if (!apc->link_up)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (devfn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	base = apc->devcfg_base;
+
+	spin_lock_irqsave(&apc->lock, flags);
+	data = __raw_readl(base + (where & ~3));
+
+	switch (size) {
+	case 1:
+		if (where & 1)
+			data >>= 8;
+		if (where & 2)
+			data >>= 16;
+		data &= 0xff;
+		break;
+	case 2:
+		if (where & 2)
+			data >>= 16;
+		data &= 0xffff;
+		break;
+	case 4:
+		break;
+	default:
+		spin_unlock_irqrestore(&apc->lock, flags);
+
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	if (where == PCI_BASE_ADDRESS_0 && size == 4 &&
+	    apc->bar0_is_cached) {
+		/* use the cached value */
+		*value = apc->bar0_value;
+	} else {
+		*value = data;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+			     int size, uint32_t value)
+{
+	struct ar724x_pci_controller *apc;
+	unsigned long flags;
+	void __iomem *base;
+	u32 data;
+	int s;
+
+	apc = pci_bus_to_ar724x_controller(bus);
+	if (!apc->link_up)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (devfn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) {
+		if (value != 0xffffffff) {
+			/*
+			 * WAR for a hw issue. If the BAR0 register of the
+			 * device is set to the proper base address, the
+			 * memory space of the device is not accessible.
+			 *
+			 * Cache the intended value so it can be read back,
+			 * and write a SoC specific constant value to the
+			 * BAR0 register in order to make the device memory
+			 * accessible.
+			 */
+			apc->bar0_is_cached = true;
+			apc->bar0_value = value;
+
+			value = AR7240_BAR0_WAR_VALUE;
+		} else {
+			apc->bar0_is_cached = false;
+		}
+	}
+
+	base = apc->devcfg_base;
+
+	spin_lock_irqsave(&apc->lock, flags);
+	data = __raw_readl(base + (where & ~3));
+
+	switch (size) {
+	case 1:
+		s = ((where & 3) * 8);
+		data &= ~(0xff << s);
+		data |= ((value & 0xff) << s);
+		break;
+	case 2:
+		s = ((where & 2) * 8);
+		data &= ~(0xffff << s);
+		data |= ((value & 0xffff) << s);
+		break;
+	case 4:
+		data = value;
+		break;
+	default:
+		spin_unlock_irqrestore(&apc->lock, flags);
+
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	__raw_writel(data, base + (where & ~3));
+	/* flush write */
+	__raw_readl(base + (where & ~3));
+	spin_unlock_irqrestore(&apc->lock, flags);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops ar724x_pci_ops = {
+	.read	= ar724x_pci_read,
+	.write	= ar724x_pci_write,
+};
+
+static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct ar724x_pci_controller *apc;
+	void __iomem *base;
+	u32 pending;
+
+	apc = irq_get_handler_data(irq);
+	base = apc->ctrl_base;
+
+	pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) &
+		  __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+
+	if (pending & AR724X_PCI_INT_DEV0)
+		generic_handle_irq(apc->irq_base + 0);
+
+	else
+		spurious_interrupt();
+}
+
+static void ar724x_pci_irq_unmask(struct irq_data *d)
+{
+	struct ar724x_pci_controller *apc;
+	void __iomem *base;
+	int offset;
+	u32 t;
+
+	apc = irq_data_get_irq_chip_data(d);
+	base = apc->ctrl_base;
+	offset = apc->irq_base - d->irq;
+
+	switch (offset) {
+	case 0:
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_MASK);
+	}
+}
+
+static void ar724x_pci_irq_mask(struct irq_data *d)
+{
+	struct ar724x_pci_controller *apc;
+	void __iomem *base;
+	int offset;
+	u32 t;
+
+	apc = irq_data_get_irq_chip_data(d);
+	base = apc->ctrl_base;
+	offset = apc->irq_base - d->irq;
+
+	switch (offset) {
+	case 0:
+		t = __raw_readl(base + AR724X_PCI_REG_INT_MASK);
+		__raw_writel(t & ~AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_MASK);
+
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_MASK);
+
+		t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS);
+		__raw_writel(t | AR724X_PCI_INT_DEV0,
+			     base + AR724X_PCI_REG_INT_STATUS);
+
+		/* flush write */
+		__raw_readl(base + AR724X_PCI_REG_INT_STATUS);
+	}
+}
+
+static struct irq_chip ar724x_pci_irq_chip = {
+	.name		= "AR724X PCI ",
+	.irq_mask	= ar724x_pci_irq_mask,
+	.irq_unmask	= ar724x_pci_irq_unmask,
+	.irq_mask_ack	= ar724x_pci_irq_mask,
+};
+
+static void __devinit ar724x_pci_irq_init(struct ar724x_pci_controller *apc,
+					  int id)
+{
+	void __iomem *base;
+	int i;
+
+	base = apc->ctrl_base;
+
+	__raw_writel(0, base + AR724X_PCI_REG_INT_MASK);
+	__raw_writel(0, base + AR724X_PCI_REG_INT_STATUS);
+
+	apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT);
+
+	for (i = apc->irq_base;
+	     i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) {
+		irq_set_chip_and_handler(i, &ar724x_pci_irq_chip,
+					 handle_level_irq);
+		irq_set_chip_data(i, apc);
+	}
+
+	irq_set_handler_data(apc->irq, apc);
+	irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler);
+}
+
+static int __devinit ar724x_pci_probe(struct platform_device *pdev)
+{
+	struct ar724x_pci_controller *apc;
+	struct resource *res;
+	int id;
+
+	id = pdev->id;
+	if (id == -1)
+		id = 0;
+
+	apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller),
+			    GFP_KERNEL);
+	if (!apc)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->ctrl_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (apc->ctrl_base == NULL)
+		return -EBUSY;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->devcfg_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!apc->devcfg_base)
+		return -EBUSY;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->crp_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (apc->crp_base == NULL)
+		return -EBUSY;
+
+	apc->irq = platform_get_irq(pdev, 0);
+	if (apc->irq < 0)
+		return -EINVAL;
+
+	spin_lock_init(&apc->lock);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->io_res.parent = res;
+	apc->io_res.name = "PCI IO space";
+	apc->io_res.start = res->start;
+	apc->io_res.end = res->end;
+	apc->io_res.flags = IORESOURCE_IO;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base");
+	if (!res)
+		return -EINVAL;
+
+	apc->mem_res.parent = res;
+	apc->mem_res.name = "PCI memory space";
+	apc->mem_res.start = res->start;
+	apc->mem_res.end = res->end;
+	apc->mem_res.flags = IORESOURCE_MEM;
+
+	apc->pci_controller.pci_ops = &ar724x_pci_ops;
+	apc->pci_controller.io_resource = &apc->io_res;
+	apc->pci_controller.mem_resource = &apc->mem_res;
+
+	apc->link_up = ar724x_pci_check_link(apc);
+	if (!apc->link_up)
+		dev_warn(&pdev->dev, "PCIe link is down\n");
+
+	ar724x_pci_irq_init(apc, id);
+
+	ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT);
+
+	register_pci_controller(&apc->pci_controller);
+
+	return 0;
+}
+
+static struct platform_driver ar724x_pci_driver = {
+	.probe = ar724x_pci_probe,
+	.driver = {
+		.name = "ar724x-pci",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init ar724x_pci_init(void)
+{
+	return platform_driver_register(&ar724x_pci_driver);
+}
+
+postcore_initcall(ar724x_pci_init);
diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c
deleted file mode 100644
index a4dd24a..0000000
--- a/arch/mips/pci/pci-ath724x.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *  Atheros 724x PCI support
- *
- *  Copyright (C) 2011 René Bolldorf <xsecute@googlemail.com>
- *
- *  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.
- */
-
-#include <linux/pci.h>
-#include <asm/mach-ath79/pci-ath724x.h>
-
-#define reg_read(_phys)		(*(unsigned int *) KSEG1ADDR(_phys))
-#define reg_write(_phys, _val)	((*(unsigned int *) KSEG1ADDR(_phys)) = (_val))
-
-#define ATH724X_PCI_DEV_BASE	0x14000000
-#define ATH724X_PCI_MEM_BASE	0x10000000
-#define ATH724X_PCI_MEM_SIZE	0x08000000
-
-static DEFINE_SPINLOCK(ath724x_pci_lock);
-static struct ath724x_pci_data *pci_data;
-static int pci_data_size;
-
-static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
-			    int size, uint32_t *value)
-{
-	unsigned long flags, addr, tval, mask;
-
-	if (devfn)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if (where & (size - 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&ath724x_pci_lock, flags);
-
-	switch (size) {
-	case 1:
-		addr = where & ~3;
-		mask = 0xff000000 >> ((where % 4) * 8);
-		tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
-		tval = tval & ~mask;
-		*value = (tval >> ((4 - (where % 4))*8));
-		break;
-	case 2:
-		addr = where & ~3;
-		mask = 0xffff0000 >> ((where % 4)*8);
-		tval = reg_read(ATH724X_PCI_DEV_BASE + addr);
-		tval = tval & ~mask;
-		*value = (tval >> ((4 - (where % 4))*8));
-		break;
-	case 4:
-		*value = reg_read(ATH724X_PCI_DEV_BASE + where);
-		break;
-	default:
-		spin_unlock_irqrestore(&ath724x_pci_lock, flags);
-
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	}
-
-	spin_unlock_irqrestore(&ath724x_pci_lock, flags);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
-			     int size, uint32_t value)
-{
-	unsigned long flags, tval, addr, mask;
-
-	if (devfn)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if (where & (size - 1))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	spin_lock_irqsave(&ath724x_pci_lock, flags);
-
-	switch (size) {
-	case 1:
-		addr = (ATH724X_PCI_DEV_BASE + where) & ~3;
-		mask = 0xff000000 >> ((where % 4)*8);
-		tval = reg_read(addr);
-		tval = tval & ~mask;
-		tval |= (value << ((4 - (where % 4))*8)) & mask;
-		reg_write(addr, tval);
-		break;
-	case 2:
-		addr = (ATH724X_PCI_DEV_BASE + where) & ~3;
-		mask = 0xffff0000 >> ((where % 4)*8);
-		tval = reg_read(addr);
-		tval = tval & ~mask;
-		tval |= (value << ((4 - (where % 4))*8)) & mask;
-		reg_write(addr, tval);
-		break;
-	case 4:
-		reg_write((ATH724X_PCI_DEV_BASE + where), value);
-		break;
-	default:
-		spin_unlock_irqrestore(&ath724x_pci_lock, flags);
-
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	}
-
-	spin_unlock_irqrestore(&ath724x_pci_lock, flags);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops ath724x_pci_ops = {
-	.read	= ath724x_pci_read,
-	.write	= ath724x_pci_write,
-};
-
-static struct resource ath724x_io_resource = {
-	.name   = "PCI IO space",
-	.start  = 0,
-	.end    = 0,
-	.flags  = IORESOURCE_IO,
-};
-
-static struct resource ath724x_mem_resource = {
-	.name   = "PCI memory space",
-	.start  = ATH724X_PCI_MEM_BASE,
-	.end    = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
-
-static struct pci_controller ath724x_pci_controller = {
-	.pci_ops        = &ath724x_pci_ops,
-	.io_resource    = &ath724x_io_resource,
-	.mem_resource	= &ath724x_mem_resource,
-};
-
-void ath724x_pci_add_data(struct ath724x_pci_data *data, int size)
-{
-	pci_data	= data;
-	pci_data_size	= size;
-}
-
-int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin)
-{
-	unsigned int devfn = dev->devfn;
-	int irq = -1;
-
-	if (devfn > pci_data_size - 1)
-		return irq;
-
-	irq = pci_data[devfn].irq;
-
-	return irq;
-}
-
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	unsigned int devfn = dev->devfn;
-
-	if (devfn > pci_data_size - 1)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	dev->dev.platform_data = pci_data[devfn].pdata;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int __init ath724x_pcibios_init(void)
-{
-	register_pci_controller(&ath724x_pci_controller);
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-arch_initcall(ath724x_pcibios_init);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 1552150..7ff1f7a 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -127,9 +127,20 @@
 
 void __devinit register_pci_controller(struct pci_controller *hose)
 {
-	if (request_resource(&iomem_resource, hose->mem_resource) < 0)
+	struct resource *parent;
+
+	parent = hose->mem_resource->parent;
+	if (!parent)
+		parent = &iomem_resource;
+
+	if (request_resource(parent, hose->mem_resource) < 0)
 		goto out;
-	if (request_resource(&ioport_resource, hose->io_resource) < 0) {
+
+	parent = hose->io_resource->parent;
+	if (!parent)
+		parent = &ioport_resource;
+
+	if (request_resource(parent, hose->io_resource) < 0) {
 		release_resource(hose->mem_resource);
 		goto out;
 	}
diff --git a/drivers/Makefile b/drivers/Makefile
index 34503cc..3b32aad 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -52,8 +52,8 @@
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_TARGET_CORE)	+= target/
-obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-$(CONFIG_MTD)		+= mtd/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_FUSION)		+= message/
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d0c4118..454b13a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -489,4 +489,13 @@
 	help
 	  Select this option to enable GPIO driver for the TPS65910
 	  chip family.
+
+comment "Other GPIO expanders"
+
+config GPIO_NXP_74HC153
+	tristate "NXP 74HC153 Dual 4-input multiplexer"
+	help
+	  Platform driver for NXP 74HC153 Dual 4-input Multiplexer. This
+	  provides a GPIO interface supporting input mode only.
+
 endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fa10df6..f3f1eec 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o
 obj-$(CONFIG_PLAT_NOMADIK)	+= gpio-nomadik.o
+obj-$(CONFIG_GPIO_NXP_74HC153)	+= gpio-nxp-74hc153.o
 obj-$(CONFIG_ARCH_OMAP)		+= gpio-omap.o
 obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d7e6b7f..ed4072f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -418,6 +418,17 @@
 	  These triggers allow kernel events to drive the LEDs and can
 	  be configured via sysfs. If unsure, say Y.
 
+config LEDS_WNDR3700_USB
+	tristate "NETGEAR WNDR3700 USB LED driver"
+	depends on LEDS_CLASS && ATH79_MACH_WNDR3700
+	help
+	  This option enables support for the USB LED found on the
+	  NETGEAR WNDR3700 board.
+
+config LEDS_RB750
+	tristate "LED driver for the Mikrotik RouterBOARD 750"
+	depends on LEDS_CLASS && ATH79_MACH_RB750
+
 comment "LED Triggers"
 
 config LEDS_TRIGGER_TIMER
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 3627c67..2587402 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -35,12 +35,14 @@
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o
 obj-$(CONFIG_LEDS_PWM)			+= leds-pwm.o
+obj-${CONFIG_LEDS_WNDR3700_USB}		+= leds-wndr3700-usb.o
 obj-$(CONFIG_LEDS_REGULATOR)		+= leds-regulator.o
 obj-$(CONFIG_LEDS_INTEL_SS4200)		+= leds-ss4200.o
 obj-$(CONFIG_LEDS_LT3593)		+= leds-lt3593.o
 obj-$(CONFIG_LEDS_ADP5520)		+= leds-adp5520.o
 obj-$(CONFIG_LEDS_DELL_NETBOOKS)	+= dell-led.o
 obj-$(CONFIG_LEDS_MC13783)		+= leds-mc13783.o
+obj-$(CONFIG_LEDS_RB750)		+= leds-rb750.o
 obj-$(CONFIG_LEDS_NS2)			+= leds-ns2.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 982a98b..ae7c206 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -156,6 +156,12 @@
 	  This provides partions parsing for BCM63xx devices with CFE
 	  bootloaders.
 
+config MTD_WRT160NL_PARTS
+	tristate "Linksys WRT160NL partitioning support"
+	depends on ATH79_MACH_WRT160NL
+	---help---
+	   Linksys WRT160NL partitioning support
+
 config MTD_MYLOADER_PARTS
 	tristate "MyLoader partition parsing"
 	depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79
@@ -172,6 +178,12 @@
 	  You will still need the parsing functions to be called by the driver
 	  for your particular device. It won't happen automatically.
 
+config MTD_TPLINK_PARTS
+	tristate "TP-Link AR7XXX/AR9XXX partitioning support"
+	depends on ATH79
+	---help---
+	  TBD.
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index cc0c225..7260810 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -13,6 +13,8 @@
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
 obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
+obj-$(CONFIG_MTD_TPLINK_PARTS)	+= tplinkpart.o
+obj-$(CONFIG_MTD_WRT160NL_PARTS) += wrt160nl_part.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index a4ceb01..b838b57 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -39,7 +39,7 @@
 #include <linux/mtd/xip.h>
 
 #define AMD_BOOTLOC_BUG
-#define FORCE_WORD_WRITE 0
+#define FORCE_WORD_WRITE 1
 
 #define MAX_WORD_RETRIES 3
 
@@ -50,7 +50,9 @@
 
 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+#if !FORCE_WORD_WRITE
 static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+#endif
 static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
 static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
 static void cfi_amdstd_sync (struct mtd_info *);
@@ -183,6 +185,7 @@
 }
 #endif
 
+#if !FORCE_WORD_WRITE
 static void fixup_use_write_buffers(struct mtd_info *mtd)
 {
 	struct map_info *map = mtd->priv;
@@ -192,6 +195,7 @@
 		mtd->write = cfi_amdstd_write_buffers;
 	}
 }
+#endif /* !FORCE_WORD_WRITE */
 
 /* Atmel chips don't use the same PRI format as AMD chips */
 static void fixup_convert_atmel_pri(struct mtd_info *mtd)
@@ -1214,8 +1218,8 @@
 			break;
 		}
 
-		if (chip_ready(map, adr))
-			break;
+		if (chip_good(map, adr, datum))
+			goto enable_xip;
 
 		/* Latency issues. Drop the lock, wait a while and retry */
 		UDELAY(map, chip, adr, 1);
@@ -1231,6 +1235,8 @@
 
 		ret = -EIO;
 	}
+
+ enable_xip:
 	xip_enable(map, chip, adr);
  op_done:
 	chip->state = FL_READY;
@@ -1372,6 +1378,7 @@
 /*
  * FIXME: interleaved mode not tested, and probably not supported!
  */
+#if !FORCE_WORD_WRITE
 static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 				    unsigned long adr, const u_char *buf,
 				    int len)
@@ -1483,7 +1490,6 @@
 	return ret;
 }
 
-
 static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
 				    size_t *retlen, const u_char *buf)
 {
@@ -1562,7 +1568,7 @@
 
 	return 0;
 }
-
+#endif /* !FORCE_WORD_WRITE */
 
 /*
  * Handle devices with one erase region, that only implement
@@ -1627,8 +1633,8 @@
 			chip->erase_suspended = 0;
 		}
 
-		if (chip_ready(map, adr))
-			break;
+		if (chip_good(map, adr, map_word_ff(map)))
+			goto op_done;
 
 		if (time_after(jiffies, timeo)) {
 			printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -1648,6 +1654,7 @@
 		ret = -EIO;
 	}
 
+ op_done:
 	chip->state = FL_READY;
 	xip_enable(map, chip, adr);
 	put_chip(map, chip, adr);
@@ -1715,9 +1722,9 @@
 			chip->erase_suspended = 0;
 		}
 
-		if (chip_ready(map, adr)) {
+		if (chip_good(map, adr, map_word_ff(map))) {
 			xip_enable(map, chip, adr);
-			break;
+			goto op_done;
 		}
 
 		if (time_after(jiffies, timeo)) {
@@ -1739,6 +1746,7 @@
 		ret = -EIO;
 	}
 
+ op_done:
 	chip->state = FL_READY;
 	put_chip(map, chip, adr);
 	mutex_unlock(&chip->mutex);
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index c443f52..dc80479 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -148,6 +148,7 @@
 #define SST39LF160	0x2782
 #define SST39VF1601	0x234b
 #define SST39VF3201	0x235b
+#define SST39VF6401B	0x236d
 #define SST39WF1601	0x274b
 #define SST39WF1602	0x274a
 #define SST39LF512	0x00D4
@@ -1568,6 +1569,18 @@
 			ERASEINFO(0x10000,64),
 		}
 	}, {
+		.mfr_id         = CFI_MFR_SST,
+		.dev_id         = SST39VF6401B,
+		.name           = "SST 39VF6401B",
+		.devtypes       = CFI_DEVICETYPE_X16,
+		.uaddr          = MTD_UADDR_0xAAAA_0x5555,
+		.dev_size       = SIZE_8MiB,
+		.cmd_set        = P_ID_AMD_STD,
+		.nr_regions     = 1,
+		.regions        = {
+			ERASEINFO(0x10000,128)
+		}
+	}, {
 		.mfr_id		= CFI_MFR_ST,
 		.dev_id		= M29F800AB,
 		.name		= "ST M29F800AB",
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index e9ecd39..3d64590 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -100,6 +100,7 @@
 	u16			addr_width;
 	u8			erase_opcode;
 	u8			*command;
+	size_t			max_read_len;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -352,6 +353,7 @@
 	struct m25p *flash = mtd_to_m25p(mtd);
 	struct spi_transfer t[2];
 	struct spi_message m;
+	loff_t ofs;
 
 	pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
 			__func__, (u32)from, len);
@@ -370,12 +372,12 @@
 	 * OPCODE_FAST_READ (if available) is faster.
 	 * Should add 1 byte DUMMY_BYTE.
 	 */
+	t[0].type = SPI_TRANSFER_FLASH_READ_CMD;
 	t[0].tx_buf = flash->command;
 	t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
 	spi_message_add_tail(&t[0], &m);
 
-	t[1].rx_buf = buf;
-	t[1].len = len;
+	t[1].type = SPI_TRANSFER_FLASH_READ_DATA;
 	spi_message_add_tail(&t[1], &m);
 
 	/* Byte count starts at zero. */
@@ -383,13 +385,6 @@
 
 	mutex_lock(&flash->lock);
 
-	/* Wait till previous write/erase is done. */
-	if (wait_till_ready(flash)) {
-		/* REVISIT status return?? */
-		mutex_unlock(&flash->lock);
-		return 1;
-	}
-
 	/* FIXME switch to OPCODE_FAST_READ.  It's required for higher
 	 * clocks; and at this writing, every chip this driver handles
 	 * supports that opcode.
@@ -397,11 +392,44 @@
 
 	/* Set up the write data buffer. */
 	flash->command[0] = OPCODE_READ;
-	m25p_addr2cmd(flash, from, flash->command);
 
-	spi_sync(flash->spi, &m);
+	ofs = 0;
+	while (len) {
+		size_t readlen;
+		size_t done;
+		int ret;
 
-	*retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
+		ret = wait_till_ready(flash);
+		if (ret) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		if (flash->max_read_len > 0 &&
+		    flash->max_read_len < len)
+			readlen = flash->max_read_len;
+		else
+			readlen = len;
+
+		t[1].rx_buf = buf + ofs;
+		t[1].len = readlen;
+
+		m25p_addr2cmd(flash, from + ofs, flash->command);
+
+		spi_sync(flash->spi, &m);
+
+		done = m.actual_length - m25p_cmdsz(flash) -
+		       FAST_READ_DUMMY_BYTE;
+		if (done != readlen) {
+			mutex_unlock(&flash->lock);
+			return 1;
+		}
+
+		ofs += done;
+		len -= done;
+	}
+
+	*retlen = ofs;
 
 	mutex_unlock(&flash->lock);
 
@@ -695,6 +723,13 @@
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
+	/* Micron */
+	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, 0) },
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, 0) },
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, 0) },
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K) },
+	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+
 	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */
 	{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
 	{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
@@ -925,6 +960,12 @@
 	flash->mtd.erase = m25p80_erase;
 	flash->mtd.read = m25p80_read;
 
+	if (data && data->max_read_len) {
+		flash->max_read_len = data->max_read_len;
+		dev_warn(&spi->dev, "max_read_len set to %d bytes\n",
+			flash->max_read_len);
+	}
+
 	/* sst flash chips use AAI word program */
 	if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
 		flash->mtd.write = sst_write;
@@ -946,6 +987,7 @@
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	memset(&ppdata, '\0', sizeof(ppdata));
 	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
@@ -986,7 +1028,9 @@
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+	return mtd_device_parse_register(&flash->mtd,
+			data ? data->part_probes : NULL,
+			&ppdata,
 			data ? data->parts : NULL,
 			data ? data->nr_parts : 0);
 }
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index abc5626..b0116d5 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -29,6 +29,66 @@
 	struct map_info		map[MAX_RESOURCES];
 };
 
+static struct platform_device *physmap_map2pdev(struct map_info *map)
+{
+	return (struct platform_device *) map->map_priv_1;
+}
+
+static void physmap_lock(struct map_info *map)
+{
+	struct platform_device *pdev;
+	struct physmap_flash_data *physmap_data;
+
+	pdev = physmap_map2pdev(map);
+	physmap_data = pdev->dev.platform_data;
+	physmap_data->lock(pdev);
+}
+
+static void physmap_unlock(struct map_info *map)
+{
+	struct platform_device *pdev;
+	struct physmap_flash_data *physmap_data;
+
+	pdev = physmap_map2pdev(map);
+	physmap_data = pdev->dev.platform_data;
+	physmap_data->unlock(pdev);
+}
+
+static map_word physmap_flash_read_lock(struct map_info *map, unsigned long ofs)
+{
+	map_word ret;
+
+	physmap_lock(map);
+	ret = inline_map_read(map, ofs);
+	physmap_unlock(map);
+
+	return ret;
+}
+
+static void physmap_flash_write_lock(struct map_info *map, map_word d,
+				     unsigned long ofs)
+{
+	physmap_lock(map);
+	inline_map_write(map, d, ofs);
+	physmap_unlock(map);
+}
+
+static void physmap_flash_copy_from_lock(struct map_info *map, void *to,
+					 unsigned long from, ssize_t len)
+{
+	physmap_lock(map);
+	inline_map_copy_from(map, to, from, len);
+	physmap_unlock(map);
+}
+
+static void physmap_flash_copy_to_lock(struct map_info *map, unsigned long to,
+				       const void *from, ssize_t len)
+{
+	physmap_lock(map);
+	inline_map_copy_to(map, to, from, len);
+	physmap_unlock(map);
+}
+
 static int physmap_flash_remove(struct platform_device *dev)
 {
 	struct physmap_flash_info *info;
@@ -141,6 +201,13 @@
 
 		simple_map_init(&info->map[i]);
 
+		if (physmap_data->lock && physmap_data->unlock) {
+			info->map[i].read = physmap_flash_read_lock;
+			info->map[i].write = physmap_flash_write_lock;
+			info->map[i].copy_from = physmap_flash_copy_from_lock;
+			info->map[i].copy_to = physmap_flash_copy_to_lock;
+		}
+
 		probe_type = rom_probe_types;
 		if (physmap_data->probe_type == NULL) {
 			for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 31b034b..c8e913f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -536,4 +536,24 @@
 	  Enables support for NAND Flash chips on the ST Microelectronics
 	  Flexible Static Memory Controller (FSMC)
 
+config MTD_NAND_RB4XX
+	tristate "NAND flash driver for RouterBoard 4xx series"
+	depends on MTD_NAND && ATH79_MACH_RB4XX
+
+config MTD_NAND_RB750
+	tristate "NAND flash driver for the RouterBoard 750"
+	depends on MTD_NAND && ATH79_MACH_RB750
+
+config MTD_NAND_AR934X
+	tristate "NAND flash driver for the Atheros AR934x SoCs"
+	depends on SOC_AR934X
+
+config MTD_NAND_ATH79
+	tristate "Nand flash support for Qualcomm-Atheros SoCs 71xx & 93xx"
+	default n
+	depends on MTD_NAND && (SOC_AR724X || SOC_AR934X)
+	help
+	  Enables the driver for NAND flash controller on Qualcomm-Atheros System on Chips
+	  This controller is used on families AR71xx and AR9xxx.
+
 endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 618f4ba..9883660 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -11,6 +11,7 @@
 obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
 obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
+obj-$(CONFIG_MTD_NAND_AR934X)		+= ar934x_nfc.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
@@ -33,6 +34,8 @@
 obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
 obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
+obj-$(CONFIG_MTD_NAND_RB4XX)		+= rb4xx_nand.o
+obj-$(CONFIG_MTD_NAND_RB750)		+= rb750_nand.o
 obj-$(CONFIG_MTD_ALAUDA)		+= alauda.o
 obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
@@ -49,5 +52,6 @@
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
 obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
+obj-$(CONFIG_MTD_NAND_ATH79)		+= ath79_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index cc7ed51..ea3f4e4 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -79,6 +79,11 @@
 	static char nullstring[] = "unallocated";
 #endif
 
+	buf = vmalloc(master->erasesize);
+	if (!buf)
+		return -ENOMEM;
+
+ restart:
 	if ( directory < 0 ) {
 		offset = master->size + directory * master->erasesize;
 		while (mtd_can_have_bb(master) &&
@@ -86,6 +91,7 @@
 			if (!offset) {
 			nogood:
 				printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n");
+				vfree(buf);
 				return -EIO;
 			}
 			offset -= master->erasesize;
@@ -99,10 +105,6 @@
 				goto nogood;
 		}
 	}
-	buf = vmalloc(master->erasesize);
-
-	if (!buf)
-		return -ENOMEM;
 
 	printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
 	       master->name, offset);
@@ -175,6 +177,11 @@
 	}
 	if (i == numslots) {
 		/* Didn't find it */
+		if (offset + master->erasesize < master->size) {
+			/* not at the end of the flash yet, maybe next block :) */
+			directory++;
+			goto restart;
+		}
 		printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
 		       master->name);
 		ret = 0;
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index dd151d5..2ca6ec6 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -12,6 +12,13 @@
 	  This enables support for the Marvell 88E6060 ethernet switch
 	  chip.
 
+config NET_DSA_MV88E6063
+	bool "Marvell 88E6063 ethernet switch chip support"
+	select NET_DSA_TAG_TRAILER
+	---help---
+	  This enables support for the Marvell 88E6063 ethernet switch
+	  chip
+
 config NET_DSA_MV88E6XXX_NEED_PPU
 	bool
 	default n
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index f3bda05..39e01de 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o
 obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx_drv.o
 mv88e6xxx_drv-y += mv88e6xxx.o
 ifdef CONFIG_NET_DSA_MV88E6123_61_65
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 1ed886d..ffbdd247 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_ATHEROS
 	bool "Atheros devices"
 	default y
-	depends on PCI
+	depends on (PCI || ATH79)
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y
 	  and read the Ethernet-HOWTO, available from
@@ -67,4 +67,6 @@
 	  To compile this driver as a module, choose M here.  The module
 	  will be called atl1c.
 
+source drivers/net/ethernet/atheros/ag71xx/Kconfig
+
 endif # NET_VENDOR_ATHEROS
diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile
index e7e76fb..ac77faa 100644
--- a/drivers/net/ethernet/atheros/Makefile
+++ b/drivers/net/ethernet/atheros/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Atheros network device drivers.
 #
 
+obj-$(CONFIG_AG71XX) += ag71xx/
 obj-$(CONFIG_ATL1) += atlx/
 obj-$(CONFIG_ATL2) += atlx/
 obj-$(CONFIG_ATL1E) += atl1e/
diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index daec9b0..a369c31 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -165,16 +165,7 @@
 
 	ctrl->ops->set_mdio_dir(ctrl, 0);
 
-	/* check the turnaround bit: the PHY should be driving it to zero */
-	if (mdiobb_get_bit(ctrl) != 0) {
-		/* PHY didn't drive TA low -- flush any bits it
-		 * may be trying to send.
-		 */
-		for (i = 0; i < 32; i++)
-			mdiobb_get_bit(ctrl);
-
-		return 0xffff;
-	}
+	mdiobb_get_bit(ctrl);
 
 	ret = mdiobb_get_num(ctrl, 16);
 	mdiobb_get_bit(ctrl);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index f62424f..6b0095d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -59,6 +59,14 @@
 	help
 	  This is the driver for the Altera SPI Controller.
 
+config SPI_AP83
+	tristate "Atheros AP83 specific SPI Controller"
+	depends on SPI_MASTER && ATH79_MACH_AP83
+	select SPI_BITBANG
+	help
+	  This is a specific SPI controller driver for the Atheros AP83
+	  reference board.
+
 config SPI_ATH79
 	tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
 	depends on ATH79 && GENERIC_GPIO
@@ -288,6 +296,12 @@
 config SPI_PXA2XX_PCI
 	def_bool SPI_PXA2XX && X86_32 && PCI
 
+config SPI_RB4XX
+	tristate "Mikrotik RB4XX SPI master"
+	depends on SPI_MASTER && ATH79_MACH_RB4XX
+	help
+	  SPI controller driver for the Mikrotik RB4xx series boards.
+
 config SPI_S3C24XX
 	tristate "Samsung S3C24XX series SPI"
 	depends on ARCH_S3C2410 && EXPERIMENTAL
@@ -433,6 +447,18 @@
 	  sysfs interface, with each line presented as a kind of GPIO
 	  exposing both switch control and diagnostic feedback.
 
+config SPI_RB4XX_CPLD
+	tristate "MikroTik RB4XX CPLD driver"
+	depends on ATH79_MACH_RB4XX
+	help
+	  SPI driver for the Xilinx CPLD chip present on the
+	  MikroTik RB4xx boards.
+
+config SPI_VSC7385
+	tristate "Vitesse VSC7385 ethernet switch driver"
+	help
+	  SPI driver for the Vitesse VSC7385 ethernet switch.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 1514c1d..b9552fa 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -12,6 +12,7 @@
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ALTERA)		+= spi-altera.o
 obj-$(CONFIG_SPI_ATMEL)			+= spi-atmel.o
+obj-$(CONFIG_SPI_AP83)			+= spi-ap83.o
 obj-$(CONFIG_SPI_ATH79)			+= spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)		+= spi-au1550.o
 obj-$(CONFIG_SPI_BFIN)			+= spi-bfin5xx.o
@@ -45,6 +46,8 @@
 obj-$(CONFIG_SPI_PPC4xx)		+= spi-ppc4xx.o
 obj-$(CONFIG_SPI_PXA2XX)		+= spi-pxa2xx.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)		+= spi-pxa2xx-pci.o
+obj-$(CONFIG_SPI_RB4XX)			+= spi-rb4xx.o
+obj-$(CONFIG_SPI_RB4XX_CPLD)		+= spi-rb4xx-cpld.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o
 spi-s3c24xx-hw-y			:= spi-s3c24xx.o
 spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o
@@ -58,5 +61,5 @@
 obj-$(CONFIG_SPI_TLE62X0)		+= spi-tle62x0.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi-topcliff-pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi-txx9.o
+obj-$(CONFIG_SPI_VSC7385)		+= spi-vsc7385.o
 obj-$(CONFIG_SPI_XILINX)		+= spi-xilinx.o
-
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index acc88b4..07e2a14 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -1,6 +1,7 @@
 /*
  * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
  *
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
  *
  * This driver has been based on the spi-gpio.c:
@@ -24,17 +25,40 @@
 #include <linux/spi/spi_bitbang.h>
 #include <linux/bitops.h>
 #include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
 
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include <asm/mach-ath79/ath79_spi_platform.h>
 
 #define DRV_NAME	"ath79-spi"
 
+#define ATH79_SPI_RRW_DELAY_FACTOR	12000
+#define MHZ				(1000 * 1000)
+
+#define ATH79_SPI_CS_LINE_MAX		2
+
+enum ath79_spi_state {
+	ATH79_SPI_STATE_WAIT_CMD = 0,
+	ATH79_SPI_STATE_WAIT_READ,
+};
+
 struct ath79_spi {
 	struct spi_bitbang	bitbang;
 	u32			ioc_base;
 	u32			reg_ctrl;
 	void __iomem		*base;
+	struct clk		*clk;
+	unsigned		rrw_delay;
+	unsigned		miso_line;
+
+	enum ath79_spi_state	state;
+	u32			clk_div;
+	unsigned long 		read_addr;
+	unsigned long		ahb_rate;
 };
 
 static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
@@ -52,10 +76,17 @@
 	return spi_master_get_devdata(spi->master);
 }
 
+static inline void ath79_spi_delay(struct ath79_spi *sp, unsigned nsecs)
+{
+	if (nsecs > sp->rrw_delay)
+		ndelay(nsecs - sp->rrw_delay);
+}
+
 static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
 {
 	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
 	int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
+	struct ath79_spi_controller_data *cdata = spi->controller_data;
 
 	if (is_active) {
 		/* set initial clock polarity */
@@ -67,84 +98,129 @@
 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
 	}
 
-	if (spi->chip_select) {
-		struct ath79_spi_controller_data *cdata = spi->controller_data;
-
-		/* SPI is normally active-low */
-		gpio_set_value(cdata->gpio, cs_high);
-	} else {
+	switch (cdata->cs_type) {
+	case ATH79_SPI_CS_TYPE_INTERNAL:
 		if (cs_high)
-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
+			sp->ioc_base |= AR71XX_SPI_IOC_CS(cdata->cs_line);
 		else
-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
+			sp->ioc_base &= ~AR71XX_SPI_IOC_CS(cdata->cs_line);
 
 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
-	}
+		break;
 
+	case ATH79_SPI_CS_TYPE_GPIO:
+		/* SPI is normally active-low */
+		if (gpio_cansleep(cdata->cs_line))
+			gpio_set_value_cansleep(cdata->cs_line, cs_high);
+		else
+			gpio_set_value(cdata->cs_line, cs_high);
+		break;
+	}
 }
 
-static int ath79_spi_setup_cs(struct spi_device *spi)
+static void ath79_spi_enable(struct ath79_spi *sp)
 {
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-	struct ath79_spi_controller_data *cdata;
-
-	cdata = spi->controller_data;
-	if (spi->chip_select && !cdata)
-		return -EINVAL;
-
 	/* enable GPIO mode */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
 
 	/* save CTRL register */
 	sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
 	sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
-
-	/* TODO: setup speed? */
-	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
-
-	if (spi->chip_select) {
-		int status = 0;
-
-		status = gpio_request(cdata->gpio, dev_name(&spi->dev));
-		if (status)
-			return status;
-
-		status = gpio_direction_output(cdata->gpio,
-					       spi->mode & SPI_CS_HIGH);
-		if (status) {
-			gpio_free(cdata->gpio);
-			return status;
-		}
-	} else {
-		if (spi->mode & SPI_CS_HIGH)
-			sp->ioc_base |= AR71XX_SPI_IOC_CS0;
-		else
-			sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
-		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
-	}
-
-	return 0;
 }
 
-static void ath79_spi_cleanup_cs(struct spi_device *spi)
+static void ath79_spi_disable(struct ath79_spi *sp)
 {
-	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
-
-	if (spi->chip_select) {
-		struct ath79_spi_controller_data *cdata = spi->controller_data;
-		gpio_free(cdata->gpio);
-	}
-
 	/* restore CTRL register */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
 	/* disable GPIO mode */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
 }
 
+static int ath79_spi_setup_cs(struct spi_device *spi)
+{
+	struct ath79_spi_controller_data *cdata;
+	unsigned long flags;
+	int status;
+
+	cdata = spi->controller_data;
+	if (!cdata)
+		return -EINVAL;
+
+	status = 0;
+	switch (cdata->cs_type) {
+	case ATH79_SPI_CS_TYPE_INTERNAL:
+		if (cdata->cs_line > ATH79_SPI_CS_LINE_MAX)
+			status = -EINVAL;
+		break;
+
+	case ATH79_SPI_CS_TYPE_GPIO:
+		flags = GPIOF_DIR_OUT;
+		if (spi->mode & SPI_CS_HIGH)
+			flags |= GPIOF_INIT_HIGH;
+		else
+			flags |= GPIOF_INIT_LOW;
+
+		status = gpio_request_one(cdata->cs_line, flags,
+					  dev_name(&spi->dev));
+		break;
+	}
+
+	return status;
+}
+
+static void ath79_spi_cleanup_cs(struct spi_device *spi)
+{
+	struct ath79_spi_controller_data *cdata;
+
+	cdata = spi->controller_data;
+	if (!cdata)
+		return;
+
+	switch (cdata->cs_type) {
+	case ATH79_SPI_CS_TYPE_INTERNAL:
+		/* nothing to do */
+		break;
+	case ATH79_SPI_CS_TYPE_GPIO:
+		gpio_free(cdata->cs_line);
+		break;
+	}
+}
+
+#ifdef CONFIG_OF
+static struct ath79_spi_controller_data ath79_spi_of_cdata;
+static int ath79_spi_of_cdata_setup(struct spi_device *spi)
+{
+	u32 cdata[3];
+
+	if (!spi->dev.of_node)
+		return -EINVAL;
+
+	if (!of_property_read_u32_array(spi->dev.of_node,
+				"spi-controller-data", cdata, 3)) {
+		ath79_spi_of_cdata.is_flash = cdata[0];
+		ath79_spi_of_cdata.cs_type = cdata[1];
+		ath79_spi_of_cdata.cs_line = cdata[2];
+		spi->controller_data = &ath79_spi_of_cdata;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+#else
+static int ath79_spi_of_cdata_setup(struct spi_device *spi)
+{
+    return -EINVAL;
+}
+#endif
+
 static int ath79_spi_setup(struct spi_device *spi)
 {
 	int status = 0;
 
+	if (spi->controller_data == NULL &&
+			ath79_spi_of_cdata_setup(spi))
+		return -EINVAL;
+
 	if (spi->bits_per_word > 32)
 		return -EINVAL;
 
@@ -184,7 +260,11 @@
 
 		/* setup MSB (to slave) on trailing edge */
 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_delay(sp, nsecs);
 		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+		ath79_spi_delay(sp, nsecs);
+		if (bits == 1)
+			ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
 
 		word <<= 1;
 	}
@@ -192,14 +272,215 @@
 	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
 }
 
+static u32 ath79_spi_txrx_mode1(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	u32 readword = 0;
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
+		ath79_spi_delay(sp, nsecs);
+		readword <<= 1;
+		readword |= gpio_get_value(sp->miso_line);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_delay(sp, nsecs);
+
+		word <<= 1;
+	}
+
+	return readword;
+}
+
+static u32 ath79_spi_txrx_mode2(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	u32 readword = 0;
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_delay(sp, nsecs);
+		readword <<= 1;
+		readword |= gpio_get_value(sp->miso_line);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out & ~AR71XX_SPI_IOC_CLK);
+		ath79_spi_delay(sp, nsecs);
+		if (bits == 1)
+			ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+
+		word <<= 1;
+	}
+
+	return readword;
+}
+
+static u32 ath79_spi_txrx_mode3(struct spi_device *spi, unsigned nsecs,
+			       u32 word, u8 bits)
+{
+	u32 readword = 0;
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	u32 ioc = sp->ioc_base;
+
+	/* clock starts at inactive polarity */
+	for (word <<= (32 - bits); likely(bits); bits--) {
+		u32 out;
+
+		if (word & (1 << 31))
+			out = ioc | AR71XX_SPI_IOC_DO;
+		else
+			out = ioc & ~AR71XX_SPI_IOC_DO;
+
+		/* setup MSB (to slave) on trailing edge */
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out & ~AR71XX_SPI_IOC_CLK);
+		ath79_spi_delay(sp, nsecs);
+		readword <<= 1;
+		readword |= gpio_get_value(sp->miso_line);
+		ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
+		ath79_spi_delay(sp, nsecs);
+
+		word <<= 1;
+	}
+
+	return readword;
+}
+
+static int ath79_spi_do_read_flash_data(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+
+	/* disable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
+
+	memcpy_fromio(t->rx_buf, sp->base + sp->read_addr, t->len);
+
+	/* enable GPIO mode */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
+
+	/* restore IOC register */
+	ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
+
+	return t->len;
+}
+
+static int ath79_spi_do_read_flash_cmd(struct spi_device *spi,
+				       struct spi_transfer *t)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	int len;
+	const u8 *p;
+
+	sp->read_addr = 0;
+
+	len = t->len - 1;
+	p = t->tx_buf;
+
+	while (len--) {
+		p++;
+		sp->read_addr <<= 8;
+		sp->read_addr |= *p;
+	}
+
+	return t->len;
+}
+
+static bool ath79_spi_is_read_cmd(struct spi_device *spi,
+				 struct spi_transfer *t)
+{
+	return t->type == SPI_TRANSFER_FLASH_READ_CMD;
+}
+
+static bool ath79_spi_is_data_read(struct spi_device *spi,
+				  struct spi_transfer *t)
+{
+	return t->type == SPI_TRANSFER_FLASH_READ_DATA;
+}
+
+static int ath79_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	int ret;
+
+	switch (sp->state) {
+	case ATH79_SPI_STATE_WAIT_CMD:
+		if (ath79_spi_is_read_cmd(spi, t)) {
+			ret = ath79_spi_do_read_flash_cmd(spi, t);
+			sp->state = ATH79_SPI_STATE_WAIT_READ;
+		} else {
+			ret = spi_bitbang_bufs(spi, t);
+		}
+		break;
+
+	case ATH79_SPI_STATE_WAIT_READ:
+		if (ath79_spi_is_data_read(spi, t)) {
+			ret = ath79_spi_do_read_flash_data(spi, t);
+		} else {
+			dev_warn(&spi->dev, "flash data read expected\n");
+			ret = -EIO;
+		}
+		sp->state = ATH79_SPI_STATE_WAIT_CMD;
+		break;
+
+	default:
+		BUG();
+	}
+
+	return ret;
+}
+
+static int ath79_spi_setup_transfer(struct spi_device *spi,
+				    struct spi_transfer *t)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+	struct ath79_spi_controller_data *cdata;
+	int ret;
+
+	ret = spi_bitbang_setup_transfer(spi, t);
+	if (ret)
+		return ret;
+
+	cdata = spi->controller_data;
+	if (cdata->is_flash)
+		sp->bitbang.txrx_bufs = ath79_spi_txrx_bufs;
+	else
+		sp->bitbang.txrx_bufs = spi_bitbang_bufs;
+
+	return ret;
+}
+
 static __devinit int ath79_spi_probe(struct platform_device *pdev)
 {
 	struct spi_master *master;
 	struct ath79_spi *sp;
 	struct ath79_spi_platform_data *pdata;
 	struct resource	*r;
+	unsigned long rate;
 	int ret;
 
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -EINVAL;
+
 	master = spi_alloc_master(&pdev->dev, sizeof(*sp));
 	if (master == NULL) {
 		dev_err(&pdev->dev, "failed to allocate spi master\n");
@@ -209,22 +490,24 @@
 	sp = spi_master_get_devdata(master);
 	platform_set_drvdata(pdev, sp);
 
-	pdata = pdev->dev.platform_data;
+	sp->state = ATH79_SPI_STATE_WAIT_CMD;
 
 	master->setup = ath79_spi_setup;
 	master->cleanup = ath79_spi_cleanup;
-	if (pdata) {
-		master->bus_num = pdata->bus_num;
-		master->num_chipselect = pdata->num_chipselect;
-	} else {
-		master->bus_num = -1;
-		master->num_chipselect = 1;
-	}
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->num_chipselect;
+	master->dev.parent = &pdev->dev;
+	master->dev.of_node = pdev->dev.of_node;
+
+	sp->miso_line = pdata->miso_line;
 
 	sp->bitbang.master = spi_master_get(master);
 	sp->bitbang.chipselect = ath79_spi_chipselect;
 	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
-	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+	sp->bitbang.txrx_word[SPI_MODE_1] = ath79_spi_txrx_mode1;
+	sp->bitbang.txrx_word[SPI_MODE_2] = ath79_spi_txrx_mode2;
+	sp->bitbang.txrx_word[SPI_MODE_3] = ath79_spi_txrx_mode3;
+	sp->bitbang.setup_transfer = ath79_spi_setup_transfer;
 	sp->bitbang.flags = SPI_CS_HIGH;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -239,12 +522,40 @@
 		goto err_put_master;
 	}
 
+	sp->clk = clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(sp->clk)) {
+		ret = PTR_ERR(sp->clk);
+		goto err_unmap;
+	}
+
+	ret = clk_enable(sp->clk);
+	if (ret)
+		goto err_clk_put;
+
+	sp->ahb_rate = clk_get_rate(sp->clk);
+	rate = DIV_ROUND_UP(sp->ahb_rate, MHZ);
+	if (!rate) {
+		ret = -EINVAL;
+		goto err_clk_disable;
+	}
+
+	sp->rrw_delay = ATH79_SPI_RRW_DELAY_FACTOR / rate;
+	dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
+		sp->rrw_delay);
+
+	ath79_spi_enable(sp);
 	ret = spi_bitbang_start(&sp->bitbang);
 	if (ret)
-		goto err_unmap;
+		goto err_disable;
 
 	return 0;
 
+err_disable:
+	ath79_spi_disable(sp);
+err_clk_disable:
+	clk_disable(sp->clk);
+err_clk_put:
+	clk_put(sp->clk);
 err_unmap:
 	iounmap(sp->base);
 err_put_master:
@@ -254,21 +565,34 @@
 	return ret;
 }
 
-static __devexit int ath79_spi_remove(struct platform_device *pdev)
+static void __ath79_spi_remove(struct platform_device *pdev)
 {
 	struct ath79_spi *sp = platform_get_drvdata(pdev);
 
 	spi_bitbang_stop(&sp->bitbang);
+	ath79_spi_disable(sp);
+	clk_disable(sp->clk);
+	clk_put(sp->clk);
 	iounmap(sp->base);
 	platform_set_drvdata(pdev, NULL);
 	spi_master_put(sp->bitbang.master);
+}
 
+static __devexit int ath79_spi_remove(struct platform_device *pdev)
+{
+	__ath79_spi_remove(pdev);
 	return 0;
 }
 
+static void ath79_spi_shutdown(struct platform_device *pdev)
+{
+	__ath79_spi_remove(pdev);
+}
+
 static struct platform_driver ath79_spi_driver = {
 	.probe		= ath79_spi_probe,
 	.remove		= __devexit_p(ath79_spi_remove),
+	.shutdown	= ath79_spi_shutdown,
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index aef59b1..c516e20 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -234,13 +234,14 @@
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
 
-static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
+int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct spi_bitbang_cs	*cs = spi->controller_state;
 	unsigned		nsecs = cs->nsecs;
 
 	return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
 }
+EXPORT_SYMBOL_GPL(spi_bitbang_bufs);
 
 /*----------------------------------------------------------------------*/
 
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index e4f60e2..4ddfcf1 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -25,11 +25,19 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include <asm/div64.h>
+
 #include <asm/mach-ath79/ar933x_uart.h>
 #include <asm/mach-ath79/ar933x_uart_platform.h>
 
 #define DRIVER_NAME "ar933x-uart"
 
+#define AR933X_UART_MAX_SCALE	0xff
+#define AR933X_UART_MAX_STEP	0xffff
+
+#define AR933X_UART_MIN_BAUD	300
+#define AR933X_UART_MAX_BAUD	3000000
+
 #define AR933X_DUMMY_STATUS_RD	0x01
 
 static struct uart_driver ar933x_uart_driver;
@@ -37,6 +45,8 @@
 struct ar933x_uart_port {
 	struct uart_port	port;
 	unsigned int		ier;	/* shadow Interrupt Enable Register */
+	unsigned int		min_baud;
+	unsigned int		max_baud;
 };
 
 static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -162,6 +172,57 @@
 {
 }
 
+/*
+ * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
+ */
+static unsigned long ar933x_uart_get_baud(unsigned int clk,
+					  unsigned int scale,
+					  unsigned int step)
+{
+	u64 t;
+	u32 div;
+
+	div = (2 << 16) * (scale + 1);
+	t = clk;
+	t *= step;
+	t += (div / 2);
+	do_div(t, div);
+
+	return t;
+}
+
+static void ar933x_uart_get_scale_step(unsigned int clk,
+				       unsigned int baud,
+				       unsigned int *scale,
+				       unsigned int *step)
+{
+	unsigned int tscale;
+	long min_diff;
+
+	*scale = 0;
+	*step = 0;
+
+	min_diff = baud;
+	for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
+		u64 tstep;
+		int diff;
+
+		tstep = baud * (tscale + 1);
+		tstep *= (2 << 16);
+		do_div(tstep, clk);
+
+		if (tstep > AR933X_UART_MAX_STEP)
+			break;
+
+		diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
+		if (diff < min_diff) {
+			min_diff = diff;
+			*scale = tscale;
+			*step = tstep;
+		}
+	}
+}
+
 static void ar933x_uart_set_termios(struct uart_port *port,
 				    struct ktermios *new,
 				    struct ktermios *old)
@@ -169,7 +230,7 @@
 	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
 	unsigned int cs;
 	unsigned long flags;
-	unsigned int baud, scale;
+	unsigned int baud, scale, step;
 
 	/* Only CS8 is supported */
 	new->c_cflag &= ~CSIZE;
@@ -191,8 +252,8 @@
 	/* Mark/space parity is not supported */
 	new->c_cflag &= ~CMSPAR;
 
-	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
-	scale = (port->uartclk / (16 * baud)) - 1;
+	baud = uart_get_baud_rate(port, new, old, up->min_baud, up->max_baud);
+	ar933x_uart_get_scale_step(port->uartclk, baud, &scale, &step);
 
 	/*
 	 * Ok, we're now changing the port state. Do it with
@@ -200,6 +261,10 @@
 	 */
 	spin_lock_irqsave(&up->port.lock, flags);
 
+	/* disable the UART */
+	ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+		      AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S);
+
 	/* Update the per-port timeout. */
 	uart_update_timeout(port, new->c_cflag, baud);
 
@@ -210,7 +275,7 @@
 		up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
 
 	ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
-			  scale << AR933X_UART_CLOCK_SCALE_S | 8192);
+			  scale << AR933X_UART_CLOCK_SCALE_S | step);
 
 	/* setup configuration register */
 	ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
@@ -219,6 +284,11 @@
 	ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
 			    AR933X_UART_CS_HOST_INT_EN);
 
+	/* reenable the UART */
+	ar933x_uart_rmw(up, AR933X_UART_CS_REG,
+		        AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+		        AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
+
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
 	if (tty_termios_baud_rate(new))
@@ -401,6 +471,8 @@
 static int ar933x_uart_verify_port(struct uart_port *port,
 				   struct serial_struct *ser)
 {
+	struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
+
 	if (ser->type != PORT_UNKNOWN &&
 	    ser->type != PORT_AR933X)
 		return -EINVAL;
@@ -408,7 +480,8 @@
 	if (ser->irq < 0 || ser->irq >= NR_IRQS)
 		return -EINVAL;
 
-	if (ser->baud_base < 28800)
+	if (ser->baud_base < up->min_baud ||
+	    ser->baud_base > up->max_baud)
 		return -EINVAL;
 
 	return 0;
@@ -561,6 +634,7 @@
 	struct uart_port *port;
 	struct resource *mem_res;
 	struct resource *irq_res;
+	unsigned int baud;
 	int id;
 	int ret;
 
@@ -611,6 +685,12 @@
 	port->fifosize = AR933X_UART_FIFO_SIZE;
 	port->ops = &ar933x_uart_ops;
 
+	baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
+	up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
+
+	baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
+	up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
+
 	ar933x_uart_add_console_port(up);
 
 	ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 353cdd4..ed33da2 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -218,11 +218,15 @@
 	  support.
 
 config USB_EHCI_ATH79
-	bool "EHCI support for AR7XXX/AR9XXX SoCs"
+	bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)"
 	depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
 	select USB_EHCI_ROOT_HUB_TT
+	select USB_EHCI_HCD_PLATFORM
 	default y
 	---help---
+	  This option is deprecated now and the driver was removed, use
+	  USB_EHCI_HCD_PLATFORM instead.
+
 	  Enables support for the built-in EHCI controller present
 	  on the Atheros AR7XXX/AR9XXX SoCs.
 
@@ -312,10 +316,14 @@
 	  OMAP3 and later chips.
 
 config USB_OHCI_ATH79
-	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs"
+	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)"
 	depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
+	select USB_OHCI_HCD_PLATFORM
 	default y
 	help
+	  This option is deprecated now and the driver was removed, use
+	  USB_OHCI_HCD_PLATFORM instead.
+
 	  Enables support for the built-in OHCI controller present on the
 	  Atheros AR71XX/AR7240 SoCs.
 
@@ -393,6 +401,26 @@
 	  Enable support for the CNS3XXX SOC's on-chip OHCI controller.
 	  It is needed for low-speed USB 1.0 device support.
 
+config USB_OHCI_HCD_PLATFORM
+	bool "Generic OHCI driver for a platform device"
+	depends on USB_OHCI_HCD && EXPERIMENTAL
+	default n
+	---help---
+	  Adds an OHCI host driver for a generic platform device, which
+	  provieds a memory space and an irq.
+
+	  If unsure, say N.
+
+config USB_EHCI_HCD_PLATFORM
+	bool "Generic EHCI driver for a platform device"
+	depends on USB_EHCI_HCD && EXPERIMENTAL
+	default n
+	---help---
+	  Adds an EHCI host driver for a generic platform device, which
+	  provieds a memory space and an irq.
+
+	  If unsure, say N.
+
 config USB_OHCI_BIG_ENDIAN_DESC
 	bool
 	depends on USB_OHCI_HCD
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
deleted file mode 100644
index f1424f9..0000000
--- a/drivers/usb/host/ehci-ath79.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller.
- *
- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
- *	Copyright (C) 2007 Atheros Communications, Inc.
- *
- *  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.
- */
-
-#include <linux/platform_device.h>
-
-enum {
-	EHCI_ATH79_IP_V1 = 0,
-	EHCI_ATH79_IP_V2,
-};
-
-static const struct platform_device_id ehci_ath79_id_table[] = {
-	{
-		.name		= "ar71xx-ehci",
-		.driver_data	= EHCI_ATH79_IP_V1,
-	},
-	{
-		.name		= "ar724x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		.name		= "ar913x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		.name		= "ar933x-ehci",
-		.driver_data	= EHCI_ATH79_IP_V2,
-	},
-	{
-		/* terminating entry */
-	},
-};
-
-MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table);
-
-static int ehci_ath79_init(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-	struct platform_device *pdev = to_platform_device(hcd->self.controller);
-	const struct platform_device_id *id;
-	int ret;
-
-	id = platform_get_device_id(pdev);
-	if (!id) {
-		dev_err(hcd->self.controller, "missing device id\n");
-		return -EINVAL;
-	}
-
-	switch (id->driver_data) {
-	case EHCI_ATH79_IP_V1:
-		ehci->has_synopsys_hc_bug = 1;
-
-		ehci->caps = hcd->regs;
-		ehci->regs = hcd->regs +
-			HC_LENGTH(ehci,
-				  ehci_readl(ehci, &ehci->caps->hc_capbase));
-		break;
-
-	case EHCI_ATH79_IP_V2:
-		hcd->has_tt = 1;
-
-		ehci->caps = hcd->regs + 0x100;
-		ehci->regs = hcd->regs + 0x100 +
-			HC_LENGTH(ehci,
-				  ehci_readl(ehci, &ehci->caps->hc_capbase));
-		break;
-
-	default:
-		BUG();
-	}
-
-	dbg_hcs_params(ehci, "reset");
-	dbg_hcc_params(ehci, "reset");
-	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
-	ehci->sbrn = 0x20;
-
-	ehci_reset(ehci);
-
-	ret = ehci_init(hcd);
-	if (ret)
-		return ret;
-
-	ehci_port_power(ehci, 0);
-
-	return 0;
-}
-
-static const struct hc_driver ehci_ath79_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Atheros built-in EHCI controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
-
-	.reset			= ehci_ath79_init,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.shutdown		= ehci_shutdown,
-
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-
-	.get_frame_number	= ehci_get_frame,
-
-	.hub_status_data	= ehci_hub_status_data,
-	.hub_control		= ehci_hub_control,
-
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
-static int ehci_ath79_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no IRQ specified\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no base address specified\n");
-		return -ENODEV;
-	}
-
-	hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev,
-			     dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	hcd->rsrc_start	= res->start;
-	hcd->rsrc_len	= resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		ret = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto err_release_region;
-	}
-
-	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (ret)
-		goto err_iounmap;
-
-	return 0;
-
-err_iounmap:
-	iounmap(hcd->regs);
-
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_put_hcd:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ehci_ath79_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ehci_ath79_driver = {
-	.probe		= ehci_ath79_probe,
-	.remove		= ehci_ath79_remove,
-	.id_table	= ehci_ath79_id_table,
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "ath79-ehci",
-	}
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci");
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8b80ea6..5f39816 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1356,11 +1356,6 @@
 #define PLATFORM_DRIVER		s5p_ehci_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_ATH79
-#include "ehci-ath79.c"
-#define PLATFORM_DRIVER		ehci_ath79_driver
-#endif
-
 #ifdef CONFIG_SPARC_LEON
 #include "ehci-grlib.c"
 #define PLATFORM_DRIVER		ehci_grlib_driver
@@ -1381,6 +1376,11 @@
 #define        PLATFORM_DRIVER         ehci_mv_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_PLATFORM
+#include "ehci-platform.c"
+#define PLATFORM_DRIVER		ehci_platform_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
new file mode 100644
index 0000000..82c1eb8
--- /dev/null
+++ b/drivers/usb/host/ehci-platform.c
@@ -0,0 +1,196 @@
+/*
+ * Generic platform ehci driver
+ *
+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
+ * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Derived from the ohci-ssb driver
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ *
+ * Derived from the EHCI-PCI driver
+ * Copyright (c) 2000-2004 by David Brownell
+ *
+ * Derived from the ohci-pci driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/ehci_pdriver.h>
+
+static int ehci_platform_reset(struct usb_hcd *hcd)
+{
+	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+	struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	hcd->has_tt = pdata->has_tt;
+	ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
+
+	ehci->caps = hcd->regs + pdata->caps_offset;
+	retval = ehci_setup(hcd);
+	if (retval)
+		return retval;
+
+	if (pdata->port_power_on)
+		ehci_port_power(ehci, 1);
+	if (pdata->port_power_off)
+		ehci_port_power(ehci, 0);
+
+	return 0;
+}
+
+static const struct hc_driver ehci_platform_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Generic Platform EHCI Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	.reset			= ehci_platform_reset,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	.get_frame_number	= ehci_get_frame,
+
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+#if defined(CONFIG_PM)
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static int __devinit ehci_platform_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	int irq;
+	int err = -ENOMEM;
+
+	BUG_ON(!dev->dev.platform_data);
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		pr_err("no irq provieded");
+		return irq;
+	}
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res_mem) {
+		pr_err("no memory recourse provieded");
+		return -ENXIO;
+	}
+
+	hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
+			     dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_err("controller already in use");
+		err = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs)
+		goto err_release_region;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_iounmap;
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int __devexit ehci_platform_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ehci_platform_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	bool wakeup = device_may_wakeup(dev);
+
+	ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup);
+	return 0;
+}
+
+static int ehci_platform_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
+	return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ehci_platform_suspend	NULL
+#define ehci_platform_resume	NULL
+#endif /* CONFIG_PM */
+
+static const struct platform_device_id ehci_platform_table[] = {
+	{ "ehci-platform", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, ehci_platform_table);
+
+static const struct dev_pm_ops ehci_platform_pm_ops = {
+	.suspend	= ehci_platform_suspend,
+	.resume		= ehci_platform_resume,
+};
+
+static struct platform_driver ehci_platform_driver = {
+	.id_table	= ehci_platform_table,
+	.probe		= ehci_platform_probe,
+	.remove		= __devexit_p(ehci_platform_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ehci-platform",
+		.pm	= &ehci_platform_pm_ops,
+	}
+};
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c
deleted file mode 100644
index 18d574d..0000000
--- a/drivers/usb/host/ohci-ath79.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  OHCI HCD (Host Controller Driver) for USB.
- *
- *  Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller.
- *
- *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- *
- *  Parts of this file are based on Atheros' 2.6.15 BSP
- *	Copyright (C) 2007 Atheros Communications, Inc.
- *
- *  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.
- */
-
-#include <linux/platform_device.h>
-
-static int __devinit ohci_ath79_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ret = ohci_init(ohci);
-	if (ret < 0)
-		return ret;
-
-	ret = ohci_run(ohci);
-	if (ret < 0)
-		goto err;
-
-	return 0;
-
-err:
-	ohci_stop(hcd);
-	return ret;
-}
-
-static const struct hc_driver ohci_ath79_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Atheros built-in OHCI controller",
-	.hcd_priv_size		= sizeof(struct ohci_hcd),
-
-	.irq			= ohci_irq,
-	.flags			= HCD_USB11 | HCD_MEMORY,
-
-	.start			= ohci_ath79_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number	= ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-	.start_port_reset	= ohci_start_port_reset,
-};
-
-static int ohci_ath79_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no IRQ specified\n");
-		return -ENODEV;
-	}
-	irq = res->start;
-
-	hcd = usb_create_hcd(&ohci_ath79_hc_driver, &pdev->dev,
-			     dev_name(&pdev->dev));
-	if (!hcd)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_dbg(&pdev->dev, "no base address specified\n");
-		ret = -ENODEV;
-		goto err_put_hcd;
-	}
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		dev_dbg(&pdev->dev, "controller already in use\n");
-		ret = -EBUSY;
-		goto err_put_hcd;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_dbg(&pdev->dev, "error mapping memory\n");
-		ret = -EFAULT;
-		goto err_release_region;
-	}
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	ret = usb_add_hcd(hcd, irq, 0);
-	if (ret)
-		goto err_stop_hcd;
-
-	return 0;
-
-err_stop_hcd:
-	iounmap(hcd->regs);
-err_release_region:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err_put_hcd:
-	usb_put_hcd(hcd);
-	return ret;
-}
-
-static int ohci_ath79_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-static struct platform_driver ohci_hcd_ath79_driver = {
-	.probe		= ohci_ath79_probe,
-	.remove		= ohci_ath79_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver		= {
-		.name	= "ath79-ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ohci");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 34b9edd..380fdc0 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1111,16 +1111,16 @@
 #define PLATFORM_DRIVER		ohci_hcd_cns3xxx_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_ATH79
-#include "ohci-ath79.c"
-#define PLATFORM_DRIVER		ohci_hcd_ath79_driver
-#endif
-
 #ifdef CONFIG_CPU_XLR
 #include "ohci-xls.c"
 #define PLATFORM_DRIVER		ohci_xls_driver
 #endif
 
+#ifdef CONFIG_USB_OHCI_HCD_PLATFORM
+#include "ohci-platform.c"
+#define PLATFORM_DRIVER		ohci_platform_driver
+#endif
+
 #if	!defined(PCI_DRIVER) &&		\
 	!defined(PLATFORM_DRIVER) &&	\
 	!defined(OMAP1_PLATFORM_DRIVER) &&	\
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
new file mode 100644
index 0000000..ec5c679
--- /dev/null
+++ b/drivers/usb/host/ohci-platform.c
@@ -0,0 +1,194 @@
+/*
+ * Generic platform ohci driver
+ *
+ * Copyright 2007 Michael Buesch <m@bues.ch>
+ * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Derived from the OCHI-SSB driver
+ * Derived from the OHCI-PCI driver
+ * Copyright 1999 Roman Weissgaerber
+ * Copyright 2000-2002 David Brownell
+ * Copyright 1999 Linus Torvalds
+ * Copyright 1999 Gregory P. Smith
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/ohci_pdriver.h>
+
+static int ohci_platform_reset(struct usb_hcd *hcd)
+{
+	struct platform_device *pdev = to_platform_device(hcd->self.controller);
+	struct usb_ohci_pdata *pdata = pdev->dev.platform_data;
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int err;
+
+	if (pdata->big_endian_desc)
+		ohci->flags |= OHCI_QUIRK_BE_DESC;
+	if (pdata->big_endian_mmio)
+		ohci->flags |= OHCI_QUIRK_BE_MMIO;
+	if (pdata->no_big_frame_no)
+		ohci->flags |= OHCI_QUIRK_FRAME_NO;
+
+	ohci_hcd_init(ohci);
+	err = ohci_init(ohci);
+
+	return err;
+}
+
+static int ohci_platform_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	int err;
+
+	err = ohci_run(ohci);
+	if (err < 0) {
+		ohci_err(ohci, "can't start\n");
+		ohci_stop(hcd);
+	}
+
+	return err;
+}
+
+static const struct hc_driver ohci_platform_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Generic Platform OHCI Controller",
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
+
+	.irq			= ohci_irq,
+	.flags			= HCD_MEMORY | HCD_USB11,
+
+	.reset			= ohci_platform_reset,
+	.start			= ohci_platform_start,
+	.stop			= ohci_stop,
+	.shutdown		= ohci_shutdown,
+
+	.urb_enqueue		= ohci_urb_enqueue,
+	.urb_dequeue		= ohci_urb_dequeue,
+	.endpoint_disable	= ohci_endpoint_disable,
+
+	.get_frame_number	= ohci_get_frame,
+
+	.hub_status_data	= ohci_hub_status_data,
+	.hub_control		= ohci_hub_control,
+#ifdef	CONFIG_PM
+	.bus_suspend		= ohci_bus_suspend,
+	.bus_resume		= ohci_bus_resume,
+#endif
+
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+static int __devinit ohci_platform_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	int irq;
+	int err = -ENOMEM;
+
+	BUG_ON(!dev->dev.platform_data);
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		pr_err("no irq provieded");
+		return irq;
+	}
+
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res_mem) {
+		pr_err("no memory recourse provieded");
+		return -ENXIO;
+	}
+
+	hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
+			dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_err("controller already in use");
+		err = -EBUSY;
+		goto err_put_hcd;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs)
+		goto err_release_region;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_iounmap;
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_iounmap:
+	iounmap(hcd->regs);
+err_release_region:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_put_hcd:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int __devexit ohci_platform_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ohci_platform_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int ohci_platform_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	ohci_finish_controller_resume(hcd);
+	return 0;
+}
+
+#else /* !CONFIG_PM */
+#define ohci_platform_suspend	NULL
+#define ohci_platform_resume	NULL
+#endif /* CONFIG_PM */
+
+static const struct platform_device_id ohci_platform_table[] = {
+	{ "ohci-platform", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, ohci_platform_table);
+
+static const struct dev_pm_ops ohci_platform_pm_ops = {
+	.suspend	= ohci_platform_suspend,
+	.resume		= ohci_platform_resume,
+};
+
+static struct platform_driver ohci_platform_driver = {
+	.id_table	= ohci_platform_table,
+	.probe		= ohci_platform_probe,
+	.remove		= __devexit_p(ohci_platform_remove),
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci-platform",
+		.pm	= &ohci_platform_pm_ops,
+	}
+};
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index 9db8083..bf79909 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -75,6 +76,15 @@
 static inline void ath79_wdt_enable(void)
 {
 	ath79_wdt_keepalive();
+
+	/*
+	 * Updating the TIMER register requires a few microseconds
+	 * on the AR934x SoCs at least. Use a small delay to ensure
+	 * that the TIMER register is updated within the hardware
+	 * before enabling the watchdog.
+	 */
+	udelay(2);
+
 	ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR);
 	/* flush write */
 	ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644
index 0000000..227c624
--- /dev/null
+++ b/include/linux/hashtable.h
@@ -0,0 +1,192 @@
+/*
+ * Statically sized hash table implementation
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits)						\
+	struct hlist_head name[1 << (bits)] =					\
+			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
+#define DECLARE_HASHTABLE(name, bits)                                   	\
+	struct hlist_head name[1 << (bits)]
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits)							\
+	(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
+{
+	unsigned int i;
+
+	for (i = 0; i < sz; i++)
+		INIT_HLIST_HEAD(&ht[i]);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key)						\
+	hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key)					\
+	hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+static inline bool hash_hashed(struct hlist_node *node)
+{
+	return !hlist_unhashed(node);
+}
+
+static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
+{
+	unsigned int i;
+
+	for (i = 0; i < sz; i++)
+		if (!hlist_empty(&ht[i]))
+			return false;
+
+	return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+	hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+	hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member)				\
+	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+		hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member)				\
+	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+		hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member)			\
+	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+		hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key)			\
+	hlist_for_each_entry(obj, node,	&name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
+ * same bucket in an rcu enabled hashtable
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key)		\
+	hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
+ * same bucket safe against removals
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)		\
+	hlist_for_each_entry_safe(obj, node, tmp,				\
+		&name[hash_min(key, HASH_BITS(name))], member)
+
+
+#endif
diff --git a/include/linux/ip.h b/include/linux/ip.h
index bd0a2a8..7a3f2d3 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -102,7 +102,7 @@
 	__be32	saddr;
 	__be32	daddr;
 	/*The options start here. */
-};
+} __packed;
 
 #ifdef __KERNEL__
 #include <linux/skbuff.h>
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 6318268..fdada3e 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -126,7 +126,7 @@
 
 	struct	in6_addr	saddr;
 	struct	in6_addr	daddr;
-};
+} __packed;
 
 #ifdef __KERNEL__
 /*
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index 3eb3143..05519a9 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -26,6 +26,8 @@
 	unsigned int		width;
 	int			(*init)(struct platform_device *);
 	void			(*exit)(struct platform_device *);
+	void			(*lock)(struct platform_device *);
+	void			(*unlock)(struct platform_device *);
 	void			(*set_vpp)(struct platform_device *, int);
 	unsigned int		nr_parts;
 	unsigned int		pfow_base;
diff --git a/include/linux/rle.h b/include/linux/rle.h
new file mode 100644
index 0000000..21cf66c
--- /dev/null
+++ b/include/linux/rle.h
@@ -0,0 +1,8 @@
+#ifndef _RLE_H_
+#define _RLE_H_
+
+int rle_decode(const unsigned char *src, size_t srclen,
+	       unsigned char *dst, size_t dstlen,
+	       size_t *src_done, size_t *dst_done);
+
+#endif /* _RLE_H_ */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4f247e2..b3df9ca 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1559,7 +1559,7 @@
  * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
  */
 #ifndef NET_SKB_PAD
-#define NET_SKB_PAD	max(48, L1_CACHE_BYTES)
+#define NET_SKB_PAD	max(32, L1_CACHE_BYTES)
 #endif
 
 extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
diff --git a/include/linux/spi/flash.h b/include/linux/spi/flash.h
index 3f22932..20d1c3d 100644
--- a/include/linux/spi/flash.h
+++ b/include/linux/spi/flash.h
@@ -24,7 +24,9 @@
 	unsigned int	nr_parts;
 
 	char		*type;
+	const char	**part_probes;
 
+	size_t		max_read_len;
 	/* we'll likely add more ... use JEDEC IDs, etc */
 };
 
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index f9e30a5..2901d35 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -406,6 +406,12 @@
 
 /*---------------------------------------------------------------------------*/
 
+enum spi_transfer_type {
+	SPI_TRANSFER_GENERIC = 0,
+	SPI_TRANSFER_FLASH_READ_CMD,
+	SPI_TRANSFER_FLASH_READ_DATA,
+};
+
 /*
  * I/O INTERFACE between SPI controller and protocol drivers
  *
@@ -503,9 +509,12 @@
 	dma_addr_t	rx_dma;
 
 	unsigned	cs_change:1;
+	unsigned	verify:1;
+	unsigned	fast_write:1;
 	u8		bits_per_word;
 	u16		delay_usecs;
 	u32		speed_hz;
+	enum spi_transfer_type type;
 
 	struct list_head transfer_list;
 };
@@ -544,6 +553,7 @@
 	struct spi_device	*spi;
 
 	unsigned		is_dma_mapped:1;
+	unsigned		fast_read:1;
 
 	/* REVISIT:  we might want a flag affecting the behavior of the
 	 * last transfer ... allowing things like "read 16 bit length L"
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index f987a2b..1443e4a 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -44,6 +44,7 @@
 extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
 				      struct spi_transfer *t);
+extern int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t);
 
 /* start or stop queue processing */
 extern int spi_bitbang_start(struct spi_bitbang *spi);
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 3c7ffdb..e48536a 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -54,7 +54,7 @@
 	__be16	window;
 	__sum16	check;
 	__be16	urg_ptr;
-};
+} __packed;
 
 /*
  *	The union cast uses a gcc extension to avoid aliasing problems
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 03f72a2..ea34ce7 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -24,7 +24,7 @@
 	__be16	dest;
 	__be16	len;
 	__sum16	check;
-};
+} __packed;
 
 /* UDP socket options */
 #define UDP_CORK	1	/* Never send partially complete segments */
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
new file mode 100644
index 0000000..1894f42
--- /dev/null
+++ b/include/linux/usb/ehci_pdriver.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __USB_CORE_EHCI_PDRIVER_H
+#define __USB_CORE_EHCI_PDRIVER_H
+
+/**
+ * struct usb_ehci_pdata - platform_data for generic ehci driver
+ *
+ * @caps_offset:	offset of the EHCI Capability Registers to the start of
+ *			the io memory region provided to the driver.
+ * @has_tt:		set to 1 if TT is integrated in root hub.
+ * @port_power_on:	set to 1 if the controller needs a power up after
+ *			initialization.
+ * @port_power_off:	set to 1 if the controller needs to be powered down
+ *			after initialization.
+ *
+ * These are general configuration options for the EHCI controller. All of
+ * these options are activating more or less workarounds for some hardware.
+ */
+struct usb_ehci_pdata {
+	int		caps_offset;
+	unsigned	has_tt:1;
+	unsigned	has_synopsys_hc_bug:1;
+	unsigned	big_endian_desc:1;
+	unsigned	big_endian_mmio:1;
+	unsigned	port_power_on:1;
+	unsigned	port_power_off:1;
+};
+
+#endif /* __USB_CORE_EHCI_PDRIVER_H */
diff --git a/include/linux/usb/ohci_pdriver.h b/include/linux/usb/ohci_pdriver.h
new file mode 100644
index 0000000..2808f2a
--- /dev/null
+++ b/include/linux/usb/ohci_pdriver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __USB_CORE_OHCI_PDRIVER_H
+#define __USB_CORE_OHCI_PDRIVER_H
+
+/**
+ * struct usb_ohci_pdata - platform_data for generic ohci driver
+ *
+ * @big_endian_desc:	BE descriptors
+ * @big_endian_mmio:	BE registers
+ * @no_big_frame_no:	no big endian frame_no shift
+ *
+ * These are general configuration options for the OHCI controller. All of
+ * these options are activating more or less workarounds for some hardware.
+ */
+struct usb_ohci_pdata {
+	unsigned	big_endian_desc:1;
+	unsigned	big_endian_mmio:1;
+	unsigned	no_big_frame_no:1;
+};
+
+#endif /* __USB_CORE_OHCI_PDRIVER_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index f9c6c50..ea2a382 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -124,6 +124,9 @@
 config LZMA_DECOMPRESS
     tristate
 
+config RLE_DECOMPRESS
+	tristate
+
 #
 # These all provide a common interface (hence the apparent duplication with
 # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.)
diff --git a/lib/Makefile b/lib/Makefile
index b08cc8c..95e8737 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -85,6 +85,7 @@
 obj-$(CONFIG_RAID6_PQ) += raid6/
 obj-$(CONFIG_LZMA_COMPRESS) += lzma/
 obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/
+obj-$(CONFIG_RLE_DECOMPRESS) += rle.o
 
 lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
 lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
diff --git a/lib/rle.c b/lib/rle.c
new file mode 100644
index 0000000..84f7ce8
--- /dev/null
+++ b/lib/rle.c
@@ -0,0 +1,78 @@
+/*
+ *  RLE decoding routine
+ *
+ *  Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ *  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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rle.h>
+
+int rle_decode(const unsigned char *src, size_t srclen,
+	       unsigned char *dst, size_t dstlen,
+	       size_t *src_done, size_t *dst_done)
+{
+	size_t srcpos, dstpos;
+	int ret;
+
+	srcpos = 0;
+	dstpos = 0;
+	ret = -EINVAL;
+
+	/* sanity checks */
+	if (!src || !srclen || !dst || !dstlen)
+		goto out;
+
+	while (1) {
+		char count;
+
+		if (srcpos >= srclen)
+			break;
+
+		count = (char) src[srcpos++];
+		if (count == 0) {
+			ret = 0;
+			break;
+		}
+
+		if (count > 0) {
+			unsigned char c;
+
+			if (srcpos >= srclen)
+				break;
+
+			c = src[srcpos++];
+
+			while (count--) {
+				if (dstpos >= dstlen)
+					break;
+
+				dst[dstpos++] = c;
+			}
+		} else {
+			count *= -1;
+
+			while (count--) {
+				if (srcpos >= srclen)
+					break;
+				if (dstpos >= dstlen)
+					break;
+				dst[dstpos++] = src[srcpos++];
+			}
+		}
+	}
+
+out:
+	if (src_done)
+		*src_done = srcpos;
+	if (dst_done)
+		*dst_done = dstpos;
+
+	return ret;
+}
+
+EXPORT_SYMBOL_GPL(rle_decode);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index a88a97a..ae67054 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -59,6 +59,7 @@
 #include <linux/errqueue.h>
 #include <linux/prefetch.h>
 #include <linux/if.h>
+#include <linux/cpu.h>
 
 #include <net/protocol.h>
 #include <net/dst.h>
@@ -74,6 +75,16 @@
 
 static struct kmem_cache *skbuff_head_cache __read_mostly;
 static struct kmem_cache *skbuff_fclone_cache __read_mostly;
+static DEFINE_PER_CPU(struct sk_buff_head, recycle_list);
+/*
+ * We want to ensure that we do not include >4K size SKBs on this list for
+ * memory usage reasons.  So, we do the reverse calculation done by the stack
+ * to calculate the allocation size.  We may eventually allow multiple,
+ * different-sized recycle lists, but this handles the general case for now.
+ * 4096 - aligned(skb_shared_info) = 3904
+ */
+#define SKB_RECYCLE_SIZE	(3904 - NET_SKB_PAD)
+#define SKB_RECYCLE_MAX_SKBS	1024
 
 static void sock_pipe_buf_release(struct pipe_inode_info *pipe,
 				  struct pipe_buffer *buf)
@@ -148,6 +159,56 @@
 	BUG();
 }
 
+static inline void zero_struct(void *v, int size)
+{
+	uint32_t *s = (uint32_t *)v;
+
+	/* We assume that size is word aligned; in fact, it's constant */
+	BUG_ON((size & 3) != 0);
+
+	/*
+	 * This looks odd but we "know" size is a constant, and so the
+	 * compiler can fold away all of the conditionals.  The compiler is
+	 * pretty smart here, and can fold away the loop, too!
+	 */
+	while (size > 0) {
+		if (size >= 4)
+			s[0] = 0;
+		if (size >= 8)
+			s[1] = 0;
+		if (size >= 12)
+			s[2] = 0;
+		if (size >= 16)
+			s[3] = 0;
+		if (size >= 20)
+			s[4] = 0;
+		if (size >= 24)
+			s[5] = 0;
+		if (size >= 28)
+			s[6] = 0;
+		if (size >= 32)
+			s[7] = 0;
+		if (size >= 36)
+			s[8] = 0;
+		if (size >= 40)
+			s[9] = 0;
+		if (size >= 44)
+			s[10] = 0;
+		if (size >= 48)
+			s[11] = 0;
+		if (size >= 52)
+			s[12] = 0;
+		if (size >= 56)
+			s[13] = 0;
+		if (size >= 60)
+			s[14] = 0;
+		if (size >= 64)
+			s[15] = 0;
+		size -= 64;
+		s += 16;
+	}
+}
+
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
@@ -310,13 +371,56 @@
 struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
 		unsigned int length, gfp_t gfp_mask)
 {
+	unsigned int len;
 	struct sk_buff *skb;
 
-	skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
-	if (likely(skb)) {
-		skb_reserve(skb, NET_SKB_PAD);
-		skb->dev = dev;
+	/*
+	 * Is this a request for an skb that we might be able to pull
+	 * from the recycling list?
+	 */
+	if (likely(length <= SKB_RECYCLE_SIZE)) {
+		unsigned long flags;
+		struct sk_buff_head *h = &get_cpu_var(recycle_list);
+		local_irq_save(flags);
+		skb = __skb_dequeue(h);
+		local_irq_restore(flags);
+		put_cpu_var(recycle_list);
+		if (likely(skb)) {
+			struct skb_shared_info *shinfo;
+
+			/*
+			 * We're about to write a large amount to the skb to
+			 * zero most of the structure so prefetch the start
+			 * of the shinfo region now so it's in the D-cache
+			 * before we start to write that.
+			 */
+			prefetchw(&skb->end);
+
+			zero_struct(skb, offsetof(struct sk_buff, tail));
+			skb->data = skb->head;
+			skb_reset_tail_pointer(skb);
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+			skb->mac_header = ~0U;
+#endif
+			shinfo = skb_shinfo(skb);
+			zero_struct(shinfo, offsetof(struct skb_shared_info, dataref));
+			atomic_set(&shinfo->dataref, 1);
+
+			skb_reserve(skb, NET_SKB_PAD);
+			skb->dev = dev;
+			return skb;
+		}
 	}
+
+	len = SKB_RECYCLE_SIZE;
+	if (unlikely(length > SKB_RECYCLE_SIZE))
+		len = length;
+	skb = __alloc_skb(len + NET_SKB_PAD, gfp_mask, 0, NUMA_NO_NODE);
+	if (unlikely(skb == NULL))
+		return NULL;
+
+	skb_reserve(skb, NET_SKB_PAD);
+	skb->dev = dev;
 	return skb;
 }
 EXPORT_SYMBOL(__netdev_alloc_skb);
@@ -361,11 +465,50 @@
  */
 struct sk_buff *dev_alloc_skb(unsigned int length)
 {
+	unsigned int len;
+
+	/*
+	 * Is this a request for an skb that we might be able to pull
+	 * from the recycling list?
+	 */
+	if (likely(length <= SKB_RECYCLE_SIZE)) {
+		unsigned long flags;
+		struct sk_buff *skb;
+		struct sk_buff_head *h = &get_cpu_var(recycle_list);
+		local_irq_save(flags);
+		skb = __skb_dequeue(h);
+		local_irq_restore(flags);
+		put_cpu_var(recycle_list);
+		if (likely(skb)) {
+			struct skb_shared_info *shinfo;
+			/*
+			 * We're about to write a large amount to the skb to
+			 * zero most of the structure so prefetch the start
+			 * of the shinfo region now so it's in the D-cache
+			 * before we start to write that.
+			 */
+			prefetchw(&skb->end);
+			zero_struct(skb, offsetof(struct sk_buff, tail));
+			skb->data = skb->head;
+			skb_reset_tail_pointer(skb);
+			skb_reserve(skb, NET_SKB_PAD);
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+			skb->mac_header = ~0U;
+#endif
+			shinfo = skb_shinfo(skb);
+			zero_struct(shinfo,
+				    offsetof(struct skb_shared_info, dataref));
+			atomic_set(&shinfo->dataref, 1);
+			return skb;
+		}
+	}
+
+	len = (length <= SKB_RECYCLE_SIZE) ? SKB_RECYCLE_SIZE : length;
 	/*
 	 * There is more code here than it seems:
 	 * __dev_alloc_skb is an inline
 	 */
-	return __dev_alloc_skb(length, GFP_ATOMIC);
+	return __dev_alloc_skb(len, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(dev_alloc_skb);
 
@@ -428,7 +571,7 @@
 /*
  *	Free an skbuff by memory without cleaning the state.
  */
-static void kfree_skbmem(struct sk_buff *skb)
+static inline void kfree_skbmem(struct sk_buff *skb)
 {
 	struct sk_buff *other;
 	atomic_t *fclone_ref;
@@ -530,6 +673,31 @@
 }
 EXPORT_SYMBOL(kfree_skb);
 
+static inline bool consume_skb_can_recycle(const struct sk_buff *skb,
+					   int skb_size)
+{
+	if (unlikely(irqs_disabled()))
+		return false;
+
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY))
+		return false;
+
+	if (unlikely(skb_is_nonlinear(skb)))
+		return false;
+
+	if (unlikely(skb->fclone != SKB_FCLONE_UNAVAILABLE))
+		return false;
+
+	skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD);
+	if (unlikely(skb_end_pointer(skb) - skb->head < skb_size))
+		return false;
+
+	if (unlikely(skb_cloned(skb)))
+		return false;
+
+	return true;
+}
+
 /**
  *	consume_skb - free an skbuff
  *	@skb: buffer to free
@@ -542,12 +710,53 @@
 {
 	if (unlikely(!skb))
 		return;
+
+	prefetch(&skb->destructor);
+
 	if (likely(atomic_read(&skb->users) == 1))
 		smp_rmb();
 	else if (likely(!atomic_dec_and_test(&skb->users)))
 		return;
+
+	/*
+	 * If possible we'd like to recycle any skb rather than just free it,
+	 * but in order to do that we need to release any head state too.
+	 * We don't want to do this later because we'll be in a pre-emption
+	 * disabled state.
+	 */
+	skb_release_head_state(skb);
+
+	/*
+	 * Can we recycle this skb?  If we can then it will be much faster
+	 * for us to recycle this one later than to allocate a new one
+	 * from scratch.
+	 */
+	if (likely(consume_skb_can_recycle(skb, SKB_RECYCLE_SIZE))) {
+		unsigned long flags;
+		struct sk_buff_head *h;
+
+		h = &get_cpu_var(recycle_list);
+		local_irq_save(flags);
+		if (likely(skb_queue_len(h) < SKB_RECYCLE_MAX_SKBS)) {
+			__skb_queue_head(h, skb);
+			local_irq_restore(flags);
+			put_cpu_var(recycle_list);
+			return;
+		}
+
+		local_irq_restore(flags);
+		put_cpu_var(recycle_list);
+	}
+
 	trace_consume_skb(skb);
-	__kfree_skb(skb);
+
+	/*
+	 * We're not recycling so now we need to do the rest of what we would
+	 * have done in __kfree_skb (above and beyond the skb_release_head_state
+	 * that we already did.
+	 */
+	skb_release_data(skb);
+	kfree_skbmem(skb);
 }
 EXPORT_SYMBOL(consume_skb);
 
@@ -2962,8 +3171,23 @@
 }
 EXPORT_SYMBOL_GPL(skb_gro_receive);
 
+static int skb_cpu_callback(struct notifier_block *nfb,
+			    unsigned long action, void *ocpu)
+{
+	unsigned long oldcpu = (unsigned long)ocpu;
+
+	if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
+		struct sk_buff_head *h = &per_cpu(recycle_list, oldcpu);
+		skb_queue_purge(h);
+	}
+
+	return NOTIFY_OK;
+}
+
 void __init skb_init(void)
 {
+	int cpu;
+
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
 					      sizeof(struct sk_buff),
 					      0,
@@ -2975,6 +3199,14 @@
 						0,
 						SLAB_HWCACHE_ALIGN|SLAB_PANIC,
 						NULL);
+
+	for_each_possible_cpu(cpu) {
+		struct sk_buff_head *h = &per_cpu(recycle_list, cpu);
+		skb_queue_head_init(h);
+		printk(KERN_INFO "Initialized recycle list for cpu %d.\n", cpu);
+	}
+
+	hotcpu_notifier(skb_cpu_callback, 0);
 }
 
 /**
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 94bc260..e14de5c 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -87,7 +87,7 @@
 
 	trailer = skb_tail_pointer(skb) - 4;
 	if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 ||
-	    (trailer[3] & 0xef) != 0x00 || trailer[3] != 0x00)
+	    (trailer[2] & 0xef) != 0x00 || (trailer[3] & 0xfe) != 0x00)
 		goto out_drop;
 
 	source_port = trailer[1] & 7;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index de9da21..2704407 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -14,6 +14,7 @@
 #include <linux/skbuff.h>
 #include <linux/icmp.h>
 #include <linux/sysctl.h>
+#include <linux/unaligned/packed_struct.h>
 #include <net/route.h>
 #include <net/ip.h>
 
@@ -44,8 +45,8 @@
 	if (ap == NULL)
 		return false;
 
-	tuple->src.u3.ip = ap[0];
-	tuple->dst.u3.ip = ap[1];
+	tuple->src.u3.ip = __get_unaligned_cpu32(ap++);
+	tuple->dst.u3.ip = __get_unaligned_cpu32(ap);
 
 	return true;
 }
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 35e662d..97d05be 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -39,6 +39,7 @@
 source "sound/soc/kirkwood/Kconfig"
 source "sound/soc/mid-x86/Kconfig"
 source "sound/soc/mxs/Kconfig"
+source "sound/soc/ath79/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/s6000/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 9ea8ac8..5089f82 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
 obj-$(CONFIG_SND_SOC)	+= pxa/
+obj-$(CONFIG_SND_SOC)	+= ath79/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/