From b756e8c6708a2ab07388667e0d5399ddf020621b Mon Sep 17 00:00:00 2001
From: hauke <hauke@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Thu, 25 Jun 2015 21:33:53 +0000
Subject: [PATCH] bcm53xx: add support for kernel 4.1

This only removes the patches already applied upstream and makes the
rest apply cleanly.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>


git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46128 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 target/linux/bcm53xx/config-4.1               |  312 ++++
 ...-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch |   26 +
 ...5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch |  157 ++
 ...-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch |  148 ++
 ...RM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch |  112 ++
 ...RM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch |  125 ++
 ...ore-another-BCM4709-specific-fault-c.patch |   41 +
 ...301X-add-NAND-flash-chip-description.patch |  210 +++
 ...-add-IRQ-numbers-for-PCIe-controller.patch |   48 +
 ...RM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch |   95 +
 .../110-firmware-backport-NVRAM-driver.patch  |   49 +
 .../112-bcm53xx-sprom-add-sprom-driver.patch  |   69 +
 ...1-ARM-BCM5301X-Implement-SMP-support.patch |  314 ++++
 ...2-bcma-add-new-PCIe2-driver-for-bcma.patch |  534 ++++++
 .../180-USB-bcma-remove-chip-id-check.patch   |   34 +
 ...-bcma-replace-numbers-with-constants.patch |   24 +
 .../182-USB-bcma-use-devm_kzalloc.patch       |   47 +
 ...ror-handling-in-bcma_hcd_create_pdev.patch |   33 +
 .../184-USB-bcma-add-bcm53xx-support.patch    |  133 ++
 ...port-for-controlling-bus-power-throu.patch |   82 +
 ...ble-MMU-and-Dcache-for-decompression.patch |  195 ++
 .../301-ARM-BCM5301X-Add-SPROM.patch          |   26 +
 ...Enable-earlyprintk-on-tested-devices.patch |  148 ++
 ...05-ARM-BCM53XX-set-customized-AUXCTL.patch |   30 +
 ...cify-RAM-on-devices-by-including-HIG.patch |  161 ++
 ...-Buffalo-WXR-1900DHP-clock-and-USB-p.patch |   41 +
 ...01X-Set-vcc-gpio-for-USB-controllers.patch |   63 +
 ...power-button-for-Buffalo-WZR-1750DHP.patch |   20 +
 ...0-ARM-BCM5301X-Add-profiling-support.patch |   20 +
 ...nable-ChipCommon-UART-serial-console.patch |  250 +++
 ...-back-Luxul-XWC-1000-NAND-flash-layo.patch |   37 +
 ...t-scan-whole-flash-on-ARCH_BCM_5301X.patch |   31 +
 ...ash-new-driver-for-SPI-flahes-on-Bro.patch |   19 +
 .../patches-4.1/420-mtd-bcm5301x_nand.patch   | 1608 +++++++++++++++++
 ...-mark-and-erase-all-remaining-blocks.patch |   59 +
 ...-support-for-the-3rd-bus-core-device.patch |   63 +
 ...U-port-fixes-for-devices-not-using-p.patch |   35 +
 ...-two-different-initcalls-if-built-in.patch |   65 +
 ...lper-creating-platform-dev-more-gene.patch |   73 +
 ...arated-function-for-USB-2.0-initiali.patch |  102 ++
 .../812-USB-bcma-add-USB-3.0-support.patch    |  274 +++
 ...-USB-bcma-fix-setting-VCC-GPIO-value.patch |   45 +
 ...-add-Broadcom-specific-fake-doorbell.patch |   94 +
 ...workaround-for-Asus-RT-AC87U-asus-pa.patch |   42 +
 44 files changed, 6094 insertions(+)
 create mode 100644 target/linux/bcm53xx/config-4.1
 create mode 100644 target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch
 create mode 100644 target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch

