aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm63xx
diff options
context:
space:
mode:
authorblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-05 10:12:53 +0000
committerblogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73>2012-10-05 10:12:53 +0000
commit5c105d9f3fd086aff195d3849dcf847d6b0bd927 (patch)
tree1229a11f725bfa58aa7c57a76898553bb5f6654a /target/linux/brcm63xx
downloadopenwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.tar.gz
openwrt-5c105d9f3fd086aff195d3849dcf847d6b0bd927.zip
branch Attitude Adjustment
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@33625 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/brcm63xx')
-rw-r--r--target/linux/brcm63xx/Makefile27
-rw-r--r--target/linux/brcm63xx/base-files.mk5
-rwxr-xr-xtarget/linux/brcm63xx/base-files/etc/diag.sh71
-rwxr-xr-xtarget/linux/brcm63xx/base-files/etc/init.d/defconfig18
-rwxr-xr-xtarget/linux/brcm63xx/base-files/etc/uci-defaults/brcm63xx_fixcrc.sh28
-rwxr-xr-xtarget/linux/brcm63xx/base-files/etc/uci-defaults/network54
-rwxr-xr-xtarget/linux/brcm63xx/base-files/lib/brcm63xx.sh94
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/03_do_brcm63xx.sh7
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/05_failsafe_config_switch_brcm63xx15
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/05_init_interfaces_brcm63xx26
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/05_reset_button_brcm63xx16
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/15_set_preinit_interface_brcm63xx44
-rw-r--r--target/linux/brcm63xx/base-files/lib/preinit/20_failsafe_net_echo_brcm63xx12
-rw-r--r--target/linux/brcm63xx/base-files/lib/upgrade/platform.sh16
-rw-r--r--target/linux/brcm63xx/config-3.3161
-rw-r--r--target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h70
-rw-r--r--target/linux/brcm63xx/image/Makefile259
-rw-r--r--target/linux/brcm63xx/image/README.images-bcm63xx127
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/Makefile33
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.c663
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.h100
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/Makefile77
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/README55
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/decompress.c175
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/decompress.lds.in20
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/head.S155
-rw-r--r--target/linux/brcm63xx/image/lzma-loader/src/loader.lds.in17
-rw-r--r--target/linux/brcm63xx/modules.mk37
-rw-r--r--target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch36
-rw-r--r--target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch93
-rw-r--r--target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch68
-rw-r--r--target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch21
-rw-r--r--target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch26
-rw-r--r--target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch26
-rw-r--r--target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch83
-rw-r--r--target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch140
-rw-r--r--target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch243
-rw-r--r--target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch29
-rw-r--r--target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch532
-rw-r--r--target/linux/brcm63xx/patches-3.3/012-mtd-bcm63xxpart-handle-Broadcom-partition-order.patch101
-rw-r--r--target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch289
-rw-r--r--target/linux/brcm63xx/patches-3.3/014-spi-bcm63xx-don-t-use-the-stopping-state.patch68
-rw-r--r--target/linux/brcm63xx/patches-3.3/015-spi-bcm63xx-set-master-driver-mode_bits.patch24
-rw-r--r--target/linux/brcm63xx/patches-3.3/016-spi-bcm63xx-fix-bcm6348-38.patch128
-rw-r--r--target/linux/brcm63xx/patches-3.3/017-MIPS-BCM63XX-fix-BCM6368-IPSec-clock-bit.patch23
-rw-r--r--target/linux/brcm63xx/patches-3.3/018-MIPS-BCM63XX-add-support-for-ipsec-clock.patch48
-rw-r--r--target/linux/brcm63xx/patches-3.3/019-MIPS-BCM63XX-add-RNG-peripheral-definitions.patch113
-rw-r--r--target/linux/brcm63xx/patches-3.3/020-MIPS-BCM63XX-add-RNG-driver-platform_device-stub.patch71
-rw-r--r--target/linux/brcm63xx/patches-3.3/021-hw_random-add-Broadcom-BCM63xx-RNG-driver.patch229
-rw-r--r--target/linux/brcm63xx/patches-3.3/022-MIPS-BCM63XX-Move-flash-registration-out-of-board_bc.patch202
-rw-r--r--target/linux/brcm63xx/patches-3.3/023-MIPS-BCM63XX-Add-flash-type-detection.patch137
-rw-r--r--target/linux/brcm63xx/patches-3.3/024-MIPS-BCM63XX-Use-the-Chip-ID-register-for-identifyin.patch53
-rw-r--r--target/linux/brcm63xx/patches-3.3/025-MIPS-BCM63XX-Add-basic-BCM6328-support.patch590
-rw-r--r--target/linux/brcm63xx/patches-3.3/026-MIPS-BCM63XX-Move-the-PCI-initialization-into-its-ow.patch61
-rw-r--r--target/linux/brcm63xx/patches-3.3/027-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch427
-rw-r--r--target/linux/brcm63xx/patches-3.3/028-MIPS-Expose-PCIe-drivers-for-MIPS.patch28
-rw-r--r--target/linux/brcm63xx/patches-3.3/100-MIPS-BCM63XX-add-missing-include-for-bcm63xx_gpio.h.patch41
-rw-r--r--target/linux/brcm63xx/patches-3.3/101-MTD-bcm63xxpart-remove-unused-variable.patch41
-rw-r--r--target/linux/brcm63xx/patches-3.3/102-MTD-bcm63xxpart-merge-sparelen-calculation.patch33
-rw-r--r--target/linux/brcm63xx/patches-3.3/103-MTD-bcm63xxpart-make-fixed-part-length-calculation-m.patch49
-rw-r--r--target/linux/brcm63xx/patches-3.3/104-MTD-bcm63xxpart-move-the-last-curpart-to-its-correct.patch26
-rw-r--r--target/linux/brcm63xx/patches-3.3/105-MTD-bcm63xxpart-use-correct-printk-format-for-partit.patch27
-rw-r--r--target/linux/brcm63xx/patches-3.3/106-bcm63xx_watchdog_section_mismatch.patch20
-rw-r--r--target/linux/brcm63xx/patches-3.3/107-MIPS-BCM63XX-Fix-USB-IRQ-definitions-for-6328.patch26
-rw-r--r--target/linux/brcm63xx/patches-3.3/108-BCM63XX-Add-register-definitions-for-USBD-depen.patch62
-rw-r--r--target/linux/brcm63xx/patches-3.3/201-SPI-Allow-specifying-the-parsers-for-SPI-flash.patch38
-rw-r--r--target/linux/brcm63xx/patches-3.3/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch23
-rw-r--r--target/linux/brcm63xx/patches-3.3/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch92
-rw-r--r--target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch116
-rw-r--r--target/linux/brcm63xx/patches-3.3/301-led_count.patch41
-rw-r--r--target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch25
-rw-r--r--target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch33
-rw-r--r--target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch61
-rw-r--r--target/linux/brcm63xx/patches-3.3/305-missing_ext_irq_bits.patch96
-rw-r--r--target/linux/brcm63xx/patches-3.3/306-Revert-MIPS-BCM63XX-Call-board_register_device-from-.patch23
-rw-r--r--target/linux/brcm63xx/patches-3.3/307-MIPS-BCM63XX-allow-second-UART-on-BCM6328.patch22
-rw-r--r--target/linux/brcm63xx/patches-3.3/308-MIPS-BCM63XX-expose-the-HS-SPI-clock.patch48
-rw-r--r--target/linux/brcm63xx/patches-3.3/309-MIPS-BCM63XX-add-HSSPI-register-definitions.patch211
-rw-r--r--target/linux/brcm63xx/patches-3.3/310-board_leds_naming.patch267
-rw-r--r--target/linux/brcm63xx/patches-3.3/311-cfe_version_mod.patch26
-rw-r--r--target/linux/brcm63xx/patches-3.3/312-MIPS-BCM63XX-add-basic-BCM6362-support.patch497
-rw-r--r--target/linux/brcm63xx/patches-3.3/313-MIPS-BCM63XX-enable-pcie-for-BCM6362.patch110
-rw-r--r--target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch234
-rw-r--r--target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch143
-rw-r--r--target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch241
-rw-r--r--target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch125
-rw-r--r--target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch65
-rw-r--r--target/linux/brcm63xx/patches-3.3/405-bcm963xx_real_rootfs_length.patch27
-rw-r--r--target/linux/brcm63xx/patches-3.3/406_bcm63xx_enet_vlan_incoming_fixed.patch11
-rw-r--r--target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch22
-rw-r--r--target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch169
-rw-r--r--target/linux/brcm63xx/patches-3.3/411-bcm63xx_enet-implement-reset_autoneg-ethtool.patch40
-rw-r--r--target/linux/brcm63xx/patches-3.3/412-bcm63xx_enet-use-resource_size.patch69
-rw-r--r--target/linux/brcm63xx/patches-3.3/413-bcm63xx_enet-disable-clock-when-uninitializing-devic.patch20
-rw-r--r--target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch381
-rw-r--r--target/linux/brcm63xx/patches-3.3/415-bcm63xx_enet-add-support-for-bcm6368-internal-ethern.patch1490
-rw-r--r--target/linux/brcm63xx/patches-3.3/416-bcm63xx_enet-reset-port-link-state-in-bcm_enetsw_ope.patch28
-rw-r--r--target/linux/brcm63xx/patches-3.3/417-bcm63xx_enet-don-t-overwrite-settings-when-setting-d.patch20
-rw-r--r--target/linux/brcm63xx/patches-3.3/418-bcm63xx_enet-store-the-number-of-ports-instead-of-ha.patch98
-rw-r--r--target/linux/brcm63xx/patches-3.3/419-bcm63xx_enet-store-is_sw-in-a-variable-instead-of-ch.patch73
-rw-r--r--target/linux/brcm63xx/patches-3.3/420-BCM63XX-allow-enetsw-without-tx-irq.patch69
-rw-r--r--target/linux/brcm63xx/patches-3.3/421-BCM63XX-use-port-id-for-deciding-external-phy.patch87
-rw-r--r--target/linux/brcm63xx/patches-3.3/422-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch53
-rw-r--r--target/linux/brcm63xx/patches-3.3/423-bcm63xx_enet-fix-lockup-on-BCM6328.patch93
-rw-r--r--target/linux/brcm63xx/patches-3.3/424-MIPS-BCM63XX-add-support-for-BCM6328-in-bcm_enetsw.patch103
-rw-r--r--target/linux/brcm63xx/patches-3.3/425-MIPS-BCM63XX-add-HS-SPI-platform-device-and-register.patch128
-rw-r--r--target/linux/brcm63xx/patches-3.3/426-SPI-MIPS-BCM63XX-Add-HS-SPI-driver.patch481
-rw-r--r--target/linux/brcm63xx/patches-3.3/427-MIPS-BCM63XX-Register-SPI-flash-if-present.patch102
-rw-r--r--target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-add-flash-detection-for-BCM6362.patch50
-rw-r--r--target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-move-nvram-related-functions-into-their.patch351
-rw-r--r--target/linux/brcm63xx/patches-3.3/429-MIPS-BCM63XX-export-PSI-size-from-nvram.patch44
-rw-r--r--target/linux/brcm63xx/patches-3.3/430-MTD-bcm63xxpart-use-nvram-for-PSI-size.patch29
-rw-r--r--target/linux/brcm63xx/patches-3.3/431-MTD-physmap-allow-passing-pp_data.patch41
-rw-r--r--target/linux/brcm63xx/patches-3.3/432-BCM63XX-allow-providing-fixup-data-in-board-data.patch81
-rw-r--r--target/linux/brcm63xx/patches-3.3/433-MTD-m25p80-allow-passing-pp_data.patch40
-rw-r--r--target/linux/brcm63xx/patches-3.3/434-MIPS-BCM63XX-store-the-flash-type-in-global-variable.patch122
-rw-r--r--target/linux/brcm63xx/patches-3.3/435-BCM63XX-add-a-fixup-for-ath9k-devices.patch227
-rw-r--r--target/linux/brcm63xx/patches-3.3/436-MTD-bcm63xxpart-allow-passing-a-caldata-offset.patch118
-rw-r--r--target/linux/brcm63xx/patches-3.3/437-MIPS-BCM63XX-pass-caldata-info-to-flash.patch82
-rw-r--r--target/linux/brcm63xx/patches-3.3/438-MIPS-BCM63XX-enable-USB-for-BCM6328.patch60
-rw-r--r--target/linux/brcm63xx/patches-3.3/439-MIPS-BCM63XX-wire-up-the-HS-SPI-controller-for-BCM63.patch56
-rw-r--r--target/linux/brcm63xx/patches-3.3/440-MIPS-BCM63XX-enable-SPI-controller-for-BCM6362.patch101
-rw-r--r--target/linux/brcm63xx/patches-3.3/441-MIPS-BCM63XX-enable-USB-for-BCM6362.patch84
-rw-r--r--target/linux/brcm63xx/patches-3.3/442-MIPS-BCM63XX-enable-enetsw-for-BCM6362.patch77
-rw-r--r--target/linux/brcm63xx/patches-3.3/500-board-D4PW.patch65
-rw-r--r--target/linux/brcm63xx/patches-3.3/501-board-NB4.patch640
-rw-r--r--target/linux/brcm63xx/patches-3.3/502-board-96338W2_E7T.patch49
-rw-r--r--target/linux/brcm63xx/patches-3.3/503-board-CPVA642.patch107
-rw-r--r--target/linux/brcm63xx/patches-3.3/504-board_dsl_274xb_rev_c.patch70
-rw-r--r--target/linux/brcm63xx/patches-3.3/505-board_spw500v.patch78
-rw-r--r--target/linux/brcm63xx/patches-3.3/506-board_gw6200_gw6000.patch124
-rw-r--r--target/linux/brcm63xx/patches-3.3/507-board-MAGIC.patch87
-rw-r--r--target/linux/brcm63xx/patches-3.3/508-board_hw553.patch91
-rw-r--r--target/linux/brcm63xx/patches-3.3/509-board_rta1320_16m.patch54
-rw-r--r--target/linux/brcm63xx/patches-3.3/510-board_spw303v.patch83
-rw-r--r--target/linux/brcm63xx/patches-3.3/511-board_V2500V.patch122
-rw-r--r--target/linux/brcm63xx/patches-3.3/512-board_BTV2110.patch73
-rw-r--r--target/linux/brcm63xx/patches-3.3/513-board_livebox.patch391
-rw-r--r--target/linux/brcm63xx/patches-3.3/514-board_ct536_ct5621.patch60
-rw-r--r--target/linux/brcm63xx/patches-3.3/515-board_DWV-S0_fixes.patch19
-rw-r--r--target/linux/brcm63xx/patches-3.3/516-board_96348A-122.patch78
-rw-r--r--target/linux/brcm63xx/patches-3.3/517-RTA1205W_16_uart_fixes.patch10
-rw-r--r--target/linux/brcm63xx/patches-3.3/519_board_CPVA502plus.patch55
-rw-r--r--target/linux/brcm63xx/patches-3.3/520-bcm63xx-add-support-for-96368MVWG-board.patch128
-rw-r--r--target/linux/brcm63xx/patches-3.3/521-bcm63xx-add-support-for-96368MVNgr-board.patch92
-rw-r--r--target/linux/brcm63xx/patches-3.3/522-MIPS-BCM63XX-add-96328avng-reference-board.patch102
-rw-r--r--target/linux/brcm63xx/patches-3.3/523-MIPS-BCM63XX-add-963281TAN-reference-board.patch96
-rw-r--r--target/linux/brcm63xx/patches-3.3/524-board_dsl_274xb_rev_f.patch130
-rw-r--r--target/linux/brcm63xx/patches-3.3/525-board_96348w3.patch68
-rw-r--r--target/linux/brcm63xx/patches-3.3/526-board_CT6373-1.patch136
-rw-r--r--target/linux/brcm63xx/patches-3.3/527-board_dva-g3810bn-tl-1.patch82
-rw-r--r--target/linux/brcm63xx/patches-3.3/528-board_nb6.patch146
-rw-r--r--target/linux/brcm63xx/patches-3.3/550-alice_gate2_leds.patch102
-rw-r--r--target/linux/brcm63xx/patches-3.3/551-96348gw_a_leds.patch22
-rw-r--r--target/linux/brcm63xx/patches-3.3/552-board_96348gw-10_reset_button.patch20
-rw-r--r--target/linux/brcm63xx/patches-3.3/800-wl_exports.patch34
-rw-r--r--target/linux/brcm63xx/patches-3.3/801-ssb_export_fallback_sprom.patch27
-rw-r--r--target/linux/brcm63xx/patches-3.3/802-rtl8367r_fix_RGMII_support.patch30
-rw-r--r--target/linux/brcm63xx/profiles/100-Broadcom.mk17
-rw-r--r--target/linux/brcm63xx/profiles/101-Broadcom-wl.mk19
-rw-r--r--target/linux/brcm63xx/profiles/102-Atheros.mk17
-rw-r--r--target/linux/brcm63xx/profiles/103-Ralink.mk13
-rw-r--r--target/linux/brcm63xx/profiles/104-No-WiFi.mk17
-rw-r--r--target/linux/brcm63xx/profiles/105-Broadcom-brcmsmac.mk17
-rw-r--r--target/linux/brcm63xx/profiles/200-GW6X00.mk21
165 files changed, 17852 insertions, 0 deletions
diff --git a/target/linux/brcm63xx/Makefile b/target/linux/brcm63xx/Makefile
new file mode 100644
index 000000000..098820f40
--- /dev/null
+++ b/target/linux/brcm63xx/Makefile
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=mips
+BOARD:=brcm63xx
+BOARDNAME:=Broadcom BCM63xx
+FEATURES:=squashfs jffs2 usb atm pci pcmcia
+LINUX_VERSION:=3.3.8
+MAINTAINER:=Florian Fainelli <florian@openwrt.org>
+
+include $(INCLUDE_DIR)/target.mk
+
+DEFAULT_PACKAGES += kmod-switch kmod-input-gpio-keys-polled \
+ kmod-button-hotplug
+
+define Target/Description
+ Build firmware images for Broadcom based xDSL/routers
+ currently supports BCM6338, BCM6348 and BCM6358 based devices.
+ (e.g. Inventel Livebox, Siemens SE515, Neufbox 4)
+endef
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/brcm63xx/base-files.mk b/target/linux/brcm63xx/base-files.mk
new file mode 100644
index 000000000..d6682bd38
--- /dev/null
+++ b/target/linux/brcm63xx/base-files.mk
@@ -0,0 +1,5 @@
+define Package/base-files/install-target
+ rm -f $(1)/etc/config/network
+endef
+
+
diff --git a/target/linux/brcm63xx/base-files/etc/diag.sh b/target/linux/brcm63xx/base-files/etc/diag.sh
new file mode 100755
index 000000000..d492cd553
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/etc/diag.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+#
+
+. /lib/brcm63xx.sh
+
+led_set_attr() {
+ [ -f "/sys/class/leds/$1/$2" ] && echo "$3" > "/sys/class/leds/$1/$2"
+}
+
+status_led_set_timer() {
+ led_set_attr $status_led "trigger" "timer"
+ led_set_attr $status_led "delay_on" "$1"
+ led_set_attr $status_led "delay_off" "$2"
+ [ -n "$status_led2" ] && {
+ led_set_attr $status_led2 "trigger" "timer"
+ led_set_attr $status_led2 "delay_on" "$1"
+ led_set_attr $status_led2 "delay_off" "$2"
+ }
+}
+
+status_led_set_morse() {
+ led_set_attr $status_led "trigger" "morse"
+ led_set_attr $status_led "delay" "$1"
+ led_set_attr $status_led "message" "$2"
+ [ -n "$status_led2" ] && {
+ led_set_attr $status_led2 "trigger" "morse"
+ led_set_attr $status_led2 "delay" "$1"
+ led_set_attr $status_led2 "message" "$2"
+ }
+}
+
+status_led_on() {
+ led_set_attr $status_led "trigger" "none"
+ led_set_attr $status_led "brightness" 255
+ [ -n "$status_led2" ] && {
+ led_set_attr $status_led2 "trigger" "none"
+ led_set_attr $status_led2 "brightness" 255
+ }
+}
+
+status_led_off() {
+ led_set_attr $status_led "trigger" "none"
+ led_set_attr $status_led "brightness" 0
+ [ -n "$status_led2" ] && {
+ led_set_attr $status_led2 "trigger" "none"
+ led_set_attr $status_led2 "brightness" 0
+ }
+}
+
+set_state() {
+ case "$1" in
+ preinit)
+ insmod leds-gpio
+ status_led_on
+ status_led_set_timer 200 200
+ ;;
+ failsafe)
+ status_led_set_timer 50 50
+ ;;
+ done)
+ if [ "${status_led/power}" != "$status_led" ]; then
+ status_led_on
+ else
+ status_led_off
+ fi
+ ;;
+ esac
+}
diff --git a/target/linux/brcm63xx/base-files/etc/init.d/defconfig b/target/linux/brcm63xx/base-files/etc/init.d/defconfig
new file mode 100755
index 000000000..a49c32785
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/etc/init.d/defconfig
@@ -0,0 +1,18 @@
+#!/bin/sh /etc/rc.common
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+
+START=05
+
+start() {
+ . /lib/brcm63xx.sh
+
+ [ ! -d /etc/defconfig/$board_name ] && board_name="generic"
+
+ for f in $( ls /etc/defconfig/$board_name ); do
+ if [ ! -e /etc/config/$f ]; then
+ cp /etc/defconfig/$board_name/$f /etc/config/
+ fi
+ done
+}
diff --git a/target/linux/brcm63xx/base-files/etc/uci-defaults/brcm63xx_fixcrc.sh b/target/linux/brcm63xx/base-files/etc/uci-defaults/brcm63xx_fixcrc.sh
new file mode 100755
index 000000000..f5b6d440e
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/etc/uci-defaults/brcm63xx_fixcrc.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+#
+
+. /lib/brcm63xx.sh
+
+do_fixcrc() {
+ mtd fixtrx linux
+}
+
+brcm63xx_detect
+
+case "$board_name" in
+ 96328avng |\
+ 963281TAN |\
+ "CPVA502+" |\
+ AW4339U |\
+ CPVA642 |\
+ CT6373-1 |\
+ MAGIC |\
+ V2110 |\
+ V2500V_BB)
+ do_fixcrc
+ ;;
+esac
+
diff --git a/target/linux/brcm63xx/base-files/etc/uci-defaults/network b/target/linux/brcm63xx/base-files/etc/uci-defaults/network
new file mode 100755
index 000000000..53c29ac5a
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/etc/uci-defaults/network
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+
+[ -e /etc/config/network ] && exit 0
+
+touch /etc/config/network
+
+. /lib/functions/uci-defaults.sh
+. /lib/brcm63xx.sh
+
+ucidef_set_interface_loopback
+
+case "$board_name" in
+
+96328avng |\
+963281TAN |\
+96348A-122 |\
+96358-502V |\
+CT6373-1 |\
+AW4339U |\
+CPVA642 |\
+CT536_CT5621 |\
+D-4P-W |\
+NB6 |\
+SPW303V |\
+SPW500V |\
+V2110 |\
+96348W3)
+ ucidef_set_interface_lan "eth0"
+ ;;
+
+AW4139)
+ ucidef_set_interface_lan "eth0.1"
+ ucidef_add_switch "eth0" "1" "1"
+ ucidef_add_switch_vlan "eth0" "1" "0 1 2 3 4 5t"
+ ;;
+
+DVG3810BN)
+ ucidef_set_interfaces_lan_wan "eth1.1" "eth0"
+ ucidef_add_switch "eth1" "1" "1"
+ ucidef_add_switch_vlan "eth1" "1" "0 1 2 3 4 5t"
+ ;;
+
+*)
+ ucidef_set_interfaces_lan_wan "eth1" "eth0"
+ ;;
+
+esac
+
+uci commit network
+
+exit 0
diff --git a/target/linux/brcm63xx/base-files/lib/brcm63xx.sh b/target/linux/brcm63xx/base-files/lib/brcm63xx.sh
new file mode 100755
index 000000000..11774770d
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/brcm63xx.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# Copyright (C) 2007 OpenWrt.org
+#
+#
+
+board_name=""
+status_led=""
+status_led2=""
+sys_mtd_part=""
+brcm63xx_has_reset_button=""
+
+brcm63xx_detect() {
+ board_name=$(awk 'BEGIN{FS="[ \t:/]+"} /system type/ {print $4}' /proc/cpuinfo)
+
+ if [ "$board_name" = "96358VW" ] && [ -e /proc/switch/eth1/enable ]; then
+ board_name="DVAG3810BN"
+ fi
+
+ case "$board_name" in
+ 96328avng)
+ status_led="96328avng::power"
+ ifname=eth0
+ ;;
+ 963281TAN)
+ status_led="963281TAN::power"
+ ifname=eth0
+ ;;
+ 96348GW)
+ status_led="power"
+ brcm63xx_has_reset_button="true"
+ ifname=eth1
+ ;;
+ GW6000)
+ brcm63xx_has_reset_button="true"
+ ifname=eth1
+ ;;
+ GW6200)
+ status_led="line1"
+ status_led2="tel"
+ brcm63xx_has_reset_button="true"
+ ifname=eth1
+ ;;
+ 96348GW-11)
+ status_led="power"
+ brcm63xx_has_reset_button="true"
+ ifname=eth1
+ ;;
+ CT536_CT5621)
+ status_led="power"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ SPW500V)
+ status_led="power:green"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ AW4139 |\
+ AW4339U)
+ status_led="dsl-274xb:green:power"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ 96358-502V)
+ status_led="spw303v:green:power+adsl"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ V2110)
+ status_led="V2110:power:green"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ CPVA642)
+ status_led="power:green"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ D-4P-W)
+ status_led="power:green"
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ NB6)
+ brcm63xx_has_reset_button="true"
+ ifname=eth0
+ ;;
+ *)
+ ;;
+ esac
+}
+
+brcm63xx_detect
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/03_do_brcm63xx.sh b/target/linux/brcm63xx/base-files/lib/preinit/03_do_brcm63xx.sh
new file mode 100644
index 000000000..dd60c4995
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/03_do_brcm63xx.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+do_brcm63xx() {
+ . /lib/brcm63xx.sh
+}
+
+boot_hook_add preinit_main do_brcm63xx
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/05_failsafe_config_switch_brcm63xx b/target/linux/brcm63xx/base-files/lib/preinit/05_failsafe_config_switch_brcm63xx
new file mode 100644
index 000000000..43da8cc06
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/05_failsafe_config_switch_brcm63xx
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+failsafe_ip() {
+ [ -d "/proc/switch/$ifname" ] && {
+ ifconfig "$ifname" 0.0.0.0 down
+ echo "0 1 2 3 4 ${cpu_port:-5u*}" > "/proc/switch/$ifname/vlan/0/ports"
+ }
+
+ [ -n "$pi_ifname" ] && grep -q "$pi_ifname" /proc/net/dev && {
+ ifconfig $pi_ifname $pi_ip netmask $pi_netmask broadcast $pi_broadcast up
+ }
+}
+
+boot_hook_add failsafe failsafe_ip
+
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/05_init_interfaces_brcm63xx b/target/linux/brcm63xx/base-files/lib/preinit/05_init_interfaces_brcm63xx
new file mode 100644
index 000000000..b7cbecd4f
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/05_init_interfaces_brcm63xx
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set_preinit_iface() {
+ ifname=eth1
+
+ . /lib/brcm63xx.sh
+
+ ifconfig $ifname 0.0.0.0 up
+}
+
+check_module () {
+ module="$1"; shift; params="$*"
+
+ insmod "$module" "$params"
+ sleep 1
+ grep "^$module" /proc/modules
+ return $?
+}
+
+init_iface() {
+ insmod switch-core
+ check_module switch-robo || check_module switch-adm || rmmod switch-core
+}
+
+boot_hook_add preinit_main set_preinit_iface
+boot_hook_add preinit_main init_iface
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/05_reset_button_brcm63xx b/target/linux/brcm63xx/base-files/lib/preinit/05_reset_button_brcm63xx
new file mode 100644
index 000000000..f33825f96
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/05_reset_button_brcm63xx
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. /lib/brcm63xx.sh
+
+enable_reset_button() {
+ if [ "$brcm63xx_has_reset_button" = "true" ]; then
+ insmod input-core
+ insmod input-polldev
+ insmod gpio_buttons
+ insmod button-hotplug
+ fi
+}
+
+boot_hook_add preinit_main enable_reset_button
+
+
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/15_set_preinit_interface_brcm63xx b/target/linux/brcm63xx/base-files/lib/preinit/15_set_preinit_interface_brcm63xx
new file mode 100644
index 000000000..9d366fa33
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/15_set_preinit_interface_brcm63xx
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+port_net_echo() {
+ [ -n "$pi_ifname" ] && grep -q "$pi_ifname" /proc/net/dev && {
+ if [ "$pi_preinit_net_messages" = "y" ] || [ "$pi_failsafe_net_message" = "true" ] && [ "$pi_preinit_no_failsafe_netmsg" != "y" ]; then
+ netmsg $pi_broadcast "$1"
+ fi
+ }
+}
+
+preinit_ip_deconfig() {
+ if [ -z "$pi_ifname" ]; then
+ ifconfig $ifname 0.0.0.0 down
+ else
+ grep -q "$pi_ifname" /proc/net/dev && {
+ ifconfig $pi_ifname 0.0.0.0 down
+ }
+ fi
+ [ -d "/proc/switch/$ifname" ] && {
+ echo 1 > "/proc/switch/$ifname/reset"
+ echo "0 1 2 3 4 ${cpu_port:-5u*}" > "/proc/switch/$ifname/vlan/0/ports"
+ }
+
+}
+
+preinit_net_echo() {
+ preinit_ip
+
+ [ -d "/proc/switch/$ifname" ] && {
+ echo 1 > "/proc/switch/$ifname/reset"
+
+ # this would be easier if we blasted the message across all ports
+ # but we don't want packets leaking across interfaces
+ for port in $(seq 0 4); do {
+ echo "$port ${cpu_port:-5u*}" > "/proc/switch/$ifname/vlan/0/ports"
+ port_net_echo $1
+ }; done
+
+ echo "0 ${cpu_port:-5u*}" > "/proc/switch/$ifname/vlan/0/ports"
+
+ } || port_net_echo $1
+}
+
+
diff --git a/target/linux/brcm63xx/base-files/lib/preinit/20_failsafe_net_echo_brcm63xx b/target/linux/brcm63xx/base-files/lib/preinit/20_failsafe_net_echo_brcm63xx
new file mode 100644
index 000000000..f030cb283
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/preinit/20_failsafe_net_echo_brcm63xx
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+indicate_failsafe() {
+ preinit_net_echo() {
+ port_net_echo $1
+ }
+ echo "- failsafe -"
+ preinit_net_echo "Entering Failsafe!\n"
+ indicate_failsafe_led
+}
+
+
diff --git a/target/linux/brcm63xx/base-files/lib/upgrade/platform.sh b/target/linux/brcm63xx/base-files/lib/upgrade/platform.sh
new file mode 100644
index 000000000..1a025f7d7
--- /dev/null
+++ b/target/linux/brcm63xx/base-files/lib/upgrade/platform.sh
@@ -0,0 +1,16 @@
+PART_NAME=linux
+platform_check_image() {
+ [ "$ARGC" -gt 1 ] && return 1
+ case "$(get_magic_word "$1")" in
+ 3600)
+ # 6348GW-11 boards use openwrt-96348GW-11-squashfs-cfe.bin files
+ return 0
+ ;;
+ *)
+ echo "Invalid image type. Please use only .bin files"
+ return 1
+ ;;
+ esac
+}
+
+# use default for platform_do_upgrade()
diff --git a/target/linux/brcm63xx/config-3.3 b/target/linux/brcm63xx/config-3.3
new file mode 100644
index 000000000..f8cf4869c
--- /dev/null
+++ b/target/linux/brcm63xx/config-3.3
@@ -0,0 +1,161 @@
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_AUDIT=y
+CONFIG_AUDIT_GENERIC=y
+CONFIG_BCM63XX=y
+CONFIG_BCM63XX_CPU_6328=y
+CONFIG_BCM63XX_CPU_6338=y
+CONFIG_BCM63XX_CPU_6345=y
+CONFIG_BCM63XX_CPU_6348=y
+CONFIG_BCM63XX_CPU_6358=y
+CONFIG_BCM63XX_CPU_6362=y
+CONFIG_BCM63XX_CPU_6368=y
+CONFIG_BCM63XX_ENET=y
+CONFIG_BCM63XX_PHY=y
+CONFIG_BCM63XX_WDT=y
+CONFIG_BCMA_POSSIBLE=y
+CONFIG_BOARD_BCM963XX=y
+# CONFIG_BOARD_LIVEBOX is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_CEVT_R4K=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200"
+CONFIG_CMDLINE_BOOL=y
+# CONFIG_CMDLINE_OVERRIDE is not set
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_CRAMFS=y
+CONFIG_CSRC_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_ELF_CORE=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_74X164=y
+CONFIG_GPIO_DEVICE=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HAMRADIO is not set
+CONFIG_HARDWARE_WATCHPOINTS=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HW_HAS_PCI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_BCM63XX=y
+CONFIG_HZ=250
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+CONFIG_IMAGE_CMDLINE_HACK=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_KEXEC=y
+CONFIG_LEDS_GPIO=y
+CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MIPS=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_MIPS_MACHINE is not set
+CONFIG_MIPS_MT_DISABLED=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MTD_BCM63XX_PARTS=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_BE_BYTE_SWAP=y
+# CONFIG_MTD_CFI_GEOMETRY is not set
+# CONFIG_MTD_CFI_NOSWAP is not set
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PCI=y
+# CONFIG_PCIEAER is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PHYLIB=y
+CONFIG_RTL8366_SMI=y
+CONFIG_RTL8367_PHY=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RELAY=y
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_BCM63XX=y
+CONFIG_SERIAL_BCM63XX_CONSOLE=y
+CONFIG_SPI=y
+# CONFIG_SPI_BCM63XX is not set
+CONFIG_SPI_BCM63XX_HSSPI=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_MASTER=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SSB=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_BLOCKIO=y
+# CONFIG_SSB_DRIVER_MIPS is not set
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_SPROM=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_SWCONFIG=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_USB_ARCH_HAS_XHCI=y
+CONFIG_USB_SUPPORT=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_XZ_DEC=y
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h
new file mode 100644
index 000000000..2730edc9a
--- /dev/null
+++ b/target/linux/brcm63xx/files/arch/mips/include/asm/mach-bcm63xx/bcm_tag.h
@@ -0,0 +1,70 @@
+#ifndef __BCM63XX_TAG_H
+#define __BCM63XX_TAG_H
+
+#define TAGVER_LEN 4 /* Length of Tag Version */
+#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
+#define SIG1_LEN 20 /* Company Signature 1 Length */
+#define SIG2_LEN 14 /* Company Signature 2 Lenght */
+#define BOARDID_LEN 16 /* Length of BoardId */
+#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
+#define CHIPID_LEN 6 /* Chip Id Length */
+#define IMAGE_LEN 10 /* Length of Length Field */
+#define ADDRESS_LEN 12 /* Length of Address field */
+#define DUALFLAG_LEN 2 /* Dual Image flag Length */
+#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
+#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
+#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
+#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
+#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
+#define CRC_LEN 4 /* Length of CRC in bytes */
+#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
+
+#define NUM_PIRELLI 2
+#define IMAGETAG_CRC_START 0xFFFFFFFF
+
+#define PIRELLI_BOARDS { \
+ "AGPF-S0", \
+ "DWV-S0", \
+}
+
+/*
+ * The broadcom firmware assumes the rootfs starts the image,
+ * therefore uses the rootfs start (flashImageAddress)
+ * to determine where to flash the image. Since we have the kernel first
+ * we have to give it the kernel address, but the crc uses the length
+ * associated with this address (rootLength), which is added to the kernel
+ * length (kernelLength) to determine the length of image to flash and thus
+ * needs to be rootfs + deadcode (jffs2 EOF marker)
+*/
+
+struct bcm_tag {
+ char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
+ char sig_1[SIG1_LEN]; // 4-23: Company Line 1
+ char sig_2[SIG2_LEN]; // 24-37: Company Line 2
+ char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
+ char boardid[BOARDID_LEN]; // 44-59: Board name
+ char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
+ char totalLength[IMAGE_LEN]; // 62-71: Total length of image
+ char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
+ char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
+ char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
+ char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
+ char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
+ char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
+ char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
+ char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
+ char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
+ char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT)
+ char flashLayoutVer[FLASHLAYOUTVER_LEN];// 192-195: Version flash layout
+ char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32
+ char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
+ char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
+ char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
+ char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
+ char imageSequence[4]; // 228-231: Image sequence number
+ char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
+ char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
+ char reserved2[16]; // 240-255: Unused at present
+};
+
+#endif /* __BCM63XX_TAG_H */
diff --git a/target/linux/brcm63xx/image/Makefile b/target/linux/brcm63xx/image/Makefile
new file mode 100644
index 000000000..af5a68c82
--- /dev/null
+++ b/target/linux/brcm63xx/image/Makefile
@@ -0,0 +1,259 @@
+#
+# Copyright (C) 2006-2011 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+LOADADDR = 0x80010000 # RAM start + 16M
+KERNEL_ENTRY = $(LOADADDR) # Newer kernels add a jmp to the kernel_entry at the start of the binary
+RAMSIZE = 0x01000000 # 64MB
+
+LOADER_MAKEOPTS= \
+ KDIR=$(KDIR) \
+ LOADADDR=$(LOADADDR) \
+ KERNEL_ENTRY=$(KERNEL_ENTRY) \
+ RAMSIZE=$(RAMSIZE)
+
+define trxalign/jffs2-128k
+-a 0x20000
+endef
+define trxalign/jffs2-64k
+-a 0x10000
+endef
+define trxalign/squashfs
+-a 1024
+endef
+
+define Image/LimitName16
+$(shell expr substr "$(1)" 1 16)
+endef
+
+define Image/Build/CFE
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin \
+ --boardid $(2) --chipid $(3) --entry $(KERNEL_ENTRY) \
+ --load-addr $(LOADADDR) --rsa-signature "$(5)" \
+ --info1 "-$(call Image/LimitName16,$(4))" --info2 $(1) \
+ $(6) $(7) $(8) $(9)
+endef
+
+define Image/Build/CFEFIXUP
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \
+ --boardid $(2) --chipid $(4) --entry $(KERNEL_ENTRY) \
+ --load-addr $(LOADADDR) --rsa-signature "$(6)" \
+ --info1 "+$(call Image/LimitName16,$(3))" --info2 $(1) \
+ $(7) $(8) $(9) $(10)
+endef
+
+define Image/Build/CFEHW553
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \
+ --boardid $(2) --chipid $(3) --entry $(LOADADDR) \
+ --load-addr $(LOADADDR) --tag-version 7 \
+ --block-size 0x20000 --image-offset $(4)
+endef
+
+define Image/Build/CFEAGPF
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \
+ --boardid $(2) --chipid $(3) --entry $(LOADADDR) \
+ --load-addr $(LOADADDR) --tag-version 8 \
+ --signature2 IMAGE --block-size 0x20000 \
+ --image-offset $(4) --info1 "-$(call Image/LimitName16,$(5))" --info2 $(1)
+endef
+
+define Image/Build/RG100A
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(5)-$(1)-cfe.bin \
+ --boardid $(2) --chipid $(3) --entry $(LOADADDR) \
+ --load-addr $(LOADADDR) --block-size 0x20000 \
+ --image-offset $(4) --info1 "-$(call Image/LimitName16,$(5))" --info2 $(1)
+endef
+
+define Image/Build/RedBoot
+ cp $(KDIR)/vmlinux.elf $(BIN_DIR)/openwrt-$(1)-vmlinux.elf
+ gzip -9 -c $(KDIR)/vmlinux > $(KDIR)/vmlinux.bin.gz
+ $(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/vmlinux $(KDIR)/vmlinux.bin.l7
+ dd if=$(KDIR)/vmlinux.bin.l7 of=$(BIN_DIR)/openwrt-$(1)-vmlinux.lzma bs=65536 conv=sync
+ dd if=$(KDIR)/vmlinux.bin.gz of=$(BIN_DIR)/openwrt-$(1)-vmlinux.gz bs=65536 conv=sync
+endef
+
+define Image/Build/SPW303V
+ # Generate the tagged image
+ $(STAGING_DIR_HOST)/bin/imagetag -i $(KDIR)/vmlinux.lzma.cfe -f $(KDIR)/root.$(1) \
+ --output $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin.tmp \
+ --boardid $(2) --chipid $(3) --entry $(KERNEL_ENTRY) \
+ --load-addr $(LOADADDR) --rsa-signature "$(5)" \
+ --pad 4 $(6) $(7) $(8) $(9)
+ # Fix up header
+ $(STAGING_DIR_HOST)/bin/spw303v -i $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin.tmp \
+ -o $(BIN_DIR)/openwrt-$(4)-$(1)-cfe-sysupgrade.bin
+ $(STAGING_DIR_HOST)/bin/xorimage -i $(BIN_DIR)/openwrt-$(4)-$(1)-cfe-sysupgrade.bin \
+ -o $(BIN_DIR)/openwrt-$(4)-$(1)-cfe-factory.bin
+ rm -f $(BIN_DIR)/openwrt-$(4)-$(1)-cfe.bin.tmp
+endef
+
+define Image/Build/CFEOLD
+ $(TOPDIR)/scripts/brcmImage.pl -t -p \
+ -b $(2) -c $(3) \
+ -k $(KDIR)/vmlinux.lzma.cfe \
+ -r $(KDIR)/root.$(1) \
+ -o $(BIN_DIR)/openwrt-$(2)-$(1)-cfe.bin
+endef
+
+define Build/Clean
+ $(MAKE) -C lzma-loader clean
+endef
+
+define Image/Prepare
+ # Standard LZMA kernel
+ cat $(KDIR)/vmlinux | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma
+
+ # CFE is a LZMA nazi! It took me hours to find out the parameters!
+ # Also I think lzma has a bug cause it generates different output depending on
+ # if you use stdin / stdout or not. Use files instead of stdio here, cause
+ # otherwise CFE will complain and not boot the image.
+ $(STAGING_DIR_HOST)/bin/lzma e -d22 -fb64 -a1 $(KDIR)/vmlinux $(KDIR)/vmlinux.lzma.tmp
+
+ # Strip out the length, CFE doesn't like this
+ dd if=$(KDIR)/vmlinux.lzma.tmp of=$(KDIR)/vmlinux.lzma.cfe bs=5 count=1
+ dd if=$(KDIR)/vmlinux.lzma.tmp of=$(KDIR)/vmlinux.lzma.cfe ibs=13 obs=5 skip=1 seek=1 conv=notrunc
+ rm -f $(KDIR)/vmlinux.lzma.tmp
+
+ # Build the LZMA loader
+ rm -f $(KDIR)/loader.gz
+ $(MAKE) -C lzma-loader \
+ BUILD_DIR="$(KDIR)" \
+ TARGET="$(KDIR)" \
+ clean install
+
+ echo -ne "\\x00" >> $(KDIR)/loader.gz
+ rm -f $(KDIR)/fs_mark
+ touch $(KDIR)/fs_mark
+ $(call prepare_generic_squashfs,$(KDIR)/fs_mark)
+endef
+
+define Image/Build
+ dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync
+ # Various routers
+ $(call Image/Build/CFE,$(1),96328avng,6328,96328avng-4M-flash-generic,,--pad 2)
+ $(call Image/Build/CFE,$(1),96328avng,6328,96328avng-8M-flash-generic,,--pad 4)
+ $(call Image/Build/CFE,$(1),96328avng,6328,96328avng-16M-flash-generic,,--pad 8)
+ $(call Image/Build/CFE,$(1),963281TAN,6328,963481TAN-4M-flash-generic,,--pad 2)
+ $(call Image/Build/CFE,$(1),963281TAN,6328,963481TAN-8M-flash-generic,,--pad 4)
+ $(call Image/Build/CFE,$(1),963281TAN,6328,963481TAN-16M-flash-generic,,--pad 8)
+ $(call Image/Build/CFE,$(1),96345GW2,6345,96345GW2-generic)
+ $(call Image/Build/CFE,$(1),96345GW2,6345,96348GW2-bc221,,--layoutver 5)
+ $(call Image/Build/CFE,$(1),96345GW2,6345,92345GW2-rev,OpenWRT-$(REVISION))
+ $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-generic,,)
+ $(call Image/Build/CFE,$(1),96348R,6348,96348R-generic,,)
+ $(call Image/Build/CFE,$(1),96348GW,6348,96348GW-bc221,,--layoutver 5)
+ $(call Image/Build/CFE,$(1),6338GW,6338,6338GW-generic,,)
+ $(call Image/Build/CFE,$(1),6338W,6338,6338W-generic,,)
+ $(call Image/Build/CFE,$(1),96348GW-11,6348,96348GW-11-generic)
+ $(call Image/Build/CFE,$(1),96348GW-10,6348,96348GW-10-generic)
+ $(call Image/Build/CFE,$(1),96348A-122,6348,96348A-122-generic)
+ $(call Image/Build/CFE,$(1),96358VW,6358,96358VW-generic)
+ $(call Image/Build/CFE,$(1),96358VW2,6358,96358VW2-generic)
+ $(call Image/Build/CFE,$(1),96368MVNgr,6368,96368MVNgr-generic)
+ $(call Image/Build/CFE,$(1),96368MVWG,6368,96368MVWG-generic)
+
+ # BT Voyager V210_BTR
+ $(call Image/Build/CFE,$(1),V210_BB,6348,BTV210_BTR,,--layoutver 5)
+ # BT Voyager V210_ROI, V210_WB
+ $(call Image/Build/CFE,$(1),V210,6348,BTV210_ROI_WB,,--layoutver 5)
+ # BT Voyager V2091_BTR
+ $(call Image/Build/CFE,$(1),V2091_BB,6348,BTV2091_BTR,,--layoutver 5)
+ # BT Voyager V2091_ROI, V2091_WB
+ $(call Image/Build/CFE,$(1),V2091,6348,BTV2091_ROI_WB,,--layoutver 5)
+ # BT Voyager V220V, V220V_MGCP_BTR
+ $(call Image/Build/CFE,$(1),RTA1052V,6348,BTV220V_MGCP_BTR,,--layoutver 5)
+ # BT Voyager V2110, V2110_AA, V2110_ROI
+ $(call Image/Build/CFE,$(1),V2110,6348,BTV2110,,--layoutver 5)
+ # BT Voyager V2500V, V2500V_SIP_CLUB, V2500V_AA
+ $(call Image/Build/CFE,$(1),V2500V_BB,6348,BTV2500V,,--layoutver 5)
+ # RTA1025W_16 (numerous routers)
+ $(call Image/Build/CFE,$(1),RTA1025W_16,6348,RTA1025W_16,,--layoutver 5)
+ # RTA1320_16M (numerous routers)
+ $(call Image/Build/CFE,$(1),RTA1320_16M,6338,RTA1320_16M,,--layoutver 5)
+ # Tecom GW6000
+ $(call Image/Build/CFEFIXUP,$(1),96348GW,GW6000,6348,GW6000)
+ # Tecom GW6200
+ $(call Image/Build/CFEFIXUP,$(1),96348GW,GW6200,6348,GW6200,$(shell printf '\x99'))
+ # Neufbox4
+ $(call Image/Build/CFE,$(1),96358VW,6358,NEUFBOX4,OpenWRT-$(REVISION))
+ # Neufbox6
+ $(call Image/Build/CFE,$(1),NB6-SER-r0,6362,NEUFBOX6,OpenWRT-$(REVISION))
+ # Comtrend 6373
+ $(call Image/Build/CFE,$(1),CT6373-1,6358,CT6373)
+ # Comtrend 536, 5621
+ $(call Image/Build/CFEFIXUP,$(1),96348GW-11,CT536_CT5621,6348,CT536_CT5621)
+ # Davolink DV201AMR
+ $(call Image/Build/CFEOLD,$(1),DV201AMR,6348)
+ # USR 9108
+ $(call Image/Build/CFE,$(1),96348GW-A,6348,USR9108)
+ # NetGear DG834GT, DG834PN
+ $(call Image/Build/CFE,$(1),96348GW-10,6348,DG834GT_DG834PN)
+ # Belkin f5d7633
+ $(call Image/Build/CFE,$(1),96348GW-10,6348,F5D7633)
+ # D-Link DSL-2640B, rev B2
+ $(call Image/Build/CFE,$(1),D-4P-W,6348,DSL2640B-B2)
+ # D-Link DSL-2650U
+ $(call Image/Build/CFE,$(1),96358VW2,6358,DSL2650U)
+ # D-Link DSL-2740B/DSL-2741B, rev C2
+ $(call Image/Build/CFEFIXUP,$(1),96358GW,AW4139,6358,DSL274XB-C2)
+ # D-Link DSL-2740B/DSL-2741B, rev C3
+ $(call Image/Build/CFE,$(1),AW4139,6358,DSL274XB-C3)
+ # D-Link DSL-2740B/DSL-2741B, rev F1
+ $(call Image/Build/CFE,$(1),AW4339U,6328,DSL274XB-F1-EU,,--signature2="4.06.01.EUF1" --pad 4)
+ $(call Image/Build/CFE,$(1),AW4339U,6328,DSL274XB-F1-AU,,--signature2="4.06.01.AUF1" --pad 4)
+ # D-Link DVA-G3810BN/TL
+ $(call Image/Build/CFEFIXUP,$(1),96358VW,DVAG3810BN,6358,DVAG3810BN)
+
+ # TP-Link TD-8810A, TD-8810B, TD-8811A, TD-8811B
+ $(call Image/Build/CFE,$(1),8L-2M-8M,6338,TP8810_8811)
+ # TP-Link 8900GB
+ $(call Image/Build/CFE,$(1),96348GW-11,6348,TD8900GB,$(shell printf 'PRID\x89\x10\x00\x02'))
+
+ # Sagem F@ST2404
+ $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404-cfe)
+ $(call Image/Build/CFE,$(1),F@ST2404,6348,F@ST2404,OpenWRT-$(REVISION))
+ # Inventel Livebox
+ $(call Image/Build/RedBoot,livebox)
+ # Pirelli Alice Gate VoIP 2 Plus Wi-Fi AGPF-S0
+ $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W-cfe)
+ $(call Image/Build/CFEAGPF,$(1),AGPF-S0,6358,0x20000,AGV2+W)
+ # Pirelli A226G
+ $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G-cfe)
+ $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x10000,A226G)
+
+ # Pirelli A226M
+ $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x20000,A226M-cfe)
+ $(call Image/Build/CFEAGPF,$(1),DWV-S0,6358,0x20000,A226M)
+
+ # RG100A,DB120 etc.
+ $(call Image/Build/RG100A,$(1),96358VW2,6358,0x20000,RG100A_DB120)
+
+ # Telsey CPVA642-type (e.g. CPA-ZNTE60T)
+ $(call Image/Build/CFE,$(1),CPVA642,6358,CPA-ZNTE60T,,--signature "Telsey Tlc",--signature2 "99.99.999",--second-image-flag "0")
+
+ # T-Com Speedport W 500V
+ $(call Image/Build/CFEFIXUP,$(1),96348GW,SPW500V,6348,SPW500V)
+
+ #HW553
+ $(call Image/Build/CFEHW553,$(1),HW553,6358,0x20000,HW553)
+
+ # T-Com Speedport W 303V Typ B
+ $(call Image/Build/SPW303V,$(1),96358-502V,6358,SPW303V)
+endef
+
+$(eval $(call BuildImage))
diff --git a/target/linux/brcm63xx/image/README.images-bcm63xx b/target/linux/brcm63xx/image/README.images-bcm63xx
new file mode 100644
index 000000000..91b6d019e
--- /dev/null
+++ b/target/linux/brcm63xx/image/README.images-bcm63xx
@@ -0,0 +1,127 @@
+The image neede to flash onto a Broadcom 63xx-series board depends on the
+board, method you are using to flash, and, for web-based flash, on the version
+of the Broadcom code your router uses.
+
+There are two major revisions of the Broadcom code as far as imagetags are
+concerned, before 3.08 and after 3.08, however there are some variations
+within in that, either due to vendor differences or due to changes at
+Broadcom (it's not clear yet which is the case). In addtion Pirelli modified
+the Broadcom code, so Alice Gate models use a different imagetag than any
+other vendor.
+
+The imagetag format for flashing via CFE is the same for almost all the
+boards, and is the same for all images generated by the imagetag utility.
+Images flashable using cfe are labelled openwrt-<board>-<filesystem>-cfe.bin
+
+The imagetags for tftp/ftp flashing is based on Broadcom 3.00-3.04 imagetags
+and is known to be correct as the source code GPL and is available for reading.
+
+Broadcom code 2.21 is based on the BT Voyager firmware image I looked at. It
+may in fact be BT Voyager-specific. 2.21 is actually more difficult to deal
+with the imagetag from 3.00 as it has three different CRC calculations in
+addtition to the header CRC.
+
+Broadcom 3.00-3.02 flashing has been tested on Comtrend CT-5261, CT-536 and
+Tecom GW6000, and is the version of the flashing that was present before the
+imagetags were split by broadcom code version (early June 2009)
+
+3.04 is guessed to be the same as 3.00-3.02 based on available information
+
+Broadom 3.06 is thought to be the same as 3.00-3.02, however the only 3.06
+this author (Daniel Dickinson) has seen is the Alice Gate (Pirelli) firmware
+which is known to be different due to vendor (Pirelli) modifications to the
+Broadcom code.
+
+Broadcom 3.10 uses an imagetag that is believed to apply to all 3.10 and 3.12
+versions, and has been tested on the Tecom GW6200. This version introdec changes to
+the imagetag to deal with TR69 (a remote rouer management system developed by the
+DSL forum). There is a field for vendor-specific information, that at least in some
+cases is not optional. It is based on the hexedit of a neufbox4 firmware image, the
+information in https://dev.openwrt.org/ticket/4987, and the hexedit of a Tecom
+GW6200 image.
+
+Some boards share the same tag format, but require vendor-specific fields in
+the board. In that case the tagid is shared, but the filename of the generated
+image reflects the router for which the image was created.
+
+router |method | codever |filename
++-------------+-------------+---------+---------------------------------------
+|any |cfe+most web | any |openwrt-<board>-<fs>-cfe.bin
+|AGVoIP2+WiFi |cfe |alice3.06|openwrt-AGV2+W-cfe-<fs>-cfe.bin
+|AGVoIP2+WiFi |web |alice3.06|openwrt-AGV2+W-cfe-<fs>-cfe.bin
+|CT536 |web |3.02 |openwrt-CT536_CT5621-<fs>-cfe.bin
+|CT5621 |web |3.02 |openwrt-CT536_CT5621-<fs>-cfe.bin
+|DG834GT |web |3.02 |openwrt-DG834GT_DG834PN-<fs>-cfe.bin
+|DG834PN |web |3.02 |openwrt-DG834GT_DG834PN-<fs>-cfe.bin
+|DSL-2640B |web |3.10 |openwrt-DSL2640B-<fs>-cfe.bin
+|DSL-2740B |web |3.10 |openwrt-DSL2670B-<fs>-cfe.bin
+|F5D7633 |web |3.10 |openwrt-F5D7633-<fs>-cfe.bin
+|F@ST2404 |web |3.0X? |openwrt-F@ST2404-cfe-<fs>-cfe.bin
+|F@ST2404 |web |3.1X? |openwrt-F@ST2404-<fs>-cfe.bin
+|GW6000 |web |3.00 |openwrt-GW6000-<fs>-cfe.bin
+|GW6200 |web |3.10 |openwrt-GW6200-<fs>-cfe.bin
+|Neufbox4 |web |3.12 |openwrt-NEUFBOX4-<fs>-cfe.bin
+|TD8810A |web |3.06 |openwrt-TD8810-<fs>-cfe.bin
+|TD8810B |web |3.06 |openwrt-TD8810-<fs>-cfe.bin
+|TD8811A |web |3.06 |openwrt-TD8811-<fs>-cfe.bin
+|TD8811B |web |3.06 |openwrt-TD881-<fs>-cfe.bin
+|TD8900GB |web |3.06 |openwrt-TD8900DB<fs>-cfe.bin
+|USR9108 |web |3.0X? |openwrt-USR9108-<fs>-cfe.bin
+|V2091_BTR |web |2.21 |openwrt-V2091_BTR-<fs>-cfe.bin
+|V2091_ROI |web |2.21 |openwrt-V2091-<fs>-cfe.bin
+|V2091_WB |web |2.21 |openwrt-V2091-<fs>-cfe.bin
+|V210_BTR |web |2.21 |openwrt-V210_BTR-<fs>-cfe.bin
+|V210_ROI |web |2.21 |openwrt-V210-ROI_WB<fs>-cfe.bin
+|V210_WB |web |2.21 |openwrt-V210-ROI_WB<fs>-cfe.bin
+|V2110 |web |2.21 |openwrt-V2110-<fs>-cfe.bin
+|V2110_AA |web |2.21 |openwrt-V2110-<fs>-cfe.bin
+|V2110_ROI |web |2.21 |openwrt-V2110-<fs>-cfe.bin
+|V2500V |web |2.21 |openwrt-V2500V<fs>-cfe.bin
+|V2500V_AA |web |2.21 |openwrt-V2500V-<fs>-cfe.bin
+|V2500V_SIP_CLUB |web |2.21 |openwrt-V2500V-<fs>-cfe.bin
+
+Old imagetag routers
+--------------------
+Davolink DV201AMR
+
+Redboot routers
+---------------
+Inventel Livebox
+
+Known router->code versions
+---------------------------
+
+Vendor |Model |Code Ver
+---------------------------+------------------------------------------+--------
+Belkin |F5D7633 |3.10
+British Telecom (BT) |Voyager V2091_BTR |2.21
+British Telecom (BT) |Voyager V2091_ROI |2.21
+British Telecom (BT) |Voyager V2091_WB |2.21
+British Telecom (BT) |Voyager V210_BTR |2.21
+British Telecom (BT) |Voyager V210_ROI |2.21
+British Telecom (BT) |Voyager V210_WB |2.21
+British Telecom (BT) |Voyager V2110 |2.21
+British Telecom (BT) |Voyager V2110_AA |2.21
+British Telecom (BT) |Voyager V2110_ROI |2.21
+British Telecom (BT) |Voyager V220V |2.21
+British Telecom (BT) |Voyager V2500V |2.21
+British Telecom (BT) |Voyager V2500V_AA |2.21
+British Telecom (BT) |Voyager V2500V_SIP_CLUB |2.21
+Comtrend |CT-5261 |3.02
+Comtrend |CT-536 |3.02
+D-Link |DSL-2640B |3.10
+D-Link |DSL-2670B |3.10
+NetGear |DG834GT |3.02
+NetGear |DG834PN |3.02
+Neuf Cegetel |Neufbox 4 |3.12
+Pirelli |Alice Gate Wi-Fi (+VoIP models?) |ag 3.06
+Sagem |F@ST2404 |?
+TP-Link |TD-8810A |3.06
+TP-Link |TD-8810B |3.06
+TP-Link |TD-8811A |3.06
+TP-Link |TD-8811B |3.06
+TP-Link |TD-W8900GB |3.06
+Tecom |GW6000 |3.00
+Tecom |GW6200 |3.10
+USR |9108 |?
+
diff --git a/target/linux/brcm63xx/image/lzma-loader/Makefile b/target/linux/brcm63xx/image/lzma-loader/Makefile
new file mode 100644
index 000000000..5dd6f5097
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/Makefile
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := lzma-loader
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+$(PKG_BUILD_DIR)/.prepared:
+ mkdir $(PKG_BUILD_DIR)
+ $(CP) ./src/* $(PKG_BUILD_DIR)/
+ touch $@
+
+$(PKG_BUILD_DIR)/loader.gz: $(PKG_BUILD_DIR)/.prepared
+ $(MAKE) -C $(PKG_BUILD_DIR) CC="$(TARGET_CC)" \
+ LD="$(TARGET_CROSS)ld" CROSS_COMPILE="$(TARGET_CROSS)"
+
+download:
+prepare: $(PKG_BUILD_DIR)/.prepared
+compile: $(PKG_BUILD_DIR)/loader.gz
+install:
+
+ifneq ($(TARGET),)
+install: compile
+ $(CP) $(PKG_BUILD_DIR)/loader.gz $(PKG_BUILD_DIR)/loader.elf $(TARGET)/
+endif
+
+clean:
+ rm -rf $(PKG_BUILD_DIR)
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.c b/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.c
new file mode 100644
index 000000000..951700bdd
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.c
@@ -0,0 +1,663 @@
+/*
+ LzmaDecode.c
+ LZMA Decoder
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+typedef struct _CRangeDecoder
+{
+ Byte *Buffer;
+ Byte *BufferLim;
+ UInt32 Range;
+ UInt32 Code;
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback;
+ int Result;
+ #endif
+ int ExtraBytes;
+} CRangeDecoder;
+
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
+{
+ if (rd->Buffer == rd->BufferLim)
+ {
+ #ifdef _LZMA_IN_CB
+ UInt32 size;
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
+ rd->BufferLim = rd->Buffer + size;
+ if (size == 0)
+ #endif
+ {
+ rd->ExtraBytes = 1;
+ return 0xFF;
+ }
+ }
+ return (*rd->Buffer++);
+}
+
+/* #define ReadByte (*rd->Buffer++) */
+#define ReadByte (RangeDecoderReadByte(rd))
+
+void RangeDecoderInit(CRangeDecoder *rd,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ Byte *stream, UInt32 bufferSize
+ #endif
+ )
+{
+ int i;
+ #ifdef _LZMA_IN_CB
+ rd->InCallback = inCallback;
+ rd->Buffer = rd->BufferLim = 0;
+ #else
+ rd->Buffer = stream;
+ rd->BufferLim = stream + bufferSize;
+ #endif
+ rd->ExtraBytes = 0;
+ rd->Code = 0;
+ rd->Range = (0xFFFFFFFF);
+ for(i = 0; i < 5; i++)
+ rd->Code = (rd->Code << 8) | ReadByte;
+}
+
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
+{
+ RC_INIT_VAR
+ UInt32 result = 0;
+ int i;
+ for (i = numTotalBits; i > 0; i--)
+ {
+ /* UInt32 t; */
+ range >>= 1;
+
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ /*
+ t = (code - range) >> 31;
+ t &= 1;
+ code -= range & (t - 1);
+ result = (result + result) | (1 - t);
+ */
+ RC_NORMALIZE
+ }
+ RC_FLUSH_VAR
+ return result;
+}
+
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
+{
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
+ if (rd->Code < bound)
+ {
+ rd->Range = bound;
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rd->Range -= bound;
+ rd->Code -= bound;
+ *prob -= (*prob) >> kNumMoveBits;
+ if (rd->Range < kTopValue)
+ {
+ rd->Code = (rd->Code << 8) | ReadByte;
+ rd->Range <<= 8;
+ }
+ return 1;
+ }
+}
+
+#define RC_GET_BIT2(prob, mi, A0, A1) \
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
+ if (code < bound) \
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
+ else \
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
+ RC_NORMALIZE
+
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
+
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = numLevels; i > 0; i--)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT(prob, mi)
+ #else
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return mi - (1 << numLevels);
+}
+
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
+{
+ int mi = 1;
+ int i;
+ int symbol = 0;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ for(i = 0; i < numLevels; i++)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + mi;
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
+ #else
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
+ mi = mi + mi + bit;
+ symbol |= (bit << i);
+ #endif
+ }
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
+{
+ int symbol = 1;
+ #ifdef _LZMA_LOC_OPT
+ RC_INIT_VAR
+ #endif
+ do
+ {
+ int bit;
+ int matchBit = (matchByte >> 7) & 1;
+ matchByte <<= 1;
+ #ifdef _LZMA_LOC_OPT
+ {
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
+ }
+ #else
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
+ symbol = (symbol << 1) | bit;
+ #endif
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ {
+ #ifdef _LZMA_LOC_OPT
+ CProb *prob = probs + symbol;
+ RC_GET_BIT(prob, symbol)
+ #else
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
+ #endif
+ }
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ #ifdef _LZMA_LOC_OPT
+ RC_FLUSH_VAR
+ #endif
+ return symbol;
+}
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
+{
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
+ return RangeDecoderBitTreeDecode(p + LenLow +
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
+ return kLenNumLowSymbols + kLenNumMidSymbols +
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
+}
+
+#define kNumStates 12
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#ifdef _LZMA_OUT_READ
+
+typedef struct _LzmaVarState
+{
+ CRangeDecoder RangeDecoder;
+ Byte *Dictionary;
+ UInt32 DictionarySize;
+ UInt32 DictionaryPos;
+ UInt32 GlobalPos;
+ UInt32 Reps[4];
+ int lc;
+ int lp;
+ int pb;
+ int State;
+ int PreviousIsMatch;
+ int RemainLen;
+} LzmaVarState;
+
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+ )
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ UInt32 i;
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ vs->Dictionary = dictionary;
+ vs->DictionarySize = dictionarySize;
+ vs->DictionaryPos = 0;
+ vs->GlobalPos = 0;
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
+ vs->lc = lc;
+ vs->lp = lp;
+ vs->pb = pb;
+ vs->State = 0;
+ vs->PreviousIsMatch = 0;
+ vs->RemainLen = 0;
+ dictionary[dictionarySize - 1] = 0;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&vs->RangeDecoder,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+ return LZMA_RESULT_OK;
+}
+
+int LzmaDecode(unsigned char *buffer,
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ LzmaVarState *vs = (LzmaVarState *)buffer;
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
+ CRangeDecoder rd = vs->RangeDecoder;
+ int state = vs->State;
+ int previousIsMatch = vs->PreviousIsMatch;
+ Byte previousByte;
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
+ int lc = vs->lc;
+ int len = vs->RemainLen;
+ UInt32 globalPos = vs->GlobalPos;
+
+ Byte *dictionary = vs->Dictionary;
+ UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionaryPos = vs->DictionaryPos;
+
+ if (len == -1)
+ {
+ *outSizeProcessed = 0;
+ return LZMA_RESULT_OK;
+ }
+
+ while(len > 0 && nowPos < outSize)
+ {
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ len--;
+ }
+ if (dictionaryPos == 0)
+ previousByte = dictionary[dictionarySize - 1];
+ else
+ previousByte = dictionary[dictionaryPos - 1];
+#else
+
+int LzmaDecode(
+ Byte *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
+ CProb *p = (CProb *)buffer;
+ CRangeDecoder rd;
+ UInt32 i;
+ int state = 0;
+ int previousIsMatch = 0;
+ Byte previousByte = 0;
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+ UInt32 nowPos = 0;
+ UInt32 posStateMask = (1 << pb) - 1;
+ UInt32 literalPosMask = (1 << lp) - 1;
+ int len = 0;
+ if (bufferSize < numProbs * sizeof(CProb))
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ RangeDecoderInit(&rd,
+ #ifdef _LZMA_IN_CB
+ inCallback
+ #else
+ inStream, inSize
+ #endif
+ );
+#endif
+
+ *outSizeProcessed = 0;
+ while(nowPos < outSize)
+ {
+ int posState = (int)(
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & posStateMask);
+ #ifdef _LZMA_IN_CB
+ if (rd.Result != LZMA_RESULT_OK)
+ return rd.Result;
+ #endif
+ if (rd.ExtraBytes != 0)
+ return LZMA_RESULT_DATA_ERROR;
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
+ (((
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+ if (state < 4) state = 0;
+ else if (state < 10) state -= 3;
+ else state -= 6;
+ if (previousIsMatch)
+ {
+ Byte matchByte;
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ matchByte = dictionary[pos];
+ #else
+ matchByte = outStream[nowPos - rep0];
+ #endif
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
+ previousIsMatch = 0;
+ }
+ else
+ previousByte = LzmaLiteralDecode(probs, &rd);
+ outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #endif
+ }
+ else
+ {
+ previousIsMatch = 1;
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+ {
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+ {
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos;
+ #endif
+ if (
+ (nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ == 0)
+ return LZMA_RESULT_DATA_ERROR;
+ state = state < 7 ? 9 : 11;
+ #ifdef _LZMA_OUT_READ
+ pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+ distance = rep1;
+ else
+ {
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
+ state = state < 7 ? 8 : 11;
+ }
+ else
+ {
+ int posSlot;
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ state = state < 7 ? 7 : 10;
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+ if (posSlot < kEndPosModelIndex)
+ {
+ rep0 += RangeDecoderReverseBitTreeDecode(
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+ }
+ else
+ {
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+ }
+ }
+ else
+ rep0 = posSlot;
+ rep0++;
+ }
+ if (rep0 == (UInt32)(0))
+ {
+ /* it's for stream version */
+ len = -1;
+ break;
+ }
+ if (rep0 > nowPos
+ #ifdef _LZMA_OUT_READ
+ + globalPos
+ #endif
+ )
+ {
+ return LZMA_RESULT_DATA_ERROR;
+ }
+ len += kMatchMinLen;
+ do
+ {
+ #ifdef _LZMA_OUT_READ
+ UInt32 pos = dictionaryPos - rep0;
+ if (pos >= dictionarySize)
+ pos += dictionarySize;
+ previousByte = dictionary[pos];
+ dictionary[dictionaryPos] = previousByte;
+ if (++dictionaryPos == dictionarySize)
+ dictionaryPos = 0;
+ #else
+ previousByte = outStream[nowPos - rep0];
+ #endif
+ outStream[nowPos++] = previousByte;
+ len--;
+ }
+ while(len > 0 && nowPos < outSize);
+ }
+ }
+
+ #ifdef _LZMA_OUT_READ
+ vs->RangeDecoder = rd;
+ vs->DictionaryPos = dictionaryPos;
+ vs->GlobalPos = globalPos + nowPos;
+ vs->Reps[0] = rep0;
+ vs->Reps[1] = rep1;
+ vs->Reps[2] = rep2;
+ vs->Reps[3] = rep3;
+ vs->State = state;
+ vs->PreviousIsMatch = previousIsMatch;
+ vs->RemainLen = len;
+ #endif
+
+ *outSizeProcessed = nowPos;
+ return LZMA_RESULT_OK;
+}
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.h b/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.h
new file mode 100644
index 000000000..f58944e3c
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/LzmaDecode.h
@@ -0,0 +1,100 @@
+/*
+ LzmaDecode.h
+ LZMA Decoder interface
+
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+ http://www.7-zip.org/
+
+ LZMA SDK is licensed under two licenses:
+ 1) GNU Lesser General Public License (GNU LGPL)
+ 2) Common Public License (CPL)
+ It means that you can select one of these two licenses and
+ follow rules of that license.
+
+ SPECIAL EXCEPTION:
+ Igor Pavlov, as the author of this code, expressly permits you to
+ statically or dynamically link your code (or bind by name) to the
+ interfaces of this file without subjecting your linked code to the
+ terms of the CPL or GNU LGPL. Any modifications or additions
+ to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs,
+ but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+/*
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
+bufferSize += 100 in case of _LZMA_OUT_READ
+by default CProb is unsigned short,
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
+*/
+
+#ifdef _LZMA_OUT_READ
+int LzmaDecoderInit(
+ unsigned char *buffer, UInt32 bufferSize,
+ int lc, int lp, int pb,
+ unsigned char *dictionary, UInt32 dictionarySize,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback
+ #else
+ unsigned char *inStream, UInt32 inSize
+ #endif
+);
+#endif
+
+int LzmaDecode(
+ unsigned char *buffer,
+ #ifndef _LZMA_OUT_READ
+ UInt32 bufferSize,
+ int lc, int lp, int pb,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *inCallback,
+ #else
+ unsigned char *inStream, UInt32 inSize,
+ #endif
+ #endif
+ unsigned char *outStream, UInt32 outSize,
+ UInt32 *outSizeProcessed);
+
+#endif
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/Makefile b/target/linux/brcm63xx/image/lzma-loader/src/Makefile
new file mode 100644
index 000000000..83e2c5238
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/Makefile
@@ -0,0 +1,77 @@
+#
+# Makefile for Broadcom BCM947XX boards
+#
+# Copyright 2001-2003, Broadcom Corporation
+# All Rights Reserved.
+#
+# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+#
+# Copyright 2004 Manuel Novoa III <mjn3@codepoet.org>
+# Modified to support bzip'd kernels.
+# Of course, it would be better to integrate bunzip capability into CFE.
+#
+# Copyright 2005 Oleg I. Vdovikin <oleg@cs.msu.su>
+# Cleaned up, modified for lzma support, removed from kernel
+#
+
+TEXT_START := 0x80010000
+BZ_TEXT_START := 0x80300000
+
+OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
+
+CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
+ -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \
+ -ffunction-sections -pipe -mlong-calls -fno-common \
+ -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
+CFLAGS += -DLOADADDR=$(TEXT_START) -D_LZMA_IN_CB
+
+ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ -DBZ_TEXT_START=$(BZ_TEXT_START)
+
+SEDFLAGS := s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/TEXT_START/$(TEXT_START)/
+
+OBJECTS := head.o data.o
+
+all: loader.gz loader.elf
+
+# Don't build dependencies, this may die if $(CC) isn't gcc
+dep:
+
+install:
+
+loader.gz: loader
+ gzip -nc9 $< > $@
+
+loader.elf: loader.o
+ cp $< $@
+
+loader: loader.o
+ $(OBJCOPY) $< $@
+
+loader.o: loader.lds $(OBJECTS)
+ $(LD) -static --gc-sections -no-warn-mismatch -T loader.lds -o $@ $(OBJECTS)
+
+loader.lds: loader.lds.in Makefile
+ @sed "$(SEDFLAGS)" < $< > $@
+
+data.o: data.lds decompress.image
+ $(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary decompress.image -b elf32-tradlittlemips
+
+data.lds:
+ @echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@
+
+decompress.image: decompress
+ $(OBJCOPY) $< $@
+
+decompress: decompress.lds decompress.o LzmaDecode.o
+ $(LD) -static --gc-sections -no-warn-mismatch -T decompress.lds -o $@ decompress.o LzmaDecode.o
+
+decompress.lds: decompress.lds.in Makefile
+ @sed "$(SEDFLAGS)" < $< > $@
+
+mrproper: clean
+
+clean:
+ rm -f loader.gz loader decompress *.lds *.o *.image
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/README b/target/linux/brcm63xx/image/lzma-loader/src/README
new file mode 100644
index 000000000..16649e950
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/README
@@ -0,0 +1,55 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+The code is intended to decompress kernel, being compressed using lzma utility
+build using 7zip LZMA SDK. This utility is located in the LZMA_Alone directory
+
+decompressor code expects that your .trx file consist of three partitions:
+
+1) decompressor itself (this is gziped code which pmon/cfe will extract and run
+on boot-up instead of real kernel)
+2) LZMA compressed kernel (both streamed and regular modes are supported now)
+3) Root filesystem
+
+Please be sure to apply the following patch for use this new trx layout (it will
+allow using both new and old trx files for root filesystem lookup code)
+
+--- linuz/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:24:27.503322896 +0300
++++ linux/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:29:05.237100944 +0300
+@@ -221,7 +221,9 @@
+ /* Try looking at TRX header for rootfs offset */
+ if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
+ bcm947xx_parts[1].offset = off;
+- if (le32_to_cpu(trx->offsets[1]) > off)
++ if (le32_to_cpu(trx->offsets[2]) > off)
++ off = le32_to_cpu(trx->offsets[2]);
++ else if (le32_to_cpu(trx->offsets[1]) > off)
+ off = le32_to_cpu(trx->offsets[1]);
+ continue;
+ }
+
+
+Revision history:
+ 0.02 Initial release
+ 0.03 Added Mineharu Takahara <mtakahar@yahoo.com> patch to pass actual
+ output size to decoder (stream mode compressed input is not
+ a requirement anymore)
+ 0.04 Reordered functions using lds script
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/decompress.c b/target/linux/brcm63xx/image/lzma-loader/src/decompress.c
new file mode 100644
index 000000000..ec510e21e
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/decompress.c
@@ -0,0 +1,175 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Please note, this was code based on the bunzip2 decompressor code
+ * by Manuel Novoa III (mjn3@codepoet.org), although the only thing left
+ * is an idea and part of original vendor code
+ *
+ *
+ * 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com>
+ * pass actual output size to decoder (stream mode
+ * compressed input is not a requirement anymore)
+ *
+ * 24-Apr-2005 Oleg I. Vdovikin
+ * reordered functions using lds script, removed forward decl
+ *
+ */
+
+#include "LzmaDecode.h"
+
+#define BCM4710_FLASH 0x1fc00000 /* Flash */
+
+#define KSEG0 0x80000000
+#define KSEG1 0xa0000000
+
+#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+#define cache_unroll(base,op) \
+ __asm__ __volatile__( \
+ ".set noreorder;\n" \
+ ".set mips3;\n" \
+ "cache %1, (%0);\n" \
+ ".set mips0;\n" \
+ ".set reorder\n" \
+ : \
+ : "r" (base), \
+ "i" (op));
+
+static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Invalidate_I);
+ start += lsize;
+ }
+}
+
+static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
+{
+ unsigned long start = KSEG0;
+ unsigned long end = (start + size);
+
+ while(start < end) {
+ cache_unroll(start,Index_Writeback_Inv_D);
+ start += lsize;
+ }
+}
+
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+
+struct trx_header {
+ unsigned int magic; /* "HDR0" */
+ unsigned int len; /* Length of file including header */
+ unsigned int crc32; /* 32-bit CRC from flag_version to end of file */
+ unsigned int flag_version; /* 0:15 flags, 16:31 version */
+ unsigned int offsets[3]; /* Offsets of partitions from start of header */
+};
+
+/* beyound the image end, size not known in advance */
+extern unsigned char workspace[];
+
+unsigned int offset;
+unsigned char *data;
+
+/* flash access should be aligned, so wrapper is used */
+/* read byte from the flash, all accesses are 32-bit aligned */
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+{
+ static unsigned int val;
+
+ if (((unsigned int)offset % 4) == 0) {
+ val = *(unsigned int *)data;
+ data += 4;
+ }
+
+ *bufferSize = 1;
+ *buffer = ((unsigned char *)&val) + (offset++ & 3);
+
+ return LZMA_RESULT_OK;
+}
+
+static __inline__ unsigned char get_byte(void)
+{
+ unsigned char *buffer;
+ UInt32 fake;
+
+ return read_byte(0, &buffer, &fake), *buffer;
+}
+
+/* should be the first function */
+void entry(unsigned long icache_size, unsigned long icache_lsize,
+ unsigned long dcache_size, unsigned long dcache_lsize)
+{
+ unsigned int i; /* temp value */
+ unsigned int lc; /* literal context bits */
+ unsigned int lp; /* literal pos state bits */
+ unsigned int pb; /* pos state bits */
+ unsigned int osize; /* uncompressed size */
+
+ ILzmaInCallback callback;
+ callback.Read = read_byte;
+
+ /* look for trx header, 32-bit data access */
+ for (data = ((unsigned char *) KSEG1ADDR(BCM4710_FLASH));
+ ((struct trx_header *)data)->magic != TRX_MAGIC; data += 65536);
+
+ /* compressed kernel is in the partition 0 or 1 */
+ if (((struct trx_header *)data)->offsets[1] > 65536)
+ data += ((struct trx_header *)data)->offsets[0];
+ else
+ data += ((struct trx_header *)data)->offsets[1];
+
+ offset = 0;
+
+ /* lzma args */
+ i = get_byte();
+ lc = i % 9, i = i / 9;
+ lp = i % 5, pb = i / 5;
+
+ /* skip rest of the LZMA coder property */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* read the lower half of uncompressed size in the header */
+ osize = ((unsigned int)get_byte()) +
+ ((unsigned int)get_byte() << 8) +
+ ((unsigned int)get_byte() << 16) +
+ ((unsigned int)get_byte() << 24);
+
+ /* skip rest of the header (upper half of uncompressed size) */
+ for (i = 0; i < 4; i++)
+ get_byte();
+
+ /* decompress kernel */
+ if (LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
+ (unsigned char*)LOADADDR, osize, &i) == LZMA_RESULT_OK)
+ {
+ blast_dcache(dcache_size, dcache_lsize);
+ blast_icache(icache_size, icache_lsize);
+
+ /* Jump to load address */
+ ((void (*)(void)) LOADADDR)();
+ }
+}
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/decompress.lds.in b/target/linux/brcm63xx/image/lzma-loader/src/decompress.lds.in
new file mode 100644
index 000000000..33f56f8a0
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/decompress.lds.in
@@ -0,0 +1,20 @@
+OUTPUT_ARCH(mips)
+ENTRY(entry)
+SECTIONS {
+ . = BZ_TEXT_START;
+ .text : {
+ *(.text.entry)
+ *(.text)
+ *(.rodata)
+ }
+
+ .data : {
+ *(.data)
+ }
+
+ .bss : {
+ *(.bss)
+ }
+
+ workspace = .;
+}
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/head.S b/target/linux/brcm63xx/image/lzma-loader/src/head.S
new file mode 100644
index 000000000..9bfbd53d5
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/head.S
@@ -0,0 +1,155 @@
+/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su) */
+/* cache manipulation adapted from Broadcom code */
+/* idea taken from original bunzip2 decompressor code */
+/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */
+/* Licensed under the linux kernel's version of the GPL.*/
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define KSEG0 0x80000000
+
+#define C0_CONFIG $16
+#define C0_TAGLO $28
+#define C0_TAGHI $29
+
+#define CONF1_DA_SHIFT 7 /* D$ associativity */
+#define CONF1_DA_MASK 0x00000380
+#define CONF1_DA_BASE 1
+#define CONF1_DL_SHIFT 10 /* D$ line size */
+#define CONF1_DL_MASK 0x00001c00
+#define CONF1_DL_BASE 2
+#define CONF1_DS_SHIFT 13 /* D$ sets/way */
+#define CONF1_DS_MASK 0x0000e000
+#define CONF1_DS_BASE 64
+#define CONF1_IA_SHIFT 16 /* I$ associativity */
+#define CONF1_IA_MASK 0x00070000
+#define CONF1_IA_BASE 1
+#define CONF1_IL_SHIFT 19 /* I$ line size */
+#define CONF1_IL_MASK 0x00380000
+#define CONF1_IL_BASE 2
+#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
+#define CONF1_IS_MASK 0x01c00000
+#define CONF1_IS_BASE 64
+
+#define Index_Invalidate_I 0x00
+#define Index_Writeback_Inv_D 0x01
+
+ .text
+ LEAF(startup)
+ .set noreorder
+
+ /* Copy decompressor code to the right place */
+ li t2, BZ_TEXT_START
+ add a0, t2, 0
+ la a1, code_start
+ la a2, code_stop
+$L1:
+ lw t0, 0(a1)
+ sw t0, 0(a0)
+ add a1, 4
+ add a0, 4
+ blt a1, a2, $L1
+ nop
+
+ /* At this point we need to invalidate dcache and */
+ /* icache before jumping to new code */
+
+1: /* Get cache sizes */
+ .set mips32
+ mfc0 s0,C0_CONFIG,1
+ .set mips0
+
+ li s1,CONF1_DL_MASK
+ and s1,s0
+ beq s1,zero,nodc
+ nop
+
+ srl s1,CONF1_DL_SHIFT
+ li t0,CONF1_DL_BASE
+ sll s1,t0,s1 /* s1 has D$ cache line size */
+
+ li s2,CONF1_DA_MASK
+ and s2,s0
+ srl s2,CONF1_DA_SHIFT
+ addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */
+
+ li t0,CONF1_DS_MASK
+ and t0,s0
+ srl t0,CONF1_DS_SHIFT
+ li s3,CONF1_DS_BASE
+ sll s3,s3,t0 /* s3 has D$ sets per way */
+
+ multu s2,s3 /* sets/way * associativity */
+ mflo t0 /* total cache lines */
+
+ multu s1,t0 /* D$ linesize * lines */
+ mflo s2 /* s2 is now D$ size in bytes */
+
+ /* Initilize the D$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s2 /* + size of cache == end */
+
+ .set mips3
+1: cache Index_Writeback_Inv_D,0(t0)
+ .set mips0
+ bne t0,t1,1b
+ addu t0,s1
+
+nodc:
+ /* Now we get to do it all again for the I$ */
+
+ move s3,zero /* just in case there is no icache */
+ move s4,zero
+
+ li t0,CONF1_IL_MASK
+ and t0,s0
+ beq t0,zero,noic
+ nop
+
+ srl t0,CONF1_IL_SHIFT
+ li s3,CONF1_IL_BASE
+ sll s3,t0 /* s3 has I$ cache line size */
+
+ li t0,CONF1_IA_MASK
+ and t0,s0
+ srl t0,CONF1_IA_SHIFT
+ addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */
+
+ li t0,CONF1_IS_MASK
+ and t0,s0
+ srl t0,CONF1_IS_SHIFT
+ li s5,CONF1_IS_BASE
+ sll s5,t0 /* s5 has I$ sets per way */
+
+ multu s4,s5 /* sets/way * associativity */
+ mflo t0 /* s4 is now total cache lines */
+
+ multu s3,t0 /* I$ linesize * lines */
+ mflo s4 /* s4 is cache size in bytes */
+
+ /* Initilize the I$: */
+ mtc0 zero,C0_TAGLO
+ mtc0 zero,C0_TAGHI
+
+ li t0,KSEG0 /* Just an address for the first $ line */
+ addu t1,t0,s4 /* + size of cache == end */
+
+ .set mips3
+1: cache Index_Invalidate_I,0(t0)
+ .set mips0
+ bne t0,t1,1b
+ addu t0,s3
+
+noic:
+ move a0,s3 /* icache line size */
+ move a1,s4 /* icache size */
+ move a2,s1 /* dcache line size */
+ jal t2
+ move a3,s2 /* dcache size */
+
+ .set reorder
+ END(startup)
diff --git a/target/linux/brcm63xx/image/lzma-loader/src/loader.lds.in b/target/linux/brcm63xx/image/lzma-loader/src/loader.lds.in
new file mode 100644
index 000000000..20f2ea98e
--- /dev/null
+++ b/target/linux/brcm63xx/image/lzma-loader/src/loader.lds.in
@@ -0,0 +1,17 @@
+OUTPUT_ARCH(mips)
+ENTRY(startup)
+SECTIONS {
+ . = TEXT_START;
+ .text : {
+ *(.text)
+ *(.rodata)
+ }
+
+ .data : {
+ *(.data)
+ }
+
+ .bss : {
+ *(.bss)
+ }
+}
diff --git a/target/linux/brcm63xx/modules.mk b/target/linux/brcm63xx/modules.mk
new file mode 100644
index 000000000..43ec62430
--- /dev/null
+++ b/target/linux/brcm63xx/modules.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define KernelPackage/bcm63xx-spi
+ SUBMENU:=$(SPI_MENU)
+ TITLE:=Broadcom BCM63xx SPI driver
+ DEPENDS:=@TARGET_brcm63xx
+ KCONFIG:=CONFIG_SPI_BCM63XX
+ FILES:=$(LINUX_DIR)/drivers/spi/spi-bcm63xx.ko
+ AUTOLOAD:=$(call AutoLoad,92,spi-bcm63xx)
+endef
+
+define KernelPackage/bcm63xx-spi/description
+ This package contains the Broadcom BCM63xx SPI Master driver
+endef
+
+$(eval $(call KernelPackage,bcm63xx-spi))
+
+
+define KernelPackage/pcmcia-bcm63xx
+ SUBMENU:=$(PCMCIA_MENU)
+ TITLE:=Broadcom BCM63xx PCMCIA support
+ DEPENDS:=@TARGET_brcm63xx +kmod-pcmcia-rsrc
+ KCONFIG:=CONFIG_PCMCIA_BCM63XX
+ FILES:=$(LINUX_DIR)/drivers/pcmcia/bcm63xx_pcmcia.ko
+ AUTOLOAD:=$(call AutoLoad,41,bcm63xx_pcmcia)
+endef
+
+define KernelPackage/pcmcia-bcm63xx/description
+ Kernel support for PCMCIA/CardBus controller on the BCM63xx SoC
+endef
+
+$(eval $(call KernelPackage,pcmcia-bcm63xx))
diff --git a/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch b/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch
new file mode 100644
index 000000000..f83490e6c
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/001-MIPS-BCM63XX-fix-platform_devices-id.patch
@@ -0,0 +1,36 @@
+From cbcfe65e357666106c3c6250baf9c5ce33f3e3e3 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:53 +0100
+Subject: [PATCH 03/63] MIPS: BCM63XX: fix platform_devices id
+
+There is only one watchdog and VoIP DSP platform devices per board, use
+-1 as the platform_device id accordingly.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/bcm63xx/dev-dsp.c | 2 +-
+ arch/mips/bcm63xx/dev-wdt.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-dsp.c
++++ b/arch/mips/bcm63xx/dev-dsp.c
+@@ -31,7 +31,7 @@ static struct resource voip_dsp_resource
+
+ static struct platform_device bcm63xx_voip_dsp_device = {
+ .name = "bcm63xx-voip-dsp",
+- .id = 0,
++ .id = -1,
+ .num_resources = ARRAY_SIZE(voip_dsp_resources),
+ .resource = voip_dsp_resources,
+ };
+--- a/arch/mips/bcm63xx/dev-wdt.c
++++ b/arch/mips/bcm63xx/dev-wdt.c
+@@ -21,7 +21,7 @@ static struct resource wdt_resources[] =
+
+ static struct platform_device bcm63xx_wdt_device = {
+ .name = "bcm63xx-wdt",
+- .id = 0,
++ .id = -1,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+ .resource = wdt_resources,
+ };
diff --git a/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch b/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch
new file mode 100644
index 000000000..439d11ea1
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/002-MIPS-BCM63XX-be-consistent-in-clock-bits-enable-nami.patch
@@ -0,0 +1,93 @@
+From db1cc4ee366bf0528fcb8b4afa65dec915d98889 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:55 +0100
+Subject: [PATCH 04/63] MIPS: BCM63XX: be consistent in clock bits enable naming
+
+Remove the _CLK suffix from the BCM6368 clock bits definitions to be
+consistent with what is already present.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/bcm63xx/clk.c | 6 ++--
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 36 ++++++++++----------
+ 2 files changed, 21 insertions(+), 21 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -120,7 +120,7 @@ static void enetsw_set(struct clk *clk,
+ {
+ if (!BCMCPU_IS_6368())
+ return;
+- bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN |
++ bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
+ CKCTL_6368_SWPKT_USB_EN |
+ CKCTL_6368_SWPKT_SAR_EN, enable);
+ if (enable) {
+@@ -163,7 +163,7 @@ static void usbh_set(struct clk *clk, in
+ if (BCMCPU_IS_6348())
+ bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
+ else if (BCMCPU_IS_6368())
+- bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable);
++ bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
+ }
+
+ static struct clk clk_usbh = {
+@@ -199,7 +199,7 @@ static void xtm_set(struct clk *clk, int
+ if (!BCMCPU_IS_6368())
+ return;
+
+- bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN |
++ bcm_hwclock_set(CKCTL_6368_SAR_EN |
+ CKCTL_6368_SWPKT_SAR_EN, enable);
+
+ if (enable) {
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -90,29 +90,29 @@
+ #define CKCTL_6368_PHYMIPS_EN (1 << 6)
+ #define CKCTL_6368_SWPKT_USB_EN (1 << 7)
+ #define CKCTL_6368_SWPKT_SAR_EN (1 << 8)
+-#define CKCTL_6368_SPI_CLK_EN (1 << 9)
+-#define CKCTL_6368_USBD_CLK_EN (1 << 10)
+-#define CKCTL_6368_SAR_CLK_EN (1 << 11)
+-#define CKCTL_6368_ROBOSW_CLK_EN (1 << 12)
+-#define CKCTL_6368_UTOPIA_CLK_EN (1 << 13)
+-#define CKCTL_6368_PCM_CLK_EN (1 << 14)
+-#define CKCTL_6368_USBH_CLK_EN (1 << 15)
++#define CKCTL_6368_SPI_EN (1 << 9)
++#define CKCTL_6368_USBD_EN (1 << 10)
++#define CKCTL_6368_SAR_EN (1 << 11)
++#define CKCTL_6368_ROBOSW_EN (1 << 12)
++#define CKCTL_6368_UTOPIA_EN (1 << 13)
++#define CKCTL_6368_PCM_EN (1 << 14)
++#define CKCTL_6368_USBH_EN (1 << 15)
+ #define CKCTL_6368_DISABLE_GLESS_EN (1 << 16)
+-#define CKCTL_6368_NAND_CLK_EN (1 << 17)
+-#define CKCTL_6368_IPSEC_CLK_EN (1 << 17)
++#define CKCTL_6368_NAND_EN (1 << 17)
++#define CKCTL_6368_IPSEC_EN (1 << 17)
+
+ #define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \
+ CKCTL_6368_SWPKT_SAR_EN | \
+- CKCTL_6368_SPI_CLK_EN | \
+- CKCTL_6368_USBD_CLK_EN | \
+- CKCTL_6368_SAR_CLK_EN | \
+- CKCTL_6368_ROBOSW_CLK_EN | \
+- CKCTL_6368_UTOPIA_CLK_EN | \
+- CKCTL_6368_PCM_CLK_EN | \
+- CKCTL_6368_USBH_CLK_EN | \
++ CKCTL_6368_SPI_EN | \
++ CKCTL_6368_USBD_EN | \
++ CKCTL_6368_SAR_EN | \
++ CKCTL_6368_ROBOSW_EN | \
++ CKCTL_6368_UTOPIA_EN | \
++ CKCTL_6368_PCM_EN | \
++ CKCTL_6368_USBH_EN | \
+ CKCTL_6368_DISABLE_GLESS_EN | \
+- CKCTL_6368_NAND_CLK_EN | \
+- CKCTL_6368_IPSEC_CLK_EN)
++ CKCTL_6368_NAND_EN | \
++ CKCTL_6368_IPSEC_EN)
+
+ /* System PLL Control register */
+ #define PERF_SYS_PLL_CTL_REG 0x8
diff --git a/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch b/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch
new file mode 100644
index 000000000..b4c787c52
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/003-MIPS-BCM63XX-add-IRQ_SPI-and-CPU-specific-SPI-IRQ-va.patch
@@ -0,0 +1,68 @@
+From 04456614952a9a848192253439b4e361f0321cb5 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:51 +0100
+Subject: [PATCH 05/63] MIPS: BCM63XX: add IRQ_SPI and CPU specific SPI IRQ values
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -478,6 +478,7 @@ static inline unsigned long bcm63xx_regs
+ */
+ enum bcm63xx_irq {
+ IRQ_TIMER = 0,
++ IRQ_SPI,
+ IRQ_UART0,
+ IRQ_UART1,
+ IRQ_DSL,
+@@ -509,6 +510,7 @@ enum bcm63xx_irq {
+ * 6338 irqs
+ */
+ #define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6338_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
+ #define BCM_6338_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+ #define BCM_6338_UART1_IRQ 0
+ #define BCM_6338_DSL_IRQ (IRQ_INTERNAL_BASE + 5)
+@@ -539,6 +541,7 @@ enum bcm63xx_irq {
+ * 6345 irqs
+ */
+ #define BCM_6345_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6345_SPI_IRQ 0
+ #define BCM_6345_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+ #define BCM_6345_UART1_IRQ 0
+ #define BCM_6345_DSL_IRQ (IRQ_INTERNAL_BASE + 3)
+@@ -569,6 +572,7 @@ enum bcm63xx_irq {
+ * 6348 irqs
+ */
+ #define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6348_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
+ #define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+ #define BCM_6348_UART1_IRQ 0
+ #define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
+@@ -599,6 +603,7 @@ enum bcm63xx_irq {
+ * 6358 irqs
+ */
+ #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6358_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
+ #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+ #define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
+ #define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29)
+@@ -638,6 +643,7 @@ enum bcm63xx_irq {
+ #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
+
+ #define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6368_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
+ #define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
+ #define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
+ #define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
+@@ -677,6 +683,7 @@ extern const int *bcm63xx_irqs;
+
+ #define __GEN_CPU_IRQ_TABLE(__cpu) \
+ [IRQ_TIMER] = BCM_## __cpu ##_TIMER_IRQ, \
++ [IRQ_SPI] = BCM_## __cpu ##_SPI_IRQ, \
+ [IRQ_UART0] = BCM_## __cpu ##_UART0_IRQ, \
+ [IRQ_UART1] = BCM_## __cpu ##_UART1_IRQ, \
+ [IRQ_DSL] = BCM_## __cpu ##_DSL_IRQ, \
diff --git a/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch b/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch
new file mode 100644
index 000000000..0c314da74
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/004-MIPS-BCM63XX-define-BCM6358-SPI-base-address.patch
@@ -0,0 +1,21 @@
+From bfd78dda2ad5afb4434ebe99c05528614065bdb1 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:56 +0100
+Subject: [PATCH 06/63] MIPS: BCM63XX: define BCM6358 SPI base address
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -289,7 +289,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_UART0_BASE (0xfffe0100)
+ #define BCM_6358_UART1_BASE (0xfffe0120)
+ #define BCM_6358_GPIO_BASE (0xfffe0080)
+-#define BCM_6358_SPI_BASE (0xdeadbeef)
++#define BCM_6358_SPI_BASE (0xfffe0800)
+ #define BCM_6358_SPI2_BASE (0xfffe0800)
+ #define BCM_6358_UDC0_BASE (0xfffe0800)
+ #define BCM_6358_OHCI0_BASE (0xfffe1400)
diff --git a/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch b/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch
new file mode 100644
index 000000000..b7fac8448
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/005-MIPS-BCM63XX-add-BCM6368-SPI-clock-mask.patch
@@ -0,0 +1,26 @@
+From 9b990ee00f70bdd6a731dbe264d5acb453a6c5e2 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:57 +0100
+Subject: [PATCH 07/63] MIPS: BCM63XX: add BCM6368 SPI clock mask
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/bcm63xx/clk.c | 6 ++++--
+ 1 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -181,9 +181,11 @@ static void spi_set(struct clk *clk, int
+ mask = CKCTL_6338_SPI_EN;
+ else if (BCMCPU_IS_6348())
+ mask = CKCTL_6348_SPI_EN;
+- else
+- /* BCMCPU_IS_6358 */
++ else if (BCMCPU_IS_6358())
+ mask = CKCTL_6358_SPI_EN;
++ else
++ /* BCMCPU_IS_6368 */
++ mask = CKCTL_6368_SPI_EN;
+ bcm_hwclock_set(mask, enable);
+ }
+
diff --git a/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch b/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch
new file mode 100644
index 000000000..0eab43a18
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/006-MIPS-BCM63XX-define-SPI-register-sizes.patch
@@ -0,0 +1,26 @@
+From 16ba44545156e4e7cc1e812ad93e562ce92fd74c Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:40:00 +0100
+Subject: [PATCH 08/63] MIPS: BCM63XX: define SPI register sizes.
+
+There are two distinct sizes for the SPI register depending on the SoC
+generation (6338 & 6348 vs 6358 & 6368).
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -135,6 +135,10 @@ enum bcm63xx_regs_set {
+ #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4)
+ #define RSET_DSL_SIZE 4096
+ #define RSET_WDT_SIZE 12
++#define BCM_6338_RSET_SPI_SIZE 64
++#define BCM_6348_RSET_SPI_SIZE 64
++#define BCM_6358_RSET_SPI_SIZE 1804
++#define BCM_6368_RSET_SPI_SIZE 1804
+ #define RSET_ENET_SIZE 2048
+ #define RSET_ENETDMA_SIZE 2048
+ #define RSET_ENETSW_SIZE 65536
diff --git a/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch b/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch
new file mode 100644
index 000000000..cafef10db
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/007-MIPS-BCM63XX-remove-SPI2-register.patch
@@ -0,0 +1,83 @@
+From 32511e7dfab9b9cabe2772e3f5430559294a8d1c Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:40:01 +0100
+Subject: [PATCH 09/63] MIPS: BCM63XX: remove SPI2 register
+
+This register was introduced with the support of the BCM6368 CPU in the idea
+that its internal layout was different from the other CPUs SPI controller.
+The controller is actually the same as the one present on BCM6358 so we can
+remove this register and use the usual SPI register instead.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 10 +---------
+ 1 files changed, 1 insertions(+), 9 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -102,7 +102,6 @@ enum bcm63xx_regs_set {
+ RSET_UART1,
+ RSET_GPIO,
+ RSET_SPI,
+- RSET_SPI2,
+ RSET_UDC0,
+ RSET_OHCI0,
+ RSET_OHCI_PRIV,
+@@ -166,7 +165,6 @@ enum bcm63xx_regs_set {
+ #define BCM_6338_UART1_BASE (0xdeadbeef)
+ #define BCM_6338_GPIO_BASE (0xfffe0400)
+ #define BCM_6338_SPI_BASE (0xfffe0c00)
+-#define BCM_6338_SPI2_BASE (0xdeadbeef)
+ #define BCM_6338_UDC0_BASE (0xdeadbeef)
+ #define BCM_6338_USBDMA_BASE (0xfffe2400)
+ #define BCM_6338_OHCI0_BASE (0xdeadbeef)
+@@ -210,7 +208,6 @@ enum bcm63xx_regs_set {
+ #define BCM_6345_UART1_BASE (0xdeadbeef)
+ #define BCM_6345_GPIO_BASE (0xfffe0400)
+ #define BCM_6345_SPI_BASE (0xdeadbeef)
+-#define BCM_6345_SPI2_BASE (0xdeadbeef)
+ #define BCM_6345_UDC0_BASE (0xdeadbeef)
+ #define BCM_6345_USBDMA_BASE (0xfffe2800)
+ #define BCM_6345_ENET0_BASE (0xfffe1800)
+@@ -253,7 +250,6 @@ enum bcm63xx_regs_set {
+ #define BCM_6348_UART1_BASE (0xdeadbeef)
+ #define BCM_6348_GPIO_BASE (0xfffe0400)
+ #define BCM_6348_SPI_BASE (0xfffe0c00)
+-#define BCM_6348_SPI2_BASE (0xdeadbeef)
+ #define BCM_6348_UDC0_BASE (0xfffe1000)
+ #define BCM_6348_OHCI0_BASE (0xfffe1b00)
+ #define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00)
+@@ -294,7 +290,6 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_UART1_BASE (0xfffe0120)
+ #define BCM_6358_GPIO_BASE (0xfffe0080)
+ #define BCM_6358_SPI_BASE (0xfffe0800)
+-#define BCM_6358_SPI2_BASE (0xfffe0800)
+ #define BCM_6358_UDC0_BASE (0xfffe0800)
+ #define BCM_6358_OHCI0_BASE (0xfffe1400)
+ #define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef)
+@@ -335,8 +330,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6368_UART0_BASE (0xb0000100)
+ #define BCM_6368_UART1_BASE (0xb0000120)
+ #define BCM_6368_GPIO_BASE (0xb0000080)
+-#define BCM_6368_SPI_BASE (0xdeadbeef)
+-#define BCM_6368_SPI2_BASE (0xb0000800)
++#define BCM_6368_SPI_BASE (0xb0000800)
+ #define BCM_6368_UDC0_BASE (0xdeadbeef)
+ #define BCM_6368_OHCI0_BASE (0xb0001600)
+ #define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef)
+@@ -383,7 +377,6 @@ extern const unsigned long *bcm63xx_regs
+ __GEN_RSET_BASE(__cpu, UART1) \
+ __GEN_RSET_BASE(__cpu, GPIO) \
+ __GEN_RSET_BASE(__cpu, SPI) \
+- __GEN_RSET_BASE(__cpu, SPI2) \
+ __GEN_RSET_BASE(__cpu, UDC0) \
+ __GEN_RSET_BASE(__cpu, OHCI0) \
+ __GEN_RSET_BASE(__cpu, OHCI_PRIV) \
+@@ -422,7 +415,6 @@ extern const unsigned long *bcm63xx_regs
+ [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \
+ [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \
+ [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \
+- [RSET_SPI2] = BCM_## __cpu ##_SPI2_BASE, \
+ [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \
+ [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \
+ [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \
diff --git a/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch b/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch
new file mode 100644
index 000000000..d3968fc81
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/008-MIPS-BCM63XX-define-internal-registers-offsets-of-th.patch
@@ -0,0 +1,140 @@
+From 81f9e7d6aa1dde65483387ba9e9823ef44f90435 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:40:03 +0100
+Subject: [PATCH 10/63] MIPS: BCM63XX: define internal registers offsets of the SPI controller
+
+BCM6338, BCM6348, BCM6358 and BCM6368 basically use the same SPI controller
+though the internal registers are shuffled, which still allows a common
+driver to drive that IP block.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 119 +++++++++++++++++++++
+ 1 files changed, 119 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -973,4 +973,123 @@
+ #define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14)
+ #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18)
+
++/*************************************************************************
++ * _REG relative to RSET_SPI
++ *************************************************************************/
++
++/* BCM 6338 SPI core */
++#define SPI_6338_CMD 0x00 /* 16-bits register */
++#define SPI_6338_INT_STATUS 0x02
++#define SPI_6338_INT_MASK_ST 0x03
++#define SPI_6338_INT_MASK 0x04
++#define SPI_6338_ST 0x05
++#define SPI_6338_CLK_CFG 0x06
++#define SPI_6338_FILL_BYTE 0x07
++#define SPI_6338_MSG_TAIL 0x09
++#define SPI_6338_RX_TAIL 0x0b
++#define SPI_6338_MSG_CTL 0x40
++#define SPI_6338_MSG_DATA 0x41
++#define SPI_6338_MSG_DATA_SIZE 0x3f
++#define SPI_6338_RX_DATA 0x80
++#define SPI_6338_RX_DATA_SIZE 0x3f
++
++/* BCM 6348 SPI core */
++#define SPI_6348_CMD 0x00 /* 16-bits register */
++#define SPI_6348_INT_STATUS 0x02
++#define SPI_6348_INT_MASK_ST 0x03
++#define SPI_6348_INT_MASK 0x04
++#define SPI_6348_ST 0x05
++#define SPI_6348_CLK_CFG 0x06
++#define SPI_6348_FILL_BYTE 0x07
++#define SPI_6348_MSG_TAIL 0x09
++#define SPI_6348_RX_TAIL 0x0b
++#define SPI_6348_MSG_CTL 0x40
++#define SPI_6348_MSG_DATA 0x41
++#define SPI_6348_MSG_DATA_SIZE 0x3f
++#define SPI_6348_RX_DATA 0x80
++#define SPI_6348_RX_DATA_SIZE 0x3f
++
++/* BCM 6358 SPI core */
++#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
++#define SPI_6358_MSG_DATA 0x02
++#define SPI_6358_MSG_DATA_SIZE 0x21e
++#define SPI_6358_RX_DATA 0x400
++#define SPI_6358_RX_DATA_SIZE 0x220
++#define SPI_6358_CMD 0x700 /* 16-bits register */
++#define SPI_6358_INT_STATUS 0x702
++#define SPI_6358_INT_MASK_ST 0x703
++#define SPI_6358_INT_MASK 0x704
++#define SPI_6358_ST 0x705
++#define SPI_6358_CLK_CFG 0x706
++#define SPI_6358_FILL_BYTE 0x707
++#define SPI_6358_MSG_TAIL 0x709
++#define SPI_6358_RX_TAIL 0x70B
++
++/* BCM 6358 SPI core */
++#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
++#define SPI_6368_MSG_DATA 0x02
++#define SPI_6368_MSG_DATA_SIZE 0x21e
++#define SPI_6368_RX_DATA 0x400
++#define SPI_6368_RX_DATA_SIZE 0x220
++#define SPI_6368_CMD 0x700 /* 16-bits register */
++#define SPI_6368_INT_STATUS 0x702
++#define SPI_6368_INT_MASK_ST 0x703
++#define SPI_6368_INT_MASK 0x704
++#define SPI_6368_ST 0x705
++#define SPI_6368_CLK_CFG 0x706
++#define SPI_6368_FILL_BYTE 0x707
++#define SPI_6368_MSG_TAIL 0x709
++#define SPI_6368_RX_TAIL 0x70B
++
++/* Shared SPI definitions */
++
++/* Message configuration */
++#define SPI_FD_RW 0x00
++#define SPI_HD_W 0x01
++#define SPI_HD_R 0x02
++#define SPI_BYTE_CNT_SHIFT 0
++#define SPI_MSG_TYPE_SHIFT 14
++
++/* Command */
++#define SPI_CMD_NOOP 0x00
++#define SPI_CMD_SOFT_RESET 0x01
++#define SPI_CMD_HARD_RESET 0x02
++#define SPI_CMD_START_IMMEDIATE 0x03
++#define SPI_CMD_COMMAND_SHIFT 0
++#define SPI_CMD_COMMAND_MASK 0x000f
++#define SPI_CMD_DEVICE_ID_SHIFT 4
++#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
++#define SPI_CMD_ONE_BYTE_SHIFT 11
++#define SPI_CMD_ONE_WIRE_SHIFT 12
++#define SPI_DEV_ID_0 0
++#define SPI_DEV_ID_1 1
++#define SPI_DEV_ID_2 2
++#define SPI_DEV_ID_3 3
++
++/* Interrupt mask */
++#define SPI_INTR_CMD_DONE 0x01
++#define SPI_INTR_RX_OVERFLOW 0x02
++#define SPI_INTR_TX_UNDERFLOW 0x04
++#define SPI_INTR_TX_OVERFLOW 0x08
++#define SPI_INTR_RX_UNDERFLOW 0x10
++#define SPI_INTR_CLEAR_ALL 0x1f
++
++/* Status */
++#define SPI_RX_EMPTY 0x02
++#define SPI_CMD_BUSY 0x04
++#define SPI_SERIAL_BUSY 0x08
++
++/* Clock configuration */
++#define SPI_CLK_20MHZ 0x00
++#define SPI_CLK_0_391MHZ 0x01
++#define SPI_CLK_0_781MHZ 0x02 /* default */
++#define SPI_CLK_1_563MHZ 0x03
++#define SPI_CLK_3_125MHZ 0x04
++#define SPI_CLK_6_250MHZ 0x05
++#define SPI_CLK_12_50MHZ 0x06
++#define SPI_CLK_MASK 0x07
++#define SPI_SSOFFTIME_MASK 0x38
++#define SPI_SSOFFTIME_SHIFT 3
++#define SPI_BYTE_SWAP 0x80
++
+ #endif /* BCM63XX_REGS_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch b/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch
new file mode 100644
index 000000000..a46041fd6
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/009-MIPS-BCM63XX-add-stub-to-register-the-SPI-platform-d.patch
@@ -0,0 +1,243 @@
+From af84327888c7081662a6b949754fc54d32a50503 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:40:04 +0100
+Subject: [PATCH 11/63] MIPS: BCM63XX: add stub to register the SPI platform driver
+
+This patch adds the necessary stub to register the SPI platform driver.
+Since the registers are shuffled between the 4 BCM63xx CPUs supported by
+this SPI driver we also need to generate the internal register layout and
+export this layout for the driver to use it properly.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/bcm63xx/Makefile | 3 +-
+ arch/mips/bcm63xx/dev-spi.c | 119 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_spi.h | 89 +++++++++++++++
+ 3 files changed, 210 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-spi.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,5 +1,6 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o
++ dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \
++ dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-spi.c
+@@ -0,0 +1,119 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
++ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/export.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_spi.h>
++#include <bcm63xx_regs.h>
++
++#ifdef BCMCPU_RUNTIME_DETECT
++/*
++ * register offsets
++ */
++static const unsigned long bcm6338_regs_spi[] = {
++ __GEN_SPI_REGS_TABLE(6338)
++};
++
++static const unsigned long bcm6348_regs_spi[] = {
++ __GEN_SPI_REGS_TABLE(6348)
++};
++
++static const unsigned long bcm6358_regs_spi[] = {
++ __GEN_SPI_REGS_TABLE(6358)
++};
++
++static const unsigned long bcm6368_regs_spi[] = {
++ __GEN_SPI_REGS_TABLE(6368)
++};
++
++const unsigned long *bcm63xx_regs_spi;
++EXPORT_SYMBOL(bcm63xx_regs_spi);
++
++static __init void bcm63xx_spi_regs_init(void)
++{
++ if (BCMCPU_IS_6338())
++ bcm63xx_regs_spi = bcm6338_regs_spi;
++ if (BCMCPU_IS_6348())
++ bcm63xx_regs_spi = bcm6348_regs_spi;
++ if (BCMCPU_IS_6358())
++ bcm63xx_regs_spi = bcm6358_regs_spi;
++ if (BCMCPU_IS_6368())
++ bcm63xx_regs_spi = bcm6368_regs_spi;
++}
++#else
++static __init void bcm63xx_spi_regs_init(void) { }
++#endif
++
++static struct resource spi_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct bcm63xx_spi_pdata spi_pdata = {
++ .bus_num = 0,
++ .num_chipselect = 8,
++};
++
++static struct platform_device bcm63xx_spi_device = {
++ .name = "bcm63xx-spi",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(spi_resources),
++ .resource = spi_resources,
++ .dev = {
++ .platform_data = &spi_pdata,
++ },
++};
++
++int __init bcm63xx_spi_register(void)
++{
++ struct clk *periph_clk;
++
++ if (BCMCPU_IS_6345())
++ return -ENODEV;
++
++ periph_clk = clk_get(NULL, "periph");
++ if (IS_ERR(periph_clk)) {
++ pr_err("unable to get periph clock\n");
++ return -ENODEV;
++ }
++
++ /* Set bus frequency */
++ spi_pdata.speed_hz = clk_get_rate(periph_clk);
++
++ spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
++ spi_resources[0].end = spi_resources[0].start;
++ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
++
++ if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
++ spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
++ spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
++ }
++
++ if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
++ spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
++ spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
++ }
++
++ bcm63xx_spi_regs_init();
++
++ return platform_device_register(&bcm63xx_spi_device);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+@@ -0,0 +1,89 @@
++#ifndef BCM63XX_DEV_SPI_H
++#define BCM63XX_DEV_SPI_H
++
++#include <linux/types.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_regs.h>
++
++int __init bcm63xx_spi_register(void);
++
++struct bcm63xx_spi_pdata {
++ unsigned int fifo_size;
++ int bus_num;
++ int num_chipselect;
++ u32 speed_hz;
++};
++
++enum bcm63xx_regs_spi {
++ SPI_CMD,
++ SPI_INT_STATUS,
++ SPI_INT_MASK_ST,
++ SPI_INT_MASK,
++ SPI_ST,
++ SPI_CLK_CFG,
++ SPI_FILL_BYTE,
++ SPI_MSG_TAIL,
++ SPI_RX_TAIL,
++ SPI_MSG_CTL,
++ SPI_MSG_DATA,
++ SPI_RX_DATA,
++};
++
++#define __GEN_SPI_RSET_BASE(__cpu, __rset) \
++ case SPI_## __rset: \
++ return SPI_## __cpu ##_## __rset;
++
++#define __GEN_SPI_RSET(__cpu) \
++ switch (reg) { \
++ __GEN_SPI_RSET_BASE(__cpu, CMD) \
++ __GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \
++ __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \
++ __GEN_SPI_RSET_BASE(__cpu, INT_MASK) \
++ __GEN_SPI_RSET_BASE(__cpu, ST) \
++ __GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \
++ __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \
++ __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \
++ __GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \
++ __GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \
++ __GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \
++ __GEN_SPI_RSET_BASE(__cpu, RX_DATA) \
++ }
++
++#define __GEN_SPI_REGS_TABLE(__cpu) \
++ [SPI_CMD] = SPI_## __cpu ##_CMD, \
++ [SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \
++ [SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \
++ [SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \
++ [SPI_ST] = SPI_## __cpu ##_ST, \
++ [SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \
++ [SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \
++ [SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \
++ [SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \
++ [SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \
++ [SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \
++ [SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA,
++
++static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
++{
++#ifdef BCMCPU_RUNTIME_DETECT
++ extern const unsigned long *bcm63xx_regs_spi;
++
++ return bcm63xx_regs_spi[reg];
++#else
++#ifdef CONFIG_BCM63XX_CPU_6338
++ __GEN_SPI_RSET(6338)
++#endif
++#ifdef CONFIG_BCM63XX_CPU_6348
++ __GEN_SPI_RSET(6348)
++#endif
++#ifdef CONFIG_BCM63XX_CPU_6358
++ __GEN_SPI_RSET(6358)
++#endif
++#ifdef CONFIG_BCM63XX_CPU_6368
++ __GEN_SPI_RSET(6368)
++#endif
++#endif
++ return 0;
++}
++
++#endif /* BCM63XX_DEV_SPI_H */
diff --git a/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch b/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch
new file mode 100644
index 000000000..516569679
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/010-MIPS-BCM63XX-make-board-setup-code-register-the-spi-.patch
@@ -0,0 +1,29 @@
+From fab0cbda27ab2400d6a461bf144007a0d5337527 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:40:05 +0100
+Subject: [PATCH 12/63] MIPS: BCM63XX: make board setup code register the spi platform device
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -25,6 +25,7 @@
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
+ #include <bcm63xx_dev_pcmcia.h>
++#include <bcm63xx_dev_spi.h>
+ #include <board_bcm963xx.h>
+
+ #define PFX "board_bcm963xx: "
+@@ -890,6 +891,8 @@ int __init board_register_devices(void)
+ }
+ #endif
+
++ bcm63xx_spi_register();
++
+ /* read base address of boot chip select (0) */
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+ val &= MPI_CSBASE_BASE_MASK;
diff --git a/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch b/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch
new file mode 100644
index 000000000..e4939599a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/011-spi-add-Broadcom-BCM63xx-SPI-controller-driver.patch
@@ -0,0 +1,532 @@
+From 5f592b818a2c5731bb12137e7cffc3aa6e24ee5a Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 1 Feb 2012 09:14:09 +0000
+Subject: [PATCH 13/63] spi: add Broadcom BCM63xx SPI controller driver
+
+This patch adds support for the SPI controller found on the Broadcom BCM63xx
+SoCs.
+
+Signed-off-by: Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/spi/Kconfig | 6 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-bcm63xx.c | 486 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 493 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/spi/spi-bcm63xx.c
+
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -94,6 +94,12 @@ config SPI_AU1550
+ If you say yes to this option, support will be included for the
+ PSC SPI controller found on Au1550, Au1200 and Au1300 series.
+
++config SPI_BCM63XX
++ tristate "Broadcom BCM63xx SPI controller"
++ depends on BCM63XX
++ help
++ Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
++
+ config SPI_BITBANG
+ tristate "Utilities for Bitbanging SPI masters"
+ help
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.
+ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
+ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
++obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
+ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
+ obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
+ obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
+--- /dev/null
++++ b/drivers/spi/spi-bcm63xx.c
+@@ -0,0 +1,486 @@
++/*
++ * Broadcom BCM63xx SPI controller support
++ *
++ * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
++ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This 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., 51 Franklin Street, Fifth Floor,
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/spi/spi.h>
++#include <linux/completion.h>
++#include <linux/err.h>
++
++#include <bcm63xx_dev_spi.h>
++
++#define PFX KBUILD_MODNAME
++#define DRV_VER "0.1.2"
++
++struct bcm63xx_spi {
++ spinlock_t lock;
++ int stopping;
++ struct completion done;
++
++ void __iomem *regs;
++ int irq;
++
++ /* Platform data */
++ u32 speed_hz;
++ unsigned fifo_size;
++
++ /* Data buffers */
++ const unsigned char *tx_ptr;
++ unsigned char *rx_ptr;
++
++ /* data iomem */
++ u8 __iomem *tx_io;
++ const u8 __iomem *rx_io;
++
++ int remaining_bytes;
++
++ struct clk *clk;
++ struct platform_device *pdev;
++};
++
++static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
++ unsigned int offset)
++{
++ return bcm_readb(bs->regs + bcm63xx_spireg(offset));
++}
++
++static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
++ unsigned int offset)
++{
++ return bcm_readw(bs->regs + bcm63xx_spireg(offset));
++}
++
++static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
++ u8 value, unsigned int offset)
++{
++ bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
++}
++
++static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
++ u16 value, unsigned int offset)
++{
++ bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
++}
++
++static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
++ { 20000000, SPI_CLK_20MHZ },
++ { 12500000, SPI_CLK_12_50MHZ },
++ { 6250000, SPI_CLK_6_250MHZ },
++ { 3125000, SPI_CLK_3_125MHZ },
++ { 1563000, SPI_CLK_1_563MHZ },
++ { 781000, SPI_CLK_0_781MHZ },
++ { 391000, SPI_CLK_0_391MHZ }
++};
++
++static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
++ struct spi_transfer *t)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
++ u8 bits_per_word;
++ u8 clk_cfg, reg;
++ u32 hz;
++ int i;
++
++ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
++ hz = (t) ? t->speed_hz : spi->max_speed_hz;
++ if (bits_per_word != 8) {
++ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
++ __func__, bits_per_word);
++ return -EINVAL;
++ }
++
++ if (spi->chip_select > spi->master->num_chipselect) {
++ dev_err(&spi->dev, "%s, unsupported slave %d\n",
++ __func__, spi->chip_select);
++ return -EINVAL;
++ }
++
++ /* Find the closest clock configuration */
++ for (i = 0; i < SPI_CLK_MASK; i++) {
++ if (hz >= bcm63xx_spi_freq_table[i][0]) {
++ clk_cfg = bcm63xx_spi_freq_table[i][1];
++ break;
++ }
++ }
++
++ /* No matching configuration found, default to lowest */
++ if (i == SPI_CLK_MASK)
++ clk_cfg = SPI_CLK_0_391MHZ;
++
++ /* clear existing clock configuration bits of the register */
++ reg = bcm_spi_readb(bs, SPI_CLK_CFG);
++ reg &= ~SPI_CLK_MASK;
++ reg |= clk_cfg;
++
++ bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
++ dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
++ clk_cfg, hz);
++
++ return 0;
++}
++
++/* the spi->mode bits understood by this driver: */
++#define MODEBITS (SPI_CPOL | SPI_CPHA)
++
++static int bcm63xx_spi_setup(struct spi_device *spi)
++{
++ struct bcm63xx_spi *bs;
++ int ret;
++
++ bs = spi_master_get_devdata(spi->master);
++
++ if (bs->stopping)
++ return -ESHUTDOWN;
++
++ if (!spi->bits_per_word)
++ spi->bits_per_word = 8;
++
++ if (spi->mode & ~MODEBITS) {
++ dev_err(&spi->dev, "%s, unsupported mode bits %x\n",
++ __func__, spi->mode & ~MODEBITS);
++ return -EINVAL;
++ }
++
++ ret = bcm63xx_spi_setup_transfer(spi, NULL);
++ if (ret < 0) {
++ dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
++ spi->mode & ~MODEBITS);
++ return ret;
++ }
++
++ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec/bit\n",
++ __func__, spi->mode & MODEBITS, spi->bits_per_word, 0);
++
++ return 0;
++}
++
++/* Fill the TX FIFO with as many bytes as possible */
++static void bcm63xx_spi_fill_tx_fifo(struct bcm63xx_spi *bs)
++{
++ u8 size;
++
++ /* Fill the Tx FIFO with as many bytes as possible */
++ size = bs->remaining_bytes < bs->fifo_size ? bs->remaining_bytes :
++ bs->fifo_size;
++ memcpy_toio(bs->tx_io, bs->tx_ptr, size);
++ bs->remaining_bytes -= size;
++}
++
++static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
++ u16 msg_ctl;
++ u16 cmd;
++
++ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
++ t->tx_buf, t->rx_buf, t->len);
++
++ /* Transmitter is inhibited */
++ bs->tx_ptr = t->tx_buf;
++ bs->rx_ptr = t->rx_buf;
++ init_completion(&bs->done);
++
++ if (t->tx_buf) {
++ bs->remaining_bytes = t->len;
++ bcm63xx_spi_fill_tx_fifo(bs);
++ }
++
++ /* Enable the command done interrupt which
++ * we use to determine completion of a command */
++ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
++
++ /* Fill in the Message control register */
++ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
++
++ if (t->rx_buf && t->tx_buf)
++ msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
++ else if (t->rx_buf)
++ msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
++ else if (t->tx_buf)
++ msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
++
++ bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
++
++ /* Issue the transfer */
++ cmd = SPI_CMD_START_IMMEDIATE;
++ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
++ cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
++ bcm_spi_writew(bs, cmd, SPI_CMD);
++ wait_for_completion(&bs->done);
++
++ /* Disable the CMD_DONE interrupt */
++ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
++
++ return t->len - bs->remaining_bytes;
++}
++
++static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
++ struct spi_transfer *t;
++ int ret = 0;
++
++ if (unlikely(list_empty(&m->transfers)))
++ return -EINVAL;
++
++ if (bs->stopping)
++ return -ESHUTDOWN;
++
++ list_for_each_entry(t, &m->transfers, transfer_list) {
++ ret += bcm63xx_txrx_bufs(spi, t);
++ }
++
++ m->complete(m->context);
++
++ return ret;
++}
++
++/* This driver supports single master mode only. Hence
++ * CMD_DONE is the only interrupt we care about
++ */
++static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
++{
++ struct spi_master *master = (struct spi_master *)dev_id;
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++ u8 intr;
++ u16 cmd;
++
++ /* Read interupts and clear them immediately */
++ intr = bcm_spi_readb(bs, SPI_INT_STATUS);
++ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
++ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
++
++ /* A tansfer completed */
++ if (intr & SPI_INTR_CMD_DONE) {
++ u8 rx_tail;
++
++ rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
++
++ /* Read out all the data */
++ if (rx_tail)
++ memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
++
++ /* See if there is more data to send */
++ if (bs->remaining_bytes > 0) {
++ bcm63xx_spi_fill_tx_fifo(bs);
++
++ /* Start the transfer */
++ bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT,
++ SPI_MSG_CTL);
++ cmd = bcm_spi_readw(bs, SPI_CMD);
++ cmd |= SPI_CMD_START_IMMEDIATE;
++ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
++ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
++ bcm_spi_writew(bs, cmd, SPI_CMD);
++ } else {
++ complete(&bs->done);
++ }
++ }
++
++ return IRQ_HANDLED;
++}
++
++
++static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
++{
++ struct resource *r;
++ struct device *dev = &pdev->dev;
++ struct bcm63xx_spi_pdata *pdata = pdev->dev.platform_data;
++ int irq;
++ struct spi_master *master;
++ struct clk *clk;
++ struct bcm63xx_spi *bs;
++ int ret;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r) {
++ dev_err(dev, "no iomem\n");
++ ret = -ENXIO;
++ goto out;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(dev, "no irq\n");
++ ret = -ENXIO;
++ goto out;
++ }
++
++ clk = clk_get(dev, "spi");
++ if (IS_ERR(clk)) {
++ dev_err(dev, "no clock for device\n");
++ ret = PTR_ERR(clk);
++ goto out;
++ }
++
++ master = spi_alloc_master(dev, sizeof(*bs));
++ if (!master) {
++ dev_err(dev, "out of memory\n");
++ ret = -ENOMEM;
++ goto out_clk;
++ }
++
++ bs = spi_master_get_devdata(master);
++ init_completion(&bs->done);
++
++ platform_set_drvdata(pdev, master);
++ bs->pdev = pdev;
++
++ if (!devm_request_mem_region(&pdev->dev, r->start,
++ resource_size(r), PFX)) {
++ dev_err(dev, "iomem request failed\n");
++ ret = -ENXIO;
++ goto out_err;
++ }
++
++ bs->regs = devm_ioremap_nocache(&pdev->dev, r->start,
++ resource_size(r));
++ if (!bs->regs) {
++ dev_err(dev, "unable to ioremap regs\n");
++ ret = -ENOMEM;
++ goto out_err;
++ }
++
++ bs->irq = irq;
++ bs->clk = clk;
++ bs->fifo_size = pdata->fifo_size;
++
++ ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
++ pdev->name, master);
++ if (ret) {
++ dev_err(dev, "unable to request irq\n");
++ goto out_err;
++ }
++
++ master->bus_num = pdata->bus_num;
++ master->num_chipselect = pdata->num_chipselect;
++ master->setup = bcm63xx_spi_setup;
++ master->transfer = bcm63xx_transfer;
++ bs->speed_hz = pdata->speed_hz;
++ bs->stopping = 0;
++ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
++ bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
++ spin_lock_init(&bs->lock);
++
++ /* Initialize hardware */
++ clk_enable(bs->clk);
++ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
++
++ /* register and we are done */
++ ret = spi_register_master(master);
++ if (ret) {
++ dev_err(dev, "spi register failed\n");
++ goto out_clk_disable;
++ }
++
++ dev_info(dev, "at 0x%08x (irq %d, FIFOs size %d) v%s\n",
++ r->start, irq, bs->fifo_size, DRV_VER);
++
++ return 0;
++
++out_clk_disable:
++ clk_disable(clk);
++out_err:
++ platform_set_drvdata(pdev, NULL);
++ spi_master_put(master);
++out_clk:
++ clk_put(clk);
++out:
++ return ret;
++}
++
++static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++
++ /* reset spi block */
++ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
++ spin_lock(&bs->lock);
++ bs->stopping = 1;
++
++ /* HW shutdown */
++ clk_disable(bs->clk);
++ clk_put(bs->clk);
++
++ spin_unlock(&bs->lock);
++ platform_set_drvdata(pdev, 0);
++ spi_unregister_master(master);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int bcm63xx_spi_suspend(struct device *dev)
++{
++ struct spi_master *master =
++ platform_get_drvdata(to_platform_device(dev));
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++
++ clk_disable(bs->clk);
++
++ return 0;
++}
++
++static int bcm63xx_spi_resume(struct device *dev)
++{
++ struct spi_master *master =
++ platform_get_drvdata(to_platform_device(dev));
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++
++ clk_enable(bs->clk);
++
++ return 0;
++}
++
++static const struct dev_pm_ops bcm63xx_spi_pm_ops = {
++ .suspend = bcm63xx_spi_suspend,
++ .resume = bcm63xx_spi_resume,
++};
++
++#define BCM63XX_SPI_PM_OPS (&bcm63xx_spi_pm_ops)
++#else
++#define BCM63XX_SPI_PM_OPS NULL
++#endif
++
++static struct platform_driver bcm63xx_spi_driver = {
++ .driver = {
++ .name = "bcm63xx-spi",
++ .owner = THIS_MODULE,
++ .pm = BCM63XX_SPI_PM_OPS,
++ },
++ .probe = bcm63xx_spi_probe,
++ .remove = __devexit_p(bcm63xx_spi_remove),
++};
++
++module_platform_driver(bcm63xx_spi_driver);
++
++MODULE_ALIAS("platform:bcm63xx_spi");
++MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
++MODULE_AUTHOR("Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>");
++MODULE_DESCRIPTION("Broadcom BCM63xx SPI Controller driver");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm63xx/patches-3.3/012-mtd-bcm63xxpart-handle-Broadcom-partition-order.patch b/target/linux/brcm63xx/patches-3.3/012-mtd-bcm63xxpart-handle-Broadcom-partition-order.patch
new file mode 100644
index 000000000..b12aed6b9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/012-mtd-bcm63xxpart-handle-Broadcom-partition-order.patch
@@ -0,0 +1,101 @@
+From a73c2d9dc7ea0d14fbf48db48e783d123162f5c3 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 19 Apr 2012 13:15:57 +0200
+Subject: [PATCH] mtd: bcm63xxpart: handle Broadcom partition order
+
+The original Broadcom partition order has the root fs in front of the
+kernel, which resulted in miscalculated partition sizes.
+Detect when such an image is on the flash and also reorder the partitions
+accordingly.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Acked-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com>
+---
+ drivers/mtd/bcm63xxpart.c | 41 ++++++++++++++++++++++++++++++-----------
+ 1 file changed, 30 insertions(+), 11 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -4,7 +4,7 @@
+ * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org>
+ * Mike Albon <malbon@openwrt.org>
+ * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net>
+- * Copyright © 2011 Jonas Gorski <jonas.gorski@gmail.com>
++ * Copyright © 2011-2012 Jonas Gorski <jonas.gorski@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -82,6 +82,7 @@ static int bcm63xx_parse_cfe_partitions(
+ int namelen = 0;
+ int i;
+ u32 computed_crc;
++ bool rootfs_first = false;
+
+ if (bcm63xx_detect_cfe(master))
+ return -EINVAL;
+@@ -109,6 +110,7 @@ static int bcm63xx_parse_cfe_partitions(
+ char *boardid = &(buf->board_id[0]);
+ char *tagversion = &(buf->tag_version[0]);
+
++ sscanf(buf->flash_image_start, "%u", &rootfsaddr);
+ sscanf(buf->kernel_address, "%u", &kerneladdr);
+ sscanf(buf->kernel_length, "%u", &kernellen);
+ sscanf(buf->total_length, "%u", &totallen);
+@@ -117,10 +119,19 @@ static int bcm63xx_parse_cfe_partitions(
+ tagversion, boardid);
+
+ kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
+- rootfsaddr = kerneladdr + kernellen;
++ rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
+ spareaddr = roundup(totallen, master->erasesize) + cfelen;
+ sparelen = master->size - spareaddr - nvramlen;
+- rootfslen = spareaddr - rootfsaddr;
++
++ if (rootfsaddr < kerneladdr) {
++ /* default Broadcom layout */
++ rootfslen = kerneladdr - rootfsaddr;
++ rootfs_first = true;
++ } else {
++ /* OpenWrt layout */
++ rootfsaddr = kerneladdr + kernellen;
++ rootfslen = spareaddr - rootfsaddr;
++ }
+ } else {
+ pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
+ buf->header_crc, computed_crc);
+@@ -156,18 +167,26 @@ static int bcm63xx_parse_cfe_partitions(
+ curpart++;
+
+ if (kernellen > 0) {
+- parts[curpart].name = "kernel";
+- parts[curpart].offset = kerneladdr;
+- parts[curpart].size = kernellen;
++ int kernelpart = curpart;
++
++ if (rootfslen > 0 && rootfs_first)
++ kernelpart++;
++ parts[kernelpart].name = "kernel";
++ parts[kernelpart].offset = kerneladdr;
++ parts[kernelpart].size = kernellen;
+ curpart++;
+ }
+
+ if (rootfslen > 0) {
+- parts[curpart].name = "rootfs";
+- parts[curpart].offset = rootfsaddr;
+- parts[curpart].size = rootfslen;
+- if (sparelen > 0)
+- parts[curpart].size += sparelen;
++ int rootfspart = curpart;
++
++ if (kernellen > 0 && rootfs_first)
++ rootfspart--;
++ parts[rootfspart].name = "rootfs";
++ parts[rootfspart].offset = rootfsaddr;
++ parts[rootfspart].size = rootfslen;
++ if (sparelen > 0 && !rootfs_first)
++ parts[rootfspart].size += sparelen;
+ curpart++;
+ }
+
diff --git a/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch b/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch
new file mode 100644
index 000000000..7d4d9514d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/013-spi-bcm63xx-convert-to-the-pump-message-infrastructu.patch
@@ -0,0 +1,289 @@
+From cde4384e1037c15e5dd04c68d19c75798b6281dd Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Fri, 20 Apr 2012 15:37:33 +0200
+Subject: [PATCH] spi/bcm63xx: convert to the pump message infrastructure
+
+This patch converts the bcm63xx SPI driver to use the SPI infrastructure
+pump message queue. Since we were previously sleeping in the SPI
+driver's transfer() function (which is not allowed) this is now fixed as well.
+
+To complete that conversion a certain number of changes have been made:
+- the transfer len is split into multiple hardware transfers in case its
+ size is bigger than the hardware FIFO size
+- the FIFO refill is no longer done in the interrupt context, which was a
+ bad idea leading to quick interrupt handler re-entrancy
+
+Tested-by: Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/spi/spi-bcm63xx.c | 149 +++++++++++++++++++++++++++------------------
+ 1 file changed, 89 insertions(+), 60 deletions(-)
+
+--- a/drivers/spi/spi-bcm63xx.c
++++ b/drivers/spi/spi-bcm63xx.c
+@@ -1,7 +1,7 @@
+ /*
+ * Broadcom BCM63xx SPI controller support
+ *
+- * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
++ * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -30,6 +30,8 @@
+ #include <linux/spi/spi.h>
+ #include <linux/completion.h>
+ #include <linux/err.h>
++#include <linux/workqueue.h>
++#include <linux/pm_runtime.h>
+
+ #include <bcm63xx_dev_spi.h>
+
+@@ -96,17 +98,12 @@ static const unsigned bcm63xx_spi_freq_t
+ { 391000, SPI_CLK_0_391MHZ }
+ };
+
+-static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
+- struct spi_transfer *t)
++static int bcm63xx_spi_check_transfer(struct spi_device *spi,
++ struct spi_transfer *t)
+ {
+- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+ u8 bits_per_word;
+- u8 clk_cfg, reg;
+- u32 hz;
+- int i;
+
+ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
+- hz = (t) ? t->speed_hz : spi->max_speed_hz;
+ if (bits_per_word != 8) {
+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+ __func__, bits_per_word);
+@@ -119,6 +116,19 @@ static int bcm63xx_spi_setup_transfer(st
+ return -EINVAL;
+ }
+
++ return 0;
++}
++
++static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
++ struct spi_transfer *t)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
++ u32 hz;
++ u8 clk_cfg, reg;
++ int i;
++
++ hz = (t) ? t->speed_hz : spi->max_speed_hz;
++
+ /* Find the closest clock configuration */
+ for (i = 0; i < SPI_CLK_MASK; i++) {
+ if (hz >= bcm63xx_spi_freq_table[i][0]) {
+@@ -139,8 +149,6 @@ static int bcm63xx_spi_setup_transfer(st
+ bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
+ dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
+ clk_cfg, hz);
+-
+- return 0;
+ }
+
+ /* the spi->mode bits understood by this driver: */
+@@ -165,7 +173,7 @@ static int bcm63xx_spi_setup(struct spi_
+ return -EINVAL;
+ }
+
+- ret = bcm63xx_spi_setup_transfer(spi, NULL);
++ ret = bcm63xx_spi_check_transfer(spi, NULL);
+ if (ret < 0) {
+ dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
+ spi->mode & ~MODEBITS);
+@@ -190,28 +198,29 @@ static void bcm63xx_spi_fill_tx_fifo(str
+ bs->remaining_bytes -= size;
+ }
+
+-static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
++static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
++ struct spi_transfer *t)
+ {
+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+ u16 msg_ctl;
+ u16 cmd;
+
++ /* Disable the CMD_DONE interrupt */
++ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
++
+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
+ t->tx_buf, t->rx_buf, t->len);
+
+ /* Transmitter is inhibited */
+ bs->tx_ptr = t->tx_buf;
+ bs->rx_ptr = t->rx_buf;
+- init_completion(&bs->done);
+
+ if (t->tx_buf) {
+ bs->remaining_bytes = t->len;
+ bcm63xx_spi_fill_tx_fifo(bs);
+ }
+
+- /* Enable the command done interrupt which
+- * we use to determine completion of a command */
+- bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
++ init_completion(&bs->done);
+
+ /* Fill in the Message control register */
+ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
+@@ -230,33 +239,76 @@ static int bcm63xx_txrx_bufs(struct spi_
+ cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
+ cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
+ bcm_spi_writew(bs, cmd, SPI_CMD);
+- wait_for_completion(&bs->done);
+
+- /* Disable the CMD_DONE interrupt */
+- bcm_spi_writeb(bs, 0, SPI_INT_MASK);
++ /* Enable the CMD_DONE interrupt */
++ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
+
+ return t->len - bs->remaining_bytes;
+ }
+
+-static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m)
++static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
+ {
+- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+- struct spi_transfer *t;
+- int ret = 0;
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+
+- if (unlikely(list_empty(&m->transfers)))
+- return -EINVAL;
++ pm_runtime_get_sync(&bs->pdev->dev);
+
+- if (bs->stopping)
+- return -ESHUTDOWN;
++ return 0;
++}
++
++static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++
++ pm_runtime_put(&bs->pdev->dev);
++
++ return 0;
++}
++
++static int bcm63xx_spi_transfer_one(struct spi_master *master,
++ struct spi_message *m)
++{
++ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
++ struct spi_transfer *t;
++ struct spi_device *spi = m->spi;
++ int status = 0;
++ unsigned int timeout = 0;
+
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+- ret += bcm63xx_txrx_bufs(spi, t);
+- }
++ unsigned int len = t->len;
++ u8 rx_tail;
+
+- m->complete(m->context);
++ status = bcm63xx_spi_check_transfer(spi, t);
++ if (status < 0)
++ goto exit;
++
++ /* configure adapter for a new transfer */
++ bcm63xx_spi_setup_transfer(spi, t);
++
++ while (len) {
++ /* send the data */
++ len -= bcm63xx_txrx_bufs(spi, t);
++
++ timeout = wait_for_completion_timeout(&bs->done, HZ);
++ if (!timeout) {
++ status = -ETIMEDOUT;
++ goto exit;
++ }
++
++ /* read out all data */
++ rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
++
++ /* Read out all the data */
++ if (rx_tail)
++ memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
++ }
++
++ m->actual_length += t->len;
++ }
++exit:
++ m->status = status;
++ spi_finalize_current_message(master);
+
+- return ret;
++ return 0;
+ }
+
+ /* This driver supports single master mode only. Hence
+@@ -267,39 +319,15 @@ static irqreturn_t bcm63xx_spi_interrupt
+ struct spi_master *master = (struct spi_master *)dev_id;
+ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+ u8 intr;
+- u16 cmd;
+
+ /* Read interupts and clear them immediately */
+ intr = bcm_spi_readb(bs, SPI_INT_STATUS);
+ bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
+ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+
+- /* A tansfer completed */
+- if (intr & SPI_INTR_CMD_DONE) {
+- u8 rx_tail;
+-
+- rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
+-
+- /* Read out all the data */
+- if (rx_tail)
+- memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
+-
+- /* See if there is more data to send */
+- if (bs->remaining_bytes > 0) {
+- bcm63xx_spi_fill_tx_fifo(bs);
+-
+- /* Start the transfer */
+- bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT,
+- SPI_MSG_CTL);
+- cmd = bcm_spi_readw(bs, SPI_CMD);
+- cmd |= SPI_CMD_START_IMMEDIATE;
+- cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
+- bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
+- bcm_spi_writew(bs, cmd, SPI_CMD);
+- } else {
+- complete(&bs->done);
+- }
+- }
++ /* A transfer completed */
++ if (intr & SPI_INTR_CMD_DONE)
++ complete(&bs->done);
+
+ return IRQ_HANDLED;
+ }
+@@ -345,7 +373,6 @@ static int __devinit bcm63xx_spi_probe(s
+ }
+
+ bs = spi_master_get_devdata(master);
+- init_completion(&bs->done);
+
+ platform_set_drvdata(pdev, master);
+ bs->pdev = pdev;
+@@ -379,7 +406,9 @@ static int __devinit bcm63xx_spi_probe(s
+ master->bus_num = pdata->bus_num;
+ master->num_chipselect = pdata->num_chipselect;
+ master->setup = bcm63xx_spi_setup;
+- master->transfer = bcm63xx_transfer;
++ master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
++ master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
++ master->transfer_one_message = bcm63xx_spi_transfer_one;
+ bs->speed_hz = pdata->speed_hz;
+ bs->stopping = 0;
+ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
diff --git a/target/linux/brcm63xx/patches-3.3/014-spi-bcm63xx-don-t-use-the-stopping-state.patch b/target/linux/brcm63xx/patches-3.3/014-spi-bcm63xx-don-t-use-the-stopping-state.patch
new file mode 100644
index 000000000..98bc90980
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/014-spi-bcm63xx-don-t-use-the-stopping-state.patch
@@ -0,0 +1,68 @@
+From 1e41dc0ee2f3807328db95e4f87ff1333245190f Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Fri, 20 Apr 2012 15:37:34 +0200
+Subject: [PATCH] spi/bcm63xx: don't use the stopping state
+
+We do not need to use a flag to indicate if the master driver is stopping
+it is sufficient to perform spi master unregistering in the platform
+driver's remove function.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/spi/spi-bcm63xx.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+--- a/drivers/spi/spi-bcm63xx.c
++++ b/drivers/spi/spi-bcm63xx.c
+@@ -39,8 +39,6 @@
+ #define DRV_VER "0.1.2"
+
+ struct bcm63xx_spi {
+- spinlock_t lock;
+- int stopping;
+ struct completion done;
+
+ void __iomem *regs;
+@@ -161,9 +159,6 @@ static int bcm63xx_spi_setup(struct spi_
+
+ bs = spi_master_get_devdata(spi->master);
+
+- if (bs->stopping)
+- return -ESHUTDOWN;
+-
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+@@ -410,10 +405,8 @@ static int __devinit bcm63xx_spi_probe(s
+ master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
+ master->transfer_one_message = bcm63xx_spi_transfer_one;
+ bs->speed_hz = pdata->speed_hz;
+- bs->stopping = 0;
+ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
+ bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
+- spin_lock_init(&bs->lock);
+
+ /* Initialize hardware */
+ clk_enable(bs->clk);
+@@ -447,18 +440,16 @@ static int __devexit bcm63xx_spi_remove(
+ struct spi_master *master = platform_get_drvdata(pdev);
+ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+
++ spi_unregister_master(master);
++
+ /* reset spi block */
+ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+- spin_lock(&bs->lock);
+- bs->stopping = 1;
+
+ /* HW shutdown */
+ clk_disable(bs->clk);
+ clk_put(bs->clk);
+
+- spin_unlock(&bs->lock);
+ platform_set_drvdata(pdev, 0);
+- spi_unregister_master(master);
+
+ return 0;
+ }
diff --git a/target/linux/brcm63xx/patches-3.3/015-spi-bcm63xx-set-master-driver-mode_bits.patch b/target/linux/brcm63xx/patches-3.3/015-spi-bcm63xx-set-master-driver-mode_bits.patch
new file mode 100644
index 000000000..8b934d002
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/015-spi-bcm63xx-set-master-driver-mode_bits.patch
@@ -0,0 +1,24 @@
+From 88a3a255a510ed193bf0cc35424761c3c9247586 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Fri, 20 Apr 2012 15:37:35 +0200
+Subject: [PATCH] spi/bcm63xx: set master driver mode_bits.
+
+We were not properly advertising the MODE bits supported by this driver, fix
+that.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/spi/spi-bcm63xx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/spi/spi-bcm63xx.c
++++ b/drivers/spi/spi-bcm63xx.c
+@@ -404,6 +404,7 @@ static int __devinit bcm63xx_spi_probe(s
+ master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
+ master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
+ master->transfer_one_message = bcm63xx_spi_transfer_one;
++ master->mode_bits = MODEBITS;
+ bs->speed_hz = pdata->speed_hz;
+ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
+ bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
diff --git a/target/linux/brcm63xx/patches-3.3/016-spi-bcm63xx-fix-bcm6348-38.patch b/target/linux/brcm63xx/patches-3.3/016-spi-bcm63xx-fix-bcm6348-38.patch
new file mode 100644
index 000000000..ce532571d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/016-spi-bcm63xx-fix-bcm6348-38.patch
@@ -0,0 +1,128 @@
+--- a/arch/mips/bcm63xx/dev-spi.c
++++ b/arch/mips/bcm63xx/dev-spi.c
+@@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void)
+ if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
+ spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
+ spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
++ spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT;
++ spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
+ }
+
+ if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
+ spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
+ spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
++ spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
++ spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
+ }
+
+ bcm63xx_spi_regs_init();
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+@@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void);
+
+ struct bcm63xx_spi_pdata {
+ unsigned int fifo_size;
++ unsigned int msg_type_shift;
++ unsigned int msg_ctl_width;
+ int bus_num;
+ int num_chipselect;
+ u32 speed_hz;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -987,7 +987,8 @@
+ #define SPI_6338_FILL_BYTE 0x07
+ #define SPI_6338_MSG_TAIL 0x09
+ #define SPI_6338_RX_TAIL 0x0b
+-#define SPI_6338_MSG_CTL 0x40
++#define SPI_6338_MSG_CTL 0x40 /* 8-bits register */
++#define SPI_6338_MSG_CTL_WIDTH 8
+ #define SPI_6338_MSG_DATA 0x41
+ #define SPI_6338_MSG_DATA_SIZE 0x3f
+ #define SPI_6338_RX_DATA 0x80
+@@ -1003,7 +1004,8 @@
+ #define SPI_6348_FILL_BYTE 0x07
+ #define SPI_6348_MSG_TAIL 0x09
+ #define SPI_6348_RX_TAIL 0x0b
+-#define SPI_6348_MSG_CTL 0x40
++#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */
++#define SPI_6348_MSG_CTL_WIDTH 8
+ #define SPI_6348_MSG_DATA 0x41
+ #define SPI_6348_MSG_DATA_SIZE 0x3f
+ #define SPI_6348_RX_DATA 0x80
+@@ -1011,6 +1013,7 @@
+
+ /* BCM 6358 SPI core */
+ #define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
++#define SPI_6358_MSG_CTL_WIDTH 16
+ #define SPI_6358_MSG_DATA 0x02
+ #define SPI_6358_MSG_DATA_SIZE 0x21e
+ #define SPI_6358_RX_DATA 0x400
+@@ -1027,6 +1030,7 @@
+
+ /* BCM 6358 SPI core */
+ #define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
++#define SPI_6368_MSG_CTL_WIDTH 16
+ #define SPI_6368_MSG_DATA 0x02
+ #define SPI_6368_MSG_DATA_SIZE 0x21e
+ #define SPI_6368_RX_DATA 0x400
+@@ -1048,7 +1052,10 @@
+ #define SPI_HD_W 0x01
+ #define SPI_HD_R 0x02
+ #define SPI_BYTE_CNT_SHIFT 0
+-#define SPI_MSG_TYPE_SHIFT 14
++#define SPI_6338_MSG_TYPE_SHIFT 6
++#define SPI_6348_MSG_TYPE_SHIFT 6
++#define SPI_6358_MSG_TYPE_SHIFT 14
++#define SPI_6368_MSG_TYPE_SHIFT 14
+
+ /* Command */
+ #define SPI_CMD_NOOP 0x00
+--- a/drivers/spi/spi-bcm63xx.c
++++ b/drivers/spi/spi-bcm63xx.c
+@@ -47,6 +47,8 @@ struct bcm63xx_spi {
+ /* Platform data */
+ u32 speed_hz;
+ unsigned fifo_size;
++ unsigned int msg_type_shift;
++ unsigned int msg_ctl_width;
+
+ /* Data buffers */
+ const unsigned char *tx_ptr;
+@@ -221,13 +223,24 @@ static unsigned int bcm63xx_txrx_bufs(st
+ msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
+
+ if (t->rx_buf && t->tx_buf)
+- msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
++ msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
+ else if (t->rx_buf)
+- msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
++ msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
+ else if (t->tx_buf)
+- msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
++ msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
+
+- bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
++ switch (bs->msg_ctl_width) {
++ case 8:
++ bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
++ break;
++ case 16:
++ bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
++ break;
++ default:
++ dev_err(&spi->dev, "unknown MSG_CTL width: %d\n",
++ bs->msg_ctl_width);
++ return 0;
++ }
+
+ /* Issue the transfer */
+ cmd = SPI_CMD_START_IMMEDIATE;
+@@ -406,6 +419,8 @@ static int __devinit bcm63xx_spi_probe(s
+ master->transfer_one_message = bcm63xx_spi_transfer_one;
+ master->mode_bits = MODEBITS;
+ bs->speed_hz = pdata->speed_hz;
++ bs->msg_type_shift = pdata->msg_type_shift;
++ bs->msg_ctl_width = pdata->msg_ctl_width;
+ bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
+ bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
+
diff --git a/target/linux/brcm63xx/patches-3.3/017-MIPS-BCM63XX-fix-BCM6368-IPSec-clock-bit.patch b/target/linux/brcm63xx/patches-3.3/017-MIPS-BCM63XX-fix-BCM6368-IPSec-clock-bit.patch
new file mode 100644
index 000000000..81f87c610
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/017-MIPS-BCM63XX-fix-BCM6368-IPSec-clock-bit.patch
@@ -0,0 +1,23 @@
+From 41ee87b6ddd525fab54e21ede506f2084bcabed3 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Wed, 25 Jan 2012 17:39:52 +0100
+Subject: [PATCH 14/63] MIPS: BCM63XX: fix BCM6368 IPSec clock bit
+
+The IPsec clock bit is 18 and not 17.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -99,7 +99,7 @@
+ #define CKCTL_6368_USBH_EN (1 << 15)
+ #define CKCTL_6368_DISABLE_GLESS_EN (1 << 16)
+ #define CKCTL_6368_NAND_EN (1 << 17)
+-#define CKCTL_6368_IPSEC_EN (1 << 17)
++#define CKCTL_6368_IPSEC_EN (1 << 18)
+
+ #define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \
+ CKCTL_6368_SWPKT_SAR_EN | \
diff --git a/target/linux/brcm63xx/patches-3.3/018-MIPS-BCM63XX-add-support-for-ipsec-clock.patch b/target/linux/brcm63xx/patches-3.3/018-MIPS-BCM63XX-add-support-for-ipsec-clock.patch
new file mode 100644
index 000000000..6fffc1925
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/018-MIPS-BCM63XX-add-support-for-ipsec-clock.patch
@@ -0,0 +1,48 @@
+From 0fec0136456ce214ea4df6b8ff3b3728befc816a Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Tue, 31 Jan 2012 15:12:22 +0100
+Subject: [PATCH 3/6] MIPS: BCM63XX: add support for "ipsec" clock
+
+This module is only available on BCM6368 so far and does not require
+resetting the block.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: mpm@selenic.com
+Cc: herbert@gondor.apana.org.au
+Patchwork: https://patchwork.linux-mips.org/patch/3324/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/clk.c | 14 ++++++++++++++
+ 1 files changed, 14 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -224,6 +224,18 @@ static struct clk clk_xtm = {
+ };
+
+ /*
++ * IPsec clock
++ */
++static void ipsec_set(struct clk *clk, int enable)
++{
++ bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
++}
++
++static struct clk clk_ipsec = {
++ .set = ipsec_set,
++};
++
++/*
+ * Internal peripheral clock
+ */
+ static struct clk clk_periph = {
+@@ -280,6 +292,8 @@ struct clk *clk_get(struct device *dev,
+ return &clk_periph;
+ if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
+ return &clk_pcm;
++ if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
++ return &clk_ipsec;
+ return ERR_PTR(-ENOENT);
+ }
+
diff --git a/target/linux/brcm63xx/patches-3.3/019-MIPS-BCM63XX-add-RNG-peripheral-definitions.patch b/target/linux/brcm63xx/patches-3.3/019-MIPS-BCM63XX-add-RNG-peripheral-definitions.patch
new file mode 100644
index 000000000..cd7bf37e9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/019-MIPS-BCM63XX-add-RNG-peripheral-definitions.patch
@@ -0,0 +1,113 @@
+From 357761c423c0f9e4af4aafe85be7889dc36f3584 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Tue, 31 Jan 2012 15:12:23 +0100
+Subject: [PATCH 4/6] MIPS: BCM63XX: add RNG peripheral definitions
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: mpm@selenic.com
+Cc: herbert@gondor.apana.org.au
+Patchwork: https://patchwork.linux-mips.org/patch/3326/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 9 +++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 14 ++++++++++++++
+ 2 files changed, 23 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -129,6 +129,7 @@ enum bcm63xx_regs_set {
+ RSET_PCMDMA,
+ RSET_PCMDMAC,
+ RSET_PCMDMAS,
++ RSET_RNG
+ };
+
+ #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4)
+@@ -152,6 +153,7 @@ enum bcm63xx_regs_set {
+ #define RSET_XTMDMA_SIZE 256
+ #define RSET_XTMDMAC_SIZE(chans) (16 * (chans))
+ #define RSET_XTMDMAS_SIZE(chans) (16 * (chans))
++#define RSET_RNG_SIZE 20
+
+ /*
+ * 6338 register sets base address
+@@ -195,6 +197,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6338_PCMDMA_BASE (0xdeadbeef)
+ #define BCM_6338_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6338_PCMDMAS_BASE (0xdeadbeef)
++#define BCM_6338_RNG_BASE (0xdeadbeef)
+
+ /*
+ * 6345 register sets base address
+@@ -238,6 +241,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6345_PCMDMA_BASE (0xdeadbeef)
+ #define BCM_6345_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6345_PCMDMAS_BASE (0xdeadbeef)
++#define BCM_6345_RNG_BASE (0xdeadbeef)
+
+ /*
+ * 6348 register sets base address
+@@ -278,6 +282,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6348_PCMDMA_BASE (0xdeadbeef)
+ #define BCM_6348_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6348_PCMDMAS_BASE (0xdeadbeef)
++#define BCM_6348_RNG_BASE (0xdeadbeef)
+
+ /*
+ * 6358 register sets base address
+@@ -318,6 +323,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_PCMDMA_BASE (0xfffe1800)
+ #define BCM_6358_PCMDMAC_BASE (0xfffe1900)
+ #define BCM_6358_PCMDMAS_BASE (0xfffe1a00)
++#define BCM_6358_RNG_BASE (0xdeadbeef)
+
+
+ /*
+@@ -359,6 +365,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6368_PCMDMA_BASE (0xb0005800)
+ #define BCM_6368_PCMDMAC_BASE (0xb0005a00)
+ #define BCM_6368_PCMDMAS_BASE (0xb0005c00)
++#define BCM_6368_RNG_BASE (0xb0004180)
+
+
+ extern const unsigned long *bcm63xx_regs_base;
+@@ -404,6 +411,7 @@ extern const unsigned long *bcm63xx_regs
+ __GEN_RSET_BASE(__cpu, PCMDMA) \
+ __GEN_RSET_BASE(__cpu, PCMDMAC) \
+ __GEN_RSET_BASE(__cpu, PCMDMAS) \
++ __GEN_RSET_BASE(__cpu, RNG) \
+ }
+
+ #define __GEN_CPU_REGS_TABLE(__cpu) \
+@@ -442,6 +450,7 @@ extern const unsigned long *bcm63xx_regs
+ [RSET_PCMDMA] = BCM_## __cpu ##_PCMDMA_BASE, \
+ [RSET_PCMDMAC] = BCM_## __cpu ##_PCMDMAC_BASE, \
+ [RSET_PCMDMAS] = BCM_## __cpu ##_PCMDMAS_BASE, \
++ [RSET_RNG] = BCM_## __cpu ##_RNG_BASE, \
+
+
+ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -974,6 +974,20 @@
+ #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18)
+
+ /*************************************************************************
++ * _REG relative to RSET_RNG
++ *************************************************************************/
++
++#define RNG_CTRL 0x00
++#define RNG_EN (1 << 0)
++
++#define RNG_STAT 0x04
++#define RNG_AVAIL_MASK (0xff000000)
++
++#define RNG_DATA 0x08
++#define RNG_THRES 0x0c
++#define RNG_MASK 0x10
++
++/*************************************************************************
+ * _REG relative to RSET_SPI
+ *************************************************************************/
+
diff --git a/target/linux/brcm63xx/patches-3.3/020-MIPS-BCM63XX-add-RNG-driver-platform_device-stub.patch b/target/linux/brcm63xx/patches-3.3/020-MIPS-BCM63XX-add-RNG-driver-platform_device-stub.patch
new file mode 100644
index 000000000..d759c5722
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/020-MIPS-BCM63XX-add-RNG-driver-platform_device-stub.patch
@@ -0,0 +1,71 @@
+From 79fed26f65c22e0d67c9523f7a374f0585bd2803 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Tue, 31 Jan 2012 15:12:24 +0100
+Subject: [PATCH 5/6] MIPS: BCM63XX: add RNG driver platform_device stub
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: mpm@selenic.com
+Cc: herbert@gondor.apana.org.au
+Patchwork: https://patchwork.linux-mips.org/patch/3325/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/Makefile | 4 ++--
+ arch/mips/bcm63xx/dev-rng.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 42 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-rng.c
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-pcmcia.o dev-spi.o dev-uart.o \
+- dev-wdt.o
++ dev-dsp.o dev-enet.o dev-pcmcia.o dev-rng.o dev-spi.o \
++ dev-uart.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-rng.c
+@@ -0,0 +1,40 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2011 Florian Fainelli <florian@openwrt.org>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <bcm63xx_cpu.h>
++
++static struct resource rng_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++};
++
++static struct platform_device bcm63xx_rng_device = {
++ .name = "bcm63xx-rng",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(rng_resources),
++ .resource = rng_resources,
++};
++
++int __init bcm63xx_rng_register(void)
++{
++ if (!BCMCPU_IS_6368())
++ return -ENODEV;
++
++ rng_resources[0].start = bcm63xx_regset_address(RSET_RNG);
++ rng_resources[0].end = rng_resources[0].start;
++ rng_resources[0].end += RSET_RNG_SIZE - 1;
++
++ return platform_device_register(&bcm63xx_rng_device);
++}
++arch_initcall(bcm63xx_rng_register);
diff --git a/target/linux/brcm63xx/patches-3.3/021-hw_random-add-Broadcom-BCM63xx-RNG-driver.patch b/target/linux/brcm63xx/patches-3.3/021-hw_random-add-Broadcom-BCM63xx-RNG-driver.patch
new file mode 100644
index 000000000..7e66fd52a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/021-hw_random-add-Broadcom-BCM63xx-RNG-driver.patch
@@ -0,0 +1,229 @@
+From 1cfc5c76c5f48359716bd804daef2f2f7554fb4a Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Tue, 31 Jan 2012 15:12:25 +0100
+Subject: [PATCH 6/6] hw_random: add Broadcom BCM63xx RNG driver
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Cc: linux-mips@linux-mips.org
+Cc: mpm@selenic.com
+Cc: herbert@gondor.apana.org.au
+Patchwork: https://patchwork.linux-mips.org/patch/3327/
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ drivers/char/hw_random/Kconfig | 14 +++
+ drivers/char/hw_random/Makefile | 1 +
+ drivers/char/hw_random/bcm63xx-rng.c | 175 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 190 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/char/hw_random/bcm63xx-rng.c
+
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -73,6 +73,20 @@ config HW_RANDOM_ATMEL
+
+ If unsure, say Y.
+
++config HW_RANDOM_BCM63XX
++ tristate "Broadcom BCM63xx Random Number Generator support"
++ depends on HW_RANDOM && BCM63XX
++ default HW_RANDOM
++ ---help---
++ This driver provides kernel-side support for the Random Number
++ Generator hardware found on the Broadcom BCM63xx SoCs.
++
++ To compile this driver as a module, choose M here: the
++ module will be called bcm63xx-rng
++
++ If unusure, say Y.
++
++
+ config HW_RANDOM_GEODE
+ tristate "AMD Geode HW Random Number Generator support"
+ depends on HW_RANDOM && X86_32 && PCI
+--- a/drivers/char/hw_random/Makefile
++++ b/drivers/char/hw_random/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += ti
+ obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
+ obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+ obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
++obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o
+ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
+ obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
+ n2-rng-y := n2-drv.o n2-asm.o
+--- /dev/null
++++ b/drivers/char/hw_random/bcm63xx-rng.c
+@@ -0,0 +1,175 @@
++/*
++ * Broadcom BCM63xx Random Number Generator support
++ *
++ * Copyright (C) 2011, Florian Fainelli <florian@openwrt.org>
++ * Copyright (C) 2009, Broadcom Corporation
++ *
++ */
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/io.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/hw_random.h>
++
++#include <bcm63xx_io.h>
++#include <bcm63xx_regs.h>
++
++struct bcm63xx_rng_priv {
++ struct clk *clk;
++ void __iomem *regs;
++};
++
++#define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv)
++
++static int bcm63xx_rng_init(struct hwrng *rng)
++{
++ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
++ u32 val;
++
++ val = bcm_readl(priv->regs + RNG_CTRL);
++ val |= RNG_EN;
++ bcm_writel(val, priv->regs + RNG_CTRL);
++
++ return 0;
++}
++
++static void bcm63xx_rng_cleanup(struct hwrng *rng)
++{
++ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
++ u32 val;
++
++ val = bcm_readl(priv->regs + RNG_CTRL);
++ val &= ~RNG_EN;
++ bcm_writel(val, priv->regs + RNG_CTRL);
++}
++
++static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
++{
++ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
++
++ return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK;
++}
++
++static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data)
++{
++ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
++
++ *data = bcm_readl(priv->regs + RNG_DATA);
++
++ return 4;
++}
++
++static int __init bcm63xx_rng_probe(struct platform_device *pdev)
++{
++ struct resource *r;
++ struct clk *clk;
++ int ret;
++ struct bcm63xx_rng_priv *priv;
++ struct hwrng *rng;
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!r) {
++ dev_err(&pdev->dev, "no iomem resource\n");
++ ret = -ENXIO;
++ goto out;
++ }
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv) {
++ dev_err(&pdev->dev, "no memory for private structure\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ rng = kzalloc(sizeof(*rng), GFP_KERNEL);
++ if (!rng) {
++ dev_err(&pdev->dev, "no memory for rng structure\n");
++ ret = -ENOMEM;
++ goto out_free_priv;
++ }
++
++ platform_set_drvdata(pdev, rng);
++ rng->priv = (unsigned long)priv;
++ rng->name = pdev->name;
++ rng->init = bcm63xx_rng_init;
++ rng->cleanup = bcm63xx_rng_cleanup;
++ rng->data_present = bcm63xx_rng_data_present;
++ rng->data_read = bcm63xx_rng_data_read;
++
++ clk = clk_get(&pdev->dev, "ipsec");
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "no clock for device\n");
++ ret = PTR_ERR(clk);
++ goto out_free_rng;
++ }
++
++ priv->clk = clk;
++
++ if (!devm_request_mem_region(&pdev->dev, r->start,
++ resource_size(r), pdev->name)) {
++ dev_err(&pdev->dev, "request mem failed");
++ ret = -ENOMEM;
++ goto out_free_rng;
++ }
++
++ priv->regs = devm_ioremap_nocache(&pdev->dev, r->start,
++ resource_size(r));
++ if (!priv->regs) {
++ dev_err(&pdev->dev, "ioremap failed");
++ ret = -ENOMEM;
++ goto out_free_rng;
++ }
++
++ clk_enable(clk);
++
++ ret = hwrng_register(rng);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to register rng device\n");
++ goto out_clk_disable;
++ }
++
++ dev_info(&pdev->dev, "registered RNG driver\n");
++
++ return 0;
++
++out_clk_disable:
++ clk_disable(clk);
++out_free_rng:
++ platform_set_drvdata(pdev, NULL);
++ kfree(rng);
++out_free_priv:
++ kfree(priv);
++out:
++ return ret;
++}
++
++static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
++{
++ struct hwrng *rng = platform_get_drvdata(pdev);
++ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
++
++ hwrng_unregister(rng);
++ clk_disable(priv->clk);
++ kfree(priv);
++ kfree(rng);
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++static struct platform_driver bcm63xx_rng_driver = {
++ .probe = bcm63xx_rng_probe,
++ .remove = __devexit_p(bcm63xx_rng_remove),
++ .driver = {
++ .name = "bcm63xx-rng",
++ .owner = THIS_MODULE,
++ },
++};
++
++module_platform_driver(bcm63xx_rng_driver);
++
++MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
++MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm63xx/patches-3.3/022-MIPS-BCM63XX-Move-flash-registration-out-of-board_bc.patch b/target/linux/brcm63xx/patches-3.3/022-MIPS-BCM63XX-Move-flash-registration-out-of-board_bc.patch
new file mode 100644
index 000000000..e9c85a2a6
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/022-MIPS-BCM63XX-Move-flash-registration-out-of-board_bc.patch
@@ -0,0 +1,202 @@
+From bfe47f0f68b5f7a3a92d07266cba58b188fe10e7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 12 Jun 2012 10:23:38 +0200
+Subject: [PATCH 1/8] MIPS: BCM63XX: Move flash registration out of board_bcm963xx.c
+
+board_bcm963xx.c is already large enough.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3952/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/Makefile | 4 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 49 +-------------
+ arch/mips/bcm63xx/dev-flash.c | 69 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 6 ++
+ 4 files changed, 79 insertions(+), 49 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-flash.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-pcmcia.o dev-rng.o dev-spi.o \
+- dev-uart.o dev-wdt.o
++ dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
++ dev-spi.o dev-uart.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -11,9 +11,6 @@
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/platform_device.h>
+-#include <linux/mtd/mtd.h>
+-#include <linux/mtd/partitions.h>
+-#include <linux/mtd/physmap.h>
+ #include <linux/ssb/ssb.h>
+ #include <asm/addrspace.h>
+ #include <bcm63xx_board.h>
+@@ -24,6 +21,7 @@
+ #include <bcm63xx_dev_pci.h>
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
++#include <bcm63xx_dev_flash.h>
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
+ #include <board_bcm963xx.h>
+@@ -809,40 +807,6 @@ void __init board_setup(void)
+ panic("unexpected CPU for bcm963xx board");
+ }
+
+-static struct mtd_partition mtd_partitions[] = {
+- {
+- .name = "cfe",
+- .offset = 0x0,
+- .size = 0x40000,
+- }
+-};
+-
+-static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
+-
+-static struct physmap_flash_data flash_data = {
+- .width = 2,
+- .nr_parts = ARRAY_SIZE(mtd_partitions),
+- .parts = mtd_partitions,
+- .part_probe_types = bcm63xx_part_types,
+-};
+-
+-static struct resource mtd_resources[] = {
+- {
+- .start = 0, /* filled at runtime */
+- .end = 0, /* filled at runtime */
+- .flags = IORESOURCE_MEM,
+- }
+-};
+-
+-static struct platform_device mtd_dev = {
+- .name = "physmap-flash",
+- .resource = mtd_resources,
+- .num_resources = ARRAY_SIZE(mtd_resources),
+- .dev = {
+- .platform_data = &flash_data,
+- },
+-};
+-
+ static struct gpio_led_platform_data bcm63xx_led_data;
+
+ static struct platform_device bcm63xx_gpio_leds = {
+@@ -856,8 +820,6 @@ static struct platform_device bcm63xx_gp
+ */
+ int __init board_register_devices(void)
+ {
+- u32 val;
+-
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+
+@@ -893,14 +855,7 @@ int __init board_register_devices(void)
+
+ bcm63xx_spi_register();
+
+- /* read base address of boot chip select (0) */
+- val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+- val &= MPI_CSBASE_BASE_MASK;
+-
+- mtd_resources[0].start = val;
+- mtd_resources[0].end = 0x1FFFFFFF;
+-
+- platform_device_register(&mtd_dev);
++ bcm63xx_flash_register();
+
+ bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
+ bcm63xx_led_data.leds = board.leds;
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -0,0 +1,69 @@
++/*
++ * Broadcom BCM63xx flash registration
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/physmap.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_flash.h>
++#include <bcm63xx_regs.h>
++#include <bcm63xx_io.h>
++
++static struct mtd_partition mtd_partitions[] = {
++ {
++ .name = "cfe",
++ .offset = 0x0,
++ .size = 0x40000,
++ }
++};
++
++static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
++
++static struct physmap_flash_data flash_data = {
++ .width = 2,
++ .parts = mtd_partitions,
++ .part_probe_types = bcm63xx_part_types,
++};
++
++static struct resource mtd_resources[] = {
++ {
++ .start = 0, /* filled at runtime */
++ .end = 0, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device mtd_dev = {
++ .name = "physmap-flash",
++ .resource = mtd_resources,
++ .num_resources = ARRAY_SIZE(mtd_resources),
++ .dev = {
++ .platform_data = &flash_data,
++ },
++};
++
++int __init bcm63xx_flash_register(void)
++{
++ u32 val;
++
++ /* read base address of boot chip select (0) */
++ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ val &= MPI_CSBASE_BASE_MASK;
++
++ mtd_resources[0].start = val;
++ mtd_resources[0].end = 0x1FFFFFFF;
++
++ return platform_device_register(&mtd_dev);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -0,0 +1,6 @@
++#ifndef __BCM63XX_FLASH_H
++#define __BCM63XX_FLASH_H
++
++int __init bcm63xx_flash_register(void);
++
++#endif /* __BCM63XX_FLASH_H */
diff --git a/target/linux/brcm63xx/patches-3.3/023-MIPS-BCM63XX-Add-flash-type-detection.patch b/target/linux/brcm63xx/patches-3.3/023-MIPS-BCM63XX-Add-flash-type-detection.patch
new file mode 100644
index 000000000..b0f13abba
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/023-MIPS-BCM63XX-Add-flash-type-detection.patch
@@ -0,0 +1,137 @@
+From 0c921d542eb4359791cffd1737bf45184f6ae352 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 12 Jun 2012 10:23:39 +0200
+Subject: [PATCH 2/8] MIPS: BCM63XX: Add flash type detection
+
+On BCM6358 and BCM6368 the attached flash type is exposed through a
+bootstrapping register. Use it for auto detecting the flash type on
+those and default to parallel flash for earlier SoCs.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3954/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/dev-flash.c | 60 ++++++++++++++++++--
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 6 ++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 9 +++
+ 3 files changed, 69 insertions(+), 6 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -7,6 +7,7 @@
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
++ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
+ */
+
+ #include <linux/init.h>
+@@ -54,16 +55,63 @@ static struct platform_device mtd_dev =
+ },
+ };
+
+-int __init bcm63xx_flash_register(void)
++static int __init bcm63xx_detect_flash_type(void)
+ {
+ u32 val;
+
+- /* read base address of boot chip select (0) */
+- val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+- val &= MPI_CSBASE_BASE_MASK;
++ switch (bcm63xx_get_cpu_id()) {
++ case BCM6338_CPU_ID:
++ case BCM6345_CPU_ID:
++ case BCM6348_CPU_ID:
++ /* no way to auto detect so assume parallel */
++ return BCM63XX_FLASH_TYPE_PARALLEL;
++ case BCM6358_CPU_ID:
++ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
++ if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
++ return BCM63XX_FLASH_TYPE_PARALLEL;
++ else
++ return BCM63XX_FLASH_TYPE_SERIAL;
++ case BCM6368_CPU_ID:
++ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
++ switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
++ case STRAPBUS_6368_BOOT_SEL_NAND:
++ return BCM63XX_FLASH_TYPE_NAND;
++ case STRAPBUS_6368_BOOT_SEL_SERIAL:
++ return BCM63XX_FLASH_TYPE_SERIAL;
++ case STRAPBUS_6368_BOOT_SEL_PARALLEL:
++ return BCM63XX_FLASH_TYPE_PARALLEL;
++ }
++ default:
++ return -EINVAL;
++ }
++}
++
++int __init bcm63xx_flash_register(void)
++{
++ int flash_type;
++ u32 val;
+
+- mtd_resources[0].start = val;
+- mtd_resources[0].end = 0x1FFFFFFF;
++ flash_type = bcm63xx_detect_flash_type();
+
+- return platform_device_register(&mtd_dev);
++ switch (flash_type) {
++ case BCM63XX_FLASH_TYPE_PARALLEL:
++ /* read base address of boot chip select (0) */
++ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ val &= MPI_CSBASE_BASE_MASK;
++
++ mtd_resources[0].start = val;
++ mtd_resources[0].end = 0x1FFFFFFF;
++
++ return platform_device_register(&mtd_dev);
++ case BCM63XX_FLASH_TYPE_SERIAL:
++ pr_warn("unsupported serial flash detected\n");
++ return -ENODEV;
++ case BCM63XX_FLASH_TYPE_NAND:
++ pr_warn("unsupported NAND flash detected\n");
++ return -ENODEV;
++ default:
++ pr_err("flash detection failed for BCM%x: %d\n",
++ bcm63xx_get_cpu_id(), flash_type);
++ return -ENODEV;
++ }
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -1,6 +1,12 @@
+ #ifndef __BCM63XX_FLASH_H
+ #define __BCM63XX_FLASH_H
+
++enum {
++ BCM63XX_FLASH_TYPE_PARALLEL,
++ BCM63XX_FLASH_TYPE_SERIAL,
++ BCM63XX_FLASH_TYPE_NAND,
++};
++
+ int __init bcm63xx_flash_register(void);
+
+ #endif /* __BCM63XX_FLASH_H */
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -507,6 +507,15 @@
+ #define GPIO_BASEMODE_6368_MASK 0x7
+ /* those bits must be kept as read in gpio basemode register*/
+
++#define GPIO_STRAPBUS_REG 0x40
++#define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
++#define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
++#define STRAPBUS_6368_BOOT_SEL_MASK 0x3
++#define STRAPBUS_6368_BOOT_SEL_NAND 0
++#define STRAPBUS_6368_BOOT_SEL_SERIAL 1
++#define STRAPBUS_6368_BOOT_SEL_PARALLEL 3
++
++
+ /*************************************************************************
+ * _REG relative to RSET_ENET
+ *************************************************************************/
diff --git a/target/linux/brcm63xx/patches-3.3/024-MIPS-BCM63XX-Use-the-Chip-ID-register-for-identifyin.patch b/target/linux/brcm63xx/patches-3.3/024-MIPS-BCM63XX-Use-the-Chip-ID-register-for-identifyin.patch
new file mode 100644
index 000000000..e45a0d163
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/024-MIPS-BCM63XX-Use-the-Chip-ID-register-for-identifyin.patch
@@ -0,0 +1,53 @@
+From a9168d99658bd050e49afc06880d140e2fc2c231 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 12 Jun 2012 10:23:40 +0200
+Subject: [PATCH 3/8] MIPS: BCM63XX: Use the Chip ID register for identifying the SoC
+
+Newer BCM63XX SoCs use virtually the same CPU ID, differing only in the
+revision bits. But since they all have the Chip ID register at the same
+location, we can use that to identify the SoC we are running on.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3955/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/cpu.c | 20 ++++++++++++--------
+ 1 files changed, 12 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/bcm63xx/cpu.c
++++ b/arch/mips/bcm63xx/cpu.c
+@@ -228,17 +228,21 @@ void __init bcm63xx_cpu_init(void)
+ bcm63xx_irqs = bcm6345_irqs;
+ break;
+ case CPU_BMIPS4350:
+- switch (read_c0_prid() & 0xf0) {
+- case 0x10:
++ if ((read_c0_prid() & 0xf0) == 0x10) {
+ expected_cpu_id = BCM6358_CPU_ID;
+ bcm63xx_regs_base = bcm6358_regs_base;
+ bcm63xx_irqs = bcm6358_irqs;
+- break;
+- case 0x30:
+- expected_cpu_id = BCM6368_CPU_ID;
+- bcm63xx_regs_base = bcm6368_regs_base;
+- bcm63xx_irqs = bcm6368_irqs;
+- break;
++ } else {
++ /* all newer chips have the same chip id location */
++ u16 chip_id = bcm_readw(BCM_6368_PERF_BASE);
++
++ switch (chip_id) {
++ case BCM6368_CPU_ID:
++ expected_cpu_id = BCM6368_CPU_ID;
++ bcm63xx_regs_base = bcm6368_regs_base;
++ bcm63xx_irqs = bcm6368_irqs;
++ break;
++ }
+ }
+ break;
+ }
diff --git a/target/linux/brcm63xx/patches-3.3/025-MIPS-BCM63XX-Add-basic-BCM6328-support.patch b/target/linux/brcm63xx/patches-3.3/025-MIPS-BCM63XX-Add-basic-BCM6328-support.patch
new file mode 100644
index 000000000..a64eca85b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/025-MIPS-BCM63XX-Add-basic-BCM6328-support.patch
@@ -0,0 +1,590 @@
+From 8f9ed2e5502ed3ba3d4c89678cb44f43ccd5b9e0 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Wed, 13 Jun 2012 16:46:54 +0100
+Subject: [PATCH 4/8] MIPS: BCM63XX: Add basic BCM6328 support
+
+This includes CPU speed, memory size detection and working UART, but
+lacking the appropriate drivers, no support for attached flash.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3951/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/Kconfig | 3 +
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 12 ++-
+ arch/mips/bcm63xx/cpu.c | 43 ++++++++
+ arch/mips/bcm63xx/dev-flash.c | 6 +
+ arch/mips/bcm63xx/dev-spi.c | 2 +-
+ arch/mips/bcm63xx/irq.c | 21 ++++
+ arch/mips/bcm63xx/prom.c | 4 +-
+ arch/mips/bcm63xx/setup.c | 13 ++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 111 ++++++++++++++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 2 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 54 ++++++++++
+ arch/mips/include/asm/mach-bcm63xx/ioremap.h | 1 +
+ 13 files changed, 265 insertions(+), 9 deletions(-)
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -1,6 +1,9 @@
+ menu "CPU support"
+ depends on BCM63XX
+
++config BCM63XX_CPU_6328
++ bool "support 6328 CPU"
++
+ config BCM63XX_CPU_6338
+ bool "support 6338 CPU"
+ select HW_HAS_PCI
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -708,9 +708,15 @@ void __init board_prom_init(void)
+ char cfe_version[32];
+ u32 val;
+
+- /* read base address of boot chip select (0) */
+- val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+- val &= MPI_CSBASE_BASE_MASK;
++ /* read base address of boot chip select (0)
++ * 6328 does not have MPI but boots from a fixed address
++ */
++ if (BCMCPU_IS_6328())
++ val = 0x18000000;
++ else {
++ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ val &= MPI_CSBASE_BASE_MASK;
++ }
+ boot_addr = (u8 *)KSEG1ADDR(val);
+
+ /* dump cfe version */
+--- a/arch/mips/bcm63xx/cpu.c
++++ b/arch/mips/bcm63xx/cpu.c
+@@ -29,6 +29,14 @@ static u16 bcm63xx_cpu_rev;
+ static unsigned int bcm63xx_cpu_freq;
+ static unsigned int bcm63xx_memory_size;
+
++static const unsigned long bcm6328_regs_base[] = {
++ __GEN_CPU_REGS_TABLE(6328)
++};
++
++static const int bcm6328_irqs[] = {
++ __GEN_CPU_IRQ_TABLE(6328)
++};
++
+ static const unsigned long bcm6338_regs_base[] = {
+ __GEN_CPU_REGS_TABLE(6338)
+ };
+@@ -99,6 +107,33 @@ unsigned int bcm63xx_get_memory_size(voi
+ static unsigned int detect_cpu_clock(void)
+ {
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ {
++ unsigned int tmp, mips_pll_fcvo;
++
++ tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
++ mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK)
++ >> STRAPBUS_6328_FCVO_SHIFT;
++
++ switch (mips_pll_fcvo) {
++ case 0x12:
++ case 0x14:
++ case 0x19:
++ return 160000000;
++ case 0x1c:
++ return 192000000;
++ case 0x13:
++ case 0x15:
++ return 200000000;
++ case 0x1a:
++ return 384000000;
++ case 0x16:
++ return 400000000;
++ default:
++ return 320000000;
++ }
++
++ }
+ case BCM6338_CPU_ID:
+ /* BCM6338 has a fixed 240 Mhz frequency */
+ return 240000000;
+@@ -170,6 +205,9 @@ static unsigned int detect_memory_size(v
+ unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
+ u32 val;
+
++ if (BCMCPU_IS_6328())
++ return bcm_ddr_readl(DDR_CSEND_REG) << 24;
++
+ if (BCMCPU_IS_6345()) {
+ val = bcm_sdram_readl(SDRAM_MBASE_REG);
+ return (val * 8 * 1024 * 1024);
+@@ -237,6 +275,11 @@ void __init bcm63xx_cpu_init(void)
+ u16 chip_id = bcm_readw(BCM_6368_PERF_BASE);
+
+ switch (chip_id) {
++ case BCM6328_CPU_ID:
++ expected_cpu_id = BCM6328_CPU_ID;
++ bcm63xx_regs_base = bcm6328_regs_base;
++ bcm63xx_irqs = bcm6328_irqs;
++ break;
+ case BCM6368_CPU_ID:
+ expected_cpu_id = BCM6368_CPU_ID;
+ bcm63xx_regs_base = bcm6368_regs_base;
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -60,6 +60,12 @@ static int __init bcm63xx_detect_flash_t
+ u32 val;
+
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
++ if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
++ return BCM63XX_FLASH_TYPE_SERIAL;
++ else
++ return BCM63XX_FLASH_TYPE_NAND;
+ case BCM6338_CPU_ID:
+ case BCM6345_CPU_ID:
+ case BCM6348_CPU_ID:
+--- a/arch/mips/bcm63xx/dev-spi.c
++++ b/arch/mips/bcm63xx/dev-spi.c
+@@ -87,7 +87,7 @@ int __init bcm63xx_spi_register(void)
+ {
+ struct clk *periph_clk;
+
+- if (BCMCPU_IS_6345())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6345())
+ return -ENODEV;
+
+ periph_clk = clk_get(NULL, "periph");
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(uns
+ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
+
+ #ifndef BCMCPU_RUNTIME_DETECT
++#ifdef CONFIG_BCM63XX_CPU_6328
++#define irq_stat_reg PERF_IRQSTAT_6328_REG
++#define irq_mask_reg PERF_IRQMASK_6328_REG
++#define irq_bits 64
++#define is_ext_irq_cascaded 1
++#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
++#define ext_irq_end (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
++#define ext_irq_count 4
++#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6328
++#define ext_irq_cfg_reg2 0
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ #define irq_stat_reg PERF_IRQSTAT_6338_REG
+ #define irq_mask_reg PERF_IRQMASK_6338_REG
+@@ -118,6 +129,16 @@ static void bcm63xx_init_irq(void)
+ irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
+
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ irq_stat_addr += PERF_IRQSTAT_6328_REG;
++ irq_mask_addr += PERF_IRQMASK_6328_REG;
++ irq_bits = 64;
++ ext_irq_count = 4;
++ is_ext_irq_cascaded = 1;
++ ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
++ ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
++ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
++ break;
+ case BCM6338_CPU_ID:
+ irq_stat_addr += PERF_IRQSTAT_6338_REG;
+ irq_mask_addr += PERF_IRQMASK_6338_REG;
+--- a/arch/mips/bcm63xx/prom.c
++++ b/arch/mips/bcm63xx/prom.c
+@@ -26,7 +26,9 @@ void __init prom_init(void)
+ bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG);
+
+ /* disable all hardware blocks clock for now */
+- if (BCMCPU_IS_6338())
++ if (BCMCPU_IS_6328())
++ mask = CKCTL_6328_ALL_SAFE_EN;
++ else if (BCMCPU_IS_6338())
+ mask = CKCTL_6338_ALL_SAFE_EN;
+ else if (BCMCPU_IS_6345())
+ mask = CKCTL_6345_ALL_SAFE_EN;
+--- a/arch/mips/bcm63xx/setup.c
++++ b/arch/mips/bcm63xx/setup.c
+@@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void)
+
+ /* mask and clear all external irq */
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
++ break;
+ case BCM6338_CPU_ID:
+ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
+ break;
+@@ -95,9 +98,13 @@ void bcm63xx_machine_reboot(void)
+ bcm6348_a1_reboot();
+
+ printk(KERN_INFO "triggering watchdog soft-reset...\n");
+- reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
+- reg |= SYS_PLL_SOFT_RESET;
+- bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
++ if (BCMCPU_IS_6328()) {
++ bcm_wdt_writel(1, WDT_SOFTRESET_REG);
++ } else {
++ reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
++ reg |= SYS_PLL_SOFT_RESET;
++ bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
++ }
+ while (1)
+ ;
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -9,6 +9,7 @@
+ * compile time if only one CPU support is enabled (idea stolen from
+ * arm mach-types)
+ */
++#define BCM6328_CPU_ID 0x6328
+ #define BCM6338_CPU_ID 0x6338
+ #define BCM6345_CPU_ID 0x6345
+ #define BCM6348_CPU_ID 0x6348
+@@ -20,6 +21,19 @@ u16 __bcm63xx_get_cpu_id(void);
+ u16 bcm63xx_get_cpu_rev(void);
+ unsigned int bcm63xx_get_cpu_freq(void);
+
++#ifdef CONFIG_BCM63XX_CPU_6328
++# ifdef bcm63xx_get_cpu_id
++# undef bcm63xx_get_cpu_id
++# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
++# define BCMCPU_RUNTIME_DETECT
++# else
++# define bcm63xx_get_cpu_id() BCM6328_CPU_ID
++# endif
++# define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
++#else
++# define BCMCPU_IS_6328() (0)
++#endif
++
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ # ifdef bcm63xx_get_cpu_id
+ # undef bcm63xx_get_cpu_id
+@@ -129,7 +143,8 @@ enum bcm63xx_regs_set {
+ RSET_PCMDMA,
+ RSET_PCMDMAC,
+ RSET_PCMDMAS,
+- RSET_RNG
++ RSET_RNG,
++ RSET_MISC
+ };
+
+ #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4)
+@@ -156,6 +171,49 @@ enum bcm63xx_regs_set {
+ #define RSET_RNG_SIZE 20
+
+ /*
++ * 6328 register sets base address
++ */
++#define BCM_6328_DSL_LMEM_BASE (0xdeadbeef)
++#define BCM_6328_PERF_BASE (0xb0000000)
++#define BCM_6328_TIMER_BASE (0xb0000040)
++#define BCM_6328_WDT_BASE (0xb000005c)
++#define BCM_6328_UART0_BASE (0xb0000100)
++#define BCM_6328_UART1_BASE (0xb0000120)
++#define BCM_6328_GPIO_BASE (0xb0000080)
++#define BCM_6328_SPI_BASE (0xdeadbeef)
++#define BCM_6328_UDC0_BASE (0xdeadbeef)
++#define BCM_6328_USBDMA_BASE (0xdeadbeef)
++#define BCM_6328_OHCI0_BASE (0xdeadbeef)
++#define BCM_6328_OHCI_PRIV_BASE (0xdeadbeef)
++#define BCM_6328_USBH_PRIV_BASE (0xdeadbeef)
++#define BCM_6328_MPI_BASE (0xdeadbeef)
++#define BCM_6328_PCMCIA_BASE (0xdeadbeef)
++#define BCM_6328_SDRAM_REGS_BASE (0xdeadbeef)
++#define BCM_6328_DSL_BASE (0xb0001900)
++#define BCM_6328_UBUS_BASE (0xdeadbeef)
++#define BCM_6328_ENET0_BASE (0xdeadbeef)
++#define BCM_6328_ENET1_BASE (0xdeadbeef)
++#define BCM_6328_ENETDMA_BASE (0xb000d800)
++#define BCM_6328_ENETDMAC_BASE (0xb000da00)
++#define BCM_6328_ENETDMAS_BASE (0xb000dc00)
++#define BCM_6328_ENETSW_BASE (0xb0e00000)
++#define BCM_6328_EHCI0_BASE (0x10002500)
++#define BCM_6328_SDRAM_BASE (0xdeadbeef)
++#define BCM_6328_MEMC_BASE (0xdeadbeef)
++#define BCM_6328_DDR_BASE (0xb0003000)
++#define BCM_6328_M2M_BASE (0xdeadbeef)
++#define BCM_6328_ATM_BASE (0xdeadbeef)
++#define BCM_6328_XTM_BASE (0xdeadbeef)
++#define BCM_6328_XTMDMA_BASE (0xb000b800)
++#define BCM_6328_XTMDMAC_BASE (0xdeadbeef)
++#define BCM_6328_XTMDMAS_BASE (0xdeadbeef)
++#define BCM_6328_PCM_BASE (0xb000a800)
++#define BCM_6328_PCMDMA_BASE (0xdeadbeef)
++#define BCM_6328_PCMDMAC_BASE (0xdeadbeef)
++#define BCM_6328_PCMDMAS_BASE (0xdeadbeef)
++#define BCM_6328_RNG_BASE (0xdeadbeef)
++#define BCM_6328_MISC_BASE (0xb0001800)
++/*
+ * 6338 register sets base address
+ */
+ #define BCM_6338_DSL_LMEM_BASE (0xfff00000)
+@@ -198,6 +256,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6338_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6338_PCMDMAS_BASE (0xdeadbeef)
+ #define BCM_6338_RNG_BASE (0xdeadbeef)
++#define BCM_6338_MISC_BASE (0xdeadbeef)
+
+ /*
+ * 6345 register sets base address
+@@ -242,6 +301,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6345_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6345_PCMDMAS_BASE (0xdeadbeef)
+ #define BCM_6345_RNG_BASE (0xdeadbeef)
++#define BCM_6345_MISC_BASE (0xdeadbeef)
+
+ /*
+ * 6348 register sets base address
+@@ -283,6 +343,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6348_PCMDMAC_BASE (0xdeadbeef)
+ #define BCM_6348_PCMDMAS_BASE (0xdeadbeef)
+ #define BCM_6348_RNG_BASE (0xdeadbeef)
++#define BCM_6348_MISC_BASE (0xdeadbeef)
+
+ /*
+ * 6358 register sets base address
+@@ -324,6 +385,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_PCMDMAC_BASE (0xfffe1900)
+ #define BCM_6358_PCMDMAS_BASE (0xfffe1a00)
+ #define BCM_6358_RNG_BASE (0xdeadbeef)
++#define BCM_6358_MISC_BASE (0xdeadbeef)
+
+
+ /*
+@@ -366,6 +428,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6368_PCMDMAC_BASE (0xb0005a00)
+ #define BCM_6368_PCMDMAS_BASE (0xb0005c00)
+ #define BCM_6368_RNG_BASE (0xb0004180)
++#define BCM_6368_MISC_BASE (0xdeadbeef)
+
+
+ extern const unsigned long *bcm63xx_regs_base;
+@@ -412,6 +475,7 @@ extern const unsigned long *bcm63xx_regs
+ __GEN_RSET_BASE(__cpu, PCMDMAC) \
+ __GEN_RSET_BASE(__cpu, PCMDMAS) \
+ __GEN_RSET_BASE(__cpu, RNG) \
++ __GEN_RSET_BASE(__cpu, MISC) \
+ }
+
+ #define __GEN_CPU_REGS_TABLE(__cpu) \
+@@ -451,6 +515,7 @@ extern const unsigned long *bcm63xx_regs
+ [RSET_PCMDMAC] = BCM_## __cpu ##_PCMDMAC_BASE, \
+ [RSET_PCMDMAS] = BCM_## __cpu ##_PCMDMAS_BASE, \
+ [RSET_RNG] = BCM_## __cpu ##_RNG_BASE, \
++ [RSET_MISC] = BCM_## __cpu ##_MISC_BASE, \
+
+
+ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
+@@ -458,6 +523,9 @@ static inline unsigned long bcm63xx_regs
+ #ifdef BCMCPU_RUNTIME_DETECT
+ return bcm63xx_regs_base[set];
+ #else
++#ifdef CONFIG_BCM63XX_CPU_6328
++ __GEN_RSET(6328)
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ __GEN_RSET(6338)
+ #endif
+@@ -512,6 +580,47 @@ enum bcm63xx_irq {
+ };
+
+ /*
++ * 6328 irqs
++ */
++#define BCM_6328_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
++
++#define BCM_6328_TIMER_IRQ (IRQ_INTERNAL_BASE + 31)
++#define BCM_6328_SPI_IRQ 0
++#define BCM_6328_UART0_IRQ (IRQ_INTERNAL_BASE + 28)
++#define BCM_6328_UART1_IRQ (BCM_6328_HIGH_IRQ_BASE + 7)
++#define BCM_6328_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
++#define BCM_6328_UDC0_IRQ 0
++#define BCM_6328_ENET0_IRQ 0
++#define BCM_6328_ENET1_IRQ 0
++#define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
++#define BCM_6328_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9)
++#define BCM_6328_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
++#define BCM_6328_PCMCIA_IRQ 0
++#define BCM_6328_ENET0_RXDMA_IRQ 0
++#define BCM_6328_ENET0_TXDMA_IRQ 0
++#define BCM_6328_ENET1_RXDMA_IRQ 0
++#define BCM_6328_ENET1_TXDMA_IRQ 0
++#define BCM_6328_PCI_IRQ (IRQ_INTERNAL_BASE + 23)
++#define BCM_6328_ATM_IRQ 0
++#define BCM_6328_ENETSW_RXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 0)
++#define BCM_6328_ENETSW_RXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 1)
++#define BCM_6328_ENETSW_RXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 2)
++#define BCM_6328_ENETSW_RXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 3)
++#define BCM_6328_ENETSW_TXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 4)
++#define BCM_6328_ENETSW_TXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 5)
++#define BCM_6328_ENETSW_TXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 6)
++#define BCM_6328_ENETSW_TXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 7)
++#define BCM_6328_XTM_IRQ (BCM_6328_HIGH_IRQ_BASE + 31)
++#define BCM_6328_XTM_DMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 11)
++
++#define BCM_6328_PCM_DMA0_IRQ (IRQ_INTERNAL_BASE + 2)
++#define BCM_6328_PCM_DMA1_IRQ (IRQ_INTERNAL_BASE + 3)
++#define BCM_6328_EXT_IRQ0 (IRQ_INTERNAL_BASE + 24)
++#define BCM_6328_EXT_IRQ1 (IRQ_INTERNAL_BASE + 25)
++#define BCM_6328_EXT_IRQ2 (IRQ_INTERNAL_BASE + 26)
++#define BCM_6328_EXT_IRQ3 (IRQ_INTERNAL_BASE + 27)
++
++/*
+ * 6338 irqs
+ */
+ #define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+@@ -8,6 +8,8 @@ int __init bcm63xx_gpio_init(void);
+ static inline unsigned long bcm63xx_gpio_count(void)
+ {
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ return 32;
+ case BCM6358_CPU_ID:
+ return 40;
+ case BCM6338_CPU_ID:
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+@@ -91,5 +91,7 @@
+ #define bcm_memc_writel(v, o) bcm_rset_writel(RSET_MEMC, (v), (o))
+ #define bcm_ddr_readl(o) bcm_rset_readl(RSET_DDR, (o))
+ #define bcm_ddr_writel(v, o) bcm_rset_writel(RSET_DDR, (v), (o))
++#define bcm_misc_readl(o) bcm_rset_readl(RSET_MISC, (o))
++#define bcm_misc_writel(v, o) bcm_rset_writel(RSET_MISC, (v), (o))
+
+ #endif /* ! BCM63XX_IO_H_ */
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -15,6 +15,30 @@
+ /* Clock Control register */
+ #define PERF_CKCTL_REG 0x4
+
++#define CKCTL_6328_PHYMIPS_EN (1 << 0)
++#define CKCTL_6328_ADSL_QPROC_EN (1 << 1)
++#define CKCTL_6328_ADSL_AFE_EN (1 << 2)
++#define CKCTL_6328_ADSL_EN (1 << 3)
++#define CKCTL_6328_MIPS_EN (1 << 4)
++#define CKCTL_6328_SAR_EN (1 << 5)
++#define CKCTL_6328_PCM_EN (1 << 6)
++#define CKCTL_6328_USBD_EN (1 << 7)
++#define CKCTL_6328_USBH_EN (1 << 8)
++#define CKCTL_6328_HSSPI_EN (1 << 9)
++#define CKCTL_6328_PCIE_EN (1 << 10)
++#define CKCTL_6328_ROBOSW_EN (1 << 11)
++
++#define CKCTL_6328_ALL_SAFE_EN (CKCTL_6328_PHYMIPS_EN | \
++ CKCTL_6328_ADSL_QPROC_EN | \
++ CKCTL_6328_ADSL_AFE_EN | \
++ CKCTL_6328_ADSL_EN | \
++ CKCTL_6328_SAR_EN | \
++ CKCTL_6328_PCM_EN | \
++ CKCTL_6328_USBD_EN | \
++ CKCTL_6328_USBH_EN | \
++ CKCTL_6328_ROBOSW_EN | \
++ CKCTL_6328_PCIE_EN)
++
+ #define CKCTL_6338_ADSLPHY_EN (1 << 0)
+ #define CKCTL_6338_MPI_EN (1 << 1)
+ #define CKCTL_6338_DRAM_EN (1 << 2)
+@@ -119,6 +143,7 @@
+ #define SYS_PLL_SOFT_RESET 0x1
+
+ /* Interrupt Mask register */
++#define PERF_IRQMASK_6328_REG 0x20
+ #define PERF_IRQMASK_6338_REG 0xc
+ #define PERF_IRQMASK_6345_REG 0xc
+ #define PERF_IRQMASK_6348_REG 0xc
+@@ -126,6 +151,7 @@
+ #define PERF_IRQMASK_6368_REG 0x20
+
+ /* Interrupt Status register */
++#define PERF_IRQSTAT_6328_REG 0x28
+ #define PERF_IRQSTAT_6338_REG 0x10
+ #define PERF_IRQSTAT_6345_REG 0x10
+ #define PERF_IRQSTAT_6348_REG 0x10
+@@ -133,6 +159,7 @@
+ #define PERF_IRQSTAT_6368_REG 0x28
+
+ /* External Interrupt Configuration register */
++#define PERF_EXTIRQ_CFG_REG_6328 0x18
+ #define PERF_EXTIRQ_CFG_REG_6338 0x14
+ #define PERF_EXTIRQ_CFG_REG_6348 0x14
+ #define PERF_EXTIRQ_CFG_REG_6358 0x14
+@@ -162,8 +189,21 @@
+
+ /* Soft Reset register */
+ #define PERF_SOFTRESET_REG 0x28
++#define PERF_SOFTRESET_6328_REG 0x10
+ #define PERF_SOFTRESET_6368_REG 0x10
+
++#define SOFTRESET_6328_SPI_MASK (1 << 0)
++#define SOFTRESET_6328_EPHY_MASK (1 << 1)
++#define SOFTRESET_6328_SAR_MASK (1 << 2)
++#define SOFTRESET_6328_ENETSW_MASK (1 << 3)
++#define SOFTRESET_6328_USBS_MASK (1 << 4)
++#define SOFTRESET_6328_USBH_MASK (1 << 5)
++#define SOFTRESET_6328_PCM_MASK (1 << 6)
++#define SOFTRESET_6328_PCIE_CORE_MASK (1 << 7)
++#define SOFTRESET_6328_PCIE_MASK (1 << 8)
++#define SOFTRESET_6328_PCIE_EXT_MASK (1 << 9)
++#define SOFTRESET_6328_PCIE_HARD_MASK (1 << 10)
++
+ #define SOFTRESET_6338_SPI_MASK (1 << 0)
+ #define SOFTRESET_6338_ENET_MASK (1 << 2)
+ #define SOFTRESET_6338_USBH_MASK (1 << 3)
+@@ -307,6 +347,8 @@
+ /* Watchdog reset length register */
+ #define WDT_RSTLEN_REG 0x8
+
++/* Watchdog soft reset register (BCM6328 only) */
++#define WDT_SOFTRESET_REG 0xc
+
+ /*************************************************************************
+ * _REG relative to RSET_UARTx
+@@ -933,6 +975,8 @@
+ * _REG relative to RSET_DDR
+ *************************************************************************/
+
++#define DDR_CSEND_REG 0x8
++
+ #define DDR_DMIPSPLLCFG_REG 0x18
+ #define DMIPSPLLCFG_M1_SHIFT 0
+ #define DMIPSPLLCFG_M1_MASK (0xff << DMIPSPLLCFG_M1_SHIFT)
+@@ -1122,4 +1166,14 @@
+ #define SPI_SSOFFTIME_SHIFT 3
+ #define SPI_BYTE_SWAP 0x80
+
++/*************************************************************************
++ * _REG relative to RSET_MISC
++ *************************************************************************/
++
++#define MISC_STRAPBUS_6328_REG 0x240
++#define STRAPBUS_6328_FCVO_SHIFT 7
++#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
++#define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
++#define STRAPBUS_6328_BOOT_SEL_NAND (0 << 28)
++
+ #endif /* BCM63XX_REGS_H_ */
+--- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h
++++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h
+@@ -18,6 +18,7 @@ static inline int is_bcm63xx_internal_re
+ if (offset >= 0xfff00000)
+ return 1;
+ break;
++ case BCM6328_CPU_ID:
+ case BCM6368_CPU_ID:
+ if (offset >= 0xb0000000 && offset < 0xb1000000)
+ return 1;
diff --git a/target/linux/brcm63xx/patches-3.3/026-MIPS-BCM63XX-Move-the-PCI-initialization-into-its-ow.patch b/target/linux/brcm63xx/patches-3.3/026-MIPS-BCM63XX-Move-the-PCI-initialization-into-its-ow.patch
new file mode 100644
index 000000000..0f44b4910
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/026-MIPS-BCM63XX-Move-the-PCI-initialization-into-its-ow.patch
@@ -0,0 +1,61 @@
+From b8420b9150fa03fcdfacd32e8c5ad286e208d5e9 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Wed, 13 Jun 2012 16:48:02 +0100
+Subject: [PATCH 5/8] MIPS: BCM63XX: Move the PCI initialization into its own function
+
+Also make the cpu check a bit more explicit.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3953/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/pci/pci-bcm63xx.c | 25 +++++++++++++++++--------
+ 1 files changed, 17 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/pci/pci-bcm63xx.c
++++ b/arch/mips/pci/pci-bcm63xx.c
+@@ -94,17 +94,10 @@ static void bcm63xx_int_cfg_writel(u32 v
+
+ void __iomem *pci_iospace_start;
+
+-static int __init bcm63xx_pci_init(void)
++static int __init bcm63xx_register_pci(void)
+ {
+ unsigned int mem_size;
+ u32 val;
+-
+- if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368())
+- return -ENODEV;
+-
+- if (!bcm63xx_pci_enabled)
+- return -ENODEV;
+-
+ /*
+ * configuration access are done through IO space, remap 4
+ * first bytes to access it from CPU.
+@@ -221,4 +214,20 @@ static int __init bcm63xx_pci_init(void)
+ return 0;
+ }
+
++
++static int __init bcm63xx_pci_init(void)
++{
++ if (!bcm63xx_pci_enabled)
++ return -ENODEV;
++
++ switch (bcm63xx_get_cpu_id()) {
++ case BCM6348_CPU_ID:
++ case BCM6358_CPU_ID:
++ case BCM6368_CPU_ID:
++ return bcm63xx_register_pci();
++ default:
++ return -ENODEV;
++ }
++}
++
+ arch_initcall(bcm63xx_pci_init);
diff --git a/target/linux/brcm63xx/patches-3.3/027-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch b/target/linux/brcm63xx/patches-3.3/027-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch
new file mode 100644
index 000000000..ff375cd2a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/027-MIPS-BCM63XX-Add-PCIe-Support-for-BCM6328.patch
@@ -0,0 +1,427 @@
+From 45655e79f84e35c13b8964b961d804e64b3aca91 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Wed, 13 Jun 2012 17:07:13 +0100
+Subject: [PATCH 6/8] MIPS: BCM63XX: Add PCIe Support for BCM6328
+
+Add support for the PCIe port found on BCM6328.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3956/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/bcm63xx/Kconfig | 1 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 9 ++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 6 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 54 ++++++++++
+ arch/mips/pci/ops-bcm63xx.c | 61 +++++++++++
+ arch/mips/pci/pci-bcm63xx.c | 112 +++++++++++++++++++++
+ arch/mips/pci/pci-bcm63xx.h | 5 +
+ 7 files changed, 248 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -3,6 +3,7 @@ menu "CPU support"
+
+ config BCM63XX_CPU_6328
+ bool "support 6328 CPU"
++ select HW_HAS_PCI
+
+ config BCM63XX_CPU_6338
+ bool "support 6338 CPU"
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -122,6 +122,7 @@ enum bcm63xx_regs_set {
+ RSET_USBH_PRIV,
+ RSET_MPI,
+ RSET_PCMCIA,
++ RSET_PCIE,
+ RSET_DSL,
+ RSET_ENET0,
+ RSET_ENET1,
+@@ -188,6 +189,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6328_USBH_PRIV_BASE (0xdeadbeef)
+ #define BCM_6328_MPI_BASE (0xdeadbeef)
+ #define BCM_6328_PCMCIA_BASE (0xdeadbeef)
++#define BCM_6328_PCIE_BASE (0xb0e40000)
+ #define BCM_6328_SDRAM_REGS_BASE (0xdeadbeef)
+ #define BCM_6328_DSL_BASE (0xb0001900)
+ #define BCM_6328_UBUS_BASE (0xdeadbeef)
+@@ -232,6 +234,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6338_USBH_PRIV_BASE (0xdeadbeef)
+ #define BCM_6338_MPI_BASE (0xfffe3160)
+ #define BCM_6338_PCMCIA_BASE (0xdeadbeef)
++#define BCM_6338_PCIE_BASE (0xdeadbeef)
+ #define BCM_6338_SDRAM_REGS_BASE (0xfffe3100)
+ #define BCM_6338_DSL_BASE (0xfffe1000)
+ #define BCM_6338_UBUS_BASE (0xdeadbeef)
+@@ -279,6 +282,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6345_ENETSW_BASE (0xdeadbeef)
+ #define BCM_6345_PCMCIA_BASE (0xfffe2028)
+ #define BCM_6345_MPI_BASE (0xfffe2000)
++#define BCM_6345_PCIE_BASE (0xdeadbeef)
+ #define BCM_6345_OHCI0_BASE (0xfffe2100)
+ #define BCM_6345_OHCI_PRIV_BASE (0xfffe2200)
+ #define BCM_6345_USBH_PRIV_BASE (0xdeadbeef)
+@@ -320,6 +324,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6348_USBH_PRIV_BASE (0xdeadbeef)
+ #define BCM_6348_MPI_BASE (0xfffe2000)
+ #define BCM_6348_PCMCIA_BASE (0xfffe2054)
++#define BCM_6348_PCIE_BASE (0xdeadbeef)
+ #define BCM_6348_SDRAM_REGS_BASE (0xfffe2300)
+ #define BCM_6348_M2M_BASE (0xfffe2800)
+ #define BCM_6348_DSL_BASE (0xfffe3000)
+@@ -362,6 +367,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_USBH_PRIV_BASE (0xfffe1500)
+ #define BCM_6358_MPI_BASE (0xfffe1000)
+ #define BCM_6358_PCMCIA_BASE (0xfffe1054)
++#define BCM_6358_PCIE_BASE (0xdeadbeef)
+ #define BCM_6358_SDRAM_REGS_BASE (0xfffe2300)
+ #define BCM_6358_M2M_BASE (0xdeadbeef)
+ #define BCM_6358_DSL_BASE (0xfffe3000)
+@@ -405,6 +411,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6368_USBH_PRIV_BASE (0xb0001700)
+ #define BCM_6368_MPI_BASE (0xb0001000)
+ #define BCM_6368_PCMCIA_BASE (0xb0001054)
++#define BCM_6368_PCIE_BASE (0xdeadbeef)
+ #define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef)
+ #define BCM_6368_M2M_BASE (0xdeadbeef)
+ #define BCM_6368_DSL_BASE (0xdeadbeef)
+@@ -453,6 +460,7 @@ extern const unsigned long *bcm63xx_regs
+ __GEN_RSET_BASE(__cpu, USBH_PRIV) \
+ __GEN_RSET_BASE(__cpu, MPI) \
+ __GEN_RSET_BASE(__cpu, PCMCIA) \
++ __GEN_RSET_BASE(__cpu, PCIE) \
+ __GEN_RSET_BASE(__cpu, DSL) \
+ __GEN_RSET_BASE(__cpu, ENET0) \
+ __GEN_RSET_BASE(__cpu, ENET1) \
+@@ -493,6 +501,7 @@ extern const unsigned long *bcm63xx_regs
+ [RSET_USBH_PRIV] = BCM_## __cpu ##_USBH_PRIV_BASE, \
+ [RSET_MPI] = BCM_## __cpu ##_MPI_BASE, \
+ [RSET_PCMCIA] = BCM_## __cpu ##_PCMCIA_BASE, \
++ [RSET_PCIE] = BCM_## __cpu ##_PCIE_BASE, \
+ [RSET_DSL] = BCM_## __cpu ##_DSL_BASE, \
+ [RSET_ENET0] = BCM_## __cpu ##_ENET0_BASE, \
+ [RSET_ENET1] = BCM_## __cpu ##_ENET1_BASE, \
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
+@@ -40,6 +40,10 @@
+ #define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
+ BCM_CB_MEM_SIZE - 1)
+
++#define BCM_PCIE_MEM_BASE_PA 0x10f00000
++#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024)
++#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
++ BCM_PCIE_MEM_SIZE - 1)
+
+ /*
+ * Internal registers are accessed through KSEG3
+@@ -85,6 +89,8 @@
+ #define bcm_mpi_writel(v, o) bcm_rset_writel(RSET_MPI, (v), (o))
+ #define bcm_pcmcia_readl(o) bcm_rset_readl(RSET_PCMCIA, (o))
+ #define bcm_pcmcia_writel(v, o) bcm_rset_writel(RSET_PCMCIA, (v), (o))
++#define bcm_pcie_readl(o) bcm_rset_readl(RSET_PCIE, (o))
++#define bcm_pcie_writel(v, o) bcm_rset_writel(RSET_PCIE, (v), (o))
+ #define bcm_sdram_readl(o) bcm_rset_readl(RSET_SDRAM, (o))
+ #define bcm_sdram_writel(v, o) bcm_rset_writel(RSET_SDRAM, (v), (o))
+ #define bcm_memc_readl(o) bcm_rset_readl(RSET_MEMC, (o))
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -1169,6 +1169,9 @@
+ /*************************************************************************
+ * _REG relative to RSET_MISC
+ *************************************************************************/
++#define MISC_SERDES_CTRL_REG 0x0
++#define SERDES_PCIE_EN (1 << 0)
++#define SERDES_PCIE_EXD_EN (1 << 15)
+
+ #define MISC_STRAPBUS_6328_REG 0x240
+ #define STRAPBUS_6328_FCVO_SHIFT 7
+@@ -1176,4 +1179,55 @@
+ #define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
+ #define STRAPBUS_6328_BOOT_SEL_NAND (0 << 28)
+
++/*************************************************************************
++ * _REG relative to RSET_PCIE
++ *************************************************************************/
++
++#define PCIE_CONFIG2_REG 0x408
++#define CONFIG2_BAR1_SIZE_EN 1
++#define CONFIG2_BAR1_SIZE_MASK 0xf
++
++#define PCIE_IDVAL3_REG 0x43c
++#define IDVAL3_CLASS_CODE_MASK 0xffffff
++#define IDVAL3_SUBCLASS_SHIFT 8
++#define IDVAL3_CLASS_SHIFT 16
++
++#define PCIE_DLSTATUS_REG 0x1048
++#define DLSTATUS_PHYLINKUP (1 << 13)
++
++#define PCIE_BRIDGE_OPT1_REG 0x2820
++#define OPT1_RD_BE_OPT_EN (1 << 7)
++#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9)
++#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11)
++#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12)
++
++#define PCIE_BRIDGE_OPT2_REG 0x2824
++#define OPT2_UBUS_UR_DECODE_DIS (1 << 2)
++#define OPT2_TX_CREDIT_CHK_EN (1 << 4)
++#define OPT2_CFG_TYPE1_BD_SEL (1 << 7)
++#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16
++#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT)
++
++#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828
++#define PCIE_BRIDGE_BAR1_BASEMASK_REG 0x2830
++#define BASEMASK_REMAP_EN (1 << 0)
++#define BASEMASK_SWAP_EN (1 << 1)
++#define BASEMASK_MASK_SHIFT 4
++#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT)
++#define BASEMASK_BASE_SHIFT 20
++#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT)
++
++#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c
++#define PCIE_BRIDGE_BAR1_REBASE_ADDR_REG 0x2834
++#define REBASE_ADDR_BASE_SHIFT 20
++#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT)
++
++#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854
++#define PCIE_RC_INT_A (1 << 0)
++#define PCIE_RC_INT_B (1 << 1)
++#define PCIE_RC_INT_C (1 << 2)
++#define PCIE_RC_INT_D (1 << 3)
++
++#define PCIE_DEVICE_OFFSET 0x8000
++
+ #endif /* BCM63XX_REGS_H_ */
+--- a/arch/mips/pci/ops-bcm63xx.c
++++ b/arch/mips/pci/ops-bcm63xx.c
+@@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev
+
+ DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
+ #endif
++
++static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
++{
++ switch (bus->number) {
++ case PCIE_BUS_BRIDGE:
++ return (PCI_SLOT(devfn) == 0);
++ case PCIE_BUS_DEVICE:
++ if (PCI_SLOT(devfn) == 0)
++ return bcm_pcie_readl(PCIE_DLSTATUS_REG)
++ & DLSTATUS_PHYLINKUP;
++ default:
++ return false;
++ }
++}
++
++static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 *val)
++{
++ u32 data;
++ u32 reg = where & ~3;
++
++ if (!bcm63xx_pcie_can_access(bus, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (bus->number == PCIE_BUS_DEVICE)
++ reg += PCIE_DEVICE_OFFSET;
++
++ data = bcm_pcie_readl(reg);
++
++ *val = postprocess_read(data, where, size);
++
++ return PCIBIOS_SUCCESSFUL;
++
++}
++
++static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ u32 data;
++ u32 reg = where & ~3;
++
++ if (!bcm63xx_pcie_can_access(bus, devfn))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (bus->number == PCIE_BUS_DEVICE)
++ reg += PCIE_DEVICE_OFFSET;
++
++
++ data = bcm_pcie_readl(reg);
++
++ data = preprocess_write(data, val, where, size);
++ bcm_pcie_writel(data, reg);
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++
++struct pci_ops bcm63xx_pcie_ops = {
++ .read = bcm63xx_pcie_read,
++ .write = bcm63xx_pcie_write
++};
+--- a/arch/mips/pci/pci-bcm63xx.c
++++ b/arch/mips/pci/pci-bcm63xx.c
+@@ -10,6 +10,7 @@
+ #include <linux/pci.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
++#include <linux/delay.h>
+ #include <asm/bootinfo.h>
+
+ #include "pci-bcm63xx.h"
+@@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_control
+ };
+ #endif
+
++static struct resource bcm_pcie_mem_resource = {
++ .name = "bcm63xx PCIe memory space",
++ .start = BCM_PCIE_MEM_BASE_PA,
++ .end = BCM_PCIE_MEM_END_PA,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource bcm_pcie_io_resource = {
++ .name = "bcm63xx PCIe IO space",
++ .start = 0,
++ .end = 0,
++ .flags = 0,
++};
++
++struct pci_controller bcm63xx_pcie_controller = {
++ .pci_ops = &bcm63xx_pcie_ops,
++ .io_resource = &bcm_pcie_io_resource,
++ .mem_resource = &bcm_pcie_mem_resource,
++};
++
+ static u32 bcm63xx_int_cfg_readl(u32 reg)
+ {
+ u32 tmp;
+@@ -94,6 +115,95 @@ static void bcm63xx_int_cfg_writel(u32 v
+
+ void __iomem *pci_iospace_start;
+
++static void __init bcm63xx_reset_pcie(void)
++{
++ u32 val;
++
++ /* enable clock */
++ val = bcm_perf_readl(PERF_CKCTL_REG);
++ val |= CKCTL_6328_PCIE_EN;
++ bcm_perf_writel(val, PERF_CKCTL_REG);
++
++ /* enable SERDES */
++ val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
++ val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
++ bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
++
++ /* reset the PCIe core */
++ val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
++
++ val &= ~SOFTRESET_6328_PCIE_MASK;
++ val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
++ val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
++ val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
++ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ mdelay(10);
++
++ val |= SOFTRESET_6328_PCIE_MASK;
++ val |= SOFTRESET_6328_PCIE_CORE_MASK;
++ val |= SOFTRESET_6328_PCIE_HARD_MASK;
++ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ mdelay(10);
++
++ val |= SOFTRESET_6328_PCIE_EXT_MASK;
++ bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ mdelay(200);
++}
++
++static int __init bcm63xx_register_pcie(void)
++{
++ u32 val;
++
++ bcm63xx_reset_pcie();
++
++ /* configure the PCIe bridge */
++ val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
++ val |= OPT1_RD_BE_OPT_EN;
++ val |= OPT1_RD_REPLY_BE_FIX_EN;
++ val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
++ val |= OPT1_L1_INT_STATUS_MASK_POL;
++ bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
++
++ /* setup the interrupts */
++ val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
++ val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
++ bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
++
++ val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
++ /* enable credit checking and error checking */
++ val |= OPT2_TX_CREDIT_CHK_EN;
++ val |= OPT2_UBUS_UR_DECODE_DIS;
++
++ /* set device bus/func for the pcie device */
++ val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
++ val |= OPT2_CFG_TYPE1_BD_SEL;
++ bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
++
++ /* setup class code as bridge */
++ val = bcm_pcie_readl(PCIE_IDVAL3_REG);
++ val &= ~IDVAL3_CLASS_CODE_MASK;
++ val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
++ bcm_pcie_writel(val, PCIE_IDVAL3_REG);
++
++ /* disable bar1 size */
++ val = bcm_pcie_readl(PCIE_CONFIG2_REG);
++ val &= ~CONFIG2_BAR1_SIZE_MASK;
++ bcm_pcie_writel(val, PCIE_CONFIG2_REG);
++
++ /* set bar0 to little endian */
++ val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
++ val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
++ val |= BASEMASK_REMAP_EN;
++ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
++
++ val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
++ bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
++
++ register_pci_controller(&bcm63xx_pcie_controller);
++
++ return 0;
++}
++
+ static int __init bcm63xx_register_pci(void)
+ {
+ unsigned int mem_size;
+@@ -221,6 +331,8 @@ static int __init bcm63xx_pci_init(void)
+ return -ENODEV;
+
+ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ return bcm63xx_register_pcie();
+ case BCM6348_CPU_ID:
+ case BCM6358_CPU_ID:
+ case BCM6368_CPU_ID:
+--- a/arch/mips/pci/pci-bcm63xx.h
++++ b/arch/mips/pci/pci-bcm63xx.h
+@@ -13,11 +13,16 @@
+ */
+ #define CARDBUS_PCI_IDSEL 0x8
+
++
++#define PCIE_BUS_BRIDGE 0
++#define PCIE_BUS_DEVICE 1
++
+ /*
+ * defined in ops-bcm63xx.c
+ */
+ extern struct pci_ops bcm63xx_pci_ops;
+ extern struct pci_ops bcm63xx_cb_ops;
++extern struct pci_ops bcm63xx_pcie_ops;
+
+ /*
+ * defined in pci-bcm63xx.c
diff --git a/target/linux/brcm63xx/patches-3.3/028-MIPS-Expose-PCIe-drivers-for-MIPS.patch b/target/linux/brcm63xx/patches-3.3/028-MIPS-Expose-PCIe-drivers-for-MIPS.patch
new file mode 100644
index 000000000..3169ca2fa
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/028-MIPS-Expose-PCIe-drivers-for-MIPS.patch
@@ -0,0 +1,28 @@
+From 4831929b8c37aa866afca1498001c939377e5a67 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Wed, 13 Jun 2012 17:07:16 +0100
+Subject: [PATCH 7/8] MIPS: Expose PCIe drivers for MIPS
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+Cc: linux-mips@linux-mips.org
+Cc: Maxime Bizon <mbizon@freebox.fr>
+Cc: Florian Fainelli <florian@openwrt.org>
+Cc: Kevin Cernekee <cernekee@gmail.com>
+Patchwork: https://patchwork.linux-mips.org/patch/3957/
+Reviewed-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+---
+ arch/mips/Kconfig | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -2392,6 +2392,8 @@ config PCI_DOMAINS
+
+ source "drivers/pci/Kconfig"
+
++source "drivers/pci/pcie/Kconfig"
++
+ #
+ # ISA support is now enabled via select. Too many systems still have the one
+ # or other ISA chip on the board that users don't know about so don't expect
diff --git a/target/linux/brcm63xx/patches-3.3/100-MIPS-BCM63XX-add-missing-include-for-bcm63xx_gpio.h.patch b/target/linux/brcm63xx/patches-3.3/100-MIPS-BCM63XX-add-missing-include-for-bcm63xx_gpio.h.patch
new file mode 100644
index 000000000..f6b15ac6f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/100-MIPS-BCM63XX-add-missing-include-for-bcm63xx_gpio.h.patch
@@ -0,0 +1,41 @@
+From a183d93bf0c6f9219ef1dd6e4948edf81c57ea3b Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 2 Feb 2012 09:27:58 +0100
+Subject: [PATCH] MIPS: BCM63XX: add missing include for bcm63xx_gpio.h
+
+bcm63xx_gpio.h uses macros defined in bcm63xx_cpu.h without including it,
+leading to the following build failure:
+
+ CC [M] drivers/mmc/core/cd-gpio.o
+In file included from arch/mips/include/asm/mach-bcm63xx/gpio.h:4:0,
+ from arch/mips/include/asm/gpio.h:4,
+ from include/linux/gpio.h:30,
+ from drivers/mmc/core/cd-gpio.c:12:
+
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h: In function 'bcm63xx_gpio_count':
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:10:2: error: implicit declaration of function 'bcm63xx_get_cpu_id'
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:11:7: error: 'BCM6358_CPU_ID' undeclared (first use in this function)
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:11:7: note: each undeclared identifier is reported only once for each function it appears in
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:13:7: error: 'BCM6338_CPU_ID' undeclared (first use in this function)
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:15:7: error: 'BCM6345_CPU_ID' undeclared (first use in this function)
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:17:7: error: 'BCM6368_CPU_ID' undeclared (first use in this function)
+arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h:19:7: error: 'BCM6348_CPU_ID' undeclared (first use in this function)
+
+make[7]: *** [drivers/mmc/core/cd-gpio.o] Error 1
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+@@ -2,6 +2,7 @@
+ #define BCM63XX_GPIO_H
+
+ #include <linux/init.h>
++#include <bcm63xx_cpu.h>
+
+ int __init bcm63xx_gpio_init(void);
+
diff --git a/target/linux/brcm63xx/patches-3.3/101-MTD-bcm63xxpart-remove-unused-variable.patch b/target/linux/brcm63xx/patches-3.3/101-MTD-bcm63xxpart-remove-unused-variable.patch
new file mode 100644
index 000000000..470f96663
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/101-MTD-bcm63xxpart-remove-unused-variable.patch
@@ -0,0 +1,41 @@
+From 2962bbe9cc807549c0705551c5b7be47e34e3fac Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 30 Apr 2012 09:32:56 +0200
+Subject: [PATCH 20/79] MTD: bcm63xxpart: remove unused variable
+
+namelen is never used, so drop it.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/bcm63xxpart.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -79,7 +79,6 @@ static int bcm63xx_parse_cfe_partitions(
+ unsigned int rootfsaddr, kerneladdr, spareaddr;
+ unsigned int rootfslen, kernellen, sparelen, totallen;
+ unsigned int cfelen, nvramlen;
+- int namelen = 0;
+ int i;
+ u32 computed_crc;
+ bool rootfs_first = false;
+@@ -143,15 +142,11 @@ static int bcm63xx_parse_cfe_partitions(
+ }
+
+ /* Determine number of partitions */
+- namelen = 8;
+- if (rootfslen > 0) {
++ if (rootfslen > 0)
+ nrparts++;
+- namelen += 6;
+- }
+- if (kernellen > 0) {
++
++ if (kernellen > 0)
+ nrparts++;
+- namelen += 6;
+- }
+
+ /* Ask kernel for more memory */
+ parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
diff --git a/target/linux/brcm63xx/patches-3.3/102-MTD-bcm63xxpart-merge-sparelen-calculation.patch b/target/linux/brcm63xx/patches-3.3/102-MTD-bcm63xxpart-merge-sparelen-calculation.patch
new file mode 100644
index 000000000..da24b1b85
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/102-MTD-bcm63xxpart-merge-sparelen-calculation.patch
@@ -0,0 +1,33 @@
+From fd2ab39f22af4176eb3d23acbc4d1218cf835065 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 8 May 2012 09:47:32 +0200
+Subject: [PATCH 21/79] MTD: bcm63xxpart: merge sparelen calculation
+
+The length of the spare part is calculated the same way in both branches
+so move to a common place.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/bcm63xxpart.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -120,7 +120,6 @@ static int bcm63xx_parse_cfe_partitions(
+ kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
+ rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
+ spareaddr = roundup(totallen, master->erasesize) + cfelen;
+- sparelen = master->size - spareaddr - nvramlen;
+
+ if (rootfsaddr < kerneladdr) {
+ /* default Broadcom layout */
+@@ -138,8 +137,8 @@ static int bcm63xx_parse_cfe_partitions(
+ rootfslen = 0;
+ rootfsaddr = 0;
+ spareaddr = cfelen;
+- sparelen = master->size - cfelen - nvramlen;
+ }
++ sparelen = master->size - spareaddr - nvramlen;
+
+ /* Determine number of partitions */
+ if (rootfslen > 0)
diff --git a/target/linux/brcm63xx/patches-3.3/103-MTD-bcm63xxpart-make-fixed-part-length-calculation-m.patch b/target/linux/brcm63xx/patches-3.3/103-MTD-bcm63xxpart-make-fixed-part-length-calculation-m.patch
new file mode 100644
index 000000000..ca0cddde9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/103-MTD-bcm63xxpart-make-fixed-part-length-calculation-m.patch
@@ -0,0 +1,49 @@
+From 465f1b3ff24dbf3bec43dce344a7bc2640e05ffc Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 8 May 2012 09:53:07 +0200
+Subject: [PATCH 22/79] MTD: bcm63xxpart: make fixed part length calculation
+ more generic
+
+The CFE does not use 4K sectors even if the flash supports it, so
+for the fixed partitions like CFE itself or NVRAM the erase block
+size is always 64k or bigger.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/bcm63xxpart.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -37,8 +37,7 @@
+
+ #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
+
+-#define BCM63XX_MIN_CFE_SIZE 0x10000 /* always at least 64KiB */
+-#define BCM63XX_MIN_NVRAM_SIZE 0x10000 /* always at least 64KiB */
++#define BCM63XX_CFE_BLOCK_SIZE 0x10000 /* always at least 64KiB */
+
+ #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
+
+@@ -79,6 +78,7 @@ static int bcm63xx_parse_cfe_partitions(
+ unsigned int rootfsaddr, kerneladdr, spareaddr;
+ unsigned int rootfslen, kernellen, sparelen, totallen;
+ unsigned int cfelen, nvramlen;
++ unsigned int cfe_erasesize;
+ int i;
+ u32 computed_crc;
+ bool rootfs_first = false;
+@@ -86,8 +86,11 @@ static int bcm63xx_parse_cfe_partitions(
+ if (bcm63xx_detect_cfe(master))
+ return -EINVAL;
+
+- cfelen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_CFE_SIZE);
+- nvramlen = max_t(uint32_t, master->erasesize, BCM63XX_MIN_NVRAM_SIZE);
++ cfe_erasesize = max_t(uint32_t, master->erasesize,
++ BCM63XX_CFE_BLOCK_SIZE);
++
++ cfelen = cfe_erasesize;
++ nvramlen = cfe_erasesize;
+
+ /* Allocate memory for buffer */
+ buf = vmalloc(sizeof(struct bcm_tag));
diff --git a/target/linux/brcm63xx/patches-3.3/104-MTD-bcm63xxpart-move-the-last-curpart-to-its-correct.patch b/target/linux/brcm63xx/patches-3.3/104-MTD-bcm63xxpart-move-the-last-curpart-to-its-correct.patch
new file mode 100644
index 000000000..8e05803ff
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/104-MTD-bcm63xxpart-move-the-last-curpart-to-its-correct.patch
@@ -0,0 +1,26 @@
+From d5173b2c806f4039679b001f1b55a3c245afdf68 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 8 May 2012 10:02:13 +0200
+Subject: [PATCH 23/79] MTD: bcm63xxpart: move the last curpart++ to its
+ correct place
+
+The line belongs above the comment, not below it.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/bcm63xxpart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -190,9 +190,9 @@ static int bcm63xx_parse_cfe_partitions(
+ parts[curpart].name = "nvram";
+ parts[curpart].offset = master->size - nvramlen;
+ parts[curpart].size = nvramlen;
++ curpart++;
+
+ /* Global partition "linux" to make easy firmware upgrade */
+- curpart++;
+ parts[curpart].name = "linux";
+ parts[curpart].offset = cfelen;
+ parts[curpart].size = master->size - cfelen - nvramlen;
diff --git a/target/linux/brcm63xx/patches-3.3/105-MTD-bcm63xxpart-use-correct-printk-format-for-partit.patch b/target/linux/brcm63xx/patches-3.3/105-MTD-bcm63xxpart-use-correct-printk-format-for-partit.patch
new file mode 100644
index 000000000..60396abae
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/105-MTD-bcm63xxpart-use-correct-printk-format-for-partit.patch
@@ -0,0 +1,27 @@
+From 55aa355612ce55dc1943f116ea49e795a098b60c Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 8 May 2012 10:03:27 +0200
+Subject: [PATCH 24/79] MTD: bcm63xxpart: use correct printk format for
+ partitions
+
+Use ll to be able to remove the casts.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/bcm63xxpart.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -198,9 +198,8 @@ static int bcm63xx_parse_cfe_partitions(
+ parts[curpart].size = master->size - cfelen - nvramlen;
+
+ for (i = 0; i < nrparts; i++)
+- pr_info("Partition %d is %s offset %lx and length %lx\n", i,
+- parts[i].name, (long unsigned int)(parts[i].offset),
+- (long unsigned int)(parts[i].size));
++ pr_info("Partition %d is %s offset %llx and length %llx\n", i,
++ parts[i].name, parts[i].offset, parts[i].size);
+
+ pr_info("Spare partition is offset %x and length %x\n", spareaddr,
+ sparelen);
diff --git a/target/linux/brcm63xx/patches-3.3/106-bcm63xx_watchdog_section_mismatch.patch b/target/linux/brcm63xx/patches-3.3/106-bcm63xx_watchdog_section_mismatch.patch
new file mode 100644
index 000000000..ae4157774
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/106-bcm63xx_watchdog_section_mismatch.patch
@@ -0,0 +1,20 @@
+--- a/drivers/watchdog/bcm63xx_wdt.c
++++ b/drivers/watchdog/bcm63xx_wdt.c
+@@ -301,7 +301,7 @@ static void bcm63xx_wdt_shutdown(struct
+ bcm63xx_wdt_pause();
+ }
+
+-static struct platform_driver bcm63xx_wdt = {
++static struct platform_driver bcm63xx_wdt_driver = {
+ .probe = bcm63xx_wdt_probe,
+ .remove = __devexit_p(bcm63xx_wdt_remove),
+ .shutdown = bcm63xx_wdt_shutdown,
+@@ -311,7 +311,7 @@ static struct platform_driver bcm63xx_wd
+ }
+ };
+
+-module_platform_driver(bcm63xx_wdt);
++module_platform_driver(bcm63xx_wdt_driver);
+
+ MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
+ MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
diff --git a/target/linux/brcm63xx/patches-3.3/107-MIPS-BCM63XX-Fix-USB-IRQ-definitions-for-6328.patch b/target/linux/brcm63xx/patches-3.3/107-MIPS-BCM63XX-Fix-USB-IRQ-definitions-for-6328.patch
new file mode 100644
index 000000000..c9d0421a2
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/107-MIPS-BCM63XX-Fix-USB-IRQ-definitions-for-6328.patch
@@ -0,0 +1,26 @@
+From 960e1ef3c5b2d69a4a5a6984b6408d65221dd86c Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Sat, 23 Jun 2012 04:14:55 +0000
+Subject: [PATCH 06/81] MIPS: BCM63XX: Fix USB IRQ definitions for 6328
+
+OHCI/EHCI are in the high (second) word. Not currently used by any
+driver.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -602,8 +602,8 @@ enum bcm63xx_irq {
+ #define BCM_6328_ENET0_IRQ 0
+ #define BCM_6328_ENET1_IRQ 0
+ #define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
+-#define BCM_6328_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9)
+-#define BCM_6328_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
++#define BCM_6328_OHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 9)
++#define BCM_6328_EHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 10)
+ #define BCM_6328_PCMCIA_IRQ 0
+ #define BCM_6328_ENET0_RXDMA_IRQ 0
+ #define BCM_6328_ENET0_TXDMA_IRQ 0
diff --git a/target/linux/brcm63xx/patches-3.3/108-BCM63XX-Add-register-definitions-for-USBD-depen.patch b/target/linux/brcm63xx/patches-3.3/108-BCM63XX-Add-register-definitions-for-USBD-depen.patch
new file mode 100644
index 000000000..c2130a563
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/108-BCM63XX-Add-register-definitions-for-USBD-depen.patch
@@ -0,0 +1,62 @@
+From 21bb8141c205ae48d331787debb6b272add90ac7 Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Sat, 23 Jun 2012 04:14:54 +0000
+Subject: [PATCH 05/81] MIPS: BCM63XX: Add register definitions for USBD
+ dependencies
+
+The USB 2.0 device depends on some functionality in other blocks, such
+as GPIO and USBH. Add those register definitions here.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 6 +++---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 8 ++++++++
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -184,9 +184,9 @@ enum bcm63xx_regs_set {
+ #define BCM_6328_SPI_BASE (0xdeadbeef)
+ #define BCM_6328_UDC0_BASE (0xdeadbeef)
+ #define BCM_6328_USBDMA_BASE (0xdeadbeef)
+-#define BCM_6328_OHCI0_BASE (0xdeadbeef)
++#define BCM_6328_OHCI0_BASE (0xb0002600)
+ #define BCM_6328_OHCI_PRIV_BASE (0xdeadbeef)
+-#define BCM_6328_USBH_PRIV_BASE (0xdeadbeef)
++#define BCM_6328_USBH_PRIV_BASE (0xb0002700)
+ #define BCM_6328_MPI_BASE (0xdeadbeef)
+ #define BCM_6328_PCMCIA_BASE (0xdeadbeef)
+ #define BCM_6328_PCIE_BASE (0xb0e40000)
+@@ -199,7 +199,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6328_ENETDMAC_BASE (0xb000da00)
+ #define BCM_6328_ENETDMAS_BASE (0xb000dc00)
+ #define BCM_6328_ENETSW_BASE (0xb0e00000)
+-#define BCM_6328_EHCI0_BASE (0x10002500)
++#define BCM_6328_EHCI0_BASE (0xb0002500)
+ #define BCM_6328_SDRAM_BASE (0xdeadbeef)
+ #define BCM_6328_MEMC_BASE (0xdeadbeef)
+ #define BCM_6328_DDR_BASE (0xb0003000)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -543,6 +543,12 @@
+ #define GPIO_MODE_6368_SPI_SSN5 (1 << 31)
+
+
++#define GPIO_PINMUX_OTHR_REG 0x24
++#define GPIO_PINMUX_OTHR_6328_USB_SHIFT 12
++#define GPIO_PINMUX_OTHR_6328_USB_MASK (3 << GPIO_PINMUX_OTHR_6328_USB_SHIFT)
++#define GPIO_PINMUX_OTHR_6328_USB_HOST (1 << GPIO_PINMUX_OTHR_6328_USB_SHIFT)
++#define GPIO_PINMUX_OTHR_6328_USB_DEV (2 << GPIO_PINMUX_OTHR_6328_USB_SHIFT)
++
+ #define GPIO_BASEMODE_6368_REG 0x38
+ #define GPIO_BASEMODE_6368_UART2 0x1
+ #define GPIO_BASEMODE_6368_GPIO 0x0
+@@ -770,6 +776,8 @@
+ #define USBH_PRIV_SWAP_6358_REG 0x0
+ #define USBH_PRIV_SWAP_6368_REG 0x1c
+
++#define USBH_PRIV_SWAP_USBD_SHIFT 6
++#define USBH_PRIV_SWAP_USBD_MASK (1 << USBH_PRIV_SWAP_USBD_SHIFT)
+ #define USBH_PRIV_SWAP_EHCI_ENDN_SHIFT 4
+ #define USBH_PRIV_SWAP_EHCI_ENDN_MASK (1 << USBH_PRIV_SWAP_EHCI_ENDN_SHIFT)
+ #define USBH_PRIV_SWAP_EHCI_DATA_SHIFT 3
diff --git a/target/linux/brcm63xx/patches-3.3/201-SPI-Allow-specifying-the-parsers-for-SPI-flash.patch b/target/linux/brcm63xx/patches-3.3/201-SPI-Allow-specifying-the-parsers-for-SPI-flash.patch
new file mode 100644
index 000000000..00dc9c90e
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/201-SPI-Allow-specifying-the-parsers-for-SPI-flash.patch
@@ -0,0 +1,38 @@
+From 3f650fc30aa0badf9d02842ce396cea3eef2eeaa Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Fri, 1 Jul 2011 23:16:47 +0200
+Subject: [PATCH 49/79] SPI: Allow specifying the parsers for SPI flash
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ include/linux/spi/flash.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/include/linux/spi/flash.h
++++ b/include/linux/spi/flash.h
+@@ -2,7 +2,7 @@
+ #define LINUX_SPI_FLASH_H
+
+ struct mtd_partition;
+-
++struct mtd_part_parser_data;
+ /**
+ * struct flash_platform_data: board-specific flash data
+ * @name: optional flash device name (eg, as used with mtdparts=)
+@@ -10,6 +10,8 @@ struct mtd_partition;
+ * @nr_parts: number of mtd_partitions for static partitoning
+ * @type: optional flash device type (e.g. m25p80 vs m25p64), for use
+ * with chips that can't be queried for JEDEC or other IDs
++ * @part_probe_types: optional list of MTD parser names to use for
++ * partitioning
+ *
+ * Board init code (in arch/.../mach-xxx/board-yyy.c files) can
+ * provide information about SPI flash parts (such as DataFlash) to
+@@ -25,6 +27,7 @@ struct flash_platform_data {
+
+ char *type;
+
++ const char **part_probe_types;
+ /* we'll likely add more ... use JEDEC IDs, etc */
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch b/target/linux/brcm63xx/patches-3.3/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch
new file mode 100644
index 000000000..486ec3a6d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch
@@ -0,0 +1,23 @@
+From c7c3c338cb25d7f55ddb3f6bfbf3572758ca3896 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 10 Nov 2011 16:53:08 +0100
+Subject: [PATCH 50/79] MTD: DEVICES: m25p80: use parsers if provided in flash
+ platform data
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/devices/m25p80.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -986,7 +986,8 @@ static int __devinit m25p_probe(struct s
+ /* 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_probe_types : NULL, &ppdata,
+ data ? data->parts : NULL,
+ data ? data->nr_parts : 0);
+ }
diff --git a/target/linux/brcm63xx/patches-3.3/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch b/target/linux/brcm63xx/patches-3.3/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch
new file mode 100644
index 000000000..847b6959e
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch
@@ -0,0 +1,92 @@
+From 5fb4e8d7287ac8fcb33aae8b1e9e22c5a3c392bd Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 10 Nov 2011 17:33:40 +0100
+Subject: [PATCH 51/79] MTD: DEVICES: m25p80: add support for limiting reads
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/mtd/devices/m25p80.c | 29 +++++++++++++++++++++++++++--
+ include/linux/spi/flash.h | 4 ++++
+ 2 files changed, 31 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -100,6 +100,7 @@ struct m25p {
+ u16 addr_width;
+ u8 erase_opcode;
+ u8 *command;
++ int max_transfer_len;
+ };
+
+ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+@@ -346,10 +347,9 @@ static int m25p80_erase(struct mtd_info
+ * Read an address range from the flash chip. The address range
+ * may be any size provided it is within the physical boundaries.
+ */
+-static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
++static int __m25p80_read(struct m25p *flash, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+ {
+- struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
+
+@@ -408,6 +408,28 @@ static int m25p80_read(struct mtd_info *
+ return 0;
+ }
+
++static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
++ size_t *retlen, u_char *buf)
++{
++ struct m25p *flash = mtd_to_m25p(mtd);
++ size_t off;
++ size_t read_len = flash->max_transfer_len;
++ size_t part_len;
++ int ret = 0;
++
++ if (!read_len)
++ return __m25p80_read(flash, from, len, retlen, buf);
++
++ *retlen = 0;
++
++ for (off = 0; off < len && !ret; off += read_len) {
++ ret = __m25p80_read(flash, from + off, min(len - off, read_len),
++ &part_len, buf + off);
++ *retlen += part_len;
++ }
++
++ return ret;
++}
+ /*
+ * Write an address range to the flash chip. Data must be written in
+ * FLASH_PAGESIZE chunks. The address range may be any size provided
+@@ -897,6 +919,9 @@ static int __devinit m25p_probe(struct s
+ return -ENOMEM;
+ }
+
++ if (data)
++ flash->max_transfer_len = data->max_transfer_len;
++
+ flash->spi = spi;
+ mutex_init(&flash->lock);
+ dev_set_drvdata(&spi->dev, flash);
+--- a/include/linux/spi/flash.h
++++ b/include/linux/spi/flash.h
+@@ -13,6 +13,8 @@ struct mtd_part_parser_data;
+ * @part_probe_types: optional list of MTD parser names to use for
+ * partitioning
+ *
++ * @max_transfer_len: option maximum read/write length limitation for
++ * SPI controllers not able to transfer any length commands.
+ * Board init code (in arch/.../mach-xxx/board-yyy.c files) can
+ * provide information about SPI flash parts (such as DataFlash) to
+ * help set up the device and its appropriate default partitioning.
+@@ -28,6 +30,8 @@ struct flash_platform_data {
+ char *type;
+
+ const char **part_probe_types;
++
++ unsigned int max_transfer_len;
+ /* we'll likely add more ... use JEDEC IDs, etc */
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch b/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch
new file mode 100644
index 000000000..0e1d6f8d9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/300-reset_buttons.patch
@@ -0,0 +1,116 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -12,6 +12,8 @@
+ #include <linux/string.h>
+ #include <linux/platform_device.h>
+ #include <linux/ssb/ssb.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
+ #include <asm/addrspace.h>
+ #include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+@@ -28,6 +30,9 @@
+
+ #define PFX "board_bcm963xx: "
+
++#define BCM963XX_KEYS_POLL_INTERVAL 20
++#define BCM963XX_KEYS_DEBOUNCE_INTERVAL (BCM963XX_KEYS_POLL_INTERVAL * 3)
++
+ static struct bcm963xx_nvram nvram;
+ static unsigned int mac_addr_used;
+ static struct board_info board;
+@@ -293,6 +298,16 @@ static struct board_info __initdata boar
+ .active_low = 1,
+ },
+ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 33,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
+ };
+
+ static struct board_info __initdata board_96348gw = {
+@@ -351,6 +366,16 @@ static struct board_info __initdata boar
+ .active_low = 1,
+ },
+ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 36,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
+ };
+
+ static struct board_info __initdata board_FAST2404 = {
+@@ -821,11 +846,23 @@ static struct platform_device bcm63xx_gp
+ .dev.platform_data = &bcm63xx_led_data,
+ };
+
++static struct gpio_keys_platform_data bcm63xx_gpio_keys_data = {
++ .poll_interval = BCM963XX_KEYS_POLL_INTERVAL,
++};
++
++static struct platform_device bcm63xx_gpio_keys_device = {
++ .name = "gpio-keys-polled",
++ .id = 0,
++ .dev.platform_data = &bcm63xx_gpio_keys_data,
++};
++
+ /*
+ * third stage init callback, register all board devices.
+ */
+ int __init board_register_devices(void)
+ {
++ int button_count = 0;
++
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+
+@@ -868,5 +905,16 @@ int __init board_register_devices(void)
+
+ platform_device_register(&bcm63xx_gpio_leds);
+
++ /* count number of BUTTONs defined by this device */
++ while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
++ button_count++;
++
++ if (button_count) {
++ bcm63xx_gpio_keys_data.nbuttons = button_count;
++ bcm63xx_gpio_keys_data.buttons = board.buttons;
++
++ platform_device_register(&bcm63xx_gpio_keys_device);
++ }
++
+ return 0;
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -3,6 +3,7 @@
+
+ #include <linux/types.h>
+ #include <linux/gpio.h>
++#include <linux/gpio_keys.h>
+ #include <linux/leds.h>
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
+@@ -57,6 +58,9 @@ struct board_info {
+
+ /* GPIO LEDs */
+ struct gpio_led leds[5];
++
++ /* Buttons */
++ struct gpio_keys_button buttons[4];
+ };
+
+ #endif /* ! BOARD_BCM963XX_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/301-led_count.patch b/target/linux/brcm63xx/patches-3.3/301-led_count.patch
new file mode 100644
index 000000000..b6c1196a5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/301-led_count.patch
@@ -0,0 +1,41 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -862,6 +862,7 @@ static struct platform_device bcm63xx_gp
+ int __init board_register_devices(void)
+ {
+ int button_count = 0;
++ int led_count = 0;
+
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+@@ -900,10 +901,16 @@ int __init board_register_devices(void)
+
+ bcm63xx_flash_register();
+
+- bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
+- bcm63xx_led_data.leds = board.leds;
++ /* count number of LEDs defined by this device */
++ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
++ led_count++;
++
++ if (led_count) {
++ bcm63xx_led_data.num_leds = led_count;
++ bcm63xx_led_data.leds = board.leds;
+
+- platform_device_register(&bcm63xx_gpio_leds);
++ platform_device_register(&bcm63xx_gpio_leds);
++ }
+
+ /* count number of BUTTONs defined by this device */
+ while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -57,7 +57,7 @@ struct board_info {
+ struct bcm63xx_dsp_platform_data dsp;
+
+ /* GPIO LEDs */
+- struct gpio_led leds[5];
++ struct gpio_led leds[14];
+
+ /* Buttons */
+ struct gpio_keys_button buttons[4];
diff --git a/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch b/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch
new file mode 100644
index 000000000..b48ef733b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/302-extended-platform-devices.patch
@@ -0,0 +1,25 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -899,6 +899,9 @@ int __init board_register_devices(void)
+
+ bcm63xx_spi_register();
+
++ if (board.num_devs)
++ platform_add_devices(board.devs, board.num_devs);
++
+ bcm63xx_flash_register();
+
+ /* count number of LEDs defined by this device */
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -61,6 +61,10 @@ struct board_info {
+
+ /* Buttons */
+ struct gpio_keys_button buttons[4];
++
++ /* Additional platform devices */
++ struct platform_device **devs;
++ unsigned int num_devs;
+ };
+
+ #endif /* ! BOARD_BCM963XX_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch b/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch
new file mode 100644
index 000000000..517a53b56
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/303-spi-board-info.patch
@@ -0,0 +1,33 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -14,6 +14,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/spi/spi.h>
+ #include <asm/addrspace.h>
+ #include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+@@ -902,6 +903,9 @@ int __init board_register_devices(void)
+ if (board.num_devs)
+ platform_add_devices(board.devs, board.num_devs);
+
++ if (board.num_spis)
++ spi_register_board_info(board.spis, board.num_spis);
++
+ bcm63xx_flash_register();
+
+ /* count number of LEDs defined by this device */
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -65,6 +65,10 @@ struct board_info {
+ /* Additional platform devices */
+ struct platform_device **devs;
+ unsigned int num_devs;
++
++ /* Additional platform devices */
++ struct spi_board_info *spis;
++ unsigned int num_spis;
+ };
+
+ #endif /* ! BOARD_BCM963XX_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch b/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch
new file mode 100644
index 000000000..0c2fab575
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/304-boardid_fixup.patch
@@ -0,0 +1,61 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -28,12 +28,16 @@
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
+ #include <board_bcm963xx.h>
++#include <bcm_tag.h>
+
+ #define PFX "board_bcm963xx: "
+
+ #define BCM963XX_KEYS_POLL_INTERVAL 20
+ #define BCM963XX_KEYS_DEBOUNCE_INTERVAL (BCM963XX_KEYS_POLL_INTERVAL * 3)
+
++#define CFE_OFFSET_64K 0x10000
++#define CFE_OFFSET_128K 0x20000
++
+ static struct bcm963xx_nvram nvram;
+ static unsigned int mac_addr_used;
+ static struct board_info board;
+@@ -724,6 +728,29 @@ static int board_get_mac_address(u8 *mac
+ return 0;
+ }
+
++static void __init boardid_fixup(u8 *boot_addr)
++{
++ struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
++
++ /* check if bcm_tag is at 64k offset */
++ if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ /* else try 128k */
++ tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_128K);
++ if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ /* No tag found */
++ printk(KERN_DEBUG "No bcm_tag found!\n");
++ return;
++ }
++ }
++ /* check if we should override the boardid */
++ if (tag->information1[0] != '+')
++ return;
++
++ strncpy(nvram.name, &tag->information1[1], BOARDID_LEN);
++
++ printk(KERN_INFO "Overriding boardid with '%s'\n", nvram.name);
++}
++
+ /*
+ * early init callback, read nvram data from flash and checksum it
+ */
+@@ -771,6 +798,11 @@ void __init board_prom_init(void)
+ return;
+ }
+
++ if (strcmp(cfe_version, "unknown") != 0) {
++ /* cfe present */
++ boardid_fixup(boot_addr);
++ }
++
+ /* find board by name */
+ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
+ if (strncmp(nvram.name, bcm963xx_boards[i]->name,
diff --git a/target/linux/brcm63xx/patches-3.3/305-missing_ext_irq_bits.patch b/target/linux/brcm63xx/patches-3.3/305-missing_ext_irq_bits.patch
new file mode 100644
index 000000000..703f4b54b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/305-missing_ext_irq_bits.patch
@@ -0,0 +1,96 @@
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -56,8 +56,8 @@ static void __internal_irq_unmask_64(uns
+ #define is_ext_irq_cascaded 0
+ #define ext_irq_start 0
+ #define ext_irq_end 0
+-#define ext_irq_count 0
+-#define ext_irq_cfg_reg1 0
++#define ext_irq_count 4
++#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6345
+ #define ext_irq_cfg_reg2 0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6348
+@@ -143,11 +143,15 @@ static void bcm63xx_init_irq(void)
+ irq_stat_addr += PERF_IRQSTAT_6338_REG;
+ irq_mask_addr += PERF_IRQMASK_6338_REG;
+ irq_bits = 32;
++ ext_irq_count = 4;
++ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+ break;
+ case BCM6345_CPU_ID:
+ irq_stat_addr += PERF_IRQSTAT_6345_REG;
+ irq_mask_addr += PERF_IRQMASK_6345_REG;
+ irq_bits = 32;
++ ext_irq_count = 4;
++ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+ break;
+ case BCM6348_CPU_ID:
+ irq_stat_addr += PERF_IRQSTAT_6348_REG;
+@@ -434,7 +438,8 @@ static int bcm63xx_external_irq_set_type
+ reg = bcm_perf_readl(regaddr);
+ irq %= 4;
+
+- if (BCMCPU_IS_6348()) {
++ switch (bcm63xx_get_cpu_id()) {
++ case BCM6348_CPU_ID:
+ if (levelsense)
+ reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
+ else
+@@ -447,9 +452,12 @@ static int bcm63xx_external_irq_set_type
+ reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
+ else
+ reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
+- }
++ break;
+
+- if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
++ case BCM6338_CPU_ID:
++ case BCM6345_CPU_ID:
++ case BCM6358_CPU_ID:
++ case BCM6368_CPU_ID:
+ if (levelsense)
+ reg |= EXTIRQ_CFG_LEVELSENSE(irq);
+ else
+@@ -462,6 +470,9 @@ static int bcm63xx_external_irq_set_type
+ reg |= EXTIRQ_CFG_BOTHEDGE(irq);
+ else
+ reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
++ break;
++ default:
++ BUG();
+ }
+
+ bcm_perf_writel(reg, regaddr);
+--- a/arch/mips/bcm63xx/setup.c
++++ b/arch/mips/bcm63xx/setup.c
+@@ -74,6 +74,9 @@ void bcm63xx_machine_reboot(void)
+ case BCM6338_CPU_ID:
+ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
+ break;
++ case BCM6345_CPU_ID:
++ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6345;
++ break;
+ case BCM6348_CPU_ID:
+ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6348;
+ break;
+@@ -83,6 +86,9 @@ void bcm63xx_machine_reboot(void)
+ }
+
+ for (i = 0; i < 2; i++) {
++ if (!perf_regs[i])
++ break;
++
+ reg = bcm_perf_readl(perf_regs[i]);
+ if (BCMCPU_IS_6348()) {
+ reg &= ~EXTIRQ_CFG_MASK_ALL_6348;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -161,6 +161,7 @@
+ /* External Interrupt Configuration register */
+ #define PERF_EXTIRQ_CFG_REG_6328 0x18
+ #define PERF_EXTIRQ_CFG_REG_6338 0x14
++#define PERF_EXTIRQ_CFG_REG_6345 0x14
+ #define PERF_EXTIRQ_CFG_REG_6348 0x14
+ #define PERF_EXTIRQ_CFG_REG_6358 0x14
+ #define PERF_EXTIRQ_CFG_REG_6368 0x18
diff --git a/target/linux/brcm63xx/patches-3.3/306-Revert-MIPS-BCM63XX-Call-board_register_device-from-.patch b/target/linux/brcm63xx/patches-3.3/306-Revert-MIPS-BCM63XX-Call-board_register_device-from-.patch
new file mode 100644
index 000000000..aa7ef8bbd
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/306-Revert-MIPS-BCM63XX-Call-board_register_device-from-.patch
@@ -0,0 +1,23 @@
+From a7d2622b6614fdca504c074a0cd307d5a1165c30 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 8 May 2012 09:39:01 +0200
+Subject: [PATCH 04/59] Revert "MIPS: BCM63XX: Call board_register_device from device_initcall()"
+
+This commit causes a race between PCI scan and SSB fallback SPROM handler
+registration, causing the wifi to not work on slower systems. The only
+subsystem touched from board_register_device is platform device
+registration, which should be safe as an arch init call.
+
+This reverts commit d64ed7ada2f689d2c62af1892ca55e47d3653e36.
+---
+ arch/mips/bcm63xx/setup.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/arch/mips/bcm63xx/setup.c
++++ b/arch/mips/bcm63xx/setup.c
+@@ -157,4 +157,4 @@ int __init bcm63xx_register_devices(void
+ return board_register_devices();
+ }
+
+-device_initcall(bcm63xx_register_devices);
++arch_initcall(bcm63xx_register_devices);
diff --git a/target/linux/brcm63xx/patches-3.3/307-MIPS-BCM63XX-allow-second-UART-on-BCM6328.patch b/target/linux/brcm63xx/patches-3.3/307-MIPS-BCM63XX-allow-second-UART-on-BCM6328.patch
new file mode 100644
index 000000000..1418d65bf
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/307-MIPS-BCM63XX-allow-second-UART-on-BCM6328.patch
@@ -0,0 +1,22 @@
+From c110865541e2d3782c412af9d48c016de5a64d9c Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 14 Jun 2011 21:14:39 +0200
+Subject: [PATCH 42/79] MIPS: BCM63XX: allow second UART on BCM6328
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/dev-uart.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/dev-uart.c
++++ b/arch/mips/bcm63xx/dev-uart.c
+@@ -54,7 +54,8 @@ int __init bcm63xx_uart_register(unsigne
+ if (id >= ARRAY_SIZE(bcm63xx_uart_devices))
+ return -ENODEV;
+
+- if (id == 1 && (!BCMCPU_IS_6358() && !BCMCPU_IS_6368()))
++ if (id == 1 && !BCMCPU_IS_6328() && !BCMCPU_IS_6358() &&
++ !BCMCPU_IS_6368())
+ return -ENODEV;
+
+ if (id == 0) {
diff --git a/target/linux/brcm63xx/patches-3.3/308-MIPS-BCM63XX-expose-the-HS-SPI-clock.patch b/target/linux/brcm63xx/patches-3.3/308-MIPS-BCM63XX-expose-the-HS-SPI-clock.patch
new file mode 100644
index 000000000..8a11f8266
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/308-MIPS-BCM63XX-expose-the-HS-SPI-clock.patch
@@ -0,0 +1,48 @@
+From 5aeb6273a610f8aab090b3499827177eb41311ba Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:19:09 +0100
+Subject: [PATCH 53/79] MIPS: BCM63XX: expose the HS SPI clock
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/clk.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -194,6 +194,26 @@ static struct clk clk_spi = {
+ };
+
+ /*
++ * SPI clock
++ */
++static void hsspi_set(struct clk *clk, int enable)
++{
++ u32 mask;
++
++ if (BCMCPU_IS_6328())
++ mask = CKCTL_6328_HSSPI_EN;
++ else
++ return;
++
++ bcm_hwclock_set(mask, enable);
++}
++
++static struct clk clk_hsspi = {
++ .set = hsspi_set,
++};
++
++
++/*
+ * XTM clock
+ */
+ static void xtm_set(struct clk *clk, int enable)
+@@ -286,6 +306,8 @@ struct clk *clk_get(struct device *dev,
+ return &clk_usbh;
+ if (!strcmp(id, "spi"))
+ return &clk_spi;
++ if (!strcmp(id, "hsspi"))
++ return &clk_hsspi;
+ if (!strcmp(id, "xtm"))
+ return &clk_xtm;
+ if (!strcmp(id, "periph"))
diff --git a/target/linux/brcm63xx/patches-3.3/309-MIPS-BCM63XX-add-HSSPI-register-definitions.patch b/target/linux/brcm63xx/patches-3.3/309-MIPS-BCM63XX-add-HSSPI-register-definitions.patch
new file mode 100644
index 000000000..5e2cd96d3
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/309-MIPS-BCM63XX-add-HSSPI-register-definitions.patch
@@ -0,0 +1,211 @@
+From 70f970222bc1096689ae1bffeb9ed09a7c4bed07 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:19:55 +0100
+Subject: [PATCH 28/60] MIPS: BCM63XX: add HSSPI register definitions
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 18 ++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 47 +++++++++++++++++++++
+ 2 files changed, 65 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -116,6 +116,7 @@ enum bcm63xx_regs_set {
+ RSET_UART1,
+ RSET_GPIO,
+ RSET_SPI,
++ RSET_HSSPI,
+ RSET_UDC0,
+ RSET_OHCI0,
+ RSET_OHCI_PRIV,
+@@ -159,6 +160,7 @@ enum bcm63xx_regs_set {
+ #define RSET_ENETDMA_SIZE 2048
+ #define RSET_ENETSW_SIZE 65536
+ #define RSET_UART_SIZE 24
++#define RSET_HSSPI_SIZE 1536
+ #define RSET_UDC_SIZE 256
+ #define RSET_OHCI_SIZE 256
+ #define RSET_EHCI_SIZE 256
+@@ -182,6 +184,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6328_UART1_BASE (0xb0000120)
+ #define BCM_6328_GPIO_BASE (0xb0000080)
+ #define BCM_6328_SPI_BASE (0xdeadbeef)
++#define BCM_6328_HSSPI_BASE (0xb0001000)
+ #define BCM_6328_UDC0_BASE (0xdeadbeef)
+ #define BCM_6328_USBDMA_BASE (0xdeadbeef)
+ #define BCM_6328_OHCI0_BASE (0xb0002600)
+@@ -227,6 +230,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6338_UART1_BASE (0xdeadbeef)
+ #define BCM_6338_GPIO_BASE (0xfffe0400)
+ #define BCM_6338_SPI_BASE (0xfffe0c00)
++#define BCM_6338_HSSPI_BASE (0xdeadbeef)
+ #define BCM_6338_UDC0_BASE (0xdeadbeef)
+ #define BCM_6338_USBDMA_BASE (0xfffe2400)
+ #define BCM_6338_OHCI0_BASE (0xdeadbeef)
+@@ -273,6 +277,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6345_UART1_BASE (0xdeadbeef)
+ #define BCM_6345_GPIO_BASE (0xfffe0400)
+ #define BCM_6345_SPI_BASE (0xdeadbeef)
++#define BCM_6345_HSSPI_BASE (0xdeadbeef)
+ #define BCM_6345_UDC0_BASE (0xdeadbeef)
+ #define BCM_6345_USBDMA_BASE (0xfffe2800)
+ #define BCM_6345_ENET0_BASE (0xfffe1800)
+@@ -318,6 +323,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6348_UART1_BASE (0xdeadbeef)
+ #define BCM_6348_GPIO_BASE (0xfffe0400)
+ #define BCM_6348_SPI_BASE (0xfffe0c00)
++#define BCM_6348_HSSPI_BASE (0xdeadbeef)
+ #define BCM_6348_UDC0_BASE (0xfffe1000)
+ #define BCM_6348_OHCI0_BASE (0xfffe1b00)
+ #define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00)
+@@ -361,6 +367,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_UART1_BASE (0xfffe0120)
+ #define BCM_6358_GPIO_BASE (0xfffe0080)
+ #define BCM_6358_SPI_BASE (0xfffe0800)
++#define BCM_6358_HSSPI_BASE (0xdeadbeef)
+ #define BCM_6358_UDC0_BASE (0xfffe0800)
+ #define BCM_6358_OHCI0_BASE (0xfffe1400)
+ #define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef)
+@@ -405,6 +412,7 @@ enum bcm63xx_regs_set {
+ #define BCM_6368_UART1_BASE (0xb0000120)
+ #define BCM_6368_GPIO_BASE (0xb0000080)
+ #define BCM_6368_SPI_BASE (0xb0000800)
++#define BCM_6368_HSSPI_BASE (0xdeadbeef)
+ #define BCM_6368_UDC0_BASE (0xdeadbeef)
+ #define BCM_6368_OHCI0_BASE (0xb0001600)
+ #define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef)
+@@ -454,6 +462,7 @@ extern const unsigned long *bcm63xx_regs
+ __GEN_RSET_BASE(__cpu, UART1) \
+ __GEN_RSET_BASE(__cpu, GPIO) \
+ __GEN_RSET_BASE(__cpu, SPI) \
++ __GEN_RSET_BASE(__cpu, HSSPI) \
+ __GEN_RSET_BASE(__cpu, UDC0) \
+ __GEN_RSET_BASE(__cpu, OHCI0) \
+ __GEN_RSET_BASE(__cpu, OHCI_PRIV) \
+@@ -495,6 +504,7 @@ extern const unsigned long *bcm63xx_regs
+ [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \
+ [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \
+ [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \
++ [RSET_HSSPI] = BCM_## __cpu ##_HSSPI_BASE, \
+ [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \
+ [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \
+ [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \
+@@ -567,6 +577,7 @@ enum bcm63xx_irq {
+ IRQ_ENET0,
+ IRQ_ENET1,
+ IRQ_ENET_PHY,
++ IRQ_HSSPI,
+ IRQ_OHCI0,
+ IRQ_EHCI0,
+ IRQ_ENET0_RXDMA,
+@@ -602,6 +613,7 @@ enum bcm63xx_irq {
+ #define BCM_6328_ENET0_IRQ 0
+ #define BCM_6328_ENET1_IRQ 0
+ #define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
++#define BCM_6328_HSSPI_IRQ (IRQ_INTERNAL_BASE + 29)
+ #define BCM_6328_OHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 9)
+ #define BCM_6328_EHCI0_IRQ (BCM_6328_HIGH_IRQ_BASE + 10)
+ #define BCM_6328_PCMCIA_IRQ 0
+@@ -640,6 +652,7 @@ enum bcm63xx_irq {
+ #define BCM_6338_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
+ #define BCM_6338_ENET1_IRQ 0
+ #define BCM_6338_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
++#define BCM_6338_HSSPI_IRQ 0
+ #define BCM_6338_OHCI0_IRQ 0
+ #define BCM_6338_EHCI0_IRQ 0
+ #define BCM_6338_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 15)
+@@ -671,6 +684,7 @@ enum bcm63xx_irq {
+ #define BCM_6345_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
+ #define BCM_6345_ENET1_IRQ 0
+ #define BCM_6345_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
++#define BCM_6345_HSSPI_IRQ 0
+ #define BCM_6345_OHCI0_IRQ 0
+ #define BCM_6345_EHCI0_IRQ 0
+ #define BCM_6345_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 13 + 1)
+@@ -702,6 +716,7 @@ enum bcm63xx_irq {
+ #define BCM_6348_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
+ #define BCM_6348_ENET1_IRQ (IRQ_INTERNAL_BASE + 7)
+ #define BCM_6348_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
++#define BCM_6348_HSSPI_IRQ 0
+ #define BCM_6348_OHCI0_IRQ (IRQ_INTERNAL_BASE + 12)
+ #define BCM_6348_EHCI0_IRQ 0
+ #define BCM_6348_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 20)
+@@ -733,6 +748,7 @@ enum bcm63xx_irq {
+ #define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)
+ #define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
+ #define BCM_6358_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 9)
++#define BCM_6358_HSSPI_IRQ 0
+ #define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
+ #define BCM_6358_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
+ #define BCM_6358_ENET0_RXDMA_IRQ (IRQ_INTERNAL_BASE + 15)
+@@ -773,6 +789,7 @@ enum bcm63xx_irq {
+ #define BCM_6368_ENET0_IRQ 0
+ #define BCM_6368_ENET1_IRQ 0
+ #define BCM_6368_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 15)
++#define BCM_6368_HSSPI_IRQ 0
+ #define BCM_6368_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
+ #define BCM_6368_EHCI0_IRQ (IRQ_INTERNAL_BASE + 7)
+ #define BCM_6368_PCMCIA_IRQ 0
+@@ -813,6 +830,7 @@ extern const int *bcm63xx_irqs;
+ [IRQ_ENET0] = BCM_## __cpu ##_ENET0_IRQ, \
+ [IRQ_ENET1] = BCM_## __cpu ##_ENET1_IRQ, \
+ [IRQ_ENET_PHY] = BCM_## __cpu ##_ENET_PHY_IRQ, \
++ [IRQ_HSSPI] = BCM_## __cpu ##_HSSPI_IRQ, \
+ [IRQ_OHCI0] = BCM_## __cpu ##_OHCI0_IRQ, \
+ [IRQ_EHCI0] = BCM_## __cpu ##_EHCI0_IRQ, \
+ [IRQ_ENET0_RXDMA] = BCM_## __cpu ##_ENET0_RXDMA_IRQ, \
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -1239,4 +1239,51 @@
+
+ #define PCIE_DEVICE_OFFSET 0x8000
+
++/*************************************************************************
++ * _REG relative to RSET_HSSPI
++ *************************************************************************/
++
++#define HSSPI_GLOBAL_CTRL_REG 0x0
++#define GLOBAL_CTRL_CLK_POLARITY (1 << 17)
++#define GLOBAL_CTRL_CLK_GATE_SSOFF (1 << 16)
++
++#define HSSPI_GLOBAL_EXT_TRIGGER_REG 0x4
++
++#define HSSPI_INT_STATUS_REG 0x8
++#define HSSPI_INT_STATUS_MASKED_REG 0xc
++#define HSSPI_INT_MASK_REG 0x10
++
++#define HSSPI_PING0_CMD_DONE (1 << 0)
++
++#define HSSPI_INT_CLEAR_ALL 0xff001f1f
++
++#define HSSPI_PINGPONG_COMMAND_REG(x) (0x80 + (x) * 0x40)
++#define PINGPONG_CMD_COMMAND_MASK 0xf
++#define PINGPONG_COMMAND_NOOP 0
++#define PINGPONG_COMMAND_START_NOW 1
++#define PINGPONG_COMMAND_START_TRIGGER 2
++#define PINGPONG_COMMAND_HALT 3
++#define PINGPONG_COMMAND_FLUSH 4
++#define PINGPONG_CMD_PROFILE_SHIFT 8
++#define PINGPONG_CMD_SS_SHIFT 12
++
++#define HSSPI_PINGPONG_STATUS_REG(x) (0x84 + (x) * 0x40)
++
++#define HSSPI_PROFILE_CLK_CTRL_REG(x) (0x100 + (x) * 0x20)
++#define CLK_CTRL_ACCUM_RST_ON_LOOP (1 << 15)
++
++#define HSSPI_PROFILE_SIGNAL_CTRL_REG(x) (0x104 + (x) * 0x20)
++#define SIGNAL_CTRL_LATCH_RISING (1 << 12)
++#define SIGNAL_CTRL_LAUNCH_RISING (1 << 13)
++#define SIGNAL_CTRL_ASYNC_INPUT_PATH (1 << 16)
++
++#define HSSPI_PROFILE_MODE_CTRL_REG(x) (0x108 + (x) * 0x20)
++#define MODE_CTRL_MULTIDATA_RD_STRT_SHIFT 8
++#define MODE_CTRL_MULTIDATA_WR_STRT_SHIFT 12
++#define MODE_CTRL_MULTIDATA_RD_SIZE_SHIFT 16
++#define MODE_CTRL_MULTIDATA_WR_SIZE_SHIFT 18
++#define MODE_CTRL_PREPENDBYTE_CNT_SHIFT 24
++
++#define HSSPI_FIFO_REG(x) (0x200 + (x) * 0x200)
++
+ #endif /* BCM63XX_REGS_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/310-board_leds_naming.patch b/target/linux/brcm63xx/patches-3.3/310-board_leds_naming.patch
new file mode 100644
index 000000000..798e8018f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/310-board_leds_naming.patch
@@ -0,0 +1,267 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -61,28 +61,28 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl",
++ .name = "96338GW:green:adsl",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ses",
++ .name = "96338GW:green:ses",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96338GW:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96338GW!green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96338GW:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ }
+@@ -102,28 +102,28 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl",
++ .name = "96338W:green:adsl",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ses",
++ .name = "96338W:green:ses",
+ .gpio = 5,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96338W:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96338W:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96338W:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+@@ -162,29 +162,29 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl-fail",
++ .name = "96348R:green:adsl-fail",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp",
++ .name = "96348R:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96348R:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96348R:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+
+ },
+ {
+- .name = "stop",
++ .name = "96348R:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+@@ -223,28 +223,28 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl-fail",
++ .name = "96348GW-10:green:adsl-fail",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp",
++ .name = "96348GW-10:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96348GW-10:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96348GW-10:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96348GW-10:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+@@ -277,28 +277,28 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl-fail",
++ .name = "96348GW-11:green:adsl-fail",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp",
++ .name = "96348GW-11:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96348GW-11:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96348GW-11:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96348GW-11:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+@@ -345,28 +345,28 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl-fail",
++ .name = "96348GW:green:adsl-fail",
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp",
++ .name = "96348GW:green:ppp",
+ .gpio = 3,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96348GW:green:ppp-fail",
+ .gpio = 4,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96348GW:green:power",
+ .gpio = 0,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96348GW:green:stop",
+ .gpio = 1,
+ .active_low = 1,
+ },
+@@ -498,27 +498,27 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl-fail",
++ .name = "96358VW:green:adsl-fail",
+ .gpio = 15,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp",
++ .name = "96358VW:green:ppp",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96358VW:green:ppp-fail",
+ .gpio = 23,
+ .active_low = 1,
+ },
+ {
+- .name = "power",
++ .name = "96358VW:green:power",
+ .gpio = 4,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96358VW:green:stop",
+ .gpio = 5,
+ },
+ },
+@@ -550,22 +550,22 @@ static struct board_info __initdata boar
+
+ .leds = {
+ {
+- .name = "adsl",
++ .name = "96358VW2:green:adsl",
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+- .name = "ppp-fail",
++ .name = "96358VW2:green:ppp-fail",
+ .gpio = 23,
+ },
+ {
+- .name = "power",
++ .name = "96358VW2:green:power",
+ .gpio = 5,
+ .active_low = 1,
+ .default_trigger = "default-on",
+ },
+ {
+- .name = "stop",
++ .name = "96358VW2:green:stop",
+ .gpio = 4,
+ .active_low = 1,
+ },
diff --git a/target/linux/brcm63xx/patches-3.3/311-cfe_version_mod.patch b/target/linux/brcm63xx/patches-3.3/311-cfe_version_mod.patch
new file mode 100644
index 000000000..1269bc0c4
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/311-cfe_version_mod.patch
@@ -0,0 +1,26 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -777,6 +777,8 @@ void __init board_prom_init(void)
+ if (!memcmp(cfe, "cfe-v", 5))
+ snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u",
+ cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]);
++ else if (!memcmp(cfe, "cfe-", 4))
++ snprintf(cfe_version, 16, "%s", (char *) &cfe[4]);
+ else
+ strcpy(cfe_version, "unknown");
+ printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -54,10 +54,10 @@ static int bcm63xx_detect_cfe(struct mtd
+ if (ret)
+ return ret;
+
+- if (strncmp("cfe-v", buf, 5) == 0)
++ if (strncmp("cfe-", buf, 4) == 0)
+ return 0;
+
+- /* very old CFE's do not have the cfe-v string, so check for magic */
++ /* very old CFE's do not have the cfe- string, so check for magic */
+ ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
+ (void *)buf);
+ buf[retlen] = 0;
diff --git a/target/linux/brcm63xx/patches-3.3/312-MIPS-BCM63XX-add-basic-BCM6362-support.patch b/target/linux/brcm63xx/patches-3.3/312-MIPS-BCM63XX-add-basic-BCM6362-support.patch
new file mode 100644
index 000000000..5b6ecbed4
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/312-MIPS-BCM63XX-add-basic-BCM6362-support.patch
@@ -0,0 +1,497 @@
+From 27ebbb819b1f92d52309276b29b7a56e362e5c4d Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 21 Nov 2011 00:48:52 +0100
+Subject: [PATCH 54/84] MIPS: BCM63XX: add basic BCM6362 support
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Kconfig | 4 +
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
+ arch/mips/bcm63xx/cpu.c | 52 ++++++++-
+ arch/mips/bcm63xx/irq.c | 19 +++
+ arch/mips/bcm63xx/prom.c | 2 +
+ arch/mips/bcm63xx/setup.c | 3 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 139 +++++++++++++++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h | 2 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 59 +++++++++
+ arch/mips/include/asm/mach-bcm63xx/ioremap.h | 1 +
+ 10 files changed, 281 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -25,6 +25,10 @@ config BCM63XX_CPU_6358
+ bool "support 6358 CPU"
+ select HW_HAS_PCI
+
++config BCM63XX_CPU_6362
++ bool "support 6362 CPU"
++ select HW_HAS_PCI
++
+ config BCM63XX_CPU_6368
+ bool "support 6368 CPU"
+ select HW_HAS_PCI
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -764,7 +764,7 @@ void __init board_prom_init(void)
+ /* read base address of boot chip select (0)
+ * 6328 does not have MPI but boots from a fixed address
+ */
+- if (BCMCPU_IS_6328())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
+ val = 0x18000000;
+ else {
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+--- a/arch/mips/bcm63xx/cpu.c
++++ b/arch/mips/bcm63xx/cpu.c
+@@ -71,6 +71,15 @@ static const int bcm6358_irqs[] = {
+
+ };
+
++static const unsigned long bcm6362_regs_base[] = {
++ __GEN_CPU_REGS_TABLE(6362)
++};
++
++static const int bcm6362_irqs[] = {
++ __GEN_CPU_IRQ_TABLE(6362)
++
++};
++
+ static const unsigned long bcm6368_regs_base[] = {
+ __GEN_CPU_REGS_TABLE(6368)
+ };
+@@ -169,6 +178,42 @@ static unsigned int detect_cpu_clock(voi
+ return (16 * 1000000 * n1 * n2) / m1;
+ }
+
++ case BCM6362_CPU_ID:
++ {
++ unsigned int tmp, mips_pll_fcvo;
++
++ tmp = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
++ mips_pll_fcvo = (tmp & STRAPBUS_6362_FCVO_MASK)
++ >> STRAPBUS_6362_FCVO_SHIFT;
++ switch (mips_pll_fcvo) {
++ case 0x03:
++ case 0x0b:
++ case 0x13:
++ case 0x1b:
++ return 240000000;
++ case 0x04:
++ case 0x0c:
++ case 0x14:
++ case 0x1c:
++ return 160000000;
++ case 0x05:
++ case 0x0e:
++ case 0x16:
++ case 0x1e:
++ case 0x1f:
++ return 400000000;
++ case 0x06:
++ return 440000000;
++ case 0x07:
++ case 0x17:
++ return 384000000;
++ case 0x15:
++ case 0x1d:
++ return 200000000;
++ default:
++ return 320000000;
++ }
++ }
+ case BCM6368_CPU_ID:
+ {
+ unsigned int tmp, p1, p2, ndiv, m1;
+@@ -205,7 +250,7 @@ static unsigned int detect_memory_size(v
+ unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
+ u32 val;
+
+- if (BCMCPU_IS_6328())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
+ return bcm_ddr_readl(DDR_CSEND_REG) << 24;
+
+ if (BCMCPU_IS_6345()) {
+@@ -280,6 +325,11 @@ void __init bcm63xx_cpu_init(void)
+ bcm63xx_regs_base = bcm6328_regs_base;
+ bcm63xx_irqs = bcm6328_irqs;
+ break;
++ case BCM6362_CPU_ID:
++ expected_cpu_id = BCM6362_CPU_ID;
++ bcm63xx_regs_base = bcm6362_regs_base;
++ bcm63xx_irqs = bcm6362_irqs;
++ break;
+ case BCM6368_CPU_ID:
+ expected_cpu_id = BCM6368_CPU_ID;
+ bcm63xx_regs_base = bcm6368_regs_base;
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -82,6 +82,14 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6358
+ #define ext_irq_cfg_reg2 0
+ #endif
++#ifdef CONFIG_BCM63XX_CPU_6362
++#define irq_stat_reg PERF_IRQSTAT_6362_REG
++#define irq_mask_reg PERF_IRQMASK_6362_REG
++#define irq_bits 64
++#define is_ext_irq_cascaded 1
++#define ext_irq_start (BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
++#define ext_irq_end (BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE)
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ #define irq_stat_reg PERF_IRQSTAT_6368_REG
+ #define irq_mask_reg PERF_IRQMASK_6368_REG
+@@ -170,6 +178,16 @@ static void bcm63xx_init_irq(void)
+ ext_irq_end = BCM_6358_EXT_IRQ3 - IRQ_INTERNAL_BASE;
+ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+ break;
++ case BCM6362_CPU_ID:
++ irq_stat_addr += PERF_IRQSTAT_6362_REG;
++ irq_mask_addr += PERF_IRQMASK_6362_REG;
++ irq_bits = 64;
++ ext_irq_count = 4;
++ is_ext_irq_cascaded = 1;
++ ext_irq_start = BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE;
++ ext_irq_end = BCM_6362_EXT_IRQ3 - IRQ_INTERNAL_BASE;
++ ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
++ break;
+ case BCM6368_CPU_ID:
+ irq_stat_addr += PERF_IRQSTAT_6368_REG;
+ irq_mask_addr += PERF_IRQMASK_6368_REG;
+@@ -457,6 +475,7 @@ static int bcm63xx_external_irq_set_type
+ case BCM6338_CPU_ID:
+ case BCM6345_CPU_ID:
+ case BCM6358_CPU_ID:
++ case BCM6362_CPU_ID:
+ case BCM6368_CPU_ID:
+ if (levelsense)
+ reg |= EXTIRQ_CFG_LEVELSENSE(irq);
+--- a/arch/mips/bcm63xx/prom.c
++++ b/arch/mips/bcm63xx/prom.c
+@@ -36,6 +36,8 @@ void __init prom_init(void)
+ mask = CKCTL_6348_ALL_SAFE_EN;
+ else if (BCMCPU_IS_6358())
+ mask = CKCTL_6358_ALL_SAFE_EN;
++ else if (BCMCPU_IS_6362())
++ mask = CKCTL_6362_ALL_SAFE_EN;
+ else if (BCMCPU_IS_6368())
+ mask = CKCTL_6368_ALL_SAFE_EN;
+ else
+--- a/arch/mips/bcm63xx/setup.c
++++ b/arch/mips/bcm63xx/setup.c
+@@ -83,6 +83,9 @@ void bcm63xx_machine_reboot(void)
+ case BCM6358_CPU_ID:
+ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6358;
+ break;
++ case BCM6362_CPU_ID:
++ perf_regs[0] = PERF_EXTIRQ_CFG_REG_6362;
++ break;
+ }
+
+ for (i = 0; i < 2; i++) {
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -14,6 +14,7 @@
+ #define BCM6345_CPU_ID 0x6345
+ #define BCM6348_CPU_ID 0x6348
+ #define BCM6358_CPU_ID 0x6358
++#define BCM6362_CPU_ID 0x6362
+ #define BCM6368_CPU_ID 0x6368
+
+ void __init bcm63xx_cpu_init(void);
+@@ -86,6 +87,20 @@ unsigned int bcm63xx_get_cpu_freq(void);
+ # define BCMCPU_IS_6358() (0)
+ #endif
+
++#ifdef CONFIG_BCM63XX_CPU_6362
++# ifdef bcm63xx_get_cpu_id
++# undef bcm63xx_get_cpu_id
++# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
++# define BCMCPU_RUNTIME_DETECT
++# else
++# define bcm63xx_get_cpu_id() BCM6362_CPU_ID
++# endif
++# define BCMCPU_IS_6362() (bcm63xx_get_cpu_id() == BCM6362_CPU_ID)
++#else
++# define BCMCPU_IS_6362() (0)
++#endif
++
++
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ # ifdef bcm63xx_get_cpu_id
+ # undef bcm63xx_get_cpu_id
+@@ -402,6 +417,62 @@ enum bcm63xx_regs_set {
+
+
+ /*
++ * 6362 register sets base address
++ */
++#define BCM_6362_DSL_LMEM_BASE (0xdeadbeef)
++#define BCM_6362_PERF_BASE (0xb0000000)
++#define BCM_6362_TIMER_BASE (0xb0000040)
++#define BCM_6362_WDT_BASE (0xb000005c)
++#define BCM_6362_UART0_BASE (0xb0000100)
++#define BCM_6362_UART1_BASE (0xb0000120)
++#define BCM_6362_GPIO_BASE (0xb0000080)
++#define BCM_6362_SPI_BASE (0xb0000800)
++#define BCM_6362_HSSPI_BASE (0xb0001000)
++#define BCM_6362_UDC0_BASE (0xdeadbeef)
++#define BCM_6362_USBDMA_BASE (0xb000c000)
++#define BCM_6362_OHCI0_BASE (0xb0002600)
++#define BCM_6362_OHCI_PRIV_BASE (0xdeadbeef)
++#define BCM_6362_USBH_PRIV_BASE (0xb0002700)
++#define BCM_6362_USBD_BASE (0xb0002400)
++#define BCM_6362_MPI_BASE (0xdeadbeef)
++#define BCM_6362_PCMCIA_BASE (0xdeadbeef)
++#define BCM_6362_PCIE_BASE (0xb0e40000)
++#define BCM_6362_SDRAM_REGS_BASE (0xdeadbeef)
++#define BCM_6362_DSL_BASE (0xdeadbeef)
++#define BCM_6362_UBUS_BASE (0xdeadbeef)
++#define BCM_6362_ENET0_BASE (0xdeadbeef)
++#define BCM_6362_ENET1_BASE (0xdeadbeef)
++#define BCM_6362_ENETDMA_BASE (0xb000d800)
++#define BCM_6362_ENETDMAC_BASE (0xb000da00)
++#define BCM_6362_ENETDMAS_BASE (0xb000dc00)
++#define BCM_6362_ENETSW_BASE (0xb0e00000)
++#define BCM_6362_EHCI0_BASE (0xb0002500)
++#define BCM_6362_SDRAM_BASE (0xdeadbeef)
++#define BCM_6362_MEMC_BASE (0xdeadbeef)
++#define BCM_6362_DDR_BASE (0xb0003000)
++#define BCM_6362_M2M_BASE (0xdeadbeef)
++#define BCM_6362_ATM_BASE (0xdeadbeef)
++#define BCM_6362_XTM_BASE (0xb0007800)
++#define BCM_6362_XTMDMA_BASE (0xb000b800)
++#define BCM_6362_XTMDMAC_BASE (0xdeadbeef)
++#define BCM_6362_XTMDMAS_BASE (0xdeadbeef)
++#define BCM_6362_PCM_BASE (0xb000a800)
++#define BCM_6362_PCMDMA_BASE (0xdeadbeef)
++#define BCM_6362_PCMDMAC_BASE (0xdeadbeef)
++#define BCM_6362_PCMDMAS_BASE (0xdeadbeef)
++#define BCM_6362_RNG_BASE (0xdeadbeef)
++#define BCM_6362_MISC_BASE (0xb0001800)
++
++#define BCM_6362_NAND_REG_BASE (0xb0000200)
++#define BCM_6362_NAND_CACHE_BASE (0xb0000600)
++#define BCM_6362_LED_BASE (0xb0001900)
++#define BCM_6362_IPSEC_BASE (0xb0002800)
++#define BCM_6362_IPSEC_DMA_BASE (0xb000d000)
++#define BCM_6362_WLAN_CHIPCOMMON_BASE (0xb0004000)
++#define BCM_6362_WLAN_D11_BASE (0xb0005000)
++#define BCM_6362_WLAN_SHIM_BASE (0xb0007000)
++
++/*
+ * 6368 register sets base address
+ */
+ #define BCM_6368_DSL_LMEM_BASE (0xdeadbeef)
+@@ -557,6 +628,9 @@ static inline unsigned long bcm63xx_regs
+ #ifdef CONFIG_BCM63XX_CPU_6358
+ __GEN_RSET(6358)
+ #endif
++#ifdef CONFIG_BCM63XX_CPU_6362
++ __GEN_RSET(6362)
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ __GEN_RSET(6368)
+ #endif
+@@ -777,6 +851,71 @@ enum bcm63xx_irq {
+ #define BCM_6358_EXT_IRQ3 (IRQ_INTERNAL_BASE + 28)
+
+ /*
++ * 6362 irqs
++ */
++#define BCM_6362_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
++
++#define BCM_6362_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
++#define BCM_6362_SPI_IRQ (IRQ_INTERNAL_BASE + 2)
++#define BCM_6362_UART0_IRQ (IRQ_INTERNAL_BASE + 3)
++#define BCM_6362_UART1_IRQ (IRQ_INTERNAL_BASE + 4)
++#define BCM_6362_DSL_IRQ (IRQ_INTERNAL_BASE + 28)
++#define BCM_6362_UDC0_IRQ 0
++#define BCM_6362_ENET0_IRQ 0
++#define BCM_6362_ENET1_IRQ 0
++#define BCM_6362_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 14)
++#define BCM_6362_HSSPI_IRQ (IRQ_INTERNAL_BASE + 5)
++#define BCM_6362_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9)
++#define BCM_6362_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
++#define BCM_6362_USBD_IRQ (IRQ_INTERNAL_BASE + 11)
++#define BCM_6362_USBD_RXDMA0_IRQ (IRQ_INTERNAL_BASE + 20)
++#define BCM_6362_USBD_TXDMA0_IRQ (IRQ_INTERNAL_BASE + 21)
++#define BCM_6362_USBD_RXDMA1_IRQ (IRQ_INTERNAL_BASE + 22)
++#define BCM_6362_USBD_TXDMA1_IRQ (IRQ_INTERNAL_BASE + 23)
++#define BCM_6362_USBD_RXDMA2_IRQ (IRQ_INTERNAL_BASE + 24)
++#define BCM_6362_USBD_TXDMA2_IRQ (IRQ_INTERNAL_BASE + 25)
++#define BCM_6362_PCMCIA_IRQ 0
++#define BCM_6362_ENET0_RXDMA_IRQ 0
++#define BCM_6362_ENET0_TXDMA_IRQ 0
++#define BCM_6362_ENET1_RXDMA_IRQ 0
++#define BCM_6362_ENET1_TXDMA_IRQ 0
++#define BCM_6362_PCI_IRQ (IRQ_INTERNAL_BASE + 30)
++#define BCM_6362_ATM_IRQ 0
++#define BCM_6362_ENETSW_RXDMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 0)
++#define BCM_6362_ENETSW_RXDMA1_IRQ (BCM_6362_HIGH_IRQ_BASE + 1)
++#define BCM_6362_ENETSW_RXDMA2_IRQ (BCM_6362_HIGH_IRQ_BASE + 2)
++#define BCM_6362_ENETSW_RXDMA3_IRQ (BCM_6362_HIGH_IRQ_BASE + 3)
++#define BCM_6362_ENETSW_TXDMA0_IRQ 0
++#define BCM_6362_ENETSW_TXDMA1_IRQ 0
++#define BCM_6362_ENETSW_TXDMA2_IRQ 0
++#define BCM_6362_ENETSW_TXDMA3_IRQ 0
++#define BCM_6362_XTM_IRQ 0
++#define BCM_6362_XTM_DMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 12)
++
++#define BCM_6362_RING_OSC_IRQ (IRQ_INTERNAL_BASE + 1)
++#define BCM_6362_WLAN_GPIO_IRQ (IRQ_INTERNAL_BASE + 6)
++#define BCM_6362_WLAN_IRQ (IRQ_INTERNAL_BASE + 7)
++#define BCM_6362_IPSEC_IRQ (IRQ_INTERNAL_BASE + 8)
++#define BCM_6362_NAND_IRQ (IRQ_INTERNAL_BASE + 12)
++#define BCM_6362_PCM_IRQ (IRQ_INTERNAL_BASE + 13)
++#define BCM_6362_DG_IRQ (IRQ_INTERNAL_BASE + 15)
++#define BCM_6362_EPHY_ENERGY0_IRQ (IRQ_INTERNAL_BASE + 16)
++#define BCM_6362_EPHY_ENERGY1_IRQ (IRQ_INTERNAL_BASE + 17)
++#define BCM_6362_EPHY_ENERGY2_IRQ (IRQ_INTERNAL_BASE + 18)
++#define BCM_6362_EPHY_ENERGY3_IRQ (IRQ_INTERNAL_BASE + 19)
++#define BCM_6362_IPSEC_DMA0_IRQ (IRQ_INTERNAL_BASE + 26)
++#define BCM_6362_IPSEC_DMA1_IRQ (IRQ_INTERNAL_BASE + 27)
++#define BCM_6362_FAP0_IRQ (IRQ_INTERNAL_BASE + 29)
++#define BCM_6362_PCM_DMA0_IRQ (BCM_6362_HIGH_IRQ_BASE + 4)
++#define BCM_6362_PCM_DMA1_IRQ (BCM_6362_HIGH_IRQ_BASE + 5)
++#define BCM_6362_DECT0_IRQ (BCM_6362_HIGH_IRQ_BASE + 6)
++#define BCM_6362_DECT1_IRQ (BCM_6362_HIGH_IRQ_BASE + 7)
++#define BCM_6362_EXT_IRQ0 (BCM_6362_HIGH_IRQ_BASE + 8)
++#define BCM_6362_EXT_IRQ1 (BCM_6362_HIGH_IRQ_BASE + 9)
++#define BCM_6362_EXT_IRQ2 (BCM_6362_HIGH_IRQ_BASE + 10)
++#define BCM_6362_EXT_IRQ3 (BCM_6362_HIGH_IRQ_BASE + 11)
++
++/*
+ * 6368 irqs
+ */
+ #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h
+@@ -17,6 +17,8 @@ static inline unsigned long bcm63xx_gpio
+ return 8;
+ case BCM6345_CPU_ID:
+ return 16;
++ case BCM6362_CPU_ID:
++ return 48;
+ case BCM6368_CPU_ID:
+ return 38;
+ case BCM6348_CPU_ID:
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -107,6 +107,39 @@
+ CKCTL_6358_USBSU_EN | \
+ CKCTL_6358_EPHY_EN)
+
++#define CKCTL_6362_ADSL_QPROC_EN (1 << 1)
++#define CKCTL_6362_ADSL_AFE_EN (1 << 2)
++#define CKCTL_6362_ADSL_EN (1 << 3)
++#define CKCTL_6362_MIPS_EN (1 << 4)
++#define CKCTL_6362_WLAN_OCP_EN (1 << 5)
++#define CKCTL_6362_SWPKT_USB_EN (1 << 7)
++#define CKCTL_6362_SWPKT_SAR_EN (1 << 8)
++#define CKCTL_6362_SAR_EN (1 << 9)
++#define CKCTL_6362_ROBOSW_EN (1 << 10)
++#define CKCTL_6362_PCM_EN (1 << 11)
++#define CKCTL_6362_USBD_EN (1 << 12)
++#define CKCTL_6362_USBH_EN (1 << 13)
++#define CKCTL_6362_IPSEC_EN (1 << 14)
++#define CKCTL_6362_SPI_EN (1 << 15)
++#define CKCTL_6362_HSSPI_EN (1 << 16)
++#define CKCTL_6362_PCIE_EN (1 << 17)
++#define CKCTL_6362_FAP_EN (1 << 18)
++#define CKCTL_6362_PHYMIPS_EN (1 << 19)
++#define CKCTL_6362_NAND_EN (1 << 20)
++
++#define CKCTL_6362_ALL_SAFE_EN (CKCTL_6362_PHYMIPS_EN | \
++ CKCTL_6362_ADSL_QPROC_EN | \
++ CKCTL_6362_ADSL_AFE_EN | \
++ CKCTL_6362_ADSL_EN | \
++ CKCTL_6362_SAR_EN | \
++ CKCTL_6362_PCM_EN | \
++ CKCTL_6362_IPSEC_EN | \
++ CKCTL_6362_USBD_EN | \
++ CKCTL_6362_USBH_EN | \
++ CKCTL_6362_ROBOSW_EN | \
++ CKCTL_6362_PCIE_EN)
++
++
+ #define CKCTL_6368_VDSL_QPROC_EN (1 << 2)
+ #define CKCTL_6368_VDSL_AFE_EN (1 << 3)
+ #define CKCTL_6368_VDSL_BONDING_EN (1 << 4)
+@@ -148,6 +181,7 @@
+ #define PERF_IRQMASK_6345_REG 0xc
+ #define PERF_IRQMASK_6348_REG 0xc
+ #define PERF_IRQMASK_6358_REG 0xc
++#define PERF_IRQMASK_6362_REG 0x20
+ #define PERF_IRQMASK_6368_REG 0x20
+
+ /* Interrupt Status register */
+@@ -156,6 +190,7 @@
+ #define PERF_IRQSTAT_6345_REG 0x10
+ #define PERF_IRQSTAT_6348_REG 0x10
+ #define PERF_IRQSTAT_6358_REG 0x10
++#define PERF_IRQSTAT_6362_REG 0x28
+ #define PERF_IRQSTAT_6368_REG 0x28
+
+ /* External Interrupt Configuration register */
+@@ -164,6 +199,7 @@
+ #define PERF_EXTIRQ_CFG_REG_6345 0x14
+ #define PERF_EXTIRQ_CFG_REG_6348 0x14
+ #define PERF_EXTIRQ_CFG_REG_6358 0x14
++#define PERF_EXTIRQ_CFG_REG_6362 0x18
+ #define PERF_EXTIRQ_CFG_REG_6368 0x18
+
+ #define PERF_EXTIRQ_CFG_REG2_6368 0x1c
+@@ -191,6 +227,7 @@
+ /* Soft Reset register */
+ #define PERF_SOFTRESET_REG 0x28
+ #define PERF_SOFTRESET_6328_REG 0x10
++#define PERF_SOFTRESET_6362_REG 0x10
+ #define PERF_SOFTRESET_6368_REG 0x10
+
+ #define SOFTRESET_6328_SPI_MASK (1 << 0)
+@@ -244,6 +281,22 @@
+ SOFTRESET_6348_ACLC_MASK | \
+ SOFTRESET_6348_ADSLMIPSPLL_MASK)
+
++#define SOFTRESET_6362_SPI_MASK (1 << 0)
++#define SOFTRESET_6362_IPSEC_MASK (1 << 1)
++#define SOFTRESET_6362_EPHY_MASK (1 << 2)
++#define SOFTRESET_6362_SAR_MASK (1 << 3)
++#define SOFTRESET_6362_ENETSW_MASK (1 << 4)
++#define SOFTRESET_6362_USBS_MASK (1 << 5)
++#define SOFTRESET_6362_USBH_MASK (1 << 6)
++#define SOFTRESET_6362_PCM_MASK (1 << 7)
++#define SOFTRESET_6362_PCIE_CORE_MASK (1 << 8)
++#define SOFTRESET_6362_PCIE_MASK (1 << 9)
++#define SOFTRESET_6362_PCIE_EXT_MASK (1 << 10)
++#define SOFTRESET_6362_WLAN_SHIM_MASK (1 << 11)
++#define SOFTRESET_6362_DDR_PHY_MASK (1 << 12)
++#define SOFTRESET_6362_FAP_MASK (1 << 13)
++#define SOFTRESET_6362_WLAN_UBUS_MASK (1 << 14)
++
+ #define SOFTRESET_6368_SPI_MASK (1 << 0)
+ #define SOFTRESET_6368_MPI_MASK (1 << 3)
+ #define SOFTRESET_6368_EPHY_MASK (1 << 6)
+@@ -1182,6 +1235,12 @@
+ #define SERDES_PCIE_EN (1 << 0)
+ #define SERDES_PCIE_EXD_EN (1 << 15)
+
++#define MISC_STRAPBUS_6362_REG 0x14
++#define STRAPBUS_6362_FCVO_SHIFT 1
++#define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT)
++#define STRAPBUS_6362_BOOT_SEL_SERIAL (1 << 15)
++#define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15)
++
+ #define MISC_STRAPBUS_6328_REG 0x240
+ #define STRAPBUS_6328_FCVO_SHIFT 7
+ #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
+--- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h
++++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h
+@@ -19,6 +19,7 @@ static inline int is_bcm63xx_internal_re
+ return 1;
+ break;
+ case BCM6328_CPU_ID:
++ case BCM6362_CPU_ID:
+ case BCM6368_CPU_ID:
+ if (offset >= 0xb0000000 && offset < 0xb1000000)
+ return 1;
diff --git a/target/linux/brcm63xx/patches-3.3/313-MIPS-BCM63XX-enable-pcie-for-BCM6362.patch b/target/linux/brcm63xx/patches-3.3/313-MIPS-BCM63XX-enable-pcie-for-BCM6362.patch
new file mode 100644
index 000000000..36024d10b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/313-MIPS-BCM63XX-enable-pcie-for-BCM6362.patch
@@ -0,0 +1,110 @@
+From e49546bf3f255f028d0877ceeb7ed6466fe37d8a Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 21 Nov 2011 00:53:26 +0100
+Subject: [PATCH 56/84] MIPS: BCM63XX: enable pcie for BCM6362
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 3 +-
+ arch/mips/pci/pci-bcm63xx.c | 57 +++++++++++++++------
+ 2 files changed, 44 insertions(+), 16 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -1231,7 +1231,8 @@
+ /*************************************************************************
+ * _REG relative to RSET_MISC
+ *************************************************************************/
+-#define MISC_SERDES_CTRL_REG 0x0
++#define MISC_SERDES_CTRL_6328_REG 0x0
++#define MISC_SERDES_CTRL_6362_REG 0x4
+ #define SERDES_PCIE_EN (1 << 0)
+ #define SERDES_PCIE_EXD_EN (1 << 15)
+
+--- a/arch/mips/pci/pci-bcm63xx.c
++++ b/arch/mips/pci/pci-bcm63xx.c
+@@ -118,35 +118,61 @@ void __iomem *pci_iospace_start;
+ static void __init bcm63xx_reset_pcie(void)
+ {
+ u32 val;
++ u32 reg;
++ u32 mask;
+
+ /* enable clock */
++
++ if (BCMCPU_IS_6328())
++ mask = CKCTL_6328_PCIE_EN;
++ else
++ mask = CKCTL_6362_PCIE_EN;
++
+ val = bcm_perf_readl(PERF_CKCTL_REG);
+- val |= CKCTL_6328_PCIE_EN;
++ val |= mask;
+ bcm_perf_writel(val, PERF_CKCTL_REG);
+
+ /* enable SERDES */
+- val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
++
++ if (BCMCPU_IS_6328())
++ reg = MISC_SERDES_CTRL_6328_REG;
++ else
++ reg = MISC_SERDES_CTRL_6362_REG;
++
++ val = bcm_misc_readl(reg);
+ val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
+- bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
++ bcm_misc_writel(val, reg);
+
+ /* reset the PCIe core */
+- val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
++ if (BCMCPU_IS_6328()) {
++ reg = PERF_SOFTRESET_6328_REG;
++ mask = SOFTRESET_6328_PCIE_MASK | SOFTRESET_6328_PCIE_CORE_MASK
++ | SOFTRESET_6328_PCIE_HARD_MASK;
++ } else {
++ reg = PERF_SOFTRESET_6362_REG;
++ mask = SOFTRESET_6362_PCIE_MASK | SOFTRESET_6362_PCIE_CORE_MASK;
++ }
++ val = bcm_perf_readl(reg);
++ val &= ~mask;
++
++ if (BCMCPU_IS_6328())
++ val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
++ else
++ val &= ~SOFTRESET_6362_PCIE_EXT_MASK;
+
+- val &= ~SOFTRESET_6328_PCIE_MASK;
+- val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
+- val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
+- val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ bcm_perf_writel(val, reg);
+ mdelay(10);
+
+- val |= SOFTRESET_6328_PCIE_MASK;
+- val |= SOFTRESET_6328_PCIE_CORE_MASK;
+- val |= SOFTRESET_6328_PCIE_HARD_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ val |= mask;
++ bcm_perf_writel(val, reg);
+ mdelay(10);
+
+- val |= SOFTRESET_6328_PCIE_EXT_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
++ if (BCMCPU_IS_6328())
++ val |= SOFTRESET_6328_PCIE_EXT_MASK;
++ else
++ val |= SOFTRESET_6362_PCIE_EXT_MASK;
++
++ bcm_perf_writel(val, reg);
+ mdelay(200);
+ }
+
+@@ -332,6 +358,7 @@ static int __init bcm63xx_pci_init(void)
+
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6328_CPU_ID:
++ case BCM6362_CPU_ID:
+ return bcm63xx_register_pcie();
+ case BCM6348_CPU_ID:
+ case BCM6358_CPU_ID:
diff --git a/target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch b/target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch
new file mode 100644
index 000000000..debbb13cd
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/400-ohci-add-driver-for-bcm63xx-integrated-controller.patch
@@ -0,0 +1,234 @@
+From 7b510c5754d3c46e1287803f51e8ecb177414438 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Fri, 10 Jun 2011 19:14:30 +0200
+Subject: [PATCH 23/63] ohci: add driver for bcm63xx integrated controller.
+
+---
+ drivers/usb/host/Kconfig | 9 ++
+ drivers/usb/host/ohci-bcm63xx.c | 175 +++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/ohci-hcd.c | 5 +
+ drivers/usb/host/ohci.h | 2 +-
+ 4 files changed, 190 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/usb/host/ohci-bcm63xx.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -296,6 +296,15 @@ config USB_OHCI_HCD
+ To compile this driver as a module, choose M here: the
+ module will be called ohci-hcd.
+
++config USB_OHCI_BCM63XX
++ bool "Support for Broadcom 63xx on-chip OHCI USB controller"
++ depends on USB_OHCI_HCD && BCM63XX
++ select USB_OHCI_BIG_ENDIAN_DESC
++ select USB_OHCI_BIG_ENDIAN_MMIO
++ ---help---
++ Enables support for the on-chip OHCI controller on
++ BCM63XX chips.
++
+ config USB_OHCI_HCD_OMAP1
+ bool "OHCI support for OMAP1/2 chips"
+ depends on USB_OHCI_HCD && (ARCH_OMAP1 || ARCH_OMAP2)
+--- /dev/null
++++ b/drivers/usb/host/ohci-bcm63xx.c
+@@ -0,0 +1,175 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ */
++
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_regs.h>
++#include <bcm63xx_io.h>
++
++static struct clk *usb_host_clock;
++
++static int __devinit ohci_bcm63xx_start(struct usb_hcd *hcd)
++{
++ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++ int ret;
++
++ ohci->num_ports = 1;
++
++ ret = ohci_init(ohci);
++ if (ret < 0)
++ return ret;
++
++ /* FIXME: autodetected port 2 is shared with USB slave */
++
++ ret = ohci_run(ohci);
++ if (ret < 0) {
++ err("can't start %s", hcd->self.bus_name);
++ ohci_stop(hcd);
++ return ret;
++ }
++ return 0;
++}
++
++static const struct hc_driver ohci_bcm63xx_hc_driver = {
++ .description = hcd_name,
++ .product_desc = "BCM63XX integrated OHCI controller",
++ .hcd_priv_size = sizeof(struct ohci_hcd),
++
++ .irq = ohci_irq,
++ .flags = HCD_USB11 | HCD_MEMORY,
++ .start = ohci_bcm63xx_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,
++ .start_port_reset = ohci_start_port_reset,
++};
++
++static int __devinit ohci_hcd_bcm63xx_drv_probe(struct platform_device *pdev)
++{
++ struct resource *res_mem;
++ struct usb_hcd *hcd;
++ struct ohci_hcd *ohci;
++ struct clk *clk;
++ u32 reg;
++ int ret, irq;
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);
++ if (!res_mem || irq < 0)
++ return -ENODEV;
++
++ /* enable USB host clock */
++ clk = clk_get(&pdev->dev, "usbh");
++ if (IS_ERR(clk))
++ return -ENODEV;
++
++ clk_enable(clk);
++ usb_host_clock = clk;
++ msleep(100);
++
++ if (BCMCPU_IS_6348())
++ bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG);
++ else if (BCMCPU_IS_6358()) {
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
++ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
++ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
++ /*
++ * The magic value comes for the original vendor BSP
++ * and is needed for USB to work. Datasheet does not
++ * help, so the magic value is used as-is.
++ */
++ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
++ USBH_PRIV_TEST_6358_REG);
++
++ } else if (BCMCPU_IS_6368()) {
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
++ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
++ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
++
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
++ reg |= USBH_PRIV_SETUP_IOC_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
++ }
++
++ hcd = usb_create_hcd(&ohci_bcm63xx_hc_driver, &pdev->dev, "bcm63xx");
++ if (!hcd)
++ return -ENOMEM;
++ hcd->rsrc_start = res_mem->start;
++ hcd->rsrc_len = res_mem->end - res_mem->start + 1;
++
++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
++ pr_debug("request_mem_region failed\n");
++ ret = -EBUSY;
++ goto out;
++ }
++
++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
++ if (!hcd->regs) {
++ pr_debug("ioremap failed\n");
++ ret = -EIO;
++ goto out1;
++ }
++
++ ohci = hcd_to_ohci(hcd);
++ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC |
++ OHCI_QUIRK_FRAME_NO;
++ ohci_hcd_init(ohci);
++
++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
++ if (ret)
++ goto out2;
++
++ platform_set_drvdata(pdev, hcd);
++ return 0;
++
++out2:
++ iounmap(hcd->regs);
++out1:
++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++out:
++ usb_put_hcd(hcd);
++ return ret;
++}
++
++static int __devexit ohci_hcd_bcm63xx_drv_remove(struct platform_device *pdev)
++{
++ struct usb_hcd *hcd;
++
++ hcd = platform_get_drvdata(pdev);
++ usb_remove_hcd(hcd);
++ iounmap(hcd->regs);
++ usb_put_hcd(hcd);
++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++ if (usb_host_clock) {
++ clk_disable(usb_host_clock);
++ clk_put(usb_host_clock);
++ }
++ platform_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++static struct platform_driver ohci_hcd_bcm63xx_driver = {
++ .probe = ohci_hcd_bcm63xx_drv_probe,
++ .remove = __devexit_p(ohci_hcd_bcm63xx_drv_remove),
++ .shutdown = usb_hcd_platform_shutdown,
++ .driver = {
++ .name = "bcm63xx_ohci",
++ .owner = THIS_MODULE,
++ },
++};
++
++MODULE_ALIAS("platform:bcm63xx_ohci");
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -1121,6 +1121,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER ohci_xls_driver
+ #endif
+
++#ifdef CONFIG_USB_OHCI_BCM63XX
++#include "ohci-bcm63xx.c"
++#define PLATFORM_DRIVER ohci_hcd_bcm63xx_driver
++#endif
++
+ #if !defined(PCI_DRIVER) && \
+ !defined(PLATFORM_DRIVER) && \
+ !defined(OMAP1_PLATFORM_DRIVER) && \
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -652,7 +652,7 @@ static inline u32 hc32_to_cpup (const st
+ * some big-endian SOC implementations. Same thing happens with PSW access.
+ */
+
+-#ifdef CONFIG_PPC_MPC52xx
++#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_BCM63XX)
+ #define big_endian_frame_no_quirk(ohci) (ohci->flags & OHCI_QUIRK_FRAME_NO)
+ #else
+ #define big_endian_frame_no_quirk(ohci) 0
diff --git a/target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch b/target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch
new file mode 100644
index 000000000..27ecc5a8b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/401-MIPS-BCM63XX-register-ohci-device.patch
@@ -0,0 +1,143 @@
+From ab96f20ca1c3c8e7e5acd82d1e50823a5d572675 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Tue, 24 May 2011 21:47:41 +0200
+Subject: [PATCH 24/63] MIPS: BCM63XX: register ohci device.
+
+---
+ arch/mips/bcm63xx/Kconfig | 9 ++--
+ arch/mips/bcm63xx/Makefile | 2 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++
+ arch/mips/bcm63xx/dev-usb-ohci.c | 50 ++++++++++++++++++++
+ .../asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h | 6 ++
+ 5 files changed, 65 insertions(+), 6 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-usb-ohci.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -8,22 +8,20 @@ config BCM63XX_CPU_6328
+ config BCM63XX_CPU_6338
+ bool "support 6338 CPU"
+ select HW_HAS_PCI
+- select USB_ARCH_HAS_OHCI
+- select USB_OHCI_BIG_ENDIAN_DESC
+- select USB_OHCI_BIG_ENDIAN_MMIO
++ select USB_ARCH_HAS_OHCI if USB_SUPPORT
+
+ config BCM63XX_CPU_6345
+ bool "support 6345 CPU"
+- select USB_OHCI_BIG_ENDIAN_DESC
+- select USB_OHCI_BIG_ENDIAN_MMIO
+
+ config BCM63XX_CPU_6348
+ bool "support 6348 CPU"
+ select HW_HAS_PCI
++ select USB_ARCH_HAS_OHCI if USB_SUPPORT
+
+ config BCM63XX_CPU_6358
+ bool "support 6358 CPU"
+ select HW_HAS_PCI
++ select USB_ARCH_HAS_OHCI if USB_SUPPORT
+
+ config BCM63XX_CPU_6362
+ bool "support 6362 CPU"
+@@ -32,6 +30,7 @@ config BCM63XX_CPU_6362
+ config BCM63XX_CPU_6368
+ bool "support 6368 CPU"
+ select HW_HAS_PCI
++ select USB_ARCH_HAS_OHCI if USB_SUPPORT
+ endmenu
+
+ source "arch/mips/bcm63xx/boards/Kconfig"
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+ dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
+- dev-spi.o dev-uart.o dev-wdt.o
++ dev-spi.o dev-uart.o dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -27,6 +27,7 @@
+ #include <bcm63xx_dev_flash.h>
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
++#include <bcm63xx_dev_usb_ohci.h>
+ #include <board_bcm963xx.h>
+ #include <bcm_tag.h>
+
+@@ -916,6 +917,9 @@ int __init board_register_devices(void)
+ !board_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
++ if (board.has_ohci0)
++ bcm63xx_ohci_register();
++
+ if (board.has_dsp)
+ bcm63xx_dsp_register(&board.dsp);
+
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-usb-ohci.c
+@@ -0,0 +1,50 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_usb_ohci.h>
++
++static struct resource ohci_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ohci_dmamask = ~(u32)0;
++
++static struct platform_device bcm63xx_ohci_device = {
++ .name = "bcm63xx_ohci",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ohci_resources),
++ .resource = ohci_resources,
++ .dev = {
++ .dma_mask = &ohci_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++};
++
++int __init bcm63xx_ohci_register(void)
++{
++ if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368())
++ return 0;
++
++ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
++ ohci_resources[0].end = ohci_resources[0].start;
++ ohci_resources[0].end += RSET_OHCI_SIZE - 1;
++ ohci_resources[1].start = bcm63xx_get_irq_number(IRQ_OHCI0);
++ return platform_device_register(&bcm63xx_ohci_device);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ohci.h
+@@ -0,0 +1,6 @@
++#ifndef BCM63XX_DEV_USB_OHCI_H_
++#define BCM63XX_DEV_USB_OHCI_H_
++
++int bcm63xx_ohci_register(void);
++
++#endif /* BCM63XX_DEV_USB_OHCI_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch b/target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch
new file mode 100644
index 000000000..42c85e991
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/402-ehci-add-driver-for-bcm63xx-integrated-controller.patch
@@ -0,0 +1,241 @@
+From db58271d5152aa1d3894fdef13ca04379139d5d9 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Fri, 10 Jun 2011 19:15:47 +0200
+Subject: [PATCH 25/63] ehci: add driver for bcm63xx integrated controller.
+
+---
+ drivers/usb/host/Kconfig | 10 ++-
+ drivers/usb/host/ehci-bcm63xx.c | 186 +++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/ehci-hcd.c | 5 +
+ 3 files changed, 199 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/usb/host/ehci-bcm63xx.c
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -106,7 +106,7 @@ config USB_EHCI_BIG_ENDIAN_MMIO
+ depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
+ ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
+ PPC_MPC512x || CPU_CAVIUM_OCTEON || \
+- PMC_MSP || SPARC_LEON)
++ PMC_MSP || SPARC_LEON || BCM63XX)
+ default y
+
+ config USB_EHCI_BIG_ENDIAN_DESC
+@@ -129,6 +129,14 @@ config XPS_USB_HCD_XILINX
+ config USB_FSL_MPH_DR_OF
+ tristate
+
++config USB_EHCI_BCM63XX
++ bool "Support for Broadcom 63xx on-chip EHCI USB controller"
++ depends on USB_EHCI_HCD && BCM63XX
++ select USB_EHCI_BIG_ENDIAN_MMIO
++ ---help---
++ Enables support for the on-chip EHCI controller on
++ BCM6358 and later chips.
++
+ config USB_EHCI_FSL
+ bool "Support for Freescale PPC on-chip EHCI USB controller"
+ depends on USB_EHCI_HCD && FSL_SOC
+--- /dev/null
++++ b/drivers/usb/host/ehci-bcm63xx.c
+@@ -0,0 +1,186 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ */
++
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_regs.h>
++#include <bcm63xx_io.h>
++
++static struct clk *usb_host_clock;
++
++static int ehci_bcm63xx_setup(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ int retval;
++
++ retval = ehci_halt(ehci);
++ if (retval)
++ return retval;
++
++ retval = ehci_init(hcd);
++ if (retval)
++ return retval;
++
++ ehci_reset(ehci);
++ ehci_port_power(ehci, 0);
++
++ return retval;
++}
++
++
++static const struct hc_driver ehci_bcm63xx_hc_driver = {
++ .description = hcd_name,
++ .product_desc = "BCM63XX integrated EHCI controller",
++ .hcd_priv_size = sizeof(struct ehci_hcd),
++
++ .irq = ehci_irq,
++ .flags = HCD_MEMORY | HCD_USB2,
++
++ .reset = ehci_bcm63xx_setup,
++ .start = ehci_run,
++ .stop = ehci_stop,
++ .shutdown = ehci_shutdown,
++
++ .urb_enqueue = ehci_urb_enqueue,
++ .urb_dequeue = ehci_urb_dequeue,
++ .endpoint_disable = ehci_endpoint_disable,
++
++ .get_frame_number = ehci_get_frame,
++
++ .hub_status_data = ehci_hub_status_data,
++ .hub_control = ehci_hub_control,
++ .bus_suspend = ehci_bus_suspend,
++ .bus_resume = ehci_bus_resume,
++ .relinquish_port = ehci_relinquish_port,
++ .port_handed_over = ehci_port_handed_over,
++};
++
++static int __devinit ehci_hcd_bcm63xx_drv_probe(struct platform_device *pdev)
++{
++ struct resource *res_mem;
++ struct usb_hcd *hcd;
++ struct ehci_hcd *ehci;
++ struct clk *clk;
++ u32 reg;
++ int ret, irq;
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq = platform_get_irq(pdev, 0);;
++ if (!res_mem || irq < 0)
++ return -ENODEV;
++
++ /* enable USB host clock */
++ clk = clk_get(&pdev->dev, "usbh");
++ if (IS_ERR(clk))
++ return -ENODEV;
++
++ clk_enable(clk);
++ usb_host_clock = clk;
++ msleep(100);
++
++ if (BCMCPU_IS_6358()) {
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
++ reg &= ~USBH_PRIV_SWAP_EHCI_DATA_MASK;
++ reg |= USBH_PRIV_SWAP_EHCI_ENDN_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
++
++ /*
++ * The magic value comes for the original vendor BSP
++ * and is needed for USB to work. Datasheet does not
++ * help, so the magic value is used as-is.
++ */
++ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
++ USBH_PRIV_TEST_6358_REG);
++
++ } else if (BCMCPU_IS_6368()) {
++
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
++ reg &= ~USBH_PRIV_SWAP_EHCI_DATA_MASK;
++ reg |= USBH_PRIV_SWAP_EHCI_ENDN_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
++
++ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
++ reg |= USBH_PRIV_SETUP_IOC_MASK;
++ bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
++ }
++
++ hcd = usb_create_hcd(&ehci_bcm63xx_hc_driver, &pdev->dev, "bcm63xx");
++ if (!hcd)
++ return -ENOMEM;
++ hcd->rsrc_start = res_mem->start;
++ hcd->rsrc_len = res_mem->end - res_mem->start + 1;
++
++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
++ pr_debug("request_mem_region failed\n");
++ ret = -EBUSY;
++ goto out;
++ }
++
++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
++ if (!hcd->regs) {
++ pr_debug("ioremap failed\n");
++ ret = -EIO;
++ goto out1;
++ }
++
++ ehci = hcd_to_ehci(hcd);
++ ehci->big_endian_mmio = 1;
++ ehci->big_endian_desc = 0;
++ ehci->caps = hcd->regs;
++ ehci->regs = hcd->regs +
++ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
++ ehci->sbrn = 0x20;
++ ehci->ignore_oc = 1;
++
++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
++ if (ret)
++ goto out2;
++
++ platform_set_drvdata(pdev, hcd);
++ return 0;
++
++out2:
++ iounmap(hcd->regs);
++out1:
++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++out:
++ usb_put_hcd(hcd);
++ return ret;
++}
++
++static int __devexit ehci_hcd_bcm63xx_drv_remove(struct platform_device *pdev)
++{
++ struct usb_hcd *hcd;
++
++ hcd = platform_get_drvdata(pdev);
++ usb_remove_hcd(hcd);
++ iounmap(hcd->regs);
++ usb_put_hcd(hcd);
++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++ if (usb_host_clock) {
++ clk_disable(usb_host_clock);
++ clk_put(usb_host_clock);
++ }
++ platform_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++static struct platform_driver ehci_hcd_bcm63xx_driver = {
++ .probe = ehci_hcd_bcm63xx_drv_probe,
++ .remove = __devexit_p(ehci_hcd_bcm63xx_drv_remove),
++ .shutdown = usb_hcd_platform_shutdown,
++ .driver = {
++ .name = "bcm63xx_ehci",
++ .owner = THIS_MODULE,
++ },
++};
++
++MODULE_ALIAS("platform:bcm63xx_ehci");
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -1381,6 +1381,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER ehci_mv_driver
+ #endif
+
++#ifdef CONFIG_USB_EHCI_BCM63XX
++#include "ehci-bcm63xx.c"
++#define PLATFORM_DRIVER ehci_hcd_bcm63xx_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/target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch b/target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch
new file mode 100644
index 000000000..cd5eb73ce
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/403-MIPS-BCM63XX-register-ehci-device.patch
@@ -0,0 +1,125 @@
+From a2d78246e4cb45b5978fc682aad19c0fff0cd20d Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Tue, 24 May 2011 21:50:33 +0200
+Subject: [PATCH 26/63] MIPS: BCM63XX: register ehci device.
+
+---
+ arch/mips/bcm63xx/Kconfig | 2 +
+ arch/mips/bcm63xx/Makefile | 2 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 4 ++
+ arch/mips/bcm63xx/dev-usb-ehci.c | 50 ++++++++++++++++++++
+ .../asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h | 6 ++
+ 5 files changed, 63 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-usb-ehci.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -22,6 +22,7 @@ config BCM63XX_CPU_6358
+ bool "support 6358 CPU"
+ select HW_HAS_PCI
+ select USB_ARCH_HAS_OHCI if USB_SUPPORT
++ select USB_ARCH_HAS_EHCI if USB_SUPPORT
+
+ config BCM63XX_CPU_6362
+ bool "support 6362 CPU"
+@@ -31,6 +32,7 @@ config BCM63XX_CPU_6368
+ bool "support 6368 CPU"
+ select HW_HAS_PCI
+ select USB_ARCH_HAS_OHCI if USB_SUPPORT
++ select USB_ARCH_HAS_EHCI if USB_SUPPORT
+ endmenu
+
+ source "arch/mips/bcm63xx/boards/Kconfig"
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+ dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
+- dev-spi.o dev-uart.o dev-usb-ohci.o dev-wdt.o
++ dev-spi.o dev-uart.o dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -28,6 +28,7 @@
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
+ #include <bcm63xx_dev_usb_ohci.h>
++#include <bcm63xx_dev_usb_ehci.h>
+ #include <board_bcm963xx.h>
+ #include <bcm_tag.h>
+
+@@ -917,6 +918,9 @@ int __init board_register_devices(void)
+ !board_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
++ if (board.has_ehci0)
++ bcm63xx_ehci_register();
++
+ if (board.has_ohci0)
+ bcm63xx_ohci_register();
+
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-usb-ehci.c
+@@ -0,0 +1,50 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_usb_ehci.h>
++
++static struct resource ehci_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static u64 ehci_dmamask = ~(u32)0;
++
++static struct platform_device bcm63xx_ehci_device = {
++ .name = "bcm63xx_ehci",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ehci_resources),
++ .resource = ehci_resources,
++ .dev = {
++ .dma_mask = &ehci_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++};
++
++int __init bcm63xx_ehci_register(void)
++{
++ if (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())
++ return 0;
++
++ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
++ ehci_resources[0].end = ehci_resources[0].start;
++ ehci_resources[0].end += RSET_EHCI_SIZE - 1;
++ ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
++ return platform_device_register(&bcm63xx_ehci_device);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
+@@ -0,0 +1,6 @@
++#ifndef BCM63XX_DEV_USB_EHCI_H_
++#define BCM63XX_DEV_USB_EHCI_H_
++
++int bcm63xx_ehci_register(void);
++
++#endif /* BCM63XX_DEV_USB_EHCI_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch b/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch
new file mode 100644
index 000000000..8338962e5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/404-bcm963xx_flashmap.patch
@@ -0,0 +1,65 @@
+From a4d005c91d403d9f3d0272db6cc46202c06ec774 Mon Sep 17 00:00:00 2001
+From: Axel Gembe <ago@bastart.eu.org>
+Date: Mon, 12 May 2008 18:54:09 +0200
+Subject: [PATCH] bcm963xx: flashmap support
+
+Signed-off-by: Axel Gembe <ago@bastart.eu.org>
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 19 +----------------
+ drivers/mtd/maps/bcm963xx-flash.c | 32 ++++++++++++++++++++++++----
+ drivers/mtd/redboot.c | 13 +++++++++--
+ 3 files changed, 38 insertions(+), 26 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -30,7 +30,7 @@ static struct mtd_partition mtd_partitio
+ }
+ };
+
+-static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
++static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
+
+ static struct physmap_flash_data flash_data = {
+ .width = 2,
+--- a/drivers/mtd/redboot.c
++++ b/drivers/mtd/redboot.c
+@@ -75,6 +75,7 @@ static int parse_redboot_partitions(stru
+ int nulllen = 0;
+ int numslots;
+ unsigned long offset;
++ unsigned long fis_origin = 0;
+ #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+ static char nullstring[] = "unallocated";
+ #endif
+@@ -181,6 +182,16 @@ static int parse_redboot_partitions(stru
+ goto out;
+ }
+
++ if (data && data->origin) {
++ fis_origin = data->origin;
++ } else {
++ for (i = 0; i < numslots; i++) {
++ if (!strncmp(buf[i].name, "RedBoot", 8)) {
++ fis_origin = (buf[i].flash_base & (master->size << 1) - 1);
++ }
++ }
++ }
++
+ for (i = 0; i < numslots; i++) {
+ struct fis_list *new_fl, **prev;
+
+@@ -201,10 +212,10 @@ static int parse_redboot_partitions(stru
+ goto out;
+ }
+ new_fl->img = &buf[i];
+- if (data && data->origin)
+- buf[i].flash_base -= data->origin;
+- else
+- buf[i].flash_base &= master->size-1;
++ if (fis_origin)
++ buf[i].flash_base -= fis_origin;
++
++ buf[i].flash_base &= (master->size << 1) - 1;
+
+ /* I'm sure the JFFS2 code has done me permanent damage.
+ * I now think the following is _normal_
diff --git a/target/linux/brcm63xx/patches-3.3/405-bcm963xx_real_rootfs_length.patch b/target/linux/brcm63xx/patches-3.3/405-bcm963xx_real_rootfs_length.patch
new file mode 100644
index 000000000..856b9e267
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/405-bcm963xx_real_rootfs_length.patch
@@ -0,0 +1,27 @@
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
+@@ -85,8 +85,10 @@ struct bcm_tag {
+ __u32 rootfs_crc;
+ /* 224-227: CRC32 of kernel partition */
+ __u32 kernel_crc;
+- /* 228-235: Unused at present */
+- char reserved1[8];
++ /* 228-231: Image sequence number */
++ char image_sequence[4];
++ /* 222-235: Openwrt: real rootfs length */
++ __u32 real_rootfs_length;
+ /* 236-239: CRC32 of header excluding last 20 bytes */
+ __u32 header_crc;
+ /* 240-255: Unused at present */
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -131,7 +131,8 @@ static int bcm63xx_parse_cfe_partitions(
+ } else {
+ /* OpenWrt layout */
+ rootfsaddr = kerneladdr + kernellen;
+- rootfslen = spareaddr - rootfsaddr;
++ rootfslen = buf->real_rootfs_length;
++ spareaddr = rootfsaddr + rootfslen;
+ }
+ } else {
+ pr_warn("CFE boot tag CRC invalid (expected %08x, actual %08x)\n",
diff --git a/target/linux/brcm63xx/patches-3.3/406_bcm63xx_enet_vlan_incoming_fixed.patch b/target/linux/brcm63xx/patches-3.3/406_bcm63xx_enet_vlan_incoming_fixed.patch
new file mode 100644
index 000000000..7d9f4a96d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/406_bcm63xx_enet_vlan_incoming_fixed.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -1515,7 +1515,7 @@ static int compute_hw_mtu(struct bcm_ene
+ actual_mtu = mtu;
+
+ /* add ethernet header + vlan tag size */
+- actual_mtu += VLAN_ETH_HLEN;
++ actual_mtu += VLAN_ETH_HLEN + VLAN_HLEN;
+
+ if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
+ return -EINVAL;
diff --git a/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch b/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch
new file mode 100644
index 000000000..3820e6323
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/408-6358-enet1-external-mii-clk.patch
@@ -0,0 +1,22 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -855,6 +855,8 @@ void __init board_prom_init(void)
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G3_EXT_MII |
+ GPIO_MODE_6348_G0_EXT_MII;
++ else if (BCMCPU_IS_6358())
++ val |= GPIO_MODE_6358_ENET1_MII_CLK_INV;
+ }
+
+ bcm_gpio_writel(val, GPIO_MODE_REG);
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -563,6 +563,8 @@
+ #define GPIO_MODE_6358_EXTRA_SPI_SS (1 << 7)
+ #define GPIO_MODE_6358_SERIAL_LED (1 << 10)
+ #define GPIO_MODE_6358_UTOPIA (1 << 12)
++#define GPIO_MODE_6358_ENET1_MII_CLK_INV (1 << 30)
++#define GPIO_MODE_6358_ENET0_MII_CLK_INV (1 << 31)
+
+ #define GPIO_MODE_6368_ANALOG_AFE_0 (1 << 0)
+ #define GPIO_MODE_6368_ANALOG_AFE_1 (1 << 1)
diff --git a/target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch b/target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch
new file mode 100644
index 000000000..2102db35e
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/410-NET-bcm63xx_enet-move-phy_-dis-connect-into-probe-re.patch
@@ -0,0 +1,169 @@
+From b11218c750ab92cfab4408a0328f1b36ceec3f33 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Fri, 6 Jan 2012 12:24:18 +0100
+Subject: [PATCH 19/63] NET: bcm63xx_enet: move phy_(dis)connect into probe/remove
+
+Only connect/disconnect the phy during probe and remove, not during any
+open/close. The phy seldom changes during the runtime, and disconnecting
+the phy during close will prevent it from keeping any configuration over
+a down/up cycle.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 84 +++++++++++++-------------
+ 1 files changed, 41 insertions(+), 43 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -784,10 +784,8 @@ static int bcm_enet_open(struct net_devi
+ struct bcm_enet_priv *priv;
+ struct sockaddr addr;
+ struct device *kdev;
+- struct phy_device *phydev;
+ int i, ret;
+ unsigned int size;
+- char phy_id[MII_BUS_ID_SIZE + 3];
+ void *p;
+ u32 val;
+
+@@ -795,40 +793,10 @@ static int bcm_enet_open(struct net_devi
+ kdev = &priv->pdev->dev;
+
+ if (priv->has_phy) {
+- /* connect to PHY */
+- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+- priv->mii_bus->id, priv->phy_id);
+-
+- phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
+- PHY_INTERFACE_MODE_MII);
+-
+- if (IS_ERR(phydev)) {
+- dev_err(kdev, "could not attach to PHY\n");
+- return PTR_ERR(phydev);
+- }
+-
+- /* mask with MAC supported features */
+- phydev->supported &= (SUPPORTED_10baseT_Half |
+- SUPPORTED_10baseT_Full |
+- SUPPORTED_100baseT_Half |
+- SUPPORTED_100baseT_Full |
+- SUPPORTED_Autoneg |
+- SUPPORTED_Pause |
+- SUPPORTED_MII);
+- phydev->advertising = phydev->supported;
+-
+- if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
+- phydev->advertising |= SUPPORTED_Pause;
+- else
+- phydev->advertising &= ~SUPPORTED_Pause;
+-
+- dev_info(kdev, "attached PHY at address %d [%s]\n",
+- phydev->addr, phydev->drv->name);
+-
++ /* Reset state */
+ priv->old_link = 0;
+ priv->old_duplex = -1;
+ priv->old_pause = -1;
+- priv->phydev = phydev;
+ }
+
+ /* mask all interrupts and request them */
+@@ -838,7 +806,7 @@ static int bcm_enet_open(struct net_devi
+
+ ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
+ if (ret)
+- goto out_phy_disconnect;
++ return ret;
+
+ ret = request_irq(priv->irq_rx, bcm_enet_isr_dma, IRQF_DISABLED,
+ dev->name, dev);
+@@ -1025,9 +993,6 @@ out_freeirq_rx:
+ out_freeirq:
+ free_irq(dev->irq, dev);
+
+-out_phy_disconnect:
+- phy_disconnect(priv->phydev);
+-
+ return ret;
+ }
+
+@@ -1132,12 +1097,6 @@ static int bcm_enet_stop(struct net_devi
+ free_irq(priv->irq_rx, dev);
+ free_irq(dev->irq, dev);
+
+- /* release phy */
+- if (priv->has_phy) {
+- phy_disconnect(priv->phydev);
+- priv->phydev = NULL;
+- }
+-
+ return 0;
+ }
+
+@@ -1714,6 +1673,8 @@ static int __devinit bcm_enet_probe(stru
+
+ /* MII bus registration */
+ if (priv->has_phy) {
++ struct phy_device *phydev;
++ char phy_id[MII_BUS_ID_SIZE + 3];
+
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+@@ -1750,6 +1711,38 @@ static int __devinit bcm_enet_probe(stru
+ dev_err(&pdev->dev, "unable to register mdio bus\n");
+ goto out_free_mdio;
+ }
++
++ /* connect to PHY */
++ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
++ priv->mii_bus->id, priv->phy_id);
++
++ phydev = phy_connect(dev, phy_id, bcm_enet_adjust_phy_link, 0,
++ PHY_INTERFACE_MODE_MII);
++
++ if (IS_ERR(phydev)) {
++ dev_err(&pdev->dev, "could not attach to PHY\n");
++ goto out_unregister_mdio;
++ }
++
++ /* mask with MAC supported features */
++ phydev->supported &= (SUPPORTED_10baseT_Half |
++ SUPPORTED_10baseT_Full |
++ SUPPORTED_100baseT_Half |
++ SUPPORTED_100baseT_Full |
++ SUPPORTED_Autoneg |
++ SUPPORTED_Pause |
++ SUPPORTED_MII);
++ phydev->advertising = phydev->supported;
++
++ if (priv->pause_auto && priv->pause_rx && priv->pause_tx)
++ phydev->advertising |= SUPPORTED_Pause;
++ else
++ phydev->advertising &= ~SUPPORTED_Pause;
++
++ dev_info(&pdev->dev, "attached PHY at address %d [%s]\n",
++ phydev->addr, phydev->drv->name);
++
++ priv->phydev = phydev;
+ } else {
+
+ /* run platform code to initialize PHY device */
+@@ -1795,6 +1788,9 @@ static int __devinit bcm_enet_probe(stru
+ return 0;
+
+ out_unregister_mdio:
++ if (priv->phydev)
++ phy_disconnect(priv->phydev);
++
+ if (priv->mii_bus) {
+ mdiobus_unregister(priv->mii_bus);
+ kfree(priv->mii_bus->irq);
+@@ -1845,6 +1841,8 @@ static int __devexit bcm_enet_remove(str
+ enet_writel(priv, 0, ENET_MIISC_REG);
+
+ if (priv->has_phy) {
++ phy_disconnect(priv->phydev);
++ priv->phydev = NULL;
+ mdiobus_unregister(priv->mii_bus);
+ kfree(priv->mii_bus->irq);
+ mdiobus_free(priv->mii_bus);
diff --git a/target/linux/brcm63xx/patches-3.3/411-bcm63xx_enet-implement-reset_autoneg-ethtool.patch b/target/linux/brcm63xx/patches-3.3/411-bcm63xx_enet-implement-reset_autoneg-ethtool.patch
new file mode 100644
index 000000000..d143b473d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/411-bcm63xx_enet-implement-reset_autoneg-ethtool.patch
@@ -0,0 +1,40 @@
+From accc558f334662c8b16c121b4819931c028e8eb0 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Mon, 8 Jun 2009 16:12:10 +0200
+Subject: [PATCH 27/63] bcm63xx_enet: implement reset_autoneg ethtool.
+
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 15 +++++++++++++++
+ 1 files changed, 15 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -1290,6 +1290,20 @@ static void bcm_enet_get_ethtool_stats(s
+ mutex_unlock(&priv->mib_update_lock);
+ }
+
++static int bcm_enet_nway_reset(struct net_device *dev)
++{
++ struct bcm_enet_priv *priv;
++
++ priv = netdev_priv(dev);
++ if (priv->has_phy) {
++ if (!priv->phydev)
++ return -ENODEV;
++ return genphy_restart_aneg(priv->phydev);
++ }
++
++ return -EOPNOTSUPP;
++}
++
+ static int bcm_enet_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+ {
+@@ -1432,6 +1446,7 @@ static const struct ethtool_ops bcm_enet
+ .get_strings = bcm_enet_get_strings,
+ .get_sset_count = bcm_enet_get_sset_count,
+ .get_ethtool_stats = bcm_enet_get_ethtool_stats,
++ .nway_reset = bcm_enet_nway_reset,
+ .get_settings = bcm_enet_get_settings,
+ .set_settings = bcm_enet_set_settings,
+ .get_drvinfo = bcm_enet_get_drvinfo,
diff --git a/target/linux/brcm63xx/patches-3.3/412-bcm63xx_enet-use-resource_size.patch b/target/linux/brcm63xx/patches-3.3/412-bcm63xx_enet-use-resource_size.patch
new file mode 100644
index 000000000..11d035dd5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/412-bcm63xx_enet-use-resource_size.patch
@@ -0,0 +1,69 @@
+From dbd9b51204aa4114756b8659e180139ef3878032 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Thu, 21 Jan 2010 17:28:36 +0100
+Subject: [PATCH 28/63] bcm63xx_enet: use resource_size().
+
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 18 ++++++++----------
+ 1 files changed, 8 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -1594,7 +1594,6 @@ static int __devinit bcm_enet_probe(stru
+ struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx;
+ struct mii_bus *bus;
+ const char *clk_name;
+- unsigned int iomem_size;
+ int i, ret;
+
+ /* stop if shared driver failed, assume driver->probe will be
+@@ -1619,13 +1618,13 @@ static int __devinit bcm_enet_probe(stru
+ if (ret)
+ goto out;
+
+- iomem_size = resource_size(res_mem);
+- if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
++ if (!request_mem_region(res_mem->start, resource_size(res_mem),
++ "bcm63xx_enet")) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+- priv->base = ioremap(res_mem->start, iomem_size);
++ priv->base = ioremap(res_mem->start, resource_size(res_mem));
+ if (priv->base == NULL) {
+ ret = -ENOMEM;
+ goto out_release_mem;
+@@ -1831,7 +1830,7 @@ out_unmap:
+ iounmap(priv->base);
+
+ out_release_mem:
+- release_mem_region(res_mem->start, iomem_size);
++ release_mem_region(res_mem->start, resource_size(res_mem));
+ out:
+ free_netdev(dev);
+ return ret;
+@@ -1903,19 +1902,18 @@ struct platform_driver bcm63xx_enet_driv
+ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
+ {
+ struct resource *res;
+- unsigned int iomem_size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+- iomem_size = resource_size(res);
+- if (!request_mem_region(res->start, iomem_size, "bcm63xx_enet_dma"))
++ if (!request_mem_region(res->start, resource_size(res),
++ "bcm63xx_enet_dma"))
+ return -EBUSY;
+
+- bcm_enet_shared_base = ioremap(res->start, iomem_size);
++ bcm_enet_shared_base = ioremap(res->start, resource_size(res));
+ if (!bcm_enet_shared_base) {
+- release_mem_region(res->start, iomem_size);
++ release_mem_region(res->start, resource_size(res));
+ return -ENOMEM;
+ }
+ return 0;
diff --git a/target/linux/brcm63xx/patches-3.3/413-bcm63xx_enet-disable-clock-when-uninitializing-devic.patch b/target/linux/brcm63xx/patches-3.3/413-bcm63xx_enet-disable-clock-when-uninitializing-devic.patch
new file mode 100644
index 000000000..a98bea900
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/413-bcm63xx_enet-disable-clock-when-uninitializing-devic.patch
@@ -0,0 +1,20 @@
+From fd15ecd10c95480be5635f8993b781fe3a1527c2 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Fri, 29 Apr 2011 16:54:50 +0200
+Subject: [PATCH 29/63] bcm63xx_enet: disable clock when uninitializing device.
+
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -1870,6 +1870,8 @@ static int __devexit bcm_enet_remove(str
+ }
+
+ /* release device resources */
++ clk_disable(priv->mac_clk);
++ clk_put(priv->mac_clk);
+ iounmap(priv->base);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
diff --git a/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch b/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch
new file mode 100644
index 000000000..90999fa95
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/414-bcm63xx_enet-split-dma-registers-access.patch
@@ -0,0 +1,381 @@
+From 305579c1f946ed1aa6c125252ace21c53d47c11d Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Thu, 21 Jan 2010 17:50:54 +0100
+Subject: [PATCH 30/63] bcm63xx_enet: split dma registers access.
+
+---
+ arch/mips/bcm63xx/dev-enet.c | 23 +++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h | 4 +-
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 179 ++++++++++++++--------
+ 3 files changed, 138 insertions(+), 68 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -19,6 +19,16 @@ static struct resource shared_res[] = {
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
+ };
+
+ static struct platform_device bcm63xx_enet_shared_device = {
+@@ -110,10 +120,15 @@ int __init bcm63xx_enet_register(int uni
+ if (!shared_device_registered) {
+ shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
+ shared_res[0].end = shared_res[0].start;
+- if (BCMCPU_IS_6338())
+- shared_res[0].end += (RSET_ENETDMA_SIZE / 2) - 1;
+- else
+- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
++ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
++
++ shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
++ shared_res[1].end = shared_res[1].start;
++ shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
++
++ shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
++ shared_res[2].end = shared_res[2].start;
++ shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
+
+ ret = platform_device_register(&bcm63xx_enet_shared_device);
+ if (ret)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h
+@@ -172,7 +172,9 @@ enum bcm63xx_regs_set {
+ #define BCM_6358_RSET_SPI_SIZE 1804
+ #define BCM_6368_RSET_SPI_SIZE 1804
+ #define RSET_ENET_SIZE 2048
+-#define RSET_ENETDMA_SIZE 2048
++#define RSET_ENETDMA_SIZE 256
++#define RSET_ENETDMAC_SIZE(chans) (16 * (chans))
++#define RSET_ENETDMAS_SIZE(chans) (16 * (chans))
+ #define RSET_ENETSW_SIZE 65536
+ #define RSET_UART_SIZE 24
+ #define RSET_HSSPI_SIZE 1536
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -41,8 +41,8 @@ static int copybreak __read_mostly = 128
+ module_param(copybreak, int, 0);
+ MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+
+-/* io memory shared between all devices */
+-static void __iomem *bcm_enet_shared_base;
++/* io registers memory shared between all devices */
++static void __iomem *bcm_enet_shared_base[3];
+
+ /*
+ * io helpers to access mac registers
+@@ -63,13 +63,35 @@ static inline void enet_writel(struct bc
+ */
+ static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off)
+ {
+- return bcm_readl(bcm_enet_shared_base + off);
++ return bcm_readl(bcm_enet_shared_base[0] + off);
+ }
+
+ static inline void enet_dma_writel(struct bcm_enet_priv *priv,
+ u32 val, u32 off)
+ {
+- bcm_writel(val, bcm_enet_shared_base + off);
++ bcm_writel(val, bcm_enet_shared_base[0] + off);
++}
++
++static inline u32 enet_dmac_readl(struct bcm_enet_priv *priv, u32 off)
++{
++ return bcm_readl(bcm_enet_shared_base[1] + off);
++}
++
++static inline void enet_dmac_writel(struct bcm_enet_priv *priv,
++ u32 val, u32 off)
++{
++ bcm_writel(val, bcm_enet_shared_base[1] + off);
++}
++
++static inline u32 enet_dmas_readl(struct bcm_enet_priv *priv, u32 off)
++{
++ return bcm_readl(bcm_enet_shared_base[2] + off);
++}
++
++static inline void enet_dmas_writel(struct bcm_enet_priv *priv,
++ u32 val, u32 off)
++{
++ bcm_writel(val, bcm_enet_shared_base[2] + off);
+ }
+
+ /*
+@@ -353,8 +375,8 @@ static int bcm_enet_receive_queue(struct
+ bcm_enet_refill_rx(dev);
+
+ /* kick rx dma */
+- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
+- ENETDMA_CHANCFG_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
++ ENETDMAC_CHANCFG_REG(priv->rx_chan));
+ }
+
+ return processed;
+@@ -429,10 +451,10 @@ static int bcm_enet_poll(struct napi_str
+ dev = priv->net_dev;
+
+ /* ack interrupts */
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IR_REG(priv->rx_chan));
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IR_REG(priv->tx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->tx_chan));
+
+ /* reclaim sent skb */
+ tx_work_done = bcm_enet_tx_reclaim(dev, 0);
+@@ -451,10 +473,10 @@ static int bcm_enet_poll(struct napi_str
+ napi_complete(napi);
+
+ /* restore rx/tx interrupt */
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IRMASK_REG(priv->rx_chan));
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IRMASK_REG(priv->tx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->tx_chan));
+
+ return rx_work_done;
+ }
+@@ -497,8 +519,8 @@ static irqreturn_t bcm_enet_isr_dma(int
+ priv = netdev_priv(dev);
+
+ /* mask rx/tx interrupts */
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+
+ napi_schedule(&priv->napi);
+
+@@ -557,8 +579,8 @@ static int bcm_enet_start_xmit(struct sk
+ wmb();
+
+ /* kick tx dma */
+- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
+- ENETDMA_CHANCFG_REG(priv->tx_chan));
++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
++ ENETDMAC_CHANCFG_REG(priv->tx_chan));
+
+ /* stop queue if no more desc available */
+ if (!priv->tx_desc_count)
+@@ -801,8 +823,8 @@ static int bcm_enet_open(struct net_devi
+
+ /* mask all interrupts and request them */
+ enet_writel(priv, 0, ENET_IRMASK_REG);
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+
+ ret = request_irq(dev->irq, bcm_enet_isr_mac, 0, dev->name, dev);
+ if (ret)
+@@ -891,28 +913,28 @@ static int bcm_enet_open(struct net_devi
+ }
+
+ /* write rx & tx ring addresses */
+- enet_dma_writel(priv, priv->rx_desc_dma,
+- ENETDMA_RSTART_REG(priv->rx_chan));
+- enet_dma_writel(priv, priv->tx_desc_dma,
+- ENETDMA_RSTART_REG(priv->tx_chan));
++ enet_dmas_writel(priv, priv->rx_desc_dma,
++ ENETDMAS_RSTART_REG(priv->rx_chan));
++ enet_dmas_writel(priv, priv->tx_desc_dma,
++ ENETDMAS_RSTART_REG(priv->tx_chan));
+
+ /* clear remaining state ram for rx & tx channel */
+- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_SRAM2_REG(priv->tx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_SRAM3_REG(priv->tx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
+
+ /* set max rx/tx length */
+ enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG);
+ enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
+
+ /* set dma maximum burst len */
+- enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
+- ENETDMA_MAXBURST_REG(priv->rx_chan));
+- enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
+- ENETDMA_MAXBURST_REG(priv->tx_chan));
++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ ENETDMAC_MAXBURST_REG(priv->rx_chan));
++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ ENETDMAC_MAXBURST_REG(priv->tx_chan));
+
+ /* set correct transmit fifo watermark */
+ enet_writel(priv, BCMENET_TX_FIFO_TRESH, ENET_TXWMARK_REG);
+@@ -930,26 +952,26 @@ static int bcm_enet_open(struct net_devi
+ val |= ENET_CTL_ENABLE_MASK;
+ enet_writel(priv, val, ENET_CTL_REG);
+ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
+- enet_dma_writel(priv, ENETDMA_CHANCFG_EN_MASK,
+- ENETDMA_CHANCFG_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
++ ENETDMAC_CHANCFG_REG(priv->rx_chan));
+
+ /* watch "mib counters about to overflow" interrupt */
+ enet_writel(priv, ENET_IR_MIB, ENET_IR_REG);
+ enet_writel(priv, ENET_IR_MIB, ENET_IRMASK_REG);
+
+ /* watch "packet transferred" interrupt in rx and tx */
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IR_REG(priv->rx_chan));
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IR_REG(priv->tx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->tx_chan));
+
+ /* make sure we enable napi before rx interrupt */
+ napi_enable(&priv->napi);
+
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IRMASK_REG(priv->rx_chan));
+- enet_dma_writel(priv, ENETDMA_IR_PKTDONE_MASK,
+- ENETDMA_IRMASK_REG(priv->tx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->tx_chan));
+
+ if (priv->has_phy)
+ phy_start(priv->phydev);
+@@ -1026,14 +1048,14 @@ static void bcm_enet_disable_dma(struct
+ {
+ int limit;
+
+- enet_dma_writel(priv, 0, ENETDMA_CHANCFG_REG(chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_CHANCFG_REG(chan));
+
+ limit = 1000;
+ do {
+ u32 val;
+
+- val = enet_dma_readl(priv, ENETDMA_CHANCFG_REG(chan));
+- if (!(val & ENETDMA_CHANCFG_EN_MASK))
++ val = enet_dmac_readl(priv, ENETDMAC_CHANCFG_REG(chan));
++ if (!(val & ENETDMAC_CHANCFG_EN_MASK))
+ break;
+ udelay(1);
+ } while (limit--);
+@@ -1059,8 +1081,8 @@ static int bcm_enet_stop(struct net_devi
+
+ /* mask all interrupts */
+ enet_writel(priv, 0, ENET_IRMASK_REG);
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->rx_chan));
+- enet_dma_writel(priv, 0, ENETDMA_IRMASK_REG(priv->tx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
+
+ /* make sure no mib update is scheduled */
+ cancel_work_sync(&priv->mib_update_task);
+@@ -1598,7 +1620,7 @@ static int __devinit bcm_enet_probe(stru
+
+ /* stop if shared driver failed, assume driver->probe will be
+ * called in the same order we register devices (correct ?) */
+- if (!bcm_enet_shared_base)
++ if (!bcm_enet_shared_base[0])
+ return -ENODEV;
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -1904,30 +1926,61 @@ struct platform_driver bcm63xx_enet_driv
+ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
+ {
+ struct resource *res;
++ int ret, i, requested[3];
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res)
+- return -ENODEV;
++ memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base));
++ memset(requested, 0, sizeof (requested));
+
+- if (!request_mem_region(res->start, resource_size(res),
+- "bcm63xx_enet_dma"))
+- return -EBUSY;
++ for (i = 0; i < 3; i++) {
++ void __iomem *p;
+
+- bcm_enet_shared_base = ioremap(res->start, resource_size(res));
+- if (!bcm_enet_shared_base) {
+- release_mem_region(res->start, resource_size(res));
+- return -ENOMEM;
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ if (!res) {
++ ret = -EINVAL;
++ goto fail;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res),
++ "bcm63xx_enet_dma")) {
++ ret = -EBUSY;
++ goto fail;
++ }
++ requested[i] = 0;
++
++ p = ioremap(res->start, resource_size(res));
++ if (!p) {
++ ret = -ENOMEM;
++ goto fail;
++ }
++
++ bcm_enet_shared_base[i] = p;
+ }
++
+ return 0;
++
++fail:
++ for (i = 0; i < 3; i++) {
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ if (!res)
++ continue;
++ if (bcm_enet_shared_base[i])
++ iounmap(bcm_enet_shared_base[i]);
++ if (requested[i])
++ release_mem_region(res->start, resource_size(res));
++ }
++ return ret;
+ }
+
+ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
+ {
+ struct resource *res;
++ int i;
+
+- iounmap(bcm_enet_shared_base);
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- release_mem_region(res->start, resource_size(res));
++ for (i = 0; i < 3; i++) {
++ iounmap(bcm_enet_shared_base[i]);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ release_mem_region(res->start, resource_size(res));
++ }
+ return 0;
+ }
+
diff --git a/target/linux/brcm63xx/patches-3.3/415-bcm63xx_enet-add-support-for-bcm6368-internal-ethern.patch b/target/linux/brcm63xx/patches-3.3/415-bcm63xx_enet-add-support-for-bcm6368-internal-ethern.patch
new file mode 100644
index 000000000..67bf01a3f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/415-bcm63xx_enet-add-support-for-bcm6368-internal-ethern.patch
@@ -0,0 +1,1490 @@
+From 1324bb5db6815d19b09c1b7bcac3cc2804412205 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Sat, 23 Jan 2010 03:01:02 +0100
+Subject: [PATCH 31/63] bcm63xx_enet: add support for bcm6368 internal ethernet switch.
+
+---
+ arch/mips/bcm63xx/dev-enet.c | 106 ++-
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 25 +
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 50 +
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 1054 ++++++++++++++++++--
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 71 ++
+ 5 files changed, 1221 insertions(+), 85 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -920,6 +920,10 @@ int __init board_register_devices(void)
+ !board_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
++ if (board.has_enetsw &&
++ !board_get_mac_address(board.enetsw.mac_addr))
++ bcm63xx_enetsw_register(&board.enetsw);
++
+ if (board.has_ehci0)
+ bcm63xx_ehci_register();
+
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -41,6 +41,7 @@ struct board_info {
+ /* enabled feature/device */
+ unsigned int has_enet0:1;
+ unsigned int has_enet1:1;
++ unsigned int has_enetsw:1;
+ unsigned int has_pci:1;
+ unsigned int has_pccard:1;
+ unsigned int has_ohci0:1;
+@@ -52,6 +53,7 @@ struct board_info {
+ /* ethernet config */
+ struct bcm63xx_enet_platform_data enet0;
+ struct bcm63xx_enet_platform_data enet1;
++ struct bcm63xx_enetsw_platform_data enetsw;
+
+ /* DSP config */
+ struct bcm63xx_dsp_platform_data dsp;
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -104,6 +104,64 @@ static struct platform_device bcm63xx_en
+ },
+ };
+
++static struct resource enetsw_res[] = {
++ {
++ /* start & end filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ /* start filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ /* start filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct bcm63xx_enetsw_platform_data enetsw_pd;
++
++static struct platform_device bcm63xx_enetsw_device = {
++ .name = "bcm63xx_enetsw",
++ .num_resources = ARRAY_SIZE(enetsw_res),
++ .resource = enetsw_res,
++ .dev = {
++ .platform_data = &enetsw_pd,
++ },
++};
++
++static int __init register_shared(void)
++{
++ int ret, chan_count;
++
++ if (shared_device_registered)
++ return 0;
++
++ shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
++ shared_res[0].end = shared_res[0].start;
++ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
++
++ if (BCMCPU_IS_6368())
++ chan_count = 32;
++ else
++ chan_count = 16;
++
++ shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
++ shared_res[1].end = shared_res[1].start;
++ shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count) - 1;
++
++ shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
++ shared_res[2].end = shared_res[2].start;
++ shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count) - 1;
++
++ ret = platform_device_register(&bcm63xx_enet_shared_device);
++ if (ret)
++ return ret;
++ shared_device_registered = 1;
++
++ return 0;
++}
++
+ int __init bcm63xx_enet_register(int unit,
+ const struct bcm63xx_enet_platform_data *pd)
+ {
+@@ -117,24 +175,9 @@ int __init bcm63xx_enet_register(int uni
+ if (unit == 1 && BCMCPU_IS_6338())
+ return -ENODEV;
+
+- if (!shared_device_registered) {
+- shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
+- shared_res[0].end = shared_res[0].start;
+- shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+-
+- shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
+- shared_res[1].end = shared_res[1].start;
+- shared_res[1].end += RSET_ENETDMAC_SIZE(16) - 1;
+-
+- shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
+- shared_res[2].end = shared_res[2].start;
+- shared_res[2].end += RSET_ENETDMAS_SIZE(16) - 1;
+-
+- ret = platform_device_register(&bcm63xx_enet_shared_device);
+- if (ret)
+- return ret;
+- shared_device_registered = 1;
+- }
++ ret = register_shared();
++ if (ret)
++ return ret;
+
+ if (unit == 0) {
+ enet0_res[0].start = bcm63xx_regset_address(RSET_ENET0);
+@@ -175,3 +218,30 @@ int __init bcm63xx_enet_register(int uni
+ return ret;
+ return 0;
+ }
++
++int __init
++bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
++{
++ int ret;
++
++ if (!BCMCPU_IS_6368())
++ return -ENODEV;
++
++ ret = register_shared();
++ if (ret)
++ return ret;
++
++ enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
++ enetsw_res[0].end = enetsw_res[0].start;
++ enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
++ enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
++ enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
++
++ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
++
++ ret = platform_device_register(&bcm63xx_enetsw_device);
++ if (ret)
++ return ret;
++
++ return 0;
++}
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -39,7 +39,32 @@ struct bcm63xx_enet_platform_data {
+ int phy_id, int reg, int val));
+ };
+
++/*
++ * on board ethernet switch platform data
++ */
++#define ENETSW_MAX_PORT 6
++
++struct bcm63xx_enetsw_port {
++ int used;
++ int external_phy;
++ int phy_id;
++
++ int bypass_link;
++ int force_speed;
++ int force_duplex_full;
++
++ const char *name;
++};
++
++struct bcm63xx_enetsw_platform_data {
++ char mac_addr[ETH_ALEN];
++ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
++};
++
+ int __init bcm63xx_enet_register(int unit,
+ const struct bcm63xx_enet_platform_data *pd);
+
++int __init
++bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd);
++
+ #endif /* ! BCM63XX_DEV_ENET_H_ */
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -809,10 +809,60 @@
+ * _REG relative to RSET_ENETSW
+ *************************************************************************/
+
++/* Port traffic control */
++#define ENETSW_PTCTRL_REG(x) (0x0 + (x))
++#define ENETSW_PTCTRL_RXDIS_MASK (1 << 0)
++#define ENETSW_PTCTRL_TXDIS_MASK (1 << 1)
++
++/* Switch mode register */
++#define ENETSW_SWMODE_REG (0xb)
++#define ENETSW_SWMODE_FWD_EN_MASK (1 << 1)
++
++/* IMP override Register */
++#define ENETSW_IMPOV_REG (0xe)
++#define ENETSW_IMPOV_FORCE_MASK (1 << 7)
++#define ENETSW_IMPOV_TXFLOW_MASK (1 << 5)
++#define ENETSW_IMPOV_RXFLOW_MASK (1 << 4)
++#define ENETSW_IMPOV_1000_MASK (1 << 3)
++#define ENETSW_IMPOV_100_MASK (1 << 2)
++#define ENETSW_IMPOV_FDX_MASK (1 << 1)
++#define ENETSW_IMPOV_LINKUP_MASK (1 << 0)
++
++/* Port override Register */
++#define ENETSW_PORTOV_REG(x) (0x58 + (x))
++#define ENETSW_PORTOV_ENABLE_MASK (1 << 6)
++#define ENETSW_PORTOV_TXFLOW_MASK (1 << 5)
++#define ENETSW_PORTOV_RXFLOW_MASK (1 << 4)
++#define ENETSW_PORTOV_1000_MASK (1 << 3)
++#define ENETSW_PORTOV_100_MASK (1 << 2)
++#define ENETSW_PORTOV_FDX_MASK (1 << 1)
++#define ENETSW_PORTOV_LINKUP_MASK (1 << 0)
++
++/* MDIO control register */
++#define ENETSW_MDIOC_REG (0xb0)
++#define ENETSW_MDIOC_EXT_MASK (1 << 16)
++#define ENETSW_MDIOC_REG_SHIFT 20
++#define ENETSW_MDIOC_PHYID_SHIFT 25
++#define ENETSW_MDIOC_RD_MASK (1 << 30)
++#define ENETSW_MDIOC_WR_MASK (1 << 31)
++
++/* MDIO data register */
++#define ENETSW_MDIOD_REG (0xb4)
++
++/* Global Management Configuration Register */
++#define ENETSW_GMCR_REG (0x200)
++#define ENETSW_GMCR_RST_MIB_MASK (1 << 0)
++
+ /* MIB register */
+ #define ENETSW_MIB_REG(x) (0x2800 + (x) * 4)
+ #define ENETSW_MIB_REG_COUNT 47
+
++/* Jumbo control register port mask register */
++#define ENETSW_JMBCTL_PORT_REG (0x4004)
++
++/* Jumbo control mib good frame register */
++#define ENETSW_JMBCTL_MAXSIZE_REG (0x4008)
++
+
+ /*************************************************************************
+ * _REG relative to RSET_OHCI_PRIV
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -59,6 +59,49 @@ static inline void enet_writel(struct bc
+ }
+
+ /*
++ * io helpers to access switch registers
++ */
++static inline u32 enetsw_readl(struct bcm_enet_priv *priv, u32 off)
++{
++ /* printk("enetsw_readl at %p\n", priv->base + off); */
++ return bcm_readl(priv->base + off);
++}
++
++static inline void enetsw_writel(struct bcm_enet_priv *priv,
++ u32 val, u32 off)
++{
++ /* printk("enetsw_writel %08x at %p\n", val, priv->base + off); */
++ bcm_writel(val, priv->base + off);
++}
++
++static inline u16 enetsw_readw(struct bcm_enet_priv *priv, u32 off)
++{
++ /* printk("enetsw_readw at %p\n", priv->base + off); */
++ return bcm_readw(priv->base + off);
++}
++
++static inline void enetsw_writew(struct bcm_enet_priv *priv,
++ u16 val, u32 off)
++{
++ /* printk("enetsw_writew %04x at %p\n", val, priv->base + off); */
++ bcm_writew(val, priv->base + off);
++}
++
++static inline u8 enetsw_readb(struct bcm_enet_priv *priv, u32 off)
++{
++ /* printk("enetsw_readb at %p\n", priv->base + off); */
++ return bcm_readb(priv->base + off);
++}
++
++static inline void enetsw_writeb(struct bcm_enet_priv *priv,
++ u8 val, u32 off)
++{
++ /* printk("enetsw_writeb %02x at %p\n", val, priv->base + off); */
++ bcm_writeb(val, priv->base + off);
++}
++
++
++/*
+ * io helpers to access shared registers
+ */
+ static inline u32 enet_dma_readl(struct bcm_enet_priv *priv, u32 off)
+@@ -321,7 +364,8 @@ static int bcm_enet_receive_queue(struct
+ }
+
+ /* recycle packet if it's marked as bad */
+- if (unlikely(len_stat & DMADESC_ERR_MASK)) {
++ if (!bcm_enet_is_sw(priv) &&
++ unlikely(len_stat & DMADESC_ERR_MASK)) {
+ dev->stats.rx_errors++;
+
+ if (len_stat & DMADESC_OVSIZE_MASK)
+@@ -552,6 +596,26 @@ static int bcm_enet_start_xmit(struct sk
+ goto out_unlock;
+ }
+
++ /* pad small packets sent on a switch device */
++ if (bcm_enet_is_sw(priv) && skb->len < 64) {
++ int needed = 64 - skb->len;
++ char *data;
++
++ if (unlikely(skb_tailroom(skb) < needed)) {
++ struct sk_buff *nskb;
++
++ nskb = skb_copy_expand(skb, 0, needed, GFP_ATOMIC);
++ if (!nskb) {
++ ret = NETDEV_TX_BUSY;
++ goto out_unlock;
++ }
++ dev_kfree_skb(skb);
++ skb = nskb;
++ }
++ data = skb_put(skb, needed);
++ memset(data, 0, needed);
++ }
++
+ /* point to the next available desc */
+ desc = &priv->tx_desc_cpu[priv->tx_curr_desc];
+ priv->tx_skb[priv->tx_curr_desc] = skb;
+@@ -1921,96 +1985,951 @@ struct platform_driver bcm63xx_enet_driv
+ };
+
+ /*
+- * reserve & remap memory space shared between all macs
++ * switch mii access callbacks
+ */
+-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
++static int bcmenet_sw_mdio_read(struct bcm_enet_priv *priv,
++ int ext, int phy_id, int location)
+ {
+- struct resource *res;
+- int ret, i, requested[3];
++ u32 reg;
++ int ret;
+
+- memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base));
+- memset(requested, 0, sizeof (requested));
++ spin_lock_bh(&priv->enetsw_mdio_lock);
++ enetsw_writel(priv, 0, ENETSW_MDIOC_REG);
+
+- for (i = 0; i < 3; i++) {
+- void __iomem *p;
++ reg = ENETSW_MDIOC_RD_MASK |
++ (phy_id << ENETSW_MDIOC_PHYID_SHIFT) |
++ (location << ENETSW_MDIOC_REG_SHIFT);
++
++ if (ext)
++ reg |= ENETSW_MDIOC_EXT_MASK;
++
++ enetsw_writel(priv, reg, ENETSW_MDIOC_REG);
++ udelay(50);
++ ret = enetsw_readw(priv, ENETSW_MDIOD_REG);
++ spin_unlock_bh(&priv->enetsw_mdio_lock);
++ return ret;
++}
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+- if (!res) {
+- ret = -EINVAL;
+- goto fail;
+- }
++static void bcmenet_sw_mdio_write(struct bcm_enet_priv *priv,
++ int ext, int phy_id, int location,
++ uint16_t data)
++{
++ u32 reg;
+
+- if (!request_mem_region(res->start, resource_size(res),
+- "bcm63xx_enet_dma")) {
+- ret = -EBUSY;
+- goto fail;
+- }
+- requested[i] = 0;
++ spin_lock_bh(&priv->enetsw_mdio_lock);
++ enetsw_writel(priv, 0, ENETSW_MDIOC_REG);
+
+- p = ioremap(res->start, resource_size(res));
+- if (!p) {
+- ret = -ENOMEM;
+- goto fail;
+- }
++ reg = ENETSW_MDIOC_WR_MASK |
++ (phy_id << ENETSW_MDIOC_PHYID_SHIFT) |
++ (location << ENETSW_MDIOC_REG_SHIFT);
+
+- bcm_enet_shared_base[i] = p;
+- }
++ if (ext)
++ reg |= ENETSW_MDIOC_EXT_MASK;
+
+- return 0;
++ reg |= data;
+
+-fail:
+- for (i = 0; i < 3; i++) {
+- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+- if (!res)
+- continue;
+- if (bcm_enet_shared_base[i])
+- iounmap(bcm_enet_shared_base[i]);
+- if (requested[i])
+- release_mem_region(res->start, resource_size(res));
+- }
+- return ret;
++ enetsw_writel(priv, reg, ENETSW_MDIOC_REG);
++ udelay(50);
++ spin_unlock_bh(&priv->enetsw_mdio_lock);
+ }
+
+-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
++/*
++ * enet sw PHY polling
++ */
++static void swphy_poll_timer(unsigned long data)
+ {
+- struct resource *res;
+- int i;
++ struct bcm_enet_priv *priv = (struct bcm_enet_priv *)data;
++ unsigned int i;
+
+- for (i = 0; i < 3; i++) {
+- iounmap(bcm_enet_shared_base[i]);
+- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+- release_mem_region(res->start, resource_size(res));
++ for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ struct bcm63xx_enetsw_port *port;
++ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
++ u8 override;
++
++ port = &priv->used_ports[i];
++ if (!port->used)
++ continue;
++
++ if (port->bypass_link)
++ continue;
++
++ /* dummy read to clear */
++ for (j = 0; j < 2; j++)
++ val = bcmenet_sw_mdio_read(priv, port->external_phy,
++ port->phy_id, MII_BMSR);
++
++ if (val == 0xffff)
++ continue;
++
++ up = (val & BMSR_LSTATUS) ? 1 : 0;
++ if (!(up ^ priv->sw_port_link[i]))
++ continue;
++
++ priv->sw_port_link[i] = up;
++
++ /* link changed */
++ if (!up) {
++ dev_info(&priv->pdev->dev, "link DOWN on %s\n",
++ port->name);
++ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
++ ENETSW_PORTOV_REG(i));
++ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
++ ENETSW_PTCTRL_TXDIS_MASK,
++ ENETSW_PTCTRL_REG(i));
++ continue;
++ }
++
++ advertise = bcmenet_sw_mdio_read(priv, port->external_phy,
++ port->phy_id, MII_ADVERTISE);
++
++ lpa = bcmenet_sw_mdio_read(priv, port->external_phy,
++ port->phy_id, MII_LPA);
++
++ lpa2 = bcmenet_sw_mdio_read(priv, port->external_phy,
++ port->phy_id, MII_STAT1000);
++
++ /* figure out media and duplex from advertise and LPA values */
++ media = mii_nway_result(lpa & advertise);
++ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
++ if (lpa2 & LPA_1000FULL)
++ duplex = 1;
++
++ if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
++ speed = 1000;
++ else {
++ if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
++ speed = 100;
++ else
++ speed = 10;
++ }
++
++ dev_info(&priv->pdev->dev,
++ "link UP on %s, %dMbps, %s-duplex\n",
++ port->name, speed, duplex ? "full" : "half");
++
++ override = ENETSW_PORTOV_ENABLE_MASK |
++ ENETSW_PORTOV_LINKUP_MASK;
++
++ if (speed == 1000)
++ override |= ENETSW_IMPOV_1000_MASK;
++ else if (speed == 100)
++ override |= ENETSW_IMPOV_100_MASK;
++ if (duplex)
++ override |= ENETSW_IMPOV_FDX_MASK;
++
++ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
++ enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i));
+ }
+- return 0;
+-}
+
+-/*
+- * this "shared" driver is needed because both macs share a single
+- * address space
+- */
+-struct platform_driver bcm63xx_enet_shared_driver = {
+- .probe = bcm_enet_shared_probe,
+- .remove = __devexit_p(bcm_enet_shared_remove),
+- .driver = {
+- .name = "bcm63xx_enet_shared",
+- .owner = THIS_MODULE,
+- },
+-};
++ priv->swphy_poll.expires = jiffies + HZ;
++ add_timer(&priv->swphy_poll);
++}
+
+ /*
+- * entry point
++ * open callback, allocate dma rings & buffers and start rx operation
+ */
+-static int __init bcm_enet_init(void)
++static int bcm_enetsw_open(struct net_device *dev)
+ {
+- int ret;
++ struct bcm_enet_priv *priv;
++ struct device *kdev;
++ int i, ret;
++ unsigned int size;
++ void *p;
++ u32 val;
+
+- ret = platform_driver_register(&bcm63xx_enet_shared_driver);
++ priv = netdev_priv(dev);
++ kdev = &priv->pdev->dev;
++
++ /* mask all interrupts and request them */
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
++
++ ret = request_irq(priv->irq_rx, bcm_enet_isr_dma,
++ IRQF_DISABLED, dev->name, dev);
+ if (ret)
+- return ret;
++ goto out_freeirq;
+
+- ret = platform_driver_register(&bcm63xx_enet_driver);
++ ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
++ IRQF_DISABLED, dev->name, dev);
+ if (ret)
+- platform_driver_unregister(&bcm63xx_enet_shared_driver);
++ goto out_freeirq_rx;
++
++ /* allocate rx dma ring */
++ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
++ p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
++ if (!p) {
++ dev_err(kdev, "cannot allocate rx ring %u\n", size);
++ ret = -ENOMEM;
++ goto out_freeirq_tx;
++ }
++
++ memset(p, 0, size);
++ priv->rx_desc_alloc_size = size;
++ priv->rx_desc_cpu = p;
++
++ /* allocate tx dma ring */
++ size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
++ p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
++ if (!p) {
++ dev_err(kdev, "cannot allocate tx ring\n");
++ ret = -ENOMEM;
++ goto out_free_rx_ring;
++ }
++
++ memset(p, 0, size);
++ priv->tx_desc_alloc_size = size;
++ priv->tx_desc_cpu = p;
++
++ priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size,
++ GFP_KERNEL);
++ if (!priv->tx_skb) {
++ dev_err(kdev, "cannot allocate rx skb queue\n");
++ ret = -ENOMEM;
++ goto out_free_tx_ring;
++ }
++
++ priv->tx_desc_count = priv->tx_ring_size;
++ priv->tx_dirty_desc = 0;
++ priv->tx_curr_desc = 0;
++ spin_lock_init(&priv->tx_lock);
++
++ /* init & fill rx ring with skbs */
++ priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size,
++ GFP_KERNEL);
++ if (!priv->rx_skb) {
++ dev_err(kdev, "cannot allocate rx skb queue\n");
++ ret = -ENOMEM;
++ goto out_free_tx_skb;
++ }
++
++ priv->rx_desc_count = 0;
++ priv->rx_dirty_desc = 0;
++ priv->rx_curr_desc = 0;
++
++ /* disable all ports */
++ for (i = 0; i < 6; i++) {
++ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
++ ENETSW_PORTOV_REG(i));
++ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
++ ENETSW_PTCTRL_TXDIS_MASK,
++ ENETSW_PTCTRL_REG(i));
++ }
++
++ /* reset mib */
++ val = enetsw_readb(priv, ENETSW_GMCR_REG);
++ val |= ENETSW_GMCR_RST_MIB_MASK;
++ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
++ mdelay(1);
++ val &= ~ENETSW_GMCR_RST_MIB_MASK;
++ enetsw_writeb(priv, val, ENETSW_GMCR_REG);
++ mdelay(1);
++
++ /* force CPU port state */
++ val = enetsw_readb(priv, ENETSW_IMPOV_REG);
++ val |= ENETSW_IMPOV_FORCE_MASK | ENETSW_IMPOV_LINKUP_MASK;
++ enetsw_writeb(priv, val, ENETSW_IMPOV_REG);
++
++ /* enable switch forward engine */
++ val = enetsw_readb(priv, ENETSW_SWMODE_REG);
++ val |= ENETSW_SWMODE_FWD_EN_MASK;
++ enetsw_writeb(priv, val, ENETSW_SWMODE_REG);
++
++ /* enable jumbo on all ports */
++ enetsw_writel(priv, 0x1ff, ENETSW_JMBCTL_PORT_REG);
++ enetsw_writew(priv, 9728, ENETSW_JMBCTL_MAXSIZE_REG);
++
++ /* initialize flow control buffer allocation */
++ enet_dma_writel(priv, ENETDMA_BUFALLOC_FORCE_MASK | 0,
++ ENETDMA_BUFALLOC_REG(priv->rx_chan));
++
++ if (bcm_enet_refill_rx(dev)) {
++ dev_err(kdev, "cannot allocate rx skb queue\n");
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ /* write rx & tx ring addresses */
++ enet_dmas_writel(priv, priv->rx_desc_dma,
++ ENETDMAS_RSTART_REG(priv->rx_chan));
++ enet_dmas_writel(priv, priv->tx_desc_dma,
++ ENETDMAS_RSTART_REG(priv->tx_chan));
++
++ /* clear remaining state ram for rx & tx channel */
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM2_REG(priv->tx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM3_REG(priv->tx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->rx_chan));
++ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
++
++ /* set dma maximum burst len */
++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ ENETDMAC_MAXBURST_REG(priv->rx_chan));
++ enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ ENETDMAC_MAXBURST_REG(priv->tx_chan));
++
++ /* set flow control low/high threshold to 1/3 / 2/3 */
++ val = priv->rx_ring_size / 3;
++ enet_dma_writel(priv, val, ENETDMA_FLOWCL_REG(priv->rx_chan));
++ val = (priv->rx_ring_size * 2) / 3;
++ enet_dma_writel(priv, val, ENETDMA_FLOWCH_REG(priv->rx_chan));
++
++ /* all set, enable mac and interrupts, start dma engine and
++ * kick rx dma channel */
++ wmb();
++ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG);
++ enet_dmac_writel(priv, ENETDMAC_CHANCFG_EN_MASK,
++ ENETDMAC_CHANCFG_REG(priv->rx_chan));
++
++ /* watch "packet transferred" interrupt in rx and tx */
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IR_REG(priv->tx_chan));
++
++ /* make sure we enable napi before rx interrupt */
++ napi_enable(&priv->napi);
++
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, ENETDMAC_IR_PKTDONE_MASK,
++ ENETDMAC_IRMASK_REG(priv->tx_chan));
++
++ netif_carrier_on(dev);
++ netif_start_queue(dev);
++
++ /*
++ * apply override config for bypass_link ports here.
++ */
++ for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ struct bcm63xx_enetsw_port *port;
++ u8 override;
++ port = &priv->used_ports[i];
++ if (!port->used)
++ continue;
++
++ if (!port->bypass_link)
++ continue;
++
++ override = ENETSW_PORTOV_ENABLE_MASK |
++ ENETSW_PORTOV_LINKUP_MASK;
++
++ switch (port->force_speed) {
++ case 1000:
++ override |= ENETSW_IMPOV_1000_MASK;
++ break;
++ case 100:
++ override |= ENETSW_IMPOV_100_MASK;
++ break;
++ case 10:
++ break;
++ default:
++ printk(KERN_WARNING "invalid forced speed on port %s: "
++ "assume 10\n",
++ port->name);
++ break;
++ }
++
++ if (port->force_duplex_full)
++ override = ENETSW_IMPOV_FDX_MASK;
++
++
++ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
++ enetsw_writeb(priv, 0, ENETSW_PTCTRL_REG(i));
++ }
++
++ /* start phy polling timer */
++ init_timer(&priv->swphy_poll);
++ priv->swphy_poll.function = swphy_poll_timer;
++ priv->swphy_poll.data = (unsigned long)priv;
++ priv->swphy_poll.expires = jiffies;
++ add_timer(&priv->swphy_poll);
++ return 0;
++
++out:
++ for (i = 0; i < priv->rx_ring_size; i++) {
++ struct bcm_enet_desc *desc;
++
++ if (!priv->rx_skb[i])
++ continue;
++
++ desc = &priv->rx_desc_cpu[i];
++ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
++ DMA_FROM_DEVICE);
++ kfree_skb(priv->rx_skb[i]);
++ }
++ kfree(priv->rx_skb);
++
++out_free_tx_skb:
++ kfree(priv->tx_skb);
++
++out_free_tx_ring:
++ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
++ priv->tx_desc_cpu, priv->tx_desc_dma);
++
++out_free_rx_ring:
++ dma_free_coherent(kdev, priv->rx_desc_alloc_size,
++ priv->rx_desc_cpu, priv->rx_desc_dma);
++
++out_freeirq_tx:
++ free_irq(priv->irq_tx, dev);
++
++out_freeirq_rx:
++ free_irq(priv->irq_rx, dev);
++
++out_freeirq:
++ return ret;
++}
++
++/*
++ * stop callback
++ */
++static int bcm_enetsw_stop(struct net_device *dev)
++{
++ struct bcm_enet_priv *priv;
++ struct device *kdev;
++ int i;
++
++ priv = netdev_priv(dev);
++ kdev = &priv->pdev->dev;
++
++ del_timer_sync(&priv->swphy_poll);
++ netif_stop_queue(dev);
++ napi_disable(&priv->napi);
++ del_timer_sync(&priv->rx_timeout);
++
++ /* mask all interrupts */
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->rx_chan));
++ enet_dmac_writel(priv, 0, ENETDMAC_IRMASK_REG(priv->tx_chan));
++
++ /* disable dma & mac */
++ bcm_enet_disable_dma(priv, priv->tx_chan);
++ bcm_enet_disable_dma(priv, priv->rx_chan);
++
++ /* force reclaim of all tx buffers */
++ bcm_enet_tx_reclaim(dev, 1);
++
++ /* free the rx skb ring */
++ for (i = 0; i < priv->rx_ring_size; i++) {
++ struct bcm_enet_desc *desc;
++
++ if (!priv->rx_skb[i])
++ continue;
++
++ desc = &priv->rx_desc_cpu[i];
++ dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
++ DMA_FROM_DEVICE);
++ kfree_skb(priv->rx_skb[i]);
++ }
++
++ /* free remaining allocated memory */
++ kfree(priv->rx_skb);
++ kfree(priv->tx_skb);
++ dma_free_coherent(kdev, priv->rx_desc_alloc_size,
++ priv->rx_desc_cpu, priv->rx_desc_dma);
++ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
++ priv->tx_desc_cpu, priv->tx_desc_dma);
++ free_irq(priv->irq_tx, dev);
++ free_irq(priv->irq_rx, dev);
++
++ return 0;
++}
++
++/*
++ * try to sort out phy external status by walking the used_port field
++ * in the bcm_enet_priv structure. in case the phy address is not
++ * assigned to any physical port on the switch, assume it is external
++ * (and yell at the user).
++ */
++static int bcm_enetsw_phy_is_external(struct bcm_enet_priv *priv, int phy_id)
++{
++ int i;
++
++ for (i = 0; i < (int)ARRAY_SIZE(priv->used_ports); ++i) {
++ if (!priv->used_ports[i].used)
++ continue;
++ if (priv->used_ports[i].phy_id == phy_id)
++ return priv->used_ports[i].external_phy;
++ }
++
++ printk_once(KERN_WARNING "bcm63xx_enet: could not find a used port "
++ "with phy_id %i, assuming phy is external\n", phy_id);
++ return 1;
++}
++
++/*
++ * can't use bcmenet_sw_mdio_read directly as we need to sort out
++ * external/internal status of the given phy_id first.
++ */
++static int bcm_enetsw_mii_mdio_read(struct net_device *dev, int phy_id,
++ int location)
++{
++ struct bcm_enet_priv *priv;
++
++ priv = netdev_priv(dev);
++ return bcmenet_sw_mdio_read(priv,
++ bcm_enetsw_phy_is_external(priv, phy_id),
++ phy_id, location);
++}
++
++/*
++ * can't use bcmenet_sw_mdio_write directly as we need to sort out
++ * external/internal status of the given phy_id first.
++ */
++static void bcm_enetsw_mii_mdio_write(struct net_device *dev, int phy_id,
++ int location,
++ int val)
++{
++ struct bcm_enet_priv *priv;
++
++ priv = netdev_priv(dev);
++ bcmenet_sw_mdio_write(priv, bcm_enetsw_phy_is_external(priv, phy_id),
++ phy_id, location, val);
++}
++
++static int bcm_enetsw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct mii_if_info mii;
++
++ mii.dev = dev;
++ mii.mdio_read = bcm_enetsw_mii_mdio_read;
++ mii.mdio_write = bcm_enetsw_mii_mdio_write;
++ mii.phy_id = 0;
++ mii.phy_id_mask = 0x3f;
++ mii.reg_num_mask = 0x1f;
++ return generic_mii_ioctl(&mii, if_mii(rq), cmd, NULL);
++
++}
++
++static const struct net_device_ops bcm_enetsw_ops = {
++ .ndo_open = bcm_enetsw_open,
++ .ndo_stop = bcm_enetsw_stop,
++ .ndo_start_xmit = bcm_enet_start_xmit,
++ .ndo_change_mtu = bcm_enet_change_mtu,
++ .ndo_do_ioctl = bcm_enetsw_ioctl,
++};
++
++
++static const struct bcm_enet_stats bcm_enetsw_gstrings_stats[] = {
++ { "rx_packets", DEV_STAT(rx_packets), -1 },
++ { "tx_packets", DEV_STAT(tx_packets), -1 },
++ { "rx_bytes", DEV_STAT(rx_bytes), -1 },
++ { "tx_bytes", DEV_STAT(tx_bytes), -1 },
++ { "rx_errors", DEV_STAT(rx_errors), -1 },
++ { "tx_errors", DEV_STAT(tx_errors), -1 },
++ { "rx_dropped", DEV_STAT(rx_dropped), -1 },
++ { "tx_dropped", DEV_STAT(tx_dropped), -1 },
++
++ { "tx_good_octets", GEN_STAT(mib.tx_gd_octets), ETHSW_MIB_RX_GD_OCT },
++ { "tx_unicast", GEN_STAT(mib.tx_unicast), ETHSW_MIB_RX_BRDCAST },
++ { "tx_broadcast", GEN_STAT(mib.tx_brdcast), ETHSW_MIB_RX_BRDCAST },
++ { "tx_multicast", GEN_STAT(mib.tx_mult), ETHSW_MIB_RX_MULT },
++ { "tx_64_octets", GEN_STAT(mib.tx_64), ETHSW_MIB_RX_64 },
++ { "tx_65_127_oct", GEN_STAT(mib.tx_65_127), ETHSW_MIB_RX_65_127 },
++ { "tx_128_255_oct", GEN_STAT(mib.tx_128_255), ETHSW_MIB_RX_128_255 },
++ { "tx_256_511_oct", GEN_STAT(mib.tx_256_511), ETHSW_MIB_RX_256_511 },
++ { "tx_512_1023_oct", GEN_STAT(mib.tx_512_1023), ETHSW_MIB_RX_512_1023},
++ { "tx_1024_1522_oct", GEN_STAT(mib.tx_1024_max),
++ ETHSW_MIB_RX_1024_1522 },
++ { "tx_1523_2047_oct", GEN_STAT(mib.tx_1523_2047),
++ ETHSW_MIB_RX_1523_2047 },
++ { "tx_2048_4095_oct", GEN_STAT(mib.tx_2048_4095),
++ ETHSW_MIB_RX_2048_4095 },
++ { "tx_4096_8191_oct", GEN_STAT(mib.tx_4096_8191),
++ ETHSW_MIB_RX_4096_8191 },
++ { "tx_8192_9728_oct", GEN_STAT(mib.tx_8192_9728),
++ ETHSW_MIB_RX_8192_9728 },
++ { "tx_oversize", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR },
++ { "tx_oversize_drop", GEN_STAT(mib.tx_ovr), ETHSW_MIB_RX_OVR_DISC },
++ { "tx_dropped", GEN_STAT(mib.tx_drop), ETHSW_MIB_RX_DROP },
++ { "tx_undersize", GEN_STAT(mib.tx_underrun), ETHSW_MIB_RX_UND },
++ { "tx_pause", GEN_STAT(mib.tx_pause), ETHSW_MIB_RX_PAUSE },
++
++ { "rx_good_octets", GEN_STAT(mib.rx_gd_octets), ETHSW_MIB_TX_ALL_OCT },
++ { "rx_broadcast", GEN_STAT(mib.rx_brdcast), ETHSW_MIB_TX_BRDCAST },
++ { "rx_multicast", GEN_STAT(mib.rx_mult), ETHSW_MIB_TX_MULT },
++ { "rx_unicast", GEN_STAT(mib.rx_unicast), ETHSW_MIB_TX_MULT },
++ { "rx_pause", GEN_STAT(mib.rx_pause), ETHSW_MIB_TX_PAUSE },
++ { "rx_dropped", GEN_STAT(mib.rx_drop), ETHSW_MIB_TX_DROP_PKTS },
++
++};
++
++#define BCM_ENETSW_STATS_LEN \
++ (sizeof(bcm_enetsw_gstrings_stats) / sizeof(struct bcm_enet_stats))
++
++static void bcm_enetsw_get_strings(struct net_device *netdev,
++ u32 stringset, u8 *data)
++{
++ int i;
++
++ switch (stringset) {
++ case ETH_SS_STATS:
++ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
++ memcpy(data + i * ETH_GSTRING_LEN,
++ bcm_enetsw_gstrings_stats[i].stat_string,
++ ETH_GSTRING_LEN);
++ }
++ break;
++ }
++}
++
++static int bcm_enetsw_get_sset_count(struct net_device *netdev,
++ int string_set)
++{
++ switch (string_set) {
++ case ETH_SS_STATS:
++ return BCM_ENETSW_STATS_LEN;
++ default:
++ return -EINVAL;
++ }
++}
++
++static void bcm_enetsw_get_drvinfo(struct net_device *netdev,
++ struct ethtool_drvinfo *drvinfo)
++{
++ strncpy(drvinfo->driver, bcm_enet_driver_name, 32);
++ strncpy(drvinfo->version, bcm_enet_driver_version, 32);
++ strncpy(drvinfo->fw_version, "N/A", 32);
++ strncpy(drvinfo->bus_info, "bcm63xx", 32);
++ drvinfo->n_stats = BCM_ENETSW_STATS_LEN;
++}
++
++static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev,
++ struct ethtool_stats *stats,
++ u64 *data)
++{
++ struct bcm_enet_priv *priv;
++ int i;
++
++ priv = netdev_priv(netdev);
++
++ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
++ const struct bcm_enet_stats *s;
++ u32 lo, hi;
++ char *p;
++ int reg;
++
++ s = &bcm_enetsw_gstrings_stats[i];
++
++ reg = s->mib_reg;
++ if (reg == -1)
++ continue;
++
++ lo = enetsw_readl(priv, ENETSW_MIB_REG(reg));
++ p = (char *)priv + s->stat_offset;
++
++ if (s->sizeof_stat == sizeof(u64)) {
++ hi = enetsw_readl(priv, ENETSW_MIB_REG(reg + 1));
++ *(u64 *)p = ((u64)hi << 32 | lo);
++ } else
++ *(u32 *)p = lo;
++ }
++
++ for (i = 0; i < BCM_ENETSW_STATS_LEN; i++) {
++ const struct bcm_enet_stats *s;
++ char *p;
++
++ s = &bcm_enetsw_gstrings_stats[i];
++
++ if (s->mib_reg == -1)
++ p = (char *)&netdev->stats + s->stat_offset;
++ else
++ p = (char *)priv + s->stat_offset;
++
++ data[i] = (s->sizeof_stat == sizeof(u64)) ?
++ *(u64 *)p : *(u32 *)p;
++ }
++}
++
++static void bcm_enetsw_get_ringparam(struct net_device *dev,
++ struct ethtool_ringparam *ering)
++{
++ struct bcm_enet_priv *priv;
++
++ priv = netdev_priv(dev);
++
++ /* rx/tx ring is actually only limited by memory */
++ ering->rx_max_pending = 8192;
++ ering->tx_max_pending = 8192;
++ ering->rx_mini_max_pending = 0;
++ ering->rx_jumbo_max_pending = 0;
++ ering->rx_pending = priv->rx_ring_size;
++ ering->tx_pending = priv->tx_ring_size;
++}
++
++static int bcm_enetsw_set_ringparam(struct net_device *dev,
++ struct ethtool_ringparam *ering)
++{
++ struct bcm_enet_priv *priv;
++ int was_running;
++
++ priv = netdev_priv(dev);
++
++ was_running = 0;
++ if (netif_running(dev)) {
++ bcm_enetsw_stop(dev);
++ was_running = 1;
++ }
++
++ priv->rx_ring_size = ering->rx_pending;
++ priv->tx_ring_size = ering->tx_pending;
++
++ if (was_running) {
++ int err;
++
++ err = bcm_enetsw_open(dev);
++ if (err)
++ dev_close(dev);
++ }
++ return 0;
++}
++
++static struct ethtool_ops bcm_enetsw_ethtool_ops = {
++ .get_strings = bcm_enetsw_get_strings,
++ .get_sset_count = bcm_enetsw_get_sset_count,
++ .get_ethtool_stats = bcm_enetsw_get_ethtool_stats,
++ .get_drvinfo = bcm_enetsw_get_drvinfo,
++ .get_ringparam = bcm_enetsw_get_ringparam,
++ .set_ringparam = bcm_enetsw_set_ringparam,
++};
++
++/*
++ * allocate netdevice, request register memory and register device.
++ */
++static int __devinit bcm_enetsw_probe(struct platform_device *pdev)
++{
++ struct bcm_enet_priv *priv;
++ struct net_device *dev;
++ struct bcm63xx_enetsw_platform_data *pd;
++ struct resource *res_mem;
++ int ret, irq_rx, irq_tx;
++
++ /* stop if shared driver failed, assume driver->probe will be
++ * called in the same order we register devices (correct ?) */
++ if (!bcm_enet_shared_base[0])
++ return -ENODEV;
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ irq_rx = platform_get_irq(pdev, 0);
++ irq_tx = platform_get_irq(pdev, 1);
++ if (!res_mem || irq_rx < 0 || irq_tx < 0)
++ return -ENODEV;
++
++ ret = 0;
++ dev = alloc_etherdev(sizeof(*priv));
++ if (!dev)
++ return -ENOMEM;
++ priv = netdev_priv(dev);
++ memset(priv, 0, sizeof(*priv));
++
++ /* initialize default and fetch platform data */
++ priv->irq_rx = irq_rx;
++ priv->irq_tx = irq_tx;
++ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
++ priv->tx_ring_size = BCMENET_DEF_TX_DESC;
++
++ pd = pdev->dev.platform_data;
++ if (pd) {
++ memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
++ memcpy(priv->used_ports, pd->used_ports,
++ sizeof (pd->used_ports));
++ }
++
++ ret = compute_hw_mtu(priv, dev->mtu);
++ if (ret)
++ goto out;
++
++ if (!request_mem_region(res_mem->start, resource_size(res_mem),
++ "bcm63xx_enetsw")) {
++ ret = -EBUSY;
++ goto out;
++ }
++
++ priv->base = ioremap(res_mem->start, resource_size(res_mem));
++ if (priv->base == NULL) {
++ ret = -ENOMEM;
++ goto out_release_mem;
++ }
++
++ priv->mac_clk = clk_get(&pdev->dev, "enetsw");
++ if (IS_ERR(priv->mac_clk)) {
++ ret = PTR_ERR(priv->mac_clk);
++ goto out_unmap;
++ }
++ clk_enable(priv->mac_clk);
++
++ priv->rx_chan = 0;
++ priv->tx_chan = 1;
++ spin_lock_init(&priv->rx_lock);
++
++ /* init rx timeout (used for oom) */
++ init_timer(&priv->rx_timeout);
++ priv->rx_timeout.function = bcm_enet_refill_rx_timer;
++ priv->rx_timeout.data = (unsigned long)dev;
++
++ /* register netdevice */
++ dev->netdev_ops = &bcm_enetsw_ops;
++ netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
++ SET_ETHTOOL_OPS(dev, &bcm_enetsw_ethtool_ops);
++ SET_NETDEV_DEV(dev, &pdev->dev);
++
++ spin_lock_init(&priv->enetsw_mdio_lock);
++
++ ret = register_netdev(dev);
++ if (ret)
++ goto out_put_clk;
++
++ netif_carrier_off(dev);
++ platform_set_drvdata(pdev, dev);
++ priv->pdev = pdev;
++ priv->net_dev = dev;
++
++ return 0;
++
++out_put_clk:
++ clk_put(priv->mac_clk);
++
++out_unmap:
++ iounmap(priv->base);
++
++out_release_mem:
++ release_mem_region(res_mem->start, resource_size(res_mem));
++out:
++ free_netdev(dev);
++ return ret;
++}
++
++
++/*
++ * exit func, stops hardware and unregisters netdevice
++ */
++static int __devexit bcm_enetsw_remove(struct platform_device *pdev)
++{
++ struct bcm_enet_priv *priv;
++ struct net_device *dev;
++ struct resource *res;
++
++ /* stop netdevice */
++ dev = platform_get_drvdata(pdev);
++ priv = netdev_priv(dev);
++ unregister_netdev(dev);
++
++ /* release device resources */
++ iounmap(priv->base);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, resource_size(res));
++
++ platform_set_drvdata(pdev, NULL);
++ free_netdev(dev);
++ return 0;
++}
++
++struct platform_driver bcm63xx_enetsw_driver = {
++ .probe = bcm_enetsw_probe,
++ .remove = __devexit_p(bcm_enetsw_remove),
++ .driver = {
++ .name = "bcm63xx_enetsw",
++ .owner = THIS_MODULE,
++ },
++};
++
++/*
++ * reserve & remap memory space shared between all macs
++ */
++static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ int ret, i, requested[3];
++
++ memset(bcm_enet_shared_base, 0, sizeof (bcm_enet_shared_base));
++ memset(requested, 0, sizeof (requested));
++
++ for (i = 0; i < 3; i++) {
++ void __iomem *p;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ if (!res) {
++ ret = -EINVAL;
++ goto fail;
++ }
++
++ if (!request_mem_region(res->start, resource_size(res),
++ "bcm63xx_enet_dma")) {
++ ret = -EBUSY;
++ goto fail;
++ }
++ requested[i] = 0;
++
++ p = ioremap(res->start, resource_size(res));
++ if (!p) {
++ ret = -ENOMEM;
++ goto fail;
++ }
++
++ bcm_enet_shared_base[i] = p;
++ }
++
++ return 0;
++
++fail:
++ for (i = 0; i < 3; i++) {
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ if (!res)
++ continue;
++ if (bcm_enet_shared_base[i])
++ iounmap(bcm_enet_shared_base[i]);
++ if (requested[i])
++ release_mem_region(res->start, resource_size(res));
++ }
++ return ret;
++}
++
++static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
++{
++ struct resource *res;
++ int i;
++
++ for (i = 0; i < 3; i++) {
++ iounmap(bcm_enet_shared_base[i]);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
++ release_mem_region(res->start, resource_size(res));
++ }
++ return 0;
++}
++
++/*
++ * this "shared" driver is needed because both macs share a single
++ * address space
++ */
++struct platform_driver bcm63xx_enet_shared_driver = {
++ .probe = bcm_enet_shared_probe,
++ .remove = __devexit_p(bcm_enet_shared_remove),
++ .driver = {
++ .name = "bcm63xx_enet_shared",
++ .owner = THIS_MODULE,
++ },
++};
++
++/*
++ * entry point
++ */
++static int __init bcm_enet_init(void)
++{
++ int ret;
++
++ ret = platform_driver_register(&bcm63xx_enet_shared_driver);
++ if (ret)
++ return ret;
++
++ ret = platform_driver_register(&bcm63xx_enet_driver);
++ if (ret)
++ platform_driver_unregister(&bcm63xx_enet_shared_driver);
++
++ ret = platform_driver_register(&bcm63xx_enetsw_driver);
++ if (ret) {
++ platform_driver_unregister(&bcm63xx_enet_driver);
++ platform_driver_unregister(&bcm63xx_enet_shared_driver);
++ }
+
+ return ret;
+ }
+@@ -2018,6 +2937,7 @@ static int __init bcm_enet_init(void)
+ static void __exit bcm_enet_exit(void)
+ {
+ platform_driver_unregister(&bcm63xx_enet_driver);
++ platform_driver_unregister(&bcm63xx_enetsw_driver);
+ platform_driver_unregister(&bcm63xx_enet_shared_driver);
+ }
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -112,11 +112,60 @@ struct bcm_enet_desc {
+ #define ETH_MIB_RX_CNTRL 54
+
+
++/*
++ * SW MIB Counters register definitions
++*/
++#define ETHSW_MIB_TX_ALL_OCT 0
++#define ETHSW_MIB_TX_DROP_PKTS 2
++#define ETHSW_MIB_TX_QOS_PKTS 3
++#define ETHSW_MIB_TX_BRDCAST 4
++#define ETHSW_MIB_TX_MULT 5
++#define ETHSW_MIB_TX_UNI 6
++#define ETHSW_MIB_TX_COL 7
++#define ETHSW_MIB_TX_1_COL 8
++#define ETHSW_MIB_TX_M_COL 9
++#define ETHSW_MIB_TX_DEF 10
++#define ETHSW_MIB_TX_LATE 11
++#define ETHSW_MIB_TX_EX_COL 12
++#define ETHSW_MIB_TX_PAUSE 14
++#define ETHSW_MIB_TX_QOS_OCT 15
++
++#define ETHSW_MIB_RX_ALL_OCT 17
++#define ETHSW_MIB_RX_UND 19
++#define ETHSW_MIB_RX_PAUSE 20
++#define ETHSW_MIB_RX_64 21
++#define ETHSW_MIB_RX_65_127 22
++#define ETHSW_MIB_RX_128_255 23
++#define ETHSW_MIB_RX_256_511 24
++#define ETHSW_MIB_RX_512_1023 25
++#define ETHSW_MIB_RX_1024_1522 26
++#define ETHSW_MIB_RX_OVR 27
++#define ETHSW_MIB_RX_JAB 28
++#define ETHSW_MIB_RX_ALIGN 29
++#define ETHSW_MIB_RX_CRC 30
++#define ETHSW_MIB_RX_GD_OCT 31
++#define ETHSW_MIB_RX_DROP 33
++#define ETHSW_MIB_RX_UNI 34
++#define ETHSW_MIB_RX_MULT 35
++#define ETHSW_MIB_RX_BRDCAST 36
++#define ETHSW_MIB_RX_SA_CHANGE 37
++#define ETHSW_MIB_RX_FRAG 38
++#define ETHSW_MIB_RX_OVR_DISC 39
++#define ETHSW_MIB_RX_SYM 40
++#define ETHSW_MIB_RX_QOS_PKTS 41
++#define ETHSW_MIB_RX_QOS_OCT 42
++#define ETHSW_MIB_RX_1523_2047 44
++#define ETHSW_MIB_RX_2048_4095 45
++#define ETHSW_MIB_RX_4096_8191 46
++#define ETHSW_MIB_RX_8192_9728 47
++
++
+ struct bcm_enet_mib_counters {
+ u64 tx_gd_octets;
+ u32 tx_gd_pkts;
+ u32 tx_all_octets;
+ u32 tx_all_pkts;
++ u32 tx_unicast;
+ u32 tx_brdcast;
+ u32 tx_mult;
+ u32 tx_64;
+@@ -125,7 +174,12 @@ struct bcm_enet_mib_counters {
+ u32 tx_256_511;
+ u32 tx_512_1023;
+ u32 tx_1024_max;
++ u32 tx_1523_2047;
++ u32 tx_2048_4095;
++ u32 tx_4096_8191;
++ u32 tx_8192_9728;
+ u32 tx_jab;
++ u32 tx_drop;
+ u32 tx_ovr;
+ u32 tx_frag;
+ u32 tx_underrun;
+@@ -142,6 +196,7 @@ struct bcm_enet_mib_counters {
+ u32 rx_all_octets;
+ u32 rx_all_pkts;
+ u32 rx_brdcast;
++ u32 rx_unicast;
+ u32 rx_mult;
+ u32 rx_64;
+ u32 rx_65_127;
+@@ -297,6 +352,22 @@ struct bcm_enet_priv {
+
+ /* maximum hardware transmit/receive size */
+ unsigned int hw_mtu;
++
++ /* port mapping for switch devices */
++ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
++ int sw_port_link[ENETSW_MAX_PORT];
++
++ /* used to poll switch port state */
++ struct timer_list swphy_poll;
++ spinlock_t enetsw_mdio_lock;
+ };
+
++static inline int bcm_enet_is_sw(struct bcm_enet_priv *priv)
++{
++ if (BCMCPU_IS_6368())
++ return 1;
++ else
++ return 0;
++}
++
+ #endif /* ! BCM63XX_ENET_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/416-bcm63xx_enet-reset-port-link-state-in-bcm_enetsw_ope.patch b/target/linux/brcm63xx/patches-3.3/416-bcm63xx_enet-reset-port-link-state-in-bcm_enetsw_ope.patch
new file mode 100644
index 000000000..6d8e5a72d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/416-bcm63xx_enet-reset-port-link-state-in-bcm_enetsw_ope.patch
@@ -0,0 +1,28 @@
+From 6d5c5bb13db3fd8e3dd0b82742b3957f41a4a3ac Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 24 May 2012 20:38:58 +0200
+Subject: [PATCH] bcm63xx_enet: reset port link state in bcm_enetsw_open
+
+bcm_enetsw_open disables all ports, but does not reset their link state.
+This results in connected ports staying disabled after a ifdown/ifup
+cycle, since bcm_enetsw_phy_poll only enables them if their current state
+is different from the stored link state.
+
+Fix this by also resetting the port link state.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2213,6 +2213,8 @@ static int bcm_enetsw_open(struct net_de
+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
+ ENETSW_PTCTRL_TXDIS_MASK,
+ ENETSW_PTCTRL_REG(i));
++
++ priv->sw_port_link[i] = 0;
+ }
+
+ /* reset mib */
diff --git a/target/linux/brcm63xx/patches-3.3/417-bcm63xx_enet-don-t-overwrite-settings-when-setting-d.patch b/target/linux/brcm63xx/patches-3.3/417-bcm63xx_enet-don-t-overwrite-settings-when-setting-d.patch
new file mode 100644
index 000000000..407c8169e
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/417-bcm63xx_enet-don-t-overwrite-settings-when-setting-d.patch
@@ -0,0 +1,20 @@
+From e79bc74f76361020d820ed4611d28f70ebd845ca Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:44:09 +0200
+Subject: [PATCH 34/84] bcm63xx_enet: don't overwrite settings when setting duplex on force
+
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2333,7 +2333,7 @@ static int bcm_enetsw_open(struct net_de
+ }
+
+ if (port->force_duplex_full)
+- override = ENETSW_IMPOV_FDX_MASK;
++ override |= ENETSW_IMPOV_FDX_MASK;
+
+
+ enetsw_writeb(priv, override, ENETSW_PORTOV_REG(i));
diff --git a/target/linux/brcm63xx/patches-3.3/418-bcm63xx_enet-store-the-number-of-ports-instead-of-ha.patch b/target/linux/brcm63xx/patches-3.3/418-bcm63xx_enet-store-the-number-of-ports-instead-of-ha.patch
new file mode 100644
index 000000000..232668b7c
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/418-bcm63xx_enet-store-the-number-of-ports-instead-of-ha.patch
@@ -0,0 +1,98 @@
+From efe31ec8fca92162fc21630611971345014a81a0 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:39:30 +0200
+Subject: [PATCH 33/84] bcm63xx_enet: store the number of ports instead of hardcoding them
+
+This will be needed for devices with a different number of ports
+---
+ arch/mips/bcm63xx/dev-enet.c | 2 ++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 2 ++
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 9 +++++----
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 1 +
+ 4 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -239,6 +239,8 @@ bcm63xx_enetsw_register(const struct bcm
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
++ enetsw_pd.num_ports = ENETSW_PORTS_6368;
++
+ ret = platform_device_register(&bcm63xx_enetsw_device);
+ if (ret)
+ return ret;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -43,6 +43,7 @@ struct bcm63xx_enet_platform_data {
+ * on board ethernet switch platform data
+ */
+ #define ENETSW_MAX_PORT 6
++#define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
+ struct bcm63xx_enetsw_port {
+ int used;
+@@ -58,6 +59,7 @@ struct bcm63xx_enetsw_port {
+
+ struct bcm63xx_enetsw_platform_data {
+ char mac_addr[ETH_ALEN];
++ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+ };
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2041,7 +2041,7 @@ static void swphy_poll_timer(unsigned lo
+ struct bcm_enet_priv *priv = (struct bcm_enet_priv *)data;
+ unsigned int i;
+
+- for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+ u8 override;
+@@ -2207,7 +2207,7 @@ static int bcm_enetsw_open(struct net_de
+ priv->rx_curr_desc = 0;
+
+ /* disable all ports */
+- for (i = 0; i < 6; i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ enetsw_writeb(priv, ENETSW_PORTOV_ENABLE_MASK,
+ ENETSW_PORTOV_REG(i));
+ enetsw_writeb(priv, ENETSW_PTCTRL_RXDIS_MASK |
+@@ -2303,7 +2303,7 @@ static int bcm_enetsw_open(struct net_de
+ /*
+ * apply override config for bypass_link ports here.
+ */
+- for (i = 0; i < ARRAY_SIZE(priv->used_ports); i++) {
++ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ u8 override;
+ port = &priv->used_ports[i];
+@@ -2447,7 +2447,7 @@ static int bcm_enetsw_phy_is_external(st
+ {
+ int i;
+
+- for (i = 0; i < (int)ARRAY_SIZE(priv->used_ports); ++i) {
++ for (i = 0; i < priv->num_ports; ++i) {
+ if (!priv->used_ports[i].used)
+ continue;
+ if (priv->used_ports[i].phy_id == phy_id)
+@@ -2735,6 +2735,7 @@ static int __devinit bcm_enetsw_probe(st
+ memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
+ memcpy(priv->used_ports, pd->used_ports,
+ sizeof (pd->used_ports));
++ priv->num_ports = pd->num_ports;
+ }
+
+ ret = compute_hw_mtu(priv, dev->mtu);
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -354,6 +354,7 @@ struct bcm_enet_priv {
+ unsigned int hw_mtu;
+
+ /* port mapping for switch devices */
++ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+ int sw_port_link[ENETSW_MAX_PORT];
+
diff --git a/target/linux/brcm63xx/patches-3.3/419-bcm63xx_enet-store-is_sw-in-a-variable-instead-of-ch.patch b/target/linux/brcm63xx/patches-3.3/419-bcm63xx_enet-store-is_sw-in-a-variable-instead-of-ch.patch
new file mode 100644
index 000000000..6f73477ab
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/419-bcm63xx_enet-store-is_sw-in-a-variable-instead-of-ch.patch
@@ -0,0 +1,73 @@
+From ef581388c45dbc48f7bbe050e87deb1e3c63a698 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 10 Jul 2012 10:52:02 +0200
+Subject: [PATCH 35/84] bcm63xx_enet: store is_sw in a variable instead of checking the cpuid
+
+Reduces the number of changes needed for making enetsw work on new
+chips.
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 7 +++++--
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 10 ++--------
+ 2 files changed, 7 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -364,7 +364,7 @@ static int bcm_enet_receive_queue(struct
+ }
+
+ /* recycle packet if it's marked as bad */
+- if (!bcm_enet_is_sw(priv) &&
++ if (!priv->enet_is_sw &&
+ unlikely(len_stat & DMADESC_ERR_MASK)) {
+ dev->stats.rx_errors++;
+
+@@ -597,7 +597,7 @@ static int bcm_enet_start_xmit(struct sk
+ }
+
+ /* pad small packets sent on a switch device */
+- if (bcm_enet_is_sw(priv) && skb->len < 64) {
++ if (priv->enet_is_sw && skb->len < 64) {
+ int needed = 64 - skb->len;
+ char *data;
+
+@@ -1700,6 +1700,8 @@ static int __devinit bcm_enet_probe(stru
+ return -ENOMEM;
+ priv = netdev_priv(dev);
+
++ priv->enet_is_sw = false;
++
+ ret = compute_hw_mtu(priv, dev->mtu);
+ if (ret)
+ goto out;
+@@ -2725,6 +2727,7 @@ static int __devinit bcm_enetsw_probe(st
+ memset(priv, 0, sizeof(*priv));
+
+ /* initialize default and fetch platform data */
++ priv->enet_is_sw = true;
+ priv->irq_rx = irq_rx;
+ priv->irq_tx = irq_tx;
+ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -353,6 +353,8 @@ struct bcm_enet_priv {
+ /* maximum hardware transmit/receive size */
+ unsigned int hw_mtu;
+
++ bool enet_is_sw;
++
+ /* port mapping for switch devices */
+ int num_ports;
+ struct bcm63xx_enetsw_port used_ports[ENETSW_MAX_PORT];
+@@ -363,12 +365,4 @@ struct bcm_enet_priv {
+ spinlock_t enetsw_mdio_lock;
+ };
+
+-static inline int bcm_enet_is_sw(struct bcm_enet_priv *priv)
+-{
+- if (BCMCPU_IS_6368())
+- return 1;
+- else
+- return 0;
+-}
+-
+ #endif /* ! BCM63XX_ENET_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/420-BCM63XX-allow-enetsw-without-tx-irq.patch b/target/linux/brcm63xx/patches-3.3/420-BCM63XX-allow-enetsw-without-tx-irq.patch
new file mode 100644
index 000000000..6396b626d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/420-BCM63XX-allow-enetsw-without-tx-irq.patch
@@ -0,0 +1,69 @@
+From 625894c377ba266c0044675b53f05d65db6355b6 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 8 Jul 2012 13:07:52 +0200
+Subject: [PATCH 38/84] BCM63XX: allow enetsw without tx irq
+
+---
+ arch/mips/bcm63xx/dev-enet.c | 2 ++
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 18 +++++++++++-------
+ 2 files changed, 13 insertions(+), 7 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -236,6 +236,8 @@ bcm63xx_enetsw_register(const struct bcm
+ enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
+ enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
+ enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
++ if (!enetsw_res[2].start)
++ enetsw_res[2].start = -1;
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2151,10 +2151,12 @@ static int bcm_enetsw_open(struct net_de
+ if (ret)
+ goto out_freeirq;
+
+- ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
+- IRQF_DISABLED, dev->name, dev);
+- if (ret)
+- goto out_freeirq_rx;
++ if (priv->irq_tx != -1) {
++ ret = request_irq(priv->irq_tx, bcm_enet_isr_dma,
++ IRQF_DISABLED, dev->name, dev);
++ if (ret)
++ goto out_freeirq_rx;
++ }
+
+ /* allocate rx dma ring */
+ size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
+@@ -2376,7 +2378,8 @@ out_free_rx_ring:
+ priv->rx_desc_cpu, priv->rx_desc_dma);
+
+ out_freeirq_tx:
+- free_irq(priv->irq_tx, dev);
++ if (priv->irq_tx != -1)
++ free_irq(priv->irq_tx, dev);
+
+ out_freeirq_rx:
+ free_irq(priv->irq_rx, dev);
+@@ -2433,7 +2436,8 @@ static int bcm_enetsw_stop(struct net_de
+ priv->rx_desc_cpu, priv->rx_desc_dma);
+ dma_free_coherent(kdev, priv->tx_desc_alloc_size,
+ priv->tx_desc_cpu, priv->tx_desc_dma);
+- free_irq(priv->irq_tx, dev);
++ if (priv->irq_tx != -1)
++ free_irq(priv->irq_tx, dev);
+ free_irq(priv->irq_rx, dev);
+
+ return 0;
+@@ -2716,7 +2720,7 @@ static int __devinit bcm_enetsw_probe(st
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq_rx = platform_get_irq(pdev, 0);
+ irq_tx = platform_get_irq(pdev, 1);
+- if (!res_mem || irq_rx < 0 || irq_tx < 0)
++ if (!res_mem || irq_rx < 0)
+ return -ENODEV;
+
+ ret = 0;
diff --git a/target/linux/brcm63xx/patches-3.3/421-BCM63XX-use-port-id-for-deciding-external-phy.patch b/target/linux/brcm63xx/patches-3.3/421-BCM63XX-use-port-id-for-deciding-external-phy.patch
new file mode 100644
index 000000000..da7013d8f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/421-BCM63XX-use-port-id-for-deciding-external-phy.patch
@@ -0,0 +1,87 @@
+From 85e4551e033df7cb043e93042661fc1e58799efa Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 8 Jul 2012 15:36:23 +0200
+Subject: [PATCH 52/84] BCM63XX: use port id for deciding external phy
+
+Ports 0-3 always use the internal phy, while 4+ always need an external
+phy to work.
+---
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 3 ++-
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 15 ++++++++-------
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 5 +++++
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -45,9 +45,10 @@ struct bcm63xx_enet_platform_data {
+ #define ENETSW_MAX_PORT 6
+ #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
++#define ENETSW_RGMII_PORT0 4
++
+ struct bcm63xx_enetsw_port {
+ int used;
+- int external_phy;
+ int phy_id;
+
+ int bypass_link;
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2046,6 +2046,7 @@ static void swphy_poll_timer(unsigned lo
+ for (i = 0; i < priv->num_ports; i++) {
+ struct bcm63xx_enetsw_port *port;
+ int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
++ int external_phy = bcm_enet_port_is_rgmii(i);
+ u8 override;
+
+ port = &priv->used_ports[i];
+@@ -2057,7 +2058,7 @@ static void swphy_poll_timer(unsigned lo
+
+ /* dummy read to clear */
+ for (j = 0; j < 2; j++)
+- val = bcmenet_sw_mdio_read(priv, port->external_phy,
++ val = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_BMSR);
+
+ if (val == 0xffff)
+@@ -2081,14 +2082,14 @@ static void swphy_poll_timer(unsigned lo
+ continue;
+ }
+
+- advertise = bcmenet_sw_mdio_read(priv, port->external_phy,
++ advertise = bcmenet_sw_mdio_read(priv, external_phy,
+ port->phy_id, MII_ADVERTISE);
+
+- lpa = bcmenet_sw_mdio_read(priv, port->external_phy,
+- port->phy_id, MII_LPA);
++ lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
++ MII_LPA);
+
+- lpa2 = bcmenet_sw_mdio_read(priv, port->external_phy,
+- port->phy_id, MII_STAT1000);
++ lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
++ MII_STAT1000);
+
+ /* figure out media and duplex from advertise and LPA values */
+ media = mii_nway_result(lpa & advertise);
+@@ -2457,7 +2458,7 @@ static int bcm_enetsw_phy_is_external(st
+ if (!priv->used_ports[i].used)
+ continue;
+ if (priv->used_ports[i].phy_id == phy_id)
+- return priv->used_ports[i].external_phy;
++ return bcm_enet_port_is_rgmii(i);
+ }
+
+ printk_once(KERN_WARNING "bcm63xx_enet: could not find a used port "
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -365,4 +365,9 @@ struct bcm_enet_priv {
+ spinlock_t enetsw_mdio_lock;
+ };
+
++static inline int bcm_enet_port_is_rgmii(int portid)
++{
++ return portid >= ENETSW_RGMII_PORT0;
++}
++
+ #endif /* ! BCM63XX_ENET_H_ */
diff --git a/target/linux/brcm63xx/patches-3.3/422-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch b/target/linux/brcm63xx/patches-3.3/422-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
new file mode 100644
index 000000000..7d1f3f3f8
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/422-bcm63xx_enet-enable-rgmii-clock-on-external-ports.patch
@@ -0,0 +1,53 @@
+From d8237d704fc25eb2fc25ef4403608b78c6a6d4be Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 15 Jul 2012 20:08:57 +0200
+Subject: [PATCH 54/81] bcm63xx_enet: enable rgmii clock on external ports
+
+---
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 13 +++++++++++++
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 12 ++++++++++++
+ 2 files changed, 25 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -838,6 +838,19 @@
+ #define ENETSW_PORTOV_FDX_MASK (1 << 1)
+ #define ENETSW_PORTOV_LINKUP_MASK (1 << 0)
+
++/* Port RGMII control register */
++#define ENETSW_RGMII_CTRL_REG(x) (0x60 + (x))
++#define ENETSW_RGMII_CTRL_GMII_CLK_EN (1 << 7)
++#define ENETSW_RGMII_CTRL_MII_OVERRIDE_EN (1 << 6)
++#define ENETSW_RGMII_CTRL_MII_MODE_MASK (3 << 4)
++#define ENETSW_RGMII_CTRL_RGMII_MODE (0 << 4)
++#define ENETSW_RGMII_CTRL_MII_MODE (1 << 4)
++#define ENETSW_RGMII_CTRL_RVMII_MODE (2 << 4)
++#define ENETSW_RGMII_CTRL_TIMING_SEL_EN (1 << 0)
++
++/* Port RGMII timing register */
++#define ENETSW_RGMII_TIMING_REG(x) (0x68 + (x))
++
+ /* MDIO control register */
+ #define ENETSW_MDIOC_REG (0xb0)
+ #define ENETSW_MDIOC_EXT_MASK (1 << 16)
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -2222,6 +2222,18 @@ static int bcm_enetsw_open(struct net_de
+ priv->sw_port_link[i] = 0;
+ }
+
++ /* enable external ports */
++ for (i = ENETSW_RGMII_PORT0; i < priv->num_ports; i++) {
++ u8 rgmii_ctrl;
++
++ if (!priv->used_ports[i].used)
++ continue;
++
++ rgmii_ctrl = enetsw_readb(priv, ENETSW_RGMII_CTRL_REG(i));
++ rgmii_ctrl |= ENETSW_RGMII_CTRL_GMII_CLK_EN;
++ enetsw_writeb(priv, rgmii_ctrl, ENETSW_RGMII_CTRL_REG(i));
++ }
++
+ /* reset mib */
+ val = enetsw_readb(priv, ENETSW_GMCR_REG);
+ val |= ENETSW_GMCR_RST_MIB_MASK;
diff --git a/target/linux/brcm63xx/patches-3.3/423-bcm63xx_enet-fix-lockup-on-BCM6328.patch b/target/linux/brcm63xx/patches-3.3/423-bcm63xx_enet-fix-lockup-on-BCM6328.patch
new file mode 100644
index 000000000..4306ce753
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/423-bcm63xx_enet-fix-lockup-on-BCM6328.patch
@@ -0,0 +1,93 @@
+From 382a0b0dc4cbd0e0fbfd6c2d132e972c3d1245b0 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 13 Nov 2011 14:59:37 +0100
+Subject: [PATCH 39/84] bcm63xx_enet: fix lockup on BCM6328
+
+BCM6328 locks up on a maxburst size of 16, reduce it to 8 for BCM6328 and
+BCM6368.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bcm63xx_enet.c | 13 +++++++------
+ drivers/net/ethernet/broadcom/bcm63xx_enet.h | 4 ++++
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+@@ -261,7 +261,6 @@ static int bcm_enet_refill_rx(struct net
+ if (!skb)
+ break;
+ priv->rx_skb[desc_idx] = skb;
+-
+ p = dma_map_single(&priv->pdev->dev, skb->data,
+ priv->rx_skb_size,
+ DMA_FROM_DEVICE);
+@@ -995,9 +994,9 @@ static int bcm_enet_open(struct net_devi
+ enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
+
+ /* set dma maximum burst len */
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
+
+ /* set correct transmit fifo watermark */
+@@ -1593,7 +1592,7 @@ static int compute_hw_mtu(struct bcm_ene
+ * it's appended
+ */
+ priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
+- BCMENET_DMA_MAXBURST * 4);
++ priv->dma_maxburst * 4);
+ return 0;
+ }
+
+@@ -1701,6 +1700,7 @@ static int __devinit bcm_enet_probe(stru
+ priv = netdev_priv(dev);
+
+ priv->enet_is_sw = false;
++ priv->dma_maxburst = BCMENET_DMA_MAXBURST;
+
+ ret = compute_hw_mtu(priv, dev->mtu);
+ if (ret)
+@@ -2282,9 +2282,9 @@ static int bcm_enetsw_open(struct net_de
+ enet_dmas_writel(priv, 0, ENETDMAS_SRAM4_REG(priv->tx_chan));
+
+ /* set dma maximum burst len */
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->rx_chan));
+- enet_dmac_writel(priv, BCMENET_DMA_MAXBURST,
++ enet_dmac_writel(priv, priv->dma_maxburst,
+ ENETDMAC_MAXBURST_REG(priv->tx_chan));
+
+ /* set flow control low/high threshold to 1/3 / 2/3 */
+@@ -2749,6 +2749,7 @@ static int __devinit bcm_enetsw_probe(st
+ priv->irq_tx = irq_tx;
+ priv->rx_ring_size = BCMENET_DEF_RX_DESC;
+ priv->tx_ring_size = BCMENET_DEF_TX_DESC;
++ priv->dma_maxburst = BCMENETSW_DMA_MAXBURST;
+
+ pd = pdev->dev.platform_data;
+ if (pd) {
+--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.h
++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.h
+@@ -17,6 +17,7 @@
+
+ /* maximum burst len for dma (4 bytes unit) */
+ #define BCMENET_DMA_MAXBURST 16
++#define BCMENETSW_DMA_MAXBURST 8
+
+ /* tx transmit threshold (4 bytes unit), fifo is 256 bytes, the value
+ * must be low enough so that a DMA transfer of above burst length can
+@@ -280,6 +281,9 @@ struct bcm_enet_priv {
+ /* number of dma desc in tx ring */
+ int tx_ring_size;
+
++ /* maximum dma burst size */
++ int dma_maxburst;
++
+ /* cpu view of rx dma ring */
+ struct bcm_enet_desc *tx_desc_cpu;
+
diff --git a/target/linux/brcm63xx/patches-3.3/424-MIPS-BCM63XX-add-support-for-BCM6328-in-bcm_enetsw.patch b/target/linux/brcm63xx/patches-3.3/424-MIPS-BCM63XX-add-support-for-BCM6328-in-bcm_enetsw.patch
new file mode 100644
index 000000000..e665249c5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/424-MIPS-BCM63XX-add-support-for-BCM6328-in-bcm_enetsw.patch
@@ -0,0 +1,103 @@
+From f1c1bfa89cdac76a215d0e21161da9f8f8373437 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 14 Jun 2011 21:14:39 +0200
+Subject: [PATCH 40/84] MIPS: BCM63XX: add support for BCM6328 in bcm_enetsw
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/clk.c | 34 ++++++++++++++-----
+ arch/mips/bcm63xx/dev-enet.c | 9 +++--
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 1 +
+ 3 files changed, 32 insertions(+), 12 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -118,21 +118,37 @@ static struct clk clk_ephy = {
+ */
+ static void enetsw_set(struct clk *clk, int enable)
+ {
+- if (!BCMCPU_IS_6368())
++ u32 mask;
++
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
+ return;
+- bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
+- CKCTL_6368_SWPKT_USB_EN |
+- CKCTL_6368_SWPKT_SAR_EN, enable);
++
++ if (BCMCPU_IS_6328())
++ mask = CKCTL_6328_ROBOSW_EN;
++ else
++ mask = CKCTL_6368_ROBOSW_EN | CKCTL_6368_SWPKT_USB_EN |
++ CKCTL_6368_SWPKT_SAR_EN;
++
++ bcm_hwclock_set(mask, enable);
+ if (enable) {
++ u32 reg;
+ u32 val;
+
++ if (BCMCPU_IS_6328()) {
++ reg = PERF_SOFTRESET_6328_REG;
++ mask = SOFTRESET_6328_ENETSW_MASK;
++ } else {
++ reg = PERF_SOFTRESET_6368_REG;
++ mask = SOFTRESET_6368_ENETSW_MASK;
++ }
++
+ /* reset switch core afer clock change */
+- val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
+- val &= ~SOFTRESET_6368_ENETSW_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
++ val = bcm_perf_readl(reg);
++ val &= ~mask;
++ bcm_perf_writel(val, reg);
+ msleep(10);
+- val |= SOFTRESET_6368_ENETSW_MASK;
+- bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
++ val |= mask;
++ bcm_perf_writel(val, reg);
+ msleep(10);
+ }
+ }
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -141,7 +141,7 @@ static int __init register_shared(void)
+ shared_res[0].end = shared_res[0].start;
+ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+
+- if (BCMCPU_IS_6368())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6368())
+ chan_count = 32;
+ else
+ chan_count = 16;
+@@ -224,7 +224,7 @@ bcm63xx_enetsw_register(const struct bcm
+ {
+ int ret;
+
+- if (!BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
+ return -ENODEV;
+
+ ret = register_shared();
+@@ -241,7 +241,10 @@ bcm63xx_enetsw_register(const struct bcm
+
+ memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof (*pd));
+
+- enetsw_pd.num_ports = ENETSW_PORTS_6368;
++ if (BCMCPU_IS_6328())
++ enetsw_pd.num_ports = ENETSW_PORTS_6328;
++ else if (BCMCPU_IS_6368())
++ enetsw_pd.num_ports = ENETSW_PORTS_6368;
+
+ ret = platform_device_register(&bcm63xx_enetsw_device);
+ if (ret)
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -43,6 +43,7 @@ struct bcm63xx_enet_platform_data {
+ * on board ethernet switch platform data
+ */
+ #define ENETSW_MAX_PORT 6
++#define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */
+ #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
+ #define ENETSW_RGMII_PORT0 4
diff --git a/target/linux/brcm63xx/patches-3.3/425-MIPS-BCM63XX-add-HS-SPI-platform-device-and-register.patch b/target/linux/brcm63xx/patches-3.3/425-MIPS-BCM63XX-add-HS-SPI-platform-device-and-register.patch
new file mode 100644
index 000000000..5b2534467
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/425-MIPS-BCM63XX-add-HS-SPI-platform-device-and-register.patch
@@ -0,0 +1,128 @@
+From 56be5a2d7e08faa7bb306faaf352ac4e6ac52c01 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:18:26 +0100
+Subject: [PATCH 26/60] MIPS: BCM63XX: add HS SPI platform device and register it
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Makefile | 5 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +
+ arch/mips/bcm63xx/dev-hsspi.c | 57 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 20 +++++++
+ 4 files changed, 82 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/dev-hsspi.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,7 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
+- dev-spi.o dev-uart.o dev-usb-ehci.o dev-usb-ohci.o dev-wdt.o
++ dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
++ dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
++ dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -25,6 +25,7 @@
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
+ #include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
+ #include <bcm63xx_dev_pcmcia.h>
+ #include <bcm63xx_dev_spi.h>
+ #include <bcm63xx_dev_usb_ohci.h>
+@@ -945,6 +946,7 @@ int __init board_register_devices(void)
+ pr_err(PFX "failed to register fallback SPROM\n");
+ }
+ #endif
++ bcm63xx_hsspi_register();
+
+ bcm63xx_spi_register();
+
+--- /dev/null
++++ b/arch/mips/bcm63xx/dev-hsspi.c
+@@ -0,0 +1,57 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_hsspi.h>
++#include <bcm63xx_regs.h>
++
++static struct resource spi_resources[] = {
++ {
++ .start = -1, /* filled at runtime */
++ .end = -1, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = -1, /* filled at runtime */
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct bcm63xx_hsspi_pdata spi_pdata = {
++ .bus_num = 0,
++};
++
++static struct platform_device bcm63xx_hsspi_device = {
++ .name = "bcm63xx-hsspi",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(spi_resources),
++ .resource = spi_resources,
++ .dev = {
++ .platform_data = &spi_pdata,
++ },
++};
++
++int __init bcm63xx_hsspi_register(void)
++{
++
++ if (!BCMCPU_IS_6328())
++ return -ENODEV;
++
++ spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
++ spi_resources[0].end = spi_resources[0].start;
++ spi_resources[0].end += RSET_HSSPI_SIZE - 1;
++ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
++
++ spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
++
++ return platform_device_register(&bcm63xx_hsspi_device);
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+@@ -0,0 +1,20 @@
++#ifndef BCM63XX_DEV_HSSPI_H
++#define BCM63XX_DEV_HSSPI_H
++
++#include <linux/types.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_regs.h>
++
++int __init bcm63xx_hsspi_register(void);
++
++struct bcm63xx_hsspi_pdata {
++ int bus_num;
++ u32 speed_hz;
++};
++
++#define bcm_hsspi_readl(o) bcm_rset_readl(RSET_HSSPI, (o))
++#define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
++
++#define HSSPI_PLL_HZ_6328 133333333
++
++#endif /* BCM63XX_DEV_HSSPI_H */
diff --git a/target/linux/brcm63xx/patches-3.3/426-SPI-MIPS-BCM63XX-Add-HS-SPI-driver.patch b/target/linux/brcm63xx/patches-3.3/426-SPI-MIPS-BCM63XX-Add-HS-SPI-driver.patch
new file mode 100644
index 000000000..739c2c60f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/426-SPI-MIPS-BCM63XX-Add-HS-SPI-driver.patch
@@ -0,0 +1,481 @@
+From 4b27423676485d05bcd6fc6f3809164fb8f9d22d Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 Nov 2011 12:19:55 +0100
+Subject: [PATCH 30/60] SPI: MIPS: BCM63XX: Add HSSPI driver
+
+Add a driver for the High Speed SPI controller found on newer BCM63XX SoCs.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 2 +
+ drivers/spi/Kconfig | 7 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-bcm63xx-hsspi.c | 427 ++++++++++++++++++++
+ 4 files changed, 437 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/spi/spi-bcm63xx-hsspi.c
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+@@ -17,4 +17,6 @@ struct bcm63xx_hsspi_pdata {
+
+ #define HSSPI_PLL_HZ_6328 133333333
+
++#define HSSPI_BUFFER_LEN 512
++
+ #endif /* BCM63XX_DEV_HSSPI_H */
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -100,6 +100,13 @@ config SPI_BCM63XX
+ help
+ Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
+
++config SPI_BCM63XX_HSSPI
++ tristate "Broadcom BCM63XX HS SPI controller driver"
++ depends on BCM63XX
++ help
++ This enables support for the High Speed SPI controller present on
++ newer Broadcom BCM63XX SoCs.
++
+ config SPI_BITBANG
+ tristate "Utilities for Bitbanging SPI masters"
+ help
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
+ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
+ obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
++obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o
+ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
+ obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
+ obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
+--- /dev/null
++++ b/drivers/spi/spi-bcm63xx-hsspi.c
+@@ -0,0 +1,427 @@
++/*
++ * Broadcom BCM63XX High Speed SPI Controller driver
++ *
++ * Copyright 2000-2010 Broadcom Corporation
++ * Copyright 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/spi/spi.h>
++#include <linux/workqueue.h>
++
++#include <bcm63xx_regs.h>
++#include <bcm63xx_dev_hsspi.h>
++
++#define HSSPI_OP_CODE_SHIFT 13
++#define HSSPI_OP_SLEEP (0 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_READ_WRITE (1 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_WRITE (2 << HSSPI_OP_CODE_SHIFT)
++#define HSSPI_OP_READ (3 << HSSPI_OP_CODE_SHIFT)
++
++#define HSSPI_MAX_PREPEND_LEN 15
++
++#define HSSPI_MAX_SYNC_CLOCK 30000000
++
++struct bcm63xx_hsspi {
++ struct completion done;
++ struct spi_transfer *curr_trans;
++
++ struct platform_device *pdev;
++ struct clk *clk;
++ void __iomem *regs;
++ u8 __iomem *fifo;
++
++ u32 speed_hz;
++ int irq;
++};
++
++static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, int hz,
++ int profile)
++{
++ u32 reg;
++
++ reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz));
++ bcm_hsspi_writel(CLK_CTRL_ACCUM_RST_ON_LOOP | reg,
++ HSSPI_PROFILE_CLK_CTRL_REG(profile));
++
++ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
++ if (hz > HSSPI_MAX_SYNC_CLOCK)
++ reg |= SIGNAL_CTRL_ASYNC_INPUT_PATH;
++ else
++ reg &= ~SIGNAL_CTRL_ASYNC_INPUT_PATH;
++ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(profile));
++}
++
++static int bcm63xx_hsspi_do_txrx(struct spi_device *spi,
++ struct spi_transfer *t1,
++ struct spi_transfer *t2)
++{
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master);
++ u8 chip_select = spi->chip_select;
++ u16 opcode = 0;
++ int len, prepend_size = 0;
++
++ init_completion(&bs->done);
++
++ bs->curr_trans = t2 ? t2 : t1;
++ bcm63xx_hsspi_set_clk(bs, bs->curr_trans->speed_hz, chip_select);
++
++ if (t2 && !t2->tx_buf)
++ prepend_size = t1->len;
++
++ bcm_hsspi_writel(prepend_size << MODE_CTRL_PREPENDBYTE_CNT_SHIFT |
++ 2 << MODE_CTRL_MULTIDATA_WR_STRT_SHIFT |
++ 2 << MODE_CTRL_MULTIDATA_RD_STRT_SHIFT | 0xff,
++ HSSPI_PROFILE_MODE_CTRL_REG(chip_select));
++
++ if (t1->rx_buf && t1->tx_buf)
++ opcode = HSSPI_OP_READ_WRITE;
++ else if (t1->rx_buf || (t2 && t2->rx_buf))
++ opcode = HSSPI_OP_READ;
++ else if (t1->tx_buf)
++ opcode = HSSPI_OP_WRITE;
++
++ if (opcode == HSSPI_OP_READ && t2)
++ len = t2->len;
++ else
++ len = t1->len;
++
++ if (t1->tx_buf) {
++ memcpy_toio(bs->fifo + 2, t1->tx_buf, t1->len);
++ if (t2 && t2->tx_buf) {
++ memcpy_toio(bs->fifo + 2 + t1->len,
++ t2->tx_buf, t2->len);
++ len += t2->len;
++ }
++ }
++
++ opcode |= len;
++ memcpy_toio(bs->fifo, &opcode, sizeof(opcode));
++
++ /* enable interrupt */
++ bcm_hsspi_writel(HSSPI_PING0_CMD_DONE, HSSPI_INT_MASK_REG);
++
++ /* start the transfer */
++ bcm_hsspi_writel(chip_select << PINGPONG_CMD_SS_SHIFT |
++ chip_select << PINGPONG_CMD_PROFILE_SHIFT |
++ PINGPONG_COMMAND_START_NOW,
++ HSSPI_PINGPONG_COMMAND_REG(0));
++
++ if (wait_for_completion_timeout(&bs->done, HZ) == 0) {
++ dev_err(&bs->pdev->dev, "transfer timed out!\n");
++ return -ETIMEDOUT;
++ }
++
++ return t1->len + (t2 ? t2->len : 0);
++}
++
++static int bcm63xx_hsspi_setup(struct spi_device *spi)
++{
++ u32 reg;
++
++ if (spi->bits_per_word != 8)
++ return -EINVAL;
++
++ if (spi->max_speed_hz == 0)
++ return -EINVAL;
++
++ reg = bcm_hsspi_readl(HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
++ reg &= ~(SIGNAL_CTRL_LAUNCH_RISING | SIGNAL_CTRL_LATCH_RISING);
++ if (spi->mode & SPI_CPHA)
++ reg |= SIGNAL_CTRL_LAUNCH_RISING;
++ else
++ reg |= SIGNAL_CTRL_LATCH_RISING;
++ bcm_hsspi_writel(reg, HSSPI_PROFILE_SIGNAL_CTRL_REG(spi->chip_select));
++
++ return 0;
++}
++
++static int bcm63xx_hsspi_transfer_one(struct spi_master *master,
++ struct spi_message *msg)
++{
++ struct spi_transfer *t, *prev = NULL;
++ struct spi_device *spi = msg->spi;
++ u32 reg;
++ int ret = -EINVAL;
++ int len = 0;
++
++ /* check if we are able to make these transfers */
++ list_for_each_entry(t, &msg->transfers, transfer_list) {
++ if (!t->tx_buf && !t->rx_buf)
++ goto out;
++
++ if (t->speed_hz == 0)
++ t->speed_hz = spi->max_speed_hz;
++
++ if (t->speed_hz > spi->max_speed_hz)
++ goto out;
++
++ if (t->len > HSSPI_BUFFER_LEN)
++ goto out;
++
++ /*
++ * This controller does not support keeping the chip select
++ * active between transfers.
++ * This logic currently supports combining:
++ * write then read with no cs_change (e.g. m25p80 RDSR)
++ * write then write with no cs_change (e.g. m25p80 PP)
++ */
++ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
++ /*
++ * reject if we have to combine two tx transfers and
++ * their combined length is bigger than the buffer
++ */
++ if (prev->tx_buf && t->tx_buf &&
++ (prev->len + t->len) > HSSPI_BUFFER_LEN)
++ goto out;
++ /*
++ * reject if we need write more than 15 bytes in read
++ * then write.
++ */
++ if (prev->tx_buf && t->rx_buf &&
++ prev->len > HSSPI_MAX_PREPEND_LEN)
++ goto out;
++ }
++
++ }
++
++ /* setup clock polarity */
++ reg = bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG);
++ reg &= ~GLOBAL_CTRL_CLK_POLARITY;
++ if (spi->mode & SPI_CPOL)
++ reg |= GLOBAL_CTRL_CLK_POLARITY;
++ bcm_hsspi_writel(reg, HSSPI_GLOBAL_CTRL_REG);
++
++ list_for_each_entry(t, &msg->transfers, transfer_list) {
++ if (prev && prev->tx_buf && !prev->cs_change && !t->cs_change) {
++ /* combine write with following transfer */
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, t);
++ if (ret < 0)
++ goto out;
++
++ len += ret;
++ prev = NULL;
++ continue;
++ }
++
++ /* write the previous pending transfer */
++ if (prev != NULL) {
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
++ if (ret < 0)
++ goto out;
++
++ len += ret;
++ }
++
++ prev = t;
++ }
++
++ /* do last pending transfer */
++ if (prev != NULL) {
++ ret = bcm63xx_hsspi_do_txrx(msg->spi, prev, NULL);
++ if (ret < 0)
++ goto out;
++ len += ret;
++ }
++
++ msg->actual_length = len;
++ ret = 0;
++out:
++ msg->status = ret;
++ spi_finalize_current_message(master);
++ return 0;
++}
++
++static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id)
++{
++ struct spi_master *master = (struct spi_master *)dev_id;
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ if (bcm_hsspi_readl(HSSPI_INT_STATUS_MASKED_REG) == 0)
++ return IRQ_NONE;
++
++ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++
++ if (bs->curr_trans && bs->curr_trans->rx_buf)
++ memcpy_fromio(bs->curr_trans->rx_buf, bs->fifo,
++ bs->curr_trans->len);
++ complete(&bs->done);
++
++ return IRQ_HANDLED;
++}
++
++static int __devinit bcm63xx_hsspi_probe(struct platform_device *pdev)
++{
++
++ struct spi_master *master;
++ struct bcm63xx_hsspi *bs;
++ struct resource *res_mem;
++ void __iomem *regs;
++ struct device *dev = &pdev->dev;
++ struct bcm63xx_hsspi_pdata *pdata = pdev->dev.platform_data;
++ struct clk *clk;
++ int irq;
++ int ret;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(dev, "no irq\n");
++ return -ENXIO;
++ }
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ regs = devm_request_and_ioremap(dev, res_mem);
++ if (!regs) {
++ dev_err(dev, "unable to ioremap regs\n");
++ return -ENXIO;
++ }
++
++ clk = clk_get(dev, "hsspi");
++
++ if (IS_ERR(clk)) {
++ ret = PTR_ERR(clk);
++ goto out_release;
++ }
++
++ clk_prepare_enable(clk);
++
++ master = spi_alloc_master(&pdev->dev, sizeof(*bs));
++ if (!master) {
++ ret = -ENOMEM;
++ goto out_disable_clk;
++ }
++
++ bs = spi_master_get_devdata(master);
++ bs->pdev = pdev;
++ bs->clk = clk;
++ bs->regs = regs;
++
++ master->bus_num = pdata->bus_num;
++ master->num_chipselect = 8;
++ master->setup = bcm63xx_hsspi_setup;
++ master->transfer_one_message = bcm63xx_hsspi_transfer_one;
++ master->mode_bits = SPI_CPOL | SPI_CPHA;
++
++ bs->speed_hz = pdata->speed_hz;
++ bs->fifo = (u8 __iomem *)(bs->regs + HSSPI_FIFO_REG(0));
++
++ platform_set_drvdata(pdev, master);
++
++ bs->curr_trans = NULL;
++
++ /* Initialize the hardware */
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++
++ /* clean up any pending interrupts */
++ bcm_hsspi_writel(HSSPI_INT_CLEAR_ALL, HSSPI_INT_STATUS_REG);
++
++ bcm_hsspi_writel(bcm_hsspi_readl(HSSPI_GLOBAL_CTRL_REG) |
++ GLOBAL_CTRL_CLK_GATE_SSOFF,
++ HSSPI_GLOBAL_CTRL_REG);
++
++ ret = devm_request_irq(dev, irq, bcm63xx_hsspi_interrupt, IRQF_SHARED,
++ pdev->name, master);
++
++ if (ret)
++ goto out_put_master;
++
++ /* register and we are done */
++ ret = spi_register_master(master);
++ if (ret)
++ goto out_free_irq;
++
++ return 0;
++
++out_free_irq:
++ devm_free_irq(dev, bs->irq, master);
++out_put_master:
++ spi_master_put(master);
++out_disable_clk:
++ clk_disable_unprepare(clk);
++ clk_put(clk);
++out_release:
++ devm_ioremap_release(dev, regs);
++
++ return ret;
++}
++
++
++static int __exit bcm63xx_hsspi_remove(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ spi_unregister_master(master);
++
++ /* reset the hardware and block queue progress */
++ bcm_hsspi_writel(0, HSSPI_INT_MASK_REG);
++ clk_disable_unprepare(bs->clk);
++ clk_put(bs->clk);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int bcm63xx_hsspi_suspend(struct platform_device *pdev,
++ pm_message_t mesg)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ spi_master_suspend(master);
++ clk_disable(bs->clk);
++
++ return 0;
++}
++
++static int bcm63xx_hsspi_resume(struct platform_device *pdev)
++{
++ struct spi_master *master = platform_get_drvdata(pdev);
++ struct bcm63xx_hsspi *bs = spi_master_get_devdata(master);
++
++ clk_enable(bs->clk);
++ spi_master_resume(master);
++
++ return 0;
++}
++
++static const struct dev_pm_ops bcm63xx_hsspi_pm_ops = {
++ .suspend = bcm63xx_hsspi_suspend,
++ .resume = bcm63xx_hsspi_resume,
++};
++
++#define BCM63XX_HSSPI_PM_OPS (&bcm63xx_hsspi_pm_ops)
++#else
++#define BCM63XX_HSSPI_PM_OPS NULL
++#endif
++
++
++
++static struct platform_driver bcm63xx_hsspi_driver = {
++ .driver = {
++ .name = "bcm63xx-hsspi",
++ .owner = THIS_MODULE,
++ .pm = BCM63XX_HSSPI_PM_OPS,
++ },
++ .probe = bcm63xx_hsspi_probe,
++ .remove = __exit_p(bcm63xx_hsspi_remove),
++};
++
++module_platform_driver(bcm63xx_hsspi_driver);
++
++MODULE_ALIAS("platform:bcm63xx_hsspi");
++MODULE_DESCRIPTION("Broadcom BCM63xx HS SPI Controller driver");
++MODULE_AUTHOR("Jonas Gorski <jonas.gorski@gmail.com>");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/brcm63xx/patches-3.3/427-MIPS-BCM63XX-Register-SPI-flash-if-present.patch b/target/linux/brcm63xx/patches-3.3/427-MIPS-BCM63XX-Register-SPI-flash-if-present.patch
new file mode 100644
index 000000000..14776af76
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/427-MIPS-BCM63XX-Register-SPI-flash-if-present.patch
@@ -0,0 +1,102 @@
+From d135d94b3d1fe599d13e7198d5f502912d694c13 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 3 Jul 2011 15:00:38 +0200
+Subject: [PATCH 29/60] MIPS: BCM63XX: Register SPI flash if present
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/dev-flash.c | 33 +++++++++++++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +
+ 2 files changed, 33 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -16,9 +16,12 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+ #include <linux/mtd/physmap.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
+
+ #include <bcm63xx_cpu.h>
+ #include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
+ #include <bcm63xx_regs.h>
+ #include <bcm63xx_io.h>
+
+@@ -55,6 +58,21 @@ static struct platform_device mtd_dev =
+ },
+ };
+
++static struct flash_platform_data bcm63xx_flash_data = {
++ .part_probe_types = bcm63xx_part_types,
++};
++
++static struct spi_board_info bcm63xx_spi_flash_info[] = {
++ {
++ .bus_num = 0,
++ .chip_select = 0,
++ .mode = 0,
++ .max_speed_hz = 781000,
++ .modalias = "m25p80",
++ .platform_data = &bcm63xx_flash_data,
++ },
++};
++
+ static int __init bcm63xx_detect_flash_type(void)
+ {
+ u32 val;
+@@ -62,6 +80,11 @@ static int __init bcm63xx_detect_flash_t
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6328_CPU_ID:
+ val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
++ if (val & STRAPBUS_6328_HSSPI_CLK_FAST)
++ bcm63xx_spi_flash_info[0].max_speed_hz = 33333334;
++ else
++ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
++
+ if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
+ return BCM63XX_FLASH_TYPE_SERIAL;
+ else
+@@ -79,6 +102,9 @@ static int __init bcm63xx_detect_flash_t
+ return BCM63XX_FLASH_TYPE_SERIAL;
+ case BCM6368_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
++ if (val & STRAPBUS_6368_SPI_CLK_FAST)
++ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
++
+ switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
+ case STRAPBUS_6368_BOOT_SEL_NAND:
+ return BCM63XX_FLASH_TYPE_NAND;
+@@ -110,8 +136,11 @@ int __init bcm63xx_flash_register(void)
+
+ return platform_device_register(&mtd_dev);
+ case BCM63XX_FLASH_TYPE_SERIAL:
+- pr_warn("unsupported serial flash detected\n");
+- return -ENODEV;
++ if (BCMCPU_IS_6328())
++ bcm63xx_flash_data.max_transfer_len = HSSPI_BUFFER_LEN;
++
++ return spi_register_board_info(bcm63xx_spi_flash_info,
++ ARRAY_SIZE(bcm63xx_spi_flash_info));
+ case BCM63XX_FLASH_TYPE_NAND:
+ pr_warn("unsupported NAND flash detected\n");
+ return -ENODEV;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -614,6 +614,7 @@
+ #define GPIO_STRAPBUS_REG 0x40
+ #define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
+ #define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
++#define STRAPBUS_6368_SPI_CLK_FAST (1 << 6)
+ #define STRAPBUS_6368_BOOT_SEL_MASK 0x3
+ #define STRAPBUS_6368_BOOT_SEL_NAND 0
+ #define STRAPBUS_6368_BOOT_SEL_SERIAL 1
+@@ -1308,6 +1309,7 @@
+ #define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15)
+
+ #define MISC_STRAPBUS_6328_REG 0x240
++#define STRAPBUS_6328_HSSPI_CLK_FAST (1 << 4)
+ #define STRAPBUS_6328_FCVO_SHIFT 7
+ #define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
+ #define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
diff --git a/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-add-flash-detection-for-BCM6362.patch b/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-add-flash-detection-for-BCM6362.patch
new file mode 100644
index 000000000..98a229b1a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-add-flash-detection-for-BCM6362.patch
@@ -0,0 +1,50 @@
+From d9666553a10ea85ea64e3e8784a42167a1709ed5 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 21 Nov 2011 00:48:52 +0100
+Subject: [PATCH 55/84] MIPS: BCM63XX: add flash detection for BCM6362
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/dev-flash.c | 13 ++++++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 1 +
+ 2 files changed, 13 insertions(+), 1 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -100,6 +100,17 @@ static int __init bcm63xx_detect_flash_t
+ return BCM63XX_FLASH_TYPE_PARALLEL;
+ else
+ return BCM63XX_FLASH_TYPE_SERIAL;
++ case BCM6362_CPU_ID:
++ val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
++ if (val & STRAPBUS_6362_HSSPI_CLK_FAST)
++ bcm63xx_spi_flash_info[0].max_speed_hz = 50000000;
++ else
++ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
++
++ if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
++ return BCM63XX_FLASH_TYPE_SERIAL;
++ else
++ return BCM63XX_FLASH_TYPE_NAND;
+ case BCM6368_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6368_SPI_CLK_FAST)
+@@ -136,7 +147,7 @@ int __init bcm63xx_flash_register(void)
+
+ return platform_device_register(&mtd_dev);
+ case BCM63XX_FLASH_TYPE_SERIAL:
+- if (BCMCPU_IS_6328())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6362())
+ bcm63xx_flash_data.max_transfer_len = HSSPI_BUFFER_LEN;
+
+ return spi_register_board_info(bcm63xx_spi_flash_info,
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -1304,6 +1304,7 @@
+
+ #define MISC_STRAPBUS_6362_REG 0x14
+ #define STRAPBUS_6362_FCVO_SHIFT 1
++#define STRAPBUS_6362_HSSPI_CLK_FAST (1 << 13)
+ #define STRAPBUS_6362_FCVO_MASK (0x1f << STRAPBUS_6362_FCVO_SHIFT)
+ #define STRAPBUS_6362_BOOT_SEL_SERIAL (1 << 15)
+ #define STRAPBUS_6362_BOOT_SEL_NAND (0 << 15)
diff --git a/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-move-nvram-related-functions-into-their.patch b/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-move-nvram-related-functions-into-their.patch
new file mode 100644
index 000000000..ff2a831d8
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/428-MIPS-BCM63XX-move-nvram-related-functions-into-their.patch
@@ -0,0 +1,351 @@
+From 5b753c1d01c6af23d7d37d37d9de30da8a971084 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 May 2012 22:51:08 +0200
+Subject: [PATCH 60/79] MIPS: BCM63XX: move nvram related functions into their
+ own file
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Makefile | 6 +-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 74 +++--------------
+ arch/mips/bcm63xx/nvram.c | 84 ++++++++++++++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 34 ++++++++
+ .../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 17 ----
+ 5 files changed, 134 insertions(+), 81 deletions(-)
+ create mode 100644 arch/mips/bcm63xx/nvram.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,6 +1,6 @@
+-obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
+- dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o dev-pcmcia.o \
+- dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
++obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
++ timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
++ dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
+ dev-usb-ohci.o dev-wdt.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -21,6 +21,7 @@
+ #include <bcm63xx_dev_uart.h>
+ #include <bcm63xx_regs.h>
+ #include <bcm63xx_io.h>
++#include <bcm63xx_nvram.h>
+ #include <bcm63xx_dev_pci.h>
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
+@@ -41,8 +42,6 @@
+ #define CFE_OFFSET_64K 0x10000
+ #define CFE_OFFSET_128K 0x20000
+
+-static struct bcm963xx_nvram nvram;
+-static unsigned int mac_addr_used;
+ static struct board_info board;
+
+ /*
+@@ -696,50 +695,16 @@ const char *board_get_name(void)
+ return board.name;
+ }
+
+-/*
+- * register & return a new board mac address
+- */
+-static int board_get_mac_address(u8 *mac)
+-{
+- u8 *p;
+- int count;
+-
+- if (mac_addr_used >= nvram.mac_addr_count) {
+- printk(KERN_ERR PFX "not enough mac address\n");
+- return -ENODEV;
+- }
+-
+- memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
+- p = mac + ETH_ALEN - 1;
+- count = mac_addr_used;
+-
+- while (count--) {
+- do {
+- (*p)++;
+- if (*p != 0)
+- break;
+- p--;
+- } while (p != mac);
+- }
+-
+- if (p == mac) {
+- printk(KERN_ERR PFX "unable to fetch mac address\n");
+- return -ENODEV;
+- }
+-
+- mac_addr_used++;
+- return 0;
+-}
+-
+ static void __init boardid_fixup(u8 *boot_addr)
+ {
+ struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
++ char *board_name = (char *)bcm63xx_nvram_get_name();
+
+ /* check if bcm_tag is at 64k offset */
+- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* else try 128k */
+ tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_128K);
+- if (strncmp(nvram.name, tag->boardid, BOARDID_LEN) != 0) {
++ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* No tag found */
+ printk(KERN_DEBUG "No bcm_tag found!\n");
+ return;
+@@ -749,9 +714,9 @@ static void __init boardid_fixup(u8 *boo
+ if (tag->information1[0] != '+')
+ return;
+
+- strncpy(nvram.name, &tag->information1[1], BOARDID_LEN);
++ strncpy(board_name, &tag->information1[1], BOARDID_LEN);
+
+- printk(KERN_INFO "Overriding boardid with '%s'\n", nvram.name);
++ printk(KERN_INFO "Overriding boardid with '%s'\n", board_name);
+ }
+
+ /*
+@@ -759,9 +724,10 @@ static void __init boardid_fixup(u8 *boo
+ */
+ void __init board_prom_init(void)
+ {
+- unsigned int check_len, i;
+- u8 *boot_addr, *cfe, *p;
++ unsigned int i;
++ u8 *boot_addr, *cfe;
+ char cfe_version[32];
++ char *board_name;
+ u32 val;
+
+ /* read base address of boot chip select (0)
+@@ -786,32 +752,19 @@ void __init board_prom_init(void)
+ strcpy(cfe_version, "unknown");
+ printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
+
+- /* extract nvram data */
+- memcpy(&nvram, boot_addr + BCM963XX_NVRAM_OFFSET, sizeof(nvram));
+-
+- /* check checksum before using data */
+- if (nvram.version <= 4)
+- check_len = offsetof(struct bcm963xx_nvram, checksum_old);
+- else
+- check_len = sizeof(nvram);
+- val = 0;
+- p = (u8 *)&nvram;
+- while (check_len--)
+- val += *p;
+- if (val) {
+- printk(KERN_ERR PFX "invalid nvram checksum\n");
++ if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET))
+ return;
+- }
+
+ if (strcmp(cfe_version, "unknown") != 0) {
+ /* cfe present */
+ boardid_fixup(boot_addr);
+ }
+
++ board_name = bcm63xx_nvram_get_name();
+ /* find board by name */
+ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) {
+- if (strncmp(nvram.name, bcm963xx_boards[i]->name,
+- sizeof(nvram.name)))
++ if (strncmp(board_name, bcm963xx_boards[i]->name,
++ BCM63XX_NVRAM_NAMELEN))
+ continue;
+ /* copy, board desc array is marked initdata */
+ memcpy(&board, bcm963xx_boards[i], sizeof(board));
+@@ -821,7 +774,7 @@ void __init board_prom_init(void)
+ /* bail out if board is not found, will complain later */
+ if (!board.name[0]) {
+ char name[17];
+- memcpy(name, nvram.name, 16);
++ memcpy(name, board_name, 16);
+ name[16] = 0;
+ printk(KERN_ERR PFX "unknown bcm963xx board: %s\n",
+ name);
+@@ -914,15 +867,15 @@ int __init board_register_devices(void)
+ bcm63xx_pcmcia_register();
+
+ if (board.has_enet0 &&
+- !board_get_mac_address(board.enet0.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enet0.mac_addr))
+ bcm63xx_enet_register(0, &board.enet0);
+
+ if (board.has_enet1 &&
+- !board_get_mac_address(board.enet1.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enet1.mac_addr))
+ bcm63xx_enet_register(1, &board.enet1);
+
+ if (board.has_enetsw &&
+- !board_get_mac_address(board.enetsw.mac_addr))
++ !bcm63xx_nvram_get_mac_address(board.enetsw.mac_addr))
+ bcm63xx_enetsw_register(&board.enetsw);
+
+ if (board.has_ehci0)
+@@ -938,7 +891,7 @@ int __init board_register_devices(void)
+ * do this after registering enet devices
+ */
+ #ifdef CONFIG_SSB_PCIHOST
+- if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
++ if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+--- /dev/null
++++ b/arch/mips/bcm63xx/nvram.c
+@@ -0,0 +1,84 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ */
++
++#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
++
++#include <linux/init.h>
++#include <linux/export.h>
++#include <linux/kernel.h>
++
++#include <bcm63xx_nvram.h>
++
++static struct bcm963xx_nvram nvram;
++static int mac_addr_used;
++
++int __init bcm63xx_nvram_init(void *addr)
++{
++ unsigned int check_len;
++ u8 *p;
++ u32 val;
++
++ /* extract nvram data */
++ memcpy(&nvram, addr, sizeof(nvram));
++
++ /* check checksum before using data */
++ if (nvram.version <= 4)
++ check_len = offsetof(struct bcm963xx_nvram, checksum_old);
++ else
++ check_len = sizeof(nvram);
++ val = 0;
++ p = (u8 *)&nvram;
++
++ while (check_len--)
++ val += *p;
++ if (val) {
++ pr_err("invalid nvram checksum\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++u8 *bcm63xx_nvram_get_name(void)
++{
++ return nvram.name;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_name);
++
++int bcm63xx_nvram_get_mac_address(u8 *mac)
++{
++ u8 *p;
++ int count;
++
++ if (mac_addr_used >= nvram.mac_addr_count) {
++ pr_err("not enough mac address\n");
++ return -ENODEV;
++ }
++
++ memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
++ p = mac + ETH_ALEN - 1;
++ count = mac_addr_used;
++
++ while (count--) {
++ do {
++ (*p)++;
++ if (*p != 0)
++ break;
++ p--;
++ } while (p != mac);
++ }
++
++ if (p == mac) {
++ pr_err("unable to fetch mac address\n");
++ return -ENODEV;
++ }
++
++ mac_addr_used++;
++ return 0;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+@@ -0,0 +1,34 @@
++#ifndef BCM63XX_NVRAM_H
++#define BCM63XX_NVRAM_H
++
++#include <linux/if_ether.h>
++
++#define BCM63XX_NVRAM_NAMELEN 16
++
++/*
++ * nvram structure
++ */
++struct bcm963xx_nvram {
++ u32 version;
++ u8 reserved1[256];
++ u8 name[BCM63XX_NVRAM_NAMELEN];
++ u32 main_tp_number;
++ u32 psi_size;
++ u32 mac_addr_count;
++ u8 mac_addr_base[ETH_ALEN];
++ u8 reserved2[2];
++ u32 checksum_old;
++ u8 reserved3[720];
++ u32 checksum_high;
++};
++
++int __init bcm63xx_nvram_init(void *);
++
++u8 *bcm63xx_nvram_get_name(void);
++
++/*
++ * register & return a new board mac address
++ */
++int bcm63xx_nvram_get_mac_address(u8 *mac);
++
++#endif /* BCM63XX_NVRAM_H */
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -15,23 +15,6 @@
+ #define BCM963XX_NVRAM_OFFSET 0x580
+
+ /*
+- * nvram structure
+- */
+-struct bcm963xx_nvram {
+- u32 version;
+- u8 reserved1[256];
+- u8 name[16];
+- u32 main_tp_number;
+- u32 psi_size;
+- u32 mac_addr_count;
+- u8 mac_addr_base[6];
+- u8 reserved2[2];
+- u32 checksum_old;
+- u8 reserved3[720];
+- u32 checksum_high;
+-};
+-
+-/*
+ * board definition
+ */
+ struct board_info {
diff --git a/target/linux/brcm63xx/patches-3.3/429-MIPS-BCM63XX-export-PSI-size-from-nvram.patch b/target/linux/brcm63xx/patches-3.3/429-MIPS-BCM63XX-export-PSI-size-from-nvram.patch
new file mode 100644
index 000000000..34966b27f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/429-MIPS-BCM63XX-export-PSI-size-from-nvram.patch
@@ -0,0 +1,44 @@
+From ffbeb183bf0e9e12fd607c5352f48420c32f588f Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sat, 12 May 2012 23:04:17 +0200
+Subject: [PATCH 61/79] MIPS: BCM63XX: export PSI size from nvram
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/nvram.c | 11 +++++++++++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h | 2 ++
+ 2 files changed, 13 insertions(+)
+
+--- a/arch/mips/bcm63xx/nvram.c
++++ b/arch/mips/bcm63xx/nvram.c
+@@ -14,6 +14,8 @@
+
+ #include <bcm63xx_nvram.h>
+
++#define BCM63XX_DEFAULT_PSI_SIZE 64
++
+ static struct bcm963xx_nvram nvram;
+ static int mac_addr_used;
+
+@@ -82,3 +84,12 @@ int bcm63xx_nvram_get_mac_address(u8 *ma
+ return 0;
+ }
+ EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
++
++int bcm63xx_nvram_get_psi_size(void)
++{
++ if (nvram.psi_size > 0)
++ return nvram.psi_size;
++
++ return BCM63XX_DEFAULT_PSI_SIZE;
++}
++EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+@@ -31,4 +31,6 @@ u8 *bcm63xx_nvram_get_name(void);
+ */
+ int bcm63xx_nvram_get_mac_address(u8 *mac);
+
++int bcm63xx_nvram_get_psi_size(void);
++
+ #endif /* BCM63XX_NVRAM_H */
diff --git a/target/linux/brcm63xx/patches-3.3/430-MTD-bcm63xxpart-use-nvram-for-PSI-size.patch b/target/linux/brcm63xx/patches-3.3/430-MTD-bcm63xxpart-use-nvram-for-PSI-size.patch
new file mode 100644
index 000000000..5ca6f4797
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/430-MTD-bcm63xxpart-use-nvram-for-PSI-size.patch
@@ -0,0 +1,29 @@
+From 658afad639a9456e1bb6fe5bba0032f3c0c3f699 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 14:10:39 +0200
+Subject: [PATCH 62/79] MTD: bcm63xxpart: use nvram for PSI size
+
+---
+ drivers/mtd/bcm63xxpart.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -32,6 +32,7 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
+
++#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
+ #include <asm/mach-bcm63xx/bcm963xx_tag.h>
+ #include <asm/mach-bcm63xx/board_bcm963xx.h>
+
+@@ -90,7 +91,8 @@ static int bcm63xx_parse_cfe_partitions(
+ BCM63XX_CFE_BLOCK_SIZE);
+
+ cfelen = cfe_erasesize;
+- nvramlen = cfe_erasesize;
++ nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
++ nvramlen = roundup(nvramlen, cfe_erasesize);
+
+ /* Allocate memory for buffer */
+ buf = vmalloc(sizeof(struct bcm_tag));
diff --git a/target/linux/brcm63xx/patches-3.3/431-MTD-physmap-allow-passing-pp_data.patch b/target/linux/brcm63xx/patches-3.3/431-MTD-physmap-allow-passing-pp_data.patch
new file mode 100644
index 000000000..f869911d5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/431-MTD-physmap-allow-passing-pp_data.patch
@@ -0,0 +1,41 @@
+From 266c506f4b262bd6aba0776a03d82c98e65d9906 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 17:32:36 +0200
+Subject: [PATCH 63/79] MTD: physmap: allow passing pp_data
+
+---
+ drivers/mtd/maps/physmap.c | 4 +++-
+ include/linux/mtd/physmap.h | 1 +
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/maps/physmap.c
++++ b/drivers/mtd/maps/physmap.c
+@@ -84,6 +84,7 @@ static int physmap_flash_probe(struct pl
+ {
+ struct physmap_flash_data *physmap_data;
+ struct physmap_flash_info *info;
++ struct mtd_part_parser_data *pp_data;
+ const char **probe_type;
+ const char **part_types;
+ int err = 0;
+@@ -173,8 +174,9 @@ static int physmap_flash_probe(struct pl
+ goto err_out;
+
+ part_types = physmap_data->part_probe_types ? : part_probe_types;
++ pp_data = physmap_data->pp_data ? physmap_data->pp_data : NULL;
+
+- mtd_device_parse_register(info->cmtd, part_types, 0,
++ mtd_device_parse_register(info->cmtd, part_types, pp_data,
+ physmap_data->parts, physmap_data->nr_parts);
+ return 0;
+
+--- a/include/linux/mtd/physmap.h
++++ b/include/linux/mtd/physmap.h
+@@ -32,6 +32,7 @@ struct physmap_flash_data {
+ char *probe_type;
+ struct mtd_partition *parts;
+ const char **part_probe_types;
++ struct mtd_part_parser_data *pp_data;
+ };
+
+ #endif /* __LINUX_MTD_PHYSMAP__ */
diff --git a/target/linux/brcm63xx/patches-3.3/432-BCM63XX-allow-providing-fixup-data-in-board-data.patch b/target/linux/brcm63xx/patches-3.3/432-BCM63XX-allow-providing-fixup-data-in-board-data.patch
new file mode 100644
index 000000000..742d11566
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/432-BCM63XX-allow-providing-fixup-data-in-board-data.patch
@@ -0,0 +1,81 @@
+From 5131195413b62df73dfd394fea272830ea8c4e1a Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 14:40:03 +0200
+Subject: [PATCH 67/80] BCM63XX: allow providing fixup data in board data
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 10 +++++++++-
+ arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 10 ++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -33,6 +33,7 @@
+ #include <bcm63xx_dev_usb_ehci.h>
+ #include <board_bcm963xx.h>
+ #include <bcm_tag.h>
++#include <pci_ath9k_fixup.h>
+
+ #define PFX "board_bcm963xx: "
+
+@@ -856,6 +857,7 @@ int __init board_register_devices(void)
+ {
+ int button_count = 0;
+ int led_count = 0;
++ int i;
+
+ if (board.has_uart0)
+ bcm63xx_uart_register(0);
+@@ -891,7 +893,8 @@ int __init board_register_devices(void)
+ * do this after registering enet devices
+ */
+ #ifdef CONFIG_SSB_PCIHOST
+- if (!bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
++ if (!board.has_caldata &&
++ !bcm63xx_nvram_get_mac_address(bcm63xx_sprom.il0mac)) {
+ memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
+ if (ssb_arch_register_fallback_sprom(
+@@ -933,5 +936,9 @@ int __init board_register_devices(void)
+ platform_device_register(&bcm63xx_gpio_keys_device);
+ }
+
++ /* register any fixups */
++ for (i = 0; i < board.has_caldata; i++)
++ pci_enable_ath9k_fixup(board.caldata[i].slot, board.caldata[i].caldata_offset);
++
+ return 0;
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
++++ b/arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h
+@@ -7,6 +7,7 @@
+ #include <linux/leds.h>
+ #include <bcm63xx_dev_enet.h>
+ #include <bcm63xx_dev_dsp.h>
++#include <pci_ath9k_fixup.h>
+
+ /*
+ * flash mapping
+@@ -14,6 +15,11 @@
+ #define BCM963XX_CFE_VERSION_OFFSET 0x570
+ #define BCM963XX_NVRAM_OFFSET 0x580
+
++struct ath9k_caldata {
++ unsigned int slot;
++ u32 caldata_offset;
++};
++
+ /*
+ * board definition
+ */
+@@ -32,6 +38,10 @@ struct board_info {
+ unsigned int has_dsp:1;
+ unsigned int has_uart0:1;
+ unsigned int has_uart1:1;
++ unsigned int has_caldata:2;
++
++ /* wifi calibration data config */
++ struct ath9k_caldata caldata[2];
+
+ /* ethernet config */
+ struct bcm63xx_enet_platform_data enet0;
diff --git a/target/linux/brcm63xx/patches-3.3/433-MTD-m25p80-allow-passing-pp_data.patch b/target/linux/brcm63xx/patches-3.3/433-MTD-m25p80-allow-passing-pp_data.patch
new file mode 100644
index 000000000..5fef3f3a2
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/433-MTD-m25p80-allow-passing-pp_data.patch
@@ -0,0 +1,40 @@
+From 7f17dfe9009beb07a3de0e380932a725293829df Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 17:33:03 +0200
+Subject: [PATCH 64/79] MTD: m25p80: allow passing pp_data
+
+---
+ drivers/mtd/devices/m25p80.c | 3 +++
+ include/linux/spi/flash.h | 2 ++
+ 2 files changed, 5 insertions(+)
+
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -887,6 +887,9 @@ static int __devinit m25p_probe(struct s
+ dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
+ }
+
++ if (data && data->pp_data)
++ memcpy(&ppdata, data->pp_data, sizeof(ppdata));
++
+ info = (void *)id->driver_data;
+
+ if (info->jedec_id) {
+--- a/include/linux/spi/flash.h
++++ b/include/linux/spi/flash.h
+@@ -12,6 +12,7 @@ struct mtd_part_parser_data;
+ * with chips that can't be queried for JEDEC or other IDs
+ * @part_probe_types: optional list of MTD parser names to use for
+ * partitioning
++ * @pp_data: optional partition parser data.
+ *
+ * @max_transfer_len: option maximum read/write length limitation for
+ * SPI controllers not able to transfer any length commands.
+@@ -30,6 +31,7 @@ struct flash_platform_data {
+ char *type;
+
+ const char **part_probe_types;
++ struct mtd_part_parser_data *pp_data;
+
+ unsigned int max_transfer_len;
+ /* we'll likely add more ... use JEDEC IDs, etc */
diff --git a/target/linux/brcm63xx/patches-3.3/434-MIPS-BCM63XX-store-the-flash-type-in-global-variable.patch b/target/linux/brcm63xx/patches-3.3/434-MIPS-BCM63XX-store-the-flash-type-in-global-variable.patch
new file mode 100644
index 000000000..703509820
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/434-MIPS-BCM63XX-store-the-flash-type-in-global-variable.patch
@@ -0,0 +1,122 @@
+From f888824d352df894ab721a5ca067b0313500efe7 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 12:17:54 +0200
+Subject: [PATCH 38/59] MIPS: BCM63XX: store the flash type in global variable
+
+---
+ arch/mips/bcm63xx/dev-flash.c | 36 +++++++++++++------
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 2 +
+ 2 files changed, 26 insertions(+), 12 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -25,6 +25,8 @@
+ #include <bcm63xx_regs.h>
+ #include <bcm63xx_io.h>
+
++int bcm63xx_attached_flash = -1;
++
+ static struct mtd_partition mtd_partitions[] = {
+ {
+ .name = "cfe",
+@@ -86,20 +88,23 @@ static int __init bcm63xx_detect_flash_t
+ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
+
+ if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
+ else
+- return BCM63XX_FLASH_TYPE_NAND;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
++ break;
+ case BCM6338_CPU_ID:
+ case BCM6345_CPU_ID:
+ case BCM6348_CPU_ID:
+ /* no way to auto detect so assume parallel */
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
++ break;
+ case BCM6358_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
+ else
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
++ break;
+ case BCM6362_CPU_ID:
+ val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
+ if (val & STRAPBUS_6362_HSSPI_CLK_FAST)
+@@ -108,9 +113,10 @@ static int __init bcm63xx_detect_flash_t
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
+ if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
+ else
+- return BCM63XX_FLASH_TYPE_NAND;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
++ break;
+ case BCM6368_CPU_ID:
+ val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6368_SPI_CLK_FAST)
+@@ -118,25 +124,32 @@ static int __init bcm63xx_detect_flash_t
+
+ switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
+ case STRAPBUS_6368_BOOT_SEL_NAND:
+- return BCM63XX_FLASH_TYPE_NAND;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_NAND;
++ break;
+ case STRAPBUS_6368_BOOT_SEL_SERIAL:
+- return BCM63XX_FLASH_TYPE_SERIAL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_SERIAL;
++ break;
+ case STRAPBUS_6368_BOOT_SEL_PARALLEL:
+- return BCM63XX_FLASH_TYPE_PARALLEL;
++ bcm63xx_attached_flash = BCM63XX_FLASH_TYPE_PARALLEL;
++ break;
++ default:
++ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
++
++ return 0;
+ }
+
+ int __init bcm63xx_flash_register(void)
+ {
+- int flash_type;
+ u32 val;
+
+- flash_type = bcm63xx_detect_flash_type();
+
+- switch (flash_type) {
++ bcm63xx_detect_flash_type();
++
++ switch (bcm63xx_attached_flash) {
+ case BCM63XX_FLASH_TYPE_PARALLEL:
+ /* read base address of boot chip select (0) */
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+@@ -157,7 +170,7 @@ int __init bcm63xx_flash_register(void)
+ return -ENODEV;
+ default:
+ pr_err("flash detection failed for BCM%x: %d\n",
+- bcm63xx_get_cpu_id(), flash_type);
++ bcm63xx_get_cpu_id(), bcm63xx_attached_flash);
+ return -ENODEV;
+ }
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -7,6 +7,8 @@ enum {
+ BCM63XX_FLASH_TYPE_NAND,
+ };
+
++extern int bcm63xx_attached_flash;
++
+ int __init bcm63xx_flash_register(void);
+
+ #endif /* __BCM63XX_FLASH_H */
diff --git a/target/linux/brcm63xx/patches-3.3/435-BCM63XX-add-a-fixup-for-ath9k-devices.patch b/target/linux/brcm63xx/patches-3.3/435-BCM63XX-add-a-fixup-for-ath9k-devices.patch
new file mode 100644
index 000000000..a3b30e444
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/435-BCM63XX-add-a-fixup-for-ath9k-devices.patch
@@ -0,0 +1,227 @@
+From fb6f6f58db9ae9cf27ab01f5f09cfbc5c078a7b8 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 14:36:11 +0200
+Subject: [PATCH 66/80] BCM63XX: add a fixup for ath9k devices
+
+---
+ arch/mips/bcm63xx/Makefile | 2 +-
+ arch/mips/bcm63xx/pci-ath9k-fixup.c | 190 ++++++++++++++++++++
+ .../include/asm/mach-bcm63xx/pci_ath9k_fixup.h | 7 +
+ 3 files changed, 198 insertions(+), 1 deletion(-)
+ create mode 100644 arch/mips/bcm63xx/pci-ath9k-fixup.c
+ create mode 100644 arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
+
+--- a/arch/mips/bcm63xx/Makefile
++++ b/arch/mips/bcm63xx/Makefile
+@@ -1,7 +1,7 @@
+ obj-y += clk.o cpu.o cs.o gpio.o irq.o nvram.o prom.o setup.o \
+ timer.o dev-dsp.o dev-enet.o dev-flash.o dev-hsspi.o \
+ dev-pcmcia.o dev-rng.o dev-spi.o dev-uart.o dev-usb-ehci.o \
+- dev-usb-ohci.o dev-wdt.o
++ dev-usb-ohci.o dev-wdt.o pci-ath9k-fixup.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+ obj-y += boards/
+--- /dev/null
++++ b/arch/mips/bcm63xx/pci-ath9k-fixup.c
+@@ -0,0 +1,190 @@
++/*
++ * Broadcom BCM63XX Ath9k EEPROM fixup helper.
++ *
++ * Copytight (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
++ *
++ * Based on
++ *
++ * Atheros AP94 reference board PCI initialization
++ *
++ * Copyright (C) 2009-2010 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/pci.h>
++#include <linux/delay.h>
++#include <linux/ath9k_platform.h>
++
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_nvram.h>
++#include <bcm63xx_dev_pci.h>
++#include <bcm63xx_dev_flash.h>
++#include <bcm63xx_dev_hsspi.h>
++#include <pci_ath9k_fixup.h>
++
++struct ath9k_fixup {
++ unsigned slot;
++ u8 mac[ETH_ALEN];
++ struct ath9k_platform_data pdata;
++};
++
++static int ath9k_num_fixups;
++static struct ath9k_fixup ath9k_fixups[2] = {
++ {
++ .slot = 255,
++ .pdata = {
++ .led_pin = -1,
++ },
++ },
++ {
++ .slot = 255,
++ .pdata = {
++ .led_pin = -1,
++ },
++ },
++};
++
++static u16 *bcm63xx_read_eeprom(u16 *eeprom, u32 offset)
++{
++ u32 addr;
++
++ if (BCMCPU_IS_6328()) {
++ addr = 0x18000000;
++ } else {
++ addr = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ addr &= MPI_CSBASE_BASE_MASK;
++ }
++
++ switch (bcm63xx_attached_flash) {
++ case BCM63XX_FLASH_TYPE_PARALLEL:
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ return eeprom;
++ case BCM63XX_FLASH_TYPE_SERIAL:
++ /* the first megabyte is memory mapped */
++ if (offset < 0x100000) {
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + offset), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ return eeprom;
++ }
++
++ if (BCMCPU_IS_6328()) {
++ /* we can change the memory mapped megabyte */
++ bcm_hsspi_writel(offset & 0xf00000, 0x18);
++ memcpy(eeprom, (void *)KSEG1ADDR(addr + (offset & 0xfffff)), ATH9K_PLAT_EEP_MAX_WORDS * sizeof(u16));
++ bcm_hsspi_writel(0, 0x18);
++ return eeprom;
++ }
++ /* can't do anything here without talking to the SPI controller. */
++ case BCM63XX_FLASH_TYPE_NAND:
++ default:
++ return NULL;
++ }
++}
++
++static void ath9k_pci_fixup(struct pci_dev *dev)
++{
++ void __iomem *mem;
++ struct ath9k_platform_data *pdata = NULL;
++ u16 *cal_data = NULL;
++ u16 cmd;
++ u32 bar0;
++ u32 val;
++ unsigned i;
++
++ for (i = 0; i < ath9k_num_fixups; i++) {
++ if (ath9k_fixups[i].slot != PCI_SLOT(dev->devfn))
++ continue;
++
++ cal_data = ath9k_fixups[i].pdata.eeprom_data;
++ pdata = &ath9k_fixups[i].pdata;
++ break;
++ }
++
++ if (cal_data == NULL)
++ return;
++
++ if (*cal_data != 0xa55a) {
++ pr_err("pci %s: invalid calibration data\n", pci_name(dev));
++ return;
++ }
++
++ pr_info("pci %s: fixup device configuration\n", pci_name(dev));
++
++ switch (bcm63xx_get_cpu_id()) {
++ case BCM6328_CPU_ID:
++ val = BCM_PCIE_MEM_BASE_PA;
++ break;
++ case BCM6348_CPU_ID:
++ case BCM6358_CPU_ID:
++ case BCM6368_CPU_ID:
++ val = BCM_PCI_MEM_BASE_PA;
++ break;
++ default:
++ BUG();
++ }
++
++ mem = ioremap(val, 0x10000);
++ if (!mem) {
++ pr_err("pci %s: ioremap error\n", pci_name(dev));
++ return;
++ }
++
++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0);
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, val);
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ /* set offset to first reg address */
++ cal_data += 3;
++ while(*cal_data != 0xffff) {
++ u32 reg;
++ reg = *cal_data++;
++ val = *cal_data++;
++ val |= (*cal_data++) << 16;
++
++ writel(val, mem + reg);
++ udelay(100);
++ }
++
++ pci_read_config_dword(dev, PCI_VENDOR_ID, &val);
++ dev->vendor = val & 0xffff;
++ dev->device = (val >> 16) & 0xffff;
++
++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val);
++ dev->revision = val & 0xff;
++ dev->class = val >> 8; /* upper 3 bytes */
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0);
++
++ iounmap(mem);
++
++ dev->dev.platform_data = pdata;
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ath9k_pci_fixup);
++
++void __init pci_enable_ath9k_fixup(unsigned slot, u32 offset)
++{
++ if (ath9k_num_fixups >= ARRAY_SIZE(ath9k_fixups))
++ return;
++
++ ath9k_fixups[ath9k_num_fixups].slot = slot;
++
++ if (!bcm63xx_read_eeprom(ath9k_fixups[ath9k_num_fixups].pdata.eeprom_data, offset))
++ return;
++
++ if (bcm63xx_nvram_get_mac_address(ath9k_fixups[ath9k_num_fixups].mac))
++ return;
++
++ ath9k_fixups[ath9k_num_fixups].pdata.macaddr = ath9k_fixups[ath9k_num_fixups].mac;
++ ath9k_num_fixups++;
++}
+--- /dev/null
++++ b/arch/mips/include/asm/mach-bcm63xx/pci_ath9k_fixup.h
+@@ -0,0 +1,7 @@
++#ifndef _PCI_ATH9K_FIXUP
++#define _PCI_ATH9K_FIXUP
++
++
++void pci_enable_ath9k_fixup(unsigned slot, u32 offset) __init;
++
++#endif /* _PCI_ATH9K_FIXUP */
diff --git a/target/linux/brcm63xx/patches-3.3/436-MTD-bcm63xxpart-allow-passing-a-caldata-offset.patch b/target/linux/brcm63xx/patches-3.3/436-MTD-bcm63xxpart-allow-passing-a-caldata-offset.patch
new file mode 100644
index 000000000..681bab248
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/436-MTD-bcm63xxpart-allow-passing-a-caldata-offset.patch
@@ -0,0 +1,118 @@
+From 8ab86c5dc38ad4de1442e50e0adbc354d9184d71 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 1 May 2012 14:38:41 +0200
+Subject: [PATCH 68/79] MTD: bcm63xxpart: allow passing a caldata offset
+
+Allow bcm63xxpart to receive a caldata offset if calibration data is
+contained in flash.
+---
+ drivers/mtd/bcm63xxpart.c | 47 ++++++++++++++++++++++++++++++++++++++--
+ include/linux/mtd/partitions.h | 2 ++
+ 2 files changed, 47 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/bcm63xxpart.c
++++ b/drivers/mtd/bcm63xxpart.c
+@@ -80,6 +80,8 @@ static int bcm63xx_parse_cfe_partitions(
+ unsigned int rootfslen, kernellen, sparelen, totallen;
+ unsigned int cfelen, nvramlen;
+ unsigned int cfe_erasesize;
++ unsigned int caldatalen1 = 0, caldataaddr1 = 0;
++ unsigned int caldatalen2 = 0, caldataaddr2 = 0;
+ int i;
+ u32 computed_crc;
+ bool rootfs_first = false;
+@@ -94,6 +96,23 @@ static int bcm63xx_parse_cfe_partitions(
+ nvramlen = bcm63xx_nvram_get_psi_size() * 1024;
+ nvramlen = roundup(nvramlen, cfe_erasesize);
+
++ if (data) {
++ if (data->caldata[0]) {
++ caldatalen1 = cfe_erasesize;
++ caldataaddr1 = rounddown(data->caldata[0],
++ cfe_erasesize);
++ }
++ if (data->caldata[1]) {
++ caldatalen2 = cfe_erasesize;
++ caldataaddr2 = rounddown(data->caldata[1],
++ cfe_erasesize);
++ }
++ if (caldataaddr1 == caldataaddr2) {
++ caldataaddr2 = 0;
++ caldatalen2 = 0;
++ }
++ }
++
+ /* Allocate memory for buffer */
+ buf = vmalloc(sizeof(struct bcm_tag));
+ if (!buf)
+@@ -144,7 +163,7 @@ static int bcm63xx_parse_cfe_partitions(
+ rootfsaddr = 0;
+ spareaddr = cfelen;
+ }
+- sparelen = master->size - spareaddr - nvramlen;
++ sparelen = master->size - spareaddr - nvramlen - caldatalen1 - caldatalen2;
+
+ /* Determine number of partitions */
+ if (rootfslen > 0)
+@@ -153,6 +172,12 @@ static int bcm63xx_parse_cfe_partitions(
+ if (kernellen > 0)
+ nrparts++;
+
++ if (caldatalen1 > 0)
++ nrparts++;
++
++ if (caldatalen2 > 0)
++ nrparts++;
++
+ /* Ask kernel for more memory */
+ parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
+ if (!parts) {
+@@ -190,6 +215,23 @@ static int bcm63xx_parse_cfe_partitions(
+ curpart++;
+ }
+
++ if (caldatalen1 > 0) {
++ if (caldatalen2 > 0)
++ parts[curpart].name = "cal_data1";
++ else
++ parts[curpart].name = "cal_data";
++ parts[curpart].offset = caldataaddr1;
++ parts[curpart].size = caldatalen1;
++ curpart++;
++ }
++
++ if (caldatalen2 > 0) {
++ parts[curpart].name = "cal_data2";
++ parts[curpart].offset = caldataaddr2;
++ parts[curpart].size = caldatalen2;
++ curpart++;
++ }
++
+ parts[curpart].name = "nvram";
+ parts[curpart].offset = master->size - nvramlen;
+ parts[curpart].size = nvramlen;
+@@ -198,7 +240,8 @@ static int bcm63xx_parse_cfe_partitions(
+ /* Global partition "linux" to make easy firmware upgrade */
+ parts[curpart].name = "linux";
+ parts[curpart].offset = cfelen;
+- parts[curpart].size = master->size - cfelen - nvramlen;
++ parts[curpart].size = master->size - cfelen - nvramlen
++ - caldatalen1 - caldatalen2;
+
+ for (i = 0; i < nrparts; i++)
+ pr_info("Partition %d is %s offset %llx and length %llx\n", i,
+--- a/include/linux/mtd/partitions.h
++++ b/include/linux/mtd/partitions.h
+@@ -58,10 +58,12 @@ struct device_node;
+ /**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device
++ * @caldata: for CFE, start address of wifi calibration data
+ * @of_node: for OF parsers, device node containing partitioning information
+ */
+ struct mtd_part_parser_data {
+ unsigned long origin;
++ unsigned long caldata[2];
+ struct device_node *of_node;
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/437-MIPS-BCM63XX-pass-caldata-info-to-flash.patch b/target/linux/brcm63xx/patches-3.3/437-MIPS-BCM63XX-pass-caldata-info-to-flash.patch
new file mode 100644
index 000000000..541efd2eb
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/437-MIPS-BCM63XX-pass-caldata-info-to-flash.patch
@@ -0,0 +1,82 @@
+From 977f8a30103b9c4992cab8f49357fe0d4274004f Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 3 May 2012 14:55:26 +0200
+Subject: [PATCH 69/80] MIPS: BCM63XX: pass caldata info to flash
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 2 +-
+ arch/mips/bcm63xx/dev-flash.c | 9 ++++++++-
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h | 4 +++-
+ 3 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -912,7 +912,7 @@ int __init board_register_devices(void)
+ if (board.num_spis)
+ spi_register_board_info(board.spis, board.num_spis);
+
+- bcm63xx_flash_register();
++ bcm63xx_flash_register(board.has_caldata, board.caldata);
+
+ /* count number of LEDs defined by this device */
+ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -35,12 +35,15 @@ static struct mtd_partition mtd_partitio
+ }
+ };
+
++static struct mtd_part_parser_data bcm63xx_parser_data;
++
+ static const char *bcm63xx_part_types[] = { "bcm63xxpart", "RedBoot", NULL };
+
+ static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .parts = mtd_partitions,
+ .part_probe_types = bcm63xx_part_types,
++ .pp_data = &bcm63xx_parser_data,
+ };
+
+ static struct resource mtd_resources[] = {
+@@ -62,6 +65,7 @@ static struct platform_device mtd_dev =
+
+ static struct flash_platform_data bcm63xx_flash_data = {
+ .part_probe_types = bcm63xx_part_types,
++ .pp_data = &bcm63xx_parser_data,
+ };
+
+ static struct spi_board_info bcm63xx_spi_flash_info[] = {
+@@ -142,10 +146,13 @@ static int __init bcm63xx_detect_flash_t
+ return 0;
+ }
+
+-int __init bcm63xx_flash_register(void)
++int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata)
+ {
+ u32 val;
++ unsigned int i;
+
++ for (i = 0; i < num_caldata; i++)
++ bcm63xx_parser_data.caldata[i] = caldata[i].caldata_offset;
+
+ bcm63xx_detect_flash_type();
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h
+@@ -1,6 +1,8 @@
+ #ifndef __BCM63XX_FLASH_H
+ #define __BCM63XX_FLASH_H
+
++#include <board_bcm963xx.h>
++
+ enum {
+ BCM63XX_FLASH_TYPE_PARALLEL,
+ BCM63XX_FLASH_TYPE_SERIAL,
+@@ -9,6 +11,6 @@ enum {
+
+ extern int bcm63xx_attached_flash;
+
+-int __init bcm63xx_flash_register(void);
++int __init bcm63xx_flash_register(int num_caldata, struct ath9k_caldata *caldata);
+
+ #endif /* __BCM63XX_FLASH_H */
diff --git a/target/linux/brcm63xx/patches-3.3/438-MIPS-BCM63XX-enable-USB-for-BCM6328.patch b/target/linux/brcm63xx/patches-3.3/438-MIPS-BCM63XX-enable-USB-for-BCM6328.patch
new file mode 100644
index 000000000..54673dcf3
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/438-MIPS-BCM63XX-enable-USB-for-BCM6328.patch
@@ -0,0 +1,60 @@
+From 38c3f8d21da90f0833578a157e22ddabf4d576bd Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 12 Feb 2012 14:28:34 +0100
+Subject: [PATCH 48/84] MIPS: BCM63XX: enable USB for BCM6328
+
+The USB controller is the same as the one on BCM6368.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/dev-usb-ehci.c | 2 +-
+ arch/mips/bcm63xx/dev-usb-ohci.c | 3 ++-
+ drivers/usb/host/ehci-bcm63xx.c | 2 +-
+ drivers/usb/host/ohci-bcm63xx.c | 2 +-
+ 4 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/bcm63xx/dev-usb-ehci.c
++++ b/arch/mips/bcm63xx/dev-usb-ehci.c
+@@ -39,7 +39,7 @@ static struct platform_device bcm63xx_eh
+
+ int __init bcm63xx_ehci_register(void)
+ {
+- if (!BCMCPU_IS_6358() && !BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368())
+ return 0;
+
+ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
+--- a/arch/mips/bcm63xx/dev-usb-ohci.c
++++ b/arch/mips/bcm63xx/dev-usb-ohci.c
+@@ -39,7 +39,8 @@ static struct platform_device bcm63xx_oh
+
+ int __init bcm63xx_ohci_register(void)
+ {
+- if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6348() && !BCMCPU_IS_6358() &&
++ !BCMCPU_IS_6368())
+ return 0;
+
+ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
+--- a/drivers/usb/host/ehci-bcm63xx.c
++++ b/drivers/usb/host/ehci-bcm63xx.c
+@@ -99,7 +99,7 @@ static int __devinit ehci_hcd_bcm63xx_dr
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+- } else if (BCMCPU_IS_6368()) {
++ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6368()) {
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_DATA_MASK;
+--- a/drivers/usb/host/ohci-bcm63xx.c
++++ b/drivers/usb/host/ohci-bcm63xx.c
+@@ -94,7 +94,7 @@ static int __devinit ohci_hcd_bcm63xx_dr
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+- } else if (BCMCPU_IS_6368()) {
++ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
diff --git a/target/linux/brcm63xx/patches-3.3/439-MIPS-BCM63XX-wire-up-the-HS-SPI-controller-for-BCM63.patch b/target/linux/brcm63xx/patches-3.3/439-MIPS-BCM63XX-wire-up-the-HS-SPI-controller-for-BCM63.patch
new file mode 100644
index 000000000..756156918
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/439-MIPS-BCM63XX-wire-up-the-HS-SPI-controller-for-BCM63.patch
@@ -0,0 +1,56 @@
+From ed225910f0e062d9c28d5cf216f97b3cf457a8c5 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 21 Nov 2011 00:55:49 +0100
+Subject: [PATCH 58/81] MIPS: BCM63XX: wire up the HS SPI controller for BCM6362
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/clk.c | 2 ++
+ arch/mips/bcm63xx/dev-hsspi.c | 7 +++++--
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h | 1 +
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -218,6 +218,8 @@ static void hsspi_set(struct clk *clk, i
+
+ if (BCMCPU_IS_6328())
+ mask = CKCTL_6328_HSSPI_EN;
++ else if (BCMCPU_IS_6362())
++ mask = CKCTL_6362_HSSPI_EN;
+ else
+ return;
+
+--- a/arch/mips/bcm63xx/dev-hsspi.c
++++ b/arch/mips/bcm63xx/dev-hsspi.c
+@@ -43,7 +43,7 @@ static struct platform_device bcm63xx_hs
+ int __init bcm63xx_hsspi_register(void)
+ {
+
+- if (!BCMCPU_IS_6328())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362())
+ return -ENODEV;
+
+ spi_resources[0].start = bcm63xx_regset_address(RSET_HSSPI);
+@@ -51,7 +51,10 @@ int __init bcm63xx_hsspi_register(void)
+ spi_resources[0].end += RSET_HSSPI_SIZE - 1;
+ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_HSSPI);
+
+- spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
++ if (BCMCPU_IS_6328())
++ spi_pdata.speed_hz = HSSPI_PLL_HZ_6328;
++ else
++ spi_pdata.speed_hz = HSSPI_PLL_HZ;
+
+ return platform_device_register(&bcm63xx_hsspi_device);
+ }
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_hsspi.h
+@@ -16,6 +16,7 @@ struct bcm63xx_hsspi_pdata {
+ #define bcm_hsspi_writel(v, o) bcm_rset_writel(RSET_HSSPI, (v), (o))
+
+ #define HSSPI_PLL_HZ_6328 133333333
++#define HSSPI_PLL_HZ 400000000
+
+ #define HSSPI_BUFFER_LEN 512
+
diff --git a/target/linux/brcm63xx/patches-3.3/440-MIPS-BCM63XX-enable-SPI-controller-for-BCM6362.patch b/target/linux/brcm63xx/patches-3.3/440-MIPS-BCM63XX-enable-SPI-controller-for-BCM6362.patch
new file mode 100644
index 000000000..f1f134286
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/440-MIPS-BCM63XX-enable-SPI-controller-for-BCM6362.patch
@@ -0,0 +1,101 @@
+From eef84812bc7ffd590da6ad6b83bfeebaa43a7055 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Thu, 5 Jul 2012 21:19:20 +0200
+Subject: [PATCH 58/84] MIPS: BCM63XX: enable SPI controller for BCM6362
+
+---
+ arch/mips/bcm63xx/clk.c | 2 ++
+ arch/mips/bcm63xx/dev-spi.c | 11 ++++++++++-
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_spi.h | 3 +++
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 16 ++++++++++++++++
+ 4 files changed, 31 insertions(+), 1 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -199,6 +199,8 @@ static void spi_set(struct clk *clk, int
+ mask = CKCTL_6348_SPI_EN;
+ else if (BCMCPU_IS_6358())
+ mask = CKCTL_6358_SPI_EN;
++ else if (BCMCPU_IS_6362())
++ mask = CKCTL_6362_SPI_EN;
+ else
+ /* BCMCPU_IS_6368 */
+ mask = CKCTL_6368_SPI_EN;
+--- a/arch/mips/bcm63xx/dev-spi.c
++++ b/arch/mips/bcm63xx/dev-spi.c
+@@ -34,6 +34,10 @@ static const unsigned long bcm6358_regs_
+ __GEN_SPI_REGS_TABLE(6358)
+ };
+
++static const unsigned long bcm6362_regs_spi[] = {
++ __GEN_SPI_REGS_TABLE(6362)
++};
++
+ static const unsigned long bcm6368_regs_spi[] = {
+ __GEN_SPI_REGS_TABLE(6368)
+ };
+@@ -49,6 +53,8 @@ static __init void bcm63xx_spi_regs_init
+ bcm63xx_regs_spi = bcm6348_regs_spi;
+ if (BCMCPU_IS_6358())
+ bcm63xx_regs_spi = bcm6358_regs_spi;
++ if (BCMCPU_IS_6362())
++ bcm63xx_regs_spi = bcm6362_regs_spi;
+ if (BCMCPU_IS_6368())
+ bcm63xx_regs_spi = bcm6368_regs_spi;
+ }
+@@ -99,6 +105,9 @@ int __init bcm63xx_spi_register(void)
+ /* Set bus frequency */
+ spi_pdata.speed_hz = clk_get_rate(periph_clk);
+
++ if (BCMCPU_IS_6362())
++ spi_pdata.bus_num = 1;
++
+ spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
+ spi_resources[0].end = spi_resources[0].start;
+ spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
+@@ -110,7 +119,7 @@ int __init bcm63xx_spi_register(void)
+ spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
+ }
+
+- if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
++ if (BCMCPU_IS_6358() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
+ spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
+ spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+@@ -81,6 +81,9 @@ static inline unsigned long bcm63xx_spir
+ #ifdef CONFIG_BCM63XX_CPU_6358
+ __GEN_SPI_RSET(6358)
+ #endif
++#ifdef CONFIG_BCM63XX_CPU_6362
++ __GEN_SPI_RSET(6362)
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ __GEN_SPI_RSET(6368)
+ #endif
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -1223,6 +1223,22 @@
+ #define SPI_6358_MSG_TAIL 0x709
+ #define SPI_6358_RX_TAIL 0x70B
+
++/* BCM 6362 SPI core */
++#define SPI_6362_MSG_CTL 0x00 /* 16-bits register */
++#define SPI_6362_MSG_DATA 0x02
++#define SPI_6362_MSG_DATA_SIZE 0x21e
++#define SPI_6362_RX_DATA 0x400
++#define SPI_6362_RX_DATA_SIZE 0x220
++#define SPI_6362_CMD 0x700 /* 16-bits register */
++#define SPI_6362_INT_STATUS 0x702
++#define SPI_6362_INT_MASK_ST 0x703
++#define SPI_6362_INT_MASK 0x704
++#define SPI_6362_ST 0x705
++#define SPI_6362_CLK_CFG 0x706
++#define SPI_6362_FILL_BYTE 0x707
++#define SPI_6362_MSG_TAIL 0x709
++#define SPI_6362_RX_TAIL 0x70B
++
+ /* BCM 6358 SPI core */
+ #define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
+ #define SPI_6368_MSG_CTL_WIDTH 16
diff --git a/target/linux/brcm63xx/patches-3.3/441-MIPS-BCM63XX-enable-USB-for-BCM6362.patch b/target/linux/brcm63xx/patches-3.3/441-MIPS-BCM63XX-enable-USB-for-BCM6362.patch
new file mode 100644
index 000000000..04d540ffb
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/441-MIPS-BCM63XX-enable-USB-for-BCM6362.patch
@@ -0,0 +1,84 @@
+From fb9e98936590637c26b66d60137a7b44b329a254 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 12 Feb 2012 14:40:56 +0100
+Subject: [PATCH 59/84] MIPS: BCM63XX: enable USB for BCM6362
+
+BCM6362 has the same USB controller as BCM6368.
+
+Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
+---
+ arch/mips/bcm63xx/Kconfig | 2 ++
+ arch/mips/bcm63xx/clk.c | 4 ++++
+ arch/mips/bcm63xx/dev-usb-ehci.c | 3 ++-
+ arch/mips/bcm63xx/dev-usb-ohci.c | 2 +-
+ drivers/usb/host/ehci-bcm63xx.c | 2 +-
+ drivers/usb/host/ohci-bcm63xx.c | 2 +-
+ 6 files changed, 11 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/bcm63xx/Kconfig
++++ b/arch/mips/bcm63xx/Kconfig
+@@ -27,6 +27,8 @@ config BCM63XX_CPU_6358
+ config BCM63XX_CPU_6362
+ bool "support 6362 CPU"
+ select HW_HAS_PCI
++ select USB_ARCH_HAS_OHCI if USB_SUPPORT
++ select USB_ARCH_HAS_EHCI if USB_SUPPORT
+
+ config BCM63XX_CPU_6368
+ bool "support 6368 CPU"
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -178,6 +178,8 @@ static void usbh_set(struct clk *clk, in
+ {
+ if (BCMCPU_IS_6348())
+ bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
++ else if (BCMCPU_IS_6362())
++ bcm_hwclock_set(CKCTL_6362_USBH_EN, enable);
+ else if (BCMCPU_IS_6368())
+ bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
+ }
+--- a/arch/mips/bcm63xx/dev-usb-ehci.c
++++ b/arch/mips/bcm63xx/dev-usb-ehci.c
+@@ -39,7 +39,8 @@ static struct platform_device bcm63xx_eh
+
+ int __init bcm63xx_ehci_register(void)
+ {
+- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6358() && !BCMCPU_IS_6362() &&
++ !BCMCPU_IS_6368())
+ return 0;
+
+ ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
+--- a/arch/mips/bcm63xx/dev-usb-ohci.c
++++ b/arch/mips/bcm63xx/dev-usb-ohci.c
+@@ -40,7 +40,7 @@ static struct platform_device bcm63xx_oh
+ int __init bcm63xx_ohci_register(void)
+ {
+ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6348() && !BCMCPU_IS_6358() &&
+- !BCMCPU_IS_6368())
++ !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ return 0;
+
+ ohci_resources[0].start = bcm63xx_regset_address(RSET_OHCI0);
+--- a/drivers/usb/host/ehci-bcm63xx.c
++++ b/drivers/usb/host/ehci-bcm63xx.c
+@@ -99,7 +99,7 @@ static int __devinit ehci_hcd_bcm63xx_dr
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+- } else if (BCMCPU_IS_6328() || BCMCPU_IS_6368()) {
++ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_EHCI_DATA_MASK;
+--- a/drivers/usb/host/ohci-bcm63xx.c
++++ b/drivers/usb/host/ohci-bcm63xx.c
+@@ -94,7 +94,7 @@ static int __devinit ohci_hcd_bcm63xx_dr
+ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
+ USBH_PRIV_TEST_6358_REG);
+
+- } else if (BCMCPU_IS_6328() || BCMCPU_IS_6368()) {
++ } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
+ reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
+ reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
+ reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
diff --git a/target/linux/brcm63xx/patches-3.3/442-MIPS-BCM63XX-enable-enetsw-for-BCM6362.patch b/target/linux/brcm63xx/patches-3.3/442-MIPS-BCM63XX-enable-enetsw-for-BCM6362.patch
new file mode 100644
index 000000000..ae46ec406
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/442-MIPS-BCM63XX-enable-enetsw-for-BCM6362.patch
@@ -0,0 +1,77 @@
+From bf9d506bd144b95f8bb4127350ab2db5fba9c12e Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Sun, 8 Jul 2012 21:07:12 +0200
+Subject: [PATCH 60/84] MIPS: BCM63XX: enable enetsw for BCM6362
+
+---
+ arch/mips/bcm63xx/clk.c | 7 ++++++-
+ arch/mips/bcm63xx/dev-enet.c | 6 ++++--
+ .../include/asm/mach-bcm63xx/bcm63xx_dev_enet.h | 1 +
+ 3 files changed, 11 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/bcm63xx/clk.c
++++ b/arch/mips/bcm63xx/clk.c
+@@ -120,11 +120,13 @@ static void enetsw_set(struct clk *clk,
+ {
+ u32 mask;
+
+- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ return;
+
+ if (BCMCPU_IS_6328())
+ mask = CKCTL_6328_ROBOSW_EN;
++ else if (BCMCPU_IS_6362())
++ mask = CKCTL_6362_ROBOSW_EN;
+ else
+ mask = CKCTL_6368_ROBOSW_EN | CKCTL_6368_SWPKT_USB_EN |
+ CKCTL_6368_SWPKT_SAR_EN;
+@@ -137,6 +139,9 @@ static void enetsw_set(struct clk *clk,
+ if (BCMCPU_IS_6328()) {
+ reg = PERF_SOFTRESET_6328_REG;
+ mask = SOFTRESET_6328_ENETSW_MASK;
++ } else if (BCMCPU_IS_6362()) {
++ reg = PERF_SOFTRESET_6362_REG;
++ mask = SOFTRESET_6362_ENETSW_MASK;
+ } else {
+ reg = PERF_SOFTRESET_6368_REG;
+ mask = SOFTRESET_6368_ENETSW_MASK;
+--- a/arch/mips/bcm63xx/dev-enet.c
++++ b/arch/mips/bcm63xx/dev-enet.c
+@@ -141,7 +141,7 @@ static int __init register_shared(void)
+ shared_res[0].end = shared_res[0].start;
+ shared_res[0].end += (RSET_ENETDMA_SIZE) - 1;
+
+- if (BCMCPU_IS_6328() || BCMCPU_IS_6368())
++ if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
+ chan_count = 32;
+ else
+ chan_count = 16;
+@@ -224,7 +224,7 @@ bcm63xx_enetsw_register(const struct bcm
+ {
+ int ret;
+
+- if (!BCMCPU_IS_6328() && !BCMCPU_IS_6368())
++ if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
+ return -ENODEV;
+
+ ret = register_shared();
+@@ -243,6 +243,8 @@ bcm63xx_enetsw_register(const struct bcm
+
+ if (BCMCPU_IS_6328())
+ enetsw_pd.num_ports = ENETSW_PORTS_6328;
++ else if (BCMCPU_IS_6362())
++ enetsw_pd.num_ports = ENETSW_PORTS_6362;
+ else if (BCMCPU_IS_6368())
+ enetsw_pd.num_ports = ENETSW_PORTS_6368;
+
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
+@@ -44,6 +44,7 @@ struct bcm63xx_enet_platform_data {
+ */
+ #define ENETSW_MAX_PORT 6
+ #define ENETSW_PORTS_6328 5 /* 4 FE PHY + 1 RGMII */
++#define ENETSW_PORTS_6362 6 /* 4 FE PHY + 2 RGMII */
+ #define ENETSW_PORTS_6368 6 /* 4 FE PHY + 2 RGMII */
+
+ #define ENETSW_RGMII_PORT0 4
diff --git a/target/linux/brcm63xx/patches-3.3/500-board-D4PW.patch b/target/linux/brcm63xx/patches-3.3/500-board-D4PW.patch
new file mode 100644
index 000000000..d3d35d7a7
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/500-board-D4PW.patch
@@ -0,0 +1,65 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -469,6 +469,54 @@ static struct board_info __initdata boar
+
+ .has_ohci0 = 1,
+ };
++
++static struct board_info __initdata board_96348_D4PW = {
++ .name = "D-4P-W",
++ .expected_cpu_id = 0x6348,
++
++ .has_enet1 = 1,
++ .has_pci = 1,
++ .has_uart0 = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "D-4P-W:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ },
++ {
++ .name = "D-4P-W::status",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "D-4P-W:green:internet",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "D-4P-W:red:internet",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 7,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -640,6 +688,7 @@ static const struct board_info __initdat
+ &board_DV201AMR,
+ &board_96348gw_a,
+ &board_rta1025w_16,
++ &board_96348_D4PW,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/501-board-NB4.patch b/target/linux/brcm63xx/patches-3.3/501-board-NB4.patch
new file mode 100644
index 000000000..2f96f4b1e
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/501-board-NB4.patch
@@ -0,0 +1,640 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -15,6 +15,8 @@
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
+ #include <linux/spi/spi.h>
++#include <linux/spi/spi_gpio.h>
++#include <linux/spi/74x164.h>
+ #include <asm/addrspace.h>
+ #include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+@@ -43,6 +45,12 @@
+ #define CFE_OFFSET_64K 0x10000
+ #define CFE_OFFSET_128K 0x20000
+
++#define NB4_PID_OFFSET 0xff80
++#define NB4_74X164_GPIO_BASE 64
++#define NB4_SPI_GPIO_MOSI 7
++#define NB4_SPI_GPIO_CLK 6
++#define NB4_74HC64_GPIO(X) (NB4_74X164_GPIO_BASE + (X))
++
+ static struct board_info board;
+
+ /*
+@@ -666,6 +674,586 @@ static struct board_info __initdata boar
+
+ .has_ohci0 = 1,
+ };
++
++struct spi_gpio_platform_data nb4_spi_gpio_data = {
++ .sck = NB4_SPI_GPIO_CLK,
++ .mosi = NB4_SPI_GPIO_MOSI,
++ .miso = SPI_GPIO_NO_MISO,
++ .num_chipselect = 1,
++};
++
++
++static struct platform_device nb4_spi_gpio = {
++ .name = "spi_gpio",
++ .id = 1,
++ .dev = {
++ .platform_data = &nb4_spi_gpio_data,
++ },
++};
++
++static struct platform_device * __initdata nb4_devices[] = {
++ &nb4_spi_gpio,
++};
++
++const struct gen_74x164_chip_platform_data nb4_74x164_platform_data = {
++ .base = NB4_74X164_GPIO_BASE
++};
++
++static struct spi_board_info nb4_spi_devices[] = {
++ {
++ .modalias = "74x164",
++ .max_speed_hz = 781000,
++ .bus_num = 1,
++ .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT,
++ .mode = SPI_MODE_0,
++ .platform_data = &nb4_74x164_platform_data
++ }
++};
++
++static struct board_info __initdata board_nb4_ser_r0 = {
++ .name = "NB4-SER-r0",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "NB4-SER-r0:white:adsl",
++ .gpio = NB4_74HC64_GPIO(4),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:white:traffic",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:white:tel",
++ .gpio = NB4_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:white:tv",
++ .gpio = NB4_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:white:wifi",
++ .gpio = 15,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:white:alarm",
++ .gpio = NB4_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:red:service",
++ .gpio = 29,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:green:service",
++ .gpio = 30,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r0:blue:service",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "service",
++ .gpio = 27,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "clip",
++ .gpio = 31,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++ .devs = nb4_devices,
++ .num_devs = ARRAY_SIZE(nb4_devices),
++ .spis = nb4_spi_devices,
++ .num_spis = ARRAY_SIZE(nb4_spi_devices),
++};
++
++static struct board_info __initdata board_nb4_ser_r1 = {
++ .name = "NB4-SER-r1",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "NB4-SER-r1:white:adsl",
++ .gpio = NB4_74HC64_GPIO(4),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:white:traffic",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:white:tel",
++ .gpio = NB4_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:white:tv",
++ .gpio = NB4_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:white:wifi",
++ .gpio = 15,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:white:alarm",
++ .gpio = NB4_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:red:service",
++ .gpio = 29,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:green:service",
++ .gpio = 30,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r1:blue:service",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "service",
++ .gpio = 27,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "clip",
++ .gpio = 31,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++ .devs = nb4_devices,
++ .num_devs = ARRAY_SIZE(nb4_devices),
++ .spis = nb4_spi_devices,
++ .num_spis = ARRAY_SIZE(nb4_spi_devices),
++};
++
++static struct board_info __initdata board_nb4_ser_r2 = {
++ .name = "NB4-SER-r2",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "NB4-SER-r2:white:adsl",
++ .gpio = NB4_74HC64_GPIO(4),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:white:traffic",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:white:tel",
++ .gpio = NB4_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:white:tv",
++ .gpio = NB4_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:white:wifi",
++ .gpio = 15,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:white:alarm",
++ .gpio = NB4_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:red:service",
++ .gpio = 29,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:green:service",
++ .gpio = 30,
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-SER-r2:blue:service",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "service",
++ .gpio = 27,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "clip",
++ .gpio = 31,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++ .devs = nb4_devices,
++ .num_devs = ARRAY_SIZE(nb4_devices),
++ .spis = nb4_spi_devices,
++ .num_spis = ARRAY_SIZE(nb4_spi_devices),
++};
++
++static struct board_info __initdata board_nb4_fxc_r1 = {
++ .name = "NB4-FXC-r1",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "NB4-FXC-r1:white:adsl",
++ .gpio = NB4_74HC64_GPIO(4),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r1:white:traffic",
++ .gpio = 2,
++ },
++ {
++ .name = "NB4-FXC-r1:white:tel",
++ .gpio = NB4_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r1:white:tv",
++ .gpio = NB4_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r1:white:wifi",
++ .gpio = 15,
++ },
++ {
++ .name = "NB4-FXC-r1:white:alarm",
++ .gpio = NB4_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r1:red:service",
++ .gpio = 29,
++ },
++ {
++ .name = "NB4-FXC-r1:green:service",
++ .gpio = 30,
++ },
++ {
++ .name = "NB4-FXC-r1:blue:service",
++ .gpio = 4,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "service",
++ .gpio = 27,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "clip",
++ .gpio = 31,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++ .devs = nb4_devices,
++ .num_devs = ARRAY_SIZE(nb4_devices),
++ .spis = nb4_spi_devices,
++ .num_spis = ARRAY_SIZE(nb4_spi_devices),
++};
++
++static struct board_info __initdata board_nb4_fxc_r2 = {
++ .name = "NB4-FXC-r2",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "NB4-FXC-r2:white:adsl",
++ .gpio = NB4_74HC64_GPIO(4),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r2:white:traffic",
++ .gpio = 2,
++ },
++ {
++ .name = "NB4-FXC-r2:white:tel",
++ .gpio = NB4_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r2:white:tv",
++ .gpio = NB4_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r2:white:wifi",
++ .gpio = 15,
++ },
++ {
++ .name = "NB4-FXC-r2:white:alarm",
++ .gpio = NB4_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "NB4-FXC-r2:red:service",
++ .gpio = 29,
++ },
++ {
++ .name = "NB4-FXC-r2:green:service",
++ .gpio = 30,
++ },
++ {
++ .name = "NB4-FXC-r2:blue:service",
++ .gpio = 4,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "service",
++ .gpio = 27,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "clip",
++ .gpio = 31,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .active_low = 1,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++ .devs = nb4_devices,
++ .num_devs = ARRAY_SIZE(nb4_devices),
++ .spis = nb4_spi_devices,
++ .num_spis = ARRAY_SIZE(nb4_spi_devices),
++};
+ #endif
+
+ /*
+@@ -696,6 +1284,11 @@ static const struct board_info __initdat
+ &board_96358vw2,
+ &board_AGPFS0,
+ &board_DWVS0,
++ &board_nb4_ser_r0,
++ &board_nb4_ser_r1,
++ &board_nb4_ser_r2,
++ &board_nb4_fxc_r1,
++ &board_nb4_fxc_r2,
+ #endif
+ };
+
+@@ -750,6 +1343,16 @@ static void __init boardid_fixup(u8 *boo
+ struct bcm_tag *tag = (struct bcm_tag *)(boot_addr + CFE_OFFSET_64K);
+ char *board_name = (char *)bcm63xx_nvram_get_name();
+
++ if (BCMCPU_IS_6358() && (!strcmp(board_name, "96358VW"))) {
++ u8 *p = boot_addr + NB4_PID_OFFSET;
++
++ /* Extract nb4 PID */
++ if (!memcmp(p, "NB4-", 4)) {
++ memcpy(board_name, p, sizeof("NB4-XXX-rX"));
++ return;
++ }
++ }
++
+ /* check if bcm_tag is at 64k offset */
+ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* else try 128k */
diff --git a/target/linux/brcm63xx/patches-3.3/502-board-96338W2_E7T.patch b/target/linux/brcm63xx/patches-3.3/502-board-96338W2_E7T.patch
new file mode 100644
index 000000000..12c7ac4f1
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/502-board-96338W2_E7T.patch
@@ -0,0 +1,49 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -140,6 +140,38 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_96338w2_e7t = {
++ .name = "96338W2_E7T",
++ .expected_cpu_id = 0x6338,
++
++ .has_enet0 = 1,
++
++ .enet0 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "96338W2_E7T:green:ppp",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "96338W2_E7T:green:ppp-fail",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "96338W2_E7T:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1263,6 +1295,7 @@ static const struct board_info __initdat
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ &board_96338gw,
+ &board_96338w,
++ &board_96338w2_e7t,
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6345
+ &board_96345gw2,
diff --git a/target/linux/brcm63xx/patches-3.3/503-board-CPVA642.patch b/target/linux/brcm63xx/patches-3.3/503-board-CPVA642.patch
new file mode 100644
index 000000000..98c9375d8
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/503-board-CPVA642.patch
@@ -0,0 +1,107 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -663,6 +663,96 @@ static struct board_info __initdata boar
+ },
+ };
+
++static struct board_info __initdata board_CPVA642 = {
++ .name = "CPVA642",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "CPVA642:red:power",
++ .gpio = 14,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:power",
++ .gpio = 11,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "CPVA642:red:wifi",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:wifi",
++ .gpio = 28,
++ .active_low = 0,
++ },
++ {
++ .name = "CPVA642:red:link",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:link",
++ .gpio = 10,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:ether",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:phone1",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:phone2",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA642:green:usb",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 36,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 37,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
++
+ static struct board_info __initdata board_AGPFS0 = {
+ .name = "AGPF-S0",
+ .expected_cpu_id = 0x6358,
+@@ -1316,6 +1406,7 @@ static const struct board_info __initdat
+ &board_96358vw,
+ &board_96358vw2,
+ &board_AGPFS0,
++ &board_CPVA642,
+ &board_DWVS0,
+ &board_nb4_ser_r0,
+ &board_nb4_ser_r1,
diff --git a/target/linux/brcm63xx/patches-3.3/504-board_dsl_274xb_rev_c.patch b/target/linux/brcm63xx/patches-3.3/504-board_dsl_274xb_rev_c.patch
new file mode 100644
index 000000000..ea8ba5980
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/504-board_dsl_274xb_rev_c.patch
@@ -0,0 +1,70 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -797,6 +797,59 @@ static struct board_info __initdata boar
+ .has_ohci0 = 1,
+ };
+
++/* D-Link DSL-274xB revison C2/C3 */
++static struct board_info __initdata board_dsl_274xb_rev_c = {
++ .name = "AW4139",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "dsl-274xb:green:power",
++ .gpio = 5,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "dsl-274xb:red:power",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:green:adsl",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:green:internet",
++ .gpio = 2,
++ },
++ {
++ .name = "dsl-274xb:red:internet",
++ .gpio = 10,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
+ struct spi_gpio_platform_data nb4_spi_gpio_data = {
+ .sck = NB4_SPI_GPIO_CLK,
+ .mosi = NB4_SPI_GPIO_MOSI,
+@@ -1408,6 +1461,7 @@ static const struct board_info __initdat
+ &board_AGPFS0,
+ &board_CPVA642,
+ &board_DWVS0,
++ &board_dsl_274xb_rev_c,
+ &board_nb4_ser_r0,
+ &board_nb4_ser_r1,
+ &board_nb4_ser_r2,
diff --git a/target/linux/brcm63xx/patches-3.3/505-board_spw500v.patch b/target/linux/brcm63xx/patches-3.3/505-board_spw500v.patch
new file mode 100644
index 000000000..584efd1e9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/505-board_spw500v.patch
@@ -0,0 +1,78 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -557,6 +557,67 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_spw500v = {
++ .name = "SPW500V",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .has_dsp = 1,
++ .dsp = {
++ .gpio_rst = 6,
++ .gpio_int = 34,
++ .ext_irq = 2,
++ .cs = 2,
++ },
++
++ .leds = {
++ {
++ .name = "SPW500V:red:power",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "SPW500V:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "SPW500V:green:ppp",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ { .name = "SPW500V:green:pstn",
++ .gpio = 28,
++ .active_low = 1,
++ },
++ {
++ .name = "SPW500V:green:voip",
++ .gpio = 32,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 33,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1453,6 +1514,7 @@ static const struct board_info __initdat
+ &board_96348gw_a,
+ &board_rta1025w_16,
+ &board_96348_D4PW,
++ &board_spw500v,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/506-board_gw6200_gw6000.patch b/target/linux/brcm63xx/patches-3.3/506-board_gw6200_gw6000.patch
new file mode 100644
index 000000000..78e06d842
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/506-board_gw6200_gw6000.patch
@@ -0,0 +1,124 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -426,6 +426,112 @@ static struct board_info __initdata boar
+ },
+ };
+
++static struct board_info __initdata board_gw6200 = {
++ .name = "GW6200",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++
++ .has_dsp = 1,
++ .dsp = {
++ .gpio_rst = 8, /* FIXME: What is real GPIO here? */
++ .gpio_int = 34,
++ .ext_irq = 2,
++ .cs = 2,
++ },
++
++ .leds = {
++ {
++ .name = "GW6200:green:line1",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "GW6200:green:line2",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "GW6200:green:line3",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ {
++ .name = "GW6200:green:tel",
++ .gpio = 7,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 36,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
++static struct board_info __initdata board_gw6000 = {
++ .name = "GW6000",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++
++ .has_dsp = 1,
++ .dsp = {
++ .gpio_rst = 6,
++ .gpio_int = 34,
++ .ext_irq = 2,
++ .cs = 2,
++ },
++
++ /* GW6000 has no GPIO-controlled leds */
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 36,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
++
++
+ static struct board_info __initdata board_FAST2404 = {
+ .name = "F@ST2404",
+ .expected_cpu_id = 0x6348,
+@@ -1507,6 +1613,8 @@ static const struct board_info __initdat
+ #ifdef CONFIG_BCM63XX_CPU_6348
+ &board_96348r,
+ &board_96348gw,
++ &board_gw6000,
++ &board_gw6200,
+ &board_96348gw_10,
+ &board_96348gw_11,
+ &board_FAST2404,
diff --git a/target/linux/brcm63xx/patches-3.3/507-board-MAGIC.patch b/target/linux/brcm63xx/patches-3.3/507-board-MAGIC.patch
new file mode 100644
index 000000000..7b96f3211
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/507-board-MAGIC.patch
@@ -0,0 +1,87 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -724,6 +724,76 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_96348sv = {
++ .name = "MAGIC",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++ .enet1 = {
++ /* it has BP_ENET_EXTERNAL_PHY */
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .has_dsp = 1,
++ .dsp = {
++ .gpio_rst = 25,
++ .gpio_int = 34,
++ .cs = 2,
++ .ext_irq = 2,
++ },
++
++ .leds = {
++ {
++ .name = "MAGIC:green:voip",
++ .gpio = 22,
++ .active_low = 1,
++ },
++ {
++ .name = "MAGIC:green:adsl",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "MAGIC:green:wifi",
++ .gpio = 28,
++ },
++ {
++ .name = "MAGIC:green:usb",
++ .gpio = 35,
++ .active_low = 1,
++ },
++ {
++ .name = "MAGIC:green:hpna",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "MAGIC:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "MAGIC:green:stop",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1623,6 +1693,7 @@ static const struct board_info __initdat
+ &board_rta1025w_16,
+ &board_96348_D4PW,
+ &board_spw500v,
++ &board_96348sv,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/508-board_hw553.patch b/target/linux/brcm63xx/patches-3.3/508-board_hw553.patch
new file mode 100644
index 000000000..dc9a744ef
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/508-board_hw553.patch
@@ -0,0 +1,91 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1666,6 +1666,80 @@ static struct board_info __initdata boar
+ .spis = nb4_spi_devices,
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+ };
++
++static struct board_info __initdata board_HW553 = {
++ .name = "HW553",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "HW553:red:lan",
++ .gpio = 34,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:blue:lan",
++ .gpio = 35,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:red:adsl",
++ .gpio = 22,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:blue:adsl",
++ .gpio = 23,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:red:power",
++ .gpio = 5,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++
++ {
++ .name = "HW553:blue:power",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:red:wifi",
++ .gpio = 25,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:red:internetkey",
++ .gpio = 12,
++ .active_low = 1,
++ },
++ {
++ .name = "HW553:blue:internetkey",
++ .gpio = 13,
++ .active_low = 1,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1708,6 +1782,7 @@ static const struct board_info __initdat
+ &board_nb4_ser_r2,
+ &board_nb4_fxc_r1,
+ &board_nb4_fxc_r2,
++ &board_HW553,
+ #endif
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/509-board_rta1320_16m.patch b/target/linux/brcm63xx/patches-3.3/509-board_rta1320_16m.patch
new file mode 100644
index 000000000..11c0903a9
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/509-board_rta1320_16m.patch
@@ -0,0 +1,54 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -172,6 +172,43 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_rta1320_16m = {
++ .name = "RTA1320_16M",
++ .expected_cpu_id = 0x6338,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++
++ .enet0 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "RTA1320_16M:green:adsl",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "RTA1320_16M:green:ppp",
++ .gpio = 4,
++ .active_low = 1,
++ },
++ {
++ .name = "RTA1320_16M:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "RTA1320_16M:green:stop",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1750,6 +1787,7 @@ static const struct board_info __initdat
+ &board_96338gw,
+ &board_96338w,
+ &board_96338w2_e7t,
++ &board_rta1320_16m,
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6345
+ &board_96345gw2,
diff --git a/target/linux/brcm63xx/patches-3.3/510-board_spw303v.patch b/target/linux/brcm63xx/patches-3.3/510-board_spw303v.patch
new file mode 100644
index 000000000..2ff60a4bc
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/510-board_spw303v.patch
@@ -0,0 +1,83 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1777,6 +1777,72 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++ /* T-Home Speedport W 303V Typ B */
++static struct board_info __initdata board_spw303v = {
++ .name = "96358-502V",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .leds = {
++ {
++ .name = "spw303v:green:power+adsl",
++ .gpio = 22,
++ .active_low = 1,
++ },
++ {
++ .name = "spw303v:red:power+adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "spw303v:green:ppp",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "spw303v:green:ses",
++ .gpio = 0,
++ .active_low = 1,
++ },
++ {
++ .name = "spw303v:green:voip",
++ .gpio = 27,
++ .active_low = 1,
++ },
++ {
++ .name = "spw303v:green:pots",
++ .gpio = 31,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 11,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "ses",
++ .gpio = 37,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ }
++};
+ #endif
+
+ /*
+@@ -1821,6 +1887,7 @@ static const struct board_info __initdat
+ &board_nb4_fxc_r1,
+ &board_nb4_fxc_r2,
+ &board_HW553,
++ &board_spw303v,
+ #endif
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/511-board_V2500V.patch b/target/linux/brcm63xx/patches-3.3/511-board_V2500V.patch
new file mode 100644
index 000000000..ff52497d4
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/511-board_V2500V.patch
@@ -0,0 +1,122 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -831,6 +831,63 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_V2500V_BB = {
++ .name = "V2500V_BB",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "V2500V_BB:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "V2500V_BB:red:power",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "V2500V_BB:green:adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ { .name = "V2500V_BB:green:ppp",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "V2500V_BB:green:wireless",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 31,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -1872,6 +1929,7 @@ static const struct board_info __initdat
+ &board_96348_D4PW,
+ &board_spw500v,
+ &board_96348sv,
++ &board_V2500V_BB,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
+@@ -1992,6 +2050,23 @@ void __init board_prom_init(void)
+ val &= MPI_CSBASE_BASE_MASK;
+ }
+ boot_addr = (u8 *)KSEG1ADDR(val);
++ printk(KERN_INFO PFX "Boot address 0x%08x\n",(unsigned int)boot_addr);
++
++ /* BT Voyager 2500V (RTA1046VW PCB) has 8 Meg flash used as two */
++ /* banks of 4 Meg. The byte at 0xBF800000 identifies the back to use.*/
++ /* Loading firmware from the CFE Prompt always loads to Bank 0 */
++ /* Do an early check of CFE and then select bank 0 */
++
++ if (boot_addr == (u8 *)0xbf800000) {
++ unsigned char board_name[16];
++ u8 *tmp_boot_addr;
++ tmp_boot_addr = (u8 *)0xbfc00000; // Address of Bank 0
++ memcpy(board_name, tmp_boot_addr + BCM963XX_NVRAM_OFFSET + offsetof(struct bcm963xx_nvram, name), sizeof(board_name));
++ if (!strcmp(board_name, "V2500V_BB")) {
++ printk(KERN_INFO PFX "V2500V: nvram bank 0\n");
++ boot_addr = (u8 *)0xbfc00000; // Bank 0
++ }
++ }
+
+ /* dump cfe version */
+ cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET;
+--- a/arch/mips/bcm63xx/dev-flash.c
++++ b/arch/mips/bcm63xx/dev-flash.c
+@@ -19,6 +19,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/flash.h>
+
++#include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+ #include <bcm63xx_dev_flash.h>
+ #include <bcm63xx_dev_hsspi.h>
+@@ -162,6 +163,13 @@ int __init bcm63xx_flash_register(int nu
+ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
+ val &= MPI_CSBASE_BASE_MASK;
+
++ /* BT Voyager 2500V has 8 Meg flash in two 4 Meg banks */
++ /* Loading from CFE always uses Bank 0 */
++ if (!strcmp(board_get_name(), "V2500V_BB")) {
++ pr_info("V2500V: Start in Bank 0\n");
++ val = val + 0x400000; // Select Bank 0 start address
++ }
++
+ mtd_resources[0].start = val;
+ mtd_resources[0].end = 0x1FFFFFFF;
+
diff --git a/target/linux/brcm63xx/patches-3.3/512-board_BTV2110.patch b/target/linux/brcm63xx/patches-3.3/512-board_BTV2110.patch
new file mode 100644
index 000000000..03d9b4144
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/512-board_BTV2110.patch
@@ -0,0 +1,73 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -395,6 +395,62 @@ static struct board_info __initdata boar
+ },
+ };
+
++
++/* BT Voyager 2110 */
++static struct board_info __initdata board_V2110 = {
++ .name = "V2110",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "V2110:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "V2110:red:power",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "V2110:green:adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ { .name = "V2110:green:ppp",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "V2110:green:wireless",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 33,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
++
+ static struct board_info __initdata board_96348gw = {
+ .name = "96348GW",
+ .expected_cpu_id = 0x6348,
+@@ -1930,6 +1986,7 @@ static const struct board_info __initdat
+ &board_spw500v,
+ &board_96348sv,
+ &board_V2500V_BB,
++ &board_V2110,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/513-board_livebox.patch b/target/linux/brcm63xx/patches-3.3/513-board_livebox.patch
new file mode 100644
index 000000000..dc53d481b
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/513-board_livebox.patch
@@ -0,0 +1,391 @@
+--- a/arch/mips/bcm63xx/boards/Kconfig
++++ b/arch/mips/bcm63xx/boards/Kconfig
+@@ -8,4 +8,10 @@ config BOARD_BCM963XX
+ select SSB
+ help
+
++config BOARD_LIVEBOX
++ bool "Inventel Livebox(es) boards"
++ select SSB
++ help
++ Inventel Livebox boards using the RedBoot bootloader.
++
+ endchoice
+--- a/arch/mips/bcm63xx/boards/Makefile
++++ b/arch/mips/bcm63xx/boards/Makefile
+@@ -1,3 +1,4 @@
+ obj-$(CONFIG_BOARD_BCM963XX) += board_bcm963xx.o
++obj-$(CONFIG_BOARD_LIVEBOX) += board_livebox.o
+
+ ccflags-y := -Werror
+--- /dev/null
++++ b/arch/mips/bcm63xx/boards/board_livebox.c
+@@ -0,0 +1,368 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/physmap.h>
++#include <linux/ssb/ssb.h>
++#include <linux/gpio_keys.h>
++#include <linux/input.h>
++#include <linux/spi/spi.h>
++#include <asm/addrspace.h>
++#include <bcm63xx_board.h>
++#include <bcm63xx_cpu.h>
++#include <bcm63xx_dev_uart.h>
++#include <bcm63xx_regs.h>
++#include <bcm63xx_io.h>
++#include <bcm63xx_dev_pci.h>
++#include <bcm63xx_dev_enet.h>
++#include <bcm63xx_dev_dsp.h>
++#include <bcm63xx_dev_pcmcia.h>
++#include <bcm63xx_dev_usb_ohci.h>
++#include <bcm63xx_dev_usb_ehci.h>
++#include <bcm63xx_dev_spi.h>
++#include <board_bcm963xx.h>
++
++#define PFX "board_livebox: "
++
++#define LIVEBOX_KEYS_POLL_INTERVAL 20
++#define LIVEBOX_KEYS_DEBOUNCE_INTERVAL (LIVEBOX_KEYS_POLL_INTERVAL * 3)
++
++static unsigned int mac_addr_used = 0;
++static struct board_info board;
++
++/*
++ * known 6348 boards
++ */
++#ifdef CONFIG_BCM63XX_CPU_6348
++static struct board_info __initdata board_livebox_blue5g = {
++ .name = "Livebox-blue-5g",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++
++ .enet1 = {
++ .has_phy = 1,
++ .phy_id = 31,
++ },
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++
++ .has_dsp = 0, /*TODO some Liveboxes have dsp*/
++ .dsp = {
++ .gpio_rst = 6, /*FIXME eth1 shares gpio6 with dsp?*/
++ .gpio_int = 35,
++ .cs = 2,
++ .ext_irq = 2,
++ },
++
++ .leds = {
++ {
++ .name = "Livebox-blue-5g::adsl-fail",
++ .gpio = 0,
++ .active_low = 0,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "Livebox-blue-5g::adsl",
++ .gpio = 1,
++ },
++ {
++ .name = "Livebox-blue-5g::traffic",
++ .gpio = 2,
++ },
++ {
++ .name = "Livebox-blue-5g::phone",
++ .gpio = 3,
++ },
++ {
++ .name = "Livebox-blue-5g::wifi",
++ .gpio = 4,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "BTN_1",
++ .gpio = 36,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = BTN_1,
++ .debounce_interval = LIVEBOX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "BTN_2",
++ .gpio = 7,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = BTN_2,
++ .debounce_interval = LIVEBOX_KEYS_DEBOUNCE_INTERVAL,
++ },
++
++ },
++};
++#endif
++
++/*
++ * all boards
++ */
++static const struct board_info __initdata *bcm963xx_boards[] = {
++#ifdef CONFIG_BCM63XX_CPU_6348
++ &board_livebox_blue5g
++#endif
++};
++/*
++ * return board name for /proc/cpuinfo
++ */
++const char *board_get_name(void)
++{
++ return board.name;
++}
++
++/*
++ * register & return a new board mac address
++ */
++static int board_get_mac_address(u8 *mac)
++{
++ u8 *p;
++ int count;
++
++ memcpy(mac, (u8 *)0xBEBFF377, ETH_ALEN);
++
++ p = mac + ETH_ALEN - 1;
++ count = mac_addr_used;
++
++ while (count--) {
++ do {
++ (*p)++;
++ if (*p != 0)
++ break;
++ p--;
++ } while (p != mac);
++ }
++
++ if (p == mac) {
++ printk(KERN_ERR PFX "unable to fetch mac address\n");
++ return -ENODEV;
++ }
++ mac_addr_used++;
++
++ return 0;
++}
++
++/*
++ * early init callback
++ */
++#define LIVEBOX_GPIO_DETECT_MASK 0x000000ff
++#define LIVEBOX_BOOT_ADDR 0x1e400000
++
++#define LIVEBOX_HW_BLUE5G_9 0x90
++
++void __init board_prom_init(void)
++{
++ u32 val;
++ u8 hw_version;
++
++ /* Get hardware version */
++ val = bcm_gpio_readl(GPIO_CTL_LO_REG);
++ val &= ~LIVEBOX_GPIO_DETECT_MASK;
++ bcm_gpio_writel(val, GPIO_CTL_LO_REG);
++
++ hw_version = bcm_gpio_readl(GPIO_DATA_LO_REG) & LIVEBOX_GPIO_DETECT_MASK;
++ switch (hw_version) {
++ case LIVEBOX_HW_BLUE5G_9:
++ printk(KERN_INFO PFX "Livebox BLUE5G.9\n");
++ memcpy(&board, bcm963xx_boards[0], sizeof(board));
++ break;
++ default:
++ printk(KERN_INFO PFX "Unknown livebox version: %02x\n", hw_version);
++ break;
++ }
++
++ /* use default livebox configuration */
++ memcpy(&board, bcm963xx_boards[0], sizeof(board));
++
++ /* setup pin multiplexing depending on board enabled device,
++ * this has to be done this early since PCI init is done
++ * inside arch_initcall */
++ val = 0;
++
++#ifdef CONFIG_PCI
++ if (board.has_pci) {
++ if (BCMCPU_IS_6348())
++ val |= GPIO_MODE_6348_G2_PCI;
++ }
++#endif
++ if (board.has_pccard) {
++ if (BCMCPU_IS_6348())
++ val |= GPIO_MODE_6348_G1_MII_PCCARD;
++ }
++
++ if (board.has_enet0 && !board.enet0.use_internal_phy) {
++ if (BCMCPU_IS_6348())
++ val |= GPIO_MODE_6348_G3_EXT_MII |
++ GPIO_MODE_6348_G0_EXT_MII;
++ }
++
++ if (board.has_enet1 && !board.enet1.use_internal_phy) {
++ if (BCMCPU_IS_6348())
++ val |= GPIO_MODE_6348_G3_EXT_MII |
++ GPIO_MODE_6348_G0_EXT_MII;
++ printk(KERN_INFO PFX "resetting gpio6 for eth1...\n");
++ gpio_request(6, "dsp_eth_rst");
++ gpio_direction_output(6, 0);
++ gpio_set_value(6, 1);
++ }
++
++ bcm_gpio_writel(val, GPIO_MODE_REG);
++}
++
++/*
++ * second stage init callback, good time to panic if we couldn't
++ * identify on which board we're running since early printk is working
++ */
++void __init board_setup(void)
++{
++ if (!board.name[0])
++ panic("unable to detect bcm963xx board");
++ printk(KERN_INFO PFX "board name: %s\n", board.name);
++
++ /* make sure we're running on expected cpu */
++ if (bcm63xx_get_cpu_id() != board.expected_cpu_id)
++ panic("unexpected CPU for bcm963xx board");
++}
++
++static struct physmap_flash_data flash_data = {
++ .width = 2,
++};
++
++static struct resource mtd_resources[] = {
++ {
++ .start = 0, /* filled at runtime */
++ .end = 0, /* filled at runtime */
++ .flags = IORESOURCE_MEM,
++ }
++};
++
++static struct platform_device mtd_dev = {
++ .name = "physmap-flash",
++ .resource = mtd_resources,
++ .num_resources = ARRAY_SIZE(mtd_resources),
++ .dev = {
++ .platform_data = &flash_data,
++ },
++};
++
++static struct gpio_led_platform_data bcm63xx_led_data;
++
++static struct platform_device bcm63xx_gpio_leds = {
++ .name = "leds-gpio",
++ .id = 0,
++ .dev.platform_data = &bcm63xx_led_data,
++};
++
++static struct gpio_keys_platform_data bcm63xx_gpio_keys_data = {
++ .poll_interval = LIVEBOX_KEYS_POLL_INTERVAL,
++};
++
++static struct platform_device bcm63xx_gpio_keys_device = {
++ .name = "gpio-keys-polled",
++ .id = 0,
++ .dev.platform_data = &bcm63xx_gpio_keys_data,
++};
++
++/*
++ * third stage init callback, register all board devices.
++ */
++int __init board_register_devices(void)
++{
++ u32 val;
++ int led_count = 0;
++ int button_count = 0;
++
++ if (board.has_uart0)
++ bcm63xx_uart_register(0);
++
++ if (board.has_uart1)
++ bcm63xx_uart_register(1);
++
++ if (board.has_pccard)
++ bcm63xx_pcmcia_register();
++
++ if (board.has_enet0 &&
++ !board_get_mac_address(board.enet0.mac_addr))
++ bcm63xx_enet_register(0, &board.enet0);
++
++ if (board.has_enet1 &&
++ !board_get_mac_address(board.enet1.mac_addr))
++ bcm63xx_enet_register(1, &board.enet1);
++
++ if (board.has_ehci0)
++ bcm63xx_ehci_register();
++
++ if (board.has_ohci0)
++ bcm63xx_ohci_register();
++
++ if (board.has_dsp)
++ bcm63xx_dsp_register(&board.dsp);
++
++ bcm63xx_spi_register();
++
++ if (board.num_devs)
++ platform_add_devices(board.devs, board.num_devs);
++
++ if (board.num_spis)
++ spi_register_board_info(board.spis, board.num_spis);
++
++
++ /* read base address of boot chip select (0) */
++ val = bcm_mpi_readl(MPI_CSBASE_REG(0));
++ val &= MPI_CSBASE_BASE_MASK;
++ if (val != LIVEBOX_BOOT_ADDR)
++ printk(KERN_NOTICE PFX "flash address is: 0x%08x, forcing to: 0x%08x\n",
++ val, LIVEBOX_BOOT_ADDR);
++ mtd_resources[0].start = LIVEBOX_BOOT_ADDR;
++ mtd_resources[0].end = 0x1ebfffff;
++
++ platform_device_register(&mtd_dev);
++
++ /* count number of LEDs defined by this device */
++ while (led_count < ARRAY_SIZE(board.leds) && board.leds[led_count].name)
++ led_count++;
++
++ bcm63xx_led_data.num_leds = led_count;
++ bcm63xx_led_data.leds = board.leds;
++
++ platform_device_register(&bcm63xx_gpio_leds);
++
++ /* count number of BUTTONs defined by this device */
++ while (button_count < ARRAY_SIZE(board.buttons) && board.buttons[button_count].desc)
++ button_count++;
++
++ if (button_count) {
++ bcm63xx_gpio_keys_data.nbuttons = button_count;
++ bcm63xx_gpio_keys_data.buttons = board.buttons;
++
++ platform_device_register(&bcm63xx_gpio_keys_device);
++ }
++
++ return 0;
++}
diff --git a/target/linux/brcm63xx/patches-3.3/514-board_ct536_ct5621.patch b/target/linux/brcm63xx/patches-3.3/514-board_ct536_ct5621.patch
new file mode 100644
index 000000000..41e37c828
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/514-board_ct536_ct5621.patch
@@ -0,0 +1,60 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -451,6 +451,49 @@ static struct board_info __initdata boar
+ };
+
+
++static struct board_info __initdata board_ct536_ct5621 = {
++ .name = "CT536_CT5621",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 0,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "CT536_CT5621:green:adsl-fail",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "CT536_CT5621:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 33,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
+ static struct board_info __initdata board_96348gw = {
+ .name = "96348GW",
+ .expected_cpu_id = 0x6348,
+@@ -1987,6 +2030,7 @@ static const struct board_info __initdat
+ &board_96348sv,
+ &board_V2500V_BB,
+ &board_V2110,
++ &board_ct536_ct5621,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/515-board_DWV-S0_fixes.patch b/target/linux/brcm63xx/patches-3.3/515-board_DWV-S0_fixes.patch
new file mode 100644
index 000000000..22d7a1836
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/515-board_DWV-S0_fixes.patch
@@ -0,0 +1,19 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1210,6 +1210,8 @@ static struct board_info __initdata boar
+ .name = "DWV-S0",
+ .expected_cpu_id = 0x6358,
+
++ .has_uart0 = 1,
++
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
+@@ -1225,6 +1227,7 @@ static struct board_info __initdata boar
+ },
+
+ .has_ohci0 = 1,
++ .has_ehci0 = 1,
+ };
+
+ /* D-Link DSL-274xB revison C2/C3 */
diff --git a/target/linux/brcm63xx/patches-3.3/516-board_96348A-122.patch b/target/linux/brcm63xx/patches-3.3/516-board_96348A-122.patch
new file mode 100644
index 000000000..dbc9aeb33
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/516-board_96348A-122.patch
@@ -0,0 +1,78 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -494,6 +494,67 @@ static struct board_info __initdata boar
+ },
+ };
+
++static struct board_info __initdata board_96348A_122 = {
++ .name = "96348A-122",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++
++ .leds = {
++ {
++ .name = "96348A-122:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "96348A-122:red:alarm",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "96348A-122:green:wps",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 33,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wlan",
++ .gpio = 34,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_WLAN,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 35,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
+ static struct board_info __initdata board_96348gw = {
+ .name = "96348GW",
+ .expected_cpu_id = 0x6348,
+@@ -2034,6 +2095,7 @@ static const struct board_info __initdat
+ &board_V2500V_BB,
+ &board_V2110,
+ &board_ct536_ct5621,
++ &board_96348A_122,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/517-RTA1205W_16_uart_fixes.patch b/target/linux/brcm63xx/patches-3.3/517-RTA1205W_16_uart_fixes.patch
new file mode 100644
index 000000000..63eccd26c
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/517-RTA1205W_16_uart_fixes.patch
@@ -0,0 +1,10 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -757,6 +757,7 @@ static struct board_info __initdata boar
+ .name = "RTA1025W_16",
+ .expected_cpu_id = 0x6348,
+
++ .has_uart0 = 1,
+ .has_enet0 = 1,
+ .has_enet1 = 1,
+ .has_pci = 1,
diff --git a/target/linux/brcm63xx/patches-3.3/519_board_CPVA502plus.patch b/target/linux/brcm63xx/patches-3.3/519_board_CPVA502plus.patch
new file mode 100644
index 000000000..07adb376f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/519_board_CPVA502plus.patch
@@ -0,0 +1,55 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1049,6 +1049,44 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_CPVA502plus = {
++ .name = "CPVA502+",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 1,
++ .use_internal_phy = 1,
++ },
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "CPVA502+:green:phone",
++ .gpio = 0,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA502+:green:link",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "CPVA502+:green:feth1", /* FIXME:does gpio4 enable eth1 phy? */
++ .gpio = 4,
++ .active_low = 1,
++ },
++ },
++};
++
+ #endif
+
+ /*
+@@ -2097,6 +2135,7 @@ static const struct board_info __initdat
+ &board_V2110,
+ &board_ct536_ct5621,
+ &board_96348A_122,
++ &board_CPVA502plus,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/520-bcm63xx-add-support-for-96368MVWG-board.patch b/target/linux/brcm63xx/patches-3.3/520-bcm63xx-add-support-for-96368MVWG-board.patch
new file mode 100644
index 000000000..f2e5dba04
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/520-bcm63xx-add-support-for-96368MVWG-board.patch
@@ -0,0 +1,128 @@
+From eeacc2529942051504bc957726aa178671344421 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Wed, 20 Jan 2010 16:21:30 +0100
+Subject: [PATCH 32/63] bcm63xx: add support for 96368MVWG board.
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 95 ++++++++++++++++++++
+ .../mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 2 +
+ 2 files changed, 97 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -2105,6 +2105,78 @@ static struct board_info __initdata boar
+ #endif
+
+ /*
++ * known 6368 boards
++ */
++#ifdef CONFIG_BCM63XX_CPU_6368
++static struct board_info __initdata board_96368mvwg = {
++ .name = "96368MVWG",
++ .expected_cpu_id = 0x6368,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [1] = {
++ .used = 1,
++ .phy_id = 2,
++ .name = "port1",
++ },
++
++ [2] = {
++ .used = 1,
++ .phy_id = 3,
++ .name = "port2",
++ },
++
++ [4] = {
++ .used = 1,
++ .phy_id = 0x12,
++ .name = "port0",
++ },
++
++ [5] = {
++ .used = 1,
++ .phy_id = 0x11,
++ .name = "port3",
++ },
++ },
++ },
++
++ .leds = {
++ {
++ .name = "96368MVWG:green:adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "96368MVWG:green:ppp",
++ .gpio = 5,
++ },
++ {
++ .name = "96368MVWG:green:power",
++ .gpio = 22,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "96368MVWG:green:wps",
++ .gpio = 23,
++ .active_low = 1,
++ },
++ {
++ .name = "96368MVWG:green:ppp-fail",
++ .gpio = 31,
++ },
++ },
++
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++};
++#endif
++
++/*
+ * all boards
+ */
+ static const struct board_info __initdata *bcm963xx_boards[] = {
+@@ -2153,6 +2225,10 @@ static const struct board_info __initdat
+ &board_HW553,
+ &board_spw303v,
+ #endif
++
++#ifdef CONFIG_BCM63XX_CPU_6368
++ &board_96368mvwg,
++#endif
+ };
+
+ /*
+@@ -2324,12 +2400,25 @@ void __init board_prom_init(void)
+ bcm63xx_pci_enabled = 1;
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G2_PCI;
++
++ if (BCMCPU_IS_6368())
++ val |= GPIO_MODE_6368_PCI_REQ1 |
++ GPIO_MODE_6368_PCI_GNT1 |
++ GPIO_MODE_6368_PCI_INTB |
++ GPIO_MODE_6368_PCI_REQ0 |
++ GPIO_MODE_6368_PCI_GNT0;
+ }
+ #endif
+
+ if (board.has_pccard) {
+ if (BCMCPU_IS_6348())
+ val |= GPIO_MODE_6348_G1_MII_PCCARD;
++
++ if (BCMCPU_IS_6368())
++ val |= GPIO_MODE_6368_PCMCIA_CD1 |
++ GPIO_MODE_6368_PCMCIA_CD2 |
++ GPIO_MODE_6368_PCMCIA_VS1 |
++ GPIO_MODE_6368_PCMCIA_VS2;
+ }
+
+ if (board.has_enet0 && !board.enet0.use_internal_phy) {
diff --git a/target/linux/brcm63xx/patches-3.3/521-bcm63xx-add-support-for-96368MVNgr-board.patch b/target/linux/brcm63xx/patches-3.3/521-bcm63xx-add-support-for-96368MVNgr-board.patch
new file mode 100644
index 000000000..8ddc6dbc5
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/521-bcm63xx-add-support-for-96368MVNgr-board.patch
@@ -0,0 +1,92 @@
+From f457fc2eb9bb915b5a4d251c7c68d4694cf07b01 Mon Sep 17 00:00:00 2001
+From: Maxime Bizon <mbizon@freebox.fr>
+Date: Fri, 4 Nov 2011 12:33:48 +0100
+Subject: [PATCH 33/63] bcm63xx: add support for 96368MVNgr board.
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 67 +++++++++++++++++++++++++++++
+ 1 files changed, 67 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -2174,6 +2174,72 @@ static struct board_info __initdata boar
+ .has_ohci0 = 1,
+ .has_ehci0 = 1,
+ };
++
++static struct board_info __initdata board_96368mvngr = {
++ .name = "96368MVNgr",
++ .expected_cpu_id = 0x6368,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [0] = {
++ .used = 1,
++ .phy_id = 1,
++ .name = "port1",
++ },
++
++ [1] = {
++ .used = 1,
++ .phy_id = 2,
++ .name = "port2",
++ },
++
++ [2] = {
++ .used = 1,
++ .phy_id = 3,
++ .name = "port3",
++ },
++
++ [3] = {
++ .used = 1,
++ .phy_id = 4,
++ .name = "port4",
++ },
++ },
++ },
++
++ .leds = {
++ {
++ .name = "96368MVNgr:green:adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "96368MVNgr:green:inet",
++ .gpio = 5,
++ },
++ {
++ .name = "96368MVNgr:green:power",
++ .gpio = 22,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "96368MVNgr:green:wps",
++ .gpio = 23,
++ .active_low = 1,
++ },
++ {
++ .name = "96368MVNgr:green:inet-fail",
++ .gpio = 3,
++ },
++ },
++
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++};
+ #endif
+
+ /*
+@@ -2228,6 +2294,7 @@ static const struct board_info __initdat
+
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ &board_96368mvwg,
++ &board_96368mvngr,
+ #endif
+ };
+
diff --git a/target/linux/brcm63xx/patches-3.3/522-MIPS-BCM63XX-add-96328avng-reference-board.patch b/target/linux/brcm63xx/patches-3.3/522-MIPS-BCM63XX-add-96328avng-reference-board.patch
new file mode 100644
index 000000000..59c6fe285
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/522-MIPS-BCM63XX-add-96328avng-reference-board.patch
@@ -0,0 +1,102 @@
+From c93c2bbf0cc96da5a47d77f01daf6c983cfe4216 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 29 May 2012 10:52:25 +0200
+Subject: [PATCH] MIPS: BCM63XX: add 96328avng reference board
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 77 +++++++++++++++++++++++++++++
+ 1 files changed, 77 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -54,6 +54,80 @@
+ static struct board_info board;
+
+ /*
++ * known 6328 boards
++ */
++#ifdef CONFIG_BCM63XX_CPU_6328
++static struct board_info __initdata board_96328avng = {
++ .name = "96328avng",
++ .expected_cpu_id = 0x6328,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [0] = {
++ .used = 1,
++ .phy_id = 1,
++ .name = "Port 1",
++ },
++ [1] = {
++ .used = 1,
++ .phy_id = 2,
++ .name = "Port 2",
++ },
++ [2] = {
++ .used = 1,
++ .phy_id = 3,
++ .name = "Port 3",
++ },
++ [3] = {
++ .used = 1,
++ .phy_id = 4,
++ .name = "Port 4",
++ },
++ },
++ },
++
++ .leds = {
++ {
++ .name = "96328avng::internet-fail",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "96328avng::dsl",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "96328avng::power",
++ .gpio = 4,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "96328avng::power-fail",
++ .gpio = 8,
++ .active_low = 1,
++ },
++ {
++ .name = "96328avng::wps",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "96328avng::internet",
++ .gpio = 11,
++ .active_low = 1,
++ },
++ },
++};
++#endif
++
++/*
+ * known 6338 boards
+ */
+ #ifdef CONFIG_BCM63XX_CPU_6338
+@@ -2246,6 +2320,9 @@ static struct board_info __initdata boar
+ * all boards
+ */
+ static const struct board_info __initdata *bcm963xx_boards[] = {
++#ifdef CONFIG_BCM63XX_CPU_6328
++ &board_96328avng,
++#endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ &board_96338gw,
+ &board_96338w,
diff --git a/target/linux/brcm63xx/patches-3.3/523-MIPS-BCM63XX-add-963281TAN-reference-board.patch b/target/linux/brcm63xx/patches-3.3/523-MIPS-BCM63XX-add-963281TAN-reference-board.patch
new file mode 100644
index 000000000..1b5d369e8
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/523-MIPS-BCM63XX-add-963281TAN-reference-board.patch
@@ -0,0 +1,96 @@
+From f0649f7b7c672cf452a1796a1422bf615e1973f8 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Tue, 29 May 2012 11:01:12 +0200
+Subject: [PATCH] MIPS: BCM63XX: add 963281TAN reference board
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 71 +++++++++++++++++++++++++++++
+ 1 files changed, 71 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -125,6 +125,76 @@ static struct board_info __initdata boar
+ },
+ },
+ };
++
++static struct board_info __initdata board_963281TAN = {
++ .name = "963281TAN",
++ .expected_cpu_id = 0x6328,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [0] = {
++ .used = 1,
++ .phy_id = 1,
++ .name = "Port 1",
++ },
++ [1] = {
++ .used = 1,
++ .phy_id = 2,
++ .name = "Port 2",
++ },
++ [2] = {
++ .used = 1,
++ .phy_id = 3,
++ .name = "Port 3",
++ },
++ [3] = {
++ .used = 1,
++ .phy_id = 4,
++ .name = "Port 4",
++ },
++ },
++ },
++
++ .leds = {
++ {
++ .name = "963281TAN::internet",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "963281TAN::power",
++ .gpio = 4,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "963281TAN::internet-fail",
++ .gpio = 7,
++ .active_low = 1,
++ },
++ {
++ .name = "963281TAN::power-fail",
++ .gpio = 8,
++ .active_low = 1,
++ },
++ {
++ .name = "963281TAN::wps",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "963281TAN::dsl",
++ .gpio = 11,
++ .active_low = 1,
++ },
++
++ },
++};
+ #endif
+
+ /*
+@@ -2322,6 +2392,7 @@ static struct board_info __initdata boar
+ static const struct board_info __initdata *bcm963xx_boards[] = {
+ #ifdef CONFIG_BCM63XX_CPU_6328
+ &board_96328avng,
++ &board_963281TAN,
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ &board_96338gw,
diff --git a/target/linux/brcm63xx/patches-3.3/524-board_dsl_274xb_rev_f.patch b/target/linux/brcm63xx/patches-3.3/524-board_dsl_274xb_rev_f.patch
new file mode 100644
index 000000000..b339d7476
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/524-board_dsl_274xb_rev_f.patch
@@ -0,0 +1,130 @@
+From 66808f706b3dcd83a9f5157997ff478a880a2906 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jonas.gorski@gmail.com>
+Date: Mon, 30 Apr 2012 09:10:51 +0200
+Subject: [PATCH 70/79] MIPS: BCM63XX: Add board definition for D-Link
+ DSL-274xB rev F1
+
+---
+ arch/mips/bcm63xx/boards/board_bcm963xx.c | 104 +++++++++++++++++++++++++++++
+ 1 files changed, 104 insertions(+), 0 deletions(-)
+
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -195,6 +195,109 @@ static struct board_info __initdata boar
+
+ },
+ };
++
++static struct board_info __initdata board_dsl_274xb_f1 = {
++ .name = "AW4339U",
++ .expected_cpu_id = 0x6328,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++
++ .has_caldata = 1,
++ .caldata = {
++ {
++ .caldata_offset = 0x7d1000,
++ .slot = 0,
++ },
++ },
++
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [0] = {
++ .used = 1,
++ .phy_id = 1,
++ .name = "Port 4",
++ },
++ [1] = {
++ .used = 1,
++ .phy_id = 2,
++ .name = "Port 3",
++ },
++ [2] = {
++ .used = 1,
++ .phy_id = 3,
++ .name = "Port 2",
++ },
++ [3] = {
++ .used = 1,
++ .phy_id = 4,
++ .name = "Port 1",
++ },
++ },
++ },
++
++ .leds = {
++ {
++ .name = "dsl-274xb:red:internet",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:green:dsl",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:green:power",
++ .gpio = 4,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "dsl-274xb:red:power",
++ .gpio = 8,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:blue:wps",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "dsl-274xb:green:internet",
++ .gpio = 11,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "wifi",
++ .gpio = 10,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "reset",
++ .gpio = 23,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 24,
++ .active_low = 1,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -2393,6 +2496,7 @@ static const struct board_info __initdat
+ #ifdef CONFIG_BCM63XX_CPU_6328
+ &board_96328avng,
+ &board_963281TAN,
++ &board_dsl_274xb_f1,
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ &board_96338gw,
diff --git a/target/linux/brcm63xx/patches-3.3/525-board_96348w3.patch b/target/linux/brcm63xx/patches-3.3/525-board_96348w3.patch
new file mode 100644
index 000000000..76425cd27
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/525-board_96348w3.patch
@@ -0,0 +1,68 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1334,6 +1334,57 @@ static struct board_info __initdata boar
+ },
+ };
+
++/* NetGear DG834G v4 */
++static struct board_info __initdata board_96348W3 = {
++ .name = "96348W3",
++ .expected_cpu_id = 0x6348,
++
++ .has_uart0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .has_ohci0 = 1,
++
++ .leds = {
++ {
++ .name = "96348W3:green:power",
++ .gpio = 0,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "96348W3:red:power",
++ .gpio = 1,
++ .active_low = 1,
++ },
++ {
++ .name = "96348W3::adsl",
++ .gpio = 2,
++ .active_low = 1,
++ },
++ {
++ .name = "96348W3::internet",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ },
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 6,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
++
+ #endif
+
+ /*
+@@ -2526,6 +2577,7 @@ static const struct board_info __initdat
+ &board_ct536_ct5621,
+ &board_96348A_122,
+ &board_CPVA502plus,
++ &board_96348W3,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6358
diff --git a/target/linux/brcm63xx/patches-3.3/526-board_CT6373-1.patch b/target/linux/brcm63xx/patches-3.3/526-board_CT6373-1.patch
new file mode 100644
index 000000000..58b209ed3
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/526-board_CT6373-1.patch
@@ -0,0 +1,136 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -51,6 +51,13 @@
+ #define NB4_SPI_GPIO_CLK 6
+ #define NB4_74HC64_GPIO(X) (NB4_74X164_GPIO_BASE + (X))
+
++#define CT6373_PID_OFFSET 0xff80
++#define CT6373_74X164_GPIO_BASE 64
++#define CT6373_SPI_GPIO_MOSI 7
++#define CT6373_SPI_GPIO_CLK 6
++#define CT6373_74HC64_GPIO(X) (CT6373_74X164_GPIO_BASE + (X))
++
++
+ static struct board_info board;
+
+ /*
+@@ -2261,6 +2268,111 @@ static struct board_info __initdata boar
+ .num_spis = ARRAY_SIZE(nb4_spi_devices),
+ };
+
++
++struct spi_gpio_platform_data ct6373_spi_gpio_data = {
++ .sck = CT6373_SPI_GPIO_CLK,
++ .mosi = CT6373_SPI_GPIO_MOSI,
++ .miso = SPI_GPIO_NO_MISO,
++ .num_chipselect = 1,
++};
++
++static struct platform_device ct6373_spi_gpio = {
++ .name = "spi_gpio",
++ .id = 1,
++ .dev = {
++ .platform_data = &ct6373_spi_gpio_data,
++ },
++};
++
++static struct platform_device * __initdata ct6373_devices[] = {
++ &ct6373_spi_gpio,
++};
++
++const struct gen_74x164_chip_platform_data ct6373_74x164_platform_data = {
++ .base = CT6373_74X164_GPIO_BASE
++};
++
++static struct spi_board_info ct6373_spi_devices[] = {
++ {
++ .modalias = "74x164",
++ .max_speed_hz = 781000,
++ .bus_num = 1,
++ .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT,
++ .mode = SPI_MODE_0,
++ .platform_data = &ct6373_74x164_platform_data
++ }
++};
++
++static struct board_info __initdata board_ct6373_1 = {
++ .name = "CT6373-1",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_pci = 1,
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++
++ .has_enet1 = 1,
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .leds = {
++ {
++ .name = "CT6373-1:green:power",
++ .gpio = 0,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "CT6373-1:green:usb",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "CT6373-1:green:wlan",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "CT6373-1:green:adsl",
++ .gpio = CT6373_74HC64_GPIO(0),
++ .active_low = 1,
++ },
++ {
++ .name = "CT6373-1:green:line",
++ .gpio = CT6373_74HC64_GPIO(1),
++ .active_low = 1,
++ },
++ {
++ .name = "CT6373-1:green:fxs1",
++ .gpio = CT6373_74HC64_GPIO(2),
++ .active_low = 1,
++ },
++ {
++ .name = "CT6373-1:green:fxs2",
++ .gpio = CT6373_74HC64_GPIO(3),
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 35,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++
++ .devs = ct6373_devices,
++ .num_devs = ARRAY_SIZE(ct6373_devices),
++ .spis = ct6373_spi_devices,
++ .num_spis = ARRAY_SIZE(ct6373_spi_devices),
++};
++
+ static struct board_info __initdata board_HW553 = {
+ .name = "HW553",
+ .expected_cpu_id = 0x6358,
+@@ -2592,6 +2704,7 @@ static const struct board_info __initdat
+ &board_nb4_ser_r2,
+ &board_nb4_fxc_r1,
+ &board_nb4_fxc_r2,
++ &board_ct6373_1,
+ &board_HW553,
+ &board_spw303v,
+ #endif
diff --git a/target/linux/brcm63xx/patches-3.3/527-board_dva-g3810bn-tl-1.patch b/target/linux/brcm63xx/patches-3.3/527-board_dva-g3810bn-tl-1.patch
new file mode 100644
index 000000000..fe47dc633
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/527-board_dva-g3810bn-tl-1.patch
@@ -0,0 +1,82 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -2512,6 +2512,71 @@ static struct board_info __initdata boar
+ },
+ }
+ };
++
++/* D-Link DVA-G3810BN/TL */
++static struct board_info __initdata board_DVAG3810BN = {
++ .name = "DVAG3810BN",
++ .expected_cpu_id = 0x6358,
++
++ .has_uart0 = 1,
++ .has_enet0 = 1,
++ .has_enet1 = 1,
++ .has_pci = 1,
++
++ .enet0 = {
++ .has_phy = 0,
++ .use_internal_phy = 1,
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++ .enet1 = {
++ .force_speed_100 = 1,
++ .force_duplex_full = 1,
++ },
++
++
++ .has_ohci0 = 1,
++ .has_pccard = 1,
++ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "DVAG3810BN::voip",
++ .gpio = 1,
++ },
++ {
++ .name = "DVAG3810BN::dsl",
++ .gpio = 22,
++ .active_low = 1,
++ },
++ {
++ .name = "DVAG3810BN::internet",
++ .gpio = 23,
++ .active_low = 1,
++ },
++ {
++ .name = "DVAG3810BN::power",
++ .gpio = 4,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "DVAG3810BN::stop",
++ .gpio = 5,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 34,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
++};
+ #endif
+
+ /*
+@@ -2707,6 +2772,7 @@ static const struct board_info __initdat
+ &board_ct6373_1,
+ &board_HW553,
+ &board_spw303v,
++ &board_DVAG3810BN,
+ #endif
+
+ #ifdef CONFIG_BCM63XX_CPU_6368
diff --git a/target/linux/brcm63xx/patches-3.3/528-board_nb6.patch b/target/linux/brcm63xx/patches-3.3/528-board_nb6.patch
new file mode 100644
index 000000000..e3f9382c0
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/528-board_nb6.patch
@@ -0,0 +1,146 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -17,6 +17,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi_gpio.h>
+ #include <linux/spi/74x164.h>
++#include <linux/rtl8367.h>
+ #include <asm/addrspace.h>
+ #include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+@@ -50,6 +51,8 @@
+ #define NB4_SPI_GPIO_MOSI 7
+ #define NB4_SPI_GPIO_CLK 6
+ #define NB4_74HC64_GPIO(X) (NB4_74X164_GPIO_BASE + (X))
++#define NB6_GPIO_RTL8367_SDA 18
++#define NB6_GPIO_RTL8367_SCK 20
+
+ #define CT6373_PID_OFFSET 0xff80
+ #define CT6373_74X164_GPIO_BASE 64
+@@ -2579,6 +2582,103 @@ static struct board_info __initdata boar
+ };
+ #endif
+
++#ifdef CONFIG_BCM63XX_CPU_6362
++static struct rtl8367_extif_config nb6_rtl8367_extif0_cfg = {
++ .mode = RTL8367_EXTIF_MODE_RGMII,
++ .txdelay = 1,
++ .rxdelay = 5,
++ .ability = {
++ .force_mode = 1,
++ .txpause = 1,
++ .rxpause = 1,
++ .link = 1,
++ .duplex = 1,
++ .speed = RTL8367_PORT_SPEED_1000,
++ },
++};
++
++static struct rtl8367_platform_data nb6_rtl8367_data = {
++ .gpio_sda = NB6_GPIO_RTL8367_SDA,
++ .gpio_sck = NB6_GPIO_RTL8367_SCK,
++ .extif0_cfg = &nb6_rtl8367_extif0_cfg,
++};
++
++static struct platform_device nb6_rtl8367_device = {
++ .name = RTL8367_DRIVER_NAME,
++ .id = -1,
++ .dev = {
++ .platform_data = &nb6_rtl8367_data,
++ }
++};
++
++static struct platform_device * __initdata nb6_devices[] = {
++ &nb6_rtl8367_device,
++};
++
++static struct board_info __initdata board_nb6 = {
++ .name = "NB6",
++ .expected_cpu_id = 0x6362,
++
++ .has_uart0 = 1,
++
++ .has_ohci0 = 1,
++ .has_ehci0 = 1,
++
++ .has_enetsw = 1,
++
++ .enetsw = {
++ .used_ports = {
++ [4] = {
++ .used = 1,
++ .phy_id = 0xff,
++ .bypass_link = 1,
++ .force_speed = 1000,
++ .force_duplex_full = 1,
++ .name = "RGMII",
++ },
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 24,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ .active_low = 1,
++ },
++ {
++ .desc = "wps",
++ .gpio = 25,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ .active_low = 1,
++ },
++ {
++ .desc = "wlan",
++ .gpio = 12,
++ .type = EV_KEY,
++ .code = KEY_WLAN,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ .active_low = 1,
++ },
++ {
++ .desc = "service",
++ .gpio = 10,
++ .type = EV_KEY,
++ .code = BTN_0,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ .active_low = 1,
++ },
++ },
++
++ .devs = nb6_devices,
++ .num_devs = ARRAY_SIZE(nb6_devices),
++};
++#endif
++
+ /*
+ * known 6368 boards
+ */
+@@ -2775,6 +2875,10 @@ static const struct board_info __initdat
+ &board_DVAG3810BN,
+ #endif
+
++#ifdef CONFIG_BCM63XX_CPU_6362
++ &board_nb6,
++#endif
++
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ &board_96368mvwg,
+ &board_96368mvngr,
+@@ -2842,6 +2946,11 @@ static void __init boardid_fixup(u8 *boo
+ }
+ }
+
++ if (BCMCPU_IS_6362() && (!strncmp(board_name, "NB6-", sizeof("NB6-") - 1))) {
++ board_name[sizeof("NB6") - 1] = '\0';
++ return ;
++ }
++
+ /* check if bcm_tag is at 64k offset */
+ if (strncmp(board_name, tag->boardid, BOARDID_LEN) != 0) {
+ /* else try 128k */
diff --git a/target/linux/brcm63xx/patches-3.3/550-alice_gate2_leds.patch b/target/linux/brcm63xx/patches-3.3/550-alice_gate2_leds.patch
new file mode 100644
index 000000000..98b988df1
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/550-alice_gate2_leds.patch
@@ -0,0 +1,102 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1612,6 +1612,99 @@ static struct board_info __initdata boar
+
+ .has_ohci0 = 1,
+ .has_ehci0 = 1,
++
++ .leds = {
++ {
++ .name = "AGPF-S0:red:power",
++ .gpio = 5,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:power",
++ .gpio = 4,
++ .active_low = 1,
++ .default_trigger = "default-on",
++ },
++ {
++ .name = "AGPF-S0:red:service",
++ .gpio = 7,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:service",
++ .gpio = 6,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:adsl",
++ .gpio = 9,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:red:adsl",
++ .gpio = 10,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:red:wifi",
++ .gpio = 23,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:wifi",
++ .gpio = 22,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:internet",
++ .gpio = 25,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:red:internet",
++ .gpio = 24,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:red:usr1",
++ .gpio = 27,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:usr1",
++ .gpio = 26,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:red:usr2",
++ .gpio = 30,
++ .active_low = 1,
++ },
++ {
++ .name = "AGPF-S0:green:usr2",
++ .gpio = 29,
++ .active_low = 1,
++ },
++ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 37,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ {
++ .desc = "wps",
++ .gpio = 34,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_WPS_BUTTON,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
+ };
+
+ static struct board_info __initdata board_DWVS0 = {
diff --git a/target/linux/brcm63xx/patches-3.3/551-96348gw_a_leds.patch b/target/linux/brcm63xx/patches-3.3/551-96348gw_a_leds.patch
new file mode 100644
index 000000000..816e8164c
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/551-96348gw_a_leds.patch
@@ -0,0 +1,22 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -1069,6 +1069,19 @@ static struct board_info __initdata boar
+ },
+
+ .has_ohci0 = 1,
++
++ .leds = {
++ {
++ .name = "96348GW-A::adsl",
++ .gpio = 3,
++ .active_low = 1,
++ },
++ {
++ .name = "96348GW-A::usb",
++ .gpio = 0,
++ .active_low = 1,
++ }
++ },
+ };
+
+ static struct board_info __initdata board_96348_D4PW = {
diff --git a/target/linux/brcm63xx/patches-3.3/552-board_96348gw-10_reset_button.patch b/target/linux/brcm63xx/patches-3.3/552-board_96348gw-10_reset_button.patch
new file mode 100644
index 000000000..3c0fe8b9d
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/552-board_96348gw-10_reset_button.patch
@@ -0,0 +1,20 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -586,6 +586,17 @@ static struct board_info __initdata boar
+ .active_low = 1,
+ },
+ },
++
++ .buttons = {
++ {
++ .desc = "reset",
++ .gpio = 6,
++ .active_low = 1,
++ .type = EV_KEY,
++ .code = KEY_RESTART,
++ .debounce_interval = BCM963XX_KEYS_DEBOUNCE_INTERVAL,
++ },
++ },
+ };
+
+ static struct board_info __initdata board_96348gw_11 = {
diff --git a/target/linux/brcm63xx/patches-3.3/800-wl_exports.patch b/target/linux/brcm63xx/patches-3.3/800-wl_exports.patch
new file mode 100644
index 000000000..0fff4d0b1
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/800-wl_exports.patch
@@ -0,0 +1,34 @@
+--- a/arch/mips/bcm63xx/nvram.c
++++ b/arch/mips/bcm63xx/nvram.c
+@@ -19,6 +19,13 @@
+ static struct bcm963xx_nvram nvram;
+ static int mac_addr_used;
+
++/*
++ * Required export for WL
++ */
++#define NVRAM_SPACE 0x8000
++char nvram_buf[NVRAM_SPACE];
++EXPORT_SYMBOL(nvram_buf);
++
+ int __init bcm63xx_nvram_init(void *addr)
+ {
+ unsigned int check_len;
+@@ -27,6 +34,7 @@ int __init bcm63xx_nvram_init(void *addr
+
+ /* extract nvram data */
+ memcpy(&nvram, addr, sizeof(nvram));
++ memcpy(&nvram_buf, addr, NVRAM_SPACE);
+
+ /* check checksum before using data */
+ if (nvram.version <= 4)
+--- a/arch/mips/mm/cache.c
++++ b/arch/mips/mm/cache.c
+@@ -58,6 +58,7 @@ void (*_dma_cache_wback)(unsigned long s
+ void (*_dma_cache_inv)(unsigned long start, unsigned long size);
+
+ EXPORT_SYMBOL(_dma_cache_wback_inv);
++EXPORT_SYMBOL(_dma_cache_inv);
+
+ #endif /* CONFIG_DMA_NONCOHERENT */
+
diff --git a/target/linux/brcm63xx/patches-3.3/801-ssb_export_fallback_sprom.patch b/target/linux/brcm63xx/patches-3.3/801-ssb_export_fallback_sprom.patch
new file mode 100644
index 000000000..724c849b4
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/801-ssb_export_fallback_sprom.patch
@@ -0,0 +1,27 @@
+--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
++++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
+@@ -14,6 +14,7 @@
+ #include <linux/ssb/ssb.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
++#include <linux/export.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi_gpio.h>
+ #include <linux/spi/74x164.h>
+@@ -3007,7 +3008,7 @@ static const struct board_info __initdat
+ * bcm4318 WLAN work
+ */
+ #ifdef CONFIG_SSB_PCIHOST
+-static struct ssb_sprom bcm63xx_sprom = {
++struct ssb_sprom bcm63xx_sprom = {
+ .revision = 0x02,
+ .board_rev = 0x17,
+ .country_code = 0x0,
+@@ -3027,6 +3028,7 @@ static struct ssb_sprom bcm63xx_sprom =
+ .boardflags_lo = 0x2848,
+ .boardflags_hi = 0x0000,
+ };
++EXPORT_SYMBOL(bcm63xx_sprom);
+
+ int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
+ {
diff --git a/target/linux/brcm63xx/patches-3.3/802-rtl8367r_fix_RGMII_support.patch b/target/linux/brcm63xx/patches-3.3/802-rtl8367r_fix_RGMII_support.patch
new file mode 100644
index 000000000..285f3f744
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.3/802-rtl8367r_fix_RGMII_support.patch
@@ -0,0 +1,30 @@
+From e3208e6087642b95a5bab3101fc9c6e34892c861 Mon Sep 17 00:00:00 2001
+From: Miguel GAIO <miguel.gaio@efixo.com>
+Date: Fri, 6 Jul 2012 14:12:33 +0200
+Subject: [PATCH 6/8] * [rtl8367r] Fix RGMII support
+
+---
+ drivers/net/phy/rtl8367.c | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+--- a/drivers/net/phy/rtl8367.c
++++ b/drivers/net/phy/rtl8367.c
+@@ -144,6 +144,10 @@
+ #define RTL8367_EXT_RGMXF_TXDELAY_MASK 1
+ #define RTL8367_EXT_RGMXF_RXDELAY_MASK 0x7
+
++#define RTL8367_PHY_AD_REG 0x130f
++#define RTL8370_PHY_AD_DUMMY_1_OFFSET 5
++#define RTL8370_PHY_AD_DUMMY_1_MASK 0xe0
++
+ #define RTL8367_DI_FORCE_REG(_x) (0x1310 + (_x))
+ #define RTL8367_DI_FORCE_MODE BIT(12)
+ #define RTL8367_DI_FORCE_NWAY BIT(7)
+@@ -892,6 +896,7 @@ static int rtl8367_extif_set_mode(struct
+ case RTL8367_EXTIF_MODE_RGMII_33V:
+ REG_WR(smi, RTL8367_CHIP_DEBUG0_REG, 0x0367);
+ REG_WR(smi, RTL8367_CHIP_DEBUG1_REG, 0x7777);
++ REG_RMW(smi, RTL8367_PHY_AD_REG, BIT(5), 0);
+ break;
+
+ case RTL8367_EXTIF_MODE_TMII_MAC:
diff --git a/target/linux/brcm63xx/profiles/100-Broadcom.mk b/target/linux/brcm63xx/profiles/100-Broadcom.mk
new file mode 100644
index 000000000..bc68f1493
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/100-Broadcom.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Broadcom
+ NAME:=Broadcom WiFi (default)
+ PACKAGES:=kmod-b43 wpad-mini
+endef
+
+define Profile/Broadcom/Description
+ Package set compatible with hardware using Broadcom WiFi cards
+endef
+$(eval $(call Profile,Broadcom))
+
diff --git a/target/linux/brcm63xx/profiles/101-Broadcom-wl.mk b/target/linux/brcm63xx/profiles/101-Broadcom-wl.mk
new file mode 100644
index 000000000..4f2d605eb
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/101-Broadcom-wl.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Broadcom-wl
+ NAME:=Broadcom BCM43xx WiFi (wl, proprietary)
+ PACKAGES:= kmod-brcm-wl wlc nas
+endef
+
+define Profile/Broadcom-wl/Description
+ Package set compatible with hardware using Broadcom BCM43xx cards
+ using the proprietary broadcom wireless "wl" driver.
+endef
+
+$(eval $(call Profile,Broadcom-wl))
+
diff --git a/target/linux/brcm63xx/profiles/102-Atheros.mk b/target/linux/brcm63xx/profiles/102-Atheros.mk
new file mode 100644
index 000000000..b214185c5
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/102-Atheros.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Atheros
+ NAME:=Atheros WiFi (default)
+ PACKAGES:=kmod-ath5k kmod-ath9k wpad-mini
+endef
+
+define Profile/Atheros/Description
+ Package set compatible with hardware using Atheros WiFi cards
+endef
+$(eval $(call Profile,Atheros))
+
diff --git a/target/linux/brcm63xx/profiles/103-Ralink.mk b/target/linux/brcm63xx/profiles/103-Ralink.mk
new file mode 100644
index 000000000..412c5a45a
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/103-Ralink.mk
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Ralink
+ NAME:=Ralink WiFi
+ PACKAGES:=kmod-rt61-pci wpad-mini
+endef
+$(eval $(call Profile,Ralink))
+
diff --git a/target/linux/brcm63xx/profiles/104-No-WiFi.mk b/target/linux/brcm63xx/profiles/104-No-WiFi.mk
new file mode 100644
index 000000000..9d32da60b
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/104-No-WiFi.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/NoWiFi
+ NAME:=No WiFi (BCM6338)
+ PACKAGES:=kmod-bcm63xx-spi
+endef
+
+define Profile/NoWiFi/description
+ Package set compatible with BCM63xx routers without Wi-Fi (e.g: BCM6338-based).
+endef
+
+$(eval $(call Profile,NoWiFi))
diff --git a/target/linux/brcm63xx/profiles/105-Broadcom-brcmsmac.mk b/target/linux/brcm63xx/profiles/105-Broadcom-brcmsmac.mk
new file mode 100644
index 000000000..bb558d139
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/105-Broadcom-brcmsmac.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/Broadcom-brcmsmac
+ NAME:=Broadcom WiFi (brcmsmac)
+ PACKAGES:=kmod-brcmsmac wpad-mini
+endef
+
+define Profile/Broadcom-brcmsmac/Description
+ Package set compatible with hardware using Broadcom WiFi cards
+endef
+$(eval $(call Profile,Broadcom-brcmsmac))
+
diff --git a/target/linux/brcm63xx/profiles/200-GW6X00.mk b/target/linux/brcm63xx/profiles/200-GW6X00.mk
new file mode 100644
index 000000000..b1c516a8b
--- /dev/null
+++ b/target/linux/brcm63xx/profiles/200-GW6X00.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/GW6X00
+ NAME:=Tecom GW6X00
+ PACKAGES:=kmod-brcm-wl kmod-usb-core kmod-usb-ohci kmod-usb-storage \
+ kmod-fs-ext4 kmod-nls-cp437 kmod-nls-iso8859-1 e2fsprogs \
+ kmod-bcm63xx-spi \
+ kmod-ipt-nathelper-extra wlc
+endef
+
+define Profile/GW6X00/Description
+ Package set compatible with the Tecom GW6000 and GW6200 based
+ on the BCM96348GW reference design.
+endef
+$(eval $(call Profile,GW6X00))
+