diff --git a/target/linux/bcm53xx/config-4.1 b/target/linux/bcm53xx/config-4.1
new file mode 100644
index 0000000000..8daa3aa2a5
--- /dev/null
+++ b/target/linux/bcm53xx/config-4.1
@@ -0,0 +1,312 @@
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_ARCH_ALPINE is not set
+CONFIG_ARCH_BCM=y
+# CONFIG_ARCH_BCM_21664 is not set
+# CONFIG_ARCH_BCM_281XX is not set
+CONFIG_ARCH_BCM_5301X=y
+# CONFIG_ARCH_BCM_63XX is not set
+# CONFIG_ARCH_BCM_CYGNUS is not set
+CONFIG_ARCH_BCM_IPROC=y
+# CONFIG_ARCH_BRCMSTB is not set
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_ARCH_HAS_TICK_BROADCAST=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+CONFIG_ARCH_MULTI_V6_V7=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARM=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_APPENDED_DTB=y
+# CONFIG_ARM_ATAG_DTB_COMPAT is not set
+# CONFIG_ARM_CPU_SUSPEND is not set
+# CONFIG_ARM_CRYPTO is not set
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_ARM_ERRATA_798181=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GLOBAL_TIMER=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+# CONFIG_ARM_LPAE is not set
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_ATAGS=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_B53=y
+# CONFIG_B53_MMAP_DRIVER is not set
+# CONFIG_B53_PHY_DRIVER is not set
+CONFIG_B53_SRAB_DRIVER=y
+CONFIG_BCM47XX_NVRAM=y
+CONFIG_BCM47XX_SPROM=y
+CONFIG_BCM47XX_WDT=y
+CONFIG_BCMA=y
+CONFIG_BCMA_BLOCKIO=y
+CONFIG_BCMA_DEBUG=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_BCMA_DRIVER_GPIO=y
+CONFIG_BCMA_DRIVER_PCI=y
+CONFIG_BCMA_HOST_PCI=y
+CONFIG_BCMA_HOST_PCI_POSSIBLE=y
+CONFIG_BCMA_HOST_SOC=y
+CONFIG_BGMAC=y
+CONFIG_BOUNCE=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLKSRC_OF=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_XZ=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BCM_5301X=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_INCLUDE="debug/8250.S"
+CONFIG_DEBUG_UART_8250=y
+# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set
+CONFIG_DEBUG_UART_8250_SHIFT=0
+CONFIG_DEBUG_UART_PHYS=0x18000300
+CONFIG_DEBUG_UART_VIRT=0xf1000300
+CONFIG_DEBUG_UNCOMPRESS=y
+CONFIG_DEBUG_USER=y
+CONFIG_DTC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_FIXED_PHY=y
+CONFIG_FRAME_POINTER=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_74X164=y
+CONFIG_GPIO_DEVRES=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_HAVE_BPF_JIT=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SMP=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_UID16=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_PERIODIC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IOMMU_HELPER=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+# CONFIG_LZ4_COMPRESS is not set
+# CONFIG_LZ4_DECOMPRESS is not set
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_BCM47XX_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_BCM=y
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_PHYSMAP_OF is not set
+CONFIG_MTD_SPI_BCM53XXSPIFLASH=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_BLOCK=y
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+# CONFIG_MULTIUSER is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NR_CPUS=4
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_ADDRESS_PCI=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+CONFIG_OF_NET=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+CONFIG_OLD_SIGACTION=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PCI=y
+# CONFIG_PCIE_IPROC is not set
+# CONFIG_PCIE_IPROC_PLATFORM is not set
+CONFIG_PCI_BCM5301X=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PL310_ERRATA_588369 is not set
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_PL310_ERRATA_769419=y
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_SCHED_HRTICK=y
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_BCM53XX=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_MASTER=y
+CONFIG_SRCU=y
+CONFIG_STOP_MACHINE=y
+CONFIG_SWCONFIG=y
+CONFIG_SWIOTLB=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TREE_RCU=y
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_XZ=y
+CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_USB_SUPPORT=y
+CONFIG_USE_OF=y
+# CONFIG_VDSO is not set
+CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_VFP is not set
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_XEN is not set
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch
new file mode 100644
index 0000000000..290ea0aea9
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch
@@ -0,0 +1,26 @@
+From 35ad0e50bd6683c6699586e3bd5045f0695586d9 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 13 May 2015 09:10:51 +0200
+Subject: [PATCH] ARM: BCM5301X: Add USB LED for Buffalo WZR-1750DHP
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -47,6 +47,12 @@
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
++		usb {
++			label = "bcm53xx:blue:usb";
++			gpios = <&hc595 0 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
+ 		power0 {
+ 			label = "bcm53xx:red:power";
+ 			gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
diff --git a/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch b/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch
new file mode 100644
index 0000000000..e16d39b423
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch
@@ -0,0 +1,157 @@
+From 35eecd10ee57b9d4f31e12598296b235ed2b34ae Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 13 May 2015 09:10:52 +0200
+Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WXR-1900DHP
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/Makefile                        |   1 +
+ arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 127 ++++++++++++++++++++++
+ 2 files changed, 128 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -63,6 +63,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+ 	bcm47081-asus-rt-n18u.dtb \
+ 	bcm47081-buffalo-wzr-600dhp2.dtb \
+ 	bcm47081-buffalo-wzr-900dhp.dtb \
++	bcm4709-buffalo-wxr-1900dhp.dtb \
+ 	bcm4709-netgear-r8000.dtb
+ dtb-$(CONFIG_ARCH_BCM_63XX) += \
+ 	bcm963138dvt.dtb
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -0,0 +1,127 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ * DTS for Buffalo WXR-1900DHP
++ *
++ * Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++
++/ {
++	compatible = "buffalo,wxr-1900dhp", "brcm,bcm4709", "brcm,bcm4708";
++	model = "Buffalo WXR-1900DHP";
++
++	chosen {
++		bootargs = "console=ttyS0,115200";
++	};
++
++	memory {
++		reg = <0x00000000 0x08000000>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		usb {
++			label = "bcm53xx:green:usb";
++			gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		power-amber {
++			label = "bcm53xx:amber:power";
++			gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		power-white {
++			label = "bcm53xx:white:power";
++			gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-on";
++		};
++
++		router-amber {
++			label = "bcm53xx:amber:router";
++			gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		router-white {
++			label = "bcm53xx:white:router";
++			gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wan-amber {
++			label = "bcm53xx:amber:wan";
++			gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wan-white {
++			label = "bcm53xx:white:wan";
++			gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wireless-amber {
++			label = "bcm53xx:amber:wireless";
++			gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wireless-white {
++			label = "bcm53xx:white:wireless";
++			gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++	};
++
++	gpio-keys {
++		compatible = "gpio-keys";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		power {
++			label = "Power";
++			linux,code = <KEY_POWER>;
++			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
++		};
++
++		restart {
++			label = "Reset";
++			linux,code = <KEY_RESTART>;
++			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
++		};
++
++		aoss {
++			label = "AOSS";
++			linux,code = <KEY_WPS_BUTTON>;
++			gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>;
++		};
++
++		/* Commit mode set by switch? */
++		mode {
++			label = "Mode";
++			linux,code = <KEY_SETUP>;
++			gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
++		};
++
++		/* Switch: AP mode */
++		sw_ap {
++			label = "AP";
++			linux,code = <BTN_0>;
++			gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
++		};
++
++		eject {
++			label = "USB eject";
++			linux,code = <KEY_EJECTCD>;
++			gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>;
++		};
++	};
++};
diff --git a/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch b/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch
new file mode 100644
index 0000000000..dafae7b170
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch
@@ -0,0 +1,148 @@
+From 691917f20cae813d242f7123a4dc97e7d48e6ff1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 13 May 2015 09:10:53 +0200
+Subject: [PATCH] ARM: BCM5301X: Add DT for SmartRG SR400ac
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/Makefile                    |   1 +
+ arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts | 119 ++++++++++++++++++++++++++
+ 2 files changed, 120 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -60,6 +60,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+ 	bcm4708-luxul-xwc-1000.dtb \
+ 	bcm4708-netgear-r6250.dtb \
+ 	bcm4708-netgear-r6300-v2.dtb \
++	bcm4708-smartrg-sr400ac.dtb \
+ 	bcm47081-asus-rt-n18u.dtb \
+ 	bcm47081-buffalo-wzr-600dhp2.dtb \
+ 	bcm47081-buffalo-wzr-900dhp.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+@@ -0,0 +1,119 @@
++/*
++ * Broadcom BCM470X / BCM5301X arm platform code.
++ * DTS for SmartRG SR400ac
++ *
++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++
++/ {
++	compatible = "smartrg,sr400ac", "brcm,bcm4708";
++	model = "SmartRG SR400ac";
++
++	chosen {
++		bootargs = "console=ttyS0,115200";
++	};
++
++	memory {
++		reg = <0x00000000 0x08000000>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		power-white {
++			label = "bcm53xx:white:power";
++			gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-on";
++		};
++
++		power-amber {
++			label = "bcm53xx:amber:power";
++			gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		usb2 {
++			label = "bcm53xx:white:usb2";
++			gpios = <&chipcommon 3 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		usb3-white {
++			label = "bcm53xx:white:usb3";
++			gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		usb3-green {
++			label = "bcm53xx:green:usb3";
++			gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wps {
++			label = "bcm53xx:white:wps";
++			gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		status-red {
++			label = "bcm53xx:red:status";
++			gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		status-green {
++			label = "bcm53xx:green:status";
++			gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		status-blue {
++			label = "bcm53xx:blue:status";
++			gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wan-white {
++			label = "bcm53xx:white:wan";
++			gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++
++		wan-red {
++			label = "bcm53xx:red:wan";
++			gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
++			linux,default-trigger = "default-off";
++		};
++	};
++
++	gpio-keys {
++		compatible = "gpio-keys";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		rfkill {
++			label = "WiFi";
++			linux,code = <KEY_RFKILL>;
++			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
++		};
++
++		wps {
++			label = "WPS";
++			linux,code = <KEY_WPS_BUTTON>;
++			gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
++		};
++
++		restart {
++			label = "Reset";
++			linux,code = <KEY_RESTART>;
++			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
++		};
++	};
++};
diff --git a/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch b/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch
new file mode 100644
index 0000000000..02e644e7c0
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch
@@ -0,0 +1,112 @@
+From b5f350c790ae6aaf3dda5a825d7e3fdeed731164 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sat, 28 Mar 2015 15:01:38 +0100
+Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC68U
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/Makefile                  |  1 +
+ arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts | 83 +++++++++++++++++++++++++++++
+ 2 files changed, 84 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ 	bcm2835-rpi-b.dtb \
+ 	bcm2835-rpi-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
++	bcm4708-asus-rt-ac68u.dtb \
+ 	bcm4708-buffalo-wzr-1750dhp.dtb \
+ 	bcm4708-luxul-xwc-1000.dtb \
+ 	bcm4708-netgear-r6250.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+@@ -0,0 +1,83 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ * DTS for Asus RT-AC68U
++ *
++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++
++/ {
++	compatible = "asus,rt-ac68u", "brcm,bcm4708";
++	model = "Asus RT-AC68U (BCM4708)";
++
++	chosen {
++		bootargs = "console=ttyS0,115200";
++	};
++
++	memory {
++		reg = <0x00000000 0x08000000>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		usb2 {
++			label = "bcm53xx:blue:usb2";
++			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++		power {
++			label = "bcm53xx:blue:power";
++			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-on";
++		};
++
++		logo {
++			label = "bcm53xx:white:logo";
++			gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-on";
++		};
++
++		usb3 {
++			label = "bcm53xx:blue:usb3";
++			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++	};
++
++	gpio-keys {
++		compatible = "gpio-keys";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		brightness {
++			label = "Backlight";
++			linux,code = <KEY_BRIGHTNESS_ZERO>;
++			gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
++		};
++
++		wps {
++			label = "WPS";
++			linux,code = <KEY_WPS_BUTTON>;
++			gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
++		};
++
++		restart {
++			label = "Reset";
++			linux,code = <KEY_RESTART>;
++			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
++		};
++
++		rfkill {
++			label = "WiFi";
++			linux,code = <KEY_RFKILL>;
++			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
++		};
++	};
++};
diff --git a/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch b/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch
new file mode 100644
index 0000000000..e72835b186
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch
@@ -0,0 +1,125 @@
+From 16dc3bac722252a10e396546f44135ae1b6a7ff3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 31 Mar 2015 17:29:18 +0200
+Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC56U
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/Makefile                  |  1 +
+ arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts | 96 +++++++++++++++++++++++++++++
+ 2 files changed, 97 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
+ 	bcm2835-rpi-b.dtb \
+ 	bcm2835-rpi-b-plus.dtb
+ dtb-$(CONFIG_ARCH_BCM_5301X) += \
++	bcm4708-asus-rt-ac56u.dtb \
+ 	bcm4708-asus-rt-ac68u.dtb \
+ 	bcm4708-buffalo-wzr-1750dhp.dtb \
+ 	bcm4708-luxul-xwc-1000.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+@@ -0,0 +1,96 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ * DTS for Asus RT-AC56U
++ *
++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++
++/ {
++	compatible = "asus,rt-ac56u", "brcm,bcm4708";
++	model = "Asus RT-AC56U (BCM4708)";
++
++	chosen {
++		bootargs = "console=ttyS0,115200";
++	};
++
++	memory {
++		reg = <0x00000000 0x08000000>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		usb3 {
++			label = "bcm53xx:blue:usb3";
++			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++		wan {
++			label = "bcm53xx:blue:wan";
++			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++		lan {
++			label = "bcm53xx:blue:lan";
++			gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++		power {
++			label = "bcm53xx:blue:power";
++			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-on";
++		};
++
++		all {
++			label = "bcm53xx:blue:all";
++			gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-on";
++		};
++
++		2ghz {
++			label = "bcm53xx:blue:2ghz";
++			gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++
++		usb2 {
++			label = "bcm53xx:blue:usb2";
++			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++	};
++
++	gpio-keys {
++		compatible = "gpio-keys";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		rfkill {
++			label = "WiFi";
++			linux,code = <KEY_RFKILL>;
++			gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
++		};
++
++		restart {
++			label = "Reset";
++			linux,code = <KEY_RESTART>;
++			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
++		};
++
++		wps {
++			label = "WPS";
++			linux,code = <KEY_WPS_BUTTON>;
++			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
++		};
++	};
++};
diff --git a/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch b/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch
new file mode 100644
index 0000000000..8716a0d5c6
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch
@@ -0,0 +1,41 @@
+From 7eb68a2a0519a77b93184c695d4d293c92dc2286 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 11 Feb 2015 16:40:58 +0100
+Subject: [PATCH] ARM: BCM5301X: Ignore another (BCM4709 specific) fault code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Broadcom ARM devices seem to generate some fault once per boot. We
+already have an ignoring handler for BCM4707/BCM4708, but BCM4709
+generates different code.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/mach-bcm/bcm_5301x.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/mach-bcm/bcm_5301x.c
++++ b/arch/arm/mach-bcm/bcm_5301x.c
+@@ -18,15 +18,16 @@ static bool first_fault = true;
+ static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr,
+ 				 struct pt_regs *regs)
+ {
+-	if (fsr == 0x1c06 && first_fault) {
++	if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) {
+ 		first_fault = false;
+ 
+ 		/*
+-		 * These faults with code 0x1c06 happens for no good reason,
+-		 * possibly left over from the CFE boot loader.
++		 * These faults with codes 0x1406 (BCM4709) or 0x1c06 happens
++		 * for no good reason, possibly left over from the CFE boot
++		 * loader.
+ 		 */
+ 		pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n",
+-		addr, fsr);
++			addr, fsr);
+ 
+ 		/* Returning non-zero causes fault display and panic */
+ 		return 0;
diff --git a/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch b/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch
new file mode 100644
index 0000000000..aa99f3758c
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch
@@ -0,0 +1,210 @@
+From 9faa5960eef3204cae6637b530f5e23e53b5a9ef Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Fri, 29 May 2015 23:39:47 +0200
+Subject: [PATCH] ARM: BCM5301X: add NAND flash chip description
+
+This adds the NAND flash chip description for a standard chip found
+connected to this SoC. This makes use of generic Broadcom NAND driver
+with the iProc interface.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts        |  1 +
+ arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts        |  1 +
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  |  1 +
+ arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts       |  9 +++-----
+ arch/arm/boot/dts/bcm4708-netgear-r6250.dts        |  1 +
+ arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts     |  1 +
+ arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts      |  1 +
+ arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts        |  1 +
+ arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts |  1 +
+ arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts  |  1 +
+ arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts  |  1 +
+ arch/arm/boot/dts/bcm4709-netgear-r8000.dts        |  1 +
+ arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi      | 24 ++++++++++++++++++++++
+ arch/arm/boot/dts/bcm5301x.dtsi                    | 12 +++++++++++
+ 14 files changed, 50 insertions(+), 6 deletions(-)
+ create mode 100644 arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
+
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "asus,rt-ac56u", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "asus,rt-ac68u", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "buffalo,wzr-1750dhp", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "luxul,xwc-1000", "brcm,bcm4708";
+@@ -23,12 +24,8 @@
+ 		reg = <0x00000000 0x08000000>;
+ 	};
+ 
+-	axi@18000000 {
+-		nand@28000 {
+-			reg = <0x00028000 0x1000>;
+-			#address-cells = <1>;
+-			#size-cells = <1>;
+-
++	nand: nand@18028000 {
++		nandcs@0 {
+ 			partition@0 {
+ 				label = "ubi";
+ 				reg = <0x00000000 0x08000000>;
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "netgear,r6250v1", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "netgear,r6300v2", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "smartrg,sr400ac", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm47081.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "asus,rt-n18u", "brcm,bcm47081", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm47081.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "buffalo,wzr-600dhp2", "brcm,bcm47081", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm47081.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "buffalo,wzr-900dhp", "brcm,bcm47081", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "buffalo,wxr-1900dhp", "brcm,bcm4709", "brcm,bcm4708";
+--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+@@ -10,6 +10,7 @@
+ /dts-v1/;
+ 
+ #include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
+ 
+ / {
+ 	compatible = "netgear,r8000", "brcm,bcm4709", "brcm,bcm4708";
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
+@@ -0,0 +1,24 @@
++/*
++ * Broadcom BCM470X / BCM5301X Nand chip defaults.
++ *
++ * This should be included if the NAND controller is on chip select 0
++ * and uses 8 bit ECC.
++ *
++ * Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/ {
++	nand@18028000 {
++		nandcs@0 {
++			compatible = "brcm,nandcs";
++			reg = <0>;
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			nand-ecc-strength = <8>;
++			nand-ecc-step-size = <512>;
++		};
++	};
++};
+--- a/arch/arm/boot/dts/bcm5301x.dtsi
++++ b/arch/arm/boot/dts/bcm5301x.dtsi
+@@ -143,4 +143,16 @@
+ 			#gpio-cells = <2>;
+ 		};
+ 	};
++
++	nand: nand@18028000 {
++		compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand";
++		reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>;
++		reg-names = "nand", "iproc-idm", "iproc-ext";
++		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
++
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		brcm,nand-has-wp;
++	};
+ };
diff --git a/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch b/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch
new file mode 100644
index 0000000000..142211520e
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch
@@ -0,0 +1,48 @@
+From 1f80de6863ca0e36cabc622e858168fe5beb1e92 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 24 May 2015 21:08:14 +0200
+Subject: [PATCH] ARM: BCM5301X: add IRQ numbers for PCIe controller
+
+The driver for the PCIe controller was just added, this adds the
+missing definition of the IRQ numbers to device tree. The driver itself
+will be automatically detected by bcma.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/bcm5301x.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm5301x.dtsi
++++ b/arch/arm/boot/dts/bcm5301x.dtsi
+@@ -108,6 +108,30 @@
+ 			/* ChipCommon */
+ 			<0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+ 
++			/* PCIe Controller 0 */
++			<0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
++
++			/* PCIe Controller 1 */
++			<0x00013000 0 &gic GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00013000 1 &gic GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00013000 2 &gic GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00013000 3 &gic GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00013000 4 &gic GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00013000 5 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
++
++			/* PCIe Controller 2 */
++			<0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
++			<0x00014000 5 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
++
+ 			/* USB 2.0 Controller */
+ 			<0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch b/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch
new file mode 100644
index 0000000000..5790c9aaaf
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch
@@ -0,0 +1,95 @@
+From 26343bdacfcdbf6ee3303d6078a015b908f90193 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sat, 16 May 2015 16:55:39 +0200
+Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC87U
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+---
+ arch/arm/boot/dts/Makefile                  |  1 +
+ arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts | 65 +++++++++++++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+ create mode 100644 arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -66,6 +66,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+ 	bcm47081-asus-rt-n18u.dtb \
+ 	bcm47081-buffalo-wzr-600dhp2.dtb \
+ 	bcm47081-buffalo-wzr-900dhp.dtb \
++	bcm4709-asus-rt-ac87u.dtb \
+ 	bcm4709-buffalo-wxr-1900dhp.dtb \
+ 	bcm4709-netgear-r8000.dtb
+ dtb-$(CONFIG_ARCH_BCM_63XX) += \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+@@ -0,0 +1,65 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ * DTS for Asus RT-AC87U
++ *
++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++
++/ {
++	compatible = "asus,rt-ac87u", "brcm,bcm4709", "brcm,bcm4708";
++	model = "Asus RT-AC87U";
++
++	chosen {
++		bootargs = "console=ttyS0,115200";
++	};
++
++	memory {
++		reg = <0x00000000 0x08000000>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		wps {
++			label = "bcm53xx:blue:wps";
++			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++
++		power {
++			label = "bcm53xx:blue:power";
++			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-on";
++		};
++
++		wan {
++			label = "bcm53xx:red:wan";
++			gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
++			linux,default-trigger = "default-off";
++		};
++	};
++
++	gpio-keys {
++		compatible = "gpio-keys";
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		wps {
++			label = "WPS";
++			linux,code = <KEY_WPS_BUTTON>;
++			gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
++		};
++
++		restart {
++			label = "Reset";
++			linux,code = <KEY_RESTART>;
++			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
++		};
++	};
++};
diff --git a/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch b/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch
new file mode 100644
index 0000000000..5e944b0513
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch
@@ -0,0 +1,49 @@
+From 0509f6dcc46d10ea4bb8c70494dc7ae11bcb3f01 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 10 Dec 2014 21:14:10 +0100
+Subject: [PATCH] firmware: backport NVRAM driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/Kconfig                      | 2 ++
+ drivers/firmware/Kconfig              | 1 +
+ drivers/firmware/Makefile             | 1 +
+ drivers/net/ethernet/broadcom/b44.c   | 2 +-
+ drivers/net/ethernet/broadcom/bgmac.c | 2 +-
+ drivers/ssb/driver_chipcommon_pmu.c   | 2 +-
+ 6 files changed, 7 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -2105,6 +2105,8 @@ source "drivers/Kconfig"
+ 
+ source "drivers/firmware/Kconfig"
+ 
++source "drivers/firmware/Kconfig"
++
+ source "fs/Kconfig"
+ 
+ source "arch/arm/Kconfig.debug"
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -136,6 +136,7 @@ config QCOM_SCM
+ 	bool
+ 	depends on ARM || ARM64
+ 
++source "drivers/firmware/broadcom/Kconfig"
+ source "drivers/firmware/google/Kconfig"
+ source "drivers/firmware/efi/Kconfig"
+ 
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.
+ obj-$(CONFIG_QCOM_SCM)		+= qcom_scm.o
+ CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+ 
++obj-y				+= broadcom/
+ obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
+ obj-$(CONFIG_EFI)		+= efi/
+ obj-$(CONFIG_UEFI_CPER)		+= efi/
diff --git a/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch b/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch
new file mode 100644
index 0000000000..b914fd995f
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch
@@ -0,0 +1,69 @@
+From 4e0ab3269a6d260a41a3673157753147f5f71341 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 4 May 2014 13:19:20 +0200
+Subject: [PATCH 03/17] bcm47xx-sprom: add Broadcom sprom parser driver
+
+This driver needs an nvram driver and fetches the sprom values from the
+nvram and provides it to any other driver. The calibration data for the
+wifi chip the mac address and some more board description data is
+stores in the sprom.
+
+This is based on a copy of arch/mips/bcm47xx/sprom.c and my plan is to
+make the bcm47xx MIPS SoCs also use this driver some time later.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../devicetree/bindings/misc/bcm47xx-sprom.txt     |  16 +
+ drivers/misc/Kconfig                               |  11 +
+ drivers/misc/Makefile                              |   1 +
+ drivers/misc/bcm47xx-sprom.c                       | 690 +++++++++++++++++++++
+ 4 files changed, 718 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
+ create mode 100644 drivers/misc/bcm47xx-sprom.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt
+@@ -0,0 +1,16 @@
++Broadcom bcm47xx/bcm53xx sprom converter
++
++This driver provbides an sprom based on a given nvram.
++
++Required properties:
++
++- compatible : brcm,bcm47xx-sprom
++
++- nvram : reference to a nvram driver, e.g. bcm47xx-nvram
++
++Example:
++
++sprom0: sprom@0 {
++	compatible = "brcm,bcm47xx-sprom";
++	nvram = <&nvram0>;
++};
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -515,6 +515,17 @@ config VEXPRESS_SYSCFG
+ 	  bus. System Configuration interface is one of the possible means
+ 	  of generating transactions on this bus.
+ 
++config BCM47XX_SPROM
++	tristate "BCM47XX sprom driver"
++	help
++	  This driver parses the sprom from a given nvram which is found on
++	  Broadcom bcm47xx and bcm53xx SoCs.
++
++	  The sprom contains board configuration data like the
++	  calibration data fro the wifi chips, the mac addresses used
++	  by the board and many other board configuration data. This
++	  driver will provide the sprom to bcma.
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE)		+= genwqe/
+ obj-$(CONFIG_ECHO)		+= echo/
+ obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
+ obj-$(CONFIG_CXL_BASE)		+= cxl/
++obj-$(CONFIG_BCM47XX_SPROM)	+= bcm47xx-sprom.o
diff --git a/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch b/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch
new file mode 100644
index 0000000000..bdc7dea9e1
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch
@@ -0,0 +1,314 @@
+From 707ab07695ea8953a5bb56512e7bb38ca79c5c38 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 19 Feb 2015 23:27:59 +0100
+Subject: [PATCH V2] ARM: BCM5301X: Implement SMP support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+V2: Change code after receiving Florian's comments:
+    1) Use "mmio-sram"
+    2) Remove commented out ASM call
+    3) Fix coding style in ASM
+    4) Simplify finding OF node
+---
+ Documentation/devicetree/bindings/arm/bcm4708.txt |  24 ++++
+ Documentation/devicetree/bindings/arm/cpus.txt    |   1 +
+ arch/arm/boot/dts/bcm4708.dtsi                    |  13 ++
+ arch/arm/mach-bcm/Makefile                        |   3 +
+ arch/arm/mach-bcm/bcm5301x_headsmp.S              |  45 ++++++
+ arch/arm/mach-bcm/bcm5301x_smp.c                  | 158 ++++++++++++++++++++++
+ 6 files changed, 244 insertions(+)
+ create mode 100644 arch/arm/mach-bcm/bcm5301x_headsmp.S
+ create mode 100644 arch/arm/mach-bcm/bcm5301x_smp.c
+
+--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt
++++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt
+@@ -6,3 +6,27 @@ Boards with the BCM4708 SoC shall have t
+ Required root node property:
+ 
+ compatible = "brcm,bcm4708";
++
++Optional sub-node properties:
++
++compatible = "mmio-sram" for SRAM access with IO memory region
++		This is needed for SMP-capable SoCs which use part of
++		SRAM for storing location of code to be executed by the
++		extra cores.
++		SMP support requires another sub-node with compatible
++		property "brcm,bcm4708-sysram".
++
++Example:
++
++	sysram@ffff0000 {
++		compatible = "mmio-sram";
++		reg = <0xffff0000 0x10000>;
++		#address-cells = <1>;
++		#size-cells = <1>;
++		ranges = <0 0xffff0000 0x10000>;
++
++		smp-sysram@0 {
++			compatible = "brcm,bcm4708-sysram";
++			reg = <0x0 0x1000>;
++		};
++	};
+--- a/Documentation/devicetree/bindings/arm/cpus.txt
++++ b/Documentation/devicetree/bindings/arm/cpus.txt
+@@ -189,6 +189,7 @@ nodes to be present and contain the prop
+ 			  can be one of:
+ 			    "allwinner,sun6i-a31"
+ 			    "arm,psci"
++			    "brcm,bcm4708-smp"
+ 			    "brcm,brahma-b15"
+ 			    "marvell,armada-375-smp"
+ 			    "marvell,armada-380-smp"
+--- a/arch/arm/boot/dts/bcm4708.dtsi
++++ b/arch/arm/boot/dts/bcm4708.dtsi
+@@ -15,6 +15,7 @@
+ 	cpus {
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
++		enable-method = "brcm,bcm4708-smp";
+ 
+ 		cpu@0 {
+ 			device_type = "cpu";
+@@ -31,4 +32,16 @@
+ 		};
+ 	};
+ 
++	sysram@ffff0000 {
++		compatible = "mmio-sram";
++		reg = <0xffff0000 0x10000>;
++		#address-cells = <1>;
++		#size-cells = <1>;
++		ranges = <0 0xffff0000 0x10000>;
++
++		smp-sysram@0 {
++			compatible = "brcm,bcm4708-sysram";
++			reg = <0x0 0x1000>;
++		};
++	};
+ };
+--- a/arch/arm/mach-bcm/Makefile
++++ b/arch/arm/mach-bcm/Makefile
+@@ -36,6 +36,9 @@ obj-$(CONFIG_ARCH_BCM2835)	+= board_bcm2
+ 
+ # BCM5301X
+ obj-$(CONFIG_ARCH_BCM_5301X)	+= bcm_5301x.o
++ifeq ($(CONFIG_SMP),y)
++obj-$(CONFIG_ARCH_BCM_5301X)	+= bcm5301x_smp.o bcm5301x_headsmp.o
++endif
+ 
+ # BCM63XXx
+ obj-$(CONFIG_ARCH_BCM_63XX)	:= bcm63xx.o
+--- /dev/null
++++ b/arch/arm/mach-bcm/bcm5301x_headsmp.S
+@@ -0,0 +1,45 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ *
++ * Copyright (c) 2003 ARM Limited
++ * All Rights Reserved
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++#include <linux/linkage.h>
++
++/*
++ * BCM5301X specific entry point for secondary CPUs.
++ */
++ENTRY(bcm5301x_secondary_startup)
++	mrc	p15, 0, r0, c0, c0, 5
++	and	r0, r0, #15
++	adr	r4, 1f
++	ldmia	r4, {r5, r6}
++	sub	r4, r4, r5
++	add	r6, r6, r4
++pen:	ldr	r7, [r6]
++	cmp	r7, r0
++	bne	pen
++
++	/*
++	 * In case L1 cache has unpredictable contents at power-up
++	 * clean its contents without flushing.
++	 */
++	bl      v7_invalidate_l1
++
++	mov	r0, #0
++	mcr	p15, 0, r0, c7, c5, 0	/* Invalidate icache */
++	dsb
++	isb
++
++	/*
++	 * we've been released from the holding pen: secondary_stack
++	 * should now contain the SVC stack for this core
++	 */
++	b	secondary_startup
++ENDPROC(bcm5301x_secondary_startup)
++
++	.align 2
++1:	.long	.
++	.long	pen_release
+--- /dev/null
++++ b/arch/arm/mach-bcm/bcm5301x_smp.c
+@@ -0,0 +1,158 @@
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ *
++ * Copyright (C) 2002 ARM Ltd.
++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <asm/cacheflush.h>
++#include <asm/delay.h>
++#include <asm/smp_plat.h>
++#include <asm/smp_scu.h>
++
++#include <linux/clockchips.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++
++#define SOC_ROM_LUT_OFF		0x400
++
++extern void bcm5301x_secondary_startup(void);
++
++static void __cpuinit write_pen_release(int val)
++{
++	pen_release = val;
++	smp_wmb();
++	sync_cache_w(&pen_release);
++}
++
++static DEFINE_SPINLOCK(boot_lock);
++
++static void __init bcm5301x_smp_secondary_set_entry(void (*entry_point)(void))
++{
++	void __iomem *sysram_base_addr = NULL;
++	struct device_node *node;
++
++	node = of_find_compatible_node(NULL, NULL, "brcm,bcm4708-sysram");
++	if (!of_device_is_available(node))
++		return;
++
++	sysram_base_addr = of_iomap(node, 0);
++	if (!sysram_base_addr) {
++		pr_warn("Failed to map sysram\n");
++		return;
++	}
++
++	writel(virt_to_phys(entry_point), sysram_base_addr + SOC_ROM_LUT_OFF);
++
++	dsb_sev();	/* Exit WFI */
++	mb();		/* make sure write buffer is drained */
++
++	iounmap(sysram_base_addr);
++}
++
++static void __init bcm5301x_smp_prepare_cpus(unsigned int max_cpus)
++{
++	void __iomem *scu_base;
++
++	if (!scu_a9_has_base()) {
++		pr_warn("Unknown SCU base\n");
++		return;
++	}
++
++	scu_base = ioremap((phys_addr_t)scu_a9_get_base(), SZ_256);
++	if (!scu_base) {
++		pr_err("Failed to remap SCU\n");
++		return;
++	}
++
++	/* Initialise the SCU */
++	scu_enable(scu_base);
++
++	/* Let CPUs know where to start */
++	bcm5301x_smp_secondary_set_entry(bcm5301x_secondary_startup);
++
++	iounmap(scu_base);
++}
++
++static void __cpuinit bcm5301x_smp_secondary_init(unsigned int cpu)
++{
++	trace_hardirqs_off();
++
++	/*
++	 * let the primary processor know we're out of the
++	 * pen, then head off into the C entry point
++	 */
++	write_pen_release(-1);
++
++	/*
++	 * Synchronise with the boot thread.
++	 */
++	spin_lock(&boot_lock);
++	spin_unlock(&boot_lock);
++}
++
++static int __cpuinit bcm5301x_smp_boot_secondary(unsigned int cpu,
++						 struct task_struct *idle)
++{
++	unsigned long timeout;
++
++	/*
++	 * set synchronisation state between this boot processor
++	 * and the secondary one
++	 */
++	spin_lock(&boot_lock);
++
++	/*
++	 * The secondary processor is waiting to be released from
++	 * the holding pen - release it, then wait for it to flag
++	 * that it has been released by resetting pen_release.
++	 *
++	 * Note that "pen_release" is the hardware CPU ID, whereas
++	 * "cpu" is Linux's internal ID.
++	 */
++	write_pen_release(cpu_logical_map(cpu));
++
++	 /* Send the secondary CPU SEV */
++	dsb_sev();
++
++	udelay(100);
++
++	/*
++	 * Send the secondary CPU a soft interrupt, thereby causing
++	 * the boot monitor to read the system wide flags register,
++	 * and branch to the address found there.
++	 */
++	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
++
++	/*
++	 * Timeout set on purpose in jiffies so that on slow processors
++	 * that must also have low HZ it will wait longer.
++	 */
++	timeout = jiffies + (HZ * 10);
++	while (time_before(jiffies, timeout)) {
++		smp_rmb();
++		if (pen_release == -1)
++			break;
++
++		udelay(10);
++	}
++
++	/*
++	 * now the secondary core is starting up let it run its
++	 * calibrations, then wait for it to finish
++	 */
++	spin_unlock(&boot_lock);
++
++	return pen_release != -1 ? -ENOSYS : 0;
++}
++
++static struct smp_operations bcm5301x_smp_ops __initdata = {
++	.smp_prepare_cpus	= bcm5301x_smp_prepare_cpus,
++	.smp_secondary_init	= bcm5301x_smp_secondary_init,
++	.smp_boot_secondary	= bcm5301x_smp_boot_secondary,
++};
++
++CPU_METHOD_OF_DECLARE(bcm5301x_smp, "brcm,bcm4708-smp",
++		      &bcm5301x_smp_ops);
diff --git a/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
new file mode 100644
index 0000000000..d4dedc0365
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch
@@ -0,0 +1,534 @@
+From cf067bf8bb993d6cfdc42d750ae241c43f88403f Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Mon, 12 May 2014 11:55:20 +0200
+Subject: [PATCH 1/2] PCI: BCM5301X: add PCIe2 driver for BCM5301X SoCs
+
+This driver supports the PCIe controller found on the BCM4708 and
+similar SoCs. The controller itself is automatically detected by bcma.
+
+This controller is found on SoCs usually used in SOHO routers to
+connect the wifi cards to the SoC. All the of the BCM5301X SoCs I know
+of have 2 or 3 of these controllers in the SoC.
+
+I had to use PCI domains otherwise the pci_create_root_bus() function
+in drivers/pci/probe.c would fail for the second controller being
+registered because pci_find_bus() would find the same PCIe bus again
+and assume it is already registered, which ends up in a kernel panic in
+pcibios_init_hw() in arch/arm/kernel/bios32.c
+
+The ARM PCI code assumes that every controller has an I/O space and
+adds a dummy area if the driver does not specify one. This will work
+for the first controller, but when we register the second one this will
+result in an error. To prevent this problem we add an empty I/O space.
+
+Currently I have problems with probing the devices on the bus, because
+pci_bus_add_devices() is called too early in pci_scan_root_bus() in
+drivers/pci/probe.c, before pci_bus_assign_resources() was called in
+pci_common_init_dev() in arch/arm/kernel/bios32.c. When the devices are
+added too early they do not have any resources and adding fails. I have
+to remove the call to pci_bus_add_devices() in pci_scan_root_bus() to
+make registration work, calling pci_bus_add_devices() later again does
+not fix this problem.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/arm/mach-bcm/Kconfig            |   1 +
+ drivers/pci/host/Kconfig             |   7 +
+ drivers/pci/host/Makefile            |   1 +
+ drivers/pci/host/pci-host-bcm5301x.c | 428 +++++++++++++++++++++++++++++++++++
+ 4 files changed, 437 insertions(+)
+ create mode 100644 drivers/pci/host/pci-host-bcm5301x.c
+
+--- a/arch/arm/mach-bcm/Kconfig
++++ b/arch/arm/mach-bcm/Kconfig
+@@ -38,6 +38,7 @@ config ARCH_BCM_CYGNUS
+ config ARCH_BCM_5301X
+ 	bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
+ 	select ARCH_BCM_IPROC
++	select PCI_DOMAINS if PCI
+ 	help
+ 	  Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores.
+ 
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -125,4 +125,11 @@ config PCIE_IPROC_PLATFORM
+ 	  Say Y here if you want to use the Broadcom iProc PCIe controller
+ 	  through the generic platform bus interface
+ 
++config PCI_BCM5301X
++	bool "BCM5301X PCIe2 host controller"
++	depends on BCMA && OF && ARM && PCI_DOMAINS
++	help
++	  Say Y here if you want to support the PCIe host controller found
++	  on Broadcom BCM5301X and BCM470X (Northstar) SoCs.
++
+ endmenu
+--- a/drivers/pci/host/Makefile
++++ b/drivers/pci/host/Makefile
+@@ -15,3 +15,4 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-laye
+ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
+ obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
+ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
++obj-$(CONFIG_PCI_BCM5301X) += pci-host-bcm5301x.o
+--- /dev/null
++++ b/drivers/pci/host/pci-host-bcm5301x.c
+@@ -0,0 +1,459 @@
++/*
++ * Northstar PCI-Express driver
++ * Only supports Root-Complex (RC) mode
++ *
++ * Notes:
++ * PCI Domains are being used to identify the PCIe port 1:1.
++ *
++ * Only MEM access is supported, PAX does not support IO.
++ *
++ * Copyright 2012-2014, Broadcom Corporation
++ * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/bcma/bcma.h>
++#include <linux/bcma/bcma_driver_pcie2.h>
++
++#define	SOC_PCIE_HDR_OFF	0x400	/* 256 bytes per function */
++
++#define PCI_LINK_STATUS_CTRL_2_OFFSET 0xDC
++#define PCI_TARGET_LINK_SPEED_MASK    0xF
++#define PCI_TARGET_LINK_SPEED_GEN2    0x2
++#define PCI_TARGET_LINK_SPEED_GEN1    0x1
++
++static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
++{
++	struct pci_sys_data *sys = pdev->sysdata;
++	struct bcma_device *bdev = sys->private_data;
++
++	return bcma_core_irq(bdev, 5);
++}
++
++static u32 bcma_pcie2_cfg_base(struct bcma_device *bdev, int busno,
++			       unsigned int devfn, int where)
++{
++	int slot = PCI_SLOT(devfn);
++	int fn = PCI_FUNC(devfn);
++	u32 addr_reg;
++
++	if (busno == 0) {
++		if (slot >= 1)
++			return 0;
++		bcma_write32(bdev, BCMA_CORE_PCIE2_CONFIGINDADDR,
++			     where & 0xffc);
++		return BCMA_CORE_PCIE2_CONFIGINDDATA;
++	}
++	if (fn > 1)
++		return 0;
++	addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) |
++		   (where & 0xffc) | (1 & 0x3);
++
++	bcma_write32(bdev, BCMA_CORE_PCIE2_CFG_ADDR, addr_reg);
++	return BCMA_CORE_PCIE2_CFG_DATA;
++}
++
++static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno,
++				  unsigned int devfn, int where, int size)
++{
++	u32 base;
++	u32 data_reg;
++	u32 mask;
++	int shift;
++
++	base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
++
++	if (!base)
++		return ~0UL;
++
++	data_reg = bcma_read32(bdev, base);
++
++	if (size == 4)
++		return data_reg;
++
++	mask = (1 << (size * 8)) - 1;
++	shift = (where % 4) * 8;
++	return (data_reg >> shift) & mask;
++}
++
++static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno,
++				    unsigned int devfn, int where, int size,
++				    u32 val)
++{
++	u32 base;
++	u32 data_reg;
++
++	base = bcma_pcie2_cfg_base(bdev, busno, devfn, where);
++
++	if (!base)
++		return;
++
++	if (size < 4) {
++		u32 mask = (1 << (size * 8)) - 1;
++		int shift = (where % 4) * 8;
++
++		data_reg = bcma_read32(bdev, base);
++		data_reg &= ~(mask << shift);
++		data_reg |= (val & mask) << shift;
++	} else {
++		data_reg = val;
++	}
++
++	bcma_write32(bdev, base, data_reg);
++}
++
++static int bcma_pcie2_read_config_pci(struct pci_bus *bus, unsigned int devfn,
++				   int where, int size, u32 *val)
++{
++	struct pci_sys_data *sys = bus->sysdata;
++	struct bcma_device *bdev = sys->private_data;
++
++	*val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int bcma_pcie2_write_config_pci(struct pci_bus *bus, unsigned int devfn,
++				    int where, int size, u32 val)
++{
++	struct pci_sys_data *sys = bus->sysdata;
++	struct bcma_device *bdev = sys->private_data;
++
++	bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val);
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++/*
++ * Methods for accessing configuration registers
++ */
++static struct pci_ops bcma_pcie2_ops = {
++	.read = bcma_pcie2_read_config_pci,
++	.write = bcma_pcie2_write_config_pci,
++};
++
++/* NS: CLASS field is R/O, and set to wrong 0x200 value */
++static void bcma_pcie2_fixup_class(struct pci_dev *dev)
++{
++	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class);
++
++/*
++ * Check link status, return 0 if link is up in RC mode,
++ * otherwise return non-zero
++ */
++static int bcma_pcie2_check_link(struct bcma_device *bdev, struct pci_sys_data *sys)
++{
++	u32 tmp32;
++	u16 tmp16;
++	u16 pos;
++	u8 nlw;
++	/*
++	 * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before
++	 * creating bus root, so we don't have it here yet. On the other hand
++	 * we really want to use pci_bus_find_capability helper to check NLW.
++	 * Let's fake simple pci_bus just to query for capabilities.
++	 */
++	struct pci_bus bus = {
++		.number = 0,
++		.ops = &bcma_pcie2_ops,
++		.sysdata = sys,
++	};
++
++	tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_LINK_STATUS);
++	dev_dbg(&bdev->dev, "link status: 0x%08x\n", tmp32);
++
++	tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_STRAP_STATUS);
++	dev_dbg(&bdev->dev, "strap status: 0x%08x\n", tmp32);
++
++	/* check link status to see if link is active */
++	pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++	pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, &tmp16);
++	nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
++
++	if (nlw == 0) {
++		/* try GEN 1 link speed */
++		tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++					PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++		if ((tmp32 & PCI_TARGET_LINK_SPEED_MASK) ==
++				PCI_TARGET_LINK_SPEED_GEN2) {
++			tmp32 &= ~PCI_TARGET_LINK_SPEED_MASK;
++			tmp32 |= PCI_TARGET_LINK_SPEED_GEN1;
++			bcma_pcie2_write_config(bdev, 0, 0,
++					PCI_LINK_STATUS_CTRL_2_OFFSET, 4, tmp32);
++			tmp32 = bcma_pcie2_read_config(bdev, 0, 0,
++					PCI_LINK_STATUS_CTRL_2_OFFSET, 4);
++			msleep(100);
++
++			pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP);
++			pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA,
++					&tmp16);
++			nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >>
++				PCI_EXP_LNKSTA_NLW_SHIFT;
++		}
++	}
++
++	dev_info(&bdev->dev, "link: %s\n", nlw ? "UP" : "DOWN");
++	return nlw ? 0 : -ENODEV;
++}
++
++/*
++ * Initializte the PCIe controller
++ */
++static void bcma_pcie2_hw_init(struct bcma_device *bdev)
++{
++	u32 tmp32;
++	u16 tmp16;
++
++	/* Change MPS and MRRS to 512 */
++	tmp16 = bcma_pcie2_read_config(bdev, 0, 0, 0x4d4, 2);
++	tmp16 &= ~7;
++	tmp16 |= 2;
++	bcma_pcie2_write_config(bdev, 0, 0, 0x4d4, 2, tmp16);
++
++	tmp32 = bcma_pcie2_read_config(bdev, 0, 0, 0xb4, 4);
++	tmp32 &= ~((7 << 12) | (7 << 5));
++	tmp32 |= (2 << 12) | (2 << 5);
++	bcma_pcie2_write_config(bdev, 0, 0, 0xb4, 4, tmp32);
++
++	/*
++	 * Turn-on Root-Complex (RC) mode, from reset default of EP
++	 * The mode is set by straps, can be overwritten via DMU
++	 * register <cru_straps_control> bit 5, "1" means RC
++	 */
++
++	/* Send a downstream reset */
++	bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL,
++		     PCIE2_CLKC_RST_OE | PCIE2_CLKC_RST);
++	usleep_range(250, 400);
++	bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL, PCIE2_CLKC_RST_OE);
++	msleep(250);
++
++	/* TBD: take care of PM, check we're on */
++}
++
++/*
++ * Setup the address translation
++ *
++ * NOTE: All PCI-to-CPU address mapping are 1:1 for simplicity
++ */
++static int bcma_pcie2_map_init(struct bcma_device *bdev, u32 addr)
++{
++	/* 64MB alignment */
++	if (!addr || (addr & (SZ_64M - 1)))
++		return -EINVAL;
++
++	bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP0_LOWER, addr);
++	bcma_write32(bdev, BCMA_CORE_PCIE2_OARR0, addr | 0x01);
++
++	bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP1_LOWER, addr + SZ_64M);
++	bcma_write32(bdev, BCMA_CORE_PCIE2_OARR1, (addr + SZ_64M) | 0x01);
++
++	/*
++	 * Inbound address translation setup
++	 * Northstar only maps up to 128 MiB inbound, DRAM could be up to 1 GiB.
++	 *
++	 * For now allow access to entire DRAM, assuming it is less than 128MiB,
++	 * otherwise DMA bouncing mechanism may be required.
++	 * Also consider DMA mask to limit DMA physical address
++	 */
++	/* 64-bit LE regs, write low word, high is 0 at reset */
++	bcma_write32(bdev, BCMA_CORE_PCIE2_FUNC0_IMAP1, PHYS_OFFSET | 0x1);
++	bcma_write32(bdev, BCMA_CORE_PCIE2_IARR1_LOWER,
++			   PHYS_OFFSET | ((SZ_128M >> 20) & 0xff));
++	return 0;
++}
++
++/*
++ * Setup PCIE Host bridge
++ */
++static int bcma_pcie2_bridge_init(struct bcma_device *bdev, u32 addr, u32 size)
++{
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1, 0);
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1, 1);
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1, 4);
++
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1);
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1);
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1);
++
++	/* MEM_BASE, MEM_LIM require 1MB alignment */
++	if (((addr >> 16) & 0xf) || (((addr + size) >> 16) & 0xf))
++		return -EINVAL;
++
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_BASE, 2, addr >> 16);
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2,
++				(addr + size) >> 16);
++
++	/* These registers are not supported on the NS */
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_BASE_UPPER16, 2, 0);
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_LIMIT_UPPER16, 2, 0);
++
++	/* Force class to that of a Bridge */
++	bcma_pcie2_write_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2,
++				PCI_CLASS_BRIDGE_PCI);
++
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2);
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_BASE, 2);
++	bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2);
++	return 0;
++}
++
++static void bcma_pcie2_3rd_init(struct bcma_bus *bus)
++{
++	/* PCIE PLL block register (base 0x8000) */
++	bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x57fe8000);
++	/* Check PCIE PLL lock status */
++	bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x67c60000);
++}
++
++/* To improve PCIE phy jitter */
++static void bcma_pcie2_improve_phy_jitter(struct bcma_bus *bus, int phyaddr)
++{
++	u32 val;
++
++	/* Change blkaddr */
++	val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x1f << 18) |
++		(2 << 16) | (0x863 << 4);
++	bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
++
++	/* Write 0x0190 to 0x13 regaddr */
++	val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x13 << 18) |
++		(2 << 16) | 0x0190;
++	bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
++
++	/* Write 0x0191 to 0x19 regaddr */
++	val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x19 << 18) |
++		(2 << 16) | 0x0191;
++	bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val);
++}
++
++static int bcma_pcie2_setup(int nr, struct pci_sys_data *sys)
++{
++	struct bcma_device *bdev = sys->private_data;
++	struct bcma_bus *bus = bdev->bus;
++	struct resource *res;
++	struct bcma_device *arm_core;
++	u32 cru_straps_ctrl;
++	int ret;
++	int phyaddr;
++
++	if (bdev->core_unit == 2) {
++		arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9);
++		cru_straps_ctrl = bcma_read32(arm_core, 0x2a0);
++
++		/* 3rd PCIE is not selected */
++		if (cru_straps_ctrl & 0x10)
++			return -ENODEV;
++
++		bcma_pcie2_3rd_init(bus);
++		phyaddr = 0xf;
++	} else {
++		phyaddr = bdev->core_unit;
++	}
++	bcma_pcie2_improve_phy_jitter(bus, phyaddr);
++
++	/* create mem resource */
++	res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
++	if (!res)
++		return -EINVAL;
++
++	res->start = bdev->addr_s[0];
++	res->end = bdev->addr_s[0] + SZ_128M -1;
++	res->name = "PCIe dummy IO space";
++	res->flags = IORESOURCE_MEM;
++
++	pci_add_resource(&sys->resources, res);
++
++	/* This PCIe controller does not support IO Mem, so use a dummy one. */
++	res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL);
++	if (!res)
++		return -EINVAL;
++
++	res->start = 0;
++	res->end = 0;
++	res->name = "PCIe dummy IO space";
++	res->flags = IORESOURCE_IO;
++
++	pci_add_resource(&sys->resources, res);
++
++	bcma_pcie2_hw_init(bdev);
++	ret = bcma_pcie2_map_init(bdev, bdev->addr_s[0]);
++	if (ret)
++		return ret;
++
++	/*
++	 * Skip inactive ports -
++	 * will need to change this for hot-plugging
++	 */
++	ret = bcma_pcie2_check_link(bdev, sys);
++	if (ret)
++		return ret;
++
++	ret = bcma_pcie2_bridge_init(bdev, bdev->addr_s[0], SZ_128M);
++	if (ret)
++		return ret;
++
++	return 1;
++}
++
++static int bcma_pcie2_probe(struct bcma_device *bdev)
++{
++	struct hw_pci hw = {
++		.nr_controllers = 1,
++		.private_data	= (void **)&bdev,
++		.setup		= bcma_pcie2_setup,
++		.map_irq	= bcma_pcie2_map_irq,
++		.ops		= &bcma_pcie2_ops,
++	};
++
++	dev_info(&bdev->dev, "initializing PCIe controller\n");
++
++	/* Announce this port to ARM/PCI common code */
++	pci_common_init_dev(&bdev->dev, &hw);
++
++	/* Setup virtual-wire interrupts */
++	bcma_write32(bdev, BCMA_CORE_PCIE2_SYS_RC_INTX_EN, 0xf);
++
++	/* Enable memory and bus master */
++	bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6);
++
++	return 0;
++}
++
++static const struct bcma_device_id bcma_pcie2_table[] = {
++	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS),
++	{},
++};
++MODULE_DEVICE_TABLE(bcma, bcma_pcie2_table);
++
++static struct bcma_driver bcma_pcie2_driver = {
++	.name		= KBUILD_MODNAME,
++	.id_table	= bcma_pcie2_table,
++	.probe		= bcma_pcie2_probe,
++};
++
++static int __init bcma_pcie2_init(void)
++{
++	return bcma_driver_register(&bcma_pcie2_driver);
++}
++module_init(bcma_pcie2_init);
++
++static void __exit bcma_pcie2_exit(void)
++{
++	bcma_driver_unregister(&bcma_pcie2_driver);
++}
++module_exit(bcma_pcie2_exit);
++
++MODULE_AUTHOR("Hauke Mehrtens");
++MODULE_DESCRIPTION("BCM5301X PCIe host controller");
++MODULE_LICENSE("GPLv2");
diff --git a/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch b/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch
new file mode 100644
index 0000000000..e5e3010356
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch
@@ -0,0 +1,34 @@
+From baf3d128e5bdf9d322539609133a15b493b0c2ef Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:35 +0200
+Subject: [PATCH] USB: bcma: remove chip id check
+
+I have never seen any bcma device with an USB host core which was not a
+SoC, the bcma devices have an USB device core with a different core id.
+Some SoC have IDs with 47XX and 53XX in decimal form which would be
+rejected by this check. Instead of fixing this check just remove it.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -214,16 +214,11 @@ err_alloc:
+ static int bcma_hcd_probe(struct bcma_device *dev)
+ {
+ 	int err;
+-	u16 chipid_top;
+ 	u32 ohci_addr;
+ 	struct bcma_hcd_device *usb_dev;
+ 	struct bcma_chipinfo *chipinfo;
+ 
+ 	chipinfo = &dev->bus->chipinfo;
+-	/* USBcores are only connected on embedded devices. */
+-	chipid_top = (chipinfo->id & 0xFF00);
+-	if (chipid_top != 0x4700 && chipid_top != 0x5300)
+-		return -ENODEV;
+ 
+ 	/* TODO: Probably need checks here; is the core connected? */
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch b/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch
new file mode 100644
index 0000000000..5ae4e0d7aa
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch
@@ -0,0 +1,24 @@
+From f5bc834917a8b1b9487749bdfe8eda52a01967b4 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:36 +0200
+Subject: [PATCH] USB: bcma: replace numbers with constants
+
+The constants for these numbers were added long time ago, use them.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -233,7 +233,8 @@ static int bcma_hcd_probe(struct bcma_de
+ 
+ 	/* In AI chips EHCI is addrspace 0, OHCI is 1 */
+ 	ohci_addr = dev->addr_s[0];
+-	if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
++	if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
++	     chipinfo->id == BCMA_CHIP_ID_BCM4749)
+ 	    && chipinfo->rev == 0)
+ 		ohci_addr = 0x18009000;
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch b/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch
new file mode 100644
index 0000000000..700d354332
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch
@@ -0,0 +1,47 @@
+From 93724affb195149df6f7630901d878f6e273fa02 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:37 +0200
+Subject: [PATCH] USB: bcma: use devm_kzalloc
+
+Instead of manually handling the frees use devm. There was also a free
+missing in the unregister call which is not needed with devm.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -225,7 +225,8 @@ static int bcma_hcd_probe(struct bcma_de
+ 	if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
+ 		return -EOPNOTSUPP;
+ 
+-	usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
++	usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device),
++			       GFP_KERNEL);
+ 	if (!usb_dev)
+ 		return -ENOMEM;
+ 
+@@ -239,10 +240,8 @@ static int bcma_hcd_probe(struct bcma_de
+ 		ohci_addr = 0x18009000;
+ 
+ 	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
+-	if (IS_ERR(usb_dev->ohci_dev)) {
+-		err = PTR_ERR(usb_dev->ohci_dev);
+-		goto err_free_usb_dev;
+-	}
++	if (IS_ERR(usb_dev->ohci_dev))
++		return PTR_ERR(usb_dev->ohci_dev);
+ 
+ 	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
+ 	if (IS_ERR(usb_dev->ehci_dev)) {
+@@ -255,8 +254,6 @@ static int bcma_hcd_probe(struct bcma_de
+ 
+ err_unregister_ohci_dev:
+ 	platform_device_unregister(usb_dev->ohci_dev);
+-err_free_usb_dev:
+-	kfree(usb_dev);
+ 	return err;
+ }
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch b/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch
new file mode 100644
index 0000000000..91cd0fa320
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch
@@ -0,0 +1,33 @@
+From 232996d1ba3002e7e80b18075e2838fc86f21412 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:38 +0200
+Subject: [PATCH] USB: bcma: fix error handling in bcma_hcd_create_pdev()
+
+This patch makes bcma_hcd_create_pdev() not return NULL, but a prober
+error code in case of an error.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -169,7 +169,7 @@ static struct platform_device *bcma_hcd_
+ {
+ 	struct platform_device *hci_dev;
+ 	struct resource hci_res[2];
+-	int ret = -ENOMEM;
++	int ret;
+ 
+ 	memset(hci_res, 0, sizeof(hci_res));
+ 
+@@ -183,7 +183,7 @@ static struct platform_device *bcma_hcd_
+ 	hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
+ 					"ehci-platform" , 0);
+ 	if (!hci_dev)
+-		return NULL;
++		return ERR_PTR(-ENOMEM);
+ 
+ 	hci_dev->dev.parent = &dev->dev;
+ 	hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
diff --git a/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch b/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch
new file mode 100644
index 0000000000..bca555cf6a
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch
@@ -0,0 +1,133 @@
+From b65851f41c22b8c69b8fe9ca7782d19ed2155efc Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:39 +0200
+Subject: [PATCH] USB: bcma: add bcm53xx support
+
+The Broadcom ARM SoCs with this usb core need a different
+initialization and they have a different core id. This patch adds
+support for these USB 2.0 core.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 81 +++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 78 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -2,7 +2,8 @@
+  * Broadcom specific Advanced Microcontroller Bus
+  * Broadcom USB-core driver (BCMA bus glue)
+  *
+- * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
++ * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
+  *
+  * Based on ssb-ohci driver
+  * Copyright 2007 Michael Buesch <m@bues.ch>
+@@ -88,7 +89,7 @@ static void bcma_hcd_4716wa(struct bcma_
+ }
+ 
+ /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
+-static void bcma_hcd_init_chip(struct bcma_device *dev)
++static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
+ {
+ 	u32 tmp;
+ 
+@@ -159,6 +160,70 @@ static void bcma_hcd_init_chip(struct bc
+ 	}
+ }
+ 
++static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
++{
++	struct bcma_device *arm_core;
++	void __iomem *dmu;
++
++	arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
++	if (!arm_core) {
++		dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n");
++		return;
++	}
++
++	dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000);
++	if (!dmu) {
++		dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n");
++		return;
++	}
++
++	/* Unlock DMU PLL settings */
++	iowrite32(0x0000ea68, dmu + 0x180);
++
++	/* Write USB 2.0 PLL control setting */
++	iowrite32(0x00dd10c3, dmu + 0x164);
++
++	/* Lock DMU PLL settings */
++	iowrite32(0x00000000, dmu + 0x180);
++
++	iounmap(dmu);
++}
++
++static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev)
++{
++	u32 val;
++
++	/*
++	 * Delay after PHY initialized to ensure HC is ready to be configured
++	 */
++	usleep_range(1000, 2000);
++
++	/* Set packet buffer OUT threshold */
++	val = bcma_read32(dev, 0x94);
++	val &= 0xffff;
++	val |= 0x80 << 16;
++	bcma_write32(dev, 0x94, val);
++
++	/* Enable break memory transfer */
++	val = bcma_read32(dev, 0x9c);
++	val |= 1;
++	bcma_write32(dev, 0x9c, val);
++}
++
++static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
++{
++	bcma_core_enable(dev, 0);
++
++	if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 ||
++	    dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) {
++		if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 ||
++		    dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708)
++			bcma_hcd_init_chip_arm_phy(dev);
++
++		bcma_hcd_init_chip_arm_hc(dev);
++	}
++}
++
+ static const struct usb_ehci_pdata ehci_pdata = {
+ };
+ 
+@@ -230,7 +295,16 @@ static int bcma_hcd_probe(struct bcma_de
+ 	if (!usb_dev)
+ 		return -ENOMEM;
+ 
+-	bcma_hcd_init_chip(dev);
++	switch (dev->id.id) {
++	case BCMA_CORE_NS_USB20:
++		bcma_hcd_init_chip_arm(dev);
++		break;
++	case BCMA_CORE_USB20_HOST:
++		bcma_hcd_init_chip_mips(dev);
++		break;
++	default:
++		return -ENODEV;
++	}
+ 
+ 	/* In AI chips EHCI is addrspace 0, OHCI is 1 */
+ 	ohci_addr = dev->addr_s[0];
+@@ -299,6 +373,7 @@ static int bcma_hcd_resume(struct bcma_d
+ 
+ static const struct bcma_device_id bcma_hcd_table[] = {
+ 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
++	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
diff --git a/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch b/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch
new file mode 100644
index 0000000000..d9a8a1e621
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch
@@ -0,0 +1,82 @@
+From f3cf44a313b3687efd55ba091558e20a4d218c31 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Thu, 11 Jun 2015 22:57:40 +0200
+Subject: [PATCH] USB: bcma: add support for controlling bus power through GPIO
+
+On some boards a GPIO is needed to activate USB controller. Make it
+possible to specify such a GPIO in device tree.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ drivers/usb/host/bcma-hcd.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -24,6 +24,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/of_gpio.h>
+ #include <linux/usb/ehci_pdriver.h>
+ #include <linux/usb/ohci_pdriver.h>
+ 
+@@ -224,6 +226,23 @@ static void bcma_hcd_init_chip_arm(struc
+ 	}
+ }
+ 
++static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
++{
++	int gpio;
++
++	gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0);
++	if (!gpio_is_valid(gpio))
++		return;
++
++	if (val) {
++		gpio_request(gpio, "bcma-hcd-gpio");
++		gpio_set_value(gpio, 1);
++	} else {
++		gpio_set_value(gpio, 0);
++		gpio_free(gpio);
++	}
++}
++
+ static const struct usb_ehci_pdata ehci_pdata = {
+ };
+ 
+@@ -295,6 +314,8 @@ static int bcma_hcd_probe(struct bcma_de
+ 	if (!usb_dev)
+ 		return -ENOMEM;
+ 
++	bcma_hci_platform_power_gpio(dev, true);
++
+ 	switch (dev->id.id) {
+ 	case BCMA_CORE_NS_USB20:
+ 		bcma_hcd_init_chip_arm(dev);
+@@ -347,6 +368,7 @@ static void bcma_hcd_remove(struct bcma_
+ 
+ static void bcma_hcd_shutdown(struct bcma_device *dev)
+ {
++	bcma_hci_platform_power_gpio(dev, false);
+ 	bcma_core_disable(dev, 0);
+ }
+ 
+@@ -354,6 +376,7 @@ static void bcma_hcd_shutdown(struct bcm
+ 
+ static int bcma_hcd_suspend(struct bcma_device *dev)
+ {
++	bcma_hci_platform_power_gpio(dev, false);
+ 	bcma_core_disable(dev, 0);
+ 
+ 	return 0;
+@@ -361,6 +384,7 @@ static int bcma_hcd_suspend(struct bcma_
+ 
+ static int bcma_hcd_resume(struct bcma_device *dev)
+ {
++	bcma_hci_platform_power_gpio(dev, true);
+ 	bcma_core_enable(dev, 0);
+ 
+ 	return 0;
diff --git a/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch b/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch
new file mode 100644
index 0000000000..bc5757fb11
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch
@@ -0,0 +1,195 @@
+From 26023cdfacaf116545b1087b9d1fe50dc6fbda10 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 24 Sep 2014 22:14:07 +0200
+Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache for decompression
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without this fix kernel was randomly hanging in ~25% of tries during
+early init. Hangs used to happen at random places in the start_kernel.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/compressed/Makefile                |   5 +
+ arch/arm/boot/compressed/head-bcm_5301x-mpcore.S |  37 +++++++
+ arch/arm/boot/compressed/mpcore_cache.S          | 118 +++++++++++++++++++++++
+ 3 files changed, 160 insertions(+)
+ create mode 100644 arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
+ create mode 100644 arch/arm/boot/compressed/mpcore_cache.S
+
+--- a/arch/arm/boot/compressed/Makefile
++++ b/arch/arm/boot/compressed/Makefile
+@@ -31,6 +31,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
+ OBJS		+= ll_char_wr.o font.o
+ endif
+ 
++ifeq ($(CONFIG_ARCH_BCM_5301X),y)
++OBJS		+= head-bcm_5301x-mpcore.o
++OBJS		+= mpcore_cache.o
++endif
++
+ ifeq ($(CONFIG_ARCH_SA1100),y)
+ OBJS		+= head-sa1100.o
+ endif
+--- /dev/null
++++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S
+@@ -0,0 +1,37 @@
++/*
++ *
++ * Platform specific tweaks.  This is merged into head.S by the linker.
++ *
++ */
++
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++#include <asm/cp15.h>
++
++		.section        ".start", "ax"
++
++/*
++ * This code section is spliced into the head code by the linker
++ */
++
++__plat_uncompress_start:
++
++	@ Preserve r8/r7 i.e. kernel entry values
++	mov	r12, r8
++
++	@ Clear MMU enable and Dcache enable bits
++	mrc	p15, 0, r0, c1, c0, 0		@ Read SCTLR
++	bic	r0, #CR_C|CR_M
++	mcr	p15, 0, r0, c1, c0, 0		@ Write SCTLR
++	nop
++
++	@ Call the cache invalidation routine
++	bl	v7_all_dcache_invalidate
++	nop
++	mov	r0,#0
++	ldr	r3, =0x19022000			@ L2 cache controller, control reg
++	str	r0, [r3, #0x100]		@ Disable L2 cache
++	nop
++
++	@ Restore
++	mov	r8, r12
+--- /dev/null
++++ b/arch/arm/boot/compressed/mpcore_cache.S
+@@ -0,0 +1,118 @@
++/*****************************************************************************
++* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#include <linux/linkage.h>
++#include <linux/init.h>
++
++	__INIT
++
++/*
++ * v7_l1_cache_invalidate
++ *
++ * Invalidate contents of L1 cache without flushing its contents
++ * into outer cache and memory. This is needed when the contents
++ * of the cache are unpredictable after power-up.
++ *
++ * corrupts r0-r6
++ */
++
++ENTRY(v7_l1_cache_invalidate)
++	mov	r0, #0
++	mcr	p15, 2, r0, c0, c0, 0	@ set cache level to 1
++	mrc	p15, 1, r0, c0, c0, 0	@ read CLIDR
++
++	ldr	r1, =0x7fff
++	and	r2, r1, r0, lsr #13	@ get max # of index size
++
++	ldr	r1, =0x3ff
++	and	r3, r1, r0, lsr #3	@ NumWays - 1
++	add	r2, r2, #1		@ NumSets
++
++	and	r0, r0, #0x7
++	add	r0, r0, #4		@ SetShift
++
++	clz	r1, r3			@ WayShift
++	add	r4, r3, #1		@ NumWays
++1:	sub	r2, r2, #1		@ NumSets--
++	mov	r3, r4			@ Temp = NumWays
++2:	subs	r3, r3, #1		@ Temp--
++	mov	r5, r3, lsl r1
++	mov	r6, r2, lsl r0
++	orr	r5, r5, r6		@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
++	mcr	p15, 0, r5, c7, c6, 2	@ Invalidate line
++	bgt	2b
++	cmp	r2, #0
++	bgt	1b
++	dsb
++	mov	r0,#0
++	mcr	p15,0,r0,c7,c5,0	/* Invalidate icache */
++	isb
++	mov	pc, lr
++ENDPROC(v7_l1_cache_invalidate)
++
++/*
++ * v7_all_dcache_invalidate
++ *
++ * Invalidate without flushing the contents of all cache levels
++ * accesible by the current processor core.
++ * This is useful when the contents of cache memory are undetermined
++ * at power-up.
++ *	Corrupted registers: r0-r7, r9-r11
++ *
++ * Based on cache-v7.S: v7_flush_dcache_all()
++ */
++
++ENTRY(v7_all_dcache_invalidate)
++	mrc	p15, 1, r0, c0, c0, 1	@ read clidr
++	ands	r3, r0, #0x7000000	@ extract loc from clidr
++	mov	r3, r3, lsr #23		@ left align loc bit field
++	beq	finished		@ if loc is 0, then no need to clean
++	mov	r10, #0			@ start clean at cache level 0
++loop1:
++	add	r2, r10, r10, lsr #1	@ work out 3x current cache level
++	mov	r1, r0, lsr r2		@ extract cache type bits from clidr
++	and	r1, r1, #7		@ mask of bits for current cache only
++	cmp	r1, #2			@ see what cache we have at this level
++	blt	skip			@ skip if no cache, or just i-cache
++	mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
++	isb				@ isb to sych the new cssr&csidr
++	mrc	p15, 1, r1, c0, c0, 0	@ read the new csidr
++	and	r2, r1, #7		@ extract the length of the cache lines
++	add	r2, r2, #4		@ add 4 (line length offset)
++	ldr	r4, =0x3ff
++	ands	r4, r4, r1, lsr #3	@ find maximum number on the way size
++	clz	r5, r4			@ find bit pos of way size increment
++	ldr	r7, =0x7fff
++	ands	r7, r7, r1, lsr #13	@ extract max number of the index size
++loop2:
++	mov	r9, r4			@ create working copy of max way size
++loop3:
++	orr	r11, r10, r9, lsl r5	@ factor way and cache number into r11
++	orr	r11, r11, r7, lsl r2	@ factor index number into r11
++	mcr	p15, 0, r11, c7, c6, 2	@ Invalidate line
++	subs	r9, r9, #1		@ decrement the way
++	bge	loop3
++	subs	r7, r7, #1		@ decrement the index
++	bge	loop2
++skip:
++	add	r10, r10, #2		@ increment cache number
++	cmp	r3, r10
++	bgt	loop1
++finished:
++	mov	r10, #0			@ swith back to cache level 0
++	mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
++	dsb
++	isb
++	mov	pc, lr
++ENDPROC(v7_all_dcache_invalidate)
diff --git a/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch b/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch
new file mode 100644
index 0000000000..ca6462e3c7
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch
@@ -0,0 +1,26 @@
+From d404e0b22356078a51719fa911f6e09cb1a72d80 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 7 Jun 2015 16:18:18 +0200
+Subject: [PATCH] ARM: BCM5301X: Add SPROM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm5301x.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm5301x.dtsi
++++ b/arch/arm/boot/dts/bcm5301x.dtsi
+@@ -95,6 +95,10 @@
+ 		};
+ 	};
+ 
++	sprom0: sprom@0 {
++		compatible = "brcm,bcm47xx-sprom";
++	};
++
+ 	axi@18000000 {
+ 		compatible = "brcm,bus-axi";
+ 		reg = <0x18000000 0x1000>;
diff --git a/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch b/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch
new file mode 100644
index 0000000000..9b562ce1a9
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch
@@ -0,0 +1,148 @@
+From eb1075cc48d3c315c7403822c33da9588ab76492 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 14 Jan 2015 08:33:25 +0100
+Subject: [PATCH] ARM: BCM5310X: Enable earlyprintk on tested devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  | 2 +-
+ arch/arm/boot/dts/bcm4708-netgear-r6250.dts        | 2 +-
+ arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts        | 2 +-
+ arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 2 +-
+ 4 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -17,7 +17,7 @@
+ 	model = "Buffalo WZR-1750DHP (BCM4708)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+@@ -17,7 +17,7 @@
+ 	model = "Netgear R6250 V1 (BCM4708)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+@@ -17,7 +17,7 @@
+ 	model = "Asus RT-N18U (BCM47081)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+@@ -17,7 +17,7 @@
+ 	model = "Buffalo WZR-600DHP2 (BCM47081)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+@@ -17,7 +17,7 @@
+ 	model = "Buffalo WZR-900DHP (BCM47081)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+@@ -17,7 +17,7 @@
+ 	model = "Netgear R8000 (BCM4709)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+@@ -17,7 +17,7 @@
+ 	model = "Asus RT-AC56U (BCM4708)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+@@ -17,7 +17,7 @@
+ 	model = "Asus RT-AC68U (BCM4708)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+@@ -17,7 +17,7 @@
+ 	model = "Luxul XWC-1000 (BCM4708)";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -17,7 +17,7 @@
+ 	model = "Buffalo WXR-1900DHP";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+@@ -17,7 +17,7 @@
+ 	model = "SmartRG SR400ac";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
+--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+@@ -16,7 +16,7 @@
+ 	model = "Asus RT-AC87U";
+ 
+ 	chosen {
+-		bootargs = "console=ttyS0,115200";
++		bootargs = "console=ttyS0,115200 earlyprintk";
+ 	};
+ 
+ 	memory {
diff --git a/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch b/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch
new file mode 100644
index 0000000000..a2bed2aeb7
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch
@@ -0,0 +1,30 @@
+From 4a658590f83c1e916ab63ed7fe6f0841924247db Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Fri, 3 Oct 2014 18:37:33 +0200
+Subject: [PATCH 2/2] ARM: BCM53XX: set customized AUXCTL
+
+This activated some more features in the l310 cache.
+
+This is based on some vendor code
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/arm/mach-bcm/bcm_5301x.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mach-bcm/bcm_5301x.c
++++ b/arch/arm/mach-bcm/bcm_5301x.c
+@@ -50,7 +50,12 @@ static const char __initconst *bcm5301x_
+ };
+ 
+ DT_MACHINE_START(BCM5301X, "BCM5301X")
+-	.l2c_aux_val	= 0,
++	.l2c_aux_val	= L310_AUX_CTRL_CACHE_REPLACE_RR |
++			  L310_AUX_CTRL_DATA_PREFETCH |
++			  L310_AUX_CTRL_INSTR_PREFETCH |
++			  L310_AUX_CTRL_EARLY_BRESP |
++			  L2C_AUX_CTRL_SHARED_OVERRIDE |
++			  L310_AUX_CTRL_FULL_LINE_ZERO,
+ 	.l2c_aux_mask	= ~0,
+ 	.init_early	= bcm5301x_init_early,
+ 	.dt_compat	= bcm5301x_dt_compat,
diff --git a/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch b/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch
new file mode 100644
index 0000000000..6637a62adc
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch
@@ -0,0 +1,161 @@
+From 36b2fbb3badf0e32b371e1f7579a95d4fe25c0e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 14 Jan 2015 09:13:58 +0100
+Subject: [PATCH] ARM: BCM5301X: Specify RAM on devices by including HIGHMEM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  | 3 ++-
+ arch/arm/boot/dts/bcm4708-netgear-r6250.dts        | 3 ++-
+ arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts     | 3 ++-
+ arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts        | 3 ++-
+ arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 3 ++-
+ 5 files changed, 10 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x18000000>;
+ 	};
+ 
+ 	spi {
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	chipcommonA {
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	spi {
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	gpio-keys {
+--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x18000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+@@ -21,7 +21,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
+--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+@@ -20,7 +20,8 @@
+ 	};
+ 
+ 	memory {
+-		reg = <0x00000000 0x08000000>;
++		reg = <0x00000000 0x08000000
++		       0x88000000 0x08000000>;
+ 	};
+ 
+ 	leds {
diff --git a/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch b/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch
new file mode 100644
index 0000000000..f99460aa46
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch
@@ -0,0 +1,41 @@
+From 504dba5b073a9009ae1e3f2fc53ea9c3aa10c38a Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Wed, 13 May 2015 20:56:38 +0200
+Subject: [PATCH] ARM: BCM5301X: Add Buffalo WXR-1900DHP clock and USB power
+ control
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -25,6 +25,23 @@
+ 		       0x88000000 0x18000000>;
+ 	};
+ 
++	clocks {
++		clk_periph: periph {
++			clock-frequency = <500000000>;
++		};
++	};
++
++	axi@18000000 {
++		usb2@21000 {
++			reg = <0x00021000 0x1000>;
++
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch b/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch
new file mode 100644
index 0000000000..7e5f018fd4
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch
@@ -0,0 +1,63 @@
+From f1ee1275f65e87e035260f4d09a0f0ba98c6854d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 21 Jun 2015 12:56:32 +0200
+Subject: [PATCH] ARM: BCM5301X: Set vcc-gpio for USB controllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 20 ++++++++++++++++++++
+ arch/arm/boot/dts/bcm4708-netgear-r6250.dts       | 11 +++++++++++
+ 2 files changed, 31 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -25,6 +25,26 @@
+ 		       0x88000000 0x18000000>;
+ 	};
+ 
++	axi@18000000 {
++		usb2@21000 {
++			reg = <0x00021000 0x1000>;
++
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
++		};
++
++		usb3@23000 {
++			reg = <0x00023000 0x1000>;
++
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			vcc-gpio = <&chipcommon 10 GPIO_ACTIVE_LOW>;
++		};
++	};
++
+ 	spi {
+ 		compatible = "spi-gpio";
+ 		num-chipselects = <1>;
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+@@ -35,6 +35,17 @@
+ 		};
+ 	};
+ 
++	axi@18000000 {
++		usb3@23000 {
++			reg = <0x00023000 0x1000>;
++
++			#address-cells = <1>;
++			#size-cells = <1>;
++
++			vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch
new file mode 100644
index 0000000000..f9ca7eb7c1
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch
@@ -0,0 +1,20 @@
+From: Felix Fietkau <nbd@openwrt.org>
+Subject: [PATCH] ARM: BCM5301X: Add power button for Buffalo WZR-1750DHP
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -123,6 +123,12 @@
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
+ 
++		power {
++			label = "Power";
++			linux,code = <KEY_POWER>;
++			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
++		};
++
+ 		restart {
+ 			label = "Reset";
+ 			linux,code = <KEY_RESTART>;
diff --git a/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch b/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch
new file mode 100644
index 0000000000..291ec72f2c
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch
@@ -0,0 +1,20 @@
+Subject: [PATCH] ARM: BCM5301X: Add profiling support
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+--- a/arch/arm/boot/dts/bcm5301x.dtsi
++++ b/arch/arm/boot/dts/bcm5301x.dtsi
+@@ -82,6 +82,13 @@
+ 		};
+ 	};
+ 
++	pmu {
++		compatible = "arm,cortex-a9-pmu";
++		interrupts =
++			<GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
++			<GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
++	};
++
+ 	clocks {
+ 		#address-cells = <1>;
+ 		#size-cells = <0>;
diff --git a/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch b/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch
new file mode 100644
index 0000000000..87065de48a
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch
@@ -0,0 +1,250 @@
+From 6c223da976a9225ba9fae8d6f891a8fffaae6092 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 5 Dec 2014 17:38:40 +0100
+Subject: [PATCH] ARM: BCM5301X: Enable ChipCommon UART (serial console)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts  | 10 ++++++++++
+ arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts     | 10 ++++++++++
+ arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts        | 10 ++++++++++
+ arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 10 ++++++++++
+ 4 files changed, 40 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x18000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	axi@18000000 {
+ 		usb2@21000 {
+ 			reg = <0x00021000 0x1000>;
+--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	spi {
+ 		compatible = "spi-gpio";
+ 		num-chipselects = <1>;
+--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+@@ -23,6 +23,16 @@
+ 	memory {
+ 		reg = <0x00000000 0x08000000>;
+ 	};
++ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
+ 
+ 	nand: nand@18028000 {
+ 		nandcs@0 {
+--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	gpio-keys {
+ 		compatible = "gpio-keys";
+ 		#address-cells = <1>;
+--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+@@ -46,6 +46,18 @@
+ 		};
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++	};
++
+ 	gpio-keys {
+ 		compatible = "gpio-keys";
+ 		#address-cells = <1>;
+--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+@@ -25,6 +25,18 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
+--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+@@ -25,6 +25,18 @@
+ 		       0x88000000 0x18000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++			clock-frequency = <125000000>;
++		};
++	};
++
+ 	clocks {
+ 		clk_periph: periph {
+ 			clock-frequency = <500000000>;
+--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+@@ -25,6 +25,16 @@
+ 		       0x88000000 0x08000000>;
+ 	};
+ 
++	chipcommonA {
++		uart0: serial@0300 {
++			status = "okay";
++		};
++
++		uart1: serial@0400 {
++			status = "okay";
++		};
++	};
++
+ 	leds {
+ 		compatible = "gpio-leds";
+ 
diff --git a/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch b/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch
new file mode 100644
index 0000000000..df65e0d03d
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch
@@ -0,0 +1,37 @@
+From b97e582cd05f6ba80bdb63d9f677a3395edc7ff1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 7 Jun 2015 15:37:43 +0200
+Subject: [PATCH] ARM: BCM5301X: Add back Luxul XWC-1000 NAND flash layout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In OpenWrt we still use old NAND driver instead of "brcm,nandcs", so
+we need to add this DT entry back.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+@@ -34,6 +34,18 @@
+ 		};
+ 	};
+ 
++	axi@18000000 {
++		nand@28000 {
++			reg = <0x00028000 0x1000>;
++			#address-cells = <1>;
++			#size-cells = <1>;
++			partition@0 {
++				label = "ubi";
++				reg = <0x00000000 0x08000000>;
++			};
++		};
++	};
++
+ 	nand: nand@18028000 {
+ 		nandcs@0 {
+ 			partition@0 {
diff --git a/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch b/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch
new file mode 100644
index 0000000000..ccdb28b54d
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch
@@ -0,0 +1,31 @@
+From d658c21d6697293a928434fd6ac19264b5a8948d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Fri, 30 Jan 2015 08:25:54 +0100
+Subject: [PATCH] mtd: bcm47xxpart: scan whole flash on ARCH_BCM_5301X
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/mtd/bcm47xxpart.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/mtd/bcm47xxpart.c
++++ b/drivers/mtd/bcm47xxpart.c
+@@ -120,9 +120,15 @@ static int bcm47xxpart_parse(struct mtd_
+ 	/* Parse block by block looking for magics */
+ 	for (offset = 0; offset <= master->size - blocksize;
+ 	     offset += blocksize) {
++#ifndef CONFIG_ARCH_BCM_5301X
++		/*
++		 * ARM routers may have partitions in higher memory. E.g.
++		 * Netgear R8000 has board_data at 0x2600000.
++		 */
+ 		/* Nothing more in higher memory */
+ 		if (offset >= 0x2000000)
+ 			break;
++#endif
+ 
+ 		if (curr_part >= BCM47XXPART_MAX_PARTS) {
+ 			pr_warn("Reached maximum number of partitions, scanning stopped!\n");
diff --git a/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch b/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
new file mode 100644
index 0000000000..41ef3b300e
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch
@@ -0,0 +1,19 @@
+--- a/drivers/mtd/spi-nor/Kconfig
++++ b/drivers/mtd/spi-nor/Kconfig
+@@ -28,4 +28,10 @@ config SPI_FSL_QUADSPI
+ 	  This enables support for the Quad SPI controller in master mode.
+ 	  We only connect the NOR to this controller now.
+ 
++config MTD_SPI_BCM53XXSPIFLASH
++	tristate "SPI-NOR flashes connected to the Broadcom ARM SoC"
++	depends on MTD_SPI_NOR
++	help
++	  SPI driver for flashes used on Broadcom ARM SoCs.
++
+ endif # MTD_SPI_NOR
+--- a/drivers/mtd/spi-nor/Makefile
++++ b/drivers/mtd/spi-nor/Makefile
+@@ -1,2 +1,3 @@
+ obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
+ obj-$(CONFIG_SPI_FSL_QUADSPI)	+= fsl-quadspi.o
++obj-$(CONFIG_MTD_SPI_BCM53XXSPIFLASH)	+= bcm53xxspiflash.o
diff --git a/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch b/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch
new file mode 100644
index 0000000000..07cde2114a
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch
@@ -0,0 +1,1608 @@
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -530,4 +530,10 @@ config MTD_NAND_HISI504
+ 	help
+ 	  Enables support for NAND controller on Hisilicon SoC Hip04.
+ 
++config MTD_NAND_BCM
++	tristate "Support for NAND on some Broadcom SoC"
++	help
++	  This driver is currently used for the NAND flash controller on the
++	  Broadcom BCM5301X (NorthStar) SoCs.
++
+ endif # MTD_NAND
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -52,5 +52,6 @@ obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nan
+ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
+ obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
+ obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
++obj-$(CONFIG_MTD_NAND_BCM)		+= bcm_nand.o
+ 
+ nand-objs := nand_base.o nand_bbt.o nand_timings.o
+--- /dev/null
++++ b/drivers/mtd/nand/bcm_nand.c
+@@ -0,0 +1,1583 @@
++/*
++ * Nortstar NAND controller driver
++ *
++ * (c) Broadcom, Inc. 2012 All Rights Reserved.
++ * Copyright 2014 Hauke Mehrtens <hauke@hauke-m.de>
++ *
++ * Licensed under the GNU/GPL. See COPYING for details.
++ *
++ * This module interfaces the NAND controller and hardware ECC capabilities
++ * tp the generic NAND chip support in the NAND library.
++ *
++ * Notes:
++ *	This driver depends on generic NAND driver, but works at the
++ *	page level for operations.
++ *
++ *	When a page is written, the ECC calculated also protects the OOB
++ *	bytes not taken by ECC, and so the OOB must be combined with any
++ *	OOB data that preceded the page-write operation in order for the
++ *	ECC to be calculated correctly.
++ *	Also, when the page is erased, but OOB data is not, HW ECC will
++ *	indicate an error, because it checks OOB too, which calls for some
++ *	help from the software in this driver.
++ *
++ * TBD:
++ *	Block locking/unlocking support, OTP support
++ */
++
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/bcma/bcma.h>
++#include <linux/of_irq.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++
++#define NANDC_MAX_CHIPS		2	/* Only 2 CSn supported in NorthStar */
++
++/*
++ * Driver private control structure
++ */
++struct bcmnand_ctrl {
++	struct mtd_info		mtd;
++	struct nand_chip	nand;
++	struct bcma_device	*core;
++
++	struct completion	op_completion;
++
++	struct nand_ecclayout	ecclayout;
++	int			cmd_ret;	/* saved error code */
++	unsigned char		oob_index;
++	unsigned char		id_byte_index;
++	unsigned char		chip_num;
++	unsigned char		last_cmd;
++	unsigned char		ecc_level;
++	unsigned char		sector_size_shift;
++	unsigned char		sec_per_page_shift;
++};
++
++
++/*
++ * IRQ numbers - offset from first irq in nandc_irq resource
++ */
++#define NANDC_IRQ_RD_MISS		0
++#define NANDC_IRQ_ERASE_COMPLETE	1
++#define NANDC_IRQ_COPYBACK_COMPLETE	2
++#define NANDC_IRQ_PROGRAM_COMPLETE	3
++#define NANDC_IRQ_CONTROLLER_RDY	4
++#define NANDC_IRQ_RDBSY_RDY		5
++#define NANDC_IRQ_ECC_UNCORRECTABLE	6
++#define NANDC_IRQ_ECC_CORRECTABLE	7
++#define NANDC_IRQ_NUM			8
++
++struct bcmnand_reg_field {
++	unsigned int reg;
++	unsigned int pos;
++	unsigned int width;
++};
++
++/*
++ * REGISTERS
++ *
++ * Individual bit-fields aof registers are specificed here
++ * for clarity, and the rest of the code will access each field
++ * as if it was its own register.
++ *
++ * Following registers are off <reg_base>:
++ */
++#define REG_BIT_FIELD(r, p, w)	((struct bcmnand_reg_field){(r), (p), (w)})
++
++#define NANDC_8KB_PAGE_SUPPORT		REG_BIT_FIELD(0x0, 31, 1)
++#define NANDC_REV_MAJOR			REG_BIT_FIELD(0x0, 8, 8)
++#define NANDC_REV_MINOR			REG_BIT_FIELD(0x0, 0, 8)
++
++#define NANDC_CMD_START_OPCODE		REG_BIT_FIELD(0x4, 24, 5)
++
++#define NANDC_CMD_CS_SEL		REG_BIT_FIELD(0x8, 16, 3)
++#define NANDC_CMD_EXT_ADDR		REG_BIT_FIELD(0x8, 0, 16)
++
++#define NANDC_CMD_ADDRESS		REG_BIT_FIELD(0xc, 0, 32)
++#define NANDC_CMD_END_ADDRESS		REG_BIT_FIELD(0x10, 0, 32)
++
++#define NANDC_INT_STATUS		REG_BIT_FIELD(0x14, 0, 32)
++#define NANDC_INT_STAT_CTLR_RDY		REG_BIT_FIELD(0x14, 31, 1)
++#define NANDC_INT_STAT_FLASH_RDY	REG_BIT_FIELD(0x14, 30, 1)
++#define NANDC_INT_STAT_CACHE_VALID	REG_BIT_FIELD(0x14, 29, 1)
++#define NANDC_INT_STAT_SPARE_VALID	REG_BIT_FIELD(0x14, 28, 1)
++#define NANDC_INT_STAT_ERASED		REG_BIT_FIELD(0x14, 27, 1)
++#define NANDC_INT_STAT_PLANE_RDY	REG_BIT_FIELD(0x14, 26, 1)
++#define NANDC_INT_STAT_FLASH_STATUS	REG_BIT_FIELD(0x14, 0, 8)
++
++#define NANDC_CS_LOCK			REG_BIT_FIELD(0x18, 31, 1)
++#define NANDC_CS_AUTO_CONFIG		REG_BIT_FIELD(0x18, 30, 1)
++#define NANDC_CS_NAND_WP		REG_BIT_FIELD(0x18, 29, 1)
++#define NANDC_CS_BLK0_WP		REG_BIT_FIELD(0x18, 28, 1)
++#define NANDC_CS_SW_USING_CS(n)		REG_BIT_FIELD(0x18, 8+(n), 1)
++#define NANDC_CS_MAP_SEL_CS(n)		REG_BIT_FIELD(0x18, 0+(n), 1)
++
++#define NANDC_XOR_ADDR_BLK0_ONLY	REG_BIT_FIELD(0x1c, 31, 1)
++#define NANDC_XOR_ADDR_CS(n)		REG_BIT_FIELD(0x1c, 0+(n), 1)
++
++#define NANDC_LL_OP_RET_IDLE		REG_BIT_FIELD(0x20, 31, 1)
++#define NANDC_LL_OP_CLE			REG_BIT_FIELD(0x20, 19, 1)
++#define NANDC_LL_OP_ALE			REG_BIT_FIELD(0x20, 18, 1)
++#define NANDC_LL_OP_WE			REG_BIT_FIELD(0x20, 17, 1)
++#define NANDC_LL_OP_RE			REG_BIT_FIELD(0x20, 16, 1)
++#define NANDC_LL_OP_DATA		REG_BIT_FIELD(0x20, 0, 16)
++
++#define NANDC_MPLANE_ADDR_EXT		REG_BIT_FIELD(0x24, 0, 16)
++#define NANDC_MPLANE_ADDR		REG_BIT_FIELD(0x28, 0, 32)
++
++#define NANDC_ACC_CTRL_CS(n)		REG_BIT_FIELD(0x50+((n)<<4), 0, 32)
++#define NANDC_ACC_CTRL_RD_ECC(n)	REG_BIT_FIELD(0x50+((n)<<4), 31, 1)
++#define NANDC_ACC_CTRL_WR_ECC(n)	REG_BIT_FIELD(0x50+((n)<<4), 30, 1)
++#define NANDC_ACC_CTRL_CE_CARE(n)	REG_BIT_FIELD(0x50+((n)<<4), 29, 1)
++#define NANDC_ACC_CTRL_PGM_RDIN(n)	REG_BIT_FIELD(0x50+((n)<<4), 28, 1)
++#define NANDC_ACC_CTRL_ERA_ECC_ERR(n)	REG_BIT_FIELD(0x50+((n)<<4), 27, 1)
++#define NANDC_ACC_CTRL_PGM_PARTIAL(n)	REG_BIT_FIELD(0x50+((n)<<4), 26, 1)
++#define NANDC_ACC_CTRL_WR_PREEMPT(n)	REG_BIT_FIELD(0x50+((n)<<4), 25, 1)
++#define NANDC_ACC_CTRL_PG_HIT(n)	REG_BIT_FIELD(0x50+((n)<<4), 24, 1)
++#define NANDC_ACC_CTRL_PREFETCH(n)	REG_BIT_FIELD(0x50+((n)<<4), 23, 1)
++#define NANDC_ACC_CTRL_CACHE_MODE(n)	REG_BIT_FIELD(0x50+((n)<<4), 22, 1)
++#define NANDC_ACC_CTRL_CACHE_LASTPG(n)	REG_BIT_FIELD(0x50+((n)<<4), 21, 1)
++#define NANDC_ACC_CTRL_ECC_LEVEL(n)	REG_BIT_FIELD(0x50+((n)<<4), 16, 5)
++#define NANDC_ACC_CTRL_SECTOR_1K(n)	REG_BIT_FIELD(0x50+((n)<<4), 7, 1)
++#define NANDC_ACC_CTRL_SPARE_SIZE(n)	REG_BIT_FIELD(0x50+((n)<<4), 0, 7)
++
++#define NANDC_CONFIG_CS(n)		REG_BIT_FIELD(0x54+((n)<<4), 0, 32)
++#define NANDC_CONFIG_LOCK(n)		REG_BIT_FIELD(0x54+((n)<<4), 31, 1)
++#define NANDC_CONFIG_BLK_SIZE(n)	REG_BIT_FIELD(0x54+((n)<<4), 28, 3)
++#define NANDC_CONFIG_CHIP_SIZE(n)	REG_BIT_FIELD(0x54+((n)<<4), 24, 4)
++#define NANDC_CONFIG_CHIP_WIDTH(n)	REG_BIT_FIELD(0x54+((n)<<4), 23, 1)
++#define NANDC_CONFIG_PAGE_SIZE(n)	REG_BIT_FIELD(0x54+((n)<<4), 20, 2)
++#define NANDC_CONFIG_FUL_ADDR_BYTES(n)	REG_BIT_FIELD(0x54+((n)<<4), 16, 3)
++#define NANDC_CONFIG_COL_ADDR_BYTES(n)	REG_BIT_FIELD(0x54+((n)<<4), 12, 3)
++#define NANDC_CONFIG_BLK_ADDR_BYTES(n)	REG_BIT_FIELD(0x54+((n)<<4), 8, 3)
++
++#define NANDC_TIMING_1_CS(n)		REG_BIT_FIELD(0x58+((n)<<4), 0, 32)
++#define NANDC_TIMING_2_CS(n)		REG_BIT_FIELD(0x5c+((n)<<4), 0, 32)
++	/* Individual bits for Timing registers - TBD */
++
++#define NANDC_CORR_STAT_THRESH_CS(n)	REG_BIT_FIELD(0xc0, 6*(n), 6)
++
++#define NANDC_BLK_WP_END_ADDR		REG_BIT_FIELD(0xc8, 0, 32)
++
++#define NANDC_MPLANE_ERASE_CYC2_OPCODE	REG_BIT_FIELD(0xcc, 24, 8)
++#define NANDC_MPLANE_READ_STAT_OPCODE	REG_BIT_FIELD(0xcc, 16, 8)
++#define NANDC_MPLANE_PROG_ODD_OPCODE	REG_BIT_FIELD(0xcc, 8, 8)
++#define NANDC_MPLANE_PROG_TRL_OPCODE	REG_BIT_FIELD(0xcc, 0, 8)
++
++#define NANDC_MPLANE_PGCACHE_TRL_OPCODE	REG_BIT_FIELD(0xd0, 24, 8)
++#define NANDC_MPLANE_READ_STAT2_OPCODE	REG_BIT_FIELD(0xd0, 16, 8)
++#define NANDC_MPLANE_READ_EVEN_OPCODE	REG_BIT_FIELD(0xd0, 8, 8)
++#define NANDC_MPLANE_READ_ODD__OPCODE	REG_BIT_FIELD(0xd0, 0, 8)
++
++#define NANDC_MPLANE_CTRL_ERASE_CYC2_EN	REG_BIT_FIELD(0xd4, 31, 1)
++#define NANDC_MPLANE_CTRL_RD_ADDR_SIZE	REG_BIT_FIELD(0xd4, 30, 1)
++#define NANDC_MPLANE_CTRL_RD_CYC_ADDR	REG_BIT_FIELD(0xd4, 29, 1)
++#define NANDC_MPLANE_CTRL_RD_COL_ADDR	REG_BIT_FIELD(0xd4, 28, 1)
++
++#define NANDC_UNCORR_ERR_COUNT		REG_BIT_FIELD(0xfc, 0, 32)
++
++#define NANDC_CORR_ERR_COUNT		REG_BIT_FIELD(0x100, 0, 32)
++
++#define NANDC_READ_CORR_BIT_COUNT	REG_BIT_FIELD(0x104, 0, 32)
++
++#define NANDC_BLOCK_LOCK_STATUS		REG_BIT_FIELD(0x108, 0, 8)
++
++#define NANDC_ECC_CORR_ADDR_CS		REG_BIT_FIELD(0x10c, 16, 3)
++#define NANDC_ECC_CORR_ADDR_EXT		REG_BIT_FIELD(0x10c, 0, 16)
++
++#define NANDC_ECC_CORR_ADDR		REG_BIT_FIELD(0x110, 0, 32)
++
++#define NANDC_ECC_UNC_ADDR_CS		REG_BIT_FIELD(0x114, 16, 3)
++#define NANDC_ECC_UNC_ADDR_EXT		REG_BIT_FIELD(0x114, 0, 16)
++
++#define NANDC_ECC_UNC_ADDR		REG_BIT_FIELD(0x118, 0, 32)
++
++#define NANDC_READ_ADDR_CS		REG_BIT_FIELD(0x11c, 16, 3)
++#define NANDC_READ_ADDR_EXT		REG_BIT_FIELD(0x11c, 0, 16)
++#define NANDC_READ_ADDR			REG_BIT_FIELD(0x120, 0, 32)
++
++#define NANDC_PROG_ADDR_CS		REG_BIT_FIELD(0x124, 16, 3)
++#define NANDC_PROG_ADDR_EXT		REG_BIT_FIELD(0x124, 0, 16)
++#define NANDC_PROG_ADDR			REG_BIT_FIELD(0x128, 0, 32)
++
++#define NANDC_CPYBK_ADDR_CS		REG_BIT_FIELD(0x12c, 16, 3)
++#define NANDC_CPYBK_ADDR_EXT		REG_BIT_FIELD(0x12c, 0, 16)
++#define NANDC_CPYBK_ADDR		REG_BIT_FIELD(0x130, 0, 32)
++
++#define NANDC_ERASE_ADDR_CS		REG_BIT_FIELD(0x134, 16, 3)
++#define NANDC_ERASE_ADDR_EXT		REG_BIT_FIELD(0x134, 0, 16)
++#define NANDC_ERASE_ADDR		REG_BIT_FIELD(0x138, 0, 32)
++
++#define NANDC_INV_READ_ADDR_CS		REG_BIT_FIELD(0x13c, 16, 3)
++#define NANDC_INV_READ_ADDR_EXT		REG_BIT_FIELD(0x13c, 0, 16)
++#define NANDC_INV_READ_ADDR		REG_BIT_FIELD(0x140, 0, 32)
++
++#define NANDC_INIT_STAT			REG_BIT_FIELD(0x144, 0, 32)
++#define NANDC_INIT_ONFI_DONE		REG_BIT_FIELD(0x144, 31, 1)
++#define NANDC_INIT_DEVID_DONE		REG_BIT_FIELD(0x144, 30, 1)
++#define NANDC_INIT_SUCCESS		REG_BIT_FIELD(0x144, 29, 1)
++#define NANDC_INIT_FAIL			REG_BIT_FIELD(0x144, 28, 1)
++#define NANDC_INIT_BLANK		REG_BIT_FIELD(0x144, 27, 1)
++#define NANDC_INIT_TIMEOUT		REG_BIT_FIELD(0x144, 26, 1)
++#define NANDC_INIT_UNC_ERROR		REG_BIT_FIELD(0x144, 25, 1)
++#define NANDC_INIT_CORR_ERROR		REG_BIT_FIELD(0x144, 24, 1)
++#define NANDC_INIT_PARAM_RDY		REG_BIT_FIELD(0x144, 23, 1)
++#define NANDC_INIT_AUTH_FAIL		REG_BIT_FIELD(0x144, 22, 1)
++
++#define NANDC_ONFI_STAT			REG_BIT_FIELD(0x148, 0, 32)
++#define NANDC_ONFI_DEBUG		REG_BIT_FIELD(0x148, 28, 4)
++#define NANDC_ONFI_PRESENT		REG_BIT_FIELD(0x148, 27, 1)
++#define NANDC_ONFI_BADID_PG2		REG_BIT_FIELD(0x148, 5, 1)
++#define NANDC_ONFI_BADID_PG1		REG_BIT_FIELD(0x148, 4, 1)
++#define NANDC_ONFI_BADID_PG0		REG_BIT_FIELD(0x148, 3, 1)
++#define NANDC_ONFI_BADCRC_PG2		REG_BIT_FIELD(0x148, 2, 1)
++#define NANDC_ONFI_BADCRC_PG1		REG_BIT_FIELD(0x148, 1, 1)
++#define NANDC_ONFI_BADCRC_PG0		REG_BIT_FIELD(0x148, 0, 1)
++
++#define NANDC_ONFI_DEBUG_DATA		REG_BIT_FIELD(0x14c, 0, 32)
++
++#define NANDC_SEMAPHORE			REG_BIT_FIELD(0x150, 0, 8)
++
++#define NANDC_DEVID_BYTE(b)		REG_BIT_FIELD(0x194+((b)&0x4), \
++						24-(((b)&3)<<3), 8)
++
++#define NANDC_LL_RDDATA			REG_BIT_FIELD(0x19c, 0, 16)
++
++#define NANDC_INT_N_REG(n)		REG_BIT_FIELD(0xf00|((n)<<2), 0, 1)
++#define NANDC_INT_DIREC_READ_MISS	REG_BIT_FIELD(0xf00, 0, 1)
++#define NANDC_INT_ERASE_DONE		REG_BIT_FIELD(0xf04, 0, 1)
++#define NANDC_INT_CPYBK_DONE		REG_BIT_FIELD(0xf08, 0, 1)
++#define NANDC_INT_PROGRAM_DONE		REG_BIT_FIELD(0xf0c, 0, 1)
++#define NANDC_INT_CONTROLLER_RDY	REG_BIT_FIELD(0xf10, 0, 1)
++#define NANDC_INT_RDBSY_RDY		REG_BIT_FIELD(0xf14, 0, 1)
++#define NANDC_INT_ECC_UNCORRECTABLE	REG_BIT_FIELD(0xf18, 0, 1)
++#define NANDC_INT_ECC_CORRECTABLE	REG_BIT_FIELD(0xf1c, 0, 1)
++
++/*
++ * Following  registers are treated as contigous IO memory, offset is from
++ * <reg_base>, and the data is in big-endian byte order
++ */
++#define NANDC_SPARE_AREA_READ_OFF	0x200
++#define NANDC_SPARE_AREA_WRITE_OFF	0x280
++#define NANDC_CACHE_OFF			0x400
++#define NANDC_CACHE_SIZE		(128*4)
++
++struct bcmnand_areg_field {
++	unsigned int reg;
++	unsigned int pos;
++	unsigned int width;
++};
++
++/*
++ * Following are IDM (a.k.a. Slave Wrapper) registers are off <idm_base>:
++ */
++#define IDMREG_BIT_FIELD(r, p, w)	((struct bcmnand_areg_field){(r), (p), (w)})
++
++#define NANDC_IDM_AXI_BIG_ENDIAN	IDMREG_BIT_FIELD(0x408, 28, 1)
++#define NANDC_IDM_APB_LITTLE_ENDIAN	IDMREG_BIT_FIELD(0x408, 24, 1)
++#define NANDC_IDM_TM			IDMREG_BIT_FIELD(0x408, 16, 5)
++#define NANDC_IDM_IRQ_CORRECABLE_EN	IDMREG_BIT_FIELD(0x408, 9, 1)
++#define NANDC_IDM_IRQ_UNCORRECABLE_EN	IDMREG_BIT_FIELD(0x408, 8, 1)
++#define NANDC_IDM_IRQ_RDYBSY_RDY_EN	IDMREG_BIT_FIELD(0x408, 7, 1)
++#define NANDC_IDM_IRQ_CONTROLLER_RDY_EN	IDMREG_BIT_FIELD(0x408, 6, 1)
++#define NANDC_IDM_IRQ_PRPOGRAM_COMP_EN	IDMREG_BIT_FIELD(0x408, 5, 1)
++#define NANDC_IDM_IRQ_COPYBK_COMP_EN	IDMREG_BIT_FIELD(0x408, 4, 1)
++#define NANDC_IDM_IRQ_ERASE_COMP_EN	IDMREG_BIT_FIELD(0x408, 3, 1)
++#define NANDC_IDM_IRQ_READ_MISS_EN	IDMREG_BIT_FIELD(0x408, 2, 1)
++#define NANDC_IDM_IRQ_N_EN(n)		IDMREG_BIT_FIELD(0x408, 2+(n), 1)
++
++#define NANDC_IDM_CLOCK_EN		IDMREG_BIT_FIELD(0x408, 0, 1)
++
++#define NANDC_IDM_IO_ECC_CORR		IDMREG_BIT_FIELD(0x500, 3, 1)
++#define NANDC_IDM_IO_ECC_UNCORR		IDMREG_BIT_FIELD(0x500, 2, 1)
++#define NANDC_IDM_IO_RDYBSY		IDMREG_BIT_FIELD(0x500, 1, 1)
++#define NANDC_IDM_IO_CTRL_RDY		IDMREG_BIT_FIELD(0x500, 0, 1)
++
++#define NANDC_IDM_RESET			IDMREG_BIT_FIELD(0x800, 0, 1)
++	/* Remaining IDM registers do not seem to be useful, skipped */
++
++/*
++ * NAND Controller has its own command opcodes
++ * different from opcodes sent to the actual flash chip
++ */
++#define NANDC_CMD_OPCODE_NULL		0
++#define NANDC_CMD_OPCODE_PAGE_READ	1
++#define NANDC_CMD_OPCODE_SPARE_READ	2
++#define NANDC_CMD_OPCODE_STATUS_READ	3
++#define NANDC_CMD_OPCODE_PAGE_PROG	4
++#define NANDC_CMD_OPCODE_SPARE_PROG	5
++#define NANDC_CMD_OPCODE_DEVID_READ	7
++#define NANDC_CMD_OPCODE_BLOCK_ERASE	8
++#define NANDC_CMD_OPCODE_FLASH_RESET	9
++
++/*
++ * NAND Controller hardware ECC data size
++ *
++ * The following table contains the number of bytes needed for
++ * each of the ECC levels, per "sector", which is either 512 or 1024 bytes.
++ * The actual layout is as follows:
++ * The entire spare area is equally divided into as many sections as there
++ * are sectors per page, and the ECC data is located at the end of each
++ * of these sections.
++ * For example, given a 2K per page and 64 bytes spare device, configured for
++ * sector size 1k and ECC level of 4, the spare area will be divided into 2
++ * sections 32 bytes each, and the last 14 bytes of 32 in each section will
++ * be filled with ECC data.
++ * Note: the name of the algorythm and the number of error bits it can correct
++ * is of no consequence to this driver, therefore omitted.
++ */
++struct bcmnand_ecc_size_s {
++	unsigned char sector_size_shift;
++	unsigned char ecc_level;
++	unsigned char ecc_bytes_per_sec;
++	unsigned char reserved;
++};
++
++static const struct bcmnand_ecc_size_s bcmnand_ecc_sizes[] = {
++	{ 9,	0,	0 },
++	{ 10,	0,	0 },
++	{ 9,	1,	2 },
++	{ 10,	1,	4 },
++	{ 9,	2,	4 },
++	{ 10,	2,	7 },
++	{ 9,	3,	6 },
++	{ 10,	3,	11 },
++	{ 9,	4,	7 },
++	{ 10,	4,	14 },
++	{ 9,	5,	9 },
++	{ 10,	5,	18 },
++	{ 9,	6,	11 },
++	{ 10,	6,	21 },
++	{ 9,	7,	13 },
++	{ 10,	7,	25 },
++	{ 9,	8,	14 },
++	{ 10,	8,	28 },
++
++	{ 9,	9,	16 },
++	{ 9,	10,	18 },
++	{ 9,	11,	20 },
++	{ 9,	12,	21 },
++
++	{ 10,	9,	32 },
++	{ 10,	10,	35 },
++	{ 10,	11,	39 },
++	{ 10,	12,	42 },
++};
++
++/*
++ * Populate the various fields that depend on how
++ * the hardware ECC data is located in the spare area
++ *
++ * For this controiller, it is easier to fill-in these
++ * structures at run time.
++ *
++ * The bad-block marker is assumed to occupy one byte
++ * at chip->badblockpos, which must be in the first
++ * sector of the spare area, namely it is either
++ * at offset 0 or 5.
++ * Some chips use both for manufacturer's bad block
++ * markers, but we ingore that issue here, and assume only
++ * one byte is used as bad-block marker always.
++ */
++static int bcmnand_hw_ecc_layout(struct bcmnand_ctrl *ctrl)
++{
++	struct nand_ecclayout *layout;
++	struct device *dev = &ctrl->core->dev;
++	unsigned int i, j, k;
++	unsigned int ecc_per_sec, oob_per_sec;
++	unsigned int bbm_pos = ctrl->nand.badblockpos;
++
++	/* Caclculate spare area per sector size */
++	oob_per_sec = ctrl->mtd.oobsize >> ctrl->sec_per_page_shift;
++
++	/* Try to calculate the amount of ECC bytes per sector with a formula */
++	if (ctrl->sector_size_shift == 9)
++		ecc_per_sec = ((ctrl->ecc_level * 14) + 7) >> 3;
++	else if (ctrl->sector_size_shift == 10)
++		ecc_per_sec = ((ctrl->ecc_level * 14) + 3) >> 2;
++	else
++		ecc_per_sec = oob_per_sec + 1;	/* cause an error if not in table */
++
++	/* Now find out the answer according to the table */
++	for (i = 0; i < ARRAY_SIZE(bcmnand_ecc_sizes); i++) {
++		if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level &&
++		    bcmnand_ecc_sizes[i].sector_size_shift ==
++				ctrl->sector_size_shift) {
++			break;
++		}
++	}
++
++	/* Table match overrides formula */
++	if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level &&
++	    bcmnand_ecc_sizes[i].sector_size_shift == ctrl->sector_size_shift)
++		ecc_per_sec = bcmnand_ecc_sizes[i].ecc_bytes_per_sec;
++
++	/* Return an error if calculated ECC leaves no room for OOB */
++	if ((ctrl->sec_per_page_shift != 0 && ecc_per_sec >= oob_per_sec) ||
++	    (ctrl->sec_per_page_shift == 0 && ecc_per_sec >= (oob_per_sec - 1))) {
++		dev_err(dev, "ECC level %d too high, leaves no room for OOB data\n",
++			ctrl->ecc_level);
++		return -EINVAL;
++	}
++
++	/* Fill in the needed fields */
++	ctrl->nand.ecc.size = ctrl->mtd.writesize >> ctrl->sec_per_page_shift;
++	ctrl->nand.ecc.bytes = ecc_per_sec;
++	ctrl->nand.ecc.steps = 1 << ctrl->sec_per_page_shift;
++	ctrl->nand.ecc.total = ecc_per_sec << ctrl->sec_per_page_shift;
++	ctrl->nand.ecc.strength = ctrl->ecc_level;
++
++	/* Build an ecc layout data structure */
++	layout = &ctrl->ecclayout;
++	memset(layout, 0, sizeof(*layout));
++
++	/* Total number of bytes used by HW ECC */
++	layout->eccbytes = ecc_per_sec << ctrl->sec_per_page_shift;
++
++	/* Location for each of the HW ECC bytes */
++	for (i = j = 0, k = 1;
++	     i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes;
++	     i++, j++) {
++		/* switch sector # */
++		if (j == ecc_per_sec) {
++			j = 0;
++			k++;
++		}
++		/* save position of each HW-generated ECC byte */
++		layout->eccpos[i] = (oob_per_sec * k) - ecc_per_sec + j;
++
++		/* Check that HW ECC does not overlap bad-block marker */
++		if (bbm_pos == layout->eccpos[i]) {
++			dev_err(dev, "ECC level %d too high, HW ECC collides with bad-block marker position\n",
++				ctrl->ecc_level);
++			return -EINVAL;
++		}
++	}
++
++	/* Location of all user-available OOB byte-ranges */
++	for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++) {
++		struct nand_oobfree *oobfree = &layout->oobfree[i];
++
++		if (i >= (1 << ctrl->sec_per_page_shift))
++			break;
++		oobfree->offset = oob_per_sec * i;
++		oobfree->length = oob_per_sec - ecc_per_sec;
++
++		/* Bad-block marker must be in the first sector spare area */
++		if (WARN_ON(bbm_pos >= (oobfree->offset + oobfree->length)))
++			return -EINVAL;
++
++		if (i != 0)
++			continue;
++
++		/* Remove bad-block marker from available byte range */
++		if (bbm_pos == oobfree->offset) {
++			oobfree->offset += 1;
++			oobfree->length -= 1;
++		} else if (bbm_pos == (oobfree->offset + oobfree->length - 1)) {
++			oobfree->length -= 1;
++		} else {
++			layout->oobfree[i + 1].offset = bbm_pos + 1;
++			layout->oobfree[i + 1].length =
++				oobfree->length - bbm_pos - 1;
++			oobfree->length = bbm_pos;
++			i++;
++		}
++	}
++
++	layout->oobavail = ((oob_per_sec - ecc_per_sec)
++		<< ctrl->sec_per_page_shift) - 1;
++
++	ctrl->mtd.oobavail = layout->oobavail;
++	ctrl->nand.ecc.layout = layout;
++
++	/* Output layout for debugging */
++	dev_dbg(dev, "Spare area=%d eccbytes %d, ecc bytes located at:\n",
++		ctrl->mtd.oobsize, layout->eccbytes);
++	for (i = j = 0;
++	     i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes; i++)
++		pr_debug(" %d", layout->eccpos[i]);
++	pr_debug("\n");
++
++	dev_dbg(dev, "Available %d bytes at (off,len):\n", layout->oobavail);
++	for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++)
++		pr_debug("(%d,%d) ", layout->oobfree[i].offset,
++			 layout->oobfree[i].length);
++	pr_debug("\n");
++
++	return 0;
++}
++
++/*
++ * Register bit-field manipulation routines
++ */
++
++static inline unsigned int bcmnand_reg_read(struct bcmnand_ctrl *ctrl,
++					    struct bcmnand_reg_field rbf)
++{
++	u32 val;
++
++	val = bcma_read32(ctrl->core, rbf.reg);
++	val >>= rbf.pos;
++	val &= (1 << rbf.width) - 1;
++
++	return val;
++}
++
++static inline void bcmnand_reg_write(struct bcmnand_ctrl *ctrl,
++				     struct bcmnand_reg_field rbf,
++				     unsigned newval)
++{
++	u32 val, msk;
++
++	msk = (1 << rbf.width) - 1;
++	msk <<= rbf.pos;
++	newval <<= rbf.pos;
++	newval &= msk;
++
++	val = bcma_read32(ctrl->core, rbf.reg);
++	val &= ~msk;
++	val |= newval;
++	bcma_write32(ctrl->core, rbf.reg, val);
++}
++
++static inline unsigned int bcmnand_reg_aread(struct bcmnand_ctrl *ctrl,
++					     struct bcmnand_areg_field rbf)
++{
++	u32 val;
++
++	val = bcma_aread32(ctrl->core, rbf.reg);
++	val >>= rbf.pos;
++	val &= (1 << rbf.width) - 1;
++
++	return val;
++}
++
++static inline void bcmnand_reg_awrite(struct bcmnand_ctrl *ctrl,
++				      struct bcmnand_areg_field rbf,
++				      unsigned int newval)
++{
++	u32 val, msk;
++
++	msk = (1 << rbf.width) - 1;
++	msk <<= rbf.pos;
++	newval <<= rbf.pos;
++	newval &= msk;
++
++	val = bcma_aread32(ctrl->core, rbf.reg);
++	val &= ~msk;
++	val |= newval;
++	bcma_awrite32(ctrl->core, rbf.reg, val);
++}
++
++/*
++ * NAND Interface - dev_ready
++ *
++ * Return 1 iff device is ready, 0 otherwise
++ */
++static int bcmnand_dev_ready(struct mtd_info *mtd)
++{
++	struct nand_chip *chip = mtd->priv;
++	struct bcmnand_ctrl *ctrl = chip->priv;
++
++	return bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY);
++}
++
++/*
++ * Interrupt service routines
++ */
++static irqreturn_t bcmnand_isr(int irq, void *dev_id)
++{
++	struct bcmnand_ctrl *ctrl = dev_id;
++	int irq_off;
++
++	irq_off = irq - ctrl->core->irq;
++	WARN_ON(irq_off < 0 || irq_off >= NANDC_IRQ_NUM);
++
++	if (!bcmnand_reg_read(ctrl, NANDC_INT_N_REG(irq_off)))
++		return IRQ_NONE;
++
++	/* Acknowledge interrupt */
++	bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1);
++
++	/* Wake up task */
++	complete(&ctrl->op_completion);
++
++	return IRQ_HANDLED;
++}
++
++static int bcmnand_wait_interrupt(struct bcmnand_ctrl *ctrl,
++				  unsigned int irq_off,
++				  unsigned int timeout_usec)
++{
++	long timeout_jiffies;
++	int ret = 0;
++
++	reinit_completion(&ctrl->op_completion);
++
++	/* Acknowledge interrupt */
++	bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1);
++
++	/* Enable IRQ to wait on */
++	bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 1);
++
++	timeout_jiffies = 1 + usecs_to_jiffies(timeout_usec);
++
++	if (irq_off != NANDC_IRQ_CONTROLLER_RDY ||
++		0 == bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)) {
++
++		timeout_jiffies = wait_for_completion_timeout(
++					&ctrl->op_completion, timeout_jiffies);
++
++		if (timeout_jiffies < 0)
++			ret =  timeout_jiffies;
++		if (timeout_jiffies == 0)
++			ret = -ETIME;
++	}
++
++	/* Disable IRQ, we're done waiting */
++	bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0);
++
++	if (bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY))
++		ret = 0;
++
++	return ret;
++}
++
++/*
++ * wait for command completion
++ */
++static int bcmnand_wait_cmd(struct bcmnand_ctrl *ctrl, unsigned int timeout_usec)
++{
++	unsigned int retries;
++
++	if (bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY))
++		return 0;
++
++	/* If the timeout is long, wait for interrupt */
++	if (timeout_usec >= jiffies_to_usecs(1) >> 4)
++		return bcmnand_wait_interrupt(
++			ctrl, NANDC_IRQ_CONTROLLER_RDY, timeout_usec);
++
++	/* Wait for completion of the prior command */
++	retries = (timeout_usec >> 3) + 1;
++
++	while (retries-- &&
++		0 == bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY)) {
++		cpu_relax();
++		udelay(6);
++	}
++
++	if (retries == 0)
++		return -ETIME;
++
++	return 0;
++}
++
++
++/*
++ * NAND Interface - waitfunc
++ */
++static int bcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *chip)
++{
++	struct bcmnand_ctrl *ctrl = chip->priv;
++	unsigned int to;
++	int ret;
++
++	/* figure out timeout based on what command is on */
++	switch (ctrl->last_cmd) {
++	default:
++	case NAND_CMD_ERASE1:
++	case NAND_CMD_ERASE2:
++		to = 1 << 16;
++		break;
++	case NAND_CMD_STATUS:
++	case NAND_CMD_RESET:
++		to = 256;
++		break;
++	case NAND_CMD_READID:
++		to = 1024;
++		break;
++	case NAND_CMD_READ1:
++	case NAND_CMD_READ0:
++		to = 2048;
++		break;
++	case NAND_CMD_PAGEPROG:
++		to = 4096;
++		break;
++	case NAND_CMD_READOOB:
++		to = 512;
++		break;
++	}
++
++	/* deliver deferred error code if any */
++	ret = ctrl->cmd_ret;
++	if (ret < 0)
++		ctrl->cmd_ret = 0;
++	else
++		ret = bcmnand_wait_cmd(ctrl, to);
++
++	/* Timeout */
++	if (ret < 0)
++		return NAND_STATUS_FAIL;
++
++	ret = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS);
++
++	return ret;
++}
++
++/*
++ * NAND Interface - read_oob
++ */
++static int bcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
++			    int page)
++{
++	struct bcmnand_ctrl *ctrl = chip->priv;
++	unsigned int n = ctrl->chip_num;
++	void __iomem *ctrl_spare;
++	unsigned int spare_per_sec, sector;
++	u64 nand_addr;
++
++	ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF;
++
++	/* Set the page address for the following commands */
++	nand_addr = ((u64)page << chip->page_shift);
++	bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32);
++
++	spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift;
++
++	/* Disable ECC validation for spare area reads */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), 0);
++
++	/* Loop all sectors in page */
++	for (sector = 0; sector < (1<<ctrl->sec_per_page_shift); sector++) {
++		unsigned int col;
++
++		col = (sector << ctrl->sector_size_shift);
++
++		/* Issue command to read partial page */
++		bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col);
++
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_SPARE_READ);
++
++		/* Wait for the command to complete */
++		if (bcmnand_wait_cmd(ctrl, (sector == 0) ? 10000 : 100))
++			return -EIO;
++
++		if (!bcmnand_reg_read(ctrl, NANDC_INT_STAT_SPARE_VALID))
++			return -EIO;
++
++		/* Set controller to Little Endian mode for copying */
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1);
++
++		memcpy(chip->oob_poi + sector * spare_per_sec,
++		       ctrl_spare, spare_per_sec);
++
++		/* Return to Big Endian mode for commands etc */
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0);
++	}
++
++	return 0;
++}
++
++/*
++ * NAND Interface - write_oob
++ */
++static int bcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
++			     int page)
++{
++	struct bcmnand_ctrl *ctrl = chip->priv;
++	unsigned int n = ctrl->chip_num;
++	void __iomem *ctrl_spare;
++	unsigned int spare_per_sec, sector, num_sec;
++	u64 nand_addr;
++	int to, status = 0;
++
++	ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF;
++
++	/* Disable ECC generation for spare area writes */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), 0);
++
++	spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift;
++
++	/* Set the page address for the following commands */
++	nand_addr = ((u64)page << chip->page_shift);
++	bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32);
++
++	/* Must allow partial programming to change spare area only */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 1);
++
++	num_sec = 1 << ctrl->sec_per_page_shift;
++	/* Loop all sectors in page */
++	for (sector = 0; sector < num_sec; sector++) {
++		unsigned int col;
++
++		/* Spare area accessed by the data sector offset */
++		col = (sector << ctrl->sector_size_shift);
++
++		bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col);
++
++		/* Set controller to Little Endian mode for copying */
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1);
++
++		memcpy(ctrl_spare, chip->oob_poi + sector * spare_per_sec,
++		       spare_per_sec);
++
++		/* Return to Big Endian mode for commands etc */
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0);
++
++		/* Push spare bytes into internal buffer, last goes to flash */
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_SPARE_PROG);
++
++		if (sector == (num_sec - 1))
++			to = 1 << 16;
++		else
++			to = 1 << 10;
++
++		if (bcmnand_wait_cmd(ctrl, to))
++			return -EIO;
++	}
++
++	/* Restore partial programming inhibition */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 0);
++
++	status = bcmnand_waitfunc(mtd, chip);
++	return status & NAND_STATUS_FAIL ? -EIO : 0;
++}
++
++/*
++ * verify that a buffer is all erased
++ */
++static bool bcmnand_buf_erased(const void *buf, unsigned int len)
++{
++	unsigned int i;
++	const u32 *p = buf;
++
++	for (i = 0; i < (len >> 2); i++) {
++		if (p[i] != 0xffffffff)
++			return false;
++	}
++	return true;
++}
++
++/*
++ * read a page, with or without ECC checking
++ */
++static int bcmnand_read_page_do(struct mtd_info *mtd, struct nand_chip *chip,
++				uint8_t *buf, int page, bool ecc)
++{
++	struct bcmnand_ctrl *ctrl = chip->priv;
++	unsigned int n = ctrl->chip_num;
++	void __iomem *ctrl_cache;
++	void __iomem *ctrl_spare;
++	unsigned int data_bytes;
++	unsigned int spare_per_sec;
++	unsigned int sector, to = 1 << 16;
++	u32 err_soft_reg, err_hard_reg;
++	unsigned int hard_err_count = 0;
++	int ret;
++	u64 nand_addr;
++
++	ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF;
++	ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF;
++
++	/* Reset  ECC error stats */
++	err_hard_reg = bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT);
++	err_soft_reg = bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT);
++
++	spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift;
++
++	/* Set the page address for the following commands */
++	nand_addr = ((u64)page << chip->page_shift);
++	bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32);
++
++	/* Enable ECC validation for ecc page reads */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), ecc);
++
++	/* Loop all sectors in page */
++	for (sector = 0; sector < (1 << ctrl->sec_per_page_shift); sector++) {
++		data_bytes  = 0;
++
++		/* Copy partial sectors sized by cache reg */
++		while (data_bytes < (1<<ctrl->sector_size_shift)) {
++			unsigned int col;
++
++			col = data_bytes + (sector << ctrl->sector_size_shift);
++
++			bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS,
++					  nand_addr + col);
++
++			/* Issue command to read partial page */
++			bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++					  NANDC_CMD_OPCODE_PAGE_READ);
++
++			/* Wait for the command to complete */
++			ret = bcmnand_wait_cmd(ctrl, to);
++			if (ret < 0)
++				return ret;
++
++			/* Set controller to Little Endian mode for copying */
++			bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1);
++
++			if (data_bytes == 0) {
++				memcpy(chip->oob_poi + sector * spare_per_sec,
++				       ctrl_spare, spare_per_sec);
++			}
++
++			memcpy(buf + col, ctrl_cache, NANDC_CACHE_SIZE);
++			data_bytes += NANDC_CACHE_SIZE;
++
++			/* Return to Big Endian mode for commands etc */
++			bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0);
++
++			/* Next iterations should go fast */
++			to = 1 << 10;
++
++			/* capture hard errors for each partial */
++			if (err_hard_reg != bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT)) {
++				int era = bcmnand_reg_read(ctrl, NANDC_INT_STAT_ERASED);
++
++				if (!era &&
++				    !bcmnand_buf_erased(buf + col, NANDC_CACHE_SIZE))
++					hard_err_count++;
++
++				err_hard_reg = bcmnand_reg_read(ctrl,
++							NANDC_UNCORR_ERR_COUNT);
++			}
++		}
++	}
++
++	if (!ecc)
++		return 0;
++
++	/* Report hard ECC errors */
++	if (hard_err_count)
++		mtd->ecc_stats.failed++;
++
++	/* Get ECC soft error stats */
++	mtd->ecc_stats.corrected += err_soft_reg -
++			bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT);
++
++	return 0;
++}
++
++/*
++ * NAND Interface - read_page_ecc
++ */
++static int bcmnand_read_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
++				 uint8_t *buf, int oob_required, int page)
++{
++	return bcmnand_read_page_do(mtd, chip, buf, page, true);
++}
++
++/*
++ * NAND Interface - read_page_raw
++ */
++static int bcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
++				 uint8_t *buf, int oob_required, int page)
++{
++	return bcmnand_read_page_do(mtd, chip, buf, page, true);
++}
++
++/*
++ * do page write, with or without ECC generation enabled
++ */
++static int bcmnand_write_page_do(struct mtd_info *mtd, struct nand_chip *chip,
++				 const uint8_t *buf, bool ecc)
++{
++	struct bcmnand_ctrl *ctrl = chip->priv;
++	unsigned int n = ctrl->chip_num;
++	void __iomem *ctrl_cache;
++	void __iomem *ctrl_spare;
++	unsigned int spare_per_sec, sector, num_sec;
++	unsigned int data_bytes, spare_bytes;
++	int i, to;
++	uint8_t *tmp_poi;
++	u32 nand_addr;
++
++	ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF;
++	ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF;
++
++	/* Get start-of-page address */
++	nand_addr = bcmnand_reg_read(ctrl, NANDC_CMD_ADDRESS);
++
++	tmp_poi = kmalloc(mtd->oobsize, GFP_KERNEL);
++	if (!tmp_poi)
++		return -ENOMEM;
++
++	/* Retreive pre-existing OOB values */
++	memcpy(tmp_poi, chip->oob_poi, mtd->oobsize);
++	ctrl->cmd_ret = bcmnand_read_oob(mtd, chip,
++					 nand_addr >> chip->page_shift);
++	if (ctrl->cmd_ret < 0) {
++		kfree(tmp_poi);
++		return ctrl->cmd_ret;
++	}
++
++	/* Apply new OOB data bytes just like they would end up on the chip */
++	for (i = 0; i < mtd->oobsize; i++)
++		chip->oob_poi[i] &= tmp_poi[i];
++	kfree(tmp_poi);
++
++	spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift;
++
++	/* Enable ECC generation for ecc page write, if requested */
++	bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), ecc);
++
++	spare_bytes = 0;
++	num_sec = 1 << ctrl->sec_per_page_shift;
++
++	/* Loop all sectors in page */
++	for (sector = 0; sector < num_sec; sector++) {
++		data_bytes  = 0;
++
++		/* Copy partial sectors sized by cache reg */
++		while (data_bytes < (1<<ctrl->sector_size_shift)) {
++			unsigned int col;
++
++			col = data_bytes +
++				(sector << ctrl->sector_size_shift);
++
++			/* Set address of 512-byte sub-page */
++			bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS,
++					  nand_addr + col);
++
++			/* Set controller to Little Endian mode for copying */
++			bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN,
++					   1);
++
++			/* Set spare area is written at each sector start */
++			if (data_bytes == 0) {
++				memcpy(ctrl_spare,
++					chip->oob_poi + spare_bytes,
++					spare_per_sec);
++				spare_bytes += spare_per_sec;
++			}
++
++			/* Copy sub-page data */
++			memcpy(ctrl_cache, buf + col, NANDC_CACHE_SIZE);
++			data_bytes += NANDC_CACHE_SIZE;
++
++			/* Return to Big Endian mode for commands etc */
++			bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0);
++
++			/* Push data into internal cache */
++			bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++					  NANDC_CMD_OPCODE_PAGE_PROG);
++
++			/* Wait for the command to complete */
++			if (sector == (num_sec - 1))
++				to = 1 << 16;
++			else
++				to = 1 << 10;
++			ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to);
++			if (ctrl->cmd_ret < 0)
++				return ctrl->cmd_ret;
++		}
++	}
++	return 0;
++}
++
++/*
++ * NAND Interface = write_page_ecc
++ */
++static int bcmnand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip,
++				  const uint8_t *buf, int oob_required)
++{
++	return bcmnand_write_page_do(mtd, chip, buf, true);
++}
++
++/*
++ * NAND Interface = write_page_raw
++ */
++static int bcmnand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
++				  const uint8_t *buf, int oob_required)
++{
++	return bcmnand_write_page_do(mtd, chip, buf, false);
++}
++
++/*
++ * MTD Interface - read_byte
++ *
++ * This function emulates simple controllers behavior
++ * for just a few relevant commands
++ */
++static uint8_t bcmnand_read_byte(struct mtd_info *mtd)
++{
++	struct nand_chip *nand = mtd->priv;
++	struct bcmnand_ctrl *ctrl = nand->priv;
++	struct device *dev = &ctrl->core->dev;
++	uint8_t b = ~0;
++
++	switch (ctrl->last_cmd) {
++	case NAND_CMD_READID:
++		if (ctrl->id_byte_index < 8) {
++			b = bcmnand_reg_read(ctrl, NANDC_DEVID_BYTE(
++							ctrl->id_byte_index));
++			ctrl->id_byte_index++;
++		}
++		break;
++	case NAND_CMD_READOOB:
++		if (ctrl->oob_index < mtd->oobsize)
++			b = nand->oob_poi[ctrl->oob_index++];
++		break;
++	case NAND_CMD_STATUS:
++		b = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS);
++		break;
++	default:
++		dev_err(dev, "got unkown command: 0x%x in read_byte\n",
++			ctrl->last_cmd);
++	}
++	return b;
++}
++
++/*
++ * MTD Interface - read_word
++ *
++ * Can not be tested without x16 chip, but the SoC does not support x16 i/f.
++ */
++static u16 bcmnand_read_word(struct mtd_info *mtd)
++{
++	u16 w = ~0;
++
++	w = bcmnand_read_byte(mtd);
++	barrier();
++	w |= bcmnand_read_byte(mtd) << 8;
++
++	return w;
++}
++
++/*
++ * MTD Interface - select a chip from an array
++ */
++static void bcmnand_select_chip(struct mtd_info *mtd, int chip)
++{
++	struct nand_chip *nand = mtd->priv;
++	struct bcmnand_ctrl *ctrl = nand->priv;
++
++	ctrl->chip_num = chip;
++	bcmnand_reg_write(ctrl, NANDC_CMD_CS_SEL, chip);
++}
++
++/*
++ * NAND Interface - emulate low-level NAND commands
++ *
++ * Only a few low-level commands are really needed by generic NAND,
++ * and they do not call for CMD_LL operations the controller can support.
++ */
++static void bcmnand_cmdfunc(struct mtd_info *mtd, unsigned int command,
++			    int column, int page_addr)
++{
++	struct nand_chip *nand = mtd->priv;
++	struct bcmnand_ctrl *ctrl = nand->priv;
++	struct device *dev = &ctrl->core->dev;
++	u64 nand_addr;
++	unsigned int to = 1;
++
++	ctrl->last_cmd = command;
++
++	/* Set address for some commands */
++	switch (command) {
++	case NAND_CMD_ERASE1:
++		column = 0;
++		/*FALLTHROUGH*/
++	case NAND_CMD_SEQIN:
++	case NAND_CMD_READ0:
++	case NAND_CMD_READ1:
++		WARN_ON(column >= mtd->writesize);
++		nand_addr = (u64) column |
++			((u64)page_addr << nand->page_shift);
++		bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32);
++		bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr);
++		break;
++	case NAND_CMD_ERASE2:
++	case NAND_CMD_RESET:
++	case NAND_CMD_READID:
++	case NAND_CMD_READOOB:
++	case NAND_CMD_PAGEPROG:
++	default:
++		/* Do nothing, address not used */
++		break;
++	}
++
++	/* Issue appropriate command to controller */
++	switch (command) {
++	case NAND_CMD_SEQIN:
++		/* Only need to load command address, done */
++		return;
++
++	case NAND_CMD_RESET:
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_FLASH_RESET);
++		to = 1 << 8;
++		break;
++
++	case NAND_CMD_READID:
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_DEVID_READ);
++		ctrl->id_byte_index = 0;
++		to = 1 << 8;
++		break;
++
++	case NAND_CMD_READ0:
++	case NAND_CMD_READ1:
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_PAGE_READ);
++		to = 1 << 15;
++		break;
++	case NAND_CMD_STATUS:
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_STATUS_READ);
++		to = 1 << 8;
++		break;
++	case NAND_CMD_ERASE1:
++		return;
++
++	case NAND_CMD_ERASE2:
++		bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE,
++				  NANDC_CMD_OPCODE_BLOCK_ERASE);
++		to = 1 << 18;
++		break;
++
++	case NAND_CMD_PAGEPROG:
++		/* Cmd already set from write_page */
++		return;
++
++	case NAND_CMD_READOOB:
++		/* Emulate simple interface */
++		bcmnand_read_oob(mtd, nand, page_addr);
++		ctrl->oob_index = 0;
++		return;
++
++	default:
++		dev_err(dev, "got unkown command: 0x%x in cmdfunc\n",
++			ctrl->last_cmd);
++	}
++
++	/* Wait for command to complete */
++	ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to);
++
++}
++
++static int bcmnand_scan(struct mtd_info *mtd)
++{
++	struct nand_chip *nand = mtd->priv;
++	struct bcmnand_ctrl *ctrl = nand->priv;
++	struct device *dev = &ctrl->core->dev;
++	bool sector_1k = false;
++	unsigned int chip_num = 0;
++	int ecc_level = 0;
++	int ret;
++
++	ret = nand_scan_ident(mtd, NANDC_MAX_CHIPS, NULL);
++	if (ret)
++		return ret;
++
++	/* Get configuration from first chip */
++	sector_1k = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_SECTOR_1K(0));
++	ecc_level = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(0));
++	mtd->writesize_shift = nand->page_shift;
++
++	ctrl->ecc_level = ecc_level;
++	ctrl->sector_size_shift = sector_1k ? 10 : 9;
++
++	/* Configure spare area, tweak as needed */
++	do {
++		ctrl->sec_per_page_shift =
++			mtd->writesize_shift - ctrl->sector_size_shift;
++
++		/* will return -EINVAL if OOB space exhausted */
++		ret = bcmnand_hw_ecc_layout(ctrl);
++
++		/* First try to bump sector size to 1k, then decrease level */
++		if (ret && nand->page_shift > 9 && ctrl->sector_size_shift < 10)
++			ctrl->sector_size_shift = 10;
++		else if (ret)
++			ctrl->ecc_level--;
++
++	} while (ret && ctrl->ecc_level > 0);
++
++	if (WARN_ON(ctrl->ecc_level == 0))
++		return -ENOENT;
++
++	if ((ctrl->sector_size_shift > 9) != (sector_1k == 1)) {
++		dev_info(dev, "sector size adjusted to 1k\n");
++		sector_1k = 1;
++	}
++
++	if (ecc_level != ctrl->ecc_level) {
++		dev_info(dev, "ECC level adjusted from %u to %u\n",
++			 ecc_level, ctrl->ecc_level);
++		ecc_level = ctrl->ecc_level;
++	}
++
++	/* handle the hardware chip config registers */
++	for (chip_num = 0; chip_num < nand->numchips; chip_num++) {
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_SECTOR_1K(chip_num),
++				  sector_1k);
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip_num),
++				  ecc_level);
++
++		/* Large pages: no partial page programming */
++		if (mtd->writesize > 512) {
++			bcmnand_reg_write(ctrl,
++				NANDC_ACC_CTRL_PGM_RDIN(chip_num), 0);
++			bcmnand_reg_write(ctrl,
++				NANDC_ACC_CTRL_PGM_PARTIAL(chip_num), 0);
++		}
++
++		/* Do not raise ECC error when reading erased pages */
++		/* This bit has only partial effect, driver needs to help */
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ERA_ECC_ERR(chip_num),
++				  0);
++
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PG_HIT(chip_num), 0);
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PREFETCH(chip_num), 0);
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_MODE(chip_num), 0);
++		bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_LASTPG(chip_num),
++				  0);
++
++		/* TBD: consolidate or at least verify the s/w and h/w geometries agree */
++	}
++
++	/* Allow writing on device */
++	if (!(nand->options & NAND_ROM))
++		bcmnand_reg_write(ctrl, NANDC_CS_NAND_WP, 0);
++
++	dev_dbg(dev, "layout.oobavail=%d\n", nand->ecc.layout->oobavail);
++
++	ret = nand_scan_tail(mtd);
++
++	if (nand->badblockbits == 0)
++		nand->badblockbits = 8;
++	if (WARN_ON((1 << nand->page_shift) != mtd->writesize))
++		return -EIO;
++
++	/* Spit out some key chip parameters as detected by nand_base */
++	dev_dbg(dev, "erasesize=%d writesize=%d oobsize=%d page_shift=%d badblockpos=%d badblockbits=%d\n",
++		mtd->erasesize, mtd->writesize, mtd->oobsize,
++		nand->page_shift, nand->badblockpos, nand->badblockbits);
++
++	return ret;
++}
++
++/*
++ * main intiailization function
++ */
++static int bcmnand_ctrl_init(struct bcmnand_ctrl *ctrl)
++{
++	unsigned int chip;
++	struct nand_chip *nand;
++	struct mtd_info *mtd;
++	struct device *dev = &ctrl->core->dev;
++	int ret;
++
++	/* Software variables init */
++	nand = &ctrl->nand;
++	mtd = &ctrl->mtd;
++
++	init_completion(&ctrl->op_completion);
++
++	mtd->priv = nand;
++	mtd->owner = THIS_MODULE;
++	mtd->name = KBUILD_MODNAME;
++
++	nand->priv = ctrl;
++
++	nand->chip_delay = 5;	/* not used */
++	nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)~0L;
++
++	if (bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_WIDTH(0)))
++		nand->options |= NAND_BUSWIDTH_16;
++	nand->options |= NAND_SKIP_BBTSCAN;	/* Dont need BBTs */
++
++	nand->options |= NAND_NO_SUBPAGE_WRITE; /* Subpages unsupported */
++
++	nand->dev_ready			= bcmnand_dev_ready;
++	nand->read_byte			= bcmnand_read_byte;
++	nand->read_word			= bcmnand_read_word;
++	nand->select_chip		= bcmnand_select_chip;
++	nand->cmdfunc			= bcmnand_cmdfunc;
++	nand->waitfunc			= bcmnand_waitfunc;
++
++	nand->ecc.mode			= NAND_ECC_HW;
++	nand->ecc.read_page_raw		= bcmnand_read_page_raw;
++	nand->ecc.write_page_raw	= bcmnand_write_page_raw;
++	nand->ecc.read_page		= bcmnand_read_page_ecc;
++	nand->ecc.write_page		= bcmnand_write_page_ecc;
++	nand->ecc.read_oob		= bcmnand_read_oob;
++	nand->ecc.write_oob		= bcmnand_write_oob;
++
++	/* Set AUTO_CNFIG bit - try to auto-detect chips */
++	bcmnand_reg_write(ctrl, NANDC_CS_AUTO_CONFIG, 1);
++
++	usleep_range(1000, 1500);
++
++	/* Print out current chip config */
++	for (chip = 0; chip < NANDC_MAX_CHIPS; chip++) {
++		dev_dbg(dev, "chip[%d]: size=%#x block=%#x page=%#x ecc_level=%#x\n",
++			chip,
++			bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_SIZE(chip)),
++			bcmnand_reg_read(ctrl, NANDC_CONFIG_BLK_SIZE(chip)),
++			bcmnand_reg_read(ctrl, NANDC_CONFIG_PAGE_SIZE(chip)),
++			bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip)));
++	}
++
++	dev_dbg(dev, "Nand controller is reads=%d\n",
++		bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY));
++
++	ret = bcmnand_scan(mtd);
++	if (ret) {
++		dev_err(dev, "scanning the nand flash chip failed with %i\n",
++			ret);
++		return ret;
++	}
++
++	return 0;
++}
++
++static int bcmnand_idm_init(struct bcmnand_ctrl *ctrl)
++{
++	int irq_off;
++	unsigned int retries = 0x1000;
++	struct device *dev = &ctrl->core->dev;
++
++	if (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET))
++		dev_info(dev, "stuck in reset\n");
++
++	bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 1);
++	if (!bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) {
++		dev_err(dev, "reset of failed\n");
++		return -EIO;
++	}
++
++	while (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) {
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 0);
++		cpu_relax();
++		usleep_range(100, 150);
++		if (!(retries--)) {
++			dev_err(dev, "did not came back from reset\n");
++			return -ETIMEDOUT;
++		}
++	}
++
++	bcmnand_reg_awrite(ctrl, NANDC_IDM_CLOCK_EN, 1);
++	bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0);
++	udelay(10);
++
++	dev_info(dev, "NAND Controller rev %d.%02d\n",
++		bcmnand_reg_read(ctrl, NANDC_REV_MAJOR),
++		bcmnand_reg_read(ctrl, NANDC_REV_MINOR));
++
++	usleep_range(250, 350);
++
++	/* Disable all IRQs */
++	for (irq_off = 0; irq_off < NANDC_IRQ_NUM; irq_off++)
++		bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0);
++
++	return 0;
++}
++
++static const char * const part_probes[] = { "ofpart", "bcm47xxpart", NULL };
++
++/*
++ * Top-level init function
++ */
++static int bcmnand_probe(struct bcma_device *core)
++{
++	struct mtd_part_parser_data parser_data;
++	struct device *dev = &core->dev;
++	struct bcmnand_ctrl *ctrl;
++	int res, i, irq;
++
++	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
++	if (!ctrl)
++		return -ENOMEM;
++
++	bcma_set_drvdata(core, ctrl);
++
++	ctrl->mtd.dev.parent = &core->dev;
++	ctrl->core = core;
++
++	/* Acquire all interrupt lines */
++	for (i = 0; i < NANDC_IRQ_NUM; i++) {
++		irq = bcma_core_irq(core, i);
++		if (!irq) {
++			dev_err(dev, "IRQ idx %i not available\n", i);
++			return -ENOENT;
++		}
++		res = devm_request_irq(dev, irq, bcmnand_isr, 0,
++				       KBUILD_MODNAME, ctrl);
++		if (res < 0) {
++			dev_err(dev, "problem requesting irq: %i (idx: %i)\n",
++				irq, i);
++			return res;
++		}
++	}
++
++	res = bcmnand_idm_init(ctrl);
++	if (res)
++		return res;
++
++	res = bcmnand_ctrl_init(ctrl);
++	if (res)
++		return res;
++
++	parser_data.of_node = dev->of_node;
++	res = mtd_device_parse_register(&ctrl->mtd, part_probes, &parser_data, NULL, 0);
++	if (res) {
++		dev_err(dev, "Failed to register MTD device: %d\n", res);
++		return res;
++	}
++	return 0;
++}
++
++static void bcmnand_remove(struct bcma_device *core)
++{
++	struct bcmnand_ctrl *ctrl = bcma_get_drvdata(core);
++
++	mtd_device_unregister(&ctrl->mtd);
++}
++
++static const struct bcma_device_id bcmnand_bcma_tbl[] = {
++	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_NAND, BCMA_ANY_REV, BCMA_ANY_CLASS),
++	{},
++};
++MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl);
++
++static struct bcma_driver bcmnand_bcma_driver = {
++	.name		= KBUILD_MODNAME,
++	.id_table	= bcmnand_bcma_tbl,
++	.probe		= bcmnand_probe,
++	.remove		= bcmnand_remove,
++};
++
++static int __init bcmnand_init(void)
++{
++	return bcma_driver_register(&bcmnand_bcma_driver);
++}
++
++static void __exit bcmnand_exit(void)
++{
++	bcma_driver_unregister(&bcmnand_bcma_driver);
++}
++
++module_init(bcmnand_init)
++module_exit(bcmnand_exit)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Hauke Mehrtens");
++MODULE_DESCRIPTION("Northstar on-chip NAND Flash Controller driver");
diff --git a/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
new file mode 100644
index 0000000000..a3d0f75b48
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch
@@ -0,0 +1,59 @@
+From 2a2af518266a29323cf30c3f9ba9ef2ceb1dd84b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 16 Oct 2014 20:52:16 +0200
+Subject: [PATCH] UBI: Detect EOF mark and erase all remaining blocks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/mtd/ubi/attach.c | 5 +++++
+ drivers/mtd/ubi/io.c     | 4 ++++
+ drivers/mtd/ubi/ubi.h    | 1 +
+ 3 files changed, 10 insertions(+)
+
+--- a/drivers/mtd/ubi/attach.c
++++ b/drivers/mtd/ubi/attach.c
+@@ -95,6 +95,9 @@ static int self_check_ai(struct ubi_devi
+ static struct ubi_ec_hdr *ech;
+ static struct ubi_vid_hdr *vidh;
+ 
++/* Set on finding block with 0xdeadc0de, indicates erasing all blocks behind */
++bool erase_all_next;
++
+ /**
+  * add_to_list - add physical eraseblock to a list.
+  * @ai: attaching information
+@@ -1427,6 +1430,8 @@ int ubi_attach(struct ubi_device *ubi, i
+ 	if (!ai)
+ 		return -ENOMEM;
+ 
++	erase_all_next = false;
++
+ #ifdef CONFIG_MTD_UBI_FASTMAP
+ 	/* On small flash devices we disable fastmap in any case. */
+ 	if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) {
+--- a/drivers/mtd/ubi/io.c
++++ b/drivers/mtd/ubi/io.c
+@@ -755,6 +755,10 @@ int ubi_io_read_ec_hdr(struct ubi_device
+ 	}
+ 
+ 	magic = be32_to_cpu(ec_hdr->magic);
++	if (magic == 0xdeadc0de)
++		erase_all_next = true;
++	if (erase_all_next)
++		return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF;
+ 	if (magic != UBI_EC_HDR_MAGIC) {
+ 		if (mtd_is_eccerr(read_err))
+ 			return UBI_IO_BAD_HDR_EBADMSG;
+--- a/drivers/mtd/ubi/ubi.h
++++ b/drivers/mtd/ubi/ubi.h
+@@ -781,6 +781,7 @@ extern struct mutex ubi_devices_mutex;
+ extern struct blocking_notifier_head ubi_notifiers;
+ 
+ /* attach.c */
++extern bool erase_all_next;
+ int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
+ 		  int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips);
+ struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
diff --git a/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch b/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch
new file mode 100644
index 0000000000..6be75bb806
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch
@@ -0,0 +1,63 @@
+From f5d5afc0b1402aae0f6a2350e43241603dbaff1e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 13 May 2015 10:46:47 +0200
+Subject: [PATCH] bgmac: add support for the 3rd bus core (device)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So far we were supporting up to 2 cores but recent devices (e.g. Netgear
+R8000) may use 3rd as well. Lower ones (1st, 2nd) are usually used for
+some offloading then.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/net/ethernet/broadcom/bgmac.c | 28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bgmac.c
++++ b/drivers/net/ethernet/broadcom/bgmac.c
+@@ -1561,11 +1561,20 @@ static int bgmac_probe(struct bcma_devic
+ 	struct net_device *net_dev;
+ 	struct bgmac *bgmac;
+ 	struct ssb_sprom *sprom = &core->bus->sprom;
+-	u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac;
++	u8 *mac;
+ 	int err;
+ 
+-	/* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */
+-	if (core->core_unit > 1) {
++	switch (core->core_unit) {
++	case 0:
++		mac = sprom->et0mac;
++		break;
++	case 1:
++		mac = sprom->et1mac;
++		break;
++	case 2:
++		mac = sprom->et2mac;
++		break;
++	default:
+ 		pr_err("Unsupported core_unit %d\n", core->core_unit);
+ 		return -ENOTSUPP;
+ 	}
+@@ -1600,8 +1609,17 @@ static int bgmac_probe(struct bcma_devic
+ 	}
+ 	bgmac->cmn = core->bus->drv_gmac_cmn.core;
+ 
+-	bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr :
+-			 sprom->et0phyaddr;
++	switch (core->core_unit) {
++	case 0:
++		bgmac->phyaddr = sprom->et0phyaddr;
++		break;
++	case 1:
++		bgmac->phyaddr = sprom->et1phyaddr;
++		break;
++	case 2:
++		bgmac->phyaddr = sprom->et2phyaddr;
++		break;
++	}
+ 	bgmac->phyaddr &= BGMAC_PHY_MASK;
+ 	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
+ 		bgmac_err(bgmac, "No PHY found\n");
diff --git a/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch b/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch
new file mode 100644
index 0000000000..6015c4aaca
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch
@@ -0,0 +1,35 @@
+From 4abdde3ad6bc0b3b157c4bf6ec0bf139d11d07e8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Wed, 13 May 2015 14:13:28 +0200
+Subject: [PATCH] b53: add hacky CPU port fixes for devices not using port 5
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/net/phy/b53/b53_common.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/phy/b53/b53_common.c
++++ b/drivers/net/phy/b53/b53_common.c
+@@ -25,6 +25,7 @@
+ #include <linux/module.h>
+ #include <linux/switch.h>
+ #include <linux/platform_data/b53.h>
++#include <linux/of.h>
+ 
+ #include "b53_regs.h"
+ #include "b53_priv.h"
+@@ -1313,6 +1314,11 @@ static int b53_switch_init(struct b53_de
+ 			sw_dev->cpu_port = 5;
+ 	}
+ 
++	if (of_machine_is_compatible("asus,rt-ac87u"))
++		sw_dev->cpu_port = 7;
++	else if (of_machine_is_compatible("netgear,r8000"))
++		sw_dev->cpu_port = 8;
++
+ 	/* cpu port is always last */
+ 	sw_dev->ports = sw_dev->cpu_port + 1;
+ 	dev->enabled_ports |= BIT(sw_dev->cpu_port);
diff --git a/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch b/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch
new file mode 100644
index 0000000000..9f2cd396ae
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch
@@ -0,0 +1,65 @@
+From 666bdfc027cde41a171862dc698987a378c8b66a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Mon, 9 Feb 2015 18:00:42 +0100
+Subject: [PATCH RFC] bcma: use two different initcalls if built-in
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is needed as we can't initialize bus during fs_initcall.
+Initialization requires SPROM which depends on NVRAM which depends on
+mtd. Since mtd, spi, nand, spi-nor use standard module_init, we have to
+do the same in bcma.
+Without this we'll try to initialize SPROM without having a ready SPROM
+proviver registered using bcma_arch_register_fallback_sprom.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+While this patch seems to work and I can compile bcma as built-in and
+module, I'm not too proud of it. I don't really like these #if(n)def
+tricks and I'm afraid bcma_modinit may be called even if
+bcma_modinit_early failed.
+
+Do you see any better idea of solving this?
+---
+ drivers/bcma/main.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -637,13 +637,25 @@ static int bcma_device_uevent(struct dev
+ 			      core->id.rev, core->id.class);
+ }
+ 
++/* Bus has to be registered early, before any bcma driver */
++static int __init bcma_modinit_early(void)
++{
++	return bus_register(&bcma_bus_type);
++}
++#ifndef MODULE
++fs_initcall(bcma_modinit_early);
++#endif
++
++/* Initialization has to be done later with SPI/mtd/NAND/SPROM available */
+ static int __init bcma_modinit(void)
+ {
+ 	int err;
+ 
+-	err = bus_register(&bcma_bus_type);
++#ifdef MODULE
++	err = bcma_modinit_early();
+ 	if (err)
+ 		return err;
++#endif
+ 
+ 	err = bcma_host_soc_register_driver();
+ 	if (err) {
+@@ -660,7 +672,7 @@ static int __init bcma_modinit(void)
+ 
+ 	return err;
+ }
+-fs_initcall(bcma_modinit);
++module_init(bcma_modinit);
+ 
+ static void __exit bcma_modexit(void)
+ {
diff --git a/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch b/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch
new file mode 100644
index 0000000000..d331ae6573
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch
@@ -0,0 +1,73 @@
+From 5b4fed9fc917cc2bfc5297eeab03aeba5d340618 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 16 Jun 2015 12:33:46 +0200
+Subject: [PATCH] USB: bcma: make helper creating platform dev more generic
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Having "bool ohci" argument bounded us to two cases only and didn't
+allow re-using this code for XHCI.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/bcma-hcd.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -249,7 +249,10 @@ static const struct usb_ehci_pdata ehci_
+ static const struct usb_ohci_pdata ohci_pdata = {
+ };
+ 
+-static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr)
++static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev,
++						    const char *name, u32 addr,
++						    const void *data,
++						    size_t size)
+ {
+ 	struct platform_device *hci_dev;
+ 	struct resource hci_res[2];
+@@ -264,8 +267,7 @@ static struct platform_device *bcma_hcd_
+ 	hci_res[1].start = dev->irq;
+ 	hci_res[1].flags = IORESOURCE_IRQ;
+ 
+-	hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
+-					"ehci-platform" , 0);
++	hci_dev = platform_device_alloc(name, 0);
+ 	if (!hci_dev)
+ 		return ERR_PTR(-ENOMEM);
+ 
+@@ -276,12 +278,8 @@ static struct platform_device *bcma_hcd_
+ 					    ARRAY_SIZE(hci_res));
+ 	if (ret)
+ 		goto err_alloc;
+-	if (ohci)
+-		ret = platform_device_add_data(hci_dev, &ohci_pdata,
+-					       sizeof(ohci_pdata));
+-	else
+-		ret = platform_device_add_data(hci_dev, &ehci_pdata,
+-					       sizeof(ehci_pdata));
++	if (data)
++		ret = platform_device_add_data(hci_dev, data, size);
+ 	if (ret)
+ 		goto err_alloc;
+ 	ret = platform_device_add(hci_dev);
+@@ -334,11 +332,15 @@ static int bcma_hcd_probe(struct bcma_de
+ 	    && chipinfo->rev == 0)
+ 		ohci_addr = 0x18009000;
+ 
+-	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
++	usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform",
++						 ohci_addr, &ohci_pdata,
++						 sizeof(ohci_pdata));
+ 	if (IS_ERR(usb_dev->ohci_dev))
+ 		return PTR_ERR(usb_dev->ohci_dev);
+ 
+-	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
++	usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform",
++						 dev->addr, &ehci_pdata,
++						 sizeof(ehci_pdata));
+ 	if (IS_ERR(usb_dev->ehci_dev)) {
+ 		err = PTR_ERR(usb_dev->ehci_dev);
+ 		goto err_unregister_ohci_dev;
diff --git a/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch b/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch
new file mode 100644
index 0000000000..758b0ac1eb
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch
@@ -0,0 +1,102 @@
+From 4aed231f49954114d5ae23e97789e9aa540a0b70 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 16 Jun 2015 12:52:07 +0200
+Subject: [PATCH] USB: bcma: use separated function for USB 2.0 initialization
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This will allow adding USB 3.0 (XHCI) support cleanly.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/bcma-hcd.c | 51 +++++++++++++++++++++++++++++++--------------
+ 1 file changed, 35 insertions(+), 16 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -34,6 +34,7 @@ MODULE_DESCRIPTION("Common USB driver fo
+ MODULE_LICENSE("GPL");
+ 
+ struct bcma_hcd_device {
++	struct bcma_device *core;
+ 	struct platform_device *ehci_dev;
+ 	struct platform_device *ohci_dev;
+ };
+@@ -293,27 +294,16 @@ err_alloc:
+ 	return ERR_PTR(ret);
+ }
+ 
+-static int bcma_hcd_probe(struct bcma_device *dev)
++static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev)
+ {
+-	int err;
++	struct bcma_device *dev = usb_dev->core;
++	struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo;
+ 	u32 ohci_addr;
+-	struct bcma_hcd_device *usb_dev;
+-	struct bcma_chipinfo *chipinfo;
+-
+-	chipinfo = &dev->bus->chipinfo;
+-
+-	/* TODO: Probably need checks here; is the core connected? */
++	int err;
+ 
+ 	if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
+ 		return -EOPNOTSUPP;
+ 
+-	usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device),
+-			       GFP_KERNEL);
+-	if (!usb_dev)
+-		return -ENOMEM;
+-
+-	bcma_hci_platform_power_gpio(dev, true);
+-
+ 	switch (dev->id.id) {
+ 	case BCMA_CORE_NS_USB20:
+ 		bcma_hcd_init_chip_arm(dev);
+@@ -346,7 +336,6 @@ static int bcma_hcd_probe(struct bcma_de
+ 		goto err_unregister_ohci_dev;
+ 	}
+ 
+-	bcma_set_drvdata(dev, usb_dev);
+ 	return 0;
+ 
+ err_unregister_ohci_dev:
+@@ -354,6 +343,36 @@ err_unregister_ohci_dev:
+ 	return err;
+ }
+ 
++static int bcma_hcd_probe(struct bcma_device *dev)
++{
++	int err;
++	struct bcma_hcd_device *usb_dev;
++
++	/* TODO: Probably need checks here; is the core connected? */
++
++	usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device),
++			       GFP_KERNEL);
++	if (!usb_dev)
++		return -ENOMEM;
++	usb_dev->core = dev;
++
++	bcma_hci_platform_power_gpio(dev, true);
++
++	switch (dev->id.id) {
++	case BCMA_CORE_USB20_HOST:
++	case BCMA_CORE_NS_USB20:
++		err = bcma_hcd_usb20_init(usb_dev);
++		if (err)
++			return err;
++		break;
++	default:
++		return -ENODEV;
++	}
++
++	bcma_set_drvdata(dev, usb_dev);
++	return 0;
++}
++
+ static void bcma_hcd_remove(struct bcma_device *dev)
+ {
+ 	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
diff --git a/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch b/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch
new file mode 100644
index 0000000000..3875da4fe4
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch
@@ -0,0 +1,274 @@
+From 12c6932caa6b1fce44d0f0c68ec77d4c00ac0be7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Tue, 16 Jun 2015 17:14:26 +0200
+Subject: [PATCH] USB: bcma: add USB 3.0 support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/bcma-hcd.c | 219 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 219 insertions(+)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -37,6 +37,7 @@ struct bcma_hcd_device {
+ 	struct bcma_device *core;
+ 	struct platform_device *ehci_dev;
+ 	struct platform_device *ohci_dev;
++	struct platform_device *xhci_dev;
+ };
+ 
+ /* Wait for bitmask in a register to get set or cleared.
+@@ -343,6 +344,215 @@ err_unregister_ohci_dev:
+ 	return err;
+ }
+ 
++static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
++			  u32 value, int timeout)
++{
++	unsigned long deadline = jiffies + timeout;
++	u32 val;
++
++	do {
++		val = readl(addr);
++		if ((val & mask) == value)
++			return true;
++		cpu_relax();
++		udelay(10);
++	} while (!time_after_eq(jiffies, deadline));
++
++	pr_err("Timeout waiting for register %p\n", addr);
++
++	return false;
++}
++
++static void bcma_hcd_usb30_phy_init(struct bcma_hcd_device *bcma_hcd)
++{
++	struct bcma_device *core = bcma_hcd->core;
++	struct bcma_bus *bus = core->bus;
++	struct bcma_chipinfo *chipinfo = &bus->chipinfo;
++	struct bcma_drv_cc_b *ccb = &bus->drv_cc_b;
++	struct bcma_device *arm_core;
++	void __iomem *dmu = NULL;
++	u32 cru_straps_ctrl;
++
++	if (chipinfo->id != BCMA_CHIP_ID_BCM4707 &&
++	    chipinfo->id != BCMA_CHIP_ID_BCM53018)
++		return;
++
++	arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9);
++	if (!arm_core)
++		return;
++
++	dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000);
++	if (!dmu)
++		goto out;
++
++	/* Check strapping of PCIE/USB3 SEL */
++	cru_straps_ctrl = ioread32(dmu + 0x2a0);
++	if ((cru_straps_ctrl & 0x10) == 0)
++		goto out;
++
++	/* Perform USB3 system soft reset */
++	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
++
++	/* Enable MDIO. Setting MDCDIV as 26  */
++	iowrite32(0x0000009a, ccb->mii + 0x000);
++	udelay(2);
++
++	switch (chipinfo->id) {
++	case BCMA_CHIP_ID_BCM4707:
++		if (chipinfo->rev == 4) {
++			/* For NS-B0, USB3 PLL Block */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x587e8000, ccb->mii + 0x004);
++
++			/* Clear ana_pllSeqStart */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x58061000, ccb->mii + 0x004);
++
++			/* CMOS Divider ratio to 25 */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x582a6400, ccb->mii + 0x004);
++
++			/* Asserting PLL Reset */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x582ec000, ccb->mii + 0x004);
++
++			/* Deaaserting PLL Reset */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x582e8000, ccb->mii + 0x004);
++
++			/* Deasserting USB3 system reset */
++			bcma_awrite32(core, BCMA_RESET_CTL, 0);
++
++			/* Set ana_pllSeqStart */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x58069000, ccb->mii + 0x004);
++
++			/* RXPMD block */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x587e8020, ccb->mii + 0x004);
++
++			/* CDR int loop locking BW to 1 */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x58120049, ccb->mii + 0x004);
++
++			/* CDR int loop acquisition BW to 1 */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x580e0049, ccb->mii + 0x004);
++
++			/* CDR prop loop BW to 1 */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x580a005c, ccb->mii + 0x004);
++
++			/* Waiting MII Mgt interface idle */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		} else {
++			/* PLL30 block */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x587e8000, ccb->mii + 0x004);
++
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x582a6400, ccb->mii + 0x004);
++
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x587e80e0, ccb->mii + 0x004);
++
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x580a009c, ccb->mii + 0x004);
++
++			/* Enable SSC */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x587e8040, ccb->mii + 0x004);
++
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x580a21d3, ccb->mii + 0x004);
++
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++			iowrite32(0x58061003, ccb->mii + 0x004);
++
++			/* Waiting MII Mgt interface idle */
++			bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++
++			/* Deasserting USB3 system reset */
++			bcma_awrite32(core, BCMA_RESET_CTL, 0);
++		}
++		break;
++	case BCMA_CHIP_ID_BCM53018:
++		/* USB3 PLL Block */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x587e8000, ccb->mii + 0x004);
++
++		/* Assert Ana_Pllseq start */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x58061000, ccb->mii + 0x004);
++
++		/* Assert CML Divider ratio to 26 */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x582a6400, ccb->mii + 0x004);
++
++		/* Asserting PLL Reset */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x582ec000, ccb->mii + 0x004);
++
++		/* Deaaserting PLL Reset */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x582e8000, ccb->mii + 0x004);
++
++		/* Waiting MII Mgt interface idle */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++
++		/* Deasserting USB3 system reset */
++		bcma_awrite32(core, BCMA_RESET_CTL, 0);
++
++		/* PLL frequency monitor enable */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x58069000, ccb->mii + 0x004);
++
++		/* PIPE Block */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x587e8060, ccb->mii + 0x004);
++
++		/* CMPMAX & CMPMINTH setting */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x580af30d, ccb->mii + 0x004);
++
++		/* DEGLITCH MIN & MAX setting */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x580e6302, ccb->mii + 0x004);
++
++		/* TXPMD block */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x587e8040, ccb->mii + 0x004);
++
++		/* Enabling SSC */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++		iowrite32(0x58061003, ccb->mii + 0x004);
++
++		/* Waiting MII Mgt interface idle */
++		bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000);
++
++		break;
++	}
++out:
++	if (dmu)
++		iounmap(dmu);
++}
++
++static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd)
++{
++	struct bcma_device *core = bcma_hcd->core;
++
++	bcma_core_enable(core, 0);
++
++	bcma_hcd_usb30_phy_init(bcma_hcd);
++
++	bcma_hcd->xhci_dev = bcma_hcd_create_pdev(core, "xhci-hcd", core->addr,
++						  NULL, 0);
++	if (IS_ERR(bcma_hcd->ohci_dev))
++		return PTR_ERR(bcma_hcd->ohci_dev);
++
++	return 0;
++}
++
+ static int bcma_hcd_probe(struct bcma_device *dev)
+ {
+ 	int err;
+@@ -365,6 +575,11 @@ static int bcma_hcd_probe(struct bcma_de
+ 		if (err)
+ 			return err;
+ 		break;
++	case BCMA_CORE_NS_USB30:
++		err = bcma_hcd_usb30_init(usb_dev);
++		if (err)
++			return err;
++		break;
+ 	default:
+ 		return -ENODEV;
+ 	}
+@@ -378,11 +593,14 @@ static void bcma_hcd_remove(struct bcma_
+ 	struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev);
+ 	struct platform_device *ohci_dev = usb_dev->ohci_dev;
+ 	struct platform_device *ehci_dev = usb_dev->ehci_dev;
++	struct platform_device *xhci_dev = usb_dev->xhci_dev;
+ 
+ 	if (ohci_dev)
+ 		platform_device_unregister(ohci_dev);
+ 	if (ehci_dev)
+ 		platform_device_unregister(ehci_dev);
++	if (xhci_dev)
++		platform_device_unregister(xhci_dev);
+ 
+ 	bcma_core_disable(dev, 0);
+ }
+@@ -419,6 +637,7 @@ static int bcma_hcd_resume(struct bcma_d
+ static const struct bcma_device_id bcma_hcd_table[] = {
+ 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
++	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
diff --git a/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch b/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch
new file mode 100644
index 0000000000..9ba3bdeece
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch
@@ -0,0 +1,45 @@
+From bdc3b01d94b22f8b5f9621a1c37336e78f4f1bce Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 21 Jun 2015 12:09:57 +0200
+Subject: [PATCH] USB: bcma: fix setting VCC GPIO value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It wasn't working (on most of devices?) without setting GPIO direction
+and wasn't respecting ACTIVE_LOW flag.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/bcma-hcd.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/bcma-hcd.c
++++ b/drivers/usb/host/bcma-hcd.c
+@@ -230,17 +230,22 @@ static void bcma_hcd_init_chip_arm(struc
+ 
+ static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
+ {
++	enum of_gpio_flags of_flags;
+ 	int gpio;
+ 
+-	gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0);
++	gpio = of_get_named_gpio_flags(dev->dev.of_node, "vcc-gpio", 0, &of_flags);
+ 	if (!gpio_is_valid(gpio))
+ 		return;
+ 
+ 	if (val) {
+-		gpio_request(gpio, "bcma-hcd-gpio");
+-		gpio_set_value(gpio, 1);
++		unsigned long flags = 0;
++		bool active_low = !!(of_flags & OF_GPIO_ACTIVE_LOW);
++
++		flags |= active_low ? GPIOF_ACTIVE_LOW : 0;
++		flags |= active_low ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH;
++		gpio_request_one(gpio, flags, "bcma-hcd-gpio");
+ 	} else {
+-		gpio_set_value(gpio, 0);
++		gpiod_set_value(gpio_to_desc(gpio), 0);
+ 		gpio_free(gpio);
+ 	}
+ }
diff --git a/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch
new file mode 100644
index 0000000000..9a87a75dd4
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch
@@ -0,0 +1,94 @@
+From 9cc14ca0aae53c16d10ffea49848ac61a5015562 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 21 Jun 2015 11:10:49 +0200
+Subject: [PATCH] xhci: add Broadcom specific fake doorbell
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes problem with controller seeing devices only in some small
+percentage of cold boots.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/xhci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -121,6 +121,64 @@ int xhci_halt(struct xhci_hcd *xhci)
+ 	return ret;
+ }
+ 
++#ifdef CONFIG_ARCH_BCM_5301X
++int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
++{
++	unsigned int temp1, ret;
++
++	/* alloc a virt device for slot */
++	if (!xhci_alloc_virt_device(xhci, slot_id, 0, GFP_NOIO)) {
++		xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
++		return 1;
++        }
++
++	/* ring fake doorbell for slot_id ep 0 */
++	xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
++	mdelay(1);
++
++	/* read the status register to check if HSE is set or not? */
++	temp1 = readl(&xhci->op_regs->status);
++	xhci_dbg(xhci, "op reg status = %x\n",temp1);
++
++	/* clear HSE if set */
++	if(temp1 & STS_FATAL) {
++		xhci_dbg(xhci, "HSE problem detected\n");
++		temp1 &= ~(0x1fff);
++		temp1 |= STS_FATAL;
++		xhci_dbg(xhci, "temp1=%x\n",temp1);
++		writel(temp1, &xhci->op_regs->status);
++		mdelay(1);
++		temp1 = readl(&xhci->op_regs->status);
++		xhci_dbg(xhci, "After clear op reg status=%x\n", temp1);
++	}
++
++	/* Free virt device */
++	xhci_free_virt_device(xhci, slot_id);
++
++	/* Run the controller if needed */
++	temp1 = readl(&xhci->op_regs->command);
++	if (temp1 & CMD_RUN)
++		return 0;
++	temp1 |= (CMD_RUN);
++
++	writel(temp1, &xhci->op_regs->command);
++	/*
++	 * Wait for the HCHalted Status bit to be 0 to indicate the host is running.
++	 */
++	ret = xhci_handshake(xhci, &xhci->op_regs->status,
++			     STS_HALT, 0, XHCI_MAX_HALT_USEC);
++
++	if (ret == -ETIMEDOUT) {
++		xhci_err(xhci, "Host took too long to start, "
++				"waited %u microseconds.\n",
++				XHCI_MAX_HALT_USEC);
++		return 1;
++	}
++
++	return 0;
++}
++#endif /* CONFIG_ARCH_BCM_5301X */
++
+ /*
+  * Set the run bit and wait for the host to be running.
+  */
+@@ -145,6 +203,10 @@ static int xhci_start(struct xhci_hcd *x
+ 		xhci_err(xhci, "Host took too long to start, "
+ 				"waited %u microseconds.\n",
+ 				XHCI_MAX_HALT_USEC);
++#ifdef CONFIG_ARCH_BCM_5301X
++	xhci_fake_doorbell(xhci, 1);
++#endif /* CONFIG_ARCH_BCM_5301X */
++
+ 	if (!ret)
+ 		xhci->xhc_state &= ~XHCI_STATE_HALTED;
+ 	return ret;
diff --git a/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch b/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch
new file mode 100644
index 0000000000..c1dfa92013
--- /dev/null
+++ b/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch
@@ -0,0 +1,42 @@
+From 21500872c1dba33848ddcf6bea97d58772675d36 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 17 May 2015 14:00:52 +0200
+Subject: [PATCH] mtd: bcm47xxpart: workaround for Asus RT-AC87U "asus"
+ partition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/mtd/bcm47xxpart.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/mtd/bcm47xxpart.c
++++ b/drivers/mtd/bcm47xxpart.c
+@@ -14,6 +14,7 @@
+ #include <linux/slab.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
++#include <linux/of.h>
+ 
+ #include <uapi/linux/magic.h>
+ 
+@@ -135,6 +136,17 @@ static int bcm47xxpart_parse(struct mtd_
+ 			break;
+ 		}
+ 
++		/*
++		 * Ugly workaround for Asus RT-AC87U and its "asus" partition.
++		 * It uses JFFS2 which we don't (want to) detect. We should
++		 * probably use DT to define partitions but we need a working
++		 * TRX firmware splitter first.
++		 */
++		if (of_machine_is_compatible("asus,rt-ac87u") && offset == 0x7ec0000) {
++			bcm47xxpart_add_part(&parts[curr_part++], "asus", offset, MTD_WRITEABLE);
++			continue;
++		}
++
+ 		/* Read beginning of the block */
+ 		if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
+ 			     &bytes_read, (uint8_t *)buf) < 0) {
-- 
GitLab