diff --git a/target/linux/ipq806x/config-4.0 b/target/linux/ipq806x/config-4.0
deleted file mode 100644
index 7ec3963..0000000
--- a/target/linux/ipq806x/config-4.0
+++ /dev/null
@@ -1,424 +0,0 @@
-CONFIG_ALIGNMENT_TRAP=y
-# CONFIG_AMBA_PL08X is not set
-# CONFIG_APM_EMULATION is not set
-CONFIG_APQ_GCC_8084=y
-CONFIG_APQ_MMCC_8084=y
-CONFIG_AR8216_PHY=y
-CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
-CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=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_MSM8960=y
-CONFIG_ARCH_MSM8974=y
-CONFIG_ARCH_MSM8X60=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_QCOM=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_BIG_ENDIAN=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_ARCH_TIMER=y
-CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
-# CONFIG_ARM_ATAG_DTB_COMPAT is not set
-CONFIG_ARM_CPU_SUSPEND=y
-CONFIG_ARM_GIC=y
-CONFIG_ARM_HAS_SG_CHAIN=y
-# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
-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_QCOM_CPUFREQ=y
-# CONFIG_ARM_SMMU is not set
-# CONFIG_ARM_SP805_WATCHDOG is not set
-CONFIG_ARM_THUMB=y
-# CONFIG_ARM_THUMBEE is not set
-CONFIG_ARM_UNWIND=y
-CONFIG_ARM_VIRT_EXT=y
-CONFIG_AT803X_PHY=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_BOUNCE=y
-CONFIG_BUILD_BIN2C=y
-# CONFIG_CACHE_L2X0 is not set
-CONFIG_CLEANCACHE=y
-CONFIG_CLKDEV_LOOKUP=y
-CONFIG_CLKSRC_OF=y
-CONFIG_CLKSRC_QCOM=y
-CONFIG_CLONE_BACKWARDS=y
-CONFIG_COMMON_CLK=y
-CONFIG_COMMON_CLK_QCOM=y
-CONFIG_COMPACTION=y
-CONFIG_COREDUMP=y
-# CONFIG_CPUFREQ_DT is not set
-CONFIG_CPU_32v6K=y
-CONFIG_CPU_32v7=y
-CONFIG_CPU_ABRT_EV7=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-# 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_FREQ=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_STAT=y
-# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_HAS_ASID=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_LADDER=y
-CONFIG_CPU_IDLE_GOV_MENU=y
-CONFIG_CPU_PABRT_V7=y
-CONFIG_CPU_PM=y
-CONFIG_CPU_RMAP=y
-# CONFIG_CPU_THERMAL is not set
-CONFIG_CPU_TLB_V7=y
-CONFIG_CPU_V7=y
-CONFIG_CRC16=y
-# CONFIG_CRC32_SARWATE is not set
-CONFIG_CRC32_SLICEBY8=y
-CONFIG_CROSS_MEMORY_ATTACH=y
-# CONFIG_CRYPTO_SHA1_ARM_NEON is not set
-# CONFIG_CRYPTO_SHA512_ARM_NEON is not set
-CONFIG_CRYPTO_XZ=y
-CONFIG_DCACHE_WORD_ACCESS=y
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
-CONFIG_DEBUG_PREEMPT=y
-# CONFIG_DEBUG_UART_8250 is not set
-# CONFIG_DEBUG_USER is not set
-CONFIG_DECOMPRESS_GZIP=y
-CONFIG_DEVMEM=y
-CONFIG_DMADEVICES=y
-CONFIG_DMA_ENGINE=y
-CONFIG_DMA_OF=y
-CONFIG_DMA_VIRTUAL_CHANNELS=y
-CONFIG_DTC=y
-# CONFIG_DW_DMAC_CORE is not set
-# CONFIG_DW_DMAC_PCI is not set
-CONFIG_DYNAMIC_DEBUG=y
-CONFIG_ETHERNET_PACKET_MANGLE=y
-CONFIG_FIXED_PHY=y
-CONFIG_FREEZER=y
-CONFIG_GENERIC_ALLOCATOR=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_GENERIC_CPUFREQ_KRAIT=y
-CONFIG_GENERIC_IDLE_POLL_SETUP=y
-CONFIG_GENERIC_IO=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_MSI_IRQ=y
-CONFIG_GENERIC_PCI_IOMAP=y
-CONFIG_GENERIC_PHY=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_GPIOLIB_IRQCHIP=y
-CONFIG_GPIO_DEVRES=y
-# CONFIG_GPIO_MSM_V2 is not set
-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_ARCH_TIMER=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_HW_BREAKPOINT=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_MOD_ARCH_SPECIFIC=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=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_HWMON=y
-CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_MSM=y
-CONFIG_HZ_FIXED=0
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_COMPAT=y
-CONFIG_I2C_HELPER_AUTO=y
-CONFIG_I2C_QUP=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_IOMMU_HELPER=y
-# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
-CONFIG_IOMMU_SUPPORT=y
-CONFIG_IPQ_GCC_806X=y
-# CONFIG_IPQ_LCC_806X is not set
-CONFIG_IRQCHIP=y
-CONFIG_IRQ_DOMAIN=y
-CONFIG_IRQ_DOMAIN_HIERARCHY=y
-CONFIG_IRQ_FORCED_THREADING=y
-CONFIG_IRQ_WORK=y
-CONFIG_KPSS_XCC=y
-CONFIG_KRAITCC=y
-CONFIG_KRAIT_CLOCKS=y
-CONFIG_KRAIT_L2_ACCESSORS=y
-# CONFIG_LEDS_REGULATOR is not set
-CONFIG_LIBFDT=y
-CONFIG_LOCKUP_DETECTOR=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_BITBANG=y
-CONFIG_MDIO_BOARDINFO=y
-CONFIG_MDIO_GPIO=y
-CONFIG_MFD_QCOM_RPM=y
-# CONFIG_MFD_SPMI_PMIC is not set
-CONFIG_MFD_SYSCON=y
-CONFIG_MIGHT_HAVE_CACHE_L2X0=y
-CONFIG_MIGHT_HAVE_PCI=y
-CONFIG_MIGRATION=y
-CONFIG_MODULES_USE_ELF_REL=y
-CONFIG_MSM_GCC_8660=y
-CONFIG_MSM_GCC_8960=y
-CONFIG_MSM_GCC_8974=y
-# CONFIG_MSM_LCC_8960 is not set
-CONFIG_MSM_MMCC_8960=y
-CONFIG_MSM_MMCC_8974=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_M25P80=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_MTD_SPLIT_FIRMWARE=y
-CONFIG_MTD_SPLIT_FIT_FW=y
-CONFIG_MULTI_IRQ_HANDLER=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEON=y
-CONFIG_NET_FLOW_LIMIT=y
-CONFIG_NET_VENDOR_WIZNET=y
-CONFIG_NO_BOOTMEM=y
-CONFIG_NO_HZ=y
-CONFIG_NO_HZ_COMMON=y
-CONFIG_NO_HZ_IDLE=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_PAGEFLAGS_EXTENDED=y
-CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_PCI=y
-CONFIG_PCIEAER=y
-CONFIG_PCIEPORTBUS=y
-CONFIG_PCIE_DW=y
-CONFIG_PCIE_PME=y
-CONFIG_PCIE_QCOM=y
-CONFIG_PCI_DEBUG=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_DOMAINS_GENERIC=y
-CONFIG_PCI_MSI=y
-CONFIG_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-CONFIG_PHYLIB=y
-# CONFIG_PHY_QCOM_APQ8064_SATA is not set
-CONFIG_PHY_QCOM_IPQ806X_SATA=y
-CONFIG_PINCTRL=y
-CONFIG_PINCTRL_APQ8064=y
-# CONFIG_PINCTRL_APQ8084 is not set
-CONFIG_PINCTRL_IPQ8064=y
-CONFIG_PINCTRL_MSM=y
-# CONFIG_PINCTRL_MSM8916 is not set
-# CONFIG_PINCTRL_MSM8960 is not set
-CONFIG_PINCTRL_MSM8X74=y
-# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set
-# CONFIG_PL330_DMA is not set
-CONFIG_PM=y
-CONFIG_PM_CLK=y
-# CONFIG_PM_DEBUG is not set
-CONFIG_PM_OPP=y
-CONFIG_PM_SLEEP=y
-CONFIG_PM_SLEEP_SMP=y
-CONFIG_POWER_RESET=y
-# CONFIG_POWER_RESET_BRCMSTB is not set
-# CONFIG_POWER_RESET_GPIO is not set
-# CONFIG_POWER_RESET_GPIO_RESTART is not set
-# CONFIG_POWER_RESET_LTC2952 is not set
-CONFIG_POWER_RESET_MSM=y
-# CONFIG_POWER_RESET_SYSCON is not set
-CONFIG_POWER_SUPPLY=y
-CONFIG_PREEMPT=y
-CONFIG_PREEMPT_COUNT=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_RCU=y
-CONFIG_PRINTK_TIME=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_QCOM_BAM_DMA=y
-CONFIG_QCOM_GSBI=y
-CONFIG_QCOM_HFPLL=y
-CONFIG_QCOM_SCM=y
-CONFIG_QCOM_WDT=y
-CONFIG_RAS=y
-# CONFIG_RCU_BOOST is not set
-CONFIG_RCU_CPU_STALL_TIMEOUT=21
-CONFIG_RCU_STALL_COMMON=y
-CONFIG_RD_GZIP=y
-CONFIG_REGMAP=y
-CONFIG_REGMAP_MMIO=y
-CONFIG_REGULATOR=y
-# CONFIG_REGULATOR_DEBUG is not set
-CONFIG_REGULATOR_QCOM_RPM=y
-# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
-CONFIG_RESET_CONTROLLER=y
-CONFIG_RFS_ACCEL=y
-CONFIG_RPS=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_DRV_CMOS is not set
-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_MSM=y
-CONFIG_SERIAL_MSM_CONSOLE=y
-# CONFIG_SLAB is not set
-CONFIG_SLUB=y
-CONFIG_SLUB_CPU_PARTIAL=y
-CONFIG_SMP=y
-CONFIG_SMP_ON_UP=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_SPI=y
-CONFIG_SPI_MASTER=y
-CONFIG_SPI_QUP=y
-CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB=y
-CONFIG_SRCU=y
-CONFIG_STOP_MACHINE=y
-# CONFIG_STRIP_ASM_SYMS is not set
-CONFIG_SUSPEND=y
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_SWCONFIG=y
-CONFIG_SWIOTLB=y
-CONFIG_SWP_EMULATE=y
-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-CONFIG_THERMAL=y
-# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
-CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
-# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
-# CONFIG_THERMAL_EMULATION is not set
-# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
-CONFIG_THERMAL_GOV_STEP_WISE=y
-# CONFIG_THERMAL_GOV_USER_SPACE is not set
-CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_OF=y
-# CONFIG_THUMB2_KERNEL is not set
-CONFIG_TICK_CPU_ACCOUNTING=y
-CONFIG_TIMER_STATS=y
-CONFIG_UEVENT_HELPER_PATH=""
-CONFIG_UID16=y
-CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
-CONFIG_UNINLINE_SPIN_UNLOCK=y
-CONFIG_USB_SUPPORT=y
-CONFIG_USE_OF=y
-CONFIG_VECTORS_BASE=0xffff0000
-CONFIG_VFP=y
-CONFIG_VFPv3=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_WATCHDOG_CORE=y
-# CONFIG_WIZNET_W5100 is not set
-# CONFIG_WIZNET_W5300 is not set
-# CONFIG_WL_TI is not set
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
-# CONFIG_XEN is not set
-CONFIG_XPS=y
-CONFIG_XZ_DEC_ARM=y
-CONFIG_XZ_DEC_BCJ=y
-CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/ipq806x/config-4.1 b/target/linux/ipq806x/config-4.1
new file mode 100644
index 0000000..e80b632
--- /dev/null
+++ b/target/linux/ipq806x/config-4.1
@@ -0,0 +1,437 @@
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_AMBA_PL08X is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_APQ_GCC_8084=y
+CONFIG_APQ_MMCC_8084=y
+CONFIG_AR8216_PHY=y
+# CONFIG_ARCH_ALPINE 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_MSM8960=y
+CONFIG_ARCH_MSM8974=y
+CONFIG_ARCH_MSM8X60=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_QCOM=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_BIG_ENDIAN=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_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ATAG_DTB_COMPAT is not set
+CONFIG_ARM_CCI=y
+CONFIG_ARM_CCI400_COMMON=y
+CONFIG_ARM_CCI400_PMU=y
+# CONFIG_ARM_CPUIDLE is not set
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
+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_QCOM_CPUFREQ=y
+# CONFIG_ARM_SMMU is not set
+# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_ARM_VIRT_EXT=y
+CONFIG_AT803X_PHY=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_BOUNCE=y
+CONFIG_BUILD_BIN2C=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_CLEANCACHE=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_QCOM=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_QCOM=y
+CONFIG_COMPACTION=y
+CONFIG_COREDUMP=y
+# CONFIG_CPUFREQ_DT is not set
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+# 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_FREQ=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_HAS_ASID=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+# CONFIG_CPU_THERMAL is not set
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+CONFIG_CRC16=y
+# CONFIG_CRC32_SARWATE is not set
+CONFIG_CRC32_SLICEBY8=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_CRYPTO_XZ=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_UART_8250 is not set
+# CONFIG_DEBUG_USER is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DEVMEM=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+CONFIG_DTC=y
+# CONFIG_DW_DMAC_PCI is not set
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_ETHERNET_PACKET_MANGLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_FREEZER=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPUFREQ_KRAIT=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IO=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=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_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_DEVRES=y
+# CONFIG_GPIO_MSM_V2 is not set
+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_ARCH_TIMER=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_HW_BREAKPOINT=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_MOD_ARCH_SPECIFIC=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=y
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_HSU_DMA_PCI is not set
+CONFIG_HWMON=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_HZ_FIXED=0
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_QUP=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_IPQ_GCC_806X=y
+# CONFIG_IPQ_LCC_806X is not set
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_KPSS_XCC=y
+CONFIG_KRAITCC=y
+CONFIG_KRAIT_CLOCKS=y
+CONFIG_KRAIT_L2_ACCESSORS=y
+# CONFIG_LEDS_REGULATOR is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCKUP_DETECTOR=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_BITBANG=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_MDIO_GPIO=y
+CONFIG_MFD_QCOM_RPM=y
+# CONFIG_MFD_SPMI_PMIC is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_MIGRATION=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MSM_GCC_8660=y
+# CONFIG_MSM_GCC_8916 is not set
+CONFIG_MSM_GCC_8960=y
+CONFIG_MSM_GCC_8974=y
+# CONFIG_MSM_LCC_8960 is not set
+CONFIG_MSM_MMCC_8960=y
+CONFIG_MSM_MMCC_8974=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_FIRMWARE=y
+CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEON=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_VENDOR_WIZNET=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NO_HZ=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=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_PAGEFLAGS_EXTENDED=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PCI=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIE_DW=y
+# CONFIG_PCIE_IPROC is not set
+CONFIG_PCIE_PME=y
+CONFIG_PCIE_QCOM=y
+CONFIG_PCI_DEBUG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_MSI=y
+CONFIG_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+# CONFIG_PHY_QCOM_APQ8064_SATA is not set
+CONFIG_PHY_QCOM_IPQ806X_SATA=y
+# CONFIG_PHY_QCOM_UFS is not set
+CONFIG_PINCTRL=y
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_APQ8064=y
+# CONFIG_PINCTRL_APQ8084 is not set
+CONFIG_PINCTRL_IPQ8064=y
+CONFIG_PINCTRL_MSM=y
+# CONFIG_PINCTRL_MSM8916 is not set
+# CONFIG_PINCTRL_MSM8960 is not set
+CONFIG_PINCTRL_MSM8X74=y
+# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set
+# CONFIG_PL330_DMA is not set
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_OPP=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMSTB is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+CONFIG_POWER_RESET_MSM=y
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+CONFIG_POWER_SUPPLY=y
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_QCOM_BAM_DMA=y
+CONFIG_QCOM_GSBI=y
+CONFIG_QCOM_HFPLL=y
+CONFIG_QCOM_SCM=y
+CONFIG_QCOM_WDT=y
+# CONFIG_QORIQ_CPUFREQ is not set
+CONFIG_RAS=y
+# CONFIG_RCU_BOOST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+CONFIG_RCU_STALL_COMMON=y
+CONFIG_RD_GZIP=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_QCOM_RPM=y
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_CMOS is not set
+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_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_CPU_PARTIAL=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_QUP=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_SRCU=y
+CONFIG_STOP_MACHINE=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_SWCONFIG=y
+CONFIG_SWIOTLB=y
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_OF=y
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_STATS=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_UID16=y
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USE_OF=y
+CONFIG_VDSO=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_WL_TI is not set
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+# CONFIG_XEN is not set
+CONFIG_XPS=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_BCJ=y
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/target/linux/ipq806x/patches-4.0/001-spi-qup-Add-DMA-capabilities.patch b/target/linux/ipq806x/patches-4.0/001-spi-qup-Add-DMA-capabilities.patch
deleted file mode 100644
index a500c67..0000000
--- a/target/linux/ipq806x/patches-4.0/001-spi-qup-Add-DMA-capabilities.patch
+++ /dev/null
@@ -1,522 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: spi: qup: Add DMA capabilities
-From: Andy Gross <agross@codeaurora.org>
-X-Patchwork-Id: 4432401
-Message-Id: <1403816781-31008-1-git-send-email-agross@codeaurora.org>
-To: Mark Brown <broonie@kernel.org>
-Cc: linux-spi@vger.kernel.org, Sagar Dharia <sdharia@codeaurora.org>,
-	Daniel Sneddon <dsneddon@codeaurora.org>,
-	Bjorn Andersson <bjorn.andersson@sonymobile.com>,
-	"Ivan T. Ivanov" <iivanov@mm-sol.com>,
-	linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	linux-arm-msm@vger.kernel.org, Andy Gross <agross@codeaurora.org>
-Date: Thu, 26 Jun 2014 16:06:21 -0500
-
-This patch adds DMA capabilities to the spi-qup driver.  If DMA channels are
-present, the QUP will use DMA instead of block mode for transfers to/from SPI
-peripherals for transactions larger than the length of a block.
-
-Signed-off-by: Andy Gross <agross@codeaurora.org>
-
----
-.../devicetree/bindings/spi/qcom,spi-qup.txt       |   10 +
- drivers/spi/spi-qup.c                              |  361 ++++++++++++++++++--
- 2 files changed, 350 insertions(+), 21 deletions(-)
-
---- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
-+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
-@@ -27,6 +27,11 @@ Optional properties:
- - spi-max-frequency: Specifies maximum SPI clock frequency,
-                      Units - Hz. Definition as per
-                      Documentation/devicetree/bindings/spi/spi-bus.txt
-+- dmas :             Two DMA channel specifiers following the convention outlined
-+                     in bindings/dma/dma.txt
-+- dma-names:         Names for the dma channels, if present. There must be at
-+                     least one channel named "tx" for transmit and named "rx" for
-+                     receive.
- - num-cs:	total number of chipselects
- - cs-gpios:	should specify GPIOs used for chipselects.
- 		The gpios will be referred to as reg = <index> in the SPI child
-@@ -51,6 +56,10 @@ Example:
- 		clocks = <&gcc GCC_BLSP2_QUP2_SPI_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
- 		clock-names = "core", "iface";
- 
-+		dmas = <&blsp2_bam 2>,
-+			<&blsp2_bam 3>;
-+		dma-names = "rx", "tx";
-+
- 		pinctrl-names = "default";
- 		pinctrl-0 = <&spi8_default>;
- 
---- a/drivers/spi/spi-qup.c
-+++ b/drivers/spi/spi-qup.c
-@@ -22,6 +22,8 @@
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
- #include <linux/spi/spi.h>
-+#include <linux/dmaengine.h>
-+#include <linux/dma-mapping.h>
- 
- #define QUP_CONFIG			0x0000
- #define QUP_STATE			0x0004
-@@ -116,6 +118,8 @@
- 
- #define SPI_NUM_CHIPSELECTS		4
- 
-+#define SPI_MAX_XFER			(SZ_64K - 64)
-+
- /* high speed mode is when bus rate is greater then 26MHz */
- #define SPI_HS_MIN_RATE			26000000
- #define SPI_MAX_RATE			50000000
-@@ -143,6 +147,17 @@ struct spi_qup {
- 	int			tx_bytes;
- 	int			rx_bytes;
- 	int			qup_v1;
-+
-+	int			use_dma;
-+
-+	struct dma_chan		*rx_chan;
-+	struct dma_slave_config	rx_conf;
-+	struct dma_chan		*tx_chan;
-+	struct dma_slave_config tx_conf;
-+	dma_addr_t		rx_dma;
-+	dma_addr_t		tx_dma;
-+	void			*dummy;
-+	atomic_t		dma_outstanding;
- };
- 
- 
-@@ -266,6 +281,221 @@ static void spi_qup_fifo_write(struct sp
- 	}
- }
- 
-+static void qup_dma_callback(void *data)
-+{
-+	struct spi_qup *controller = data;
-+
-+	if (atomic_dec_and_test(&controller->dma_outstanding))
-+		complete(&controller->done);
-+}
-+
-+static int spi_qup_do_dma(struct spi_qup *controller, struct spi_transfer *xfer)
-+{
-+	struct dma_async_tx_descriptor *rxd, *txd;
-+	dma_cookie_t rx_cookie, tx_cookie;
-+	u32 xfer_len, rx_align = 0, tx_align = 0, n_words;
-+	struct scatterlist tx_sg[2], rx_sg[2];
-+	int ret = 0;
-+	u32 bytes_to_xfer = xfer->len;
-+	u32 offset = 0;
-+	u32 rx_nents = 0, tx_nents = 0;
-+	dma_addr_t rx_dma = 0, tx_dma = 0, rx_dummy_dma = 0, tx_dummy_dma = 0;
-+
-+
-+	if (xfer->rx_buf) {
-+		rx_dma = dma_map_single(controller->dev, xfer->rx_buf,
-+			xfer->len, DMA_FROM_DEVICE);
-+
-+		if (dma_mapping_error(controller->dev, rx_dma)) {
-+			ret = -ENOMEM;
-+			return ret;
-+		}
-+
-+		/* check to see if we need dummy buffer for leftover bytes */
-+		rx_align = xfer->len % controller->in_blk_sz;
-+		if (rx_align) {
-+			rx_dummy_dma = dma_map_single(controller->dev,
-+				controller->dummy, controller->in_fifo_sz,
-+				DMA_FROM_DEVICE);
-+
-+			if (dma_mapping_error(controller->dev, rx_dummy_dma)) {
-+				ret = -ENOMEM;
-+				goto err_map_rx_dummy;
-+			}
-+		}
-+	}
-+
-+	if (xfer->tx_buf) {
-+		tx_dma = dma_map_single(controller->dev,
-+			(void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
-+
-+		if (dma_mapping_error(controller->dev, tx_dma)) {
-+			ret = -ENOMEM;
-+			goto err_map_tx;
-+		}
-+
-+		/* check to see if we need dummy buffer for leftover bytes */
-+		tx_align = xfer->len % controller->out_blk_sz;
-+		if (tx_align) {
-+			memcpy(controller->dummy + SZ_1K,
-+				xfer->tx_buf + xfer->len - tx_align,
-+				tx_align);
-+			memset(controller->dummy + SZ_1K + tx_align, 0,
-+				controller->out_blk_sz - tx_align);
-+
-+			tx_dummy_dma = dma_map_single(controller->dev,
-+				controller->dummy + SZ_1K,
-+				controller->out_blk_sz, DMA_TO_DEVICE);
-+
-+			if (dma_mapping_error(controller->dev, tx_dummy_dma)) {
-+				ret = -ENOMEM;
-+				goto err_map_tx_dummy;
-+			}
-+		}
-+	}
-+
-+	atomic_set(&controller->dma_outstanding, 0);
-+
-+	while (bytes_to_xfer > 0) {
-+		xfer_len = min_t(u32, bytes_to_xfer, SPI_MAX_XFER);
-+		n_words = DIV_ROUND_UP(xfer_len, controller->w_size);
-+
-+		/* write out current word count to controller */
-+		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
-+		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
-+
-+		reinit_completion(&controller->done);
-+
-+		if (xfer->tx_buf) {
-+			/* recalc align for each transaction */
-+			tx_align = xfer_len % controller->out_blk_sz;
-+
-+			if (tx_align)
-+				tx_nents = 2;
-+			else
-+				tx_nents = 1;
-+
-+			/* initialize scatterlists */
-+			sg_init_table(tx_sg, tx_nents);
-+			sg_dma_len(&tx_sg[0]) = xfer_len - tx_align;
-+			sg_dma_address(&tx_sg[0]) = tx_dma + offset;
-+
-+			/* account for non block size transfer */
-+			if (tx_align) {
-+				sg_dma_len(&tx_sg[1]) = controller->out_blk_sz;
-+				sg_dma_address(&tx_sg[1]) = tx_dummy_dma;
-+			}
-+
-+			txd = dmaengine_prep_slave_sg(controller->tx_chan,
-+					tx_sg, tx_nents, DMA_MEM_TO_DEV, 0);
-+			if (!txd) {
-+				ret = -ENOMEM;
-+				goto err_unmap;
-+			}
-+
-+			atomic_inc(&controller->dma_outstanding);
-+
-+			txd->callback = qup_dma_callback;
-+			txd->callback_param = controller;
-+
-+			tx_cookie = dmaengine_submit(txd);
-+
-+			dma_async_issue_pending(controller->tx_chan);
-+		}
-+
-+		if (xfer->rx_buf) {
-+			/* recalc align for each transaction */
-+			rx_align = xfer_len % controller->in_blk_sz;
-+
-+			if (rx_align)
-+				rx_nents = 2;
-+			else
-+				rx_nents = 1;
-+
-+			/* initialize scatterlists */
-+			sg_init_table(rx_sg, rx_nents);
-+			sg_dma_address(&rx_sg[0]) = rx_dma + offset;
-+			sg_dma_len(&rx_sg[0]) = xfer_len - rx_align;
-+
-+			/* account for non block size transfer */
-+			if (rx_align) {
-+				sg_dma_len(&rx_sg[1]) = controller->in_blk_sz;
-+				sg_dma_address(&rx_sg[1]) = rx_dummy_dma;
-+			}
-+
-+			rxd = dmaengine_prep_slave_sg(controller->rx_chan,
-+					rx_sg, rx_nents, DMA_DEV_TO_MEM, 0);
-+			if (!rxd) {
-+				ret = -ENOMEM;
-+				goto err_unmap;
-+			}
-+
-+			atomic_inc(&controller->dma_outstanding);
-+
-+			rxd->callback = qup_dma_callback;
-+			rxd->callback_param = controller;
-+
-+			rx_cookie = dmaengine_submit(rxd);
-+
-+			dma_async_issue_pending(controller->rx_chan);
-+		}
-+
-+		if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
-+			dev_warn(controller->dev, "cannot set EXECUTE state\n");
-+			goto err_unmap;
-+		}
-+
-+		if (!wait_for_completion_timeout(&controller->done,
-+			msecs_to_jiffies(1000))) {
-+			ret = -ETIMEDOUT;
-+
-+			/* clear out all the DMA transactions */
-+			if (xfer->tx_buf)
-+				dmaengine_terminate_all(controller->tx_chan);
-+			if (xfer->rx_buf)
-+				dmaengine_terminate_all(controller->rx_chan);
-+
-+			goto err_unmap;
-+		}
-+
-+		if (rx_align)
-+			memcpy(xfer->rx_buf + offset + xfer->len - rx_align,
-+				controller->dummy, rx_align);
-+
-+		/* adjust remaining bytes to transfer */
-+		bytes_to_xfer -= xfer_len;
-+		offset += xfer_len;
-+
-+
-+		/* reset mini-core state so we can program next transaction */
-+		if (spi_qup_set_state(controller, QUP_STATE_RESET)) {
-+			dev_err(controller->dev, "cannot set RESET state\n");
-+			goto err_unmap;
-+		}
-+	}
-+
-+	ret = 0;
-+
-+err_unmap:
-+	if (tx_align)
-+		dma_unmap_single(controller->dev, tx_dummy_dma,
-+			controller->out_fifo_sz, DMA_TO_DEVICE);
-+err_map_tx_dummy:
-+	if (xfer->tx_buf)
-+		dma_unmap_single(controller->dev, tx_dma, xfer->len,
-+			DMA_TO_DEVICE);
-+err_map_tx:
-+	if (rx_align)
-+		dma_unmap_single(controller->dev, rx_dummy_dma,
-+			controller->in_fifo_sz, DMA_FROM_DEVICE);
-+err_map_rx_dummy:
-+	if (xfer->rx_buf)
-+		dma_unmap_single(controller->dev, rx_dma, xfer->len,
-+			DMA_FROM_DEVICE);
-+
-+	return ret;
-+}
-+
- static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)
- {
- 	struct spi_qup *controller = dev_id;
-@@ -315,11 +545,13 @@ static irqreturn_t spi_qup_qup_irq(int i
- 		error = -EIO;
- 	}
- 
--	if (opflags & QUP_OP_IN_SERVICE_FLAG)
--		spi_qup_fifo_read(controller, xfer);
-+	if (!controller->use_dma) {
-+		if (opflags & QUP_OP_IN_SERVICE_FLAG)
-+			spi_qup_fifo_read(controller, xfer);
- 
--	if (opflags & QUP_OP_OUT_SERVICE_FLAG)
--		spi_qup_fifo_write(controller, xfer);
-+		if (opflags & QUP_OP_OUT_SERVICE_FLAG)
-+			spi_qup_fifo_write(controller, xfer);
-+	}
- 
- 	spin_lock_irqsave(&controller->lock, flags);
- 	controller->error = error;
-@@ -339,6 +571,8 @@ static int spi_qup_io_config(struct spi_
- 	struct spi_qup *controller = spi_master_get_devdata(spi->master);
- 	u32 config, iomode, mode, control;
- 	int ret, n_words, w_size;
-+	size_t dma_align = dma_get_cache_alignment();
-+	u32 dma_available = 0;
- 
- 	if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) {
- 		dev_err(controller->dev, "too big size for loopback %d > %d\n",
-@@ -367,6 +601,11 @@ static int spi_qup_io_config(struct spi_
- 	n_words = xfer->len / w_size;
- 	controller->w_size = w_size;
- 
-+	if (controller->rx_chan &&
-+		IS_ALIGNED((size_t)xfer->tx_buf, dma_align) &&
-+		IS_ALIGNED((size_t)xfer->rx_buf, dma_align))
-+		dma_available = 1;
-+
- 	if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
- 		mode = QUP_IO_M_MODE_FIFO;
- 		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
-@@ -374,19 +613,31 @@ static int spi_qup_io_config(struct spi_
- 		/* must be zero for FIFO */
- 		writel_relaxed(0, controller->base + QUP_MX_INPUT_CNT);
- 		writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
--	} else {
-+		controller->use_dma = 0;
-+	} else if (!dma_available) {
- 		mode = QUP_IO_M_MODE_BLOCK;
- 		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
- 		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
- 		/* must be zero for BLOCK and BAM */
- 		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
- 		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
-+		controller->use_dma = 0;
-+	} else {
-+		mode = QUP_IO_M_MODE_DMOV;
-+		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
-+		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
-+		controller->use_dma = 1;
- 	}
- 
- 	iomode = readl_relaxed(controller->base + QUP_IO_M_MODES);
- 	/* Set input and output transfer mode */
- 	iomode &= ~(QUP_IO_M_INPUT_MODE_MASK | QUP_IO_M_OUTPUT_MODE_MASK);
--	iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
-+
-+	if (!controller->use_dma)
-+		iomode &= ~(QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN);
-+	else
-+		iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN;
-+
- 	iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
- 	iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
- 
-@@ -428,6 +679,14 @@ static int spi_qup_io_config(struct spi_
- 	config &= ~(QUP_CONFIG_NO_INPUT | QUP_CONFIG_NO_OUTPUT | QUP_CONFIG_N);
- 	config |= xfer->bits_per_word - 1;
- 	config |= QUP_CONFIG_SPI_MODE;
-+
-+	if (controller->use_dma) {
-+		if (!xfer->tx_buf)
-+			config |= QUP_CONFIG_NO_OUTPUT;
-+		if (!xfer->rx_buf)
-+			config |= QUP_CONFIG_NO_INPUT;
-+	}
-+
- 	writel_relaxed(config, controller->base + QUP_CONFIG);
- 
- 	/* only write to OPERATIONAL_MASK when register is present */
-@@ -461,25 +720,29 @@ static int spi_qup_transfer_one(struct s
- 	controller->tx_bytes = 0;
- 	spin_unlock_irqrestore(&controller->lock, flags);
- 
--	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
--		dev_warn(controller->dev, "cannot set RUN state\n");
--		goto exit;
--	}
-+	if (controller->use_dma) {
-+		ret = spi_qup_do_dma(controller, xfer);
-+	} else {
-+		if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
-+			dev_warn(controller->dev, "cannot set RUN state\n");
-+			goto exit;
-+		}
- 
--	if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
--		dev_warn(controller->dev, "cannot set PAUSE state\n");
--		goto exit;
--	}
-+		if (spi_qup_set_state(controller, QUP_STATE_PAUSE)) {
-+			dev_warn(controller->dev, "cannot set PAUSE state\n");
-+			goto exit;
-+		}
- 
--	spi_qup_fifo_write(controller, xfer);
-+		spi_qup_fifo_write(controller, xfer);
- 
--	if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
--		dev_warn(controller->dev, "cannot set EXECUTE state\n");
--		goto exit;
--	}
-+		if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
-+			dev_warn(controller->dev, "cannot set EXECUTE state\n");
-+			goto exit;
-+		}
- 
--	if (!wait_for_completion_timeout(&controller->done, timeout))
--		ret = -ETIMEDOUT;
-+		if (!wait_for_completion_timeout(&controller->done, timeout))
-+			ret = -ETIMEDOUT;
-+	}
- exit:
- 	spi_qup_set_state(controller, QUP_STATE_RESET);
- 	spin_lock_irqsave(&controller->lock, flags);
-@@ -563,6 +826,7 @@ static int spi_qup_probe(struct platform
- 	master->transfer_one = spi_qup_transfer_one;
- 	master->dev.of_node = pdev->dev.of_node;
- 	master->auto_runtime_pm = true;
-+	master->dma_alignment = dma_get_cache_alignment();
- 
- 	platform_set_drvdata(pdev, master);
- 
-@@ -628,6 +892,56 @@ static int spi_qup_probe(struct platform
- 			QUP_ERROR_INPUT_UNDER_RUN | QUP_ERROR_OUTPUT_UNDER_RUN,
- 			base + QUP_ERROR_FLAGS_EN);
- 
-+	/* allocate dma resources, if available */
-+	controller->rx_chan = dma_request_slave_channel(&pdev->dev, "rx");
-+	if (controller->rx_chan) {
-+		controller->tx_chan =
-+			dma_request_slave_channel(&pdev->dev, "tx");
-+
-+		if (!controller->tx_chan) {
-+			dev_err(&pdev->dev, "Failed to allocate dma tx chan");
-+			dma_release_channel(controller->rx_chan);
-+		}
-+
-+		/* set DMA parameters */
-+		controller->rx_conf.device_fc = 1;
-+		controller->rx_conf.src_addr = res->start + QUP_INPUT_FIFO;
-+		controller->rx_conf.src_maxburst = controller->in_blk_sz;
-+
-+		controller->tx_conf.device_fc = 1;
-+		controller->tx_conf.dst_addr = res->start + QUP_OUTPUT_FIFO;
-+		controller->tx_conf.dst_maxburst = controller->out_blk_sz;
-+
-+		if (dmaengine_slave_config(controller->rx_chan,
-+				&controller->rx_conf)) {
-+			dev_err(&pdev->dev, "failed to configure RX channel\n");
-+
-+			dma_release_channel(controller->rx_chan);
-+			dma_release_channel(controller->tx_chan);
-+			controller->tx_chan = NULL;
-+			controller->rx_chan = NULL;
-+		} else if (dmaengine_slave_config(controller->tx_chan,
-+				&controller->tx_conf)) {
-+			dev_err(&pdev->dev, "failed to configure TX channel\n");
-+
-+			dma_release_channel(controller->rx_chan);
-+			dma_release_channel(controller->tx_chan);
-+			controller->tx_chan = NULL;
-+			controller->rx_chan = NULL;
-+		}
-+
-+		controller->dummy = devm_kmalloc(controller->dev, PAGE_SIZE,
-+			GFP_KERNEL);
-+
-+		if (!controller->dummy) {
-+			dma_release_channel(controller->rx_chan);
-+			dma_release_channel(controller->tx_chan);
-+			controller->tx_chan = NULL;
-+			controller->rx_chan = NULL;
-+		}
-+	}
-+
-+
- 	writel_relaxed(0, base + SPI_CONFIG);
- 	writel_relaxed(SPI_IO_C_NO_TRI_STATE, base + SPI_IO_CONTROL);
- 
-@@ -740,6 +1054,11 @@ static int spi_qup_remove(struct platfor
- 	if (ret)
- 		return ret;
- 
-+	if (controller->rx_chan)
-+		dma_release_channel(controller->rx_chan);
-+	if (controller->tx_chan)
-+		dma_release_channel(controller->tx_chan);
-+
- 	clk_disable_unprepare(controller->cclk);
- 	clk_disable_unprepare(controller->iclk);
- 
diff --git a/target/linux/ipq806x/patches-4.0/002-v3-spi-qup-Fix-incorrect-block-transfers.patch b/target/linux/ipq806x/patches-4.0/002-v3-spi-qup-Fix-incorrect-block-transfers.patch
deleted file mode 100644
index c8c6e4f..0000000
--- a/target/linux/ipq806x/patches-4.0/002-v3-spi-qup-Fix-incorrect-block-transfers.patch
+++ /dev/null
@@ -1,376 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3] spi: qup: Fix incorrect block transfers
-From: Andy Gross <agross@codeaurora.org>
-X-Patchwork-Id: 5007321
-Message-Id: <1412112088-25928-1-git-send-email-agross@codeaurora.org>
-To: Mark Brown <broonie@kernel.org>
-Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org,
-	linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org,
-	"Ivan T. Ivanov" <iivanov@mm-sol.com>,
-	Bjorn Andersson <bjorn.andersson@sonymobile.com>,
-	Kumar Gala <galak@codeaurora.org>, Andy Gross <agross@codeaurora.org>
-Date: Tue, 30 Sep 2014 16:21:28 -0500
-
-This patch fixes a number of errors with the QUP block transfer mode.  Errors
-manifested themselves as input underruns, output overruns, and timed out
-transactions.
-
-The block mode does not require the priming that occurs in FIFO mode.  At the
-moment that the QUP is placed into the RUN state, the QUP will immediately raise
-an interrupt if the request is a write.  Therefore, there is no need to prime
-the pump.
-
-In addition, the block transfers require that whole blocks of data are
-read/written at a time.  The last block of data that completes a transaction may
-contain less than a full blocks worth of data.
-
-Each block of data results in an input/output service interrupt accompanied with
-a input/output block flag set.  Additional block reads/writes require clearing
-of the service flag.  It is ok to check for additional blocks of data in the
-ISR, but you have to ack every block you transfer.  Imbalanced acks result in
-early return from complete transactions with pending interrupts that still have
-to be ack'd.  The next transaction can be affected by these interrupts.
-Transactions are deemed complete when the MAX_INPUT or MAX_OUTPUT flag are set.
-
-Changes from v2:
-- Added in additional completion check so that transaction done is not
-  prematurely signaled.
-- Fixed various review comments.
-
-Changes from v1:
-- Split out read/write block function.
-- Removed extraneous checks for transfer length
-
-Signed-off-by: Andy Gross <agross@codeaurora.org>
-
----
-drivers/spi/spi-qup.c |  201 ++++++++++++++++++++++++++++++++++++-------------
- 1 file changed, 148 insertions(+), 53 deletions(-)
-
---- a/drivers/spi/spi-qup.c
-+++ b/drivers/spi/spi-qup.c
-@@ -82,6 +82,8 @@
- #define QUP_IO_M_MODE_BAM		3
- 
- /* QUP_OPERATIONAL fields */
-+#define QUP_OP_IN_BLOCK_READ_REQ	BIT(13)
-+#define QUP_OP_OUT_BLOCK_WRITE_REQ	BIT(12)
- #define QUP_OP_MAX_INPUT_DONE_FLAG	BIT(11)
- #define QUP_OP_MAX_OUTPUT_DONE_FLAG	BIT(10)
- #define QUP_OP_IN_SERVICE_FLAG		BIT(9)
-@@ -147,6 +149,7 @@ struct spi_qup {
- 	int			tx_bytes;
- 	int			rx_bytes;
- 	int			qup_v1;
-+	int			mode;
- 
- 	int			use_dma;
- 
-@@ -213,30 +216,14 @@ static int spi_qup_set_state(struct spi_
- 	return 0;
- }
- 
--
--static void spi_qup_fifo_read(struct spi_qup *controller,
--			    struct spi_transfer *xfer)
-+static void spi_qup_fill_read_buffer(struct spi_qup *controller,
-+	struct spi_transfer *xfer, u32 data)
- {
- 	u8 *rx_buf = xfer->rx_buf;
--	u32 word, state;
--	int idx, shift, w_size;
--
--	w_size = controller->w_size;
--
--	while (controller->rx_bytes < xfer->len) {
--
--		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
--		if (0 == (state & QUP_OP_IN_FIFO_NOT_EMPTY))
--			break;
--
--		word = readl_relaxed(controller->base + QUP_INPUT_FIFO);
--
--		if (!rx_buf) {
--			controller->rx_bytes += w_size;
--			continue;
--		}
-+	int idx, shift;
- 
--		for (idx = 0; idx < w_size; idx++, controller->rx_bytes++) {
-+	if (rx_buf)
-+		for (idx = 0; idx < controller->w_size; idx++) {
- 			/*
- 			 * The data format depends on bytes per SPI word:
- 			 *  4 bytes: 0x12345678
-@@ -244,41 +231,139 @@ static void spi_qup_fifo_read(struct spi
- 			 *  1 byte : 0x00000012
- 			 */
- 			shift = BITS_PER_BYTE;
--			shift *= (w_size - idx - 1);
--			rx_buf[controller->rx_bytes] = word >> shift;
-+			shift *= (controller->w_size - idx - 1);
-+			rx_buf[controller->rx_bytes + idx] = data >> shift;
-+		}
-+
-+	controller->rx_bytes += controller->w_size;
-+}
-+
-+static void spi_qup_prepare_write_data(struct spi_qup *controller,
-+	struct spi_transfer *xfer, u32 *data)
-+{
-+	const u8 *tx_buf = xfer->tx_buf;
-+	u32 val;
-+	int idx;
-+
-+	*data = 0;
-+
-+	if (tx_buf)
-+		for (idx = 0; idx < controller->w_size; idx++) {
-+			val = tx_buf[controller->tx_bytes + idx];
-+			*data |= val << (BITS_PER_BYTE * (3 - idx));
- 		}
-+
-+	controller->tx_bytes += controller->w_size;
-+}
-+
-+static void spi_qup_fifo_read(struct spi_qup *controller,
-+			    struct spi_transfer *xfer)
-+{
-+	u32 data;
-+
-+	/* clear service request */
-+	writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
-+			controller->base + QUP_OPERATIONAL);
-+
-+	while (controller->rx_bytes < xfer->len) {
-+		if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) &
-+		    QUP_OP_IN_FIFO_NOT_EMPTY))
-+			break;
-+
-+		data = readl_relaxed(controller->base + QUP_INPUT_FIFO);
-+
-+		spi_qup_fill_read_buffer(controller, xfer, data);
- 	}
- }
- 
- static void spi_qup_fifo_write(struct spi_qup *controller,
--			    struct spi_transfer *xfer)
-+	struct spi_transfer *xfer)
- {
--	const u8 *tx_buf = xfer->tx_buf;
--	u32 word, state, data;
--	int idx, w_size;
-+	u32 data;
- 
--	w_size = controller->w_size;
-+	/* clear service request */
-+	writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
-+		controller->base + QUP_OPERATIONAL);
- 
- 	while (controller->tx_bytes < xfer->len) {
- 
--		state = readl_relaxed(controller->base + QUP_OPERATIONAL);
--		if (state & QUP_OP_OUT_FIFO_FULL)
-+		if (readl_relaxed(controller->base + QUP_OPERATIONAL) &
-+				QUP_OP_OUT_FIFO_FULL)
- 			break;
- 
--		word = 0;
--		for (idx = 0; idx < w_size; idx++, controller->tx_bytes++) {
-+		spi_qup_prepare_write_data(controller, xfer, &data);
-+		writel_relaxed(data, controller->base + QUP_OUTPUT_FIFO);
- 
--			if (!tx_buf) {
--				controller->tx_bytes += w_size;
--				break;
--			}
-+	}
-+}
- 
--			data = tx_buf[controller->tx_bytes];
--			word |= data << (BITS_PER_BYTE * (3 - idx));
--		}
-+static void spi_qup_block_read(struct spi_qup *controller,
-+	struct spi_transfer *xfer)
-+{
-+	u32 data;
-+	u32 reads_per_blk = controller->in_blk_sz >> 2;
-+	u32 num_words = (xfer->len - controller->rx_bytes) / controller->w_size;
-+	int i;
-+
-+	do {
-+		/* ACK by clearing service flag */
-+		writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
-+			controller->base + QUP_OPERATIONAL);
-+
-+		/* transfer up to a block size of data in a single pass */
-+		for (i = 0; num_words && i < reads_per_blk; i++, num_words--) {
-+
-+			/* read data and fill up rx buffer */
-+			data = readl_relaxed(controller->base + QUP_INPUT_FIFO);
-+			spi_qup_fill_read_buffer(controller, xfer, data);
-+		}
-+
-+		/* check to see if next block is ready */
-+		if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) &
-+			QUP_OP_IN_BLOCK_READ_REQ))
-+			break;
- 
--		writel_relaxed(word, controller->base + QUP_OUTPUT_FIFO);
--	}
-+	} while (num_words);
-+
-+	/*
-+	 * Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
-+	 * reads, it has to be cleared again at the very end
-+	 */
-+	if (readl_relaxed(controller->base + QUP_OPERATIONAL) &
-+		QUP_OP_MAX_INPUT_DONE_FLAG)
-+		writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
-+			controller->base + QUP_OPERATIONAL);
-+
-+}
-+
-+static void spi_qup_block_write(struct spi_qup *controller,
-+	struct spi_transfer *xfer)
-+{
-+	u32 data;
-+	u32 writes_per_blk = controller->out_blk_sz >> 2;
-+	u32 num_words = (xfer->len - controller->tx_bytes) / controller->w_size;
-+	int i;
-+
-+	do {
-+		/* ACK by clearing service flag */
-+		writel_relaxed(QUP_OP_OUT_SERVICE_FLAG,
-+			controller->base + QUP_OPERATIONAL);
-+
-+		/* transfer up to a block size of data in a single pass */
-+		for (i = 0; num_words && i < writes_per_blk; i++, num_words--) {
-+
-+			/* swizzle the bytes for output and write out */
-+			spi_qup_prepare_write_data(controller, xfer, &data);
-+			writel_relaxed(data,
-+				controller->base + QUP_OUTPUT_FIFO);
-+		}
-+
-+		/* check to see if next block is ready */
-+		if (!(readl_relaxed(controller->base + QUP_OPERATIONAL) &
-+			QUP_OP_OUT_BLOCK_WRITE_REQ))
-+			break;
-+
-+	} while (num_words);
- }
- 
- static void qup_dma_callback(void *data)
-@@ -515,9 +600,9 @@ static irqreturn_t spi_qup_qup_irq(int i
- 
- 	writel_relaxed(qup_err, controller->base + QUP_ERROR_FLAGS);
- 	writel_relaxed(spi_err, controller->base + SPI_ERROR_FLAGS);
--	writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
- 
- 	if (!xfer) {
-+		writel_relaxed(opflags, controller->base + QUP_OPERATIONAL);
- 		dev_err_ratelimited(controller->dev, "unexpected irq %08x %08x %08x\n",
- 				    qup_err, spi_err, opflags);
- 		return IRQ_HANDLED;
-@@ -546,11 +631,19 @@ static irqreturn_t spi_qup_qup_irq(int i
- 	}
- 
- 	if (!controller->use_dma) {
--		if (opflags & QUP_OP_IN_SERVICE_FLAG)
--			spi_qup_fifo_read(controller, xfer);
-+		if (opflags & QUP_OP_IN_SERVICE_FLAG) {
-+			if (opflags & QUP_OP_IN_BLOCK_READ_REQ)
-+				spi_qup_block_read(controller, xfer);
-+			else
-+				spi_qup_fifo_read(controller, xfer);
-+		}
- 
--		if (opflags & QUP_OP_OUT_SERVICE_FLAG)
--			spi_qup_fifo_write(controller, xfer);
-+		if (opflags & QUP_OP_OUT_SERVICE_FLAG) {
-+			if (opflags & QUP_OP_OUT_BLOCK_WRITE_REQ)
-+				spi_qup_block_write(controller, xfer);
-+			else
-+				spi_qup_fifo_write(controller, xfer);
-+		}
- 	}
- 
- 	spin_lock_irqsave(&controller->lock, flags);
-@@ -558,7 +651,8 @@ static irqreturn_t spi_qup_qup_irq(int i
- 	controller->xfer = xfer;
- 	spin_unlock_irqrestore(&controller->lock, flags);
- 
--	if (controller->rx_bytes == xfer->len || error)
-+	if ((controller->rx_bytes == xfer->len &&
-+		(opflags & QUP_OP_MAX_INPUT_DONE_FLAG)) || error)
- 		complete(&controller->done);
- 
- 	return IRQ_HANDLED;
-@@ -569,7 +663,7 @@ static irqreturn_t spi_qup_qup_irq(int i
- static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer)
- {
- 	struct spi_qup *controller = spi_master_get_devdata(spi->master);
--	u32 config, iomode, mode, control;
-+	u32 config, iomode, control;
- 	int ret, n_words, w_size;
- 	size_t dma_align = dma_get_cache_alignment();
- 	u32 dma_available = 0;
-@@ -607,7 +701,7 @@ static int spi_qup_io_config(struct spi_
- 		dma_available = 1;
- 
- 	if (n_words <= (controller->in_fifo_sz / sizeof(u32))) {
--		mode = QUP_IO_M_MODE_FIFO;
-+		controller->mode = QUP_IO_M_MODE_FIFO;
- 		writel_relaxed(n_words, controller->base + QUP_MX_READ_CNT);
- 		writel_relaxed(n_words, controller->base + QUP_MX_WRITE_CNT);
- 		/* must be zero for FIFO */
-@@ -615,7 +709,7 @@ static int spi_qup_io_config(struct spi_
- 		writel_relaxed(0, controller->base + QUP_MX_OUTPUT_CNT);
- 		controller->use_dma = 0;
- 	} else if (!dma_available) {
--		mode = QUP_IO_M_MODE_BLOCK;
-+		controller->mode = QUP_IO_M_MODE_BLOCK;
- 		writel_relaxed(n_words, controller->base + QUP_MX_INPUT_CNT);
- 		writel_relaxed(n_words, controller->base + QUP_MX_OUTPUT_CNT);
- 		/* must be zero for BLOCK and BAM */
-@@ -623,7 +717,7 @@ static int spi_qup_io_config(struct spi_
- 		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
- 		controller->use_dma = 0;
- 	} else {
--		mode = QUP_IO_M_MODE_DMOV;
-+		controller->mode = QUP_IO_M_MODE_DMOV;
- 		writel_relaxed(0, controller->base + QUP_MX_READ_CNT);
- 		writel_relaxed(0, controller->base + QUP_MX_WRITE_CNT);
- 		controller->use_dma = 1;
-@@ -638,8 +732,8 @@ static int spi_qup_io_config(struct spi_
- 	else
- 		iomode |= QUP_IO_M_PACK_EN | QUP_IO_M_UNPACK_EN;
- 
--	iomode |= (mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
--	iomode |= (mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
-+	iomode |= (controller->mode << QUP_IO_M_OUTPUT_MODE_MASK_SHIFT);
-+	iomode |= (controller->mode << QUP_IO_M_INPUT_MODE_MASK_SHIFT);
- 
- 	writel_relaxed(iomode, controller->base + QUP_IO_M_MODES);
- 
-@@ -733,7 +827,8 @@ static int spi_qup_transfer_one(struct s
- 			goto exit;
- 		}
- 
--		spi_qup_fifo_write(controller, xfer);
-+		if (controller->mode == QUP_IO_M_MODE_FIFO)
-+			spi_qup_fifo_write(controller, xfer);
- 
- 		if (spi_qup_set_state(controller, QUP_STATE_RUN)) {
- 			dev_warn(controller->dev, "cannot set EXECUTE state\n");
-@@ -750,6 +845,7 @@ exit:
- 	if (!ret)
- 		ret = controller->error;
- 	spin_unlock_irqrestore(&controller->lock, flags);
-+
- 	return ret;
- }
- 
diff --git a/target/linux/ipq806x/patches-4.0/003-spi-qup-Ensure-done-detection.patch b/target/linux/ipq806x/patches-4.0/003-spi-qup-Ensure-done-detection.patch
deleted file mode 100644
index 7052227..0000000
--- a/target/linux/ipq806x/patches-4.0/003-spi-qup-Ensure-done-detection.patch
+++ /dev/null
@@ -1,56 +0,0 @@
-From 4faba89e3ffbb1c5f6232651375b9b3212b50f02 Mon Sep 17 00:00:00 2001
-From: Andy Gross <agross@codeaurora.org>
-Date: Thu, 15 Jan 2015 17:56:02 -0800
-Subject: [PATCH] spi: qup: Ensure done detection
-
-This patch fixes an issue where a SPI transaction has completed, but the done
-condition is missed.  This occurs because at the time of interrupt the
-MAX_INPUT_DONE_FLAG is not asserted.  However, in the process of reading blocks
-of data from the FIFO, the last portion of data comes in.
-
-The opflags read at the beginning of the irq handler no longer matches the
-current opflag state.  To get around this condition, the block read function
-should update the opflags so that done detection is correct after the return.
-
-Change-Id: If109e0eeb432f96000d765c4b34dbb2269f8093f
-Signed-off-by: Andy Gross <agross@codeaurora.org>
----
- drivers/spi/spi-qup.c | 12 +++++++-----
- 1 file changed, 7 insertions(+), 5 deletions(-)
-
---- a/drivers/spi/spi-qup.c
-+++ b/drivers/spi/spi-qup.c
-@@ -298,7 +298,7 @@ static void spi_qup_fifo_write(struct sp
- }
- 
- static void spi_qup_block_read(struct spi_qup *controller,
--	struct spi_transfer *xfer)
-+	struct spi_transfer *xfer, u32 *opflags)
- {
- 	u32 data;
- 	u32 reads_per_blk = controller->in_blk_sz >> 2;
-@@ -327,10 +327,12 @@ static void spi_qup_block_read(struct sp
- 
- 	/*
- 	 * Due to extra stickiness of the QUP_OP_IN_SERVICE_FLAG during block
--	 * reads, it has to be cleared again at the very end
-+	 * reads, it has to be cleared again at the very end.  However, be sure
-+	 * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be
-+	 * present and this is used to determine if transaction is complete
- 	 */
--	if (readl_relaxed(controller->base + QUP_OPERATIONAL) &
--		QUP_OP_MAX_INPUT_DONE_FLAG)
-+	*opflags = readl_relaxed(controller->base + QUP_OPERATIONAL);
-+	if (*opflags & QUP_OP_MAX_INPUT_DONE_FLAG)
- 		writel_relaxed(QUP_OP_IN_SERVICE_FLAG,
- 			controller->base + QUP_OPERATIONAL);
- 
-@@ -633,7 +635,7 @@ static irqreturn_t spi_qup_qup_irq(int i
- 	if (!controller->use_dma) {
- 		if (opflags & QUP_OP_IN_SERVICE_FLAG) {
- 			if (opflags & QUP_OP_IN_BLOCK_READ_REQ)
--				spi_qup_block_read(controller, xfer);
-+				spi_qup_block_read(controller, xfer, &opflags);
- 			else
- 				spi_qup_fifo_read(controller, xfer);
- 		}
diff --git a/target/linux/ipq806x/patches-4.0/011-watchdog-qcom-use-timer-devicetree-binding.patch b/target/linux/ipq806x/patches-4.0/011-watchdog-qcom-use-timer-devicetree-binding.patch
deleted file mode 100644
index 68489a8..0000000
--- a/target/linux/ipq806x/patches-4.0/011-watchdog-qcom-use-timer-devicetree-binding.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From fded70251b1b58f68de1d3757ece9965f0b75452 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Thu, 19 Feb 2015 20:19:30 -0800
-Subject: [PATCH 1/3] watchdog: qcom: use timer devicetree binding
-
-MSM watchdog configuration happens in the same register block as the
-timer, so we'll use the same binding as the existing timer.
-
-The qcom-wdt will now be probed when devicetree has an entry compatible
-with "qcom,kpss-timer" or "qcom-scss-timer".
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- drivers/watchdog/qcom-wdt.c | 21 +++++++++++++++------
- 1 file changed, 15 insertions(+), 6 deletions(-)
-
---- a/drivers/watchdog/qcom-wdt.c
-+++ b/drivers/watchdog/qcom-wdt.c
-@@ -20,9 +20,9 @@
- #include <linux/reboot.h>
- #include <linux/watchdog.h>
- 
--#define WDT_RST		0x0
--#define WDT_EN		0x8
--#define WDT_BITE_TIME	0x24
-+#define WDT_RST		0x38
-+#define WDT_EN		0x40
-+#define WDT_BITE_TIME	0x5C
- 
- struct qcom_wdt {
- 	struct watchdog_device	wdd;
-@@ -117,6 +117,8 @@ static int qcom_wdt_probe(struct platfor
- {
- 	struct qcom_wdt *wdt;
- 	struct resource *res;
-+	struct device_node *np = pdev->dev.of_node;
-+	u32 percpu_offset;
- 	int ret;
- 
- 	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-@@ -124,6 +126,14 @@ static int qcom_wdt_probe(struct platfor
- 		return -ENOMEM;
- 
- 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+	/* We use CPU0's DGT for the watchdog */
-+	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
-+		percpu_offset = 0;
-+
-+	res->start += percpu_offset;
-+	res->end += percpu_offset;
-+
- 	wdt->base = devm_ioremap_resource(&pdev->dev, res);
- 	if (IS_ERR(wdt->base))
- 		return PTR_ERR(wdt->base);
-@@ -203,9 +213,8 @@ static int qcom_wdt_remove(struct platfo
- }
- 
- static const struct of_device_id qcom_wdt_of_table[] = {
--	{ .compatible = "qcom,kpss-wdt-msm8960", },
--	{ .compatible = "qcom,kpss-wdt-apq8064", },
--	{ .compatible = "qcom,kpss-wdt-ipq8064", },
-+	{ .compatible = "qcom,kpss-timer" },
-+	{ .compatible = "qcom,scss-timer" },
- 	{ },
- };
- MODULE_DEVICE_TABLE(of, qcom_wdt_of_table);
diff --git a/target/linux/ipq806x/patches-4.0/012-ARM-qcom-add-description-of-KPSS-WDT-for-IPQ8064.patch b/target/linux/ipq806x/patches-4.0/012-ARM-qcom-add-description-of-KPSS-WDT-for-IPQ8064.patch
deleted file mode 100644
index ae96776..0000000
--- a/target/linux/ipq806x/patches-4.0/012-ARM-qcom-add-description-of-KPSS-WDT-for-IPQ8064.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 297cf8136ecd6a56520888fd28948393766b8ee7 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Thu, 19 Feb 2015 20:27:39 -0800
-Subject: [PATCH 2/3] ARM: qcom: add description of KPSS WDT for IPQ8064
-
-Add the watchdog related entries to the Krait Processor Sub-system
-(KPSS) timer IPQ8064 devicetree section. Also, add a fixed-clock
-description of SLEEP_CLK, which will do for now.
-
-Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/boot/dts/qcom-ipq8064.dtsi | 14 +++++++++++++-
- 1 file changed, 13 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -60,6 +60,14 @@
- 		};
- 	};
- 
-+	clocks {
-+		sleep_clk: sleep_clk {
-+			compatible = "fixed-clock";
-+			clock-frequency = <32768>;
-+			#clock-cells = <0>;
-+		};
-+	};
-+
- 	soc: soc {
- 		#address-cells = <1>;
- 		#size-cells = <1>;
-@@ -89,10 +97,14 @@
- 			compatible = "qcom,kpss-timer", "qcom,msm-timer";
- 			interrupts = <1 1 0x301>,
- 				     <1 2 0x301>,
--				     <1 3 0x301>;
-+				     <1 3 0x301>,
-+				     <1 4 0x301>,
-+				     <1 5 0x301>;
- 			reg = <0x0200a000 0x100>;
- 			clock-frequency = <25000000>,
- 					  <32768>;
-+			clocks = <&sleep_clk>;
-+			clock-names = "sleep";
- 			cpu-offset = <0x80000>;
- 		};
- 
diff --git a/target/linux/ipq806x/patches-4.0/013-ARM-msm-add-watchdog-entries-to-DT-timer-binding-doc.patch b/target/linux/ipq806x/patches-4.0/013-ARM-msm-add-watchdog-entries-to-DT-timer-binding-doc.patch
deleted file mode 100644
index e775f12..0000000
--- a/target/linux/ipq806x/patches-4.0/013-ARM-msm-add-watchdog-entries-to-DT-timer-binding-doc.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From e535f01dffb6dd9e09934fa219be52af3437a8f6 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Thu, 19 Feb 2015 20:36:27 -0800
-Subject: [PATCH 3/3] ARM: msm: add watchdog entries to DT timer binding doc
-
-The watchdog has been reworked to use the same DT node as the timer.
-This change is updating the device tree doc accordingly.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- Documentation/devicetree/bindings/arm/msm/timer.txt | 16 +++++++++++++---
- 1 file changed, 13 insertions(+), 3 deletions(-)
-
---- a/Documentation/devicetree/bindings/arm/msm/timer.txt
-+++ b/Documentation/devicetree/bindings/arm/msm/timer.txt
-@@ -9,11 +9,17 @@ Properties:
-                "qcom,scss-timer" - scorpion subsystem
- 
- - interrupts : Interrupts for the debug timer, the first general purpose
--               timer, and optionally a second general purpose timer in that
--               order.
-+               timer, and optionally a second general purpose timer, and
-+               optionally as well, 2 watchdog interrupts, in that order.
- 
- - reg : Specifies the base address of the timer registers.
- 
-+- clocks: Reference to the parent clocks, one per output clock. The parents
-+          must appear in the same order as the clock names.
-+
-+- clock-names: The name of the clocks as free-form strings. They should be in
-+               the same order as the clocks.
-+
- - clock-frequency : The frequency of the debug timer and the general purpose
-                     timer(s) in Hz in that order.
- 
-@@ -29,9 +35,13 @@ Example:
-                compatible = "qcom,scss-timer", "qcom,msm-timer";
-                interrupts = <1 1 0x301>,
-                             <1 2 0x301>,
--                            <1 3 0x301>;
-+                            <1 3 0x301>,
-+                            <1 4 0x301>,
-+                            <1 5 0x301>;
-                reg = <0x0200a000 0x100>;
-                clock-frequency = <19200000>,
-                                  <32768>;
-+               clocks = <&sleep_clk>;
-+               clock-names = "sleep";
-                cpu-offset = <0x40000>;
-        };
diff --git a/target/linux/ipq806x/patches-4.0/020-add-ap148-bootargs.patch b/target/linux/ipq806x/patches-4.0/020-add-ap148-bootargs.patch
deleted file mode 100644
index a61481e..0000000
--- a/target/linux/ipq806x/patches-4.0/020-add-ap148-bootargs.patch
+++ /dev/null
@@ -1,46 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -14,6 +14,14 @@
- 		};
- 	};
- 
-+	alias {
-+		serial0 = &uart4;
-+	};
-+
-+	chosen {
-+		linux,stdout-path = "serial0:115200n8";
-+	};
-+
- 	soc {
- 		pinmux@800000 {
- 			i2c4_pins: i2c4_pinmux {
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -140,7 +140,7 @@
- 			ranges;
- 			status = "disabled";
- 
--			serial@12490000 {
-+			uart2: serial@12490000 {
- 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
- 				reg = <0x12490000 0x1000>,
- 				      <0x12480000 0x1000>;
-@@ -175,7 +175,7 @@
- 			ranges;
- 			status = "disabled";
- 
--			serial@16340000 {
-+			uart4: serial@16340000 {
- 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
- 				reg = <0x16340000 0x1000>,
- 				      <0x16300000 0x1000>;
-@@ -209,7 +209,7 @@
- 			ranges;
- 			status = "disabled";
- 
--			serial@1a240000 {
-+			uart5: serial@1a240000 {
- 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
- 				reg = <0x1a240000 0x1000>,
- 				      <0x1a200000 0x1000>;
diff --git a/target/linux/ipq806x/patches-4.0/021-add-ap148-partitions.patch b/target/linux/ipq806x/patches-4.0/021-add-ap148-partitions.patch
deleted file mode 100644
index 34eb9c0..0000000
--- a/target/linux/ipq806x/patches-4.0/021-add-ap148-partitions.patch
+++ /dev/null
@@ -1,35 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -78,13 +78,28 @@
- 					reg = <0>;
- 
- 					partition@0 {
--						label = "rootfs";
--						reg = <0x0 0x1000000>;
-+						label = "lowlevel_init";
-+						reg = <0x0 0x1b0000>;
- 					};
- 
- 					partition@1 {
--						label = "scratch";
--						reg = <0x1000000 0x1000000>;
-+						label = "u-boot";
-+						reg = <0x1b0000 0x80000>;
-+					};
-+
-+					partition@2 {
-+						label = "u-boot-env";
-+						reg = <0x230000 0x40000>;
-+					};
-+
-+					partition@3 {
-+						label = "caldata";
-+						reg = <0x270000 0x40000>;
-+					};
-+
-+					partition@4 {
-+						label = "firmware";
-+						reg = <0x2b0000 0x1d50000>;
- 					};
- 				};
- 			};
diff --git a/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch b/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch
deleted file mode 100644
index 29631b2..0000000
--- a/target/linux/ipq806x/patches-4.0/022-add-db149-dts.patch
+++ /dev/null
@@ -1,160 +0,0 @@
-From f26cc3733bdd697bd81ae505fc133fa7c9b6ea19 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Tue, 7 Apr 2015 19:58:58 -0700
-Subject: [PATCH] ARM: dts: qcom: add initial DB149 device-tree
-
-Add basic DB149 (IPQ806x based platform) device-tree. It supports UART,
-SATA, USB2, USB3 and NOR flash.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/boot/dts/Makefile               |   1 +
- arch/arm/boot/dts/qcom-ipq8064-db149.dts | 132 +++++++++++++++++++++++++++++++
- 2 files changed, 133 insertions(+)
- create mode 100644 arch/arm/boot/dts/qcom-ipq8064-db149.dts
-
---- a/arch/arm/boot/dts/Makefile
-+++ b/arch/arm/boot/dts/Makefile
-@@ -438,6 +438,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
- 	qcom-apq8084-ifc6540.dtb \
- 	qcom-apq8084-mtp.dtb \
- 	qcom-ipq8064-ap148.dtb \
-+	qcom-ipq8064-db149.dtb \
- 	qcom-msm8660-surf.dtb \
- 	qcom-msm8960-cdp.dtb \
- 	qcom-msm8974-sony-xperia-honami.dtb
---- /dev/null
-+++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -0,0 +1,132 @@
-+#include "qcom-ipq8064-v1.0.dtsi"
-+
-+/ {
-+	model = "Qualcomm IPQ8064/DB149";
-+	compatible = "qcom,ipq8064-db149", "qcom,ipq8064";
-+
-+	reserved-memory {
-+		#address-cells = <1>;
-+		#size-cells = <1>;
-+		ranges;
-+		rsvd@41200000 {
-+			reg = <0x41200000 0x300000>;
-+			no-map;
-+		};
-+	};
-+
-+	alias {
-+		serial0 = &uart2;
-+	};
-+
-+	chosen {
-+		linux,stdout-path = "serial0:115200n8";
-+	};
-+
-+	soc {
-+		pinmux@800000 {
-+			i2c4_pins: i2c4_pinmux {
-+				pins = "gpio12", "gpio13";
-+				function = "gsbi4";
-+				bias-disable;
-+			};
-+
-+			spi_pins: spi_pins {
-+				mux {
-+					pins = "gpio18", "gpio19", "gpio21";
-+					function = "gsbi5";
-+					drive-strength = <10>;
-+					bias-none;
-+				};
-+			};
-+		};
-+
-+		gsbi2: gsbi@12480000 {
-+			qcom,mode = <GSBI_PROT_I2C_UART>;
-+			status = "ok";
-+			uart2: serial@12490000 {
-+				status = "ok";
-+			};
-+		};
-+
-+		gsbi5: gsbi@1a200000 {
-+			qcom,mode = <GSBI_PROT_SPI>;
-+			status = "ok";
-+
-+			spi4: spi@1a280000 {
-+				status = "ok";
-+				spi-max-frequency = <50000000>;
-+
-+				pinctrl-0 = <&spi_pins>;
-+				pinctrl-names = "default";
-+
-+				cs-gpios = <&qcom_pinmux 20 0>;
-+
-+				flash: m25p80@0 {
-+					compatible = "s25fl256s1";
-+					#address-cells = <1>;
-+					#size-cells = <1>;
-+					spi-max-frequency = <50000000>;
-+					reg = <0>;
-+					m25p,fast-read;
-+
-+					partition@0 {
-+						label = "lowlevel_init";
-+						reg = <0x0 0x1b0000>;
-+					};
-+
-+					partition@1 {
-+						label = "u-boot";
-+						reg = <0x1b0000 0x80000>;
-+					};
-+
-+					partition@2 {
-+						label = "u-boot-env";
-+						reg = <0x230000 0x40000>;
-+					};
-+
-+					partition@3 {
-+						label = "caldata";
-+						reg = <0x270000 0x40000>;
-+					};
-+
-+					partition@4 {
-+						label = "firmware";
-+						reg = <0x2b0000 0x1d50000>;
-+					};
-+				};
-+			};
-+		};
-+
-+		sata-phy@1b400000 {
-+			status = "ok";
-+		};
-+
-+		sata@29000000 {
-+			status = "ok";
-+		};
-+
-+		phy@100f8800 {		/* USB3 port 1 HS phy */
-+			status = "ok";
-+		};
-+
-+		phy@100f8830 {		/* USB3 port 1 SS phy */
-+			status = "ok";
-+		};
-+
-+		phy@110f8800 {		/* USB3 port 0 HS phy */
-+			status = "ok";
-+		};
-+
-+		phy@110f8830 {		/* USB3 port 0 SS phy */
-+			status = "ok";
-+		};
-+
-+		usb30@0 {
-+			status = "ok";
-+		};
-+
-+		usb30@1 {
-+			status = "ok";
-+		};
-+	};
-+};
diff --git a/target/linux/ipq806x/patches-4.0/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch b/target/linux/ipq806x/patches-4.0/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch
deleted file mode 100644
index 75595ca..0000000
--- a/target/linux/ipq806x/patches-4.0/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -46,15 +46,12 @@
- 			serial@16340000 {
- 				status = "ok";
- 			};
--
--			i2c4: i2c@16380000 {
--				status = "ok";
--
--				clock-frequency = <200000>;
--
--				pinctrl-0 = <&i2c4_pins>;
--				pinctrl-names = "default";
--			};
-+			/*
-+			 * The i2c device on gsbi4 should not be enabled.
-+			 * On ipq806x designs gsbi4 i2c is meant for exclusive
-+			 * RPM usage. Turning this on in kernel manifests as
-+			 * i2c failure for the RPM.
-+			 */
- 		};
- 
- 		gsbi5: gsbi@1a200000 {
---- a/drivers/clk/qcom/gcc-ipq806x.c
-+++ b/drivers/clk/qcom/gcc-ipq806x.c
-@@ -805,7 +805,7 @@ static struct clk_rcg gsbi7_qup_src = {
- 			.parent_names = gcc_pxo_pll8,
- 			.num_parents = 2,
- 			.ops = &clk_rcg_ops,
--			.flags = CLK_SET_PARENT_GATE,
-+			.flags = CLK_SET_PARENT_GATE | CLK_IGNORE_UNUSED,
- 		},
- 	},
- };
-@@ -821,7 +821,7 @@ static struct clk_branch gsbi7_qup_clk =
- 			.parent_names = (const char *[]){ "gsbi7_qup_src" },
- 			.num_parents = 1,
- 			.ops = &clk_branch_ops,
--			.flags = CLK_SET_RATE_PARENT,
-+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
- 		},
- 	},
- };
-@@ -869,7 +869,7 @@ static struct clk_branch gsbi4_h_clk = {
- 		.hw.init = &(struct clk_init_data){
- 			.name = "gsbi4_h_clk",
- 			.ops = &clk_branch_ops,
--			.flags = CLK_IS_ROOT,
-+			.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
- 		},
- 	},
- };
diff --git a/target/linux/ipq806x/patches-4.0/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch b/target/linux/ipq806x/patches-4.0/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch
deleted file mode 100644
index 41f91fa..0000000
--- a/target/linux/ipq806x/patches-4.0/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch
+++ /dev/null
@@ -1,263 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v2,3/5] DT: PCI: qcom: Document PCIe devicetree bindings
-From: Stanimir Varbanov <svarbanov@mm-sol.com>
-X-Patchwork-Id: 6326181
-Message-Id: <1430743338-10441-4-git-send-email-svarbanov@mm-sol.com>
-To: Rob Herring <robh+dt@kernel.org>, Kumar Gala <galak@codeaurora.org>,
-	Mark Rutland <mark.rutland@arm.com>,
-	Grant Likely <grant.likely@linaro.org>,
-	Bjorn Helgaas <bhelgaas@google.com>,
-	Kishon Vijay Abraham I <kishon@ti.com>,
-	Russell King <linux@arm.linux.org.uk>, Arnd Bergmann <arnd@arndb.de>
-Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
-	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
-	linux-pci@vger.kernel.org, Mathieu Olivari <mathieu@codeaurora.org>,
-	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
-	Stanimir Varbanov <svarbanov@mm-sol.com>
-Date: Mon,  4 May 2015 15:42:16 +0300
-
-Document Qualcomm PCIe driver devicetree bindings.
-
-Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
-
----
-.../devicetree/bindings/pci/qcom,pcie.txt          |  231 ++++++++++++++++++++
- 1 files changed, 231 insertions(+), 0 deletions(-)
- create mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
-@@ -0,0 +1,231 @@
-+* Qualcomm PCI express root complex
-+
-+- compatible:
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: Value shall include
-+		    - "qcom,pcie-v0" for apq/ipq8064
-+		    - "qcom,pcie-v1" for apq8084
-+
-+- reg:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: Register ranges as listed in the reg-names property
-+
-+- reg-names:
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: Must include the following entries
-+		    - "parf"   Qualcomm specific registers
-+		    - "dbi"    Designware PCIe registers
-+		    - "elbi"   External local bus interface registers
-+		    - "config" PCIe configuration space
-+
-+- device_type:
-+	Usage: required
-+	Value type: <string>
-+	Definition: Should be "pci". As specified in designware-pcie.txt
-+
-+- #address-cells:
-+	Usage: required
-+	Value type: <u32>
-+	Definition: Should be set to 3. As specified in designware-pcie.txt
-+
-+- #size-cells:
-+	Usage: required
-+	Value type: <u32>
-+	Definition: Should be set 2. As specified in designware-pcie.txt
-+
-+- ranges:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: As specified in designware-pcie.txt
-+
-+- interrupts:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: MSI interrupt
-+
-+- interrupt-names:
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: Should contain "msi"
-+
-+- #interrupt-cells:
-+	Usage: required
-+	Value type: <u32>
-+	Definition: Should be 1. As specified in designware-pcie.txt
-+
-+- interrupt-map-mask:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: As specified in designware-pcie.txt
-+
-+- interrupt-map:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: As specified in designware-pcie.txt
-+
-+- clocks:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: List of phandle and clock specifier pairs as listed
-+		    in clock-names property
-+
-+- clock-names:
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: Should contain the following entries
-+		    * should be populated for v0 and v1
-+		    	- "iface"      Configuration AHB clock
-+
-+		    * should be populated for v0
-+		    	- "core"       Clocks the pcie hw block
-+		    	- "phy"        Clocks the pcie PHY block
-+
-+		    * should be populated for v1
-+			- "aux"        Auxiliary (AUX) clock
-+		    	- "bus_master" Master AXI clock
-+		    	- "bus_slave"  Slave AXI clock
-+
-+- resets:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: List of phandle and reset specifier pairs as listed
-+		    in reset-names property
-+
-+- reset-names:
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: Should contain the following entries
-+		    * should be populated for v0
-+			- "axi"  AXI reset
-+			- "ahb"  AHB reset
-+			- "por"  POR reset
-+			- "pci"  PCI reset
-+			- "phy"  PHY reset
-+
-+		    * should be populated for v1
-+			- "core" Core reset
-+
-+- power-domains:
-+	Usage: required (for v1 only)
-+	Value type: <prop-encoded-array>
-+	Definition: A phandle and power domain specifier pair to the
-+		    power domain which is responsible for collapsing
-+		    and restoring power to the peripheral
-+
-+- <name>-supply:
-+	Usage: required
-+	Value type: <phandle>
-+	Definition: List of phandles to the power supply regulator(s)
-+		    * should be populated for v0 and v1
-+			- "vdda"        core analog power supply
-+
-+		    * should be populated for v0
-+			- "vdda_phy"    analog power supply for PHY
-+			- "vdda_refclk" analog power supply for IC which generate
-+					reference clock
-+
-+- phys:
-+	Usage: required (for v1 only)
-+	Value type: <phandle>
-+	Definition: List of phandle(s) as listed in phy-names property
-+
-+- phy-names:
-+	Usage: required (for v1 only)
-+	Value type: <stringlist>
-+	Definition: Should contain "pciephy"
-+
-+- <name>-gpio:
-+	Usage: optional
-+	Value type: <prop-encoded-array>
-+	Definition: List of phandle and gpio specifier pairs. Should contain
-+		    - "perst"  PCIe endpoint reset signal line
-+		    - "pewake" PCIe endpoint wake signal line
-+
-+- pinctrl-0:
-+	Usage: required
-+	Value type: <phandle>
-+	Definition: List of phandles pointing at a pin(s) configuration
-+
-+- pinctrl-names
-+	Usage: required
-+	Value type: <stringlist>
-+	Definition: List of names of pinctrl-0 state
-+
-+* Example for v0
-+	pcie0: pci@1b500000 {
-+		compatible = "qcom,pcie-v0";
-+		reg = <0x1b500000 0x1000
-+		       0x1b502000 0x80
-+		       0x1b600000 0x100
-+		       0x0ff00000 0x100000>;
-+		reg-names = "dbi", "elbi", "parf", "config";
-+		device_type = "pci";
-+		linux,pci-domain = <0>;
-+		bus-range = <0x00 0xff>;
-+		num-lanes = <1>;
-+		#address-cells = <3>;
-+		#size-cells = <2>;
-+		ranges = <0x81000000 0 0	  0x0fe00000 0 0x00100000   /* I/O */
-+			  0x82000000 0 0x00000000 0x08000000 0 0x07e00000>; /* memory */
-+		interrupts = <GIC_SPI 35 IRQ_TYPE_NONE>;
-+		interrupt-names = "msi";
-+		#interrupt-cells = <1>;
-+		interrupt-map-mask = <0 0 0 0x7>;
-+		interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
-+				<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
-+				<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
-+				<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
-+		clocks = <&gcc PCIE_A_CLK>,
-+			 <&gcc PCIE_H_CLK>,
-+			 <&gcc PCIE_PHY_CLK>;
-+		clock-names = "core", "iface", "phy";
-+		resets = <&gcc PCIE_ACLK_RESET>,
-+			 <&gcc PCIE_HCLK_RESET>,
-+			 <&gcc PCIE_POR_RESET>,
-+			 <&gcc PCIE_PCI_RESET>,
-+			 <&gcc PCIE_PHY_RESET>;
-+		reset-names = "axi", "ahb", "por", "pci", "phy";
-+	};
-+
-+* Example for v1
-+	pcie0@fc520000 {
-+		compatible = "qcom,pcie-v1";
-+		reg = <0xfc520000 0x2000>,
-+		      <0xff000000 0x1000>,
-+		      <0xff001000 0x1000>,
-+		      <0xff002000 0x2000>;
-+		reg-names = "parf", "dbi", "elbi", "config";
-+		device_type = "pci";
-+		linux,pci-domain = <0>;
-+		bus-range = <0x00 0xff>;
-+		num-lanes = <1>;
-+		#address-cells = <3>;
-+		#size-cells = <2>;
-+		ranges = <0x81000000 0 0          0xff200000 0 0x00100000   /* I/O */
-+			  0x82000000 0 0x00300000 0xff300000 0 0x00d00000>; /* memory */
-+		interrupts = <GIC_SPI 243 IRQ_TYPE_NONE>;
-+		interrupt-names = "msi";
-+		#interrupt-cells = <1>;
-+		interrupt-map-mask = <0 0 0 0x7>;
-+		interrupt-map = <0 0 0 1 &intc 0 244 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
-+				<0 0 0 2 &intc 0 245 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
-+				<0 0 0 3 &intc 0 247 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
-+				<0 0 0 4 &intc 0 248 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
-+		clocks = <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
-+			 <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
-+			 <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
-+			 <&gcc GCC_PCIE_0_AUX_CLK>;
-+		clock-names = "iface", "master_bus", "slave_bus", "aux";
-+		resets = <&gcc GCC_PCIE_0_BCR>;
-+		reset-names = "core";
-+		power-domains = <&gcc PCIE0_GDSC>;
-+		vdda-supply = <&pma8084_l3>;
-+		phys = <&pciephy0>;
-+		phy-names = "pciephy";
-+		perst-gpio = <&tlmm 70 GPIO_ACTIVE_LOW>;
-+		pinctrl-0 = <&pcie0_pins_default>;
-+		pinctrl-names = "default";
-+	};
diff --git a/target/linux/ipq806x/patches-4.0/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch b/target/linux/ipq806x/patches-4.0/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch
deleted file mode 100644
index b64b759..0000000
--- a/target/linux/ipq806x/patches-4.0/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch
+++ /dev/null
@@ -1,753 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v2,4/5] PCI: qcom: Add Qualcomm PCIe controller driver
-From: Stanimir Varbanov <svarbanov@mm-sol.com>
-X-Patchwork-Id: 6326161
-Message-Id: <1430743338-10441-5-git-send-email-svarbanov@mm-sol.com>
-To: Rob Herring <robh+dt@kernel.org>, Kumar Gala <galak@codeaurora.org>,
-	Mark Rutland <mark.rutland@arm.com>,
-	Grant Likely <grant.likely@linaro.org>,
-	Bjorn Helgaas <bhelgaas@google.com>,
-	Kishon Vijay Abraham I <kishon@ti.com>,
-	Russell King <linux@arm.linux.org.uk>, Arnd Bergmann <arnd@arndb.de>
-Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
-	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
-	linux-pci@vger.kernel.org, Mathieu Olivari <mathieu@codeaurora.org>,
-	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
-	Stanimir Varbanov <svarbanov@mm-sol.com>
-Date: Mon,  4 May 2015 15:42:17 +0300
-
-The PCIe driver reuse the Designware common code for host
-and MSI initialization, and also program the Qualcomm
-application specific registers.
-
-Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
-
----
-MAINTAINERS                  |    7 +
- drivers/pci/host/Kconfig     |    9 +
- drivers/pci/host/Makefile    |    1 +
- drivers/pci/host/pcie-qcom.c |  677 ++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 694 insertions(+), 0 deletions(-)
- create mode 100644 drivers/pci/host/pcie-qcom.c
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -7511,6 +7511,13 @@ L:	linux-pci@vger.kernel.org
- S:	Maintained
- F:	drivers/pci/host/*spear*
- 
-+PCIE DRIVER FOR QUALCOMM MSM
-+M:	Stanimir Varbanov <svarbanov@mm-sol.com>
-+L:	linux-pci@vger.kernel.org
-+L:	linux-arm-msm@vger.kernel.org
-+S:	Maintained
-+F:	drivers/pci/host/*qcom*
-+
- PCMCIA SUBSYSTEM
- P:	Linux PCMCIA Team
- L:	linux-pcmcia@lists.infradead.org
---- a/drivers/pci/host/Kconfig
-+++ b/drivers/pci/host/Kconfig
-@@ -106,4 +106,13 @@ config PCI_VERSATILE
- 	bool "ARM Versatile PB PCI controller"
- 	depends on ARCH_VERSATILE
- 
-+config PCIE_QCOM
-+	bool "Qualcomm PCIe controller"
-+	depends on ARCH_QCOM && OF || (ARM && COMPILE_TEST)
-+	select PCIE_DW
-+	select PCIEPORTBUS
-+	help
-+	  Say Y here to enable PCIe controller support on Qualcomm SoCs. The
-+	  PCIe controller use Designware core plus Qualcomm specific hardware
-+	  wrappers.
- endmenu
---- /dev/null
-+++ b/drivers/pci/host/pcie-qcom.c
-@@ -0,0 +1,677 @@
-+/*
-+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of_gpio.h>
-+#include <linux/pci.h>
-+#include <linux/platform_device.h>
-+#include <linux/phy/phy.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+
-+#include "pcie-designware.h"
-+
-+#define PCIE20_PARF_PHY_CTRL			0x40
-+#define PCIE20_PARF_PHY_REFCLK			0x4C
-+#define PCIE20_PARF_DBI_BASE_ADDR		0x168
-+#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16c
-+#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
-+
-+#define PCIE20_ELBI_SYS_CTRL			0x04
-+#define PCIE20_ELBI_SYS_STTS			0x08
-+#define XMLH_LINK_UP				BIT(10)
-+
-+#define PCIE20_CAP				0x70
-+#define PCIE20_CAP_LINKCTRLSTATUS		(PCIE20_CAP + 0x10)
-+
-+#define PERST_DELAY_MIN_US			1000
-+#define PERST_DELAY_MAX_US			1005
-+
-+#define LINKUP_DELAY_MIN_US			5000
-+#define LINKUP_DELAY_MAX_US			5100
-+#define LINKUP_RETRIES_COUNT			20
-+
-+#define PCIE_V0					0	/* apq8064 */
-+#define PCIE_V1					1	/* apq8084 */
-+
-+struct qcom_pcie_resources_v0 {
-+	struct clk *iface_clk;
-+	struct clk *core_clk;
-+	struct clk *phy_clk;
-+	struct reset_control *pci_reset;
-+	struct reset_control *axi_reset;
-+	struct reset_control *ahb_reset;
-+	struct reset_control *por_reset;
-+	struct reset_control *phy_reset;
-+	struct regulator *vdda;
-+	struct regulator *vdda_phy;
-+	struct regulator *vdda_refclk;
-+};
-+
-+struct qcom_pcie_resources_v1 {
-+	struct clk *iface;
-+	struct clk *aux;
-+	struct clk *master_bus;
-+	struct clk *slave_bus;
-+	struct reset_control *core;
-+	struct regulator *vdda;
-+};
-+
-+union pcie_resources {
-+	struct qcom_pcie_resources_v0 v0;
-+	struct qcom_pcie_resources_v1 v1;
-+};
-+
-+struct qcom_pcie {
-+	struct pcie_port pp;
-+	struct device *dev;
-+	union pcie_resources res;
-+	void __iomem *parf;
-+	void __iomem *dbi;
-+	void __iomem *elbi;
-+	struct phy *phy;
-+	struct gpio_desc *reset;
-+	unsigned int version;
-+};
-+
-+#define to_qcom_pcie(x)		container_of(x, struct qcom_pcie, pp)
-+
-+static inline void
-+writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask)
-+{
-+	u32 val = readl(addr);
-+
-+	val &= ~clear_mask;
-+	val |= set_mask;
-+	writel(val, addr);
-+}
-+
-+static void qcom_ep_reset_assert_deassert(struct qcom_pcie *pcie, int assert)
-+{
-+	int val, active_low;
-+
-+	if (IS_ERR_OR_NULL(pcie->reset))
-+		return;
-+
-+	active_low = gpiod_is_active_low(pcie->reset);
-+
-+	if (assert)
-+		val = !!active_low;
-+	else
-+		val = !active_low;
-+
-+	gpiod_set_value(pcie->reset, val);
-+
-+	usleep_range(PERST_DELAY_MIN_US, PERST_DELAY_MAX_US);
-+}
-+
-+static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
-+{
-+	qcom_ep_reset_assert_deassert(pcie, 1);
-+}
-+
-+static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
-+{
-+	qcom_ep_reset_assert_deassert(pcie, 0);
-+}
-+
-+static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
-+{
-+	struct pcie_port *pp = arg;
-+
-+	return dw_handle_msi_irq(pp);
-+}
-+
-+static int qcom_pcie_link_up(struct pcie_port *pp)
-+{
-+	struct qcom_pcie *pcie = to_qcom_pcie(pp);
-+	u32 val = readl(pcie->dbi + PCIE20_CAP_LINKCTRLSTATUS);
-+
-+	return val & BIT(29) ? 1 : 0;
-+}
-+
-+static void qcom_pcie_disable_resources_v0(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
-+
-+	reset_control_assert(res->pci_reset);
-+	reset_control_assert(res->axi_reset);
-+	reset_control_assert(res->ahb_reset);
-+	reset_control_assert(res->por_reset);
-+	reset_control_assert(res->pci_reset);
-+	clk_disable_unprepare(res->iface_clk);
-+	clk_disable_unprepare(res->core_clk);
-+	clk_disable_unprepare(res->phy_clk);
-+	regulator_disable(res->vdda);
-+	regulator_disable(res->vdda_phy);
-+	regulator_disable(res->vdda_refclk);
-+}
-+
-+static void qcom_pcie_disable_resources_v1(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
-+
-+	reset_control_assert(res->core);
-+	clk_disable_unprepare(res->slave_bus);
-+	clk_disable_unprepare(res->master_bus);
-+	clk_disable_unprepare(res->iface);
-+	clk_disable_unprepare(res->aux);
-+	regulator_disable(res->vdda);
-+}
-+
-+static int qcom_pcie_enable_resources_v0(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
-+	struct device *dev = pcie->dev;
-+	int ret;
-+
-+	ret = regulator_enable(res->vdda);
-+	if (ret) {
-+		dev_err(dev, "cannot enable vdda regulator\n");
-+		return ret;
-+	}
-+
-+	ret = regulator_enable(res->vdda_refclk);
-+	if (ret) {
-+		dev_err(dev, "cannot enable vdda_refclk regulator\n");
-+		goto err_refclk;
-+	}
-+
-+	ret = regulator_enable(res->vdda_phy);
-+	if (ret) {
-+		dev_err(dev, "cannot enable vdda_phy regulator\n");
-+		goto err_vdda_phy;
-+	}
-+
-+	ret = clk_prepare_enable(res->iface_clk);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable iface clock\n");
-+		goto err_iface;
-+	}
-+
-+	ret = clk_prepare_enable(res->core_clk);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable core clock\n");
-+		goto err_clk_core;
-+	}
-+
-+	ret = clk_prepare_enable(res->phy_clk);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable phy clock\n");
-+		goto err_clk_phy;
-+	}
-+
-+	ret = reset_control_deassert(res->ahb_reset);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert ahb reset\n");
-+		goto err_reset_ahb;
-+	}
-+
-+	return 0;
-+
-+err_reset_ahb:
-+	clk_disable_unprepare(res->phy_clk);
-+err_clk_phy:
-+	clk_disable_unprepare(res->core_clk);
-+err_clk_core:
-+	clk_disable_unprepare(res->iface_clk);
-+err_iface:
-+	regulator_disable(res->vdda_phy);
-+err_vdda_phy:
-+	regulator_disable(res->vdda_refclk);
-+err_refclk:
-+	regulator_disable(res->vdda);
-+	return ret;
-+}
-+
-+static int qcom_pcie_enable_resources_v1(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
-+	struct device *dev = pcie->dev;
-+	int ret;
-+
-+	ret = reset_control_deassert(res->core);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert core reset\n");
-+		return ret;
-+	}
-+
-+	ret = clk_prepare_enable(res->aux);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable aux clock\n");
-+		goto err_res;
-+	}
-+
-+	ret = clk_prepare_enable(res->iface);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable iface clock\n");
-+		goto err_aux;
-+	}
-+
-+	ret = clk_prepare_enable(res->master_bus);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable master_bus clock\n");
-+		goto err_iface;
-+	}
-+
-+	ret = clk_prepare_enable(res->slave_bus);
-+	if (ret) {
-+		dev_err(dev, "cannot prepare/enable slave_bus clock\n");
-+		goto err_master;
-+	}
-+
-+	ret = regulator_enable(res->vdda);
-+	if (ret) {
-+		dev_err(dev, "cannot enable vdda regulator\n");
-+		goto err_slave;
-+	}
-+
-+	return 0;
-+
-+err_slave:
-+	clk_disable_unprepare(res->slave_bus);
-+err_master:
-+	clk_disable_unprepare(res->master_bus);
-+err_iface:
-+	clk_disable_unprepare(res->iface);
-+err_aux:
-+	clk_disable_unprepare(res->aux);
-+err_res:
-+	reset_control_assert(res->core);
-+
-+	return ret;
-+}
-+
-+static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
-+	struct device *dev = pcie->dev;
-+
-+	res->vdda = devm_regulator_get(dev, "vdda");
-+	if (IS_ERR(res->vdda))
-+		return PTR_ERR(res->vdda);
-+
-+	res->vdda_phy = devm_regulator_get(dev, "vdda_phy");
-+	if (IS_ERR(res->vdda_phy))
-+		return PTR_ERR(res->vdda_phy);
-+
-+	res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk");
-+	if (IS_ERR(res->vdda_refclk))
-+		return PTR_ERR(res->vdda_refclk);
-+
-+	res->iface_clk = devm_clk_get(dev, "iface");
-+	if (IS_ERR(res->iface_clk))
-+		return PTR_ERR(res->iface_clk);
-+
-+	res->core_clk = devm_clk_get(dev, "core");
-+	if (IS_ERR(res->core_clk))
-+		return PTR_ERR(res->core_clk);
-+
-+	res->phy_clk = devm_clk_get(dev, "phy");
-+	if (IS_ERR(res->phy_clk))
-+		return PTR_ERR(res->phy_clk);
-+
-+	res->pci_reset = devm_reset_control_get(dev, "pci");
-+	if (IS_ERR(res->pci_reset))
-+		return PTR_ERR(res->pci_reset);
-+
-+	res->axi_reset = devm_reset_control_get(dev, "axi");
-+	if (IS_ERR(res->axi_reset))
-+		return PTR_ERR(res->axi_reset);
-+
-+	res->ahb_reset = devm_reset_control_get(dev, "ahb");
-+	if (IS_ERR(res->ahb_reset))
-+		return PTR_ERR(res->ahb_reset);
-+
-+	res->por_reset = devm_reset_control_get(dev, "por");
-+	if (IS_ERR(res->por_reset))
-+		return PTR_ERR(res->por_reset);
-+
-+	res->phy_reset = devm_reset_control_get(dev, "phy");
-+	if (IS_ERR(res->phy_reset))
-+		return PTR_ERR(res->phy_reset);
-+
-+	return 0;
-+}
-+
-+static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
-+{
-+	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
-+	struct device *dev = pcie->dev;
-+
-+	res->vdda = devm_regulator_get(dev, "vdda");
-+	if (IS_ERR(res->vdda))
-+		return PTR_ERR(res->vdda);
-+
-+	res->iface = devm_clk_get(dev, "iface");
-+	if (IS_ERR(res->iface))
-+		return PTR_ERR(res->iface);
-+
-+	res->aux = devm_clk_get(dev, "aux");
-+	if (IS_ERR(res->aux) && PTR_ERR(res->aux) == -EPROBE_DEFER)
-+		return -EPROBE_DEFER;
-+	else if (IS_ERR(res->aux))
-+		res->aux = NULL;
-+
-+	res->master_bus = devm_clk_get(dev, "master_bus");
-+	if (IS_ERR(res->master_bus))
-+		return PTR_ERR(res->master_bus);
-+
-+	res->slave_bus = devm_clk_get(dev, "slave_bus");
-+	if (IS_ERR(res->slave_bus))
-+		return PTR_ERR(res->slave_bus);
-+
-+	res->core = devm_reset_control_get(dev, "core");
-+	if (IS_ERR(res->core))
-+		return PTR_ERR(res->core);
-+
-+	return 0;
-+}
-+
-+static int qcom_pcie_enable_link_training(struct pcie_port *pp)
-+{
-+	struct qcom_pcie *pcie = to_qcom_pcie(pp);
-+	struct device *dev = pp->dev;
-+	int retries;
-+	u32 val;
-+
-+	/* enable link training */
-+	writel_masked(pcie->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0));
-+
-+	/* wait for up to 100ms for the link to come up */
-+	retries = LINKUP_RETRIES_COUNT;
-+	do {
-+		val = readl(pcie->elbi + PCIE20_ELBI_SYS_STTS);
-+		if (val & XMLH_LINK_UP)
-+			break;
-+		usleep_range(LINKUP_DELAY_MIN_US, LINKUP_DELAY_MAX_US);
-+	} while (retries--);
-+
-+	if (retries < 0 || !dw_pcie_link_up(pp)) {
-+		dev_err(dev, "link initialization failed\n");
-+		return -ENXIO;
-+	}
-+
-+	return 0;
-+}
-+
-+static void qcom_pcie_host_init_v1(struct pcie_port *pp)
-+{
-+	struct qcom_pcie *pcie = to_qcom_pcie(pp);
-+	int ret;
-+
-+	qcom_ep_reset_assert(pcie);
-+
-+	ret = qcom_pcie_enable_resources_v1(pcie);
-+	if (ret)
-+		return;
-+
-+	/* change DBI base address */
-+	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
-+
-+	if (IS_ENABLED(CONFIG_PCI_MSI))
-+		writel_masked(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT,
-+			      0, BIT(31));
-+
-+	ret = phy_init(pcie->phy);
-+	if (ret)
-+		goto err_res;
-+
-+	ret = phy_power_on(pcie->phy);
-+	if (ret)
-+		goto err_phy;
-+
-+	dw_pcie_setup_rc(pp);
-+
-+	if (IS_ENABLED(CONFIG_PCI_MSI))
-+		dw_pcie_msi_init(pp);
-+
-+	qcom_ep_reset_deassert(pcie);
-+
-+	ret = qcom_pcie_enable_link_training(pp);
-+	if (ret)
-+		goto err;
-+
-+	return;
-+
-+err:
-+	qcom_ep_reset_assert(pcie);
-+	phy_power_off(pcie->phy);
-+err_phy:
-+	phy_exit(pcie->phy);
-+err_res:
-+	qcom_pcie_disable_resources_v1(pcie);
-+}
-+
-+static void qcom_pcie_host_init_v0(struct pcie_port *pp)
-+{
-+	struct qcom_pcie *pcie = to_qcom_pcie(pp);
-+	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
-+	struct device *dev = pcie->dev;
-+	int ret;
-+
-+	qcom_ep_reset_assert(pcie);
-+
-+	ret = qcom_pcie_enable_resources_v0(pcie);
-+	if (ret)
-+		return;
-+
-+	writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
-+
-+	/* enable external reference clock */
-+	writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, 0, BIT(16));
-+
-+	ret = reset_control_deassert(res->phy_reset);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert phy reset\n");
-+		return;
-+	}
-+
-+	ret = reset_control_deassert(res->pci_reset);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert pci reset\n");
-+		return;
-+	}
-+
-+	ret = reset_control_deassert(res->por_reset);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert por reset\n");
-+		return;
-+	}
-+
-+	ret = reset_control_deassert(res->axi_reset);
-+	if (ret) {
-+		dev_err(dev, "cannot deassert axi reset\n");
-+		return;
-+	}
-+
-+	/* wait 150ms for clock acquisition */
-+	usleep_range(10000, 15000);
-+
-+	dw_pcie_setup_rc(pp);
-+
-+	if (IS_ENABLED(CONFIG_PCI_MSI))
-+		dw_pcie_msi_init(pp);
-+
-+	qcom_ep_reset_deassert(pcie);
-+
-+	ret = qcom_pcie_enable_link_training(pp);
-+	if (ret)
-+		goto err;
-+
-+	return;
-+err:
-+	qcom_ep_reset_assert(pcie);
-+	qcom_pcie_disable_resources_v0(pcie);
-+}
-+
-+static void qcom_pcie_host_init(struct pcie_port *pp)
-+{
-+	struct qcom_pcie *pcie = to_qcom_pcie(pp);
-+
-+	if (pcie->version == PCIE_V0)
-+		return qcom_pcie_host_init_v0(pp);
-+	else
-+		return qcom_pcie_host_init_v1(pp);
-+}
-+
-+static int
-+qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val)
-+{
-+	/* the device class is not reported correctly from the register */
-+	if (where == PCI_CLASS_REVISION && size == 4) {
-+		*val = readl(pp->dbi_base + PCI_CLASS_REVISION);
-+		*val &= ~(0xffff << 16);
-+		*val |= PCI_CLASS_BRIDGE_PCI << 16;
-+		return PCIBIOS_SUCCESSFUL;
-+	}
-+
-+	return dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
-+				size, val);
-+}
-+
-+static struct pcie_host_ops qcom_pcie_ops = {
-+	.link_up = qcom_pcie_link_up,
-+	.host_init = qcom_pcie_host_init,
-+	.rd_own_conf = qcom_pcie_rd_own_conf,
-+};
-+
-+static const struct of_device_id qcom_pcie_match[] = {
-+	{ .compatible = "qcom,pcie-v0", .data = (void *)PCIE_V0 },
-+	{ .compatible = "qcom,pcie-v1", .data = (void *)PCIE_V1 },
-+	{ }
-+};
-+
-+static int qcom_pcie_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	const struct of_device_id *match;
-+	struct resource *res;
-+	struct qcom_pcie *pcie;
-+	struct pcie_port *pp;
-+	int ret;
-+
-+	match = of_match_node(qcom_pcie_match, dev->of_node);
-+	if (!match)
-+		return -ENXIO;
-+
-+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
-+	if (!pcie)
-+		return -ENOMEM;
-+
-+	pcie->version = (unsigned int)match->data;
-+
-+	pcie->reset = devm_gpiod_get_optional(dev, "perst");
-+	if (IS_ERR(pcie->reset) && PTR_ERR(pcie->reset) == -EPROBE_DEFER)
-+		return PTR_ERR(pcie->reset);
-+
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
-+	pcie->parf = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pcie->parf))
-+		return PTR_ERR(pcie->parf);
-+
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
-+	pcie->dbi = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pcie->dbi))
-+		return PTR_ERR(pcie->dbi);
-+
-+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
-+	pcie->elbi = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(pcie->elbi))
-+		return PTR_ERR(pcie->elbi);
-+
-+	pcie->phy = devm_phy_optional_get(dev, "pciephy");
-+	if (IS_ERR(pcie->phy))
-+		return PTR_ERR(pcie->phy);
-+
-+	pcie->dev = dev;
-+
-+	if (pcie->version == PCIE_V0)
-+		ret = qcom_pcie_get_resources_v0(pcie);
-+	else
-+		ret = qcom_pcie_get_resources_v1(pcie);
-+
-+	if (ret)
-+		return ret;
-+
-+	pp = &pcie->pp;
-+	pp->dev = dev;
-+	pp->dbi_base = pcie->dbi;
-+	pp->root_bus_nr = -1;
-+	pp->ops = &qcom_pcie_ops;
-+
-+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
-+		pp->msi_irq = platform_get_irq_byname(pdev, "msi");
-+		if (pp->msi_irq < 0) {
-+			dev_err(dev, "cannot get msi irq\n");
-+			return pp->msi_irq;
-+		}
-+
-+		ret = devm_request_irq(dev, pp->msi_irq,
-+				       qcom_pcie_msi_irq_handler,
-+				       IRQF_SHARED, "qcom-pcie-msi", pp);
-+		if (ret) {
-+			dev_err(dev, "cannot request msi irq\n");
-+			return ret;
-+		}
-+	}
-+
-+	ret = dw_pcie_host_init(pp);
-+	if (ret) {
-+		dev_err(dev, "cannot initialize host\n");
-+		return ret;
-+	}
-+
-+	platform_set_drvdata(pdev, pcie);
-+
-+	return 0;
-+}
-+
-+static int qcom_pcie_remove(struct platform_device *pdev)
-+{
-+	struct qcom_pcie *pcie = platform_get_drvdata(pdev);
-+
-+	qcom_ep_reset_assert(pcie);
-+	phy_power_off(pcie->phy);
-+	phy_exit(pcie->phy);
-+	if (pcie->version == PCIE_V0)
-+		qcom_pcie_disable_resources_v0(pcie);
-+	else
-+		qcom_pcie_disable_resources_v1(pcie);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver qcom_pcie_driver = {
-+	.probe = qcom_pcie_probe,
-+	.remove = qcom_pcie_remove,
-+	.driver = {
-+		.name = "qcom-pcie",
-+		.of_match_table = qcom_pcie_match,
-+	},
-+};
-+
-+module_platform_driver(qcom_pcie_driver);
-+
-+MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>");
-+MODULE_DESCRIPTION("Qualcomm PCIe root complex driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:qcom-pcie");
---- a/drivers/pci/host/Makefile
-+++ b/drivers/pci/host/Makefile
-@@ -13,3 +13,4 @@ obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx
- obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
- obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
- obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
-+obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
diff --git a/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
deleted file mode 100644
index 957b054..0000000
--- a/target/linux/ipq806x/patches-4.0/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
+++ /dev/null
@@ -1,260 +0,0 @@
-From 5b40516b2f5fb9b2a7d6d3e2e924f12ec9d183a8 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Tue, 21 Apr 2015 19:01:42 -0700
-Subject: [PATCH 8/9] ARM: dts: qcom: add pcie nodes to ipq806x platforms
-
-qcom-pcie driver now supports version 0 of the controller. This change
-adds the corresponding entries to the IPQ806x dtsi file and
-corresponding platform (AP148).
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/boot/dts/qcom-ipq8064-ap148.dts |  30 ++++++++
- arch/arm/boot/dts/qcom-ipq8064.dtsi      | 124 +++++++++++++++++++++++++++++++
- 2 files changed, 154 insertions(+)
-
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -30,6 +30,22 @@
- 				bias-disable;
- 			};
- 
-+			pcie1_pins: pcie1_pinmux {
-+				mux {
-+					pins = "gpio3";
-+					drive-strength = <2>;
-+					bias-disable;
-+				};
-+			};
-+
-+			pcie2_pins: pcie2_pinmux {
-+				mux {
-+					pins = "gpio48";
-+					drive-strength = <2>;
-+					bias-disable;
-+				};
-+			};
-+
- 			spi_pins: spi_pins {
- 				mux {
- 					pins = "gpio18", "gpio19", "gpio21";
-@@ -109,5 +125,19 @@
- 		sata@29000000 {
- 			status = "ok";
- 		};
-+
-+		pcie0: pci@1b500000 {
-+			status = "ok";
-+			reset-gpio = <&qcom_pinmux 3 0>;
-+			pinctrl-0 = <&pcie1_pins>;
-+			pinctrl-names = "default";
-+		};
-+
-+		pcie1: pci@1b700000 {
-+			status = "ok";
-+			reset-gpio = <&qcom_pinmux 48 0>;
-+			pinctrl-0 = <&pcie2_pins>;
-+			pinctrl-names = "default";
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -30,6 +30,30 @@
- 				bias-disable;
- 			};
- 
-+			pcie1_pins: pcie1_pinmux {
-+				mux {
-+					pins = "gpio3";
-+					drive-strength = <2>;
-+					bias-disable;
-+				};
-+			};
-+
-+			pcie2_pins: pcie2_pinmux {
-+				mux {
-+					pins = "gpio48";
-+					drive-strength = <2>;
-+					bias-disable;
-+				};
-+			};
-+
-+			pcie3_pins: pcie3_pinmux {
-+				mux {
-+					pins = "gpio63";
-+					drive-strength = <2>;
-+					bias-disable;
-+				};
-+			};
-+
- 			spi_pins: spi_pins {
- 				mux {
- 					pins = "gpio18", "gpio19", "gpio21";
-@@ -128,5 +152,26 @@
- 		usb30@1 {
- 			status = "ok";
- 		};
-+
-+		pcie0: pci@1b500000 {
-+			status = "ok";
-+			reset-gpio = <&qcom_pinmux 3 0>;
-+			pinctrl-0 = <&pcie1_pins>;
-+			pinctrl-names = "default";
-+		};
-+
-+		pcie1: pci@1b700000 {
-+			status = "ok";
-+			reset-gpio = <&qcom_pinmux 48 0>;
-+			pinctrl-0 = <&pcie2_pins>;
-+			pinctrl-names = "default";
-+		};
-+
-+		pcie2: pci@1b900000 {
-+			status = "ok";
-+			reset-gpio = <&qcom_pinmux 63 0>;
-+			pinctrl-0 = <&pcie3_pins>;
-+			pinctrl-names = "default";
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -3,6 +3,8 @@
- #include "skeleton.dtsi"
- #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
- #include <dt-bindings/soc/qcom,gsbi.h>
-+#include <dt-bindings/reset/qcom,gcc-ipq806x.h>
-+#include <include/dt-bindings/interrupt-controller/arm-gic.h>
- 
- / {
- 	model = "Qualcomm IPQ8064";
-@@ -291,5 +293,128 @@
- 			#clock-cells = <1>;
- 			#reset-cells = <1>;
- 		};
-+
-+		pcie0: pci@1b500000 {
-+			compatible = "qcom,pcie-v0";
-+			reg = <0x1b500000 0x1000
-+			       0x1b502000 0x80
-+			       0x1b600000 0x100
-+			       0x0ff00000 0x100000>;
-+			reg-names = "dbi", "elbi", "parf", "config";
-+			device_type = "pci";
-+			linux,pci-domain = <0>;
-+			bus-range = <0x00 0xff>;
-+			num-lanes = <1>;
-+			#address-cells = <3>;
-+			#size-cells = <2>;
-+
-+			ranges = <0x81000000 0 0	  0x0fe00000 0 0x00100000   /* downstream I/O */
-+				  0x82000000 0 0x00000000 0x08000000 0 0x07e00000>; /* non-prefetchable memory */
-+
-+			interrupts = <GIC_SPI 35 IRQ_TYPE_NONE>;
-+			interrupt-names = "msi";
-+			#interrupt-cells = <1>;
-+			interrupt-map-mask = <0 0 0 0x7>;
-+			interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
-+					<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
-+					<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
-+					<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
-+
-+			clocks = <&gcc PCIE_A_CLK>,
-+				 <&gcc PCIE_H_CLK>,
-+				 <&gcc PCIE_PHY_CLK>;
-+			clock-names = "core", "iface", "phy";
-+
-+			resets = <&gcc PCIE_ACLK_RESET>,
-+				 <&gcc PCIE_HCLK_RESET>,
-+				 <&gcc PCIE_POR_RESET>,
-+				 <&gcc PCIE_PCI_RESET>,
-+				 <&gcc PCIE_PHY_RESET>;
-+			reset-names = "axi", "ahb", "por", "pci", "phy";
-+
-+			status = "disabled";
-+		};
-+
-+		pcie1: pci@1b700000 {
-+			compatible = "qcom,pcie-v0";
-+			reg = <0x1b700000 0x1000
-+			       0x1b702000 0x80
-+			       0x1b800000 0x100
-+			       0x31f00000 0x100000>;
-+			reg-names = "dbi", "elbi", "parf", "config";
-+			device_type = "pci";
-+			linux,pci-domain = <1>;
-+			bus-range = <0x00 0xff>;
-+			num-lanes = <1>;
-+			#address-cells = <3>;
-+			#size-cells = <2>;
-+
-+			ranges = <0x81000000 0 0	  0x31e00000 0 0x00100000   /* downstream I/O */
-+				  0x82000000 0 0x00000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */
-+
-+			interrupts = <GIC_SPI 57 IRQ_TYPE_NONE>;
-+			interrupt-names = "msi";
-+			#interrupt-cells = <1>;
-+			interrupt-map-mask = <0 0 0 0x7>;
-+			interrupt-map = <0 0 0 1 &intc 0 58 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
-+					<0 0 0 2 &intc 0 59 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
-+					<0 0 0 3 &intc 0 60 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
-+					<0 0 0 4 &intc 0 61 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
-+
-+			clocks = <&gcc PCIE_1_A_CLK>,
-+				 <&gcc PCIE_1_H_CLK>,
-+				 <&gcc PCIE_1_PHY_CLK>;
-+			clock-names = "core", "iface", "phy";
-+
-+			resets = <&gcc PCIE_1_ACLK_RESET>,
-+				 <&gcc PCIE_1_HCLK_RESET>,
-+				 <&gcc PCIE_1_POR_RESET>,
-+				 <&gcc PCIE_1_PCI_RESET>,
-+				 <&gcc PCIE_1_PHY_RESET>;
-+			reset-names = "axi", "ahb", "por", "pci", "phy";
-+
-+			status = "disabled";
-+		};
-+
-+		pcie2: pci@1b900000 {
-+			compatible = "qcom,pcie-v0";
-+			reg = <0x1b900000 0x1000
-+			       0x1b902000 0x80
-+			       0x1ba00000 0x100
-+			       0x35f00000 0x100000>;
-+			reg-names = "dbi", "elbi", "parf", "config";
-+			device_type = "pci";
-+			linux,pci-domain = <2>;
-+			bus-range = <0x00 0xff>;
-+			num-lanes = <1>;
-+			#address-cells = <3>;
-+			#size-cells = <2>;
-+
-+			ranges = <0x81000000 0 0	  0x35e00000 0 0x00100000   /* downstream I/O */
-+				  0x82000000 0 0x00000000 0x32000000 0 0x03e00000>; /* non-prefetchable memory */
-+
-+			interrupts = <GIC_SPI 71 IRQ_TYPE_NONE>;
-+			interrupt-names = "msi";
-+			#interrupt-cells = <1>;
-+			interrupt-map-mask = <0 0 0 0x7>;
-+			interrupt-map = <0 0 0 1 &intc 0 72 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
-+					<0 0 0 2 &intc 0 73 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
-+					<0 0 0 3 &intc 0 74 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
-+					<0 0 0 4 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
-+
-+			clocks = <&gcc PCIE_2_A_CLK>,
-+				 <&gcc PCIE_2_H_CLK>,
-+				 <&gcc PCIE_2_PHY_CLK>;
-+			clock-names = "core", "iface", "phy";
-+
-+			resets = <&gcc PCIE_2_ACLK_RESET>,
-+				 <&gcc PCIE_2_HCLK_RESET>,
-+				 <&gcc PCIE_2_POR_RESET>,
-+				 <&gcc PCIE_2_PCI_RESET>,
-+				 <&gcc PCIE_2_PHY_RESET>;
-+			reset-names = "axi", "ahb", "por", "pci", "phy";
-+
-+			status = "disabled";
-+		};
- 	};
- };
diff --git a/target/linux/ipq806x/patches-4.0/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch b/target/linux/ipq806x/patches-4.0/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch
deleted file mode 100644
index e2d3135..0000000
--- a/target/linux/ipq806x/patches-4.0/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From f004aa1dec6e2e206be025de15b115d60f2b21e3 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Tue, 21 Apr 2015 19:09:07 -0700
-Subject: [PATCH 9/9] ARM: qcom: automatically select PCI_DOMAINS if PCI is
- enabled
-
-If multiple PCIe devices are present in the system, the kernel will
-panic at boot time when trying to scan the PCI buses. This happens on
-IPQ806x based platforms, which has 3 PCIe ports.
-
-Enabling this option allows the kernel to assign the pci-domains
-according to the device-tree content. This allows multiple PCIe
-controllers to coexist in the system.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/mach-qcom/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/arm/mach-qcom/Kconfig
-+++ b/arch/arm/mach-qcom/Kconfig
-@@ -5,6 +5,7 @@ menuconfig ARCH_QCOM
- 	select ARM_AMBA
- 	select PINCTRL
- 	select QCOM_SCM if SMP
-+	select PCI_DOMAINS if PCI
- 	help
- 	  Support for Qualcomm's devicetree based systems.
- 
diff --git a/target/linux/ipq806x/patches-4.0/121-mfd-qcom_rpm-Add-support-for-IPQ8064.patch b/target/linux/ipq806x/patches-4.0/121-mfd-qcom_rpm-Add-support-for-IPQ8064.patch
deleted file mode 100644
index e5e9e4e..0000000
--- a/target/linux/ipq806x/patches-4.0/121-mfd-qcom_rpm-Add-support-for-IPQ8064.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 4d54b0adfa67476e6509bc8646b9dbac642e8a29 Mon Sep 17 00:00:00 2001
-From: Josh Cartwright <joshc@codeaurora.org>
-Date: Thu, 26 Mar 2015 11:29:26 -0700
-Subject: [PATCH] mfd: qcom_rpm: Add support for IPQ8064
-
-The IPQ8064 also includes an RPM following the same message structure as
-other chips.  In addition, it supports a few new resource types to
-support the NSS fabric clocks and the SMB208/SMB209 regulators found on
-the reference boards.
-
-Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-Signed-off-by: Lee Jones <lee.jones@linaro.org>
----
- drivers/mfd/qcom_rpm.c | 41 +++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 41 insertions(+)
-
---- a/drivers/mfd/qcom_rpm.c
-+++ b/drivers/mfd/qcom_rpm.c
-@@ -323,10 +323,51 @@ static const struct qcom_rpm_data msm896
- 	.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
- };
- 
-+static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = {
-+	[QCOM_RPM_CXO_CLK] =			{ 25, 9, 5, 1 },
-+	[QCOM_RPM_PXO_CLK] =			{ 26, 10, 6, 1 },
-+	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 27, 11, 8, 1 },
-+	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 28, 12, 9, 1 },
-+	[QCOM_RPM_NSS_FABRIC_0_CLK] =		{ 29, 13, 10, 1 },
-+	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 30, 14, 11, 1 },
-+	[QCOM_RPM_SFPB_CLK] =			{ 31, 15, 12, 1 },
-+	[QCOM_RPM_CFPB_CLK] =			{ 32, 16, 13, 1 },
-+	[QCOM_RPM_NSS_FABRIC_1_CLK] =		{ 33, 17, 14, 1 },
-+	[QCOM_RPM_EBI1_CLK] =			{ 34, 18, 16, 1 },
-+	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 35, 19, 18, 2 },
-+	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 37, 20, 19, 3 },
-+	[QCOM_RPM_APPS_FABRIC_IOCTL] =		{ 40, 21, 20, 1 },
-+	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 41, 22, 21, 12 },
-+	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 53, 23, 22, 2 },
-+	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 55, 24, 23, 3 },
-+	[QCOM_RPM_SYS_FABRIC_IOCTL] =		{ 58, 25, 24, 1 },
-+	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 59, 26, 25, 30 },
-+	[QCOM_RPM_MM_FABRIC_HALT] =		{ 89, 27, 26, 2 },
-+	[QCOM_RPM_MM_FABRIC_MODE] =		{ 91, 28, 27, 3 },
-+	[QCOM_RPM_MM_FABRIC_IOCTL] =		{ 94, 29, 28, 1 },
-+	[QCOM_RPM_MM_FABRIC_ARB] =		{ 95, 30, 29, 2 },
-+	[QCOM_RPM_CXO_BUFFERS] =		{ 209, 33, 31, 1 },
-+	[QCOM_RPM_USB_OTG_SWITCH] =		{ 210, 34, 32, 1 },
-+	[QCOM_RPM_HDMI_SWITCH] =		{ 211, 35, 33, 1 },
-+	[QCOM_RPM_DDR_DMM] =			{ 212, 36, 34, 2 },
-+	[QCOM_RPM_VDDMIN_GPIO] =		{ 215, 40, 39, 1 },
-+	[QCOM_RPM_SMB208_S1a] =			{ 216, 41, 90, 2 },
-+	[QCOM_RPM_SMB208_S1b] =			{ 218, 43, 91, 2 },
-+	[QCOM_RPM_SMB208_S2a] =			{ 220, 45, 92, 2 },
-+	[QCOM_RPM_SMB208_S2b] =			{ 222, 47, 93, 2 },
-+};
-+
-+static const struct qcom_rpm_data ipq806x_template = {
-+	.version = 3,
-+	.resource_table = ipq806x_rpm_resource_table,
-+	.n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table),
-+};
-+
- static const struct of_device_id qcom_rpm_of_match[] = {
- 	{ .compatible = "qcom,rpm-apq8064", .data = &apq8064_template },
- 	{ .compatible = "qcom,rpm-msm8660", .data = &msm8660_template },
- 	{ .compatible = "qcom,rpm-msm8960", .data = &msm8960_template },
-+	{ .compatible = "qcom,rpm-ipq8064", .data = &ipq806x_template },
- 	{ }
- };
- MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
diff --git a/target/linux/ipq806x/patches-4.0/123-mfd-devicetree-qcom_rpm-Document-IPQ8064-resources.patch b/target/linux/ipq806x/patches-4.0/123-mfd-devicetree-qcom_rpm-Document-IPQ8064-resources.patch
deleted file mode 100644
index c8a9f3f..0000000
--- a/target/linux/ipq806x/patches-4.0/123-mfd-devicetree-qcom_rpm-Document-IPQ8064-resources.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 30bc3aa5c4ed3072bdff7d915772df1b91307ed4 Mon Sep 17 00:00:00 2001
-From: Josh Cartwright <joshc@codeaurora.org>
-Date: Thu, 26 Mar 2015 11:29:25 -0700
-Subject: [PATCH] mfd: devicetree: qcom_rpm: Document IPQ8064 resources
-
-The IPQ8064 SoC has several RPM-controlled resources, an NSS fabrick
-clock and four regulator resources.  Provide definitions for them.
-
-Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
-[sboyd@codeaurora.org: Drop regulator part of binding]
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-Signed-off-by: Lee Jones <lee.jones@linaro.org>
----
- Documentation/devicetree/bindings/mfd/qcom-rpm.txt | 1 +
- include/dt-bindings/mfd/qcom-rpm.h                 | 6 ++++++
- 2 files changed, 7 insertions(+)
-
---- a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
-+++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
-@@ -12,6 +12,7 @@ frequencies.
- 		    "qcom,rpm-apq8064"
- 		    "qcom,rpm-msm8660"
- 		    "qcom,rpm-msm8960"
-+		    "qcom,rpm-ipq8064"
- 
- - reg:
- 	Usage: required
---- a/include/dt-bindings/mfd/qcom-rpm.h
-+++ b/include/dt-bindings/mfd/qcom-rpm.h
-@@ -141,6 +141,12 @@
- #define QCOM_RPM_SYS_FABRIC_MODE		131
- #define QCOM_RPM_USB_OTG_SWITCH			132
- #define QCOM_RPM_VDDMIN_GPIO			133
-+#define QCOM_RPM_NSS_FABRIC_0_CLK		134
-+#define QCOM_RPM_NSS_FABRIC_1_CLK		135
-+#define QCOM_RPM_SMB208_S1a			136
-+#define QCOM_RPM_SMB208_S1b			137
-+#define QCOM_RPM_SMB208_S2a			138
-+#define QCOM_RPM_SMB208_S2b			139
- 
- /*
-  * Constants used to select force mode for regulators.
diff --git a/target/linux/ipq806x/patches-4.0/126-add-rpm-to-ipq8064-dts.patch b/target/linux/ipq806x/patches-4.0/126-add-rpm-to-ipq8064-dts.patch
deleted file mode 100644
index 4fb62dd..0000000
--- a/target/linux/ipq806x/patches-4.0/126-add-rpm-to-ipq8064-dts.patch
+++ /dev/null
@@ -1,87 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -2,6 +2,7 @@
- 
- #include "skeleton.dtsi"
- #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
-+#include <dt-bindings/mfd/qcom-rpm.h>
- #include <dt-bindings/soc/qcom,gsbi.h>
- #include <dt-bindings/reset/qcom,gcc-ipq806x.h>
- #include <include/dt-bindings/interrupt-controller/arm-gic.h>
-@@ -76,6 +77,63 @@
- 		ranges;
- 		compatible = "simple-bus";
- 
-+		rpm@108000 {
-+			compatible = "qcom,rpm-ipq8064";
-+			reg = <0x108000 0x1000>;
-+			qcom,ipc = <&l2cc 0x8 2>;
-+
-+			interrupts = <0 19 0>,
-+				     <0 21 0>,
-+				     <0 22 0>;
-+			interrupt-names = "ack",
-+					  "err",
-+					  "wakeup";
-+
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+
-+			smb208_s1a: smb208-s1a {
-+				compatible = "qcom,rpm-smb208";
-+				reg = <QCOM_RPM_SMB208_S1a>;
-+
-+				regulator-min-microvolt = <1050000>;
-+				regulator-max-microvolt = <1150000>;
-+
-+				qcom,switch-mode-frequency = <1200000>;
-+
-+			};
-+
-+			smb208_s1b: smb208-s1b {
-+				compatible = "qcom,rpm-smb208";
-+				reg = <QCOM_RPM_SMB208_S1b>;
-+
-+				regulator-min-microvolt = <1050000>;
-+				regulator-max-microvolt = <1150000>;
-+
-+				qcom,switch-mode-frequency = <1200000>;
-+			};
-+
-+			smb208_s2a: smb208-s2a {
-+				compatible = "qcom,rpm-smb208";
-+				reg = <QCOM_RPM_SMB208_S2a>;
-+
-+				regulator-min-microvolt = < 800000>;
-+				regulator-max-microvolt = <1250000>;
-+
-+				qcom,switch-mode-frequency = <1200000>;
-+			};
-+
-+			smb208_s2b: smb208-s2b {
-+				compatible = "qcom,rpm-smb208";
-+				reg = <QCOM_RPM_SMB208_S2b>;
-+
-+				regulator-min-microvolt = < 800000>;
-+				regulator-max-microvolt = <1250000>;
-+
-+				qcom,switch-mode-frequency = <1200000>;
-+			};
-+		};
-+
- 		qcom_pinmux: pinmux@800000 {
- 			compatible = "qcom,ipq8064-pinctrl";
- 			reg = <0x800000 0x4000>;
-@@ -120,6 +178,12 @@
- 			reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
- 		};
- 
-+		l2cc: clock-controller@2011000 {
-+			compatible = "qcom,kpss-gcc", "syscon";
-+			reg = <0x2011000 0x1000>;
-+			clock-output-names = "acpu_l2_aux";
-+ 		};
-+ 
- 		saw0: regulator@2089000 {
- 			compatible = "qcom,saw2";
- 			reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
diff --git a/target/linux/ipq806x/patches-4.0/133-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-4.0/133-ARM-Add-Krait-L2-register-accessor-functions.patch
deleted file mode 100644
index 36a92c8..0000000
--- a/target/linux/ipq806x/patches-4.0/133-ARM-Add-Krait-L2-register-accessor-functions.patch
+++ /dev/null
@@ -1,144 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,01/13] ARM: Add Krait L2 register accessor functions
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063051
-Message-Id: <1426920332-9340-2-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>,
-	Mark Rutland <mark.rutland@arm.com>, Russell King <linux@arm.linux.org.uk>,
-	Courtney Cavin <courtney.cavin@sonymobile.com>
-Date: Fri, 20 Mar 2015 23:45:20 -0700
-
-Krait CPUs have a handful of L2 cache controller registers that
-live behind a cp15 based indirection register. First you program
-the indirection register (l2cpselr) to point the L2 'window'
-register (l2cpdr) at what you want to read/write.  Then you
-read/write the 'window' register to do what you want. The
-l2cpselr register is not banked per-cpu so we must lock around
-accesses to it to prevent other CPUs from re-pointing l2cpdr
-underneath us.
-
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Russell King <linux@arm.linux.org.uk>
-Cc: Courtney Cavin <courtney.cavin@sonymobile.com>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-arch/arm/common/Kconfig                   |  3 ++
- arch/arm/common/Makefile                  |  1 +
- arch/arm/common/krait-l2-accessors.c      | 58 +++++++++++++++++++++++++++++++
- arch/arm/include/asm/krait-l2-accessors.h | 20 +++++++++++
- 4 files changed, 82 insertions(+)
- create mode 100644 arch/arm/common/krait-l2-accessors.c
- create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
-
---- a/arch/arm/common/Kconfig
-+++ b/arch/arm/common/Kconfig
-@@ -9,6 +9,9 @@ config DMABOUNCE
- 	bool
- 	select ZONE_DMA
- 
-+config KRAIT_L2_ACCESSORS
-+	bool
-+
- config SHARP_LOCOMO
- 	bool
- 
---- a/arch/arm/common/Makefile
-+++ b/arch/arm/common/Makefile
-@@ -7,6 +7,7 @@ obj-y				+= firmware.o
- obj-$(CONFIG_ICST)		+= icst.o
- obj-$(CONFIG_SA1111)		+= sa1111.o
- obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
-+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
- obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
- obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
- obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
---- /dev/null
-+++ b/arch/arm/common/krait-l2-accessors.c
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/spinlock.h>
-+#include <linux/export.h>
-+
-+#include <asm/barrier.h>
-+#include <asm/krait-l2-accessors.h>
-+
-+static DEFINE_RAW_SPINLOCK(krait_l2_lock);
-+
-+void krait_set_l2_indirect_reg(u32 addr, u32 val)
-+{
-+	unsigned long flags;
-+
-+	raw_spin_lock_irqsave(&krait_l2_lock, flags);
-+	/*
-+	 * Select the L2 window by poking l2cpselr, then write to the window
-+	 * via l2cpdr.
-+	 */
-+	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
-+	isb();
-+	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
-+	isb();
-+
-+	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
-+}
-+EXPORT_SYMBOL(krait_set_l2_indirect_reg);
-+
-+u32 krait_get_l2_indirect_reg(u32 addr)
-+{
-+	u32 val;
-+	unsigned long flags;
-+
-+	raw_spin_lock_irqsave(&krait_l2_lock, flags);
-+	/*
-+	 * Select the L2 window by poking l2cpselr, then read from the window
-+	 * via l2cpdr.
-+	 */
-+	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
-+	isb();
-+	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
-+
-+	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
-+
-+	return val;
-+}
-+EXPORT_SYMBOL(krait_get_l2_indirect_reg);
---- /dev/null
-+++ b/arch/arm/include/asm/krait-l2-accessors.h
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
-+#define __ASMARM_KRAIT_L2_ACCESSORS_H
-+
-+extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
-+extern u32 krait_get_l2_indirect_reg(u32 addr);
-+
-+#endif
diff --git a/target/linux/ipq806x/patches-4.0/134-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-4.0/134-clk-mux-Split-out-register-accessors-for-reuse.patch
deleted file mode 100644
index 3a475fb..0000000
--- a/target/linux/ipq806x/patches-4.0/134-clk-mux-Split-out-register-accessors-for-reuse.patch
+++ /dev/null
@@ -1,192 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,02/13] clk: mux: Split out register accessors for reuse
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063111
-Message-Id: <1426920332-9340-3-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:21 -0700
-
-We want to reuse the logic in clk-mux.c for other clock drivers
-that don't use readl as register accessors. Fortunately, there
-really isn't much to the mux code besides the table indirection
-and quirk flags if you assume any bit shifting and masking has
-been done already. Pull that logic out into reusable functions
-that operate on an optional table and some flags so that other
-drivers can use the same logic.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-drivers/clk/clk-mux.c        | 76 +++++++++++++++++++++++++++-----------------
- include/linux/clk-provider.h |  9 ++++--
- 2 files changed, 54 insertions(+), 31 deletions(-)
-
---- a/drivers/clk/clk-mux.c
-+++ b/drivers/clk/clk-mux.c
-@@ -29,35 +29,24 @@
- 
- #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
- 
--static u8 clk_mux_get_parent(struct clk_hw *hw)
-+unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
-+				unsigned int *table, unsigned long flags)
- {
--	struct clk_mux *mux = to_clk_mux(hw);
- 	int num_parents = __clk_get_num_parents(hw->clk);
--	u32 val;
- 
--	/*
--	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
--	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
--	 * to 0x7 (index starts at one)
--	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
--	 * val = 0x4 really means "bit 2, index starts at bit 0"
--	 */
--	val = clk_readl(mux->reg) >> mux->shift;
--	val &= mux->mask;
--
--	if (mux->table) {
-+	if (table) {
- 		int i;
- 
- 		for (i = 0; i < num_parents; i++)
--			if (mux->table[i] == val)
-+			if (table[i] == val)
- 				return i;
- 		return -EINVAL;
- 	}
- 
--	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
-+	if (val && (flags & CLK_MUX_INDEX_BIT))
- 		val = ffs(val) - 1;
- 
--	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
-+	if (val && (flags & CLK_MUX_INDEX_ONE))
- 		val--;
- 
- 	if (val >= num_parents)
-@@ -65,24 +54,53 @@ static u8 clk_mux_get_parent(struct clk_
- 
- 	return val;
- }
-+EXPORT_SYMBOL_GPL(clk_mux_get_parent);
- 
--static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
-+static u8 _clk_mux_get_parent(struct clk_hw *hw)
- {
- 	struct clk_mux *mux = to_clk_mux(hw);
- 	u32 val;
--	unsigned long flags = 0;
- 
--	if (mux->table)
--		index = mux->table[index];
-+	/*
-+	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
-+	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
-+	 * to 0x7 (index starts at one)
-+	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
-+	 * val = 0x4 really means "bit 2, index starts at bit 0"
-+	 */
-+	val = clk_readl(mux->reg) >> mux->shift;
-+	val &= mux->mask;
-+
-+	return clk_mux_get_parent(hw, val, mux->table, mux->flags);
-+}
- 
--	else {
--		if (mux->flags & CLK_MUX_INDEX_BIT)
--			index = 1 << index;
-+unsigned int clk_mux_reindex(u8 index, unsigned int *table,
-+			     unsigned long flags)
-+{
-+	unsigned int val = index;
- 
--		if (mux->flags & CLK_MUX_INDEX_ONE)
--			index++;
-+	if (table) {
-+		val = table[val];
-+	} else {
-+		if (flags & CLK_MUX_INDEX_BIT)
-+			val = 1 << index;
-+
-+		if (flags & CLK_MUX_INDEX_ONE)
-+			val++;
- 	}
- 
-+	return val;
-+}
-+EXPORT_SYMBOL_GPL(clk_mux_reindex);
-+
-+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
-+{
-+	struct clk_mux *mux = to_clk_mux(hw);
-+	u32 val;
-+	unsigned long flags = 0;
-+
-+	index = clk_mux_reindex(index, mux->table, mux->flags);
-+
- 	if (mux->lock)
- 		spin_lock_irqsave(mux->lock, flags);
- 
-@@ -102,21 +120,21 @@ static int clk_mux_set_parent(struct clk
- }
- 
- const struct clk_ops clk_mux_ops = {
--	.get_parent = clk_mux_get_parent,
-+	.get_parent = _clk_mux_get_parent,
- 	.set_parent = clk_mux_set_parent,
- 	.determine_rate = __clk_mux_determine_rate,
- };
- EXPORT_SYMBOL_GPL(clk_mux_ops);
- 
- const struct clk_ops clk_mux_ro_ops = {
--	.get_parent = clk_mux_get_parent,
-+	.get_parent = _clk_mux_get_parent,
- };
- EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
- 
- struct clk *clk_register_mux_table(struct device *dev, const char *name,
- 		const char **parent_names, u8 num_parents, unsigned long flags,
- 		void __iomem *reg, u8 shift, u32 mask,
--		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
-+		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock)
- {
- 	struct clk_mux *mux;
- 	struct clk *clk;
---- a/include/linux/clk-provider.h
-+++ b/include/linux/clk-provider.h
-@@ -409,7 +409,7 @@ void clk_unregister_divider(struct clk *
- struct clk_mux {
- 	struct clk_hw	hw;
- 	void __iomem	*reg;
--	u32		*table;
-+	unsigned int	*table;
- 	u32		mask;
- 	u8		shift;
- 	u8		flags;
-@@ -425,6 +425,11 @@ struct clk_mux {
- extern const struct clk_ops clk_mux_ops;
- extern const struct clk_ops clk_mux_ro_ops;
- 
-+unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
-+				unsigned int *table, unsigned long flags);
-+unsigned int clk_mux_reindex(u8 index, unsigned int *table,
-+			     unsigned long flags);
-+
- struct clk *clk_register_mux(struct device *dev, const char *name,
- 		const char **parent_names, u8 num_parents, unsigned long flags,
- 		void __iomem *reg, u8 shift, u8 width,
-@@ -433,7 +438,7 @@ struct clk *clk_register_mux(struct devi
- struct clk *clk_register_mux_table(struct device *dev, const char *name,
- 		const char **parent_names, u8 num_parents, unsigned long flags,
- 		void __iomem *reg, u8 shift, u32 mask,
--		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
-+		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock);
- 
- void clk_unregister_mux(struct clk *clk);
- 
diff --git a/target/linux/ipq806x/patches-4.0/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch b/target/linux/ipq806x/patches-4.0/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch
deleted file mode 100644
index 52af413..0000000
--- a/target/linux/ipq806x/patches-4.0/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch
+++ /dev/null
@@ -1,130 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during
-	set_rate
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063271
-Message-Id: <1426920332-9340-4-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:22 -0700
-
-If a clock is on and we call clk_set_rate() on it we may get into
-a situation where the clock temporarily increases in rate
-dramatically while we walk the tree and call .set_rate() ops. For
-example, consider a case where a PLL feeds into a divider.
-Initially the divider is set to divide by 1 and the PLL is
-running fairly slow (100MHz). The downstream consumer of the
-divider output can only handle rates =< 400 MHz, but the divider
-can only choose between divisors of 1 and 4.
-
- +-----+   +----------------+
- | PLL |-->| div 1 or div 4 |---> consumer device
- +-----+   +----------------+
-
-To achieve a rate of 400MHz on the output of the divider, we
-would have to set the rate of the PLL to 1.6 GHz and then divide
-it by 4. The current code would set the PLL to 1.6GHz first while
-the divider is still set to 1, thus causing the downstream
-consumer of the clock to receive a few clock cycles of 1.6GHz
-clock (far beyond it's maximum acceptable rate). We should be
-changing the divider first before increasing the PLL rate to
-avoid this problem.
-
-Therefore, set the rate of any child clocks that are increasing
-in rate from their current rate so that they can increase their
-dividers if necessary. We assume that there isn't such a thing as
-minimum rate requirements.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-drivers/clk/clk.c | 34 ++++++++++++++++++++++------------
- 1 file changed, 22 insertions(+), 12 deletions(-)
-
---- a/drivers/clk/clk.c
-+++ b/drivers/clk/clk.c
-@@ -1696,21 +1696,24 @@ static struct clk_core *clk_propagate_ra
-  * walk down a subtree and set the new rates notifying the rate
-  * change on the way
-  */
--static void clk_change_rate(struct clk_core *clk)
-+static void
-+clk_change_rate(struct clk_core *clk, unsigned long best_parent_rate)
- {
- 	struct clk_core *child;
- 	struct hlist_node *tmp;
- 	unsigned long old_rate;
--	unsigned long best_parent_rate = 0;
- 	bool skip_set_rate = false;
- 	struct clk_core *old_parent;
- 
--	old_rate = clk->rate;
-+	hlist_for_each_entry(child, &clk->children, child_node) {
-+		/* Skip children who will be reparented to another clock */
-+		if (child->new_parent && child->new_parent != clk)
-+			continue;
-+		if (child->new_rate > child->rate)
-+			clk_change_rate(child, clk->new_rate);
-+	}
- 
--	if (clk->new_parent)
--		best_parent_rate = clk->new_parent->rate;
--	else if (clk->parent)
--		best_parent_rate = clk->parent->rate;
-+	old_rate = clk->rate;
- 
- 	if (clk->new_parent && clk->new_parent != clk->parent) {
- 		old_parent = __clk_set_parent_before(clk, clk->new_parent);
-@@ -1730,7 +1733,7 @@ static void clk_change_rate(struct clk_c
- 	if (!skip_set_rate && clk->ops->set_rate)
- 		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
- 
--	clk->rate = clk_recalc(clk, best_parent_rate);
-+	clk->rate = clk->new_rate;
- 
- 	if (clk->notifier_count && old_rate != clk->rate)
- 		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
-@@ -1743,12 +1746,13 @@ static void clk_change_rate(struct clk_c
- 		/* Skip children who will be reparented to another clock */
- 		if (child->new_parent && child->new_parent != clk)
- 			continue;
--		clk_change_rate(child);
-+		if (child->new_rate != child->rate)
-+			clk_change_rate(child, clk->new_rate);
- 	}
- 
- 	/* handle the new child who might not be in clk->children yet */
--	if (clk->new_child)
--		clk_change_rate(clk->new_child);
-+	if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate)
-+		clk_change_rate(clk->new_child, clk->new_rate);
- }
- 
- static int clk_core_set_rate_nolock(struct clk_core *clk,
-@@ -1757,6 +1761,7 @@ static int clk_core_set_rate_nolock(stru
- 	struct clk_core *top, *fail_clk;
- 	unsigned long rate = req_rate;
- 	int ret = 0;
-+	unsigned long parent_rate;
- 
- 	if (!clk)
- 		return 0;
-@@ -1782,8 +1787,13 @@ static int clk_core_set_rate_nolock(stru
- 		return -EBUSY;
- 	}
- 
-+	if (top->parent)
-+		parent_rate = top->parent->rate;
-+	else
-+		parent_rate = 0;
-+
- 	/* change the rates */
--	clk_change_rate(top);
-+	clk_change_rate(top, parent_rate);
- 
- 	clk->req_rate = req_rate;
- 
diff --git a/target/linux/ipq806x/patches-4.0/136-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.0/136-clk-Add-safe-switch-hook.patch
deleted file mode 100644
index a5d9c41..0000000
--- a/target/linux/ipq806x/patches-4.0/136-clk-Add-safe-switch-hook.patch
+++ /dev/null
@@ -1,164 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,04/13] clk: Add safe switch hook
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063211
-Message-Id: <1426920332-9340-5-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:23 -0700
-
-Sometimes clocks can't accept their parent source turning off
-while the source is reprogrammed to a different rate. Most
-notably CPU clocks require a way to switch away from the current
-PLL they're running on, reprogram that PLL to a new rate, and
-then switch back to the PLL with the new rate once they're done.
-Add a hook that drivers can implement allowing them to return a
-'safe parent' that they can switch their parent to while the
-upstream source is reprogrammed to support this.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-This patch is good enough for Krait, but soon I'll need to 
-support a "safe rate" where we ask a clock what rate it needs to be running
-at to be sure it's within voltage constraints. Right now safe parent
-handles that problem on Krait, but on other platforms it won't work.
-
- drivers/clk/clk.c            | 61 ++++++++++++++++++++++++++++++++++++++------
- include/linux/clk-provider.h |  1 +
- 2 files changed, 54 insertions(+), 8 deletions(-)
-
---- a/drivers/clk/clk.c
-+++ b/drivers/clk/clk.c
-@@ -56,9 +56,12 @@ struct clk_core {
- 	struct clk_core		**parents;
- 	u8			num_parents;
- 	u8			new_parent_index;
-+	u8			safe_parent_index;
- 	unsigned long		rate;
- 	unsigned long		req_rate;
-+	unsigned long		old_rate;
- 	unsigned long		new_rate;
-+	struct clk_core		*safe_parent;
- 	struct clk_core		*new_parent;
- 	struct clk_core		*new_child;
- 	unsigned long		flags;
-@@ -1557,7 +1560,8 @@ out:
- static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
- 			     struct clk_core *new_parent, u8 p_index)
- {
--	struct clk_core *child;
-+	struct clk_core *child, *parent;
-+	struct clk_hw *parent_hw;
- 
- 	clk->new_rate = new_rate;
- 	clk->new_parent = new_parent;
-@@ -1567,6 +1571,18 @@ static void clk_calc_subtree(struct clk_
- 	if (new_parent && new_parent != clk->parent)
- 		new_parent->new_child = clk;
- 
-+	if (clk->ops->get_safe_parent) {
-+		parent_hw = clk->ops->get_safe_parent(clk->hw);
-+		if (parent_hw) {
-+			parent = parent_hw->core;
-+			p_index = clk_fetch_parent_index(clk, parent);
-+			clk->safe_parent_index = p_index;
-+			clk->safe_parent = parent;
-+		}
-+	} else {
-+		clk->safe_parent = NULL;
-+	}
-+
- 	hlist_for_each_entry(child, &clk->children, child_node) {
- 		child->new_rate = clk_recalc(child, new_rate);
- 		clk_calc_subtree(child, child->new_rate, NULL, 0);
-@@ -1662,14 +1678,43 @@ static struct clk_core *clk_propagate_ra
- 						  unsigned long event)
- {
- 	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
-+	struct clk_core *old_parent;
- 	int ret = NOTIFY_DONE;
- 
--	if (clk->rate == clk->new_rate)
-+	if (clk->rate == clk->new_rate && event != POST_RATE_CHANGE)
- 		return NULL;
- 
-+	switch (event) {
-+	case PRE_RATE_CHANGE:
-+		if (clk->safe_parent)
-+			clk->ops->set_parent(clk->hw, clk->safe_parent_index);
-+		clk->old_rate = clk->rate;
-+		break;
-+	case POST_RATE_CHANGE:
-+		if (clk->safe_parent) {
-+			old_parent = __clk_set_parent_before(clk,
-+							     clk->new_parent);
-+			if (clk->ops->set_rate_and_parent) {
-+				clk->ops->set_rate_and_parent(clk->hw,
-+						clk->new_rate,
-+						clk->new_parent ?
-+						clk->new_parent->rate : 0,
-+						clk->new_parent_index);
-+			} else if (clk->ops->set_parent) {
-+				clk->ops->set_parent(clk->hw,
-+						clk->new_parent_index);
-+			}
-+			__clk_set_parent_after(clk, clk->new_parent,
-+					       old_parent);
-+		}
-+		break;
-+	}
-+
- 	if (clk->notifier_count) {
--		ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
--		if (ret & NOTIFY_STOP_MASK)
-+		if (event != POST_RATE_CHANGE || clk->old_rate != clk->rate)
-+			ret = __clk_notify(clk, event, clk->old_rate,
-+					   clk->new_rate);
-+		if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE)
- 			fail_clk = clk;
- 	}
- 
-@@ -1715,7 +1760,8 @@ clk_change_rate(struct clk_core *clk, un
- 
- 	old_rate = clk->rate;
- 
--	if (clk->new_parent && clk->new_parent != clk->parent) {
-+	if (clk->new_parent && clk->new_parent != clk->parent &&
-+			!clk->safe_parent) {
- 		old_parent = __clk_set_parent_before(clk, clk->new_parent);
- 
- 		if (clk->ops->set_rate_and_parent) {
-@@ -1735,9 +1781,6 @@ clk_change_rate(struct clk_core *clk, un
- 
- 	clk->rate = clk->new_rate;
- 
--	if (clk->notifier_count && old_rate != clk->rate)
--		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
--
- 	/*
- 	 * Use safe iteration, as change_rate can actually swap parents
- 	 * for certain clock types.
-@@ -1797,6 +1840,8 @@ static int clk_core_set_rate_nolock(stru
- 
- 	clk->req_rate = req_rate;
- 
-+	clk_propagate_rate_change(top, POST_RATE_CHANGE);
-+
- 	return ret;
- }
- 
---- a/include/linux/clk-provider.h
-+++ b/include/linux/clk-provider.h
-@@ -183,6 +183,7 @@ struct clk_ops {
- 					  struct clk_hw **best_parent_hw);
- 	int		(*set_parent)(struct clk_hw *hw, u8 index);
- 	u8		(*get_parent)(struct clk_hw *hw);
-+	struct clk_hw	*(*get_safe_parent)(struct clk_hw *hw);
- 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
- 				    unsigned long parent_rate);
- 	int		(*set_rate_and_parent)(struct clk_hw *hw,
diff --git a/target/linux/ipq806x/patches-4.0/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-4.0/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch
deleted file mode 100644
index 6fad6e8..0000000
--- a/target/linux/ipq806x/patches-4.0/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch
+++ /dev/null
@@ -1,351 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,05/13] clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063261
-Message-Id: <1426920332-9340-6-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:24 -0700
-
-HFPLLs are the main frequency source for Krait CPU clocks. Add
-support for changing the rate of these PLLs.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-I'd really like to get rid of __clk_hfpll_init_once() if possible...
-
- drivers/clk/qcom/Makefile    |   1 +
- drivers/clk/qcom/clk-hfpll.c | 253 +++++++++++++++++++++++++++++++++++++++++++
- drivers/clk/qcom/clk-hfpll.h |  54 +++++++++
- 3 files changed, 308 insertions(+)
- create mode 100644 drivers/clk/qcom/clk-hfpll.c
- create mode 100644 drivers/clk/qcom/clk-hfpll.h
-
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o
- clk-qcom-y += clk-branch.o
- clk-qcom-y += clk-regmap-divider.o
- clk-qcom-y += clk-regmap-mux.o
-+clk-qcom-y += clk-hfpll.o
- clk-qcom-y += reset.o
- 
- obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
---- /dev/null
-+++ b/drivers/clk/qcom/clk-hfpll.c
-@@ -0,0 +1,253 @@
-+/*
-+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/export.h>
-+#include <linux/regmap.h>
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/clk-provider.h>
-+#include <linux/spinlock.h>
-+
-+#include "clk-regmap.h"
-+#include "clk-hfpll.h"
-+
-+#define PLL_OUTCTRL	BIT(0)
-+#define PLL_BYPASSNL	BIT(1)
-+#define PLL_RESET_N	BIT(2)
-+
-+/* Initialize a HFPLL at a given rate and enable it. */
-+static void __clk_hfpll_init_once(struct clk_hw *hw)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+
-+	if (likely(h->init_done))
-+		return;
-+
-+	/* Configure PLL parameters for integer mode. */
-+	if (hd->config_val)
-+		regmap_write(regmap, hd->config_reg, hd->config_val);
-+	regmap_write(regmap, hd->m_reg, 0);
-+	regmap_write(regmap, hd->n_reg, 1);
-+
-+	if (hd->user_reg) {
-+		u32 regval = hd->user_val;
-+		unsigned long rate;
-+
-+		rate = __clk_get_rate(hw->clk);
-+
-+		/* Pick the right VCO. */
-+		if (hd->user_vco_mask && rate > hd->low_vco_max_rate)
-+			regval |= hd->user_vco_mask;
-+		regmap_write(regmap, hd->user_reg, regval);
-+	}
-+
-+	if (hd->droop_reg)
-+		regmap_write(regmap, hd->droop_reg, hd->droop_val);
-+
-+	h->init_done = true;
-+}
-+
-+static void __clk_hfpll_enable(struct clk_hw *hw)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	u32 val;
-+
-+	__clk_hfpll_init_once(hw);
-+
-+	/* Disable PLL bypass mode. */
-+	regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL);
-+
-+	/*
-+	 * H/W requires a 5us delay between disabling the bypass and
-+	 * de-asserting the reset. Delay 10us just to be safe.
-+	 */
-+	udelay(10);
-+
-+	/* De-assert active-low PLL reset. */
-+	regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N);
-+
-+	/* Wait for PLL to lock. */
-+	if (hd->status_reg) {
-+		do {
-+			regmap_read(regmap, hd->status_reg, &val);
-+		} while (!(val & BIT(hd->lock_bit)));
-+	} else {
-+		udelay(60);
-+	}
-+
-+	/* Enable PLL output. */
-+	regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL);
-+}
-+
-+/* Enable an already-configured HFPLL. */
-+static int clk_hfpll_enable(struct clk_hw *hw)
-+{
-+	unsigned long flags;
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	u32 mode;
-+
-+	spin_lock_irqsave(&h->lock, flags);
-+	regmap_read(regmap, hd->mode_reg, &mode);
-+	if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)))
-+		__clk_hfpll_enable(hw);
-+	spin_unlock_irqrestore(&h->lock, flags);
-+
-+	return 0;
-+}
-+
-+static void __clk_hfpll_disable(struct clk_hfpll *h)
-+{
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+
-+	/*
-+	 * Disable the PLL output, disable test mode, enable the bypass mode,
-+	 * and assert the reset.
-+	 */
-+	regmap_update_bits(regmap, hd->mode_reg,
-+			PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0);
-+}
-+
-+static void clk_hfpll_disable(struct clk_hw *hw)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&h->lock, flags);
-+	__clk_hfpll_disable(h);
-+	spin_unlock_irqrestore(&h->lock, flags);
-+}
-+
-+static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate,
-+				 unsigned long *parent_rate)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	unsigned long rrate;
-+
-+	rate = clamp(rate, hd->min_rate, hd->max_rate);
-+
-+	rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate;
-+	if (rrate > hd->max_rate)
-+		rrate -= *parent_rate;
-+
-+	return rrate;
-+}
-+
-+/*
-+ * For optimization reasons, assumes no downstream clocks are actively using
-+ * it.
-+ */
-+static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate,
-+			      unsigned long parent_rate)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	unsigned long flags;
-+	u32 l_val, val;
-+	bool enabled;
-+
-+	l_val = rate / parent_rate;
-+
-+	spin_lock_irqsave(&h->lock, flags);
-+
-+	enabled = __clk_is_enabled(hw->clk);
-+	if (enabled)
-+		__clk_hfpll_disable(h);
-+
-+	/* Pick the right VCO. */
-+	if (hd->user_reg && hd->user_vco_mask) {
-+		regmap_read(regmap, hd->user_reg, &val);
-+		if (rate <= hd->low_vco_max_rate)
-+			val &= ~hd->user_vco_mask;
-+		else
-+			val |= hd->user_vco_mask;
-+		regmap_write(regmap, hd->user_reg, val);
-+	}
-+
-+	regmap_write(regmap, hd->l_reg, l_val);
-+
-+	if (enabled)
-+		__clk_hfpll_enable(hw);
-+
-+	spin_unlock_irqrestore(&h->lock, flags);
-+
-+	return 0;
-+}
-+
-+static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw,
-+					   unsigned long parent_rate)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	u32 l_val;
-+
-+	regmap_read(regmap, hd->l_reg, &l_val);
-+
-+	return l_val * parent_rate;
-+}
-+
-+static void clk_hfpll_init(struct clk_hw *hw)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	u32 mode, status;
-+
-+	regmap_read(regmap, hd->mode_reg, &mode);
-+	if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) {
-+		__clk_hfpll_init_once(hw);
-+		return;
-+	}
-+
-+	if (hd->status_reg) {
-+		regmap_read(regmap, hd->status_reg, &status);
-+		if (!(status & BIT(hd->lock_bit))) {
-+			WARN(1, "HFPLL %s is ON, but not locked!\n",
-+					__clk_get_name(hw->clk));
-+			clk_hfpll_disable(hw);
-+			__clk_hfpll_init_once(hw);
-+		}
-+	}
-+}
-+
-+static int hfpll_is_enabled(struct clk_hw *hw)
-+{
-+	struct clk_hfpll *h = to_clk_hfpll(hw);
-+	struct hfpll_data const *hd = h->d;
-+	struct regmap *regmap = h->clkr.regmap;
-+	u32 mode;
-+
-+	regmap_read(regmap, hd->mode_reg, &mode);
-+	mode &= 0x7;
-+	return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL);
-+}
-+
-+const struct clk_ops clk_ops_hfpll = {
-+	.enable = clk_hfpll_enable,
-+	.disable = clk_hfpll_disable,
-+	.is_enabled = hfpll_is_enabled,
-+	.round_rate = clk_hfpll_round_rate,
-+	.set_rate = clk_hfpll_set_rate,
-+	.recalc_rate = clk_hfpll_recalc_rate,
-+	.init = clk_hfpll_init,
-+};
-+EXPORT_SYMBOL_GPL(clk_ops_hfpll);
---- /dev/null
-+++ b/drivers/clk/qcom/clk-hfpll.h
-@@ -0,0 +1,54 @@
-+/*
-+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+#ifndef __QCOM_CLK_HFPLL_H__
-+#define __QCOM_CLK_HFPLL_H__
-+
-+#include <linux/clk-provider.h>
-+#include <linux/spinlock.h>
-+#include "clk-regmap.h"
-+
-+struct hfpll_data {
-+	u32 mode_reg;
-+	u32 l_reg;
-+	u32 m_reg;
-+	u32 n_reg;
-+	u32 user_reg;
-+	u32 droop_reg;
-+	u32 config_reg;
-+	u32 status_reg;
-+	u8  lock_bit;
-+
-+	u32 droop_val;
-+	u32 config_val;
-+	u32 user_val;
-+	u32 user_vco_mask;
-+	unsigned long low_vco_max_rate;
-+
-+	unsigned long min_rate;
-+	unsigned long max_rate;
-+};
-+
-+struct clk_hfpll {
-+	struct hfpll_data const *d;
-+	int init_done;
-+
-+	struct clk_regmap clkr;
-+	spinlock_t lock;
-+};
-+
-+#define to_clk_hfpll(_hw) \
-+	container_of(to_clk_regmap(_hw), struct clk_hfpll, clkr)
-+
-+extern const struct clk_ops clk_ops_hfpll;
-+
-+#endif
diff --git a/target/linux/ipq806x/patches-4.0/138-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-4.0/138-clk-qcom-Add-HFPLL-driver.patch
deleted file mode 100644
index b1f870a..0000000
--- a/target/linux/ipq806x/patches-4.0/138-clk-qcom-Add-HFPLL-driver.patch
+++ /dev/null
@@ -1,206 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,06/13] clk: qcom: Add HFPLL driver
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063231
-Message-Id: <1426920332-9340-7-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
-Date: Fri, 20 Mar 2015 23:45:25 -0700
-
-On some devices (MSM8974 for example), the HFPLLs are
-instantiated within the Krait processor subsystem as separate
-register regions. Add a driver for these PLLs so that we can
-provide HFPLL clocks for use by the system.
-
-Cc: <devicetree@vger.kernel.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-.../devicetree/bindings/clock/qcom,hfpll.txt       |  40 ++++++++
- drivers/clk/qcom/Kconfig                           |   8 ++
- drivers/clk/qcom/Makefile                          |   1 +
- drivers/clk/qcom/hfpll.c                           | 109 +++++++++++++++++++++
- 4 files changed, 158 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt
- create mode 100644 drivers/clk/qcom/hfpll.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
-@@ -0,0 +1,40 @@
-+High-Frequency PLL (HFPLL)
-+
-+PROPERTIES
-+
-+- compatible:
-+	Usage: required
-+	Value type: <string>
-+	Definition: must be "qcom,hfpll"
-+
-+- reg:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: address and size of HPLL registers. An optional second
-+		    element specifies the address and size of the alias
-+		    register region.
-+
-+- clock-output-names:
-+	Usage: required
-+	Value type: <string>
-+	Definition: Name of the PLL. Typically hfpllX where X is a CPU number
-+		    starting at 0. Otherwise hfpll_Y where Y is more specific
-+		    such as "l2".
-+
-+Example:
-+
-+1) An HFPLL for the L2 cache.
-+
-+	clock-controller@f9016000 {
-+		compatible = "qcom,hfpll";
-+		reg = <0xf9016000 0x30>;
-+		clock-output-names = "hfpll_l2";
-+	};
-+
-+2) An HFPLL for CPU0. This HFPLL has the alias register region.
-+
-+	clock-controller@f908a000 {
-+		compatible = "qcom,hfpll";
-+		reg = <0xf908a000 0x30>, <0xf900a000 0x30>;
-+		clock-output-names = "hfpll0";
-+	};
---- a/drivers/clk/qcom/Kconfig
-+++ b/drivers/clk/qcom/Kconfig
-@@ -88,3 +88,11 @@ config MSM_MMCC_8974
- 	  Support for the multimedia clock controller on msm8974 devices.
- 	  Say Y if you want to support multimedia devices such as display,
- 	  graphics, video encode/decode, camera, etc.
-+
-+config QCOM_HFPLL
-+	tristate "High-Frequency PLL (HFPLL) Clock Controller"
-+	depends on COMMON_CLK_QCOM
-+	help
-+	  Support for the high-frequency PLLs present on Qualcomm devices.
-+	  Say Y if you want to support CPU frequency scaling on devices
-+	  such as MSM8974, APQ8084, etc.
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -21,3 +21,4 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896
- obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
- obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
- obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
-+obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
---- /dev/null
-+++ b/drivers/clk/qcom/hfpll.c
-@@ -0,0 +1,109 @@
-+/*
-+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/of.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/regmap.h>
-+
-+#include "clk-regmap.h"
-+#include "clk-hfpll.h"
-+
-+static const struct hfpll_data hdata = {
-+	.mode_reg = 0x00,
-+	.l_reg = 0x04,
-+	.m_reg = 0x08,
-+	.n_reg = 0x0c,
-+	.user_reg = 0x10,
-+	.config_reg = 0x14,
-+	.config_val = 0x430405d,
-+	.status_reg = 0x1c,
-+	.lock_bit = 16,
-+
-+	.user_val = 0x8,
-+	.user_vco_mask = 0x100000,
-+	.low_vco_max_rate = 1248000000,
-+	.min_rate = 537600000UL,
-+	.max_rate = 2900000000UL,
-+};
-+
-+static const struct of_device_id qcom_hfpll_match_table[] = {
-+	{ .compatible = "qcom,hfpll" },
-+	{ }
-+};
-+MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table);
-+
-+static const struct regmap_config hfpll_regmap_config = {
-+	.reg_bits	= 32,
-+	.reg_stride	= 4,
-+	.val_bits	= 32,
-+	.max_register	= 0x30,
-+	.fast_io	= true,
-+};
-+
-+static int qcom_hfpll_probe(struct platform_device *pdev)
-+{
-+	struct clk *clk;
-+	struct resource *res;
-+	struct device *dev = &pdev->dev;
-+	void __iomem *base;
-+	struct regmap *regmap;
-+	struct clk_hfpll *h;
-+	struct clk_init_data init = {
-+		.parent_names = (const char *[]){ "xo" },
-+		.num_parents = 1,
-+		.ops = &clk_ops_hfpll,
-+	};
-+
-+	h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);
-+	if (!h)
-+		return -ENOMEM;
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	base = devm_ioremap_resource(dev, res);
-+	if (IS_ERR(base))
-+		return PTR_ERR(base);
-+
-+	regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config);
-+	if (IS_ERR(regmap))
-+		return PTR_ERR(regmap);
-+
-+	if (of_property_read_string_index(dev->of_node, "clock-output-names",
-+						  0, &init.name))
-+		return -ENODEV;
-+
-+	h->d = &hdata;
-+	h->clkr.hw.init = &init;
-+	spin_lock_init(&h->lock);
-+
-+	clk = devm_clk_register_regmap(&pdev->dev, &h->clkr);
-+
-+	return PTR_ERR_OR_ZERO(clk);
-+}
-+
-+static struct platform_driver qcom_hfpll_driver = {
-+	.probe		= qcom_hfpll_probe,
-+	.driver		= {
-+		.name	= "qcom-hfpll",
-+		.of_match_table = qcom_hfpll_match_table,
-+	},
-+};
-+module_platform_driver(qcom_hfpll_driver);
-+
-+MODULE_DESCRIPTION("QCOM HFPLL Clock Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:qcom-hfpll");
diff --git a/target/linux/ipq806x/patches-4.0/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-4.0/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch
deleted file mode 100644
index d341006..0000000
--- a/target/linux/ipq806x/patches-4.0/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,08/13] clk: qcom: Add IPQ806X's HFPLLs
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063241
-Message-Id: <1426920332-9340-9-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:27 -0700
-
-Describe the HFPLLs present on IPQ806X devices.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 83 insertions(+)
-
---- a/drivers/clk/qcom/gcc-ipq806x.c
-+++ b/drivers/clk/qcom/gcc-ipq806x.c
-@@ -30,6 +30,7 @@
- #include "clk-pll.h"
- #include "clk-rcg.h"
- #include "clk-branch.h"
-+#include "clk-hfpll.h"
- #include "reset.h"
- 
- static struct clk_pll pll0 = {
-@@ -113,6 +114,85 @@ static struct clk_regmap pll8_vote = {
- 	},
- };
- 
-+static struct hfpll_data hfpll0_data = {
-+	.mode_reg = 0x3200,
-+	.l_reg = 0x3208,
-+	.m_reg = 0x320c,
-+	.n_reg = 0x3210,
-+	.config_reg = 0x3204,
-+	.status_reg = 0x321c,
-+	.config_val = 0x7845c665,
-+	.droop_reg = 0x3214,
-+	.droop_val = 0x0108c000,
-+	.min_rate = 600000000UL,
-+	.max_rate = 1800000000UL,
-+};
-+
-+static struct clk_hfpll hfpll0 = {
-+	.d = &hfpll0_data,
-+	.clkr.hw.init = &(struct clk_init_data){
-+		.parent_names = (const char *[]){ "pxo" },
-+		.num_parents = 1,
-+		.name = "hfpll0",
-+		.ops = &clk_ops_hfpll,
-+		.flags = CLK_IGNORE_UNUSED,
-+	},
-+	.lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock),
-+};
-+
-+static struct hfpll_data hfpll1_data = {
-+	.mode_reg = 0x3240,
-+	.l_reg = 0x3248,
-+	.m_reg = 0x324c,
-+	.n_reg = 0x3250,
-+	.config_reg = 0x3244,
-+	.status_reg = 0x325c,
-+	.config_val = 0x7845c665,
-+	.droop_reg = 0x3314,
-+	.droop_val = 0x0108c000,
-+	.min_rate = 600000000UL,
-+	.max_rate = 1800000000UL,
-+};
-+
-+static struct clk_hfpll hfpll1 = {
-+	.d = &hfpll1_data,
-+	.clkr.hw.init = &(struct clk_init_data){
-+		.parent_names = (const char *[]){ "pxo" },
-+		.num_parents = 1,
-+		.name = "hfpll1",
-+		.ops = &clk_ops_hfpll,
-+		.flags = CLK_IGNORE_UNUSED,
-+	},
-+	.lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock),
-+};
-+
-+static struct hfpll_data hfpll_l2_data = {
-+	.mode_reg = 0x3300,
-+	.l_reg = 0x3308,
-+	.m_reg = 0x330c,
-+	.n_reg = 0x3310,
-+	.config_reg = 0x3304,
-+	.status_reg = 0x331c,
-+	.config_val = 0x7845c665,
-+	.droop_reg = 0x3314,
-+	.droop_val = 0x0108c000,
-+	.min_rate = 600000000UL,
-+	.max_rate = 1800000000UL,
-+};
-+
-+static struct clk_hfpll hfpll_l2 = {
-+	.d = &hfpll_l2_data,
-+	.clkr.hw.init = &(struct clk_init_data){
-+		.parent_names = (const char *[]){ "pxo" },
-+		.num_parents = 1,
-+		.name = "hfpll_l2",
-+		.ops = &clk_ops_hfpll,
-+		.flags = CLK_IGNORE_UNUSED,
-+	},
-+	.lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock),
-+};
-+
-+
- static struct clk_pll pll14 = {
- 	.l_reg = 0x31c4,
- 	.m_reg = 0x31c8,
-@@ -2273,6 +2353,9 @@ static struct clk_regmap *gcc_ipq806x_cl
- 	[USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr,
- 	[USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr,
- 	[USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr,
-+	[PLL9] = &hfpll0.clkr,
-+	[PLL10] = &hfpll1.clkr,
-+	[PLL12] = &hfpll_l2.clkr,
- };
- 
- static const struct qcom_reset_map gcc_ipq806x_resets[] = {
diff --git a/target/linux/ipq806x/patches-4.0/140-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-4.0/140-clk-qcom-Add-support-for-Krait-clocks.patch
deleted file mode 100644
index cef33c8..0000000
--- a/target/linux/ipq806x/patches-4.0/140-clk-qcom-Add-support-for-Krait-clocks.patch
+++ /dev/null
@@ -1,271 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,09/13] clk: qcom: Add support for Krait clocks
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063251
-Message-Id: <1426920332-9340-10-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>
-Date: Fri, 20 Mar 2015 23:45:28 -0700
-
-The Krait clocks are made up of a series of muxes and a divider
-that choose between a fixed rate clock and dedicated HFPLLs for
-each CPU. Instead of using mmio accesses to remux parents, the
-Krait implementation exposes the remux control via cp15
-registers. Support these clocks.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-drivers/clk/qcom/Kconfig     |   4 ++
- drivers/clk/qcom/Makefile    |   1 +
- drivers/clk/qcom/clk-krait.c | 166 +++++++++++++++++++++++++++++++++++++++++++
- drivers/clk/qcom/clk-krait.h |  49 +++++++++++++
- 4 files changed, 220 insertions(+)
- create mode 100644 drivers/clk/qcom/clk-krait.c
- create mode 100644 drivers/clk/qcom/clk-krait.h
-
---- a/drivers/clk/qcom/Kconfig
-+++ b/drivers/clk/qcom/Kconfig
-@@ -96,3 +96,7 @@ config QCOM_HFPLL
- 	  Support for the high-frequency PLLs present on Qualcomm devices.
- 	  Say Y if you want to support CPU frequency scaling on devices
- 	  such as MSM8974, APQ8084, etc.
-+
-+config KRAIT_CLOCKS
-+	bool
-+	select KRAIT_L2_ACCESSORS
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o
- clk-qcom-y += clk-branch.o
- clk-qcom-y += clk-regmap-divider.o
- clk-qcom-y += clk-regmap-mux.o
-+clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o
- clk-qcom-y += clk-hfpll.o
- clk-qcom-y += reset.o
- 
---- /dev/null
-+++ b/drivers/clk/qcom/clk-krait.c
-@@ -0,0 +1,166 @@
-+/*
-+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <linux/err.h>
-+#include <linux/clk-provider.h>
-+#include <linux/spinlock.h>
-+
-+#include <asm/krait-l2-accessors.h>
-+
-+#include "clk-krait.h"
-+
-+/* Secondary and primary muxes share the same cp15 register */
-+static DEFINE_SPINLOCK(krait_clock_reg_lock);
-+
-+#define LPL_SHIFT	8
-+static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel)
-+{
-+	unsigned long flags;
-+	u32 regval;
-+
-+	spin_lock_irqsave(&krait_clock_reg_lock, flags);
-+	regval = krait_get_l2_indirect_reg(mux->offset);
-+	regval &= ~(mux->mask << mux->shift);
-+	regval |= (sel & mux->mask) << mux->shift;
-+	if (mux->lpl) {
-+		regval &= ~(mux->mask << (mux->shift + LPL_SHIFT));
-+		regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT);
-+	}
-+	krait_set_l2_indirect_reg(mux->offset, regval);
-+	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
-+
-+	/* Wait for switch to complete. */
-+	mb();
-+	udelay(1);
-+}
-+
-+static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
-+{
-+	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
-+	u32 sel;
-+
-+	sel = clk_mux_reindex(index, mux->parent_map, 0);
-+	mux->en_mask = sel;
-+	/* Don't touch mux if CPU is off as it won't work */
-+	if (__clk_is_enabled(hw->clk))
-+		__krait_mux_set_sel(mux, sel);
-+	return 0;
-+}
-+
-+static u8 krait_mux_get_parent(struct clk_hw *hw)
-+{
-+	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
-+	u32 sel;
-+
-+	sel = krait_get_l2_indirect_reg(mux->offset);
-+	sel >>= mux->shift;
-+	sel &= mux->mask;
-+	mux->en_mask = sel;
-+
-+	return clk_mux_get_parent(hw, sel, mux->parent_map, 0);
-+}
-+
-+static struct clk_hw *krait_mux_get_safe_parent(struct clk_hw *hw)
-+{
-+	int i;
-+	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
-+	int num_parents = __clk_get_num_parents(hw->clk);
-+
-+	i = mux->safe_sel;
-+	for (i = 0; i < num_parents; i++)
-+		if (mux->safe_sel == mux->parent_map[i])
-+			break;
-+
-+	return __clk_get_hw(clk_get_parent_by_index(hw->clk, i));
-+}
-+
-+static int krait_mux_enable(struct clk_hw *hw)
-+{
-+	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
-+
-+	__krait_mux_set_sel(mux, mux->en_mask);
-+
-+	return 0;
-+}
-+
-+static void krait_mux_disable(struct clk_hw *hw)
-+{
-+	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
-+
-+	__krait_mux_set_sel(mux, mux->safe_sel);
-+}
-+
-+const struct clk_ops krait_mux_clk_ops = {
-+	.enable = krait_mux_enable,
-+	.disable = krait_mux_disable,
-+	.set_parent = krait_mux_set_parent,
-+	.get_parent = krait_mux_get_parent,
-+	.determine_rate = __clk_mux_determine_rate_closest,
-+	.get_safe_parent = krait_mux_get_safe_parent,
-+};
-+EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
-+
-+/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
-+static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
-+				  unsigned long *parent_rate)
-+{
-+	*parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), rate * 2);
-+	return DIV_ROUND_UP(*parent_rate, 2);
-+}
-+
-+static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
-+			unsigned long parent_rate)
-+{
-+	struct krait_div2_clk *d = to_krait_div2_clk(hw);
-+	unsigned long flags;
-+	u32 val;
-+	u32 mask = BIT(d->width) - 1;
-+
-+	if (d->lpl)
-+		mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
-+
-+	spin_lock_irqsave(&krait_clock_reg_lock, flags);
-+	val = krait_get_l2_indirect_reg(d->offset);
-+	val &= ~mask;
-+	krait_set_l2_indirect_reg(d->offset, val);
-+	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
-+
-+	return 0;
-+}
-+
-+static unsigned long
-+krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
-+{
-+	struct krait_div2_clk *d = to_krait_div2_clk(hw);
-+	u32 mask = BIT(d->width) - 1;
-+	u32 div;
-+
-+	div = krait_get_l2_indirect_reg(d->offset);
-+	div >>= d->shift;
-+	div &= mask;
-+	div = (div + 1) * 2;
-+
-+	return DIV_ROUND_UP(parent_rate, div);
-+}
-+
-+const struct clk_ops krait_div2_clk_ops = {
-+	.round_rate = krait_div2_round_rate,
-+	.set_rate = krait_div2_set_rate,
-+	.recalc_rate = krait_div2_recalc_rate,
-+};
-+EXPORT_SYMBOL_GPL(krait_div2_clk_ops);
---- /dev/null
-+++ b/drivers/clk/qcom/clk-krait.h
-@@ -0,0 +1,49 @@
-+/*
-+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#ifndef __QCOM_CLK_KRAIT_H
-+#define __QCOM_CLK_KRAIT_H
-+
-+#include <linux/clk-provider.h>
-+
-+struct krait_mux_clk {
-+	unsigned int	*parent_map;
-+	bool		has_safe_parent;
-+	u8		safe_sel;
-+	u32		offset;
-+	u32		mask;
-+	u32		shift;
-+	u32		en_mask;
-+	bool		lpl;
-+
-+	struct clk_hw	hw;
-+};
-+
-+#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw)
-+
-+extern const struct clk_ops krait_mux_clk_ops;
-+
-+struct krait_div2_clk {
-+	u32		offset;
-+	u8		width;
-+	u32		shift;
-+	bool		lpl;
-+
-+	struct clk_hw	hw;
-+};
-+
-+#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw)
-+
-+extern const struct clk_ops krait_div2_clk_ops;
-+
-+#endif
diff --git a/target/linux/ipq806x/patches-4.0/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-4.0/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch
deleted file mode 100644
index 12f24b7..0000000
--- a/target/linux/ipq806x/patches-4.0/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch
+++ /dev/null
@@ -1,205 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,10/13] clk: qcom: Add KPSS ACC/GCC driver
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063201
-Message-Id: <1426920332-9340-11-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
-Date: Fri, 20 Mar 2015 23:45:29 -0700
-
-The ACC and GCC regions present in KPSSv1 contain registers to
-control clocks and power to each Krait CPU and L2. For CPUfreq
-purposes probe these devices and expose a mux clock that chooses
-between PXO and PLL8.
-
-Cc: <devicetree@vger.kernel.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-.../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  7 ++
- .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  | 28 +++++++
- drivers/clk/qcom/Kconfig                           |  8 ++
- drivers/clk/qcom/Makefile                          |  1 +
- drivers/clk/qcom/kpss-xcc.c                        | 95 ++++++++++++++++++++++
- 5 files changed, 139 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
- create mode 100644 drivers/clk/qcom/kpss-xcc.c
-
---- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
-+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
-@@ -21,10 +21,17 @@ PROPERTIES
- 		    the register region. An optional second element specifies
- 		    the base address and size of the alias register region.
- 
-+- clock-output-names:
-+	Usage: optional
-+	Value type: <string>
-+	Definition: Name of the output clock. Typically acpuX_aux where X is a
-+		    CPU number starting at 0.
-+
- Example:
- 
- 	clock-controller@2088000 {
- 		compatible = "qcom,kpss-acc-v2";
- 		reg = <0x02088000 0x1000>,
- 		      <0x02008000 0x1000>;
-+		clock-output-names = "acpu0_aux";
- 	};
---- /dev/null
-+++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
-@@ -0,0 +1,28 @@
-+Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
-+
-+PROPERTIES
-+
-+- compatible:
-+	Usage: required
-+	Value type: <string>
-+	Definition: should be one of:
-+			"qcom,kpss-gcc"
-+
-+- reg:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: base address and size of the register region
-+
-+- clock-output-names:
-+	Usage: required
-+	Value type: <string>
-+	Definition: Name of the output clock. Typically acpu_l2_aux indicating
-+		    an L2 cache auxiliary clock.
-+
-+Example:
-+
-+	l2cc: clock-controller@2011000 {
-+		compatible = "qcom,kpss-gcc";
-+		reg = <0x2011000 0x1000>;
-+		clock-output-names = "acpu_l2_aux";
-+	};
---- a/drivers/clk/qcom/Kconfig
-+++ b/drivers/clk/qcom/Kconfig
-@@ -97,6 +97,14 @@ config QCOM_HFPLL
- 	  Say Y if you want to support CPU frequency scaling on devices
- 	  such as MSM8974, APQ8084, etc.
- 
-+config KPSS_XCC
-+	tristate "KPSS Clock Controller"
-+	depends on COMMON_CLK_QCOM
-+	help
-+	  Support for the Krait ACC and GCC clock controllers. Say Y
-+	  if you want to support CPU frequency scaling on devices such
-+	  as MSM8960, APQ8064, etc.
-+
- config KRAIT_CLOCKS
- 	bool
- 	select KRAIT_L2_ACCESSORS
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -22,4 +22,5 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896
- obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
- obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
- obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
-+obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
- obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
---- /dev/null
-+++ b/drivers/clk/qcom/kpss-xcc.c
-@@ -0,0 +1,95 @@
-+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+
-+static const char *aux_parents[] = {
-+	"pll8_vote",
-+	"pxo",
-+};
-+
-+static unsigned int aux_parent_map[] = {
-+	3,
-+	0,
-+};
-+
-+static const struct of_device_id kpss_xcc_match_table[] = {
-+	{ .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL },
-+	{ .compatible = "qcom,kpss-gcc" },
-+	{}
-+};
-+MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
-+
-+static int kpss_xcc_driver_probe(struct platform_device *pdev)
-+{
-+	const struct of_device_id *id;
-+	struct clk *clk;
-+	struct resource *res;
-+	void __iomem *base;
-+	const char *name;
-+
-+	id = of_match_device(kpss_xcc_match_table, &pdev->dev);
-+	if (!id)
-+		return -ENODEV;
-+
-+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	base = devm_ioremap_resource(&pdev->dev, res);
-+	if (IS_ERR(base))
-+		return PTR_ERR(base);
-+
-+	if (id->data) {
-+		if (of_property_read_string_index(pdev->dev.of_node,
-+					"clock-output-names", 0, &name))
-+			return -ENODEV;
-+		base += 0x14;
-+	} else {
-+		name = "acpu_l2_aux";
-+		base += 0x28;
-+	}
-+
-+	clk = clk_register_mux_table(&pdev->dev, name, aux_parents,
-+				     ARRAY_SIZE(aux_parents), 0, base, 0, 0x3,
-+				     0, aux_parent_map, NULL);
-+
-+	platform_set_drvdata(pdev, clk);
-+
-+	return PTR_ERR_OR_ZERO(clk);
-+}
-+
-+static int kpss_xcc_driver_remove(struct platform_device *pdev)
-+{
-+	clk_unregister_mux(platform_get_drvdata(pdev));
-+	return 0;
-+}
-+
-+static struct platform_driver kpss_xcc_driver = {
-+	.probe = kpss_xcc_driver_probe,
-+	.remove = kpss_xcc_driver_remove,
-+	.driver = {
-+		.name = "kpss-xcc",
-+		.of_match_table = kpss_xcc_match_table,
-+	},
-+};
-+module_platform_driver(kpss_xcc_driver);
-+
-+MODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:kpss-xcc");
diff --git a/target/linux/ipq806x/patches-4.0/142-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-4.0/142-clk-qcom-Add-Krait-clock-controller-driver.patch
deleted file mode 100644
index 159facd..0000000
--- a/target/linux/ipq806x/patches-4.0/142-clk-qcom-Add-Krait-clock-controller-driver.patch
+++ /dev/null
@@ -1,435 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,11/13] clk: qcom: Add Krait clock controller driver
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063121
-Message-Id: <1426920332-9340-12-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
-Date: Fri, 20 Mar 2015 23:45:30 -0700
-
-The Krait CPU clocks are made up of a primary mux and secondary
-mux for each CPU and the L2, controlled via cp15 accessors. For
-Kraits within KPSSv1 each secondary mux accepts a different aux
-source, but on KPSSv2 each secondary mux accepts the same aux
-source.
-
-Cc: <devicetree@vger.kernel.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-.../devicetree/bindings/clock/qcom,krait-cc.txt    |  22 ++
- drivers/clk/qcom/Kconfig                           |   8 +
- drivers/clk/qcom/Makefile                          |   1 +
- drivers/clk/qcom/krait-cc.c                        | 352 +++++++++++++++++++++
- 4 files changed, 383 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
- create mode 100644 drivers/clk/qcom/krait-cc.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
-@@ -0,0 +1,22 @@
-+Krait Clock Controller
-+
-+PROPERTIES
-+
-+- compatible:
-+	Usage: required
-+	Value type: <string>
-+	Definition: must be one of:
-+			"qcom,krait-cc-v1"
-+			"qcom,krait-cc-v2"
-+
-+- #clock-cells:
-+	Usage: required
-+	Value type: <u32>
-+	Definition: must be 1
-+
-+Example:
-+
-+	kraitcc: clock-controller {
-+		compatible = "qcom,krait-cc-v1";
-+		#clock-cells = <1>;
-+	};
---- a/drivers/clk/qcom/Kconfig
-+++ b/drivers/clk/qcom/Kconfig
-@@ -105,6 +105,14 @@ config KPSS_XCC
- 	  if you want to support CPU frequency scaling on devices such
- 	  as MSM8960, APQ8064, etc.
- 
-+config KRAITCC
-+	tristate "Krait Clock Controller"
-+	depends on COMMON_CLK_QCOM && ARM
-+	select KRAIT_CLOCKS
-+	help
-+	  Support for the Krait CPU clocks on Qualcomm devices.
-+	  Say Y if you want to support CPU frequency scaling.
-+
- config KRAIT_CLOCKS
- 	bool
- 	select KRAIT_L2_ACCESSORS
---- a/drivers/clk/qcom/Makefile
-+++ b/drivers/clk/qcom/Makefile
-@@ -24,3 +24,4 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8
- obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
- obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
- obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
-+obj-$(CONFIG_KRAITCC) += krait-cc.o
---- /dev/null
-+++ b/drivers/clk/qcom/krait-cc.c
-@@ -0,0 +1,352 @@
-+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/slab.h>
-+
-+#include "clk-krait.h"
-+
-+static unsigned int sec_mux_map[] = {
-+	2,
-+	0,
-+};
-+
-+static unsigned int pri_mux_map[] = {
-+	1,
-+	2,
-+	0,
-+};
-+
-+static int
-+krait_add_div(struct device *dev, int id, const char *s, unsigned offset)
-+{
-+	struct krait_div2_clk *div;
-+	struct clk_init_data init = {
-+		.num_parents = 1,
-+		.ops = &krait_div2_clk_ops,
-+		.flags = CLK_SET_RATE_PARENT,
-+	};
-+	const char *p_names[1];
-+	struct clk *clk;
-+
-+	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
-+	if (!div)
-+		return -ENOMEM;
-+
-+	div->width = 2;
-+	div->shift = 6;
-+	div->lpl = id >= 0;
-+	div->offset = offset;
-+	div->hw.init = &init;
-+
-+	init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
-+	if (!init.name)
-+		return -ENOMEM;
-+
-+	init.parent_names = p_names;
-+	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
-+	if (!p_names[0]) {
-+		kfree(init.name);
-+		return -ENOMEM;
-+	}
-+
-+	clk = devm_clk_register(dev, &div->hw);
-+	kfree(p_names[0]);
-+	kfree(init.name);
-+
-+	return PTR_ERR_OR_ZERO(clk);
-+}
-+
-+static int
-+krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset,
-+		  bool unique_aux)
-+{
-+	struct krait_mux_clk *mux;
-+	static const char *sec_mux_list[] = {
-+		"acpu_aux",
-+		"qsb",
-+	};
-+	struct clk_init_data init = {
-+		.parent_names = sec_mux_list,
-+		.num_parents = ARRAY_SIZE(sec_mux_list),
-+		.ops = &krait_mux_clk_ops,
-+		.flags = CLK_SET_RATE_PARENT,
-+	};
-+	struct clk *clk;
-+
-+	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
-+	if (!mux)
-+		return -ENOMEM;
-+
-+	mux->offset = offset;
-+	mux->lpl = id >= 0;
-+	mux->has_safe_parent = true;
-+	mux->safe_sel = 2;
-+	mux->mask = 0x3;
-+	mux->shift = 2;
-+	mux->parent_map = sec_mux_map;
-+	mux->hw.init = &init;
-+
-+	init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
-+	if (!init.name)
-+		return -ENOMEM;
-+
-+	if (unique_aux) {
-+		sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
-+		if (!sec_mux_list[0]) {
-+			clk = ERR_PTR(-ENOMEM);
-+			goto err_aux;
-+		}
-+	}
-+
-+	clk = devm_clk_register(dev, &mux->hw);
-+
-+	if (unique_aux)
-+		kfree(sec_mux_list[0]);
-+err_aux:
-+	kfree(init.name);
-+	return PTR_ERR_OR_ZERO(clk);
-+}
-+
-+static struct clk *
-+krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset)
-+{
-+	struct krait_mux_clk *mux;
-+	const char *p_names[3];
-+	struct clk_init_data init = {
-+		.parent_names = p_names,
-+		.num_parents = ARRAY_SIZE(p_names),
-+		.ops = &krait_mux_clk_ops,
-+		.flags = CLK_SET_RATE_PARENT,
-+	};
-+	struct clk *clk;
-+
-+	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
-+	if (!mux)
-+		return ERR_PTR(-ENOMEM);
-+
-+	mux->has_safe_parent = true;
-+	mux->safe_sel = 0;
-+	mux->mask = 0x3;
-+	mux->shift = 0;
-+	mux->offset = offset;
-+	mux->lpl = id >= 0;
-+	mux->parent_map = pri_mux_map;
-+	mux->hw.init = &init;
-+
-+	init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
-+	if (!init.name)
-+		return ERR_PTR(-ENOMEM);
-+
-+	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
-+	if (!p_names[0]) {
-+		clk = ERR_PTR(-ENOMEM);
-+		goto err_p0;
-+	}
-+
-+	p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
-+	if (!p_names[1]) {
-+		clk = ERR_PTR(-ENOMEM);
-+		goto err_p1;
-+	}
-+
-+	p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
-+	if (!p_names[2]) {
-+		clk = ERR_PTR(-ENOMEM);
-+		goto err_p2;
-+	}
-+
-+	clk = devm_clk_register(dev, &mux->hw);
-+
-+	kfree(p_names[2]);
-+err_p2:
-+	kfree(p_names[1]);
-+err_p1:
-+	kfree(p_names[0]);
-+err_p0:
-+	kfree(init.name);
-+	return clk;
-+}
-+
-+/* id < 0 for L2, otherwise id == physical CPU number */
-+static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
-+{
-+	int ret;
-+	unsigned offset;
-+	void *p = NULL;
-+	const char *s;
-+	struct clk *clk;
-+
-+	if (id >= 0) {
-+		offset = 0x4501 + (0x1000 * id);
-+		s = p = kasprintf(GFP_KERNEL, "%d", id);
-+		if (!s)
-+			return ERR_PTR(-ENOMEM);
-+	} else {
-+		offset = 0x500;
-+		s = "_l2";
-+	}
-+
-+	ret = krait_add_div(dev, id, s, offset);
-+	if (ret) {
-+		clk = ERR_PTR(ret);
-+		goto err;
-+	}
-+
-+	ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
-+	if (ret) {
-+		clk = ERR_PTR(ret);
-+		goto err;
-+	}
-+
-+	clk = krait_add_pri_mux(dev, id, s, offset);
-+err:
-+	kfree(p);
-+	return clk;
-+}
-+
-+static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
-+{
-+	unsigned int idx = clkspec->args[0];
-+	struct clk **clks = data;
-+
-+	if (idx >= 5) {
-+		pr_err("%s: invalid clock index %d\n", __func__, idx);
-+		return ERR_PTR(-EINVAL);
-+	}
-+
-+	return clks[idx] ? : ERR_PTR(-ENODEV);
-+}
-+
-+static const struct of_device_id krait_cc_match_table[] = {
-+	{ .compatible = "qcom,krait-cc-v1", (void *)1UL },
-+	{ .compatible = "qcom,krait-cc-v2" },
-+	{}
-+};
-+MODULE_DEVICE_TABLE(of, krait_cc_match_table);
-+
-+static int krait_cc_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	const struct of_device_id *id;
-+	unsigned long cur_rate, aux_rate;
-+	int cpu;
-+	struct clk *clk;
-+	struct clk **clks;
-+	struct clk *l2_pri_mux_clk;
-+
-+	id = of_match_device(krait_cc_match_table, dev);
-+	if (!id)
-+		return -ENODEV;
-+
-+	/* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
-+	clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1);
-+	if (IS_ERR(clk))
-+		return PTR_ERR(clk);
-+
-+	if (!id->data) {
-+		clk = clk_register_fixed_factor(dev, "acpu_aux",
-+						"gpll0_vote", 0, 1, 2);
-+		if (IS_ERR(clk))
-+			return PTR_ERR(clk);
-+	}
-+
-+	/* Krait configurations have at most 4 CPUs and one L2 */
-+	clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
-+	if (!clks)
-+		return -ENOMEM;
-+
-+	for_each_possible_cpu(cpu) {
-+		clk = krait_add_clks(dev, cpu, id->data);
-+		if (IS_ERR(clk))
-+			return PTR_ERR(clk);
-+		clks[cpu] = clk;
-+	}
-+
-+	l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
-+	if (IS_ERR(l2_pri_mux_clk))
-+		return PTR_ERR(l2_pri_mux_clk);
-+	clks[4] = l2_pri_mux_clk;
-+
-+	/*
-+	 * We don't want the CPU or L2 clocks to be turned off at late init
-+	 * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
-+	 * refcount of these clocks. Any cpufreq/hotplug manager can assume
-+	 * that the clocks have already been prepared and enabled by the time
-+	 * they take over.
-+	 */
-+	for_each_online_cpu(cpu) {
-+		clk_prepare_enable(l2_pri_mux_clk);
-+		WARN(clk_prepare_enable(clks[cpu]),
-+			"Unable to turn on CPU%d clock", cpu);
-+	}
-+
-+	/*
-+	 * Force reinit of HFPLLs and muxes to overwrite any potential
-+	 * incorrect configuration of HFPLLs and muxes by the bootloader.
-+	 * While at it, also make sure the cores are running at known rates
-+	 * and print the current rate.
-+	 *
-+	 * The clocks are set to aux clock rate first to make sure the
-+	 * secondary mux is not sourcing off of QSB. The rate is then set to
-+	 * two different rates to force a HFPLL reinit under all
-+	 * circumstances.
-+	 */
-+	cur_rate = clk_get_rate(l2_pri_mux_clk);
-+	aux_rate = 384000000;
-+	if (cur_rate == 1) {
-+		pr_info("L2 @ QSB rate. Forcing new rate.\n");
-+		cur_rate = aux_rate;
-+	}
-+	clk_set_rate(l2_pri_mux_clk, aux_rate);
-+	clk_set_rate(l2_pri_mux_clk, 2);
-+	clk_set_rate(l2_pri_mux_clk, cur_rate);
-+	pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
-+	for_each_possible_cpu(cpu) {
-+		clk = clks[cpu];
-+		cur_rate = clk_get_rate(clk);
-+		if (cur_rate == 1) {
-+			pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
-+			cur_rate = aux_rate;
-+		}
-+		clk_set_rate(clk, aux_rate);
-+		clk_set_rate(clk, 2);
-+		clk_set_rate(clk, cur_rate);
-+		pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
-+	}
-+
-+	of_clk_add_provider(dev->of_node, krait_of_get, clks);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver krait_cc_driver = {
-+	.probe = krait_cc_probe,
-+	.driver = {
-+		.name = "krait-cc",
-+		.of_match_table = krait_cc_match_table,
-+	},
-+};
-+module_platform_driver(krait_cc_driver);
-+
-+MODULE_DESCRIPTION("Krait CPU Clock Driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:krait-cc");
diff --git a/target/linux/ipq806x/patches-4.0/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch b/target/linux/ipq806x/patches-4.0/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch
deleted file mode 100644
index 57d4afe..0000000
--- a/target/linux/ipq806x/patches-4.0/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch
+++ /dev/null
@@ -1,304 +0,0 @@
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [v3,12/13] cpufreq: Add module to register cpufreq on Krait CPUs
-From: Stephen Boyd <sboyd@codeaurora.org>
-X-Patchwork-Id: 6063191
-Message-Id: <1426920332-9340-13-git-send-email-sboyd@codeaurora.org>
-To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
-Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
-	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
-	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
-Date: Fri, 20 Mar 2015 23:45:31 -0700
-
-Register a cpufreq-generic device whenever we detect that a
-"qcom,krait" compatible CPU is present in DT.
-
-Cc: <devicetree@vger.kernel.org>
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
-.../devicetree/bindings/arm/msm/qcom,pvs.txt       |  38 ++++
- drivers/cpufreq/Kconfig.arm                        |   9 +
- drivers/cpufreq/Makefile                           |   1 +
- drivers/cpufreq/qcom-cpufreq.c                     | 204 +++++++++++++++++++++
- 4 files changed, 252 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt
- create mode 100644 drivers/cpufreq/qcom-cpufreq.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt
-@@ -0,0 +1,38 @@
-+Qualcomm Process Voltage Scaling Tables
-+
-+The node name is required to be "qcom,pvs". There shall only be one
-+such node present in the root of the tree.
-+
-+PROPERTIES
-+
-+- qcom,pvs-format-a or qcom,pvs-format-b:
-+	Usage: required
-+	Value type: <empty>
-+	Definition: Indicates the format of qcom,speedX-pvsY-bin-vZ properties.
-+		    If qcom,pvs-format-a is used the table is two columns
-+		    (frequency and voltage in that order). If qcom,pvs-format-b 		    is used the table is three columns (frequency, voltage,
-+		    and current in that order).
-+
-+- qcom,speedX-pvsY-bin-vZ:
-+	Usage: required
-+	Value type: <prop-encoded-array>
-+	Definition: The PVS table corresponding to the speed bin X, pvs bin Y,
-+		    and version Z.
-+Example:
-+
-+	qcom,pvs {
-+		qcom,pvs-format-a;
-+		qcom,speed0-pvs0-bin-v0 =
-+			<  384000000  950000 >,
-+			<  486000000  975000 >,
-+			<  594000000 1000000 >,
-+			<  702000000 1025000 >,
-+			<  810000000 1075000 >,
-+			<  918000000 1100000 >,
-+			< 1026000000 1125000 >,
-+			< 1134000000 1175000 >,
-+			< 1242000000 1200000 >,
-+			< 1350000000 1225000 >,
-+			< 1458000000 1237500 >,
-+			< 1512000000 1250000 >;
-+	};
---- a/drivers/cpufreq/Kconfig.arm
-+++ b/drivers/cpufreq/Kconfig.arm
-@@ -137,6 +137,15 @@ config ARM_OMAP2PLUS_CPUFREQ
- 	depends on ARCH_OMAP2PLUS
- 	default ARCH_OMAP2PLUS
- 
-+config ARM_QCOM_CPUFREQ
-+	tristate "Qualcomm based"
-+	depends on ARCH_QCOM
-+	select PM_OPP
-+	help
-+	  This adds the CPUFreq driver for Qualcomm SoC based boards.
-+
-+	  If in doubt, say N.
-+
- config ARM_S3C_CPUFREQ
- 	bool
- 	help
---- a/drivers/cpufreq/Makefile
-+++ b/drivers/cpufreq/Makefile
-@@ -65,6 +65,7 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= ki
- obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
- obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
- obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
-+obj-$(CONFIG_ARM_QCOM_CPUFREQ)		+= qcom-cpufreq.o
- obj-$(CONFIG_ARM_S3C24XX_CPUFREQ)	+= s3c24xx-cpufreq.o
- obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
- obj-$(CONFIG_ARM_S3C2410_CPUFREQ)	+= s3c2410-cpufreq.o
---- /dev/null
-+++ b/drivers/cpufreq/qcom-cpufreq.c
-@@ -0,0 +1,204 @@
-+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 and
-+ * only version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/cpu.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_opp.h>
-+#include <linux/slab.h>
-+#include <linux/cpufreq-dt.h>
-+
-+static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver)
-+{
-+	void __iomem *base;
-+	u32 pte_efuse;
-+
-+	*speed = *pvs = *pvs_ver = 0;
-+
-+	base = ioremap(0x007000c0, 4);
-+	if (!base) {
-+		pr_warn("Unable to read efuse data. Defaulting to 0!\n");
-+		return;
-+	}
-+
-+	pte_efuse = readl_relaxed(base);
-+	iounmap(base);
-+
-+	*speed = pte_efuse & 0xf;
-+	if (*speed == 0xf)
-+		*speed = (pte_efuse >> 4) & 0xf;
-+
-+	if (*speed == 0xf) {
-+		*speed = 0;
-+		pr_warn("Speed bin: Defaulting to %d\n", *speed);
-+	} else {
-+		pr_info("Speed bin: %d\n", *speed);
-+	}
-+
-+	*pvs = (pte_efuse >> 10) & 0x7;
-+	if (*pvs == 0x7)
-+		*pvs = (pte_efuse >> 13) & 0x7;
-+
-+	if (*pvs == 0x7) {
-+		*pvs = 0;
-+		pr_warn("PVS bin: Defaulting to %d\n", *pvs);
-+	} else {
-+		pr_info("PVS bin: %d\n", *pvs);
-+	}
-+}
-+
-+static void __init get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver)
-+{
-+	u32 pte_efuse, redundant_sel;
-+	void __iomem *base;
-+
-+	*speed = 0;
-+	*pvs = 0;
-+	*pvs_ver = 0;
-+
-+	base = ioremap(0xfc4b80b0, 8);
-+	if (!base) {
-+		pr_warn("Unable to read efuse data. Defaulting to 0!\n");
-+		return;
-+	}
-+
-+	pte_efuse = readl_relaxed(base);
-+	redundant_sel = (pte_efuse >> 24) & 0x7;
-+	*speed = pte_efuse & 0x7;
-+	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
-+	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
-+	*pvs_ver = (pte_efuse >> 4) & 0x3;
-+
-+	switch (redundant_sel) {
-+	case 1:
-+		*speed = (pte_efuse >> 27) & 0xf;
-+		break;
-+	case 2:
-+		*pvs = (pte_efuse >> 27) & 0xf;
-+		break;
-+	}
-+
-+	/* Check SPEED_BIN_BLOW_STATUS */
-+	if (pte_efuse & BIT(3)) {
-+		pr_info("Speed bin: %d\n", *speed);
-+	} else {
-+		pr_warn("Speed bin not set. Defaulting to 0!\n");
-+		*speed = 0;
-+	}
-+
-+	/* Check PVS_BLOW_STATUS */
-+	pte_efuse = readl_relaxed(base + 0x4) & BIT(21);
-+	if (pte_efuse) {
-+		pr_info("PVS bin: %d\n", *pvs);
-+	} else {
-+		pr_warn("PVS bin not set. Defaulting to 0!\n");
-+		*pvs = 0;
-+	}
-+
-+	pr_info("PVS version: %d\n", *pvs_ver);
-+	iounmap(base);
-+}
-+
-+static int __init qcom_cpufreq_populate_opps(void)
-+{
-+	int len, rows, cols, i, k, speed, pvs, pvs_ver;
-+	char table_name[] = "qcom,speedXX-pvsXX-bin-vXX";
-+	struct device_node *np;
-+	struct device *dev;
-+	int cpu = 0;
-+
-+	np = of_find_node_by_name(NULL, "qcom,pvs");
-+	if (!np)
-+		return -ENODEV;
-+
-+	if (of_property_read_bool(np, "qcom,pvs-format-a")) {
-+		get_krait_bin_format_a(&speed, &pvs, &pvs_ver);
-+		cols = 2;
-+	} else if (of_property_read_bool(np, "qcom,pvs-format-b")) {
-+		get_krait_bin_format_b(&speed, &pvs, &pvs_ver);
-+		cols = 3;
-+	} else {
-+		return -ENODEV;
-+	}
-+
-+	snprintf(table_name, sizeof(table_name),
-+			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver);
-+
-+	if (!of_find_property(np, table_name, &len))
-+		return -EINVAL;
-+
-+	len /= sizeof(u32);
-+	if (len % cols || len == 0)
-+		return -EINVAL;
-+
-+	rows = len / cols;
-+
-+	for (i = 0, k = 0; i < rows; i++) {
-+		u32 freq, volt;
-+
-+		of_property_read_u32_index(np, table_name, k++, &freq);
-+		of_property_read_u32_index(np, table_name, k++, &volt);
-+		while (k % cols)
-+			k++; /* Skip uA entries if present */
-+		for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
-+			dev = get_cpu_device(cpu);
-+			if (!dev)
-+				return -ENODEV;
-+			if (dev_pm_opp_add(dev, freq, volt))
-+				pr_warn("failed to add OPP %u\n", freq);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static int __init qcom_cpufreq_driver_init(void)
-+{
-+	struct cpufreq_dt_platform_data pdata = { .independent_clocks = true };
-+	struct platform_device_info devinfo = {
-+		.name = "cpufreq-dt",
-+		.data = &pdata,
-+		.size_data = sizeof(pdata),
-+	};
-+	struct device *cpu_dev;
-+	struct device_node *np;
-+	int ret;
-+
-+	cpu_dev = get_cpu_device(0);
-+	if (!cpu_dev)
-+		return -ENODEV;
-+
-+	np = of_node_get(cpu_dev->of_node);
-+	if (!np)
-+		return -ENOENT;
-+
-+	if (!of_device_is_compatible(np, "qcom,krait")) {
-+		of_node_put(np);
-+		return -ENODEV;
-+	}
-+	of_node_put(np);
-+
-+	ret = qcom_cpufreq_populate_opps();
-+	if (ret)
-+		return ret;
-+
-+	return PTR_ERR_OR_ZERO(platform_device_register_full(&devinfo));
-+}
-+module_init(qcom_cpufreq_driver_init);
-+
-+MODULE_DESCRIPTION("Qualcomm CPUfreq driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ipq806x/patches-4.0/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch b/target/linux/ipq806x/patches-4.0/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
deleted file mode 100644
index a3c3bbf..0000000
--- a/target/linux/ipq806x/patches-4.0/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
+++ /dev/null
@@ -1,100 +0,0 @@
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -24,6 +24,11 @@
- 			next-level-cache = <&L2>;
- 			qcom,acc = <&acc0>;
- 			qcom,saw = <&saw0>;
-+			clocks = <&kraitcc 0>;
-+			clock-names = "cpu";
-+			clock-latency = <100000>;
-+			core-supply = <&smb208_s2a>;
-+			voltage-tolerance = <5>;
- 		};
- 
- 		cpu@1 {
-@@ -34,11 +39,24 @@
- 			next-level-cache = <&L2>;
- 			qcom,acc = <&acc1>;
- 			qcom,saw = <&saw1>;
-+			clocks = <&kraitcc 1>;
-+			clock-names = "cpu";
-+			clock-latency = <100000>;
-+			core-supply = <&smb208_s2b>;
- 		};
- 
- 		L2: l2-cache {
- 			compatible = "cache";
- 			cache-level = <2>;
-+			clocks = <&kraitcc 4>;
-+			clock-names = "cache";
-+			cache-points-kHz = <
-+				/* kHz    uV    CPU kHz */
-+				1200000 1150000 1200000
-+				1000000 1100000  600000
-+				 384000 1100000  384000
-+			>;
-+			vdd_dig-supply = <&smb208_s1a>;
- 		};
- 	};
- 
-@@ -71,6 +89,46 @@
- 		};
- 	};
- 
-+	kraitcc: clock-controller {
-+		compatible = "qcom,krait-cc-v1";
-+		#clock-cells = <1>;
-+	};
-+
-+	qcom,pvs {
-+		qcom,pvs-format-a;
-+		qcom,speed0-pvs0-bin-v0 =
-+			< 1400000000 1250000 >,
-+			< 1200000000 1200000 >,
-+			< 1000000000 1150000 >,
-+			 < 800000000 1100000 >,
-+			 < 600000000 1050000 >,
-+			 < 384000000 1000000 >;
-+
-+		qcom,speed0-pvs1-bin-v0 =
-+			< 1400000000 1175000 >,
-+			< 1200000000 1125000 >,
-+			< 1000000000 1075000 >,
-+			 < 800000000 1025000 >,
-+			 < 600000000  975000 >,
-+			 < 384000000  925000 >;
-+
-+		qcom,speed0-pvs2-bin-v0 =
-+			< 1400000000 1125000 >,
-+			< 1200000000 1075000 >,
-+			< 1000000000 1025000 >,
-+			 < 800000000  995000 >,
-+			 < 600000000  925000 >,
-+			 < 384000000  875000 >;
-+
-+		qcom,speed0-pvs3-bin-v0 =
-+			< 1400000000 1050000 >,
-+			< 1200000000 1000000 >,
-+			< 1000000000  950000 >,
-+			 < 800000000  900000 >,
-+			 < 600000000  850000 >,
-+			 < 384000000  800000 >;
-+	};
-+
- 	soc: soc {
- 		#address-cells = <1>;
- 		#size-cells = <1>;
-@@ -171,11 +229,13 @@
- 		acc0: clock-controller@2088000 {
- 			compatible = "qcom,kpss-acc-v1";
- 			reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
-+			clock-output-names = "acpu0_aux";
- 		};
- 
- 		acc1: clock-controller@2098000 {
- 			compatible = "qcom,kpss-acc-v1";
- 			reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
-+			clock-output-names = "acpu1_aux";
- 		};
- 
- 		l2cc: clock-controller@2011000 {
diff --git a/target/linux/ipq806x/patches-4.0/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch b/target/linux/ipq806x/patches-4.0/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch
deleted file mode 100644
index 521adc5..0000000
--- a/target/linux/ipq806x/patches-4.0/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch
+++ /dev/null
@@ -1,461 +0,0 @@
-From dd77db4143290689d3a5e1ec61627233d0711b66 Mon Sep 17 00:00:00 2001
-From: Stephen Boyd <sboyd@codeaurora.org>
-Date: Fri, 30 May 2014 16:36:11 -0700
-Subject: [PATCH] FROMLIST: cpufreq: Add a cpufreq-krait based on cpufreq-cpu0
-
-Krait processors have individual clocks for each CPU that can
-scale independently from one another. cpufreq-cpu0 is fairly
-close to this, but assumes that there is only one clock for all
-CPUs. Add a driver to support the Krait configuration.
-
-TODO: Merge into cpufreq-cpu0? Or make generic?
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-
----
- drivers/cpufreq/Kconfig         |  13 +++
- drivers/cpufreq/Makefile        |   1 +
- drivers/cpufreq/cpufreq-krait.c | 190 ++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 204 insertions(+)
- create mode 100644 drivers/cpufreq/cpufreq-krait.c
-
---- a/drivers/cpufreq/Kconfig
-+++ b/drivers/cpufreq/Kconfig
-@@ -198,6 +198,19 @@ config CPUFREQ_DT
- 
- 	  If in doubt, say N.
- 
-+config GENERIC_CPUFREQ_KRAIT
-+	tristate "Krait cpufreq driver"
-+	depends on HAVE_CLK && OF
-+	# if CPU_THERMAL is on and THERMAL=m, CPU0 cannot be =y:
-+	depends on !CPU_THERMAL || THERMAL
-+	select PM_OPP
-+	help
-+	  This adds a generic cpufreq driver for CPU0 frequency management.
-+	  It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
-+	  systems which share clock and voltage across all CPUs.
-+
-+	  If in doubt, say N.
-+
- if X86
- source "drivers/cpufreq/Kconfig.x86"
- endif
---- a/drivers/cpufreq/Makefile
-+++ b/drivers/cpufreq/Makefile
-@@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)
- obj-$(CONFIG_CPU_FREQ_GOV_COMMON)		+= cpufreq_governor.o
- 
- obj-$(CONFIG_CPUFREQ_DT)		+= cpufreq-dt.o
-+obj-$(CONFIG_GENERIC_CPUFREQ_KRAIT)	+= cpufreq-krait.o
- 
- ##################################################################################
- # x86 drivers.
---- /dev/null
-+++ b/drivers/cpufreq/cpufreq-krait.c
-@@ -0,0 +1,390 @@
-+/*
-+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
-+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
-+ *
-+ * The OPP code in function krait_set_target() is reused from
-+ * drivers/cpufreq/omap-cpufreq.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/cpu.h>
-+#include <linux/cpu_cooling.h>
-+#include <linux/cpufreq.h>
-+#include <linux/cpumask.h>
-+#include <linux/err.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/pm_opp.h>
-+#include <linux/platform_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <linux/thermal.h>
-+
-+static unsigned int transition_latency;
-+static unsigned int voltage_tolerance; /* in percentage */
-+
-+static struct device *cpu_dev;
-+static DEFINE_PER_CPU(struct clk *, krait_cpu_clks);
-+static DEFINE_PER_CPU(struct regulator *, krait_supply_core);
-+static struct cpufreq_frequency_table *freq_table;
-+static struct thermal_cooling_device *cdev;
-+
-+struct cache_points {
-+	unsigned long cache_freq;
-+	unsigned int cache_volt;
-+	unsigned long cpu_freq;
-+};
-+
-+static struct regulator *krait_l2_reg;
-+static struct clk *krait_l2_clk;
-+static struct cache_points *krait_l2_points;
-+static int nr_krait_l2_points;
-+
-+static int krait_parse_cache_points(struct device *dev,
-+		struct device_node *of_node)
-+{
-+	const struct property *prop;
-+	const __be32 *val;
-+	int nr, i;
-+
-+	prop = of_find_property(of_node, "cache-points-kHz", NULL);
-+	if (!prop)
-+		return -ENODEV;
-+	if (!prop->value)
-+		return -ENODATA;
-+
-+	/*
-+	 * Each OPP is a set of tuples consisting of frequency and
-+	 * cpu-frequency like <freq-kHz volt-uV freq-kHz>.
-+	 */
-+	nr = prop->length / sizeof(u32);
-+	if (nr % 3) {
-+		dev_err(dev, "%s: Invalid cache points\n", __func__);
-+		return -EINVAL;
-+	}
-+	nr /= 3;
-+
-+	krait_l2_points = devm_kcalloc(dev, nr, sizeof(*krait_l2_points),
-+				       GFP_KERNEL);
-+	if (!krait_l2_points)
-+		return -ENOMEM;
-+	nr_krait_l2_points = nr;
-+
-+	for (i = 0, val = prop->value; i < nr; i++) {
-+		unsigned long cache_freq = be32_to_cpup(val++) * 1000;
-+		unsigned int cache_volt = be32_to_cpup(val++);
-+		unsigned long cpu_freq = be32_to_cpup(val++) * 1000;
-+
-+		krait_l2_points[i].cache_freq = cache_freq;
-+		krait_l2_points[i].cache_volt = cache_volt;
-+		krait_l2_points[i].cpu_freq = cpu_freq;
-+	}
-+
-+	return 0;
-+}
-+
-+static int krait_set_target(struct cpufreq_policy *policy, unsigned int index)
-+{
-+	struct dev_pm_opp *opp;
-+	unsigned long volt = 0, volt_old = 0, tol = 0;
-+	unsigned long freq, max_cpu_freq = 0;
-+	unsigned int old_freq, new_freq;
-+	long freq_Hz, freq_exact;
-+	int ret, i;
-+	struct clk *cpu_clk;
-+	struct regulator *core;
-+	unsigned int cpu;
-+
-+	cpu_clk = per_cpu(krait_cpu_clks, policy->cpu);
-+
-+	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
-+	if (freq_Hz <= 0)
-+		freq_Hz = freq_table[index].frequency * 1000;
-+
-+	freq_exact = freq_Hz;
-+	new_freq = freq_Hz / 1000;
-+	old_freq = clk_get_rate(cpu_clk) / 1000;
-+
-+	core = per_cpu(krait_supply_core, policy->cpu);
-+
-+	rcu_read_lock();
-+	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
-+	if (IS_ERR(opp)) {
-+		rcu_read_unlock();
-+		pr_err("failed to find OPP for %ld\n", freq_Hz);
-+		return PTR_ERR(opp);
-+	}
-+	volt = dev_pm_opp_get_voltage(opp);
-+	rcu_read_unlock();
-+	tol = volt * voltage_tolerance / 100;
-+	volt_old = regulator_get_voltage(core);
-+
-+	pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
-+		 old_freq / 1000, volt_old ? volt_old / 1000 : -1,
-+		 new_freq / 1000, volt ? volt / 1000 : -1);
-+
-+	/* scaling up?  scale voltage before frequency */
-+	if (new_freq > old_freq) {
-+		ret = regulator_set_voltage_tol(core, volt, tol);
-+		if (ret) {
-+			pr_err("failed to scale voltage up: %d\n", ret);
-+			return ret;
-+		}
-+	}
-+
-+	ret = clk_set_rate(cpu_clk, freq_exact);
-+	if (ret) {
-+		pr_err("failed to set clock rate: %d\n", ret);
-+		return ret;
-+	}
-+
-+	/* scaling down?  scale voltage after frequency */
-+	if (new_freq < old_freq) {
-+		ret = regulator_set_voltage_tol(core, volt, tol);
-+		if (ret) {
-+			pr_err("failed to scale voltage down: %d\n", ret);
-+			clk_set_rate(cpu_clk, old_freq * 1000);
-+		}
-+	}
-+
-+	for_each_possible_cpu(cpu) {
-+		freq = clk_get_rate(per_cpu(krait_cpu_clks, cpu));
-+		max_cpu_freq = max(max_cpu_freq, freq);
-+	}
-+
-+	for (i = 0; i < nr_krait_l2_points; i++) {
-+		if (max_cpu_freq >= krait_l2_points[i].cpu_freq) {
-+			if (krait_l2_reg) {
-+				ret = regulator_set_voltage_tol(krait_l2_reg,
-+						krait_l2_points[i].cache_volt,
-+						tol);
-+				if (ret) {
-+					pr_err("failed to scale l2 voltage: %d\n",
-+						ret);
-+				}
-+			}
-+			ret = clk_set_rate(krait_l2_clk,
-+					krait_l2_points[i].cache_freq);
-+			if (ret)
-+				pr_err("failed to scale l2 clk: %d\n", ret);
-+			break;
-+		}
-+
-+	}
-+
-+	return ret;
-+}
-+
-+static int krait_cpufreq_init(struct cpufreq_policy *policy)
-+{
-+	int ret;
-+
-+	policy->clk = per_cpu(krait_cpu_clks, policy->cpu);
-+
-+	ret = cpufreq_table_validate_and_show(policy, freq_table);
-+	if (ret) {
-+		pr_err("%s: invalid frequency table: %d\n", __func__, ret);
-+		return ret;
-+	}
-+
-+	policy->cpuinfo.transition_latency = transition_latency;
-+
-+	return 0;
-+}
-+
-+static struct cpufreq_driver krait_cpufreq_driver = {
-+	.flags = CPUFREQ_STICKY,
-+	.verify = cpufreq_generic_frequency_table_verify,
-+	.target_index = krait_set_target,
-+	.get = cpufreq_generic_get,
-+	.init = krait_cpufreq_init,
-+	.name = "generic_krait",
-+	.attr = cpufreq_generic_attr,
-+};
-+
-+static int krait_cpufreq_probe(struct platform_device *pdev)
-+{
-+	struct device_node *np, *cache;
-+	int ret, i;
-+	unsigned int cpu;
-+	struct device *dev;
-+	struct clk *clk;
-+	struct regulator *core;
-+	unsigned long freq_Hz, freq, max_cpu_freq;
-+	struct dev_pm_opp *opp;
-+	unsigned long volt, tol;
-+
-+	cpu_dev = get_cpu_device(0);
-+	if (!cpu_dev) {
-+		pr_err("failed to get krait device\n");
-+		return -ENODEV;
-+	}
-+
-+	np = of_node_get(cpu_dev->of_node);
-+	if (!np) {
-+		pr_err("failed to find krait node\n");
-+		return -ENOENT;
-+	}
-+
-+	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
-+	if (ret) {
-+		pr_err("failed to init cpufreq table: %d\n", ret);
-+		goto out_put_node;
-+	}
-+
-+	of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
-+
-+	if (of_property_read_u32(np, "clock-latency", &transition_latency))
-+		transition_latency = CPUFREQ_ETERNAL;
-+
-+	cache = of_find_next_cache_node(np);
-+	if (cache) {
-+		struct device_node *vdd;
-+
-+		vdd = of_parse_phandle(cache, "vdd_dig-supply", 0);
-+		if (vdd) {
-+			krait_l2_reg = regulator_get(NULL, vdd->name);
-+			if (IS_ERR(krait_l2_reg)) {
-+				pr_warn("failed to get l2 vdd_dig supply\n");
-+				krait_l2_reg = NULL;
-+			}
-+			of_node_put(vdd);
-+		}
-+
-+		krait_l2_clk = of_clk_get(cache, 0);
-+		if (!IS_ERR(krait_l2_clk)) {
-+			ret = krait_parse_cache_points(&pdev->dev, cache);
-+			if (ret)
-+				clk_put(krait_l2_clk);
-+		}
-+		if (IS_ERR(krait_l2_clk) || ret)
-+			krait_l2_clk = NULL;
-+	}
-+
-+	for_each_possible_cpu(cpu) {
-+		dev = get_cpu_device(cpu);
-+		if (!dev) {
-+			pr_err("failed to get krait device\n");
-+			ret = -ENOENT;
-+			goto out_free_table;
-+		}
-+		per_cpu(krait_cpu_clks, cpu) = clk = devm_clk_get(dev, NULL);
-+		if (IS_ERR(clk)) {
-+			ret = PTR_ERR(clk);
-+			goto out_free_table;
-+		}
-+		core = devm_regulator_get(dev, "core");
-+		if (IS_ERR(core)) {
-+			pr_debug("failed to get core regulator\n");
-+			ret = PTR_ERR(core);
-+			goto out_free_table;
-+		}
-+		per_cpu(krait_supply_core, cpu) = core;
-+
-+		freq_Hz = clk_get_rate(clk);
-+
-+		rcu_read_lock();
-+		opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
-+		if (IS_ERR(opp)) {
-+			rcu_read_unlock();
-+			pr_err("failed to find OPP for %ld\n", freq_Hz);
-+			ret = PTR_ERR(opp);
-+			goto out_free_table;
-+		}
-+		volt = dev_pm_opp_get_voltage(opp);
-+		rcu_read_unlock();
-+
-+		tol = volt * voltage_tolerance / 100;
-+		ret = regulator_set_voltage_tol(core, volt, tol);
-+		if (ret) {
-+			pr_err("failed to scale voltage up: %d\n", ret);
-+			goto out_free_table;
-+		}
-+		ret = regulator_enable(core);
-+		if (ret) {
-+			pr_err("failed to enable regulator: %d\n", ret);
-+			goto out_free_table;
-+		}
-+		max_cpu_freq = max(max_cpu_freq, freq);
-+	}
-+
-+	for (i = 0; i < nr_krait_l2_points; i++) {
-+		if (max_cpu_freq >= krait_l2_points[i].cpu_freq) {
-+			if (krait_l2_reg) {
-+				ret = regulator_set_voltage_tol(krait_l2_reg,
-+						krait_l2_points[i].cache_volt,
-+						tol);
-+				if (ret)
-+					pr_err("failed to scale l2 voltage: %d\n",
-+							ret);
-+				ret = regulator_enable(krait_l2_reg);
-+				if (ret)
-+					pr_err("failed to enable l2 voltage: %d\n",
-+							ret);
-+			}
-+			break;
-+		}
-+
-+	}
-+
-+	ret = cpufreq_register_driver(&krait_cpufreq_driver);
-+	if (ret) {
-+		pr_err("failed register driver: %d\n", ret);
-+		goto out_free_table;
-+	}
-+	of_node_put(np);
-+
-+	/*
-+	 * For now, just loading the cooling device;
-+	 * thermal DT code takes care of matching them.
-+	 */
-+	for_each_possible_cpu(cpu) {
-+		dev = get_cpu_device(cpu);
-+		np = of_node_get(dev->of_node);
-+		if (of_find_property(np, "#cooling-cells", NULL)) {
-+			cdev = of_cpufreq_cooling_register(np, cpumask_of(cpu));
-+			if (IS_ERR(cdev))
-+				pr_err("running cpufreq without cooling device: %ld\n",
-+				       PTR_ERR(cdev));
-+		}
-+		of_node_put(np);
-+	}
-+
-+	return 0;
-+
-+out_free_table:
-+	regulator_put(krait_l2_reg);
-+	clk_put(krait_l2_clk);
-+	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
-+out_put_node:
-+	of_node_put(np);
-+	return ret;
-+}
-+
-+static int krait_cpufreq_remove(struct platform_device *pdev)
-+{
-+	cpufreq_cooling_unregister(cdev);
-+	cpufreq_unregister_driver(&krait_cpufreq_driver);
-+	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
-+	clk_put(krait_l2_clk);
-+	regulator_put(krait_l2_reg);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver krait_cpufreq_platdrv = {
-+	.driver = {
-+		.name	= "cpufreq-krait",
-+		.owner	= THIS_MODULE,
-+	},
-+	.probe		= krait_cpufreq_probe,
-+	.remove		= krait_cpufreq_remove,
-+};
-+module_platform_driver(krait_cpufreq_platdrv);
-+
-+MODULE_DESCRIPTION("Krait CPUfreq driver");
-+MODULE_LICENSE("GPL v2");
---- a/drivers/cpufreq/qcom-cpufreq.c
-+++ b/drivers/cpufreq/qcom-cpufreq.c
-@@ -168,11 +168,8 @@ static int __init qcom_cpufreq_populate_
- 
- static int __init qcom_cpufreq_driver_init(void)
- {
--	struct cpufreq_dt_platform_data pdata = { .independent_clocks = true };
- 	struct platform_device_info devinfo = {
--		.name = "cpufreq-dt",
--		.data = &pdata,
--		.size_data = sizeof(pdata),
-+		.name = "cpufreq-krait",
- 	};
- 	struct device *cpu_dev;
- 	struct device_node *np;
diff --git a/target/linux/ipq806x/patches-4.0/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch b/target/linux/ipq806x/patches-4.0/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch
deleted file mode 100644
index 930a463..0000000
--- a/target/linux/ipq806x/patches-4.0/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From b12e230f09d4481424e6a5d7e2ae566b6954e83f Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Wed, 29 Apr 2015 15:21:46 -0700
-Subject: [PATCH] HACK: arch: arm: force ZRELADDR on arch-qcom
-
-ARCH_QCOM is using the ARCH_MULTIPLATFORM option, as now recommended
-on most ARM architectures. This automatically calculate ZRELADDR by
-masking PHYS_OFFSET with 0xf8000000.
-
-However, on IPQ806x, the first ~20MB of RAM is reserved for the hardware
-network accelerators, and the bootloader removes this section from the
-layout passed from the ATAGS (when used).
-
-For newer bootloader, when DT is used, this is not a problem, we just
-reserve this memory in the device tree. But if the bootloader doesn't
-have DT support, then ATAGS have to be used. In this case, the ARM
-decompressor will position the kernel in this low mem, which will not be
-in the RAM section mapped by the bootloader, which means the kernel will
-freeze in the middle of the boot process trying to map the memory.
-
-As a work around, this patch allows disabling AUTO_ZRELADDR when
-ARCH_QCOM is selected. It makes the zImage usage possible on bootloaders
-which don't support device-tree, which is the case on certain early
-IPQ806x based designs.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/Kconfig                 | 2 +-
- arch/arm/Makefile                | 2 ++
- arch/arm/mach-qcom/Makefile.boot | 1 +
- 3 files changed, 4 insertions(+), 1 deletion(-)
- create mode 100644 arch/arm/mach-qcom/Makefile.boot
-
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -314,7 +314,7 @@ config ARCH_MULTIPLATFORM
- 	select ARCH_WANT_OPTIONAL_GPIOLIB
- 	select ARM_HAS_SG_CHAIN
- 	select ARM_PATCH_PHYS_VIRT
--	select AUTO_ZRELADDR
-+	select AUTO_ZRELADDR if !ARCH_QCOM
- 	select CLKSRC_OF
- 	select COMMON_CLK
- 	select GENERIC_CLOCKEVENTS
---- a/arch/arm/Makefile
-+++ b/arch/arm/Makefile
-@@ -241,9 +241,11 @@ MACHINE  := arch/arm/mach-$(word 1,$(mac
- else
- MACHINE  :=
- endif
-+ifeq ($(CONFIG_ARCH_QCOM),)
- ifeq ($(CONFIG_ARCH_MULTIPLATFORM),y)
- MACHINE  :=
- endif
-+endif
- 
- machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
- platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
---- /dev/null
-+++ b/arch/arm/mach-qcom/Makefile.boot
-@@ -0,0 +1 @@
-+zreladdr-y+= 0x42208000
diff --git a/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
deleted file mode 100644
index 1b9d47b..0000000
--- a/target/linux/ipq806x/patches-4.0/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
+++ /dev/null
@@ -1,733 +0,0 @@
-From 2fbb18f85826a9ba308fedb2cf90d3a661a39fd7 Mon Sep 17 00:00:00 2001
-From: Stephen Boyd <sboyd@codeaurora.org>
-Date: Fri, 27 Mar 2015 00:16:14 -0700
-Subject: [PATCH] clk: qcom: Add support for NSS/GMAC clocks and resets
-
-Add the NSS/GMAC clocks and the TCM clock and NSS resets.
-
-Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
----
- drivers/clk/qcom/gcc-ipq806x.c               | 594 ++++++++++++++++++++++++++-
- drivers/clk/qcom/gcc-ipq806x.c.rej           |  50 +++
- include/dt-bindings/clock/qcom,gcc-ipq806x.h |   2 +
- include/dt-bindings/reset/qcom,gcc-ipq806x.h |  43 ++
- 4 files changed, 688 insertions(+), 1 deletion(-)
- create mode 100644 drivers/clk/qcom/gcc-ipq806x.c.rej
-
---- a/drivers/clk/qcom/gcc-ipq806x.c
-+++ b/drivers/clk/qcom/gcc-ipq806x.c
-@@ -220,11 +220,46 @@ static struct clk_regmap pll14_vote = {
- 	},
- };
- 
-+#define NSS_PLL_RATE(f, _l, _m, _n, i) \
-+	{  \
-+		.freq = f,  \
-+		.l = _l, \
-+		.m = _m, \
-+		.n = _n, \
-+		.ibits = i, \
-+	}
-+
-+static struct pll_freq_tbl pll18_freq_tbl[] = {
-+	NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625),
-+	NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625),
-+};
-+
-+static struct clk_pll pll18 = {
-+	.l_reg = 0x31a4,
-+	.m_reg = 0x31a8,
-+	.n_reg = 0x31ac,
-+	.config_reg = 0x31b4,
-+	.mode_reg = 0x31a0,
-+	.status_reg = 0x31b8,
-+	.status_bit = 16,
-+	.post_div_shift = 16,
-+	.post_div_width = 1,
-+	.freq_tbl = pll18_freq_tbl,
-+	.clkr.hw.init = &(struct clk_init_data){
-+		.name = "pll18",
-+		.parent_names = (const char *[]){ "pxo" },
-+		.num_parents = 1,
-+		.ops = &clk_pll_ops,
-+	},
-+};
-+
- #define P_PXO	0
- #define P_PLL8	1
- #define P_PLL3	1
- #define P_PLL0	2
- #define P_CXO	2
-+#define P_PLL14	3
-+#define P_PLL18 4
- 
- static const u8 gcc_pxo_pll8_map[] = {
- 	[P_PXO]		= 0,
-@@ -275,6 +310,22 @@ static const char *gcc_pxo_pll8_pll0_map
- 	"pll0_vote",
- };
- 
-+static const u8 gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
-+	[P_PXO] = 0 ,
-+	[P_PLL8] = 4,
-+	[P_PLL0] = 2,
-+	[P_PLL14] = 5,
-+	[P_PLL18] = 1,
-+};
-+
-+static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
-+	"pxo",
-+	"pll8_vote",
-+	"pll0_vote",
-+	"pll14",
-+	"pll18",
-+};
-+
- static struct freq_tbl clk_tbl_gsbi_uart[] = {
- 	{  1843200, P_PLL8, 2,  6, 625 },
- 	{  3686400, P_PLL8, 2, 12, 625 },
-@@ -2250,6 +2301,472 @@ static struct clk_branch usb_fs1_h_clk =
- 	},
- };
- 
-+static const struct freq_tbl clk_tbl_gmac[] = {
-+	{ 133000000, P_PLL0, 1,  50, 301 },
-+	{ 266000000, P_PLL0, 1, 127, 382 },
-+	{ }
-+};
-+
-+static struct clk_dyn_rcg gmac_core1_src = {
-+	.ns_reg[0] = 0x3cac,
-+	.ns_reg[1] = 0x3cb0,
-+	.md_reg[0] = 0x3ca4,
-+	.md_reg[1] = 0x3ca8,
-+	.bank_reg = 0x3ca0,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_gmac,
-+	.clkr = {
-+		.enable_reg = 0x3ca0,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core1_src",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+		},
-+	},
-+};
-+
-+static struct clk_branch gmac_core1_clk = {
-+	.halt_reg = 0x3c20,
-+	.halt_bit = 4,
-+	.hwcg_reg = 0x3cb4,
-+	.hwcg_bit = 6,
-+	.clkr = {
-+		.enable_reg = 0x3cb4,
-+		.enable_mask = BIT(4),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core1_clk",
-+			.parent_names = (const char *[]){
-+				"gmac_core1_src",
-+			},
-+			.num_parents = 1,
-+			.ops = &clk_branch_ops,
-+			.flags = CLK_SET_RATE_PARENT,
-+		},
-+	},
-+};
-+
-+static struct clk_dyn_rcg gmac_core2_src = {
-+	.ns_reg[0] = 0x3ccc,
-+	.ns_reg[1] = 0x3cd0,
-+	.md_reg[0] = 0x3cc4,
-+	.md_reg[1] = 0x3cc8,
-+	.bank_reg = 0x3ca0,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_gmac,
-+	.clkr = {
-+		.enable_reg = 0x3cc0,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core2_src",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+		},
-+	},
-+};
-+
-+static struct clk_branch gmac_core2_clk = {
-+	.halt_reg = 0x3c20,
-+	.halt_bit = 5,
-+	.hwcg_reg = 0x3cd4,
-+	.hwcg_bit = 6,
-+	.clkr = {
-+		.enable_reg = 0x3cd4,
-+		.enable_mask = BIT(4),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core2_clk",
-+			.parent_names = (const char *[]){
-+				"gmac_core2_src",
-+			},
-+			.num_parents = 1,
-+			.ops = &clk_branch_ops,
-+			.flags = CLK_SET_RATE_PARENT,
-+		},
-+	},
-+};
-+
-+static struct clk_dyn_rcg gmac_core3_src = {
-+	.ns_reg[0] = 0x3cec,
-+	.ns_reg[1] = 0x3cf0,
-+	.md_reg[0] = 0x3ce4,
-+	.md_reg[1] = 0x3ce8,
-+	.bank_reg = 0x3ce0,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_gmac,
-+	.clkr = {
-+		.enable_reg = 0x3ce0,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core3_src",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+		},
-+	},
-+};
-+
-+static struct clk_branch gmac_core3_clk = {
-+	.halt_reg = 0x3c20,
-+	.halt_bit = 6,
-+	.hwcg_reg = 0x3cf4,
-+	.hwcg_bit = 6,
-+	.clkr = {
-+		.enable_reg = 0x3cf4,
-+		.enable_mask = BIT(4),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core3_clk",
-+			.parent_names = (const char *[]){
-+				"gmac_core3_src",
-+			},
-+			.num_parents = 1,
-+			.ops = &clk_branch_ops,
-+			.flags = CLK_SET_RATE_PARENT,
-+		},
-+	},
-+};
-+
-+static struct clk_dyn_rcg gmac_core4_src = {
-+	.ns_reg[0] = 0x3d0c,
-+	.ns_reg[1] = 0x3d10,
-+	.md_reg[0] = 0x3d04,
-+	.md_reg[1] = 0x3d08,
-+	.bank_reg = 0x3d00,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_gmac,
-+	.clkr = {
-+		.enable_reg = 0x3d00,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core4_src",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+		},
-+	},
-+};
-+
-+static struct clk_branch gmac_core4_clk = {
-+	.halt_reg = 0x3c20,
-+	.halt_bit = 7,
-+	.hwcg_reg = 0x3d14,
-+	.hwcg_bit = 6,
-+	.clkr = {
-+		.enable_reg = 0x3d14,
-+		.enable_mask = BIT(4),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "gmac_core4_clk",
-+			.parent_names = (const char *[]){
-+				"gmac_core4_src",
-+			},
-+			.num_parents = 1,
-+			.ops = &clk_branch_ops,
-+			.flags = CLK_SET_RATE_PARENT,
-+		},
-+	},
-+};
-+
-+static const struct freq_tbl clk_tbl_nss_tcm[] = {
-+	{ 266000000, P_PLL0, 3, 0, 0 },
-+	{ 400000000, P_PLL0, 2, 0, 0 },
-+	{ }
-+};
-+
-+static struct clk_dyn_rcg nss_tcm_src = {
-+	.ns_reg[0] = 0x3dc4,
-+	.ns_reg[1] = 0x3dc8,
-+	.bank_reg = 0x3dc0,
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 4,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 4,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_nss_tcm,
-+	.clkr = {
-+		.enable_reg = 0x3dc0,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "nss_tcm_src",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+		},
-+	},
-+};
-+
-+static struct clk_branch nss_tcm_clk = {
-+	.halt_reg = 0x3c20,
-+	.halt_bit = 14,
-+	.clkr = {
-+		.enable_reg = 0x3dd0,
-+		.enable_mask = BIT(6) | BIT(4),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "nss_tcm_clk",
-+			.parent_names = (const char *[]){
-+				"nss_tcm_src",
-+			},
-+			.num_parents = 1,
-+			.ops = &clk_branch_ops,
-+			.flags = CLK_SET_RATE_PARENT,
-+		},
-+	},
-+};
-+
-+static const struct freq_tbl clk_tbl_nss[] = {
-+	{ 110000000, P_PLL18, 1, 1, 5 },
-+	{ 275000000, P_PLL18, 2, 0, 0 },
-+	{ 550000000, P_PLL18, 1, 0, 0 },
-+	{ 733000000, P_PLL18, 1, 0, 0 },
-+	{ }
-+};
-+
-+static struct clk_dyn_rcg ubi32_core1_src_clk = {
-+	.ns_reg[0] = 0x3d2c,
-+	.ns_reg[1] = 0x3d30,
-+	.md_reg[0] = 0x3d24,
-+	.md_reg[1] = 0x3d28,
-+	.bank_reg = 0x3d20,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_nss,
-+	.clkr = {
-+		.enable_reg = 0x3d20,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "ubi32_core1_src_clk",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
-+		},
-+	},
-+};
-+
-+static struct clk_dyn_rcg ubi32_core2_src_clk = {
-+	.ns_reg[0] = 0x3d4c,
-+	.ns_reg[1] = 0x3d50,
-+	.md_reg[0] = 0x3d44,
-+	.md_reg[1] = 0x3d48,
-+	.bank_reg = 0x3d40,
-+	.mn[0] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.mn[1] = {
-+		.mnctr_en_bit = 8,
-+		.mnctr_reset_bit = 7,
-+		.mnctr_mode_shift = 5,
-+		.n_val_shift = 16,
-+		.m_val_shift = 16,
-+		.width = 8,
-+	},
-+	.s[0] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.s[1] = {
-+		.src_sel_shift = 0,
-+		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
-+	},
-+	.p[0] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.p[1] = {
-+		.pre_div_shift = 3,
-+		.pre_div_width = 2,
-+	},
-+	.mux_sel_bit = 0,
-+	.freq_tbl = clk_tbl_nss,
-+	.clkr = {
-+		.enable_reg = 0x3d40,
-+		.enable_mask = BIT(1),
-+		.hw.init = &(struct clk_init_data){
-+			.name = "ubi32_core2_src_clk",
-+			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
-+			.num_parents = 5,
-+			.ops = &clk_dyn_rcg_ops,
-+			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
-+		},
-+	},
-+};
-+
- static struct clk_regmap *gcc_ipq806x_clks[] = {
- 	[PLL0] = &pll0.clkr,
- 	[PLL0_VOTE] = &pll0_vote,
-@@ -2259,6 +2776,7 @@ static struct clk_regmap *gcc_ipq806x_cl
- 	[PLL8_VOTE] = &pll8_vote,
- 	[PLL14] = &pll14.clkr,
- 	[PLL14_VOTE] = &pll14_vote,
-+	[PLL18] = &pll18.clkr,
- 	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
- 	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
- 	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
-@@ -2356,6 +2874,18 @@ static struct clk_regmap *gcc_ipq806x_cl
- 	[PLL9] = &hfpll0.clkr,
- 	[PLL10] = &hfpll1.clkr,
- 	[PLL12] = &hfpll_l2.clkr,
-+	[GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr,
-+	[GMAC_CORE1_CLK] = &gmac_core1_clk.clkr,
-+	[GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr,
-+	[GMAC_CORE2_CLK] = &gmac_core2_clk.clkr,
-+	[GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr,
-+	[GMAC_CORE3_CLK] = &gmac_core3_clk.clkr,
-+	[GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr,
-+	[GMAC_CORE4_CLK] = &gmac_core4_clk.clkr,
-+	[UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr,
-+	[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
-+	[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
-+	[NSSTCM_CLK] = &nss_tcm_clk.clkr,
- };
- 
- static const struct qcom_reset_map gcc_ipq806x_resets[] = {
-@@ -2474,6 +3004,48 @@ static const struct qcom_reset_map gcc_i
- 	[USB30_1_PHY_RESET] = { 0x3b58, 0 },
- 	[NSSFB0_RESET] = { 0x3b60, 6 },
- 	[NSSFB1_RESET] = { 0x3b60, 7 },
-+	[UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3},
-+	[UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 },
-+	[UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 },
-+	[UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 },
-+	[UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 },
-+	[UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 },
-+	[UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 },
-+	[UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 },
-+	[GMAC_CORE1_RESET] = { 0x3cbc, 0 },
-+	[GMAC_CORE2_RESET] = { 0x3cdc, 0 },
-+	[GMAC_CORE3_RESET] = { 0x3cfc, 0 },
-+	[GMAC_CORE4_RESET] = { 0x3d1c, 0 },
-+	[GMAC_AHB_RESET] = { 0x3e24, 0 },
-+	[NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 },
-+	[NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 },
-+	[NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 },
-+	[NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 },
-+	[NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 },
-+	[NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 },
-+	[NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 },
-+	[NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 },
-+	[NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 },
-+	[NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 },
-+	[NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 },
-+	[NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 },
-+	[NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 },
-+	[NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 },
-+	[NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 },
-+	[NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 },
-+	[NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 },
-+	[NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 },
-+	[NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 },
-+	[NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 },
-+	[NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 },
-+	[NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 },
-+	[NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 },
-+	[NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 },
-+	[NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 },
-+	[NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 },
-+	[NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 },
-+	[NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 },
-+	[NSS_SRDS_N_RESET] = { 0x3b60, 28 },
- };
- 
- static const struct regmap_config gcc_ipq806x_regmap_config = {
-@@ -2502,6 +3074,8 @@ static int gcc_ipq806x_probe(struct plat
- {
- 	struct clk *clk;
- 	struct device *dev = &pdev->dev;
-+	struct regmap *regmap;
-+	int ret;
- 
- 	/* Temporary until RPM clocks supported */
- 	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
-@@ -2512,7 +3086,25 @@ static int gcc_ipq806x_probe(struct plat
- 	if (IS_ERR(clk))
- 		return PTR_ERR(clk);
- 
--	return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
-+	ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
-+	if (ret)
-+		return ret;
-+
-+	regmap = dev_get_regmap(dev, NULL);
-+	if (!regmap)
-+		return -ENODEV;
-+
-+	/* Setup PLL18 static bits */
-+	regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400);
-+	regmap_write(regmap, 0x31b0, 0x3080);
-+
-+	/* Set GMAC footswitch sleep/wakeup values */
-+	regmap_write(regmap, 0x3cb8, 8);
-+	regmap_write(regmap, 0x3cd8, 8);
-+	regmap_write(regmap, 0x3cf8, 8);
-+	regmap_write(regmap, 0x3d18, 8);
-+
-+	return 0;
- }
- 
- static int gcc_ipq806x_remove(struct platform_device *pdev)
---- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h
-+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h
-@@ -288,5 +288,7 @@
- #define UBI32_CORE2_CLK_SRC			278
- #define UBI32_CORE1_CLK				279
- #define UBI32_CORE2_CLK				280
-+#define NSSTCM_CLK_SRC				281
-+#define NSSTCM_CLK				282
- 
- #endif
---- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h
-+++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h
-@@ -129,4 +129,47 @@
- #define USB30_1_PHY_RESET				112
- #define NSSFB0_RESET					113
- #define NSSFB1_RESET					114
-+#define UBI32_CORE1_CLKRST_CLAMP_RESET			115
-+#define UBI32_CORE1_CLAMP_RESET				116
-+#define UBI32_CORE1_AHB_RESET				117
-+#define UBI32_CORE1_AXI_RESET				118
-+#define UBI32_CORE2_CLKRST_CLAMP_RESET			119
-+#define UBI32_CORE2_CLAMP_RESET				120
-+#define UBI32_CORE2_AHB_RESET				121
-+#define UBI32_CORE2_AXI_RESET				122
-+#define GMAC_CORE1_RESET				123
-+#define GMAC_CORE2_RESET				124
-+#define GMAC_CORE3_RESET				125
-+#define GMAC_CORE4_RESET				126
-+#define GMAC_AHB_RESET					127
-+#define NSS_CH0_RST_RX_CLK_N_RESET			128
-+#define NSS_CH0_RST_TX_CLK_N_RESET			129
-+#define NSS_CH0_RST_RX_125M_N_RESET			130
-+#define NSS_CH0_HW_RST_RX_125M_N_RESET			131
-+#define NSS_CH0_RST_TX_125M_N_RESET			132
-+#define NSS_CH1_RST_RX_CLK_N_RESET			133
-+#define NSS_CH1_RST_TX_CLK_N_RESET			134
-+#define NSS_CH1_RST_RX_125M_N_RESET			135
-+#define NSS_CH1_HW_RST_RX_125M_N_RESET			136
-+#define NSS_CH1_RST_TX_125M_N_RESET			137
-+#define NSS_CH2_RST_RX_CLK_N_RESET			138
-+#define NSS_CH2_RST_TX_CLK_N_RESET			139
-+#define NSS_CH2_RST_RX_125M_N_RESET			140
-+#define NSS_CH2_HW_RST_RX_125M_N_RESET			141
-+#define NSS_CH2_RST_TX_125M_N_RESET			142
-+#define NSS_CH3_RST_RX_CLK_N_RESET			143
-+#define NSS_CH3_RST_TX_CLK_N_RESET			144
-+#define NSS_CH3_RST_RX_125M_N_RESET			145
-+#define NSS_CH3_HW_RST_RX_125M_N_RESET			146
-+#define NSS_CH3_RST_TX_125M_N_RESET			147
-+#define NSS_RST_RX_250M_125M_N_RESET			148
-+#define NSS_RST_TX_250M_125M_N_RESET			149
-+#define NSS_QSGMII_TXPI_RST_N_RESET			150
-+#define NSS_QSGMII_CDR_RST_N_RESET			151
-+#define NSS_SGMII2_CDR_RST_N_RESET			152
-+#define NSS_SGMII3_CDR_RST_N_RESET			153
-+#define NSS_CAL_PRBS_RST_N_RESET			154
-+#define NSS_LCKDT_RST_N_RESET				155
-+#define NSS_SRDS_N_RESET				156
-+
- #endif
diff --git a/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch b/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
deleted file mode 100644
index e94a746..0000000
--- a/target/linux/ipq806x/patches-4.0/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From 4f09499bc1d9bb095caccbcd73ff951ee631e521 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Fri, 8 May 2015 15:42:40 -0700
-Subject: [PATCH 1/8] stmmac: add phy-handle support to the platform layer
-
-On stmmac driver, PHY specification in device-tree was done using the
-non-standard property "snps,phy-addr". Specifying a PHY on a different
-MDIO bus that the one within the stmmac controller doesn't seem to be
-possible when device-tree is used.
-
-This change adds support for the phy-handle property, as specified in
-Documentation/devicetree/bindings/net/ethernet.txt.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 28 ++++++++++++++--------
- .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |  6 ++++-
- include/linux/stmmac.h                             |  1 +
- 3 files changed, 24 insertions(+), 11 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -52,6 +52,7 @@
- #include "stmmac_ptp.h"
- #include "stmmac.h"
- #include <linux/reset.h>
-+#include <linux/of_mdio.h>
- 
- #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
- 
-@@ -816,18 +817,25 @@ static int stmmac_init_phy(struct net_de
- 	priv->speed = 0;
- 	priv->oldduplex = -1;
- 
--	if (priv->plat->phy_bus_name)
--		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
--			 priv->plat->phy_bus_name, priv->plat->bus_id);
--	else
--		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
--			 priv->plat->bus_id);
--
--	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
--		 priv->plat->phy_addr);
--	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
-+	if (priv->plat->phy_node) {
-+		phydev = of_phy_connect(dev, priv->plat->phy_node,
-+					&stmmac_adjust_link, 0, interface);
-+	} else {
-+		if (priv->plat->phy_bus_name)
-+			snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
-+				 priv->plat->phy_bus_name, priv->plat->bus_id);
-+		else
-+			snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
-+				 priv->plat->bus_id);
-+
-+		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
-+			 priv->plat->phy_addr);
-+		pr_debug("stmmac_init_phy:  trying to attach to %s\n",
-+			 phy_id_fmt);
- 
--	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
-+		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
-+				     interface);
-+	}
- 
- 	if (IS_ERR(phydev)) {
- 		pr_err("%s: Could not attach to PHY\n", dev->name);
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -27,6 +27,7 @@
- #include <linux/of.h>
- #include <linux/of_net.h>
- #include <linux/of_device.h>
-+#include <linux/of_mdio.h>
- 
- #include "stmmac.h"
- #include "stmmac_platform.h"
-@@ -167,13 +168,16 @@ static int stmmac_probe_config_dt(struct
- 	/* Default to phy auto-detection */
- 	plat->phy_addr = -1;
- 
-+	/* If we find a phy-handle property, use it as the PHY */
-+	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
-+
- 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
- 	 * and warn of its use. Remove this when phy node support is added.
- 	 */
- 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
- 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
- 
--	if (plat->phy_bus_name)
-+	if (plat->phy_node || plat->phy_bus_name)
- 		plat->mdio_bus_data = NULL;
- 	else
- 		plat->mdio_bus_data =
---- a/include/linux/stmmac.h
-+++ b/include/linux/stmmac.h
-@@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
- 	int phy_addr;
- 	int interface;
- 	struct stmmac_mdio_bus_data *mdio_bus_data;
-+	struct device_node *phy_node;
- 	struct stmmac_dma_cfg *dma_cfg;
- 	int clk_csr;
- 	int has_gmac;
diff --git a/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch b/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
deleted file mode 100644
index 3b2134e..0000000
--- a/target/linux/ipq806x/patches-4.0/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 0149d275415cd1b2382ce94e5eb32641590097d0 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Fri, 8 May 2015 15:57:12 -0700
-Subject: [PATCH 2/8] stmmac: move error path at the end of
- stmmac_probe_config_dt()
-
-We will want to do additional clean-up on certain errors. Therefore,
-this change moves the error path at the end of the function for better
-code readability.
-
-This patch doesn't change anything functionally.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 22 ++++++++++++++++------
- 1 file changed, 16 insertions(+), 6 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -129,13 +129,18 @@ static int stmmac_probe_config_dt(struct
- 	struct device_node *np = pdev->dev.of_node;
- 	struct stmmac_dma_cfg *dma_cfg;
- 	const struct of_device_id *device;
-+	int ret;
- 
--	if (!np)
--		return -ENODEV;
-+	if (!np) {
-+		ret = -ENODEV;
-+		goto err;
-+	}
- 
- 	device = of_match_device(stmmac_dt_ids, &pdev->dev);
--	if (!device)
--		return -ENODEV;
-+	if (!device) {
-+		ret = -ENODEV;
-+		goto err;
-+	}
- 
- 	if (device->data) {
- 		const struct stmmac_of_data *data = device->data;
-@@ -231,8 +236,10 @@ static int stmmac_probe_config_dt(struct
- 	if (of_find_property(np, "snps,pbl", NULL)) {
- 		dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
- 				       GFP_KERNEL);
--		if (!dma_cfg)
--			return -ENOMEM;
-+		if (!dma_cfg) {
-+			ret = -ENOMEM;
-+			goto err;
-+		}
- 		plat->dma_cfg = dma_cfg;
- 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
- 		dma_cfg->fixed_burst =
-@@ -250,6 +257,9 @@ static int stmmac_probe_config_dt(struct
- 	}
- 
- 	return 0;
-+
-+err:
-+	return ret;
- }
- #else
- static int stmmac_probe_config_dt(struct platform_device *pdev,
diff --git a/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch b/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch
deleted file mode 100644
index 4b2c9b5..0000000
--- a/target/linux/ipq806x/patches-4.0/703-stmmac-add-fixed-link-device-tree-support.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From 3a95f75867be562cb919ff23a738f70357188fbd Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Fri, 8 May 2015 16:02:03 -0700
-Subject: [PATCH 3/8] stmmac: add fixed-link device-tree support
-
-In case DT is used, this change adds the ability to the stmmac driver to
-detect a fixed-link PHY, instanciate it, and use it during
-phy_connect().
-
-Fixed link PHYs DT usage is described in:
-Documentation/devicetree/bindings/net/fixed-link.txt
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     |  2 +-
- drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 12 +++++++++++-
- 2 files changed, 12 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -856,7 +856,7 @@ static int stmmac_init_phy(struct net_de
- 	 * device as well.
- 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
- 	 */
--	if (phydev->phy_id == 0) {
-+	if (!priv->plat->phy_node && phydev->phy_id == 0) {
- 		phy_disconnect(phydev);
- 		return -ENODEV;
- 	}
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -176,6 +176,14 @@ static int stmmac_probe_config_dt(struct
- 	/* If we find a phy-handle property, use it as the PHY */
- 	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
- 
-+	/* If phy-handle is not specified, check if we have a fixed-phy */
-+	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
-+		if ((of_phy_register_fixed_link(np) < 0))
-+			return -ENODEV;
-+
-+		plat->phy_node = of_node_get(np);
-+	}
-+
- 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
- 	 * and warn of its use. Remove this when phy node support is added.
- 	 */
-@@ -238,7 +246,7 @@ static int stmmac_probe_config_dt(struct
- 				       GFP_KERNEL);
- 		if (!dma_cfg) {
- 			ret = -ENOMEM;
--			goto err;
-+			goto err2;
- 		}
- 		plat->dma_cfg = dma_cfg;
- 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
-@@ -258,6 +266,8 @@ static int stmmac_probe_config_dt(struct
- 
- 	return 0;
- 
-+err2:
-+	of_node_put(np);
- err:
- 	return ret;
- }
diff --git a/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch b/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch
deleted file mode 100644
index fecc958..0000000
--- a/target/linux/ipq806x/patches-4.0/704-stmmac-add-ipq806x-glue-layer.patch
+++ /dev/null
@@ -1,407 +0,0 @@
-From 69fb970ad3fe05af7cb99ea78230c69c7ca0d03b Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Fri, 8 May 2015 16:10:22 -0700
-Subject: [PATCH 4/8] stmmac: add ipq806x glue layer
-
-The ethernet controller available in IPQ806x is a Synopsys DesignWare
-Gigabit MAC IP core, already supported by the stmmac driver.
-
-This glue layer implements some platform specific settings required to
-get the controller working on an IPQ806x based platform.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- drivers/net/ethernet/stmicro/stmmac/Kconfig        |   1 +
- drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
- drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c    | 324 +++++++++++++++++++++
- .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   1 +
- .../net/ethernet/stmicro/stmmac/stmmac_platform.h  |   1 +
- 5 files changed, 328 insertions(+), 1 deletion(-)
- create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c
-
---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
-+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
-@@ -16,6 +16,7 @@ if STMMAC_ETH
- config STMMAC_PLATFORM
- 	tristate "STMMAC Platform bus support"
- 	depends on STMMAC_ETH
-+	select MFD_SYSCON
- 	default y
- 	---help---
- 	  This selects the platform specific bus support for the stmmac driver.
---- a/drivers/net/ethernet/stmicro/stmmac/Makefile
-+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
-@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethto
- 
- obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
- stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o	\
--		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o
-+		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o dwmac-ipq806x.o
- 
- obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
- stmmac-pci-objs:= stmmac_pci.o
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
-@@ -42,6 +42,7 @@ static const struct of_device_id stmmac_
- 	{ .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
- 	{ .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
- 	{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
-+	{ .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data },
- 	{ .compatible = "st,spear600-gmac"},
- 	{ .compatible = "snps,dwmac-3.610"},
- 	{ .compatible = "snps,dwmac-3.70a"},
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
-@@ -25,5 +25,6 @@ extern const struct stmmac_of_data stih4
- extern const struct stmmac_of_data stid127_dwmac_data;
- extern const struct stmmac_of_data socfpga_gmac_data;
- extern const struct stmmac_of_data rk3288_gmac_data;
-+extern const struct stmmac_of_data ipq806x_gmac_data;
- 
- #endif /* __STMMAC_PLATFORM_H__ */
---- /dev/null
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
-@@ -0,0 +1,343 @@
-+/*
-+ * Qualcomm Atheros IPQ806x GMAC glue layer
-+ *
-+ * Copyright (C) 2015 The Linux Foundation
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include <linux/phy.h>
-+#include <linux/regmap.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/of_net.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/stmmac.h>
-+#include <linux/of_mdio.h>
-+
-+#include "stmmac_platform.h"
-+
-+#define NSS_COMMON_CLK_GATE			0x8
-+#define NSS_COMMON_CLK_GATE_PTP_EN(x)		BIT(0x10 + x)
-+#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x)	BIT(0x9 + (x * 2))
-+#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x)	BIT(0x8 + (x * 2))
-+#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x)	BIT(0x4 + x)
-+#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x)	BIT(0x0 + x)
-+
-+#define NSS_COMMON_CLK_DIV0			0xC
-+#define NSS_COMMON_CLK_DIV_OFFSET(x)		(x * 8)
-+#define NSS_COMMON_CLK_DIV_MASK			0x7f
-+
-+#define NSS_COMMON_CLK_SRC_CTRL			0x14
-+#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)	(1 << x)
-+/* Mode is coded on 1 bit but is different depending on the MAC ID:
-+ * MAC0: QSGMII=0 RGMII=1
-+ * MAC1: QSGMII=0 SGMII=0 RGMII=1
-+ * MAC2 & MAC3: QSGMII=0 SGMII=1
-+ */
-+#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x)	1
-+#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x)	((x >= 2) ? 1 : 0)
-+
-+#define NSS_COMMON_MACSEC_CTL			0x28
-+#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x)	(1 << x)
-+
-+#define NSS_COMMON_GMAC_CTL(x)			(0x30 + (x * 4))
-+#define NSS_COMMON_GMAC_CTL_CSYS_REQ		BIT(19)
-+#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL	BIT(16)
-+#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET	8
-+#define NSS_COMMON_GMAC_CTL_IFG_OFFSET		0
-+#define NSS_COMMON_GMAC_CTL_IFG_MASK		0x3f
-+
-+#define NSS_COMMON_CLK_DIV_RGMII_1000		1
-+#define NSS_COMMON_CLK_DIV_RGMII_100		9
-+#define NSS_COMMON_CLK_DIV_RGMII_10		99
-+#define NSS_COMMON_CLK_DIV_SGMII_1000		0
-+#define NSS_COMMON_CLK_DIV_SGMII_100		4
-+#define NSS_COMMON_CLK_DIV_SGMII_10		49
-+
-+#define QSGMII_PCS_MODE_CTL			0x68
-+#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x)	BIT((x * 8) + 7)
-+
-+#define QSGMII_PCS_CAL_LCKDT_CTL		0x120
-+#define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
-+
-+/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
-+#define QSGMII_PHY_SGMII_CTL(x)			((x == 1) ? 0x134 : \
-+						 (0x13c + (4 * (x - 2))))
-+#define QSGMII_PHY_CDR_EN			BIT(0)
-+#define QSGMII_PHY_RX_FRONT_EN			BIT(1)
-+#define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
-+#define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
-+#define QSGMII_PHY_QSGMII_EN			BIT(7)
-+#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
-+#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		0x7
-+#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
-+#define QSGMII_PHY_RX_DC_BIAS_MASK		0x3
-+#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
-+#define QSGMII_PHY_RX_INPUT_EQU_MASK		0x3
-+#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
-+#define QSGMII_PHY_CDR_PI_SLEW_MASK		0x3
-+#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
-+#define QSGMII_PHY_TX_DRV_AMP_MASK		0xf
-+
-+struct ipq806x_gmac {
-+	struct platform_device *pdev;
-+	struct regmap *nss_common;
-+	struct regmap *qsgmii_csr;
-+	uint32_t id;
-+	struct clk *core_clk;
-+	phy_interface_t phy_mode;
-+};
-+
-+static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+	struct device *dev = &gmac->pdev->dev;
-+	int div;
-+
-+	switch (speed) {
-+	case SPEED_1000:
-+		div = NSS_COMMON_CLK_DIV_SGMII_1000;
-+		break;
-+
-+	case SPEED_100:
-+		div = NSS_COMMON_CLK_DIV_SGMII_100;
-+		break;
-+
-+	case SPEED_10:
-+		div = NSS_COMMON_CLK_DIV_SGMII_10;
-+		break;
-+
-+	default:
-+		dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
-+		return -EINVAL;
-+	}
-+
-+	return div;
-+}
-+
-+static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+	struct device *dev = &gmac->pdev->dev;
-+	int div;
-+
-+	switch (speed) {
-+	case SPEED_1000:
-+		div = NSS_COMMON_CLK_DIV_RGMII_1000;
-+		break;
-+
-+	case SPEED_100:
-+		div = NSS_COMMON_CLK_DIV_RGMII_100;
-+		break;
-+
-+	case SPEED_10:
-+		div = NSS_COMMON_CLK_DIV_RGMII_10;
-+		break;
-+
-+	default:
-+		dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
-+		return -EINVAL;
-+	}
-+
-+	return div;
-+}
-+
-+static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
-+{
-+	uint32_t clk_bits, val;
-+	int div;
-+
-+	switch (gmac->phy_mode) {
-+	case PHY_INTERFACE_MODE_RGMII:
-+		div = get_clk_div_rgmii(gmac, speed);
-+		clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
-+			   NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
-+		break;
-+
-+	case PHY_INTERFACE_MODE_SGMII:
-+		div = get_clk_div_sgmii(gmac, speed);
-+		clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
-+			   NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
-+		break;
-+
-+	default:
-+		dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+			phy_modes(gmac->phy_mode));
-+		return -EINVAL;
-+	}
-+
-+	/* Disable the clocks */
-+	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+	val &= ~clk_bits;
-+	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+	/* Set the divider */
-+	regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
-+	val &= ~(NSS_COMMON_CLK_DIV_MASK
-+		 << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
-+	val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
-+	regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
-+
-+	/* Enable the clock back */
-+	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+	val |= clk_bits;
-+	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+	return 0;
-+}
-+
-+static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
-+{
-+	struct device *dev = &gmac->pdev->dev;
-+
-+	gmac->phy_mode = of_get_phy_mode(dev->of_node);
-+	if (gmac->phy_mode < 0) {
-+		dev_err(dev, "missing phy mode property\n");
-+		return ERR_PTR(-EINVAL);
-+	}
-+
-+	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
-+		dev_err(dev, "missing qcom id property\n");
-+		return ERR_PTR(-EINVAL);
-+	}
-+
-+	/* The GMACs are called 1 to 4 in the documentation, but to simplify the
-+	 * code and keep it consistent with the Linux convention, we'll number
-+	 * them from 0 to 3 here.
-+	 */
-+	if (gmac->id < 0 || gmac->id > 3) {
-+		dev_err(dev, "invalid gmac id\n");
-+		return ERR_PTR(-EINVAL);
-+	}
-+
-+	gmac->core_clk = devm_clk_get(dev, "stmmaceth");
-+	if (IS_ERR(gmac->core_clk)) {
-+		dev_err(dev, "missing stmmaceth clk property\n");
-+		return gmac->core_clk;
-+	}
-+	clk_set_rate(gmac->core_clk, 266000000);
-+
-+	/* Setup the register map for the nss common registers */
-+	gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
-+							   "qcom,nss-common");
-+	if (IS_ERR(gmac->nss_common)) {
-+		dev_err(dev, "missing nss-common node\n");
-+		return gmac->nss_common;
-+	}
-+
-+	/* Setup the register map for the qsgmii csr registers */
-+	gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
-+							   "qcom,qsgmii-csr");
-+	if (IS_ERR(gmac->qsgmii_csr)) {
-+		dev_err(dev, "missing qsgmii-csr node\n");
-+		return gmac->qsgmii_csr;
-+	}
-+
-+	return NULL;
-+}
-+
-+static void *ipq806x_gmac_setup(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	struct ipq806x_gmac *gmac;
-+	int val;
-+	void *err;
-+
-+	gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
-+	if (!gmac)
-+		return ERR_PTR(-ENOMEM);
-+
-+	gmac->pdev = pdev;
-+
-+	err = ipq806x_gmac_of_parse(gmac);
-+	if (err) {
-+		dev_err(dev, "device tree parsing error\n");
-+		return err;
-+	}
-+
-+	regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
-+		     QSGMII_PCS_CAL_LCKDT_CTL_RST);
-+
-+	/* Inter frame gap is set to 12 */
-+	val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
-+	      12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
-+	/* We also initiate an AXI low power exit request */
-+	val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
-+	switch (gmac->phy_mode) {
-+	case PHY_INTERFACE_MODE_RGMII:
-+		val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
-+		break;
-+	case PHY_INTERFACE_MODE_SGMII:
-+		val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
-+		break;
-+	default:
-+		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+			phy_modes(gmac->phy_mode));
-+		return NULL;
-+	}
-+	regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
-+
-+	/* Configure the clock src according to the mode */
-+	regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
-+	val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
-+	switch (gmac->phy_mode) {
-+	case PHY_INTERFACE_MODE_RGMII:
-+		val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
-+			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
-+		break;
-+	case PHY_INTERFACE_MODE_SGMII:
-+		val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
-+			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
-+		break;
-+	default:
-+		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-+			phy_modes(gmac->phy_mode));
-+		return NULL;
-+	}
-+	regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
-+
-+	/* Enable PTP clock */
-+	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
-+	val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
-+	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
-+
-+	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
-+		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
-+			     QSGMII_PHY_CDR_EN |
-+			     QSGMII_PHY_RX_FRONT_EN |
-+			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
-+			     QSGMII_PHY_TX_DRIVER_EN |
-+			     QSGMII_PHY_QSGMII_EN |
-+			     0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
-+			     0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
-+			     0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
-+			     0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
-+			     0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
-+	}
-+
-+	return gmac;
-+}
-+
-+static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
-+{
-+	struct ipq806x_gmac *gmac = priv;
-+
-+	ipq806x_gmac_set_speed(gmac, speed);
-+}
-+
-+const struct stmmac_of_data ipq806x_gmac_data = {
-+	.has_gmac	= 1,
-+	.setup		= ipq806x_gmac_setup,
-+	.fix_mac_speed	= ipq806x_gmac_fix_mac_speed,
-+};
diff --git a/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch b/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
deleted file mode 100644
index 3144fa3..0000000
--- a/target/linux/ipq806x/patches-4.0/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 0f9605d9409b77a89daef91cc68239fc2ff50457 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Fri, 8 May 2015 16:51:25 -0700
-Subject: [PATCH 5/8] net: stmmac: ipq806x: document device tree bindings
-
-Add the device tree bindings documentation for the QCA IPQ806x
-variant of the Synopsys DesignWare MAC.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- .../devicetree/bindings/net/ipq806x-dwmac.txt      | 35 ++++++++++++++++++++++
- 1 file changed, 35 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
-@@ -0,0 +1,35 @@
-+* IPQ806x DWMAC Ethernet controller
-+
-+The device inherits all the properties of the dwmac/stmmac devices
-+described in the file net/stmmac.txt with the following changes.
-+
-+Required properties:
-+
-+- compatible: should be "qcom,ipq806x-gmac" along with "snps,dwmac"
-+	      and any applicable more detailed version number
-+	      described in net/stmmac.txt
-+
-+- qcom,nss-common: should contain a phandle to a syscon device mapping the
-+		   nss-common registers.
-+
-+- qcom,qsgmii-csr: should contain a phandle to a syscon device mapping the
-+		   qsgmii-csr registers.
-+
-+Example:
-+
-+	gmac: ethernet@37000000 {
-+		device_type = "network";
-+		compatible = "qcom,ipq806x-gmac";
-+		reg = <0x37000000 0x200000>;
-+		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-+		interrupt-names = "macirq";
-+
-+		qcom,nss-common = <&nss_common>;
-+		qcom,qsgmii-csr = <&qsgmii_csr>;
-+
-+		clocks = <&gcc GMAC_CORE1_CLK>;
-+		clock-names = "stmmaceth";
-+
-+		resets = <&gcc GMAC_CORE1_RESET>;
-+		reset-names = "stmmaceth";
-+	};
diff --git a/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch b/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
deleted file mode 100644
index a9a2d55..0000000
--- a/target/linux/ipq806x/patches-4.0/706-net-stmmac-create-one-debugfs-dir-per-net-device.patch
+++ /dev/null
@@ -1,175 +0,0 @@
-From df944689d491e6af533173bf2ef448c3dd334f15 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Mon, 11 May 2015 15:15:25 -0700
-Subject: [PATCH 6/8] net: stmmac: create one debugfs dir per net-device
-
-stmmac DebugFS entries are currently global to the driver. As a result,
-having more than one stmmac device in the system creates the following
-error:
-* ERROR stmmaceth, debugfs create directory failed
-* stmmac_hw_setup: failed debugFS registration
-
-This also results in being able to access the debugfs information for
-the first registered device only.
-
-This patch changes the debugfs structure to have one sub-directory per
-net-device. Files under "/sys/kernel/debug/stmmaceth" will now show-up
-under /sys/kernel/debug/stmmaceth/ethN/.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac.h      |  6 ++
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 76 ++++++++++++++++-------
- 2 files changed, 59 insertions(+), 23 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
-@@ -116,6 +116,12 @@ struct stmmac_priv {
- 	int use_riwt;
- 	int irq_wake;
- 	spinlock_t ptp_lock;
-+
-+#ifdef CONFIG_DEBUG_FS
-+	struct dentry *dbgfs_dir;
-+	struct dentry *dbgfs_rings_status;
-+	struct dentry *dbgfs_dma_cap;
-+#endif
- };
- 
- int stmmac_mdio_unregister(struct net_device *ndev);
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -119,7 +119,7 @@ static irqreturn_t stmmac_interrupt(int
- 
- #ifdef CONFIG_DEBUG_FS
- static int stmmac_init_fs(struct net_device *dev);
--static void stmmac_exit_fs(void);
-+static void stmmac_exit_fs(struct net_device *dev);
- #endif
- 
- #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
-@@ -1918,7 +1918,7 @@ static int stmmac_release(struct net_dev
- 	netif_carrier_off(dev);
- 
- #ifdef CONFIG_DEBUG_FS
--	stmmac_exit_fs();
-+	stmmac_exit_fs(dev);
- #endif
- 
- 	stmmac_release_ptp(priv);
-@@ -2510,8 +2510,6 @@ static int stmmac_ioctl(struct net_devic
- 
- #ifdef CONFIG_DEBUG_FS
- static struct dentry *stmmac_fs_dir;
--static struct dentry *stmmac_rings_status;
--static struct dentry *stmmac_dma_cap;
- 
- static void sysfs_display_ring(void *head, int size, int extend_desc,
- 			       struct seq_file *seq)
-@@ -2650,36 +2648,39 @@ static const struct file_operations stmm
- 
- static int stmmac_init_fs(struct net_device *dev)
- {
--	/* Create debugfs entries */
--	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
-+	struct stmmac_priv *priv = netdev_priv(dev);
-+
-+	/* Create per netdev entries */
-+	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
- 
--	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
--		pr_err("ERROR %s, debugfs create directory failed\n",
--		       STMMAC_RESOURCE_NAME);
-+	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
-+		pr_err("ERROR %s/%s, debugfs create directory failed\n",
-+		       STMMAC_RESOURCE_NAME, dev->name);
- 
- 		return -ENOMEM;
- 	}
- 
- 	/* Entry to report DMA RX/TX rings */
--	stmmac_rings_status = debugfs_create_file("descriptors_status",
--						  S_IRUGO, stmmac_fs_dir, dev,
--						  &stmmac_rings_status_fops);
-+	priv->dbgfs_rings_status =
-+		debugfs_create_file("descriptors_status", S_IRUGO,
-+				    priv->dbgfs_dir, dev,
-+				    &stmmac_rings_status_fops);
- 
--	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
-+	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
- 		pr_info("ERROR creating stmmac ring debugfs file\n");
--		debugfs_remove(stmmac_fs_dir);
-+		debugfs_remove_recursive(priv->dbgfs_dir);
- 
- 		return -ENOMEM;
- 	}
- 
- 	/* Entry to report the DMA HW features */
--	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
--					     dev, &stmmac_dma_cap_fops);
-+	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
-+					    priv->dbgfs_dir,
-+					    dev, &stmmac_dma_cap_fops);
- 
--	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
-+	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
- 		pr_info("ERROR creating stmmac MMC debugfs file\n");
--		debugfs_remove(stmmac_rings_status);
--		debugfs_remove(stmmac_fs_dir);
-+		debugfs_remove_recursive(priv->dbgfs_dir);
- 
- 		return -ENOMEM;
- 	}
-@@ -2687,11 +2688,11 @@ static int stmmac_init_fs(struct net_dev
- 	return 0;
- }
- 
--static void stmmac_exit_fs(void)
-+static void stmmac_exit_fs(struct net_device *dev)
- {
--	debugfs_remove(stmmac_rings_status);
--	debugfs_remove(stmmac_dma_cap);
--	debugfs_remove(stmmac_fs_dir);
-+	struct stmmac_priv *priv = netdev_priv(dev);
-+
-+	debugfs_remove_recursive(priv->dbgfs_dir);
- }
- #endif /* CONFIG_DEBUG_FS */
- 
-@@ -3136,6 +3137,35 @@ err:
- __setup("stmmaceth=", stmmac_cmdline_opt);
- #endif /* MODULE */
- 
-+static int __init stmmac_init(void)
-+{
-+#ifdef CONFIG_DEBUG_FS
-+	/* Create debugfs main directory if it doesn't exist yet */
-+	if (stmmac_fs_dir == NULL) {
-+		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
-+
-+		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
-+			pr_err("ERROR %s, debugfs create directory failed\n",
-+			       STMMAC_RESOURCE_NAME);
-+
-+			return -ENOMEM;
-+		}
-+	}
-+#endif
-+
-+	return 0;
-+}
-+
-+static void __exit stmmac_exit(void)
-+{
-+#ifdef CONFIG_DEBUG_FS
-+	debugfs_remove_recursive(stmmac_fs_dir);
-+#endif
-+}
-+
-+module_init(stmmac_init)
-+module_exit(stmmac_exit)
-+
- MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
- MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
- MODULE_LICENSE("GPL");
diff --git a/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch b/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
deleted file mode 100644
index 20d8502..0000000
--- a/target/linux/ipq806x/patches-4.0/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From e81de9d28bd0421c236df322872e64edf4ee1852 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Mon, 11 May 2015 16:32:09 -0700
-Subject: [PATCH 7/8] ARM: dts: qcom: add mdio nodes to ap148 & db149
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 40 ++++++++++++++++++++++++++-
- arch/arm/boot/dts/qcom-ipq8064-db149.dts | 46 ++++++++++++++++++++++++++++++++
- 2 files changed, 85 insertions(+), 1 deletion(-)
-
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -14,8 +14,9 @@
- 		};
- 	};
- 
--	alias {
-+	aliases {
- 		serial0 = &uart4;
-+		mdio-gpio0 = &mdio0;
- 	};
- 
- 	chosen {
-@@ -54,6 +55,15 @@
- 					bias-none;
- 				};
- 			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi@16300000 {
-@@ -139,5 +149,33 @@
- 			pinctrl-0 = <&pcie2_pins>;
- 			pinctrl-names = "default";
- 		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+			pinctrl-0 = <&mdio0_pins>;
-+			pinctrl-names = "default";
-+
-+			phy0: ethernet-phy@0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+					>;
-+			};
-+
-+			phy4: ethernet-phy@4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -16,6 +16,7 @@
- 
- 	alias {
- 		serial0 = &uart2;
-+		mdio-gpio0 = &mdio0;
- 	};
- 
- 	chosen {
-@@ -62,6 +63,15 @@
- 					bias-none;
- 				};
- 			};
-+
-+			mdio0_pins: mdio0_pins {
-+				mux {
-+					pins = "gpio0", "gpio1";
-+					function = "gpio";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi2: gsbi@12480000 {
-@@ -173,5 +183,44 @@
- 			pinctrl-0 = <&pcie3_pins>;
- 			pinctrl-names = "default";
- 		};
-+
-+		mdio0: mdio {
-+			compatible = "virtual,mdio-gpio";
-+			#address-cells = <1>;
-+			#size-cells = <0>;
-+			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
-+
-+			pinctrl-0 = <&mdio0_pins>;
-+			pinctrl-names = "default";
-+
-+			phy0: ethernet-phy@0 {
-+				device_type = "ethernet-phy";
-+				reg = <0>;
-+				qca,ar8327-initvals = <
-+					0x00004 0x7600000   /* PAD0_MODE */
-+					0x00008 0x1000000   /* PAD5_MODE */
-+					0x0000c 0x80        /* PAD6_MODE */
-+					0x000e4 0xaa545     /* MAC_POWER_SEL */
-+					0x000e0 0xc74164de  /* SGMII_CTRL */
-+					0x0007c 0x4e        /* PORT0_STATUS */
-+					0x00094 0x4e        /* PORT6_STATUS */
-+				>;
-+			};
-+
-+			phy4: ethernet-phy@4 {
-+				device_type = "ethernet-phy";
-+				reg = <4>;
-+			};
-+
-+			phy6: ethernet-phy@6 {
-+				device_type = "ethernet-phy";
-+				reg = <6>;
-+			};
-+
-+			phy7: ethernet-phy@7 {
-+				device_type = "ethernet-phy";
-+				reg = <7>;
-+			};
-+		};
- 	};
- };
diff --git a/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
deleted file mode 100644
index 6a14f9f..0000000
--- a/target/linux/ipq806x/patches-4.0/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
+++ /dev/null
@@ -1,210 +0,0 @@
-From cab1f4720e82f2e17eaeed9a9ad9e4f07c742977 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Mon, 11 May 2015 12:29:18 -0700
-Subject: [PATCH 8/8] ARM: dts: qcom: add gmac nodes to ipq806x platforms
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
----
- arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 31 ++++++++++++
- arch/arm/boot/dts/qcom-ipq8064-db149.dts | 43 ++++++++++++++++
- arch/arm/boot/dts/qcom-ipq8064.dtsi      | 86 ++++++++++++++++++++++++++++++++
- 3 files changed, 160 insertions(+)
-
---- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
-@@ -64,6 +64,16 @@
- 					bias-disable;
- 				};
- 			};
-+
-+			rgmii2_pins: rgmii2_pins {
-+				mux {
-+					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
-+					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
-+					function = "rgmii2";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi@16300000 {
-@@ -177,5 +187,26 @@
- 				reg = <4>;
- 			};
- 		};
-+
-+		gmac1: ethernet@37200000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			phy-handle = <&phy4>;
-+			qcom,id = <1>;
-+
-+			pinctrl-0 = <&rgmii2_pins>;
-+			pinctrl-names = "default";
-+		};
-+
-+		gmac2: ethernet@37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+
-+			fixed-link {
-+				speed = <1000>;
-+				full-duplex;
-+			};
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-+++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
-@@ -72,6 +72,14 @@
- 					bias-disable;
- 				};
- 			};
-+
-+			rgmii0_pins: rgmii0_pins {
-+				mux {
-+					pins = "gpio2", "gpio66";
-+					drive-strength = <8>;
-+					bias-disable;
-+				};
-+			};
- 		};
- 
- 		gsbi2: gsbi@12480000 {
-@@ -222,5 +230,40 @@
- 				reg = <7>;
- 			};
- 		};
-+
-+		gmac0: ethernet@37000000 {
-+			status = "ok";
-+			phy-mode = "rgmii";
-+			qcom,id = <0>;
-+			phy-handle = <&phy4>;
-+
-+			pinctrl-0 = <&rgmii0_pins>;
-+			pinctrl-names = "default";
-+		};
-+
-+		gmac1: ethernet@37200000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <1>;
-+
-+			fixed-link {
-+				speed = <1000>;
-+				full-duplex;
-+			};
-+		};
-+
-+		gmac2: ethernet@37400000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <2>;
-+			phy-handle = <&phy6>;
-+		};
-+
-+		gmac3: ethernet@37600000 {
-+			status = "ok";
-+			phy-mode = "sgmii";
-+			qcom,id = <3>;
-+			phy-handle = <&phy7>;
-+		};
- 	};
- };
---- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
-+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
-@@ -540,5 +540,91 @@
- 
- 			status = "disabled";
- 		};
-+
-+		nss_common: syscon@03000000 {
-+			compatible = "syscon";
-+			reg = <0x03000000 0x0000FFFF>;
-+		};
-+
-+		qsgmii_csr: syscon@1bb00000 {
-+			compatible = "syscon";
-+			reg = <0x1bb00000 0x000001FF>;
-+		};
-+
-+		gmac0: ethernet@37000000 {
-+			device_type = "network";
-+			compatible = "qcom,ipq806x-gmac";
-+			reg = <0x37000000 0x200000>;
-+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
-+			interrupt-names = "macirq";
-+
-+			qcom,nss-common = <&nss_common>;
-+			qcom,qsgmii-csr = <&qsgmii_csr>;
-+
-+			clocks = <&gcc GMAC_CORE1_CLK>;
-+			clock-names = "stmmaceth";
-+
-+			resets = <&gcc GMAC_CORE1_RESET>;
-+			reset-names = "stmmaceth";
-+
-+			status = "disabled";
-+		};
-+
-+		gmac1: ethernet@37200000 {
-+			device_type = "network";
-+			compatible = "qcom,ipq806x-gmac";
-+			reg = <0x37200000 0x200000>;
-+			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
-+			interrupt-names = "macirq";
-+
-+			qcom,nss-common = <&nss_common>;
-+			qcom,qsgmii-csr = <&qsgmii_csr>;
-+
-+			clocks = <&gcc GMAC_CORE2_CLK>;
-+			clock-names = "stmmaceth";
-+
-+			resets = <&gcc GMAC_CORE2_RESET>;
-+			reset-names = "stmmaceth";
-+
-+			status = "disabled";
-+		};
-+
-+		gmac2: ethernet@37400000 {
-+			device_type = "network";
-+			compatible = "qcom,ipq806x-gmac";
-+			reg = <0x37400000 0x200000>;
-+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
-+			interrupt-names = "macirq";
-+
-+			qcom,nss-common = <&nss_common>;
-+			qcom,qsgmii-csr = <&qsgmii_csr>;
-+
-+			clocks = <&gcc GMAC_CORE3_CLK>;
-+			clock-names = "stmmaceth";
-+
-+			resets = <&gcc GMAC_CORE3_RESET>;
-+			reset-names = "stmmaceth";
-+
-+			status = "disabled";
-+		};
-+
-+		gmac3: ethernet@37600000 {
-+			device_type = "network";
-+			compatible = "qcom,ipq806x-gmac";
-+			reg = <0x37600000 0x200000>;
-+			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
-+			interrupt-names = "macirq";
-+
-+			qcom,nss-common = <&nss_common>;
-+			qcom,qsgmii-csr = <&qsgmii_csr>;
-+
-+			clocks = <&gcc GMAC_CORE4_CLK>;
-+			clock-names = "stmmaceth";
-+
-+			resets = <&gcc GMAC_CORE4_RESET>;
-+			reset-names = "stmmaceth";
-+
-+			status = "disabled";
-+		};
- 	};
- };
diff --git a/target/linux/ipq806x/patches-4.1/020-add-ap148-bootargs.patch b/target/linux/ipq806x/patches-4.1/020-add-ap148-bootargs.patch
new file mode 100644
index 0000000..c0ad74c
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/020-add-ap148-bootargs.patch
@@ -0,0 +1,46 @@
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -14,6 +14,14 @@
+ 		};
+ 	};
+ 
++	alias {
++		serial0 = &uart4;
++	};
++
++	chosen {
++		linux,stdout-path = "serial0:115200n8";
++	};
++
+ 	soc {
+ 		pinmux@800000 {
+ 			i2c4_pins: i2c4_pinmux {
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -159,7 +159,7 @@
+ 
+ 			syscon-tcsr = <&tcsr>;
+ 
+-			serial@12490000 {
++			uart2: serial@12490000 {
+ 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+ 				reg = <0x12490000 0x1000>,
+ 				      <0x12480000 0x1000>;
+@@ -197,7 +197,7 @@
+ 
+ 			syscon-tcsr = <&tcsr>;
+ 
+-			serial@16340000 {
++			uart4: serial@16340000 {
+ 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+ 				reg = <0x16340000 0x1000>,
+ 				      <0x16300000 0x1000>;
+@@ -234,7 +234,7 @@
+ 
+ 			syscon-tcsr = <&tcsr>;
+ 
+-			serial@1a240000 {
++			uart5: serial@1a240000 {
+ 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+ 				reg = <0x1a240000 0x1000>,
+ 				      <0x1a200000 0x1000>;
diff --git a/target/linux/ipq806x/patches-4.1/021-add-ap148-partitions.patch b/target/linux/ipq806x/patches-4.1/021-add-ap148-partitions.patch
new file mode 100644
index 0000000..34eb9c0
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/021-add-ap148-partitions.patch
@@ -0,0 +1,35 @@
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -78,13 +78,28 @@
+ 					reg = <0>;
+ 
+ 					partition@0 {
+-						label = "rootfs";
+-						reg = <0x0 0x1000000>;
++						label = "lowlevel_init";
++						reg = <0x0 0x1b0000>;
+ 					};
+ 
+ 					partition@1 {
+-						label = "scratch";
+-						reg = <0x1000000 0x1000000>;
++						label = "u-boot";
++						reg = <0x1b0000 0x80000>;
++					};
++
++					partition@2 {
++						label = "u-boot-env";
++						reg = <0x230000 0x40000>;
++					};
++
++					partition@3 {
++						label = "caldata";
++						reg = <0x270000 0x40000>;
++					};
++
++					partition@4 {
++						label = "firmware";
++						reg = <0x2b0000 0x1d50000>;
+ 					};
+ 				};
+ 			};
diff --git a/target/linux/ipq806x/patches-4.1/022-add-db149-dts.patch b/target/linux/ipq806x/patches-4.1/022-add-db149-dts.patch
new file mode 100644
index 0000000..7d8c8e8
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/022-add-db149-dts.patch
@@ -0,0 +1,160 @@
+From f26cc3733bdd697bd81ae505fc133fa7c9b6ea19 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Tue, 7 Apr 2015 19:58:58 -0700
+Subject: [PATCH] ARM: dts: qcom: add initial DB149 device-tree
+
+Add basic DB149 (IPQ806x based platform) device-tree. It supports UART,
+SATA, USB2, USB3 and NOR flash.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/boot/dts/Makefile               |   1 +
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 132 +++++++++++++++++++++++++++++++
+ 2 files changed, 133 insertions(+)
+ create mode 100644 arch/arm/boot/dts/qcom-ipq8064-db149.dts
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -451,6 +451,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
+ 	qcom-apq8084-ifc6540.dtb \
+ 	qcom-apq8084-mtp.dtb \
+ 	qcom-ipq8064-ap148.dtb \
++	qcom-ipq8064-db149.dtb \
+ 	qcom-msm8660-surf.dtb \
+ 	qcom-msm8960-cdp.dtb \
+ 	qcom-msm8974-sony-xperia-honami.dtb
+--- /dev/null
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -0,0 +1,132 @@
++#include "qcom-ipq8064-v1.0.dtsi"
++
++/ {
++	model = "Qualcomm IPQ8064/DB149";
++	compatible = "qcom,ipq8064-db149", "qcom,ipq8064";
++
++	reserved-memory {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		ranges;
++		rsvd@41200000 {
++			reg = <0x41200000 0x300000>;
++			no-map;
++		};
++	};
++
++	alias {
++		serial0 = &uart2;
++	};
++
++	chosen {
++		linux,stdout-path = "serial0:115200n8";
++	};
++
++	soc {
++		pinmux@800000 {
++			i2c4_pins: i2c4_pinmux {
++				pins = "gpio12", "gpio13";
++				function = "gsbi4";
++				bias-disable;
++			};
++
++			spi_pins: spi_pins {
++				mux {
++					pins = "gpio18", "gpio19", "gpio21";
++					function = "gsbi5";
++					drive-strength = <10>;
++					bias-none;
++				};
++			};
++		};
++
++		gsbi2: gsbi@12480000 {
++			qcom,mode = <GSBI_PROT_I2C_UART>;
++			status = "ok";
++			uart2: serial@12490000 {
++				status = "ok";
++			};
++		};
++
++		gsbi5: gsbi@1a200000 {
++			qcom,mode = <GSBI_PROT_SPI>;
++			status = "ok";
++
++			spi4: spi@1a280000 {
++				status = "ok";
++				spi-max-frequency = <50000000>;
++
++				pinctrl-0 = <&spi_pins>;
++				pinctrl-names = "default";
++
++				cs-gpios = <&qcom_pinmux 20 0>;
++
++				flash: m25p80@0 {
++					compatible = "s25fl256s1";
++					#address-cells = <1>;
++					#size-cells = <1>;
++					spi-max-frequency = <50000000>;
++					reg = <0>;
++					m25p,fast-read;
++
++					partition@0 {
++						label = "lowlevel_init";
++						reg = <0x0 0x1b0000>;
++					};
++
++					partition@1 {
++						label = "u-boot";
++						reg = <0x1b0000 0x80000>;
++					};
++
++					partition@2 {
++						label = "u-boot-env";
++						reg = <0x230000 0x40000>;
++					};
++
++					partition@3 {
++						label = "caldata";
++						reg = <0x270000 0x40000>;
++					};
++
++					partition@4 {
++						label = "firmware";
++						reg = <0x2b0000 0x1d50000>;
++					};
++				};
++			};
++		};
++
++		sata-phy@1b400000 {
++			status = "ok";
++		};
++
++		sata@29000000 {
++			status = "ok";
++		};
++
++		phy@100f8800 {		/* USB3 port 1 HS phy */
++			status = "ok";
++		};
++
++		phy@100f8830 {		/* USB3 port 1 SS phy */
++			status = "ok";
++		};
++
++		phy@110f8800 {		/* USB3 port 0 HS phy */
++			status = "ok";
++		};
++
++		phy@110f8830 {		/* USB3 port 0 SS phy */
++			status = "ok";
++		};
++
++		usb30@0 {
++			status = "ok";
++		};
++
++		usb30@1 {
++			status = "ok";
++		};
++	};
++};
diff --git a/target/linux/ipq806x/patches-4.1/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch b/target/linux/ipq806x/patches-4.1/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch
new file mode 100644
index 0000000..6b29637
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/023-ARM-dts-ipq806x-Disable-i2c-device-on-gsbi4.patch
@@ -0,0 +1,53 @@
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -46,15 +46,12 @@
+ 			serial@16340000 {
+ 				status = "ok";
+ 			};
+-
+-			i2c4: i2c@16380000 {
+-				status = "ok";
+-
+-				clock-frequency = <200000>;
+-
+-				pinctrl-0 = <&i2c4_pins>;
+-				pinctrl-names = "default";
+-			};
++			/*
++			 * The i2c device on gsbi4 should not be enabled.
++			 * On ipq806x designs gsbi4 i2c is meant for exclusive
++			 * RPM usage. Turning this on in kernel manifests as
++			 * i2c failure for the RPM.
++			 */
+ 		};
+ 
+ 		gsbi5: gsbi@1a200000 {
+--- a/drivers/clk/qcom/gcc-ipq806x.c
++++ b/drivers/clk/qcom/gcc-ipq806x.c
+@@ -807,7 +807,7 @@ static struct clk_rcg gsbi7_qup_src = {
+ 			.parent_names = gcc_pxo_pll8,
+ 			.num_parents = 2,
+ 			.ops = &clk_rcg_ops,
+-			.flags = CLK_SET_PARENT_GATE,
++			.flags = CLK_SET_PARENT_GATE | CLK_IGNORE_UNUSED,
+ 		},
+ 	},
+ };
+@@ -823,7 +823,7 @@ static struct clk_branch gsbi7_qup_clk =
+ 			.parent_names = (const char *[]){ "gsbi7_qup_src" },
+ 			.num_parents = 1,
+ 			.ops = &clk_branch_ops,
+-			.flags = CLK_SET_RATE_PARENT,
++			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ 		},
+ 	},
+ };
+@@ -871,7 +871,7 @@ static struct clk_branch gsbi4_h_clk = {
+ 		.hw.init = &(struct clk_init_data){
+ 			.name = "gsbi4_h_clk",
+ 			.ops = &clk_branch_ops,
+-			.flags = CLK_IS_ROOT,
++			.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+ 		},
+ 	},
+ };
diff --git a/target/linux/ipq806x/patches-4.1/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch b/target/linux/ipq806x/patches-4.1/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch
new file mode 100644
index 0000000..41f91fa
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/110-DT-PCI-qcom-Document-PCIe-devicetree-bindings.patch
@@ -0,0 +1,263 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,3/5] DT: PCI: qcom: Document PCIe devicetree bindings
+From: Stanimir Varbanov <svarbanov@mm-sol.com>
+X-Patchwork-Id: 6326181
+Message-Id: <1430743338-10441-4-git-send-email-svarbanov@mm-sol.com>
+To: Rob Herring <robh+dt@kernel.org>, Kumar Gala <galak@codeaurora.org>,
+	Mark Rutland <mark.rutland@arm.com>,
+	Grant Likely <grant.likely@linaro.org>,
+	Bjorn Helgaas <bhelgaas@google.com>,
+	Kishon Vijay Abraham I <kishon@ti.com>,
+	Russell King <linux@arm.linux.org.uk>, Arnd Bergmann <arnd@arndb.de>
+Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
+	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+	linux-pci@vger.kernel.org, Mathieu Olivari <mathieu@codeaurora.org>,
+	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
+	Stanimir Varbanov <svarbanov@mm-sol.com>
+Date: Mon,  4 May 2015 15:42:16 +0300
+
+Document Qualcomm PCIe driver devicetree bindings.
+
+Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
+
+---
+.../devicetree/bindings/pci/qcom,pcie.txt          |  231 ++++++++++++++++++++
+ 1 files changed, 231 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
+@@ -0,0 +1,231 @@
++* Qualcomm PCI express root complex
++
++- compatible:
++	Usage: required
++	Value type: <stringlist>
++	Definition: Value shall include
++		    - "qcom,pcie-v0" for apq/ipq8064
++		    - "qcom,pcie-v1" for apq8084
++
++- reg:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: Register ranges as listed in the reg-names property
++
++- reg-names:
++	Usage: required
++	Value type: <stringlist>
++	Definition: Must include the following entries
++		    - "parf"   Qualcomm specific registers
++		    - "dbi"    Designware PCIe registers
++		    - "elbi"   External local bus interface registers
++		    - "config" PCIe configuration space
++
++- device_type:
++	Usage: required
++	Value type: <string>
++	Definition: Should be "pci". As specified in designware-pcie.txt
++
++- #address-cells:
++	Usage: required
++	Value type: <u32>
++	Definition: Should be set to 3. As specified in designware-pcie.txt
++
++- #size-cells:
++	Usage: required
++	Value type: <u32>
++	Definition: Should be set 2. As specified in designware-pcie.txt
++
++- ranges:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: As specified in designware-pcie.txt
++
++- interrupts:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: MSI interrupt
++
++- interrupt-names:
++	Usage: required
++	Value type: <stringlist>
++	Definition: Should contain "msi"
++
++- #interrupt-cells:
++	Usage: required
++	Value type: <u32>
++	Definition: Should be 1. As specified in designware-pcie.txt
++
++- interrupt-map-mask:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: As specified in designware-pcie.txt
++
++- interrupt-map:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: As specified in designware-pcie.txt
++
++- clocks:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: List of phandle and clock specifier pairs as listed
++		    in clock-names property
++
++- clock-names:
++	Usage: required
++	Value type: <stringlist>
++	Definition: Should contain the following entries
++		    * should be populated for v0 and v1
++		    	- "iface"      Configuration AHB clock
++
++		    * should be populated for v0
++		    	- "core"       Clocks the pcie hw block
++		    	- "phy"        Clocks the pcie PHY block
++
++		    * should be populated for v1
++			- "aux"        Auxiliary (AUX) clock
++		    	- "bus_master" Master AXI clock
++		    	- "bus_slave"  Slave AXI clock
++
++- resets:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: List of phandle and reset specifier pairs as listed
++		    in reset-names property
++
++- reset-names:
++	Usage: required
++	Value type: <stringlist>
++	Definition: Should contain the following entries
++		    * should be populated for v0
++			- "axi"  AXI reset
++			- "ahb"  AHB reset
++			- "por"  POR reset
++			- "pci"  PCI reset
++			- "phy"  PHY reset
++
++		    * should be populated for v1
++			- "core" Core reset
++
++- power-domains:
++	Usage: required (for v1 only)
++	Value type: <prop-encoded-array>
++	Definition: A phandle and power domain specifier pair to the
++		    power domain which is responsible for collapsing
++		    and restoring power to the peripheral
++
++- <name>-supply:
++	Usage: required
++	Value type: <phandle>
++	Definition: List of phandles to the power supply regulator(s)
++		    * should be populated for v0 and v1
++			- "vdda"        core analog power supply
++
++		    * should be populated for v0
++			- "vdda_phy"    analog power supply for PHY
++			- "vdda_refclk" analog power supply for IC which generate
++					reference clock
++
++- phys:
++	Usage: required (for v1 only)
++	Value type: <phandle>
++	Definition: List of phandle(s) as listed in phy-names property
++
++- phy-names:
++	Usage: required (for v1 only)
++	Value type: <stringlist>
++	Definition: Should contain "pciephy"
++
++- <name>-gpio:
++	Usage: optional
++	Value type: <prop-encoded-array>
++	Definition: List of phandle and gpio specifier pairs. Should contain
++		    - "perst"  PCIe endpoint reset signal line
++		    - "pewake" PCIe endpoint wake signal line
++
++- pinctrl-0:
++	Usage: required
++	Value type: <phandle>
++	Definition: List of phandles pointing at a pin(s) configuration
++
++- pinctrl-names
++	Usage: required
++	Value type: <stringlist>
++	Definition: List of names of pinctrl-0 state
++
++* Example for v0
++	pcie0: pci@1b500000 {
++		compatible = "qcom,pcie-v0";
++		reg = <0x1b500000 0x1000
++		       0x1b502000 0x80
++		       0x1b600000 0x100
++		       0x0ff00000 0x100000>;
++		reg-names = "dbi", "elbi", "parf", "config";
++		device_type = "pci";
++		linux,pci-domain = <0>;
++		bus-range = <0x00 0xff>;
++		num-lanes = <1>;
++		#address-cells = <3>;
++		#size-cells = <2>;
++		ranges = <0x81000000 0 0	  0x0fe00000 0 0x00100000   /* I/O */
++			  0x82000000 0 0x00000000 0x08000000 0 0x07e00000>; /* memory */
++		interrupts = <GIC_SPI 35 IRQ_TYPE_NONE>;
++		interrupt-names = "msi";
++		#interrupt-cells = <1>;
++		interrupt-map-mask = <0 0 0 0x7>;
++		interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
++				<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
++				<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
++				<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
++		clocks = <&gcc PCIE_A_CLK>,
++			 <&gcc PCIE_H_CLK>,
++			 <&gcc PCIE_PHY_CLK>;
++		clock-names = "core", "iface", "phy";
++		resets = <&gcc PCIE_ACLK_RESET>,
++			 <&gcc PCIE_HCLK_RESET>,
++			 <&gcc PCIE_POR_RESET>,
++			 <&gcc PCIE_PCI_RESET>,
++			 <&gcc PCIE_PHY_RESET>;
++		reset-names = "axi", "ahb", "por", "pci", "phy";
++	};
++
++* Example for v1
++	pcie0@fc520000 {
++		compatible = "qcom,pcie-v1";
++		reg = <0xfc520000 0x2000>,
++		      <0xff000000 0x1000>,
++		      <0xff001000 0x1000>,
++		      <0xff002000 0x2000>;
++		reg-names = "parf", "dbi", "elbi", "config";
++		device_type = "pci";
++		linux,pci-domain = <0>;
++		bus-range = <0x00 0xff>;
++		num-lanes = <1>;
++		#address-cells = <3>;
++		#size-cells = <2>;
++		ranges = <0x81000000 0 0          0xff200000 0 0x00100000   /* I/O */
++			  0x82000000 0 0x00300000 0xff300000 0 0x00d00000>; /* memory */
++		interrupts = <GIC_SPI 243 IRQ_TYPE_NONE>;
++		interrupt-names = "msi";
++		#interrupt-cells = <1>;
++		interrupt-map-mask = <0 0 0 0x7>;
++		interrupt-map = <0 0 0 1 &intc 0 244 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
++				<0 0 0 2 &intc 0 245 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
++				<0 0 0 3 &intc 0 247 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
++				<0 0 0 4 &intc 0 248 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
++		clocks = <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
++			 <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
++			 <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
++			 <&gcc GCC_PCIE_0_AUX_CLK>;
++		clock-names = "iface", "master_bus", "slave_bus", "aux";
++		resets = <&gcc GCC_PCIE_0_BCR>;
++		reset-names = "core";
++		power-domains = <&gcc PCIE0_GDSC>;
++		vdda-supply = <&pma8084_l3>;
++		phys = <&pciephy0>;
++		phy-names = "pciephy";
++		perst-gpio = <&tlmm 70 GPIO_ACTIVE_LOW>;
++		pinctrl-0 = <&pcie0_pins_default>;
++		pinctrl-names = "default";
++	};
diff --git a/target/linux/ipq806x/patches-4.1/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch b/target/linux/ipq806x/patches-4.1/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch
new file mode 100644
index 0000000..dbf16a3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/111-PCI-qcom-Add-Qualcomm-PCIe-controller-driver.patch
@@ -0,0 +1,753 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v2,4/5] PCI: qcom: Add Qualcomm PCIe controller driver
+From: Stanimir Varbanov <svarbanov@mm-sol.com>
+X-Patchwork-Id: 6326161
+Message-Id: <1430743338-10441-5-git-send-email-svarbanov@mm-sol.com>
+To: Rob Herring <robh+dt@kernel.org>, Kumar Gala <galak@codeaurora.org>,
+	Mark Rutland <mark.rutland@arm.com>,
+	Grant Likely <grant.likely@linaro.org>,
+	Bjorn Helgaas <bhelgaas@google.com>,
+	Kishon Vijay Abraham I <kishon@ti.com>,
+	Russell King <linux@arm.linux.org.uk>, Arnd Bergmann <arnd@arndb.de>
+Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org,
+	linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
+	linux-pci@vger.kernel.org, Mathieu Olivari <mathieu@codeaurora.org>,
+	Srinivas Kandagatla <srinivas.kandagatla@linaro.org>,
+	Stanimir Varbanov <svarbanov@mm-sol.com>
+Date: Mon,  4 May 2015 15:42:17 +0300
+
+The PCIe driver reuse the Designware common code for host
+and MSI initialization, and also program the Qualcomm
+application specific registers.
+
+Signed-off-by: Stanimir Varbanov <svarbanov@mm-sol.com>
+
+---
+MAINTAINERS                  |    7 +
+ drivers/pci/host/Kconfig     |    9 +
+ drivers/pci/host/Makefile    |    1 +
+ drivers/pci/host/pcie-qcom.c |  677 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 694 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/pci/host/pcie-qcom.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -7599,6 +7599,13 @@ L:	linux-pci@vger.kernel.org
+ S:	Maintained
+ F:	drivers/pci/host/*spear*
+ 
++PCIE DRIVER FOR QUALCOMM MSM
++M:	Stanimir Varbanov <svarbanov@mm-sol.com>
++L:	linux-pci@vger.kernel.org
++L:	linux-arm-msm@vger.kernel.org
++S:	Maintained
++F:	drivers/pci/host/*qcom*
++
+ PCMCIA SUBSYSTEM
+ P:	Linux PCMCIA Team
+ L:	linux-pcmcia@lists.infradead.org
+--- a/drivers/pci/host/Kconfig
++++ b/drivers/pci/host/Kconfig
+@@ -125,4 +125,13 @@ config PCIE_IPROC_PLATFORM
+ 	  Say Y here if you want to use the Broadcom iProc PCIe controller
+ 	  through the generic platform bus interface
+ 
++config PCIE_QCOM
++	bool "Qualcomm PCIe controller"
++	depends on ARCH_QCOM && OF || (ARM && COMPILE_TEST)
++	select PCIE_DW
++	select PCIEPORTBUS
++	help
++	  Say Y here to enable PCIe controller support on Qualcomm SoCs. The
++	  PCIe controller use Designware core plus Qualcomm specific hardware
++	  wrappers.
+ endmenu
+--- /dev/null
++++ b/drivers/pci/host/pcie-qcom.c
+@@ -0,0 +1,677 @@
++/*
++ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/gpio.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/phy/phy.h>
++#include <linux/regulator/consumer.h>
++#include <linux/reset.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++#include "pcie-designware.h"
++
++#define PCIE20_PARF_PHY_CTRL			0x40
++#define PCIE20_PARF_PHY_REFCLK			0x4C
++#define PCIE20_PARF_DBI_BASE_ADDR		0x168
++#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16c
++#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT	0x178
++
++#define PCIE20_ELBI_SYS_CTRL			0x04
++#define PCIE20_ELBI_SYS_STTS			0x08
++#define XMLH_LINK_UP				BIT(10)
++
++#define PCIE20_CAP				0x70
++#define PCIE20_CAP_LINKCTRLSTATUS		(PCIE20_CAP + 0x10)
++
++#define PERST_DELAY_MIN_US			1000
++#define PERST_DELAY_MAX_US			1005
++
++#define LINKUP_DELAY_MIN_US			5000
++#define LINKUP_DELAY_MAX_US			5100
++#define LINKUP_RETRIES_COUNT			20
++
++#define PCIE_V0					0	/* apq8064 */
++#define PCIE_V1					1	/* apq8084 */
++
++struct qcom_pcie_resources_v0 {
++	struct clk *iface_clk;
++	struct clk *core_clk;
++	struct clk *phy_clk;
++	struct reset_control *pci_reset;
++	struct reset_control *axi_reset;
++	struct reset_control *ahb_reset;
++	struct reset_control *por_reset;
++	struct reset_control *phy_reset;
++	struct regulator *vdda;
++	struct regulator *vdda_phy;
++	struct regulator *vdda_refclk;
++};
++
++struct qcom_pcie_resources_v1 {
++	struct clk *iface;
++	struct clk *aux;
++	struct clk *master_bus;
++	struct clk *slave_bus;
++	struct reset_control *core;
++	struct regulator *vdda;
++};
++
++union pcie_resources {
++	struct qcom_pcie_resources_v0 v0;
++	struct qcom_pcie_resources_v1 v1;
++};
++
++struct qcom_pcie {
++	struct pcie_port pp;
++	struct device *dev;
++	union pcie_resources res;
++	void __iomem *parf;
++	void __iomem *dbi;
++	void __iomem *elbi;
++	struct phy *phy;
++	struct gpio_desc *reset;
++	unsigned int version;
++};
++
++#define to_qcom_pcie(x)		container_of(x, struct qcom_pcie, pp)
++
++static inline void
++writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask)
++{
++	u32 val = readl(addr);
++
++	val &= ~clear_mask;
++	val |= set_mask;
++	writel(val, addr);
++}
++
++static void qcom_ep_reset_assert_deassert(struct qcom_pcie *pcie, int assert)
++{
++	int val, active_low;
++
++	if (IS_ERR_OR_NULL(pcie->reset))
++		return;
++
++	active_low = gpiod_is_active_low(pcie->reset);
++
++	if (assert)
++		val = !!active_low;
++	else
++		val = !active_low;
++
++	gpiod_set_value(pcie->reset, val);
++
++	usleep_range(PERST_DELAY_MIN_US, PERST_DELAY_MAX_US);
++}
++
++static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
++{
++	qcom_ep_reset_assert_deassert(pcie, 1);
++}
++
++static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
++{
++	qcom_ep_reset_assert_deassert(pcie, 0);
++}
++
++static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
++{
++	struct pcie_port *pp = arg;
++
++	return dw_handle_msi_irq(pp);
++}
++
++static int qcom_pcie_link_up(struct pcie_port *pp)
++{
++	struct qcom_pcie *pcie = to_qcom_pcie(pp);
++	u32 val = readl(pcie->dbi + PCIE20_CAP_LINKCTRLSTATUS);
++
++	return val & BIT(29) ? 1 : 0;
++}
++
++static void qcom_pcie_disable_resources_v0(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
++
++	reset_control_assert(res->pci_reset);
++	reset_control_assert(res->axi_reset);
++	reset_control_assert(res->ahb_reset);
++	reset_control_assert(res->por_reset);
++	reset_control_assert(res->pci_reset);
++	clk_disable_unprepare(res->iface_clk);
++	clk_disable_unprepare(res->core_clk);
++	clk_disable_unprepare(res->phy_clk);
++	regulator_disable(res->vdda);
++	regulator_disable(res->vdda_phy);
++	regulator_disable(res->vdda_refclk);
++}
++
++static void qcom_pcie_disable_resources_v1(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
++
++	reset_control_assert(res->core);
++	clk_disable_unprepare(res->slave_bus);
++	clk_disable_unprepare(res->master_bus);
++	clk_disable_unprepare(res->iface);
++	clk_disable_unprepare(res->aux);
++	regulator_disable(res->vdda);
++}
++
++static int qcom_pcie_enable_resources_v0(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
++	struct device *dev = pcie->dev;
++	int ret;
++
++	ret = regulator_enable(res->vdda);
++	if (ret) {
++		dev_err(dev, "cannot enable vdda regulator\n");
++		return ret;
++	}
++
++	ret = regulator_enable(res->vdda_refclk);
++	if (ret) {
++		dev_err(dev, "cannot enable vdda_refclk regulator\n");
++		goto err_refclk;
++	}
++
++	ret = regulator_enable(res->vdda_phy);
++	if (ret) {
++		dev_err(dev, "cannot enable vdda_phy regulator\n");
++		goto err_vdda_phy;
++	}
++
++	ret = clk_prepare_enable(res->iface_clk);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable iface clock\n");
++		goto err_iface;
++	}
++
++	ret = clk_prepare_enable(res->core_clk);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable core clock\n");
++		goto err_clk_core;
++	}
++
++	ret = clk_prepare_enable(res->phy_clk);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable phy clock\n");
++		goto err_clk_phy;
++	}
++
++	ret = reset_control_deassert(res->ahb_reset);
++	if (ret) {
++		dev_err(dev, "cannot deassert ahb reset\n");
++		goto err_reset_ahb;
++	}
++
++	return 0;
++
++err_reset_ahb:
++	clk_disable_unprepare(res->phy_clk);
++err_clk_phy:
++	clk_disable_unprepare(res->core_clk);
++err_clk_core:
++	clk_disable_unprepare(res->iface_clk);
++err_iface:
++	regulator_disable(res->vdda_phy);
++err_vdda_phy:
++	regulator_disable(res->vdda_refclk);
++err_refclk:
++	regulator_disable(res->vdda);
++	return ret;
++}
++
++static int qcom_pcie_enable_resources_v1(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
++	struct device *dev = pcie->dev;
++	int ret;
++
++	ret = reset_control_deassert(res->core);
++	if (ret) {
++		dev_err(dev, "cannot deassert core reset\n");
++		return ret;
++	}
++
++	ret = clk_prepare_enable(res->aux);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable aux clock\n");
++		goto err_res;
++	}
++
++	ret = clk_prepare_enable(res->iface);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable iface clock\n");
++		goto err_aux;
++	}
++
++	ret = clk_prepare_enable(res->master_bus);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable master_bus clock\n");
++		goto err_iface;
++	}
++
++	ret = clk_prepare_enable(res->slave_bus);
++	if (ret) {
++		dev_err(dev, "cannot prepare/enable slave_bus clock\n");
++		goto err_master;
++	}
++
++	ret = regulator_enable(res->vdda);
++	if (ret) {
++		dev_err(dev, "cannot enable vdda regulator\n");
++		goto err_slave;
++	}
++
++	return 0;
++
++err_slave:
++	clk_disable_unprepare(res->slave_bus);
++err_master:
++	clk_disable_unprepare(res->master_bus);
++err_iface:
++	clk_disable_unprepare(res->iface);
++err_aux:
++	clk_disable_unprepare(res->aux);
++err_res:
++	reset_control_assert(res->core);
++
++	return ret;
++}
++
++static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
++	struct device *dev = pcie->dev;
++
++	res->vdda = devm_regulator_get(dev, "vdda");
++	if (IS_ERR(res->vdda))
++		return PTR_ERR(res->vdda);
++
++	res->vdda_phy = devm_regulator_get(dev, "vdda_phy");
++	if (IS_ERR(res->vdda_phy))
++		return PTR_ERR(res->vdda_phy);
++
++	res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk");
++	if (IS_ERR(res->vdda_refclk))
++		return PTR_ERR(res->vdda_refclk);
++
++	res->iface_clk = devm_clk_get(dev, "iface");
++	if (IS_ERR(res->iface_clk))
++		return PTR_ERR(res->iface_clk);
++
++	res->core_clk = devm_clk_get(dev, "core");
++	if (IS_ERR(res->core_clk))
++		return PTR_ERR(res->core_clk);
++
++	res->phy_clk = devm_clk_get(dev, "phy");
++	if (IS_ERR(res->phy_clk))
++		return PTR_ERR(res->phy_clk);
++
++	res->pci_reset = devm_reset_control_get(dev, "pci");
++	if (IS_ERR(res->pci_reset))
++		return PTR_ERR(res->pci_reset);
++
++	res->axi_reset = devm_reset_control_get(dev, "axi");
++	if (IS_ERR(res->axi_reset))
++		return PTR_ERR(res->axi_reset);
++
++	res->ahb_reset = devm_reset_control_get(dev, "ahb");
++	if (IS_ERR(res->ahb_reset))
++		return PTR_ERR(res->ahb_reset);
++
++	res->por_reset = devm_reset_control_get(dev, "por");
++	if (IS_ERR(res->por_reset))
++		return PTR_ERR(res->por_reset);
++
++	res->phy_reset = devm_reset_control_get(dev, "phy");
++	if (IS_ERR(res->phy_reset))
++		return PTR_ERR(res->phy_reset);
++
++	return 0;
++}
++
++static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
++{
++	struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
++	struct device *dev = pcie->dev;
++
++	res->vdda = devm_regulator_get(dev, "vdda");
++	if (IS_ERR(res->vdda))
++		return PTR_ERR(res->vdda);
++
++	res->iface = devm_clk_get(dev, "iface");
++	if (IS_ERR(res->iface))
++		return PTR_ERR(res->iface);
++
++	res->aux = devm_clk_get(dev, "aux");
++	if (IS_ERR(res->aux) && PTR_ERR(res->aux) == -EPROBE_DEFER)
++		return -EPROBE_DEFER;
++	else if (IS_ERR(res->aux))
++		res->aux = NULL;
++
++	res->master_bus = devm_clk_get(dev, "master_bus");
++	if (IS_ERR(res->master_bus))
++		return PTR_ERR(res->master_bus);
++
++	res->slave_bus = devm_clk_get(dev, "slave_bus");
++	if (IS_ERR(res->slave_bus))
++		return PTR_ERR(res->slave_bus);
++
++	res->core = devm_reset_control_get(dev, "core");
++	if (IS_ERR(res->core))
++		return PTR_ERR(res->core);
++
++	return 0;
++}
++
++static int qcom_pcie_enable_link_training(struct pcie_port *pp)
++{
++	struct qcom_pcie *pcie = to_qcom_pcie(pp);
++	struct device *dev = pp->dev;
++	int retries;
++	u32 val;
++
++	/* enable link training */
++	writel_masked(pcie->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0));
++
++	/* wait for up to 100ms for the link to come up */
++	retries = LINKUP_RETRIES_COUNT;
++	do {
++		val = readl(pcie->elbi + PCIE20_ELBI_SYS_STTS);
++		if (val & XMLH_LINK_UP)
++			break;
++		usleep_range(LINKUP_DELAY_MIN_US, LINKUP_DELAY_MAX_US);
++	} while (retries--);
++
++	if (retries < 0 || !dw_pcie_link_up(pp)) {
++		dev_err(dev, "link initialization failed\n");
++		return -ENXIO;
++	}
++
++	return 0;
++}
++
++static void qcom_pcie_host_init_v1(struct pcie_port *pp)
++{
++	struct qcom_pcie *pcie = to_qcom_pcie(pp);
++	int ret;
++
++	qcom_ep_reset_assert(pcie);
++
++	ret = qcom_pcie_enable_resources_v1(pcie);
++	if (ret)
++		return;
++
++	/* change DBI base address */
++	writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
++
++	if (IS_ENABLED(CONFIG_PCI_MSI))
++		writel_masked(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT,
++			      0, BIT(31));
++
++	ret = phy_init(pcie->phy);
++	if (ret)
++		goto err_res;
++
++	ret = phy_power_on(pcie->phy);
++	if (ret)
++		goto err_phy;
++
++	dw_pcie_setup_rc(pp);
++
++	if (IS_ENABLED(CONFIG_PCI_MSI))
++		dw_pcie_msi_init(pp);
++
++	qcom_ep_reset_deassert(pcie);
++
++	ret = qcom_pcie_enable_link_training(pp);
++	if (ret)
++		goto err;
++
++	return;
++
++err:
++	qcom_ep_reset_assert(pcie);
++	phy_power_off(pcie->phy);
++err_phy:
++	phy_exit(pcie->phy);
++err_res:
++	qcom_pcie_disable_resources_v1(pcie);
++}
++
++static void qcom_pcie_host_init_v0(struct pcie_port *pp)
++{
++	struct qcom_pcie *pcie = to_qcom_pcie(pp);
++	struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
++	struct device *dev = pcie->dev;
++	int ret;
++
++	qcom_ep_reset_assert(pcie);
++
++	ret = qcom_pcie_enable_resources_v0(pcie);
++	if (ret)
++		return;
++
++	writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
++
++	/* enable external reference clock */
++	writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, 0, BIT(16));
++
++	ret = reset_control_deassert(res->phy_reset);
++	if (ret) {
++		dev_err(dev, "cannot deassert phy reset\n");
++		return;
++	}
++
++	ret = reset_control_deassert(res->pci_reset);
++	if (ret) {
++		dev_err(dev, "cannot deassert pci reset\n");
++		return;
++	}
++
++	ret = reset_control_deassert(res->por_reset);
++	if (ret) {
++		dev_err(dev, "cannot deassert por reset\n");
++		return;
++	}
++
++	ret = reset_control_deassert(res->axi_reset);
++	if (ret) {
++		dev_err(dev, "cannot deassert axi reset\n");
++		return;
++	}
++
++	/* wait 150ms for clock acquisition */
++	usleep_range(10000, 15000);
++
++	dw_pcie_setup_rc(pp);
++
++	if (IS_ENABLED(CONFIG_PCI_MSI))
++		dw_pcie_msi_init(pp);
++
++	qcom_ep_reset_deassert(pcie);
++
++	ret = qcom_pcie_enable_link_training(pp);
++	if (ret)
++		goto err;
++
++	return;
++err:
++	qcom_ep_reset_assert(pcie);
++	qcom_pcie_disable_resources_v0(pcie);
++}
++
++static void qcom_pcie_host_init(struct pcie_port *pp)
++{
++	struct qcom_pcie *pcie = to_qcom_pcie(pp);
++
++	if (pcie->version == PCIE_V0)
++		return qcom_pcie_host_init_v0(pp);
++	else
++		return qcom_pcie_host_init_v1(pp);
++}
++
++static int
++qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val)
++{
++	/* the device class is not reported correctly from the register */
++	if (where == PCI_CLASS_REVISION && size == 4) {
++		*val = readl(pp->dbi_base + PCI_CLASS_REVISION);
++		*val &= ~(0xffff << 16);
++		*val |= PCI_CLASS_BRIDGE_PCI << 16;
++		return PCIBIOS_SUCCESSFUL;
++	}
++
++	return dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where,
++				size, val);
++}
++
++static struct pcie_host_ops qcom_pcie_ops = {
++	.link_up = qcom_pcie_link_up,
++	.host_init = qcom_pcie_host_init,
++	.rd_own_conf = qcom_pcie_rd_own_conf,
++};
++
++static const struct of_device_id qcom_pcie_match[] = {
++	{ .compatible = "qcom,pcie-v0", .data = (void *)PCIE_V0 },
++	{ .compatible = "qcom,pcie-v1", .data = (void *)PCIE_V1 },
++	{ }
++};
++
++static int qcom_pcie_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct of_device_id *match;
++	struct resource *res;
++	struct qcom_pcie *pcie;
++	struct pcie_port *pp;
++	int ret;
++
++	match = of_match_node(qcom_pcie_match, dev->of_node);
++	if (!match)
++		return -ENXIO;
++
++	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
++	if (!pcie)
++		return -ENOMEM;
++
++	pcie->version = (unsigned int)match->data;
++
++	pcie->reset = devm_gpiod_get_optional(dev, "perst");
++	if (IS_ERR(pcie->reset) && PTR_ERR(pcie->reset) == -EPROBE_DEFER)
++		return PTR_ERR(pcie->reset);
++
++	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
++	pcie->parf = devm_ioremap_resource(dev, res);
++	if (IS_ERR(pcie->parf))
++		return PTR_ERR(pcie->parf);
++
++	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
++	pcie->dbi = devm_ioremap_resource(dev, res);
++	if (IS_ERR(pcie->dbi))
++		return PTR_ERR(pcie->dbi);
++
++	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
++	pcie->elbi = devm_ioremap_resource(dev, res);
++	if (IS_ERR(pcie->elbi))
++		return PTR_ERR(pcie->elbi);
++
++	pcie->phy = devm_phy_optional_get(dev, "pciephy");
++	if (IS_ERR(pcie->phy))
++		return PTR_ERR(pcie->phy);
++
++	pcie->dev = dev;
++
++	if (pcie->version == PCIE_V0)
++		ret = qcom_pcie_get_resources_v0(pcie);
++	else
++		ret = qcom_pcie_get_resources_v1(pcie);
++
++	if (ret)
++		return ret;
++
++	pp = &pcie->pp;
++	pp->dev = dev;
++	pp->dbi_base = pcie->dbi;
++	pp->root_bus_nr = -1;
++	pp->ops = &qcom_pcie_ops;
++
++	if (IS_ENABLED(CONFIG_PCI_MSI)) {
++		pp->msi_irq = platform_get_irq_byname(pdev, "msi");
++		if (pp->msi_irq < 0) {
++			dev_err(dev, "cannot get msi irq\n");
++			return pp->msi_irq;
++		}
++
++		ret = devm_request_irq(dev, pp->msi_irq,
++				       qcom_pcie_msi_irq_handler,
++				       IRQF_SHARED, "qcom-pcie-msi", pp);
++		if (ret) {
++			dev_err(dev, "cannot request msi irq\n");
++			return ret;
++		}
++	}
++
++	ret = dw_pcie_host_init(pp);
++	if (ret) {
++		dev_err(dev, "cannot initialize host\n");
++		return ret;
++	}
++
++	platform_set_drvdata(pdev, pcie);
++
++	return 0;
++}
++
++static int qcom_pcie_remove(struct platform_device *pdev)
++{
++	struct qcom_pcie *pcie = platform_get_drvdata(pdev);
++
++	qcom_ep_reset_assert(pcie);
++	phy_power_off(pcie->phy);
++	phy_exit(pcie->phy);
++	if (pcie->version == PCIE_V0)
++		qcom_pcie_disable_resources_v0(pcie);
++	else
++		qcom_pcie_disable_resources_v1(pcie);
++
++	return 0;
++}
++
++static struct platform_driver qcom_pcie_driver = {
++	.probe = qcom_pcie_probe,
++	.remove = qcom_pcie_remove,
++	.driver = {
++		.name = "qcom-pcie",
++		.of_match_table = qcom_pcie_match,
++	},
++};
++
++module_platform_driver(qcom_pcie_driver);
++
++MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>");
++MODULE_DESCRIPTION("Qualcomm PCIe root complex driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:qcom-pcie");
+--- 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_PCIE_QCOM) += pcie-qcom.o
diff --git a/target/linux/ipq806x/patches-4.1/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.1/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
new file mode 100644
index 0000000..e7de2bb
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/112-ARM-dts-qcom-add-pcie-nodes-to-ipq806x-platforms.patch
@@ -0,0 +1,260 @@
+From 5b40516b2f5fb9b2a7d6d3e2e924f12ec9d183a8 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Tue, 21 Apr 2015 19:01:42 -0700
+Subject: [PATCH 8/9] ARM: dts: qcom: add pcie nodes to ipq806x platforms
+
+qcom-pcie driver now supports version 0 of the controller. This change
+adds the corresponding entries to the IPQ806x dtsi file and
+corresponding platform (AP148).
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts |  30 ++++++++
+ arch/arm/boot/dts/qcom-ipq8064.dtsi      | 124 +++++++++++++++++++++++++++++++
+ 2 files changed, 154 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -30,6 +30,22 @@
+ 				bias-disable;
+ 			};
+ 
++			pcie1_pins: pcie1_pinmux {
++				mux {
++					pins = "gpio3";
++					drive-strength = <2>;
++					bias-disable;
++				};
++			};
++
++			pcie2_pins: pcie2_pinmux {
++				mux {
++					pins = "gpio48";
++					drive-strength = <2>;
++					bias-disable;
++				};
++			};
++
+ 			spi_pins: spi_pins {
+ 				mux {
+ 					pins = "gpio18", "gpio19", "gpio21";
+@@ -109,5 +125,19 @@
+ 		sata@29000000 {
+ 			status = "ok";
+ 		};
++
++		pcie0: pci@1b500000 {
++			status = "ok";
++			reset-gpio = <&qcom_pinmux 3 0>;
++			pinctrl-0 = <&pcie1_pins>;
++			pinctrl-names = "default";
++		};
++
++		pcie1: pci@1b700000 {
++			status = "ok";
++			reset-gpio = <&qcom_pinmux 48 0>;
++			pinctrl-0 = <&pcie2_pins>;
++			pinctrl-names = "default";
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -30,6 +30,30 @@
+ 				bias-disable;
+ 			};
+ 
++			pcie1_pins: pcie1_pinmux {
++				mux {
++					pins = "gpio3";
++					drive-strength = <2>;
++					bias-disable;
++				};
++			};
++
++			pcie2_pins: pcie2_pinmux {
++				mux {
++					pins = "gpio48";
++					drive-strength = <2>;
++					bias-disable;
++				};
++			};
++
++			pcie3_pins: pcie3_pinmux {
++				mux {
++					pins = "gpio63";
++					drive-strength = <2>;
++					bias-disable;
++				};
++			};
++
+ 			spi_pins: spi_pins {
+ 				mux {
+ 					pins = "gpio18", "gpio19", "gpio21";
+@@ -128,5 +152,26 @@
+ 		usb30@1 {
+ 			status = "ok";
+ 		};
++
++		pcie0: pci@1b500000 {
++			status = "ok";
++			reset-gpio = <&qcom_pinmux 3 0>;
++			pinctrl-0 = <&pcie1_pins>;
++			pinctrl-names = "default";
++		};
++
++		pcie1: pci@1b700000 {
++			status = "ok";
++			reset-gpio = <&qcom_pinmux 48 0>;
++			pinctrl-0 = <&pcie2_pins>;
++			pinctrl-names = "default";
++		};
++
++		pcie2: pci@1b900000 {
++			status = "ok";
++			reset-gpio = <&qcom_pinmux 63 0>;
++			pinctrl-0 = <&pcie3_pins>;
++			pinctrl-names = "default";
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -4,6 +4,8 @@
+ #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
+ #include <dt-bindings/clock/qcom,lcc-ipq806x.h>
+ #include <dt-bindings/soc/qcom,gsbi.h>
++#include <dt-bindings/reset/qcom,gcc-ipq806x.h>
++#include <include/dt-bindings/interrupt-controller/arm-gic.h>
+ 
+ / {
+ 	model = "Qualcomm IPQ8064";
+@@ -329,5 +331,128 @@
+ 			#reset-cells = <1>;
+ 		};
+ 
++		pcie0: pci@1b500000 {
++			compatible = "qcom,pcie-v0";
++			reg = <0x1b500000 0x1000
++			       0x1b502000 0x80
++			       0x1b600000 0x100
++			       0x0ff00000 0x100000>;
++			reg-names = "dbi", "elbi", "parf", "config";
++			device_type = "pci";
++			linux,pci-domain = <0>;
++			bus-range = <0x00 0xff>;
++			num-lanes = <1>;
++			#address-cells = <3>;
++			#size-cells = <2>;
++
++			ranges = <0x81000000 0 0	  0x0fe00000 0 0x00100000   /* downstream I/O */
++				  0x82000000 0 0x00000000 0x08000000 0 0x07e00000>; /* non-prefetchable memory */
++
++			interrupts = <GIC_SPI 35 IRQ_TYPE_NONE>;
++			interrupt-names = "msi";
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 0x7>;
++			interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
++					<0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
++					<0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
++					<0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
++
++			clocks = <&gcc PCIE_A_CLK>,
++				 <&gcc PCIE_H_CLK>,
++				 <&gcc PCIE_PHY_CLK>;
++			clock-names = "core", "iface", "phy";
++
++			resets = <&gcc PCIE_ACLK_RESET>,
++				 <&gcc PCIE_HCLK_RESET>,
++				 <&gcc PCIE_POR_RESET>,
++				 <&gcc PCIE_PCI_RESET>,
++				 <&gcc PCIE_PHY_RESET>;
++			reset-names = "axi", "ahb", "por", "pci", "phy";
++
++			status = "disabled";
++		};
++
++		pcie1: pci@1b700000 {
++			compatible = "qcom,pcie-v0";
++			reg = <0x1b700000 0x1000
++			       0x1b702000 0x80
++			       0x1b800000 0x100
++			       0x31f00000 0x100000>;
++			reg-names = "dbi", "elbi", "parf", "config";
++			device_type = "pci";
++			linux,pci-domain = <1>;
++			bus-range = <0x00 0xff>;
++			num-lanes = <1>;
++			#address-cells = <3>;
++			#size-cells = <2>;
++
++			ranges = <0x81000000 0 0	  0x31e00000 0 0x00100000   /* downstream I/O */
++				  0x82000000 0 0x00000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */
++
++			interrupts = <GIC_SPI 57 IRQ_TYPE_NONE>;
++			interrupt-names = "msi";
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 0x7>;
++			interrupt-map = <0 0 0 1 &intc 0 58 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
++					<0 0 0 2 &intc 0 59 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
++					<0 0 0 3 &intc 0 60 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
++					<0 0 0 4 &intc 0 61 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
++
++			clocks = <&gcc PCIE_1_A_CLK>,
++				 <&gcc PCIE_1_H_CLK>,
++				 <&gcc PCIE_1_PHY_CLK>;
++			clock-names = "core", "iface", "phy";
++
++			resets = <&gcc PCIE_1_ACLK_RESET>,
++				 <&gcc PCIE_1_HCLK_RESET>,
++				 <&gcc PCIE_1_POR_RESET>,
++				 <&gcc PCIE_1_PCI_RESET>,
++				 <&gcc PCIE_1_PHY_RESET>;
++			reset-names = "axi", "ahb", "por", "pci", "phy";
++
++			status = "disabled";
++		};
++
++		pcie2: pci@1b900000 {
++			compatible = "qcom,pcie-v0";
++			reg = <0x1b900000 0x1000
++			       0x1b902000 0x80
++			       0x1ba00000 0x100
++			       0x35f00000 0x100000>;
++			reg-names = "dbi", "elbi", "parf", "config";
++			device_type = "pci";
++			linux,pci-domain = <2>;
++			bus-range = <0x00 0xff>;
++			num-lanes = <1>;
++			#address-cells = <3>;
++			#size-cells = <2>;
++
++			ranges = <0x81000000 0 0	  0x35e00000 0 0x00100000   /* downstream I/O */
++				  0x82000000 0 0x00000000 0x32000000 0 0x03e00000>; /* non-prefetchable memory */
++
++			interrupts = <GIC_SPI 71 IRQ_TYPE_NONE>;
++			interrupt-names = "msi";
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 0x7>;
++			interrupt-map = <0 0 0 1 &intc 0 72 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
++					<0 0 0 2 &intc 0 73 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
++					<0 0 0 3 &intc 0 74 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
++					<0 0 0 4 &intc 0 75 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
++
++			clocks = <&gcc PCIE_2_A_CLK>,
++				 <&gcc PCIE_2_H_CLK>,
++				 <&gcc PCIE_2_PHY_CLK>;
++			clock-names = "core", "iface", "phy";
++
++			resets = <&gcc PCIE_2_ACLK_RESET>,
++				 <&gcc PCIE_2_HCLK_RESET>,
++				 <&gcc PCIE_2_POR_RESET>,
++				 <&gcc PCIE_2_PCI_RESET>,
++				 <&gcc PCIE_2_PHY_RESET>;
++			reset-names = "axi", "ahb", "por", "pci", "phy";
++
++			status = "disabled";
++		};
++
+ 	};
+ };
diff --git a/target/linux/ipq806x/patches-4.1/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch b/target/linux/ipq806x/patches-4.1/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch
new file mode 100644
index 0000000..e2d3135
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/113-ARM-qcom-automatically-select-PCI_DOMAINS-if-PCI-is-.patch
@@ -0,0 +1,29 @@
+From f004aa1dec6e2e206be025de15b115d60f2b21e3 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Tue, 21 Apr 2015 19:09:07 -0700
+Subject: [PATCH 9/9] ARM: qcom: automatically select PCI_DOMAINS if PCI is
+ enabled
+
+If multiple PCIe devices are present in the system, the kernel will
+panic at boot time when trying to scan the PCI buses. This happens on
+IPQ806x based platforms, which has 3 PCIe ports.
+
+Enabling this option allows the kernel to assign the pci-domains
+according to the device-tree content. This allows multiple PCIe
+controllers to coexist in the system.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/mach-qcom/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/mach-qcom/Kconfig
++++ b/arch/arm/mach-qcom/Kconfig
+@@ -5,6 +5,7 @@ menuconfig ARCH_QCOM
+ 	select ARM_AMBA
+ 	select PINCTRL
+ 	select QCOM_SCM if SMP
++	select PCI_DOMAINS if PCI
+ 	help
+ 	  Support for Qualcomm's devicetree based systems.
+ 
diff --git a/target/linux/ipq806x/patches-4.1/126-add-rpm-to-ipq8064-dts.patch b/target/linux/ipq806x/patches-4.1/126-add-rpm-to-ipq8064-dts.patch
new file mode 100644
index 0000000..be80f4c
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/126-add-rpm-to-ipq8064-dts.patch
@@ -0,0 +1,87 @@
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -2,6 +2,7 @@
+ 
+ #include "skeleton.dtsi"
+ #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
++#include <dt-bindings/mfd/qcom-rpm.h>
+ #include <dt-bindings/clock/qcom,lcc-ipq806x.h>
+ #include <dt-bindings/soc/qcom,gsbi.h>
+ #include <dt-bindings/reset/qcom,gcc-ipq806x.h>
+@@ -92,6 +93,63 @@
+ 			reg-names = "lpass-lpaif";
+ 		};
+ 
++		rpm@108000 {
++			compatible = "qcom,rpm-ipq8064";
++			reg = <0x108000 0x1000>;
++			qcom,ipc = <&l2cc 0x8 2>;
++
++			interrupts = <0 19 0>,
++				     <0 21 0>,
++				     <0 22 0>;
++			interrupt-names = "ack",
++					  "err",
++					  "wakeup";
++
++			#address-cells = <1>;
++			#size-cells = <0>;
++
++			smb208_s1a: smb208-s1a {
++				compatible = "qcom,rpm-smb208";
++				reg = <QCOM_RPM_SMB208_S1a>;
++
++				regulator-min-microvolt = <1050000>;
++				regulator-max-microvolt = <1150000>;
++
++				qcom,switch-mode-frequency = <1200000>;
++
++			};
++
++			smb208_s1b: smb208-s1b {
++				compatible = "qcom,rpm-smb208";
++				reg = <QCOM_RPM_SMB208_S1b>;
++
++				regulator-min-microvolt = <1050000>;
++				regulator-max-microvolt = <1150000>;
++
++				qcom,switch-mode-frequency = <1200000>;
++			};
++
++			smb208_s2a: smb208-s2a {
++				compatible = "qcom,rpm-smb208";
++				reg = <QCOM_RPM_SMB208_S2a>;
++
++				regulator-min-microvolt = < 800000>;
++				regulator-max-microvolt = <1250000>;
++
++				qcom,switch-mode-frequency = <1200000>;
++			};
++
++			smb208_s2b: smb208-s2b {
++				compatible = "qcom,rpm-smb208";
++				reg = <QCOM_RPM_SMB208_S2b>;
++
++				regulator-min-microvolt = < 800000>;
++				regulator-max-microvolt = <1250000>;
++
++				qcom,switch-mode-frequency = <1200000>;
++			};
++		};
++
+ 		qcom_pinmux: pinmux@800000 {
+ 			compatible = "qcom,ipq8064-pinctrl";
+ 			reg = <0x800000 0x4000>;
+@@ -136,6 +194,12 @@
+ 			reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
+ 		};
+ 
++		l2cc: clock-controller@2011000 {
++			compatible = "qcom,kpss-gcc", "syscon";
++			reg = <0x2011000 0x1000>;
++			clock-output-names = "acpu_l2_aux";
++ 		};
++
+ 		saw0: regulator@2089000 {
+ 			compatible = "qcom,saw2";
+ 			reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
diff --git a/target/linux/ipq806x/patches-4.1/133-ARM-Add-Krait-L2-register-accessor-functions.patch b/target/linux/ipq806x/patches-4.1/133-ARM-Add-Krait-L2-register-accessor-functions.patch
new file mode 100644
index 0000000..36a92c8
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/133-ARM-Add-Krait-L2-register-accessor-functions.patch
@@ -0,0 +1,144 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,01/13] ARM: Add Krait L2 register accessor functions
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063051
+Message-Id: <1426920332-9340-2-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>,
+	Mark Rutland <mark.rutland@arm.com>, Russell King <linux@arm.linux.org.uk>,
+	Courtney Cavin <courtney.cavin@sonymobile.com>
+Date: Fri, 20 Mar 2015 23:45:20 -0700
+
+Krait CPUs have a handful of L2 cache controller registers that
+live behind a cp15 based indirection register. First you program
+the indirection register (l2cpselr) to point the L2 'window'
+register (l2cpdr) at what you want to read/write.  Then you
+read/write the 'window' register to do what you want. The
+l2cpselr register is not banked per-cpu so we must lock around
+accesses to it to prevent other CPUs from re-pointing l2cpdr
+underneath us.
+
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Courtney Cavin <courtney.cavin@sonymobile.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+arch/arm/common/Kconfig                   |  3 ++
+ arch/arm/common/Makefile                  |  1 +
+ arch/arm/common/krait-l2-accessors.c      | 58 +++++++++++++++++++++++++++++++
+ arch/arm/include/asm/krait-l2-accessors.h | 20 +++++++++++
+ 4 files changed, 82 insertions(+)
+ create mode 100644 arch/arm/common/krait-l2-accessors.c
+ create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
+
+--- a/arch/arm/common/Kconfig
++++ b/arch/arm/common/Kconfig
+@@ -9,6 +9,9 @@ config DMABOUNCE
+ 	bool
+ 	select ZONE_DMA
+ 
++config KRAIT_L2_ACCESSORS
++	bool
++
+ config SHARP_LOCOMO
+ 	bool
+ 
+--- a/arch/arm/common/Makefile
++++ b/arch/arm/common/Makefile
+@@ -7,6 +7,7 @@ obj-y				+= firmware.o
+ obj-$(CONFIG_ICST)		+= icst.o
+ obj-$(CONFIG_SA1111)		+= sa1111.o
+ obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
++obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
+ obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
+ obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
+ obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
+--- /dev/null
++++ b/arch/arm/common/krait-l2-accessors.c
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/spinlock.h>
++#include <linux/export.h>
++
++#include <asm/barrier.h>
++#include <asm/krait-l2-accessors.h>
++
++static DEFINE_RAW_SPINLOCK(krait_l2_lock);
++
++void krait_set_l2_indirect_reg(u32 addr, u32 val)
++{
++	unsigned long flags;
++
++	raw_spin_lock_irqsave(&krait_l2_lock, flags);
++	/*
++	 * Select the L2 window by poking l2cpselr, then write to the window
++	 * via l2cpdr.
++	 */
++	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
++	isb();
++	asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
++	isb();
++
++	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
++}
++EXPORT_SYMBOL(krait_set_l2_indirect_reg);
++
++u32 krait_get_l2_indirect_reg(u32 addr)
++{
++	u32 val;
++	unsigned long flags;
++
++	raw_spin_lock_irqsave(&krait_l2_lock, flags);
++	/*
++	 * Select the L2 window by poking l2cpselr, then read from the window
++	 * via l2cpdr.
++	 */
++	asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
++	isb();
++	asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
++
++	raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
++
++	return val;
++}
++EXPORT_SYMBOL(krait_get_l2_indirect_reg);
+--- /dev/null
++++ b/arch/arm/include/asm/krait-l2-accessors.h
+@@ -0,0 +1,20 @@
++/*
++ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
++#define __ASMARM_KRAIT_L2_ACCESSORS_H
++
++extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
++extern u32 krait_get_l2_indirect_reg(u32 addr);
++
++#endif
diff --git a/target/linux/ipq806x/patches-4.1/134-clk-mux-Split-out-register-accessors-for-reuse.patch b/target/linux/ipq806x/patches-4.1/134-clk-mux-Split-out-register-accessors-for-reuse.patch
new file mode 100644
index 0000000..3a475fb
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/134-clk-mux-Split-out-register-accessors-for-reuse.patch
@@ -0,0 +1,192 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,02/13] clk: mux: Split out register accessors for reuse
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063111
+Message-Id: <1426920332-9340-3-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:21 -0700
+
+We want to reuse the logic in clk-mux.c for other clock drivers
+that don't use readl as register accessors. Fortunately, there
+really isn't much to the mux code besides the table indirection
+and quirk flags if you assume any bit shifting and masking has
+been done already. Pull that logic out into reusable functions
+that operate on an optional table and some flags so that other
+drivers can use the same logic.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+drivers/clk/clk-mux.c        | 76 +++++++++++++++++++++++++++-----------------
+ include/linux/clk-provider.h |  9 ++++--
+ 2 files changed, 54 insertions(+), 31 deletions(-)
+
+--- a/drivers/clk/clk-mux.c
++++ b/drivers/clk/clk-mux.c
+@@ -29,35 +29,24 @@
+ 
+ #define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+ 
+-static u8 clk_mux_get_parent(struct clk_hw *hw)
++unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
++				unsigned int *table, unsigned long flags)
+ {
+-	struct clk_mux *mux = to_clk_mux(hw);
+ 	int num_parents = __clk_get_num_parents(hw->clk);
+-	u32 val;
+ 
+-	/*
+-	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
+-	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
+-	 * to 0x7 (index starts at one)
+-	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+-	 * val = 0x4 really means "bit 2, index starts at bit 0"
+-	 */
+-	val = clk_readl(mux->reg) >> mux->shift;
+-	val &= mux->mask;
+-
+-	if (mux->table) {
++	if (table) {
+ 		int i;
+ 
+ 		for (i = 0; i < num_parents; i++)
+-			if (mux->table[i] == val)
++			if (table[i] == val)
+ 				return i;
+ 		return -EINVAL;
+ 	}
+ 
+-	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
++	if (val && (flags & CLK_MUX_INDEX_BIT))
+ 		val = ffs(val) - 1;
+ 
+-	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
++	if (val && (flags & CLK_MUX_INDEX_ONE))
+ 		val--;
+ 
+ 	if (val >= num_parents)
+@@ -65,24 +54,53 @@ static u8 clk_mux_get_parent(struct clk_
+ 
+ 	return val;
+ }
++EXPORT_SYMBOL_GPL(clk_mux_get_parent);
+ 
+-static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
++static u8 _clk_mux_get_parent(struct clk_hw *hw)
+ {
+ 	struct clk_mux *mux = to_clk_mux(hw);
+ 	u32 val;
+-	unsigned long flags = 0;
+ 
+-	if (mux->table)
+-		index = mux->table[index];
++	/*
++	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
++	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
++	 * to 0x7 (index starts at one)
++	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
++	 * val = 0x4 really means "bit 2, index starts at bit 0"
++	 */
++	val = clk_readl(mux->reg) >> mux->shift;
++	val &= mux->mask;
++
++	return clk_mux_get_parent(hw, val, mux->table, mux->flags);
++}
+ 
+-	else {
+-		if (mux->flags & CLK_MUX_INDEX_BIT)
+-			index = 1 << index;
++unsigned int clk_mux_reindex(u8 index, unsigned int *table,
++			     unsigned long flags)
++{
++	unsigned int val = index;
+ 
+-		if (mux->flags & CLK_MUX_INDEX_ONE)
+-			index++;
++	if (table) {
++		val = table[val];
++	} else {
++		if (flags & CLK_MUX_INDEX_BIT)
++			val = 1 << index;
++
++		if (flags & CLK_MUX_INDEX_ONE)
++			val++;
+ 	}
+ 
++	return val;
++}
++EXPORT_SYMBOL_GPL(clk_mux_reindex);
++
++static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
++{
++	struct clk_mux *mux = to_clk_mux(hw);
++	u32 val;
++	unsigned long flags = 0;
++
++	index = clk_mux_reindex(index, mux->table, mux->flags);
++
+ 	if (mux->lock)
+ 		spin_lock_irqsave(mux->lock, flags);
+ 
+@@ -102,21 +120,21 @@ static int clk_mux_set_parent(struct clk
+ }
+ 
+ const struct clk_ops clk_mux_ops = {
+-	.get_parent = clk_mux_get_parent,
++	.get_parent = _clk_mux_get_parent,
+ 	.set_parent = clk_mux_set_parent,
+ 	.determine_rate = __clk_mux_determine_rate,
+ };
+ EXPORT_SYMBOL_GPL(clk_mux_ops);
+ 
+ const struct clk_ops clk_mux_ro_ops = {
+-	.get_parent = clk_mux_get_parent,
++	.get_parent = _clk_mux_get_parent,
+ };
+ EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+ 
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+ 		const char **parent_names, u8 num_parents, unsigned long flags,
+ 		void __iomem *reg, u8 shift, u32 mask,
+-		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
++		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock)
+ {
+ 	struct clk_mux *mux;
+ 	struct clk *clk;
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -409,7 +409,7 @@ void clk_unregister_divider(struct clk *
+ struct clk_mux {
+ 	struct clk_hw	hw;
+ 	void __iomem	*reg;
+-	u32		*table;
++	unsigned int	*table;
+ 	u32		mask;
+ 	u8		shift;
+ 	u8		flags;
+@@ -425,6 +425,11 @@ struct clk_mux {
+ extern const struct clk_ops clk_mux_ops;
+ extern const struct clk_ops clk_mux_ro_ops;
+ 
++unsigned int clk_mux_get_parent(struct clk_hw *hw, unsigned int val,
++				unsigned int *table, unsigned long flags);
++unsigned int clk_mux_reindex(u8 index, unsigned int *table,
++			     unsigned long flags);
++
+ struct clk *clk_register_mux(struct device *dev, const char *name,
+ 		const char **parent_names, u8 num_parents, unsigned long flags,
+ 		void __iomem *reg, u8 shift, u8 width,
+@@ -433,7 +438,7 @@ struct clk *clk_register_mux(struct devi
+ struct clk *clk_register_mux_table(struct device *dev, const char *name,
+ 		const char **parent_names, u8 num_parents, unsigned long flags,
+ 		void __iomem *reg, u8 shift, u32 mask,
+-		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
++		u8 clk_mux_flags, unsigned int *table, spinlock_t *lock);
+ 
+ void clk_unregister_mux(struct clk *clk);
+ 
diff --git a/target/linux/ipq806x/patches-4.1/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch b/target/linux/ipq806x/patches-4.1/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch
new file mode 100644
index 0000000..8063860
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/135-clk-Avoid-sending-high-rates-to-downstream-clocks-during-set_rate.patch
@@ -0,0 +1,130 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3, 03/13] clk: Avoid sending high rates to downstream clocks during
+	set_rate
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063271
+Message-Id: <1426920332-9340-4-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:22 -0700
+
+If a clock is on and we call clk_set_rate() on it we may get into
+a situation where the clock temporarily increases in rate
+dramatically while we walk the tree and call .set_rate() ops. For
+example, consider a case where a PLL feeds into a divider.
+Initially the divider is set to divide by 1 and the PLL is
+running fairly slow (100MHz). The downstream consumer of the
+divider output can only handle rates =< 400 MHz, but the divider
+can only choose between divisors of 1 and 4.
+
+ +-----+   +----------------+
+ | PLL |-->| div 1 or div 4 |---> consumer device
+ +-----+   +----------------+
+
+To achieve a rate of 400MHz on the output of the divider, we
+would have to set the rate of the PLL to 1.6 GHz and then divide
+it by 4. The current code would set the PLL to 1.6GHz first while
+the divider is still set to 1, thus causing the downstream
+consumer of the clock to receive a few clock cycles of 1.6GHz
+clock (far beyond it's maximum acceptable rate). We should be
+changing the divider first before increasing the PLL rate to
+avoid this problem.
+
+Therefore, set the rate of any child clocks that are increasing
+in rate from their current rate so that they can increase their
+dividers if necessary. We assume that there isn't such a thing as
+minimum rate requirements.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+drivers/clk/clk.c | 34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -1743,21 +1743,24 @@ static struct clk_core *clk_propagate_ra
+  * walk down a subtree and set the new rates notifying the rate
+  * change on the way
+  */
+-static void clk_change_rate(struct clk_core *clk)
++static void
++clk_change_rate(struct clk_core *clk, unsigned long best_parent_rate)
+ {
+ 	struct clk_core *child;
+ 	struct hlist_node *tmp;
+ 	unsigned long old_rate;
+-	unsigned long best_parent_rate = 0;
+ 	bool skip_set_rate = false;
+ 	struct clk_core *old_parent;
+ 
+-	old_rate = clk->rate;
++	hlist_for_each_entry(child, &clk->children, child_node) {
++		/* Skip children who will be reparented to another clock */
++		if (child->new_parent && child->new_parent != clk)
++			continue;
++		if (child->new_rate > child->rate)
++			clk_change_rate(child, clk->new_rate);
++	}
+ 
+-	if (clk->new_parent)
+-		best_parent_rate = clk->new_parent->rate;
+-	else if (clk->parent)
+-		best_parent_rate = clk->parent->rate;
++	old_rate = clk->rate;
+ 
+ 	if (clk->new_parent && clk->new_parent != clk->parent) {
+ 		old_parent = __clk_set_parent_before(clk, clk->new_parent);
+@@ -1783,7 +1786,7 @@ static void clk_change_rate(struct clk_c
+ 
+ 	trace_clk_set_rate_complete(clk, clk->new_rate);
+ 
+-	clk->rate = clk_recalc(clk, best_parent_rate);
++	clk->rate = clk->new_rate;
+ 
+ 	if (clk->notifier_count && old_rate != clk->rate)
+ 		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+@@ -1796,12 +1799,13 @@ static void clk_change_rate(struct clk_c
+ 		/* Skip children who will be reparented to another clock */
+ 		if (child->new_parent && child->new_parent != clk)
+ 			continue;
+-		clk_change_rate(child);
++		if (child->new_rate != child->rate)
++			clk_change_rate(child, clk->new_rate);
+ 	}
+ 
+ 	/* handle the new child who might not be in clk->children yet */
+-	if (clk->new_child)
+-		clk_change_rate(clk->new_child);
++	if (clk->new_child && clk->new_child->new_rate != clk->new_child->rate)
++		clk_change_rate(clk->new_child, clk->new_rate);
+ }
+ 
+ static int clk_core_set_rate_nolock(struct clk_core *clk,
+@@ -1810,6 +1814,7 @@ static int clk_core_set_rate_nolock(stru
+ 	struct clk_core *top, *fail_clk;
+ 	unsigned long rate = req_rate;
+ 	int ret = 0;
++	unsigned long parent_rate;
+ 
+ 	if (!clk)
+ 		return 0;
+@@ -1835,8 +1840,13 @@ static int clk_core_set_rate_nolock(stru
+ 		return -EBUSY;
+ 	}
+ 
++	if (top->parent)
++		parent_rate = top->parent->rate;
++	else
++		parent_rate = 0;
++
+ 	/* change the rates */
+-	clk_change_rate(top);
++	clk_change_rate(top, parent_rate);
+ 
+ 	clk->req_rate = req_rate;
+ 
diff --git a/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch b/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch
new file mode 100644
index 0000000..0cf4eb3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/136-clk-Add-safe-switch-hook.patch
@@ -0,0 +1,164 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,04/13] clk: Add safe switch hook
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063211
+Message-Id: <1426920332-9340-5-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:23 -0700
+
+Sometimes clocks can't accept their parent source turning off
+while the source is reprogrammed to a different rate. Most
+notably CPU clocks require a way to switch away from the current
+PLL they're running on, reprogram that PLL to a new rate, and
+then switch back to the PLL with the new rate once they're done.
+Add a hook that drivers can implement allowing them to return a
+'safe parent' that they can switch their parent to while the
+upstream source is reprogrammed to support this.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+This patch is good enough for Krait, but soon I'll need to 
+support a "safe rate" where we ask a clock what rate it needs to be running
+at to be sure it's within voltage constraints. Right now safe parent
+handles that problem on Krait, but on other platforms it won't work.
+
+ drivers/clk/clk.c            | 61 ++++++++++++++++++++++++++++++++++++++------
+ include/linux/clk-provider.h |  1 +
+ 2 files changed, 54 insertions(+), 8 deletions(-)
+
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -56,9 +56,12 @@ struct clk_core {
+ 	struct clk_core		**parents;
+ 	u8			num_parents;
+ 	u8			new_parent_index;
++	u8			safe_parent_index;
+ 	unsigned long		rate;
+ 	unsigned long		req_rate;
++	unsigned long		old_rate;
+ 	unsigned long		new_rate;
++	struct clk_core		*safe_parent;
+ 	struct clk_core		*new_parent;
+ 	struct clk_core		*new_child;
+ 	unsigned long		flags;
+@@ -1595,7 +1598,8 @@ out:
+ static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+ 			     struct clk_core *new_parent, u8 p_index)
+ {
+-	struct clk_core *child;
++	struct clk_core *child, *parent;
++	struct clk_hw *parent_hw;
+ 
+ 	clk->new_rate = new_rate;
+ 	clk->new_parent = new_parent;
+@@ -1605,6 +1609,18 @@ static void clk_calc_subtree(struct clk_
+ 	if (new_parent && new_parent != clk->parent)
+ 		new_parent->new_child = clk;
+ 
++	if (clk->ops->get_safe_parent) {
++		parent_hw = clk->ops->get_safe_parent(clk->hw);
++		if (parent_hw) {
++			parent = parent_hw->core;
++			p_index = clk_fetch_parent_index(clk, parent);
++			clk->safe_parent_index = p_index;
++			clk->safe_parent = parent;
++		}
++	} else {
++		clk->safe_parent = NULL;
++	}
++
+ 	hlist_for_each_entry(child, &clk->children, child_node) {
+ 		child->new_rate = clk_recalc(child, new_rate);
+ 		clk_calc_subtree(child, child->new_rate, NULL, 0);
+@@ -1709,14 +1725,43 @@ static struct clk_core *clk_propagate_ra
+ 						  unsigned long event)
+ {
+ 	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
++	struct clk_core *old_parent;
+ 	int ret = NOTIFY_DONE;
+ 
+-	if (clk->rate == clk->new_rate)
++	if (clk->rate == clk->new_rate && event != POST_RATE_CHANGE)
+ 		return NULL;
+ 
++	switch (event) {
++	case PRE_RATE_CHANGE:
++		if (clk->safe_parent)
++			clk->ops->set_parent(clk->hw, clk->safe_parent_index);
++		clk->old_rate = clk->rate;
++		break;
++	case POST_RATE_CHANGE:
++		if (clk->safe_parent) {
++			old_parent = __clk_set_parent_before(clk,
++							     clk->new_parent);
++			if (clk->ops->set_rate_and_parent) {
++				clk->ops->set_rate_and_parent(clk->hw,
++						clk->new_rate,
++						clk->new_parent ?
++						clk->new_parent->rate : 0,
++						clk->new_parent_index);
++			} else if (clk->ops->set_parent) {
++				clk->ops->set_parent(clk->hw,
++						clk->new_parent_index);
++			}
++			__clk_set_parent_after(clk, clk->new_parent,
++					       old_parent);
++		}
++		break;
++	}
++
+ 	if (clk->notifier_count) {
+-		ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
+-		if (ret & NOTIFY_STOP_MASK)
++		if (event != POST_RATE_CHANGE || clk->old_rate != clk->rate)
++			ret = __clk_notify(clk, event, clk->old_rate,
++					   clk->new_rate);
++		if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE)
+ 			fail_clk = clk;
+ 	}
+ 
+@@ -1762,7 +1807,8 @@ clk_change_rate(struct clk_core *clk, un
+ 
+ 	old_rate = clk->rate;
+ 
+-	if (clk->new_parent && clk->new_parent != clk->parent) {
++	if (clk->new_parent && clk->new_parent != clk->parent &&
++			!clk->safe_parent) {
+ 		old_parent = __clk_set_parent_before(clk, clk->new_parent);
+ 		trace_clk_set_parent(clk, clk->new_parent);
+ 
+@@ -1788,9 +1834,6 @@ clk_change_rate(struct clk_core *clk, un
+ 
+ 	clk->rate = clk->new_rate;
+ 
+-	if (clk->notifier_count && old_rate != clk->rate)
+-		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+-
+ 	/*
+ 	 * Use safe iteration, as change_rate can actually swap parents
+ 	 * for certain clock types.
+@@ -1850,6 +1893,8 @@ static int clk_core_set_rate_nolock(stru
+ 
+ 	clk->req_rate = req_rate;
+ 
++	clk_propagate_rate_change(top, POST_RATE_CHANGE);
++
+ 	return ret;
+ }
+ 
+--- a/include/linux/clk-provider.h
++++ b/include/linux/clk-provider.h
+@@ -183,6 +183,7 @@ struct clk_ops {
+ 					  struct clk_hw **best_parent_hw);
+ 	int		(*set_parent)(struct clk_hw *hw, u8 index);
+ 	u8		(*get_parent)(struct clk_hw *hw);
++	struct clk_hw	*(*get_safe_parent)(struct clk_hw *hw);
+ 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
+ 				    unsigned long parent_rate);
+ 	int		(*set_rate_and_parent)(struct clk_hw *hw,
diff --git a/target/linux/ipq806x/patches-4.1/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch b/target/linux/ipq806x/patches-4.1/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch
new file mode 100644
index 0000000..6fad6e8
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/137-clk-qcom-Add-support-for-High-Frequency-PLLs-HFPLLs.patch
@@ -0,0 +1,351 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,05/13] clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063261
+Message-Id: <1426920332-9340-6-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:24 -0700
+
+HFPLLs are the main frequency source for Krait CPU clocks. Add
+support for changing the rate of these PLLs.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+I'd really like to get rid of __clk_hfpll_init_once() if possible...
+
+ drivers/clk/qcom/Makefile    |   1 +
+ drivers/clk/qcom/clk-hfpll.c | 253 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/clk/qcom/clk-hfpll.h |  54 +++++++++
+ 3 files changed, 308 insertions(+)
+ create mode 100644 drivers/clk/qcom/clk-hfpll.c
+ create mode 100644 drivers/clk/qcom/clk-hfpll.h
+
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o
+ clk-qcom-y += clk-branch.o
+ clk-qcom-y += clk-regmap-divider.o
+ clk-qcom-y += clk-regmap-mux.o
++clk-qcom-y += clk-hfpll.o
+ clk-qcom-y += reset.o
+ 
+ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
+--- /dev/null
++++ b/drivers/clk/qcom/clk-hfpll.c
+@@ -0,0 +1,253 @@
++/*
++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++#include <linux/kernel.h>
++#include <linux/export.h>
++#include <linux/regmap.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/clk-provider.h>
++#include <linux/spinlock.h>
++
++#include "clk-regmap.h"
++#include "clk-hfpll.h"
++
++#define PLL_OUTCTRL	BIT(0)
++#define PLL_BYPASSNL	BIT(1)
++#define PLL_RESET_N	BIT(2)
++
++/* Initialize a HFPLL at a given rate and enable it. */
++static void __clk_hfpll_init_once(struct clk_hw *hw)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++
++	if (likely(h->init_done))
++		return;
++
++	/* Configure PLL parameters for integer mode. */
++	if (hd->config_val)
++		regmap_write(regmap, hd->config_reg, hd->config_val);
++	regmap_write(regmap, hd->m_reg, 0);
++	regmap_write(regmap, hd->n_reg, 1);
++
++	if (hd->user_reg) {
++		u32 regval = hd->user_val;
++		unsigned long rate;
++
++		rate = __clk_get_rate(hw->clk);
++
++		/* Pick the right VCO. */
++		if (hd->user_vco_mask && rate > hd->low_vco_max_rate)
++			regval |= hd->user_vco_mask;
++		regmap_write(regmap, hd->user_reg, regval);
++	}
++
++	if (hd->droop_reg)
++		regmap_write(regmap, hd->droop_reg, hd->droop_val);
++
++	h->init_done = true;
++}
++
++static void __clk_hfpll_enable(struct clk_hw *hw)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	u32 val;
++
++	__clk_hfpll_init_once(hw);
++
++	/* Disable PLL bypass mode. */
++	regmap_update_bits(regmap, hd->mode_reg, PLL_BYPASSNL, PLL_BYPASSNL);
++
++	/*
++	 * H/W requires a 5us delay between disabling the bypass and
++	 * de-asserting the reset. Delay 10us just to be safe.
++	 */
++	udelay(10);
++
++	/* De-assert active-low PLL reset. */
++	regmap_update_bits(regmap, hd->mode_reg, PLL_RESET_N, PLL_RESET_N);
++
++	/* Wait for PLL to lock. */
++	if (hd->status_reg) {
++		do {
++			regmap_read(regmap, hd->status_reg, &val);
++		} while (!(val & BIT(hd->lock_bit)));
++	} else {
++		udelay(60);
++	}
++
++	/* Enable PLL output. */
++	regmap_update_bits(regmap, hd->mode_reg, PLL_OUTCTRL, PLL_OUTCTRL);
++}
++
++/* Enable an already-configured HFPLL. */
++static int clk_hfpll_enable(struct clk_hw *hw)
++{
++	unsigned long flags;
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	u32 mode;
++
++	spin_lock_irqsave(&h->lock, flags);
++	regmap_read(regmap, hd->mode_reg, &mode);
++	if (!(mode & (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)))
++		__clk_hfpll_enable(hw);
++	spin_unlock_irqrestore(&h->lock, flags);
++
++	return 0;
++}
++
++static void __clk_hfpll_disable(struct clk_hfpll *h)
++{
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++
++	/*
++	 * Disable the PLL output, disable test mode, enable the bypass mode,
++	 * and assert the reset.
++	 */
++	regmap_update_bits(regmap, hd->mode_reg,
++			PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL, 0);
++}
++
++static void clk_hfpll_disable(struct clk_hw *hw)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	unsigned long flags;
++
++	spin_lock_irqsave(&h->lock, flags);
++	__clk_hfpll_disable(h);
++	spin_unlock_irqrestore(&h->lock, flags);
++}
++
++static long clk_hfpll_round_rate(struct clk_hw *hw, unsigned long rate,
++				 unsigned long *parent_rate)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	unsigned long rrate;
++
++	rate = clamp(rate, hd->min_rate, hd->max_rate);
++
++	rrate = DIV_ROUND_UP(rate, *parent_rate) * *parent_rate;
++	if (rrate > hd->max_rate)
++		rrate -= *parent_rate;
++
++	return rrate;
++}
++
++/*
++ * For optimization reasons, assumes no downstream clocks are actively using
++ * it.
++ */
++static int clk_hfpll_set_rate(struct clk_hw *hw, unsigned long rate,
++			      unsigned long parent_rate)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	unsigned long flags;
++	u32 l_val, val;
++	bool enabled;
++
++	l_val = rate / parent_rate;
++
++	spin_lock_irqsave(&h->lock, flags);
++
++	enabled = __clk_is_enabled(hw->clk);
++	if (enabled)
++		__clk_hfpll_disable(h);
++
++	/* Pick the right VCO. */
++	if (hd->user_reg && hd->user_vco_mask) {
++		regmap_read(regmap, hd->user_reg, &val);
++		if (rate <= hd->low_vco_max_rate)
++			val &= ~hd->user_vco_mask;
++		else
++			val |= hd->user_vco_mask;
++		regmap_write(regmap, hd->user_reg, val);
++	}
++
++	regmap_write(regmap, hd->l_reg, l_val);
++
++	if (enabled)
++		__clk_hfpll_enable(hw);
++
++	spin_unlock_irqrestore(&h->lock, flags);
++
++	return 0;
++}
++
++static unsigned long clk_hfpll_recalc_rate(struct clk_hw *hw,
++					   unsigned long parent_rate)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	u32 l_val;
++
++	regmap_read(regmap, hd->l_reg, &l_val);
++
++	return l_val * parent_rate;
++}
++
++static void clk_hfpll_init(struct clk_hw *hw)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	u32 mode, status;
++
++	regmap_read(regmap, hd->mode_reg, &mode);
++	if (mode != (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL)) {
++		__clk_hfpll_init_once(hw);
++		return;
++	}
++
++	if (hd->status_reg) {
++		regmap_read(regmap, hd->status_reg, &status);
++		if (!(status & BIT(hd->lock_bit))) {
++			WARN(1, "HFPLL %s is ON, but not locked!\n",
++					__clk_get_name(hw->clk));
++			clk_hfpll_disable(hw);
++			__clk_hfpll_init_once(hw);
++		}
++	}
++}
++
++static int hfpll_is_enabled(struct clk_hw *hw)
++{
++	struct clk_hfpll *h = to_clk_hfpll(hw);
++	struct hfpll_data const *hd = h->d;
++	struct regmap *regmap = h->clkr.regmap;
++	u32 mode;
++
++	regmap_read(regmap, hd->mode_reg, &mode);
++	mode &= 0x7;
++	return mode == (PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL);
++}
++
++const struct clk_ops clk_ops_hfpll = {
++	.enable = clk_hfpll_enable,
++	.disable = clk_hfpll_disable,
++	.is_enabled = hfpll_is_enabled,
++	.round_rate = clk_hfpll_round_rate,
++	.set_rate = clk_hfpll_set_rate,
++	.recalc_rate = clk_hfpll_recalc_rate,
++	.init = clk_hfpll_init,
++};
++EXPORT_SYMBOL_GPL(clk_ops_hfpll);
+--- /dev/null
++++ b/drivers/clk/qcom/clk-hfpll.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++#ifndef __QCOM_CLK_HFPLL_H__
++#define __QCOM_CLK_HFPLL_H__
++
++#include <linux/clk-provider.h>
++#include <linux/spinlock.h>
++#include "clk-regmap.h"
++
++struct hfpll_data {
++	u32 mode_reg;
++	u32 l_reg;
++	u32 m_reg;
++	u32 n_reg;
++	u32 user_reg;
++	u32 droop_reg;
++	u32 config_reg;
++	u32 status_reg;
++	u8  lock_bit;
++
++	u32 droop_val;
++	u32 config_val;
++	u32 user_val;
++	u32 user_vco_mask;
++	unsigned long low_vco_max_rate;
++
++	unsigned long min_rate;
++	unsigned long max_rate;
++};
++
++struct clk_hfpll {
++	struct hfpll_data const *d;
++	int init_done;
++
++	struct clk_regmap clkr;
++	spinlock_t lock;
++};
++
++#define to_clk_hfpll(_hw) \
++	container_of(to_clk_regmap(_hw), struct clk_hfpll, clkr)
++
++extern const struct clk_ops clk_ops_hfpll;
++
++#endif
diff --git a/target/linux/ipq806x/patches-4.1/138-clk-qcom-Add-HFPLL-driver.patch b/target/linux/ipq806x/patches-4.1/138-clk-qcom-Add-HFPLL-driver.patch
new file mode 100644
index 0000000..4056784
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/138-clk-qcom-Add-HFPLL-driver.patch
@@ -0,0 +1,206 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,06/13] clk: qcom: Add HFPLL driver
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063231
+Message-Id: <1426920332-9340-7-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
+Date: Fri, 20 Mar 2015 23:45:25 -0700
+
+On some devices (MSM8974 for example), the HFPLLs are
+instantiated within the Krait processor subsystem as separate
+register regions. Add a driver for these PLLs so that we can
+provide HFPLL clocks for use by the system.
+
+Cc: <devicetree@vger.kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+.../devicetree/bindings/clock/qcom,hfpll.txt       |  40 ++++++++
+ drivers/clk/qcom/Kconfig                           |   8 ++
+ drivers/clk/qcom/Makefile                          |   1 +
+ drivers/clk/qcom/hfpll.c                           | 109 +++++++++++++++++++++
+ 4 files changed, 158 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt
+ create mode 100644 drivers/clk/qcom/hfpll.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt
+@@ -0,0 +1,40 @@
++High-Frequency PLL (HFPLL)
++
++PROPERTIES
++
++- compatible:
++	Usage: required
++	Value type: <string>
++	Definition: must be "qcom,hfpll"
++
++- reg:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: address and size of HPLL registers. An optional second
++		    element specifies the address and size of the alias
++		    register region.
++
++- clock-output-names:
++	Usage: required
++	Value type: <string>
++	Definition: Name of the PLL. Typically hfpllX where X is a CPU number
++		    starting at 0. Otherwise hfpll_Y where Y is more specific
++		    such as "l2".
++
++Example:
++
++1) An HFPLL for the L2 cache.
++
++	clock-controller@f9016000 {
++		compatible = "qcom,hfpll";
++		reg = <0xf9016000 0x30>;
++		clock-output-names = "hfpll_l2";
++	};
++
++2) An HFPLL for CPU0. This HFPLL has the alias register region.
++
++	clock-controller@f908a000 {
++		compatible = "qcom,hfpll";
++		reg = <0xf908a000 0x30>, <0xf900a000 0x30>;
++		clock-output-names = "hfpll0";
++	};
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -97,3 +97,11 @@ config MSM_MMCC_8974
+ 	  Support for the multimedia clock controller on msm8974 devices.
+ 	  Say Y if you want to support multimedia devices such as display,
+ 	  graphics, video encode/decode, camera, etc.
++
++config QCOM_HFPLL
++	tristate "High-Frequency PLL (HFPLL) Clock Controller"
++	depends on COMMON_CLK_QCOM
++	help
++	  Support for the high-frequency PLLs present on Qualcomm devices.
++	  Say Y if you want to support CPU frequency scaling on devices
++	  such as MSM8974, APQ8084, etc.
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -22,3 +22,4 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896
+ obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
+ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
++obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
+--- /dev/null
++++ b/drivers/clk/qcom/hfpll.c
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/of.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/regmap.h>
++
++#include "clk-regmap.h"
++#include "clk-hfpll.h"
++
++static const struct hfpll_data hdata = {
++	.mode_reg = 0x00,
++	.l_reg = 0x04,
++	.m_reg = 0x08,
++	.n_reg = 0x0c,
++	.user_reg = 0x10,
++	.config_reg = 0x14,
++	.config_val = 0x430405d,
++	.status_reg = 0x1c,
++	.lock_bit = 16,
++
++	.user_val = 0x8,
++	.user_vco_mask = 0x100000,
++	.low_vco_max_rate = 1248000000,
++	.min_rate = 537600000UL,
++	.max_rate = 2900000000UL,
++};
++
++static const struct of_device_id qcom_hfpll_match_table[] = {
++	{ .compatible = "qcom,hfpll" },
++	{ }
++};
++MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table);
++
++static const struct regmap_config hfpll_regmap_config = {
++	.reg_bits	= 32,
++	.reg_stride	= 4,
++	.val_bits	= 32,
++	.max_register	= 0x30,
++	.fast_io	= true,
++};
++
++static int qcom_hfpll_probe(struct platform_device *pdev)
++{
++	struct clk *clk;
++	struct resource *res;
++	struct device *dev = &pdev->dev;
++	void __iomem *base;
++	struct regmap *regmap;
++	struct clk_hfpll *h;
++	struct clk_init_data init = {
++		.parent_names = (const char *[]){ "xo" },
++		.num_parents = 1,
++		.ops = &clk_ops_hfpll,
++	};
++
++	h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);
++	if (!h)
++		return -ENOMEM;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	base = devm_ioremap_resource(dev, res);
++	if (IS_ERR(base))
++		return PTR_ERR(base);
++
++	regmap = devm_regmap_init_mmio(&pdev->dev, base, &hfpll_regmap_config);
++	if (IS_ERR(regmap))
++		return PTR_ERR(regmap);
++
++	if (of_property_read_string_index(dev->of_node, "clock-output-names",
++						  0, &init.name))
++		return -ENODEV;
++
++	h->d = &hdata;
++	h->clkr.hw.init = &init;
++	spin_lock_init(&h->lock);
++
++	clk = devm_clk_register_regmap(&pdev->dev, &h->clkr);
++
++	return PTR_ERR_OR_ZERO(clk);
++}
++
++static struct platform_driver qcom_hfpll_driver = {
++	.probe		= qcom_hfpll_probe,
++	.driver		= {
++		.name	= "qcom-hfpll",
++		.of_match_table = qcom_hfpll_match_table,
++	},
++};
++module_platform_driver(qcom_hfpll_driver);
++
++MODULE_DESCRIPTION("QCOM HFPLL Clock Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:qcom-hfpll");
diff --git a/target/linux/ipq806x/patches-4.1/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch b/target/linux/ipq806x/patches-4.1/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch
new file mode 100644
index 0000000..ffcd462
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/139-clk-qcom-Add-IPQ806X-s-HFPLLs.patch
@@ -0,0 +1,127 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,08/13] clk: qcom: Add IPQ806X's HFPLLs
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063241
+Message-Id: <1426920332-9340-9-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:27 -0700
+
+Describe the HFPLLs present on IPQ806X devices.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+drivers/clk/qcom/gcc-ipq806x.c | 83 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 83 insertions(+)
+
+--- a/drivers/clk/qcom/gcc-ipq806x.c
++++ b/drivers/clk/qcom/gcc-ipq806x.c
+@@ -30,6 +30,7 @@
+ #include "clk-pll.h"
+ #include "clk-rcg.h"
+ #include "clk-branch.h"
++#include "clk-hfpll.h"
+ #include "reset.h"
+ 
+ static struct clk_pll pll0 = {
+@@ -113,6 +114,85 @@ static struct clk_regmap pll8_vote = {
+ 	},
+ };
+ 
++static struct hfpll_data hfpll0_data = {
++	.mode_reg = 0x3200,
++	.l_reg = 0x3208,
++	.m_reg = 0x320c,
++	.n_reg = 0x3210,
++	.config_reg = 0x3204,
++	.status_reg = 0x321c,
++	.config_val = 0x7845c665,
++	.droop_reg = 0x3214,
++	.droop_val = 0x0108c000,
++	.min_rate = 600000000UL,
++	.max_rate = 1800000000UL,
++};
++
++static struct clk_hfpll hfpll0 = {
++	.d = &hfpll0_data,
++	.clkr.hw.init = &(struct clk_init_data){
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.name = "hfpll0",
++		.ops = &clk_ops_hfpll,
++		.flags = CLK_IGNORE_UNUSED,
++	},
++	.lock = __SPIN_LOCK_UNLOCKED(hfpll0.lock),
++};
++
++static struct hfpll_data hfpll1_data = {
++	.mode_reg = 0x3240,
++	.l_reg = 0x3248,
++	.m_reg = 0x324c,
++	.n_reg = 0x3250,
++	.config_reg = 0x3244,
++	.status_reg = 0x325c,
++	.config_val = 0x7845c665,
++	.droop_reg = 0x3314,
++	.droop_val = 0x0108c000,
++	.min_rate = 600000000UL,
++	.max_rate = 1800000000UL,
++};
++
++static struct clk_hfpll hfpll1 = {
++	.d = &hfpll1_data,
++	.clkr.hw.init = &(struct clk_init_data){
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.name = "hfpll1",
++		.ops = &clk_ops_hfpll,
++		.flags = CLK_IGNORE_UNUSED,
++	},
++	.lock = __SPIN_LOCK_UNLOCKED(hfpll1.lock),
++};
++
++static struct hfpll_data hfpll_l2_data = {
++	.mode_reg = 0x3300,
++	.l_reg = 0x3308,
++	.m_reg = 0x330c,
++	.n_reg = 0x3310,
++	.config_reg = 0x3304,
++	.status_reg = 0x331c,
++	.config_val = 0x7845c665,
++	.droop_reg = 0x3314,
++	.droop_val = 0x0108c000,
++	.min_rate = 600000000UL,
++	.max_rate = 1800000000UL,
++};
++
++static struct clk_hfpll hfpll_l2 = {
++	.d = &hfpll_l2_data,
++	.clkr.hw.init = &(struct clk_init_data){
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.name = "hfpll_l2",
++		.ops = &clk_ops_hfpll,
++		.flags = CLK_IGNORE_UNUSED,
++	},
++	.lock = __SPIN_LOCK_UNLOCKED(hfpll_l2.lock),
++};
++
++
+ static struct clk_pll pll14 = {
+ 	.l_reg = 0x31c4,
+ 	.m_reg = 0x31c8,
+@@ -2307,6 +2387,9 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr,
+ 	[EBI2_CLK] = &ebi2_clk.clkr,
+ 	[EBI2_AON_CLK] = &ebi2_aon_clk.clkr,
++	[PLL9] = &hfpll0.clkr,
++	[PLL10] = &hfpll1.clkr,
++	[PLL12] = &hfpll_l2.clkr,
+ };
+ 
+ static const struct qcom_reset_map gcc_ipq806x_resets[] = {
diff --git a/target/linux/ipq806x/patches-4.1/140-clk-qcom-Add-support-for-Krait-clocks.patch b/target/linux/ipq806x/patches-4.1/140-clk-qcom-Add-support-for-Krait-clocks.patch
new file mode 100644
index 0000000..5fcc787
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/140-clk-qcom-Add-support-for-Krait-clocks.patch
@@ -0,0 +1,271 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,09/13] clk: qcom: Add support for Krait clocks
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063251
+Message-Id: <1426920332-9340-10-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>
+Date: Fri, 20 Mar 2015 23:45:28 -0700
+
+The Krait clocks are made up of a series of muxes and a divider
+that choose between a fixed rate clock and dedicated HFPLLs for
+each CPU. Instead of using mmio accesses to remux parents, the
+Krait implementation exposes the remux control via cp15
+registers. Support these clocks.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+drivers/clk/qcom/Kconfig     |   4 ++
+ drivers/clk/qcom/Makefile    |   1 +
+ drivers/clk/qcom/clk-krait.c | 166 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/clk/qcom/clk-krait.h |  49 +++++++++++++
+ 4 files changed, 220 insertions(+)
+ create mode 100644 drivers/clk/qcom/clk-krait.c
+ create mode 100644 drivers/clk/qcom/clk-krait.h
+
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -105,3 +105,7 @@ config QCOM_HFPLL
+ 	  Support for the high-frequency PLLs present on Qualcomm devices.
+ 	  Say Y if you want to support CPU frequency scaling on devices
+ 	  such as MSM8974, APQ8084, etc.
++
++config KRAIT_CLOCKS
++	bool
++	select KRAIT_L2_ACCESSORS
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -8,6 +8,7 @@ clk-qcom-y += clk-rcg2.o
+ clk-qcom-y += clk-branch.o
+ clk-qcom-y += clk-regmap-divider.o
+ clk-qcom-y += clk-regmap-mux.o
++clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o
+ clk-qcom-y += clk-hfpll.o
+ clk-qcom-y += reset.o
+ 
+--- /dev/null
++++ b/drivers/clk/qcom/clk-krait.c
+@@ -0,0 +1,166 @@
++/*
++ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/clk-provider.h>
++#include <linux/spinlock.h>
++
++#include <asm/krait-l2-accessors.h>
++
++#include "clk-krait.h"
++
++/* Secondary and primary muxes share the same cp15 register */
++static DEFINE_SPINLOCK(krait_clock_reg_lock);
++
++#define LPL_SHIFT	8
++static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel)
++{
++	unsigned long flags;
++	u32 regval;
++
++	spin_lock_irqsave(&krait_clock_reg_lock, flags);
++	regval = krait_get_l2_indirect_reg(mux->offset);
++	regval &= ~(mux->mask << mux->shift);
++	regval |= (sel & mux->mask) << mux->shift;
++	if (mux->lpl) {
++		regval &= ~(mux->mask << (mux->shift + LPL_SHIFT));
++		regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT);
++	}
++	krait_set_l2_indirect_reg(mux->offset, regval);
++	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
++
++	/* Wait for switch to complete. */
++	mb();
++	udelay(1);
++}
++
++static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
++{
++	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
++	u32 sel;
++
++	sel = clk_mux_reindex(index, mux->parent_map, 0);
++	mux->en_mask = sel;
++	/* Don't touch mux if CPU is off as it won't work */
++	if (__clk_is_enabled(hw->clk))
++		__krait_mux_set_sel(mux, sel);
++	return 0;
++}
++
++static u8 krait_mux_get_parent(struct clk_hw *hw)
++{
++	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
++	u32 sel;
++
++	sel = krait_get_l2_indirect_reg(mux->offset);
++	sel >>= mux->shift;
++	sel &= mux->mask;
++	mux->en_mask = sel;
++
++	return clk_mux_get_parent(hw, sel, mux->parent_map, 0);
++}
++
++static struct clk_hw *krait_mux_get_safe_parent(struct clk_hw *hw)
++{
++	int i;
++	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
++	int num_parents = __clk_get_num_parents(hw->clk);
++
++	i = mux->safe_sel;
++	for (i = 0; i < num_parents; i++)
++		if (mux->safe_sel == mux->parent_map[i])
++			break;
++
++	return __clk_get_hw(clk_get_parent_by_index(hw->clk, i));
++}
++
++static int krait_mux_enable(struct clk_hw *hw)
++{
++	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
++
++	__krait_mux_set_sel(mux, mux->en_mask);
++
++	return 0;
++}
++
++static void krait_mux_disable(struct clk_hw *hw)
++{
++	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
++
++	__krait_mux_set_sel(mux, mux->safe_sel);
++}
++
++const struct clk_ops krait_mux_clk_ops = {
++	.enable = krait_mux_enable,
++	.disable = krait_mux_disable,
++	.set_parent = krait_mux_set_parent,
++	.get_parent = krait_mux_get_parent,
++	.determine_rate = __clk_mux_determine_rate_closest,
++	.get_safe_parent = krait_mux_get_safe_parent,
++};
++EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
++
++/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
++static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
++				  unsigned long *parent_rate)
++{
++	*parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), rate * 2);
++	return DIV_ROUND_UP(*parent_rate, 2);
++}
++
++static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
++			unsigned long parent_rate)
++{
++	struct krait_div2_clk *d = to_krait_div2_clk(hw);
++	unsigned long flags;
++	u32 val;
++	u32 mask = BIT(d->width) - 1;
++
++	if (d->lpl)
++		mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
++
++	spin_lock_irqsave(&krait_clock_reg_lock, flags);
++	val = krait_get_l2_indirect_reg(d->offset);
++	val &= ~mask;
++	krait_set_l2_indirect_reg(d->offset, val);
++	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
++
++	return 0;
++}
++
++static unsigned long
++krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
++{
++	struct krait_div2_clk *d = to_krait_div2_clk(hw);
++	u32 mask = BIT(d->width) - 1;
++	u32 div;
++
++	div = krait_get_l2_indirect_reg(d->offset);
++	div >>= d->shift;
++	div &= mask;
++	div = (div + 1) * 2;
++
++	return DIV_ROUND_UP(parent_rate, div);
++}
++
++const struct clk_ops krait_div2_clk_ops = {
++	.round_rate = krait_div2_round_rate,
++	.set_rate = krait_div2_set_rate,
++	.recalc_rate = krait_div2_recalc_rate,
++};
++EXPORT_SYMBOL_GPL(krait_div2_clk_ops);
+--- /dev/null
++++ b/drivers/clk/qcom/clk-krait.h
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#ifndef __QCOM_CLK_KRAIT_H
++#define __QCOM_CLK_KRAIT_H
++
++#include <linux/clk-provider.h>
++
++struct krait_mux_clk {
++	unsigned int	*parent_map;
++	bool		has_safe_parent;
++	u8		safe_sel;
++	u32		offset;
++	u32		mask;
++	u32		shift;
++	u32		en_mask;
++	bool		lpl;
++
++	struct clk_hw	hw;
++};
++
++#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw)
++
++extern const struct clk_ops krait_mux_clk_ops;
++
++struct krait_div2_clk {
++	u32		offset;
++	u8		width;
++	u32		shift;
++	bool		lpl;
++
++	struct clk_hw	hw;
++};
++
++#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw)
++
++extern const struct clk_ops krait_div2_clk_ops;
++
++#endif
diff --git a/target/linux/ipq806x/patches-4.1/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch b/target/linux/ipq806x/patches-4.1/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch
new file mode 100644
index 0000000..db43888
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/141-clk-qcom-Add-KPSS-ACC-GCC-driver.patch
@@ -0,0 +1,205 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,10/13] clk: qcom: Add KPSS ACC/GCC driver
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063201
+Message-Id: <1426920332-9340-11-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
+Date: Fri, 20 Mar 2015 23:45:29 -0700
+
+The ACC and GCC regions present in KPSSv1 contain registers to
+control clocks and power to each Krait CPU and L2. For CPUfreq
+purposes probe these devices and expose a mux clock that chooses
+between PXO and PLL8.
+
+Cc: <devicetree@vger.kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+.../devicetree/bindings/arm/msm/qcom,kpss-acc.txt  |  7 ++
+ .../devicetree/bindings/arm/msm/qcom,kpss-gcc.txt  | 28 +++++++
+ drivers/clk/qcom/Kconfig                           |  8 ++
+ drivers/clk/qcom/Makefile                          |  1 +
+ drivers/clk/qcom/kpss-xcc.c                        | 95 ++++++++++++++++++++++
+ 5 files changed, 139 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
+ create mode 100644 drivers/clk/qcom/kpss-xcc.c
+
+--- a/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
++++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-acc.txt
+@@ -21,10 +21,17 @@ PROPERTIES
+ 		    the register region. An optional second element specifies
+ 		    the base address and size of the alias register region.
+ 
++- clock-output-names:
++	Usage: optional
++	Value type: <string>
++	Definition: Name of the output clock. Typically acpuX_aux where X is a
++		    CPU number starting at 0.
++
+ Example:
+ 
+ 	clock-controller@2088000 {
+ 		compatible = "qcom,kpss-acc-v2";
+ 		reg = <0x02088000 0x1000>,
+ 		      <0x02008000 0x1000>;
++		clock-output-names = "acpu0_aux";
+ 	};
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/msm/qcom,kpss-gcc.txt
+@@ -0,0 +1,28 @@
++Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
++
++PROPERTIES
++
++- compatible:
++	Usage: required
++	Value type: <string>
++	Definition: should be one of:
++			"qcom,kpss-gcc"
++
++- reg:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: base address and size of the register region
++
++- clock-output-names:
++	Usage: required
++	Value type: <string>
++	Definition: Name of the output clock. Typically acpu_l2_aux indicating
++		    an L2 cache auxiliary clock.
++
++Example:
++
++	l2cc: clock-controller@2011000 {
++		compatible = "qcom,kpss-gcc";
++		reg = <0x2011000 0x1000>;
++		clock-output-names = "acpu_l2_aux";
++	};
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -106,6 +106,14 @@ config QCOM_HFPLL
+ 	  Say Y if you want to support CPU frequency scaling on devices
+ 	  such as MSM8974, APQ8084, etc.
+ 
++config KPSS_XCC
++	tristate "KPSS Clock Controller"
++	depends on COMMON_CLK_QCOM
++	help
++	  Support for the Krait ACC and GCC clock controllers. Say Y
++	  if you want to support CPU frequency scaling on devices such
++	  as MSM8960, APQ8064, etc.
++
+ config KRAIT_CLOCKS
+ 	bool
+ 	select KRAIT_L2_ACCESSORS
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -23,4 +23,5 @@ obj-$(CONFIG_MSM_LCC_8960) += lcc-msm896
+ obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
+ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
++obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
+ obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
+--- /dev/null
++++ b/drivers/clk/qcom/kpss-xcc.c
+@@ -0,0 +1,95 @@
++/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++
++static const char *aux_parents[] = {
++	"pll8_vote",
++	"pxo",
++};
++
++static unsigned int aux_parent_map[] = {
++	3,
++	0,
++};
++
++static const struct of_device_id kpss_xcc_match_table[] = {
++	{ .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL },
++	{ .compatible = "qcom,kpss-gcc" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
++
++static int kpss_xcc_driver_probe(struct platform_device *pdev)
++{
++	const struct of_device_id *id;
++	struct clk *clk;
++	struct resource *res;
++	void __iomem *base;
++	const char *name;
++
++	id = of_match_device(kpss_xcc_match_table, &pdev->dev);
++	if (!id)
++		return -ENODEV;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	base = devm_ioremap_resource(&pdev->dev, res);
++	if (IS_ERR(base))
++		return PTR_ERR(base);
++
++	if (id->data) {
++		if (of_property_read_string_index(pdev->dev.of_node,
++					"clock-output-names", 0, &name))
++			return -ENODEV;
++		base += 0x14;
++	} else {
++		name = "acpu_l2_aux";
++		base += 0x28;
++	}
++
++	clk = clk_register_mux_table(&pdev->dev, name, aux_parents,
++				     ARRAY_SIZE(aux_parents), 0, base, 0, 0x3,
++				     0, aux_parent_map, NULL);
++
++	platform_set_drvdata(pdev, clk);
++
++	return PTR_ERR_OR_ZERO(clk);
++}
++
++static int kpss_xcc_driver_remove(struct platform_device *pdev)
++{
++	clk_unregister_mux(platform_get_drvdata(pdev));
++	return 0;
++}
++
++static struct platform_driver kpss_xcc_driver = {
++	.probe = kpss_xcc_driver_probe,
++	.remove = kpss_xcc_driver_remove,
++	.driver = {
++		.name = "kpss-xcc",
++		.of_match_table = kpss_xcc_match_table,
++	},
++};
++module_platform_driver(kpss_xcc_driver);
++
++MODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:kpss-xcc");
diff --git a/target/linux/ipq806x/patches-4.1/142-clk-qcom-Add-Krait-clock-controller-driver.patch b/target/linux/ipq806x/patches-4.1/142-clk-qcom-Add-Krait-clock-controller-driver.patch
new file mode 100644
index 0000000..59fc44f
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/142-clk-qcom-Add-Krait-clock-controller-driver.patch
@@ -0,0 +1,435 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,11/13] clk: qcom: Add Krait clock controller driver
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063121
+Message-Id: <1426920332-9340-12-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
+Date: Fri, 20 Mar 2015 23:45:30 -0700
+
+The Krait CPU clocks are made up of a primary mux and secondary
+mux for each CPU and the L2, controlled via cp15 accessors. For
+Kraits within KPSSv1 each secondary mux accepts a different aux
+source, but on KPSSv2 each secondary mux accepts the same aux
+source.
+
+Cc: <devicetree@vger.kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+.../devicetree/bindings/clock/qcom,krait-cc.txt    |  22 ++
+ drivers/clk/qcom/Kconfig                           |   8 +
+ drivers/clk/qcom/Makefile                          |   1 +
+ drivers/clk/qcom/krait-cc.c                        | 352 +++++++++++++++++++++
+ 4 files changed, 383 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
+ create mode 100644 drivers/clk/qcom/krait-cc.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
+@@ -0,0 +1,22 @@
++Krait Clock Controller
++
++PROPERTIES
++
++- compatible:
++	Usage: required
++	Value type: <string>
++	Definition: must be one of:
++			"qcom,krait-cc-v1"
++			"qcom,krait-cc-v2"
++
++- #clock-cells:
++	Usage: required
++	Value type: <u32>
++	Definition: must be 1
++
++Example:
++
++	kraitcc: clock-controller {
++		compatible = "qcom,krait-cc-v1";
++		#clock-cells = <1>;
++	};
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -114,6 +114,14 @@ config KPSS_XCC
+ 	  if you want to support CPU frequency scaling on devices such
+ 	  as MSM8960, APQ8064, etc.
+ 
++config KRAITCC
++	tristate "Krait Clock Controller"
++	depends on COMMON_CLK_QCOM && ARM
++	select KRAIT_CLOCKS
++	help
++	  Support for the Krait CPU clocks on Qualcomm devices.
++	  Say Y if you want to support CPU frequency scaling.
++
+ config KRAIT_CLOCKS
+ 	bool
+ 	select KRAIT_L2_ACCESSORS
+--- a/drivers/clk/qcom/Makefile
++++ b/drivers/clk/qcom/Makefile
+@@ -25,3 +25,4 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8
+ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
+ obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
+ obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
++obj-$(CONFIG_KRAITCC) += krait-cc.o
+--- /dev/null
++++ b/drivers/clk/qcom/krait-cc.c
+@@ -0,0 +1,352 @@
++/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/slab.h>
++
++#include "clk-krait.h"
++
++static unsigned int sec_mux_map[] = {
++	2,
++	0,
++};
++
++static unsigned int pri_mux_map[] = {
++	1,
++	2,
++	0,
++};
++
++static int
++krait_add_div(struct device *dev, int id, const char *s, unsigned offset)
++{
++	struct krait_div2_clk *div;
++	struct clk_init_data init = {
++		.num_parents = 1,
++		.ops = &krait_div2_clk_ops,
++		.flags = CLK_SET_RATE_PARENT,
++	};
++	const char *p_names[1];
++	struct clk *clk;
++
++	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
++	if (!div)
++		return -ENOMEM;
++
++	div->width = 2;
++	div->shift = 6;
++	div->lpl = id >= 0;
++	div->offset = offset;
++	div->hw.init = &init;
++
++	init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
++	if (!init.name)
++		return -ENOMEM;
++
++	init.parent_names = p_names;
++	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
++	if (!p_names[0]) {
++		kfree(init.name);
++		return -ENOMEM;
++	}
++
++	clk = devm_clk_register(dev, &div->hw);
++	kfree(p_names[0]);
++	kfree(init.name);
++
++	return PTR_ERR_OR_ZERO(clk);
++}
++
++static int
++krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset,
++		  bool unique_aux)
++{
++	struct krait_mux_clk *mux;
++	static const char *sec_mux_list[] = {
++		"acpu_aux",
++		"qsb",
++	};
++	struct clk_init_data init = {
++		.parent_names = sec_mux_list,
++		.num_parents = ARRAY_SIZE(sec_mux_list),
++		.ops = &krait_mux_clk_ops,
++		.flags = CLK_SET_RATE_PARENT,
++	};
++	struct clk *clk;
++
++	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
++	if (!mux)
++		return -ENOMEM;
++
++	mux->offset = offset;
++	mux->lpl = id >= 0;
++	mux->has_safe_parent = true;
++	mux->safe_sel = 2;
++	mux->mask = 0x3;
++	mux->shift = 2;
++	mux->parent_map = sec_mux_map;
++	mux->hw.init = &init;
++
++	init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
++	if (!init.name)
++		return -ENOMEM;
++
++	if (unique_aux) {
++		sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
++		if (!sec_mux_list[0]) {
++			clk = ERR_PTR(-ENOMEM);
++			goto err_aux;
++		}
++	}
++
++	clk = devm_clk_register(dev, &mux->hw);
++
++	if (unique_aux)
++		kfree(sec_mux_list[0]);
++err_aux:
++	kfree(init.name);
++	return PTR_ERR_OR_ZERO(clk);
++}
++
++static struct clk *
++krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset)
++{
++	struct krait_mux_clk *mux;
++	const char *p_names[3];
++	struct clk_init_data init = {
++		.parent_names = p_names,
++		.num_parents = ARRAY_SIZE(p_names),
++		.ops = &krait_mux_clk_ops,
++		.flags = CLK_SET_RATE_PARENT,
++	};
++	struct clk *clk;
++
++	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
++	if (!mux)
++		return ERR_PTR(-ENOMEM);
++
++	mux->has_safe_parent = true;
++	mux->safe_sel = 0;
++	mux->mask = 0x3;
++	mux->shift = 0;
++	mux->offset = offset;
++	mux->lpl = id >= 0;
++	mux->parent_map = pri_mux_map;
++	mux->hw.init = &init;
++
++	init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
++	if (!init.name)
++		return ERR_PTR(-ENOMEM);
++
++	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
++	if (!p_names[0]) {
++		clk = ERR_PTR(-ENOMEM);
++		goto err_p0;
++	}
++
++	p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
++	if (!p_names[1]) {
++		clk = ERR_PTR(-ENOMEM);
++		goto err_p1;
++	}
++
++	p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
++	if (!p_names[2]) {
++		clk = ERR_PTR(-ENOMEM);
++		goto err_p2;
++	}
++
++	clk = devm_clk_register(dev, &mux->hw);
++
++	kfree(p_names[2]);
++err_p2:
++	kfree(p_names[1]);
++err_p1:
++	kfree(p_names[0]);
++err_p0:
++	kfree(init.name);
++	return clk;
++}
++
++/* id < 0 for L2, otherwise id == physical CPU number */
++static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
++{
++	int ret;
++	unsigned offset;
++	void *p = NULL;
++	const char *s;
++	struct clk *clk;
++
++	if (id >= 0) {
++		offset = 0x4501 + (0x1000 * id);
++		s = p = kasprintf(GFP_KERNEL, "%d", id);
++		if (!s)
++			return ERR_PTR(-ENOMEM);
++	} else {
++		offset = 0x500;
++		s = "_l2";
++	}
++
++	ret = krait_add_div(dev, id, s, offset);
++	if (ret) {
++		clk = ERR_PTR(ret);
++		goto err;
++	}
++
++	ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
++	if (ret) {
++		clk = ERR_PTR(ret);
++		goto err;
++	}
++
++	clk = krait_add_pri_mux(dev, id, s, offset);
++err:
++	kfree(p);
++	return clk;
++}
++
++static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
++{
++	unsigned int idx = clkspec->args[0];
++	struct clk **clks = data;
++
++	if (idx >= 5) {
++		pr_err("%s: invalid clock index %d\n", __func__, idx);
++		return ERR_PTR(-EINVAL);
++	}
++
++	return clks[idx] ? : ERR_PTR(-ENODEV);
++}
++
++static const struct of_device_id krait_cc_match_table[] = {
++	{ .compatible = "qcom,krait-cc-v1", (void *)1UL },
++	{ .compatible = "qcom,krait-cc-v2" },
++	{}
++};
++MODULE_DEVICE_TABLE(of, krait_cc_match_table);
++
++static int krait_cc_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct of_device_id *id;
++	unsigned long cur_rate, aux_rate;
++	int cpu;
++	struct clk *clk;
++	struct clk **clks;
++	struct clk *l2_pri_mux_clk;
++
++	id = of_match_device(krait_cc_match_table, dev);
++	if (!id)
++		return -ENODEV;
++
++	/* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
++	clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1);
++	if (IS_ERR(clk))
++		return PTR_ERR(clk);
++
++	if (!id->data) {
++		clk = clk_register_fixed_factor(dev, "acpu_aux",
++						"gpll0_vote", 0, 1, 2);
++		if (IS_ERR(clk))
++			return PTR_ERR(clk);
++	}
++
++	/* Krait configurations have at most 4 CPUs and one L2 */
++	clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
++	if (!clks)
++		return -ENOMEM;
++
++	for_each_possible_cpu(cpu) {
++		clk = krait_add_clks(dev, cpu, id->data);
++		if (IS_ERR(clk))
++			return PTR_ERR(clk);
++		clks[cpu] = clk;
++	}
++
++	l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
++	if (IS_ERR(l2_pri_mux_clk))
++		return PTR_ERR(l2_pri_mux_clk);
++	clks[4] = l2_pri_mux_clk;
++
++	/*
++	 * We don't want the CPU or L2 clocks to be turned off at late init
++	 * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
++	 * refcount of these clocks. Any cpufreq/hotplug manager can assume
++	 * that the clocks have already been prepared and enabled by the time
++	 * they take over.
++	 */
++	for_each_online_cpu(cpu) {
++		clk_prepare_enable(l2_pri_mux_clk);
++		WARN(clk_prepare_enable(clks[cpu]),
++			"Unable to turn on CPU%d clock", cpu);
++	}
++
++	/*
++	 * Force reinit of HFPLLs and muxes to overwrite any potential
++	 * incorrect configuration of HFPLLs and muxes by the bootloader.
++	 * While at it, also make sure the cores are running at known rates
++	 * and print the current rate.
++	 *
++	 * The clocks are set to aux clock rate first to make sure the
++	 * secondary mux is not sourcing off of QSB. The rate is then set to
++	 * two different rates to force a HFPLL reinit under all
++	 * circumstances.
++	 */
++	cur_rate = clk_get_rate(l2_pri_mux_clk);
++	aux_rate = 384000000;
++	if (cur_rate == 1) {
++		pr_info("L2 @ QSB rate. Forcing new rate.\n");
++		cur_rate = aux_rate;
++	}
++	clk_set_rate(l2_pri_mux_clk, aux_rate);
++	clk_set_rate(l2_pri_mux_clk, 2);
++	clk_set_rate(l2_pri_mux_clk, cur_rate);
++	pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
++	for_each_possible_cpu(cpu) {
++		clk = clks[cpu];
++		cur_rate = clk_get_rate(clk);
++		if (cur_rate == 1) {
++			pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
++			cur_rate = aux_rate;
++		}
++		clk_set_rate(clk, aux_rate);
++		clk_set_rate(clk, 2);
++		clk_set_rate(clk, cur_rate);
++		pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
++	}
++
++	of_clk_add_provider(dev->of_node, krait_of_get, clks);
++
++	return 0;
++}
++
++static struct platform_driver krait_cc_driver = {
++	.probe = krait_cc_probe,
++	.driver = {
++		.name = "krait-cc",
++		.of_match_table = krait_cc_match_table,
++	},
++};
++module_platform_driver(krait_cc_driver);
++
++MODULE_DESCRIPTION("Krait CPU Clock Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:krait-cc");
diff --git a/target/linux/ipq806x/patches-4.1/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch b/target/linux/ipq806x/patches-4.1/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch
new file mode 100644
index 0000000..fd37c05
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/143-cpufreq-Add-module-to-register-cpufreq-on-Krait-CPUs.patch
@@ -0,0 +1,304 @@
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [v3,12/13] cpufreq: Add module to register cpufreq on Krait CPUs
+From: Stephen Boyd <sboyd@codeaurora.org>
+X-Patchwork-Id: 6063191
+Message-Id: <1426920332-9340-13-git-send-email-sboyd@codeaurora.org>
+To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
+Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
+	linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
+	Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
+Date: Fri, 20 Mar 2015 23:45:31 -0700
+
+Register a cpufreq-generic device whenever we detect that a
+"qcom,krait" compatible CPU is present in DT.
+
+Cc: <devicetree@vger.kernel.org>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+.../devicetree/bindings/arm/msm/qcom,pvs.txt       |  38 ++++
+ drivers/cpufreq/Kconfig.arm                        |   9 +
+ drivers/cpufreq/Makefile                           |   1 +
+ drivers/cpufreq/qcom-cpufreq.c                     | 204 +++++++++++++++++++++
+ 4 files changed, 252 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt
+ create mode 100644 drivers/cpufreq/qcom-cpufreq.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/arm/msm/qcom,pvs.txt
+@@ -0,0 +1,38 @@
++Qualcomm Process Voltage Scaling Tables
++
++The node name is required to be "qcom,pvs". There shall only be one
++such node present in the root of the tree.
++
++PROPERTIES
++
++- qcom,pvs-format-a or qcom,pvs-format-b:
++	Usage: required
++	Value type: <empty>
++	Definition: Indicates the format of qcom,speedX-pvsY-bin-vZ properties.
++		    If qcom,pvs-format-a is used the table is two columns
++		    (frequency and voltage in that order). If qcom,pvs-format-b 		    is used the table is three columns (frequency, voltage,
++		    and current in that order).
++
++- qcom,speedX-pvsY-bin-vZ:
++	Usage: required
++	Value type: <prop-encoded-array>
++	Definition: The PVS table corresponding to the speed bin X, pvs bin Y,
++		    and version Z.
++Example:
++
++	qcom,pvs {
++		qcom,pvs-format-a;
++		qcom,speed0-pvs0-bin-v0 =
++			<  384000000  950000 >,
++			<  486000000  975000 >,
++			<  594000000 1000000 >,
++			<  702000000 1025000 >,
++			<  810000000 1075000 >,
++			<  918000000 1100000 >,
++			< 1026000000 1125000 >,
++			< 1134000000 1175000 >,
++			< 1242000000 1200000 >,
++			< 1350000000 1225000 >,
++			< 1458000000 1237500 >,
++			< 1512000000 1250000 >;
++	};
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -146,6 +146,15 @@ config ARM_OMAP2PLUS_CPUFREQ
+ 	depends on ARCH_OMAP2PLUS
+ 	default ARCH_OMAP2PLUS
+ 
++config ARM_QCOM_CPUFREQ
++	tristate "Qualcomm based"
++	depends on ARCH_QCOM
++	select PM_OPP
++	help
++	  This adds the CPUFreq driver for Qualcomm SoC based boards.
++
++	  If in doubt, say N.
++
+ config ARM_S3C_CPUFREQ
+ 	bool
+ 	help
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -66,6 +66,7 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= ki
+ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
+ obj-$(CONFIG_ARM_PXA2xx_CPUFREQ)	+= pxa2xx-cpufreq.o
+ obj-$(CONFIG_PXA3xx)			+= pxa3xx-cpufreq.o
++obj-$(CONFIG_ARM_QCOM_CPUFREQ)		+= qcom-cpufreq.o
+ obj-$(CONFIG_ARM_S3C24XX_CPUFREQ)	+= s3c24xx-cpufreq.o
+ obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
+ obj-$(CONFIG_ARM_S3C2410_CPUFREQ)	+= s3c2410-cpufreq.o
+--- /dev/null
++++ b/drivers/cpufreq/qcom-cpufreq.c
+@@ -0,0 +1,204 @@
++/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 and
++ * only version 2 as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/cpu.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_device.h>
++#include <linux/pm_opp.h>
++#include <linux/slab.h>
++#include <linux/cpufreq-dt.h>
++
++static void __init get_krait_bin_format_a(int *speed, int *pvs, int *pvs_ver)
++{
++	void __iomem *base;
++	u32 pte_efuse;
++
++	*speed = *pvs = *pvs_ver = 0;
++
++	base = ioremap(0x007000c0, 4);
++	if (!base) {
++		pr_warn("Unable to read efuse data. Defaulting to 0!\n");
++		return;
++	}
++
++	pte_efuse = readl_relaxed(base);
++	iounmap(base);
++
++	*speed = pte_efuse & 0xf;
++	if (*speed == 0xf)
++		*speed = (pte_efuse >> 4) & 0xf;
++
++	if (*speed == 0xf) {
++		*speed = 0;
++		pr_warn("Speed bin: Defaulting to %d\n", *speed);
++	} else {
++		pr_info("Speed bin: %d\n", *speed);
++	}
++
++	*pvs = (pte_efuse >> 10) & 0x7;
++	if (*pvs == 0x7)
++		*pvs = (pte_efuse >> 13) & 0x7;
++
++	if (*pvs == 0x7) {
++		*pvs = 0;
++		pr_warn("PVS bin: Defaulting to %d\n", *pvs);
++	} else {
++		pr_info("PVS bin: %d\n", *pvs);
++	}
++}
++
++static void __init get_krait_bin_format_b(int *speed, int *pvs, int *pvs_ver)
++{
++	u32 pte_efuse, redundant_sel;
++	void __iomem *base;
++
++	*speed = 0;
++	*pvs = 0;
++	*pvs_ver = 0;
++
++	base = ioremap(0xfc4b80b0, 8);
++	if (!base) {
++		pr_warn("Unable to read efuse data. Defaulting to 0!\n");
++		return;
++	}
++
++	pte_efuse = readl_relaxed(base);
++	redundant_sel = (pte_efuse >> 24) & 0x7;
++	*speed = pte_efuse & 0x7;
++	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
++	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
++	*pvs_ver = (pte_efuse >> 4) & 0x3;
++
++	switch (redundant_sel) {
++	case 1:
++		*speed = (pte_efuse >> 27) & 0xf;
++		break;
++	case 2:
++		*pvs = (pte_efuse >> 27) & 0xf;
++		break;
++	}
++
++	/* Check SPEED_BIN_BLOW_STATUS */
++	if (pte_efuse & BIT(3)) {
++		pr_info("Speed bin: %d\n", *speed);
++	} else {
++		pr_warn("Speed bin not set. Defaulting to 0!\n");
++		*speed = 0;
++	}
++
++	/* Check PVS_BLOW_STATUS */
++	pte_efuse = readl_relaxed(base + 0x4) & BIT(21);
++	if (pte_efuse) {
++		pr_info("PVS bin: %d\n", *pvs);
++	} else {
++		pr_warn("PVS bin not set. Defaulting to 0!\n");
++		*pvs = 0;
++	}
++
++	pr_info("PVS version: %d\n", *pvs_ver);
++	iounmap(base);
++}
++
++static int __init qcom_cpufreq_populate_opps(void)
++{
++	int len, rows, cols, i, k, speed, pvs, pvs_ver;
++	char table_name[] = "qcom,speedXX-pvsXX-bin-vXX";
++	struct device_node *np;
++	struct device *dev;
++	int cpu = 0;
++
++	np = of_find_node_by_name(NULL, "qcom,pvs");
++	if (!np)
++		return -ENODEV;
++
++	if (of_property_read_bool(np, "qcom,pvs-format-a")) {
++		get_krait_bin_format_a(&speed, &pvs, &pvs_ver);
++		cols = 2;
++	} else if (of_property_read_bool(np, "qcom,pvs-format-b")) {
++		get_krait_bin_format_b(&speed, &pvs, &pvs_ver);
++		cols = 3;
++	} else {
++		return -ENODEV;
++	}
++
++	snprintf(table_name, sizeof(table_name),
++			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver);
++
++	if (!of_find_property(np, table_name, &len))
++		return -EINVAL;
++
++	len /= sizeof(u32);
++	if (len % cols || len == 0)
++		return -EINVAL;
++
++	rows = len / cols;
++
++	for (i = 0, k = 0; i < rows; i++) {
++		u32 freq, volt;
++
++		of_property_read_u32_index(np, table_name, k++, &freq);
++		of_property_read_u32_index(np, table_name, k++, &volt);
++		while (k % cols)
++			k++; /* Skip uA entries if present */
++		for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
++			dev = get_cpu_device(cpu);
++			if (!dev)
++				return -ENODEV;
++			if (dev_pm_opp_add(dev, freq, volt))
++				pr_warn("failed to add OPP %u\n", freq);
++		}
++	}
++
++	return 0;
++}
++
++static int __init qcom_cpufreq_driver_init(void)
++{
++	struct cpufreq_dt_platform_data pdata = { .independent_clocks = true };
++	struct platform_device_info devinfo = {
++		.name = "cpufreq-dt",
++		.data = &pdata,
++		.size_data = sizeof(pdata),
++	};
++	struct device *cpu_dev;
++	struct device_node *np;
++	int ret;
++
++	cpu_dev = get_cpu_device(0);
++	if (!cpu_dev)
++		return -ENODEV;
++
++	np = of_node_get(cpu_dev->of_node);
++	if (!np)
++		return -ENOENT;
++
++	if (!of_device_is_compatible(np, "qcom,krait")) {
++		of_node_put(np);
++		return -ENODEV;
++	}
++	of_node_put(np);
++
++	ret = qcom_cpufreq_populate_opps();
++	if (ret)
++		return ret;
++
++	return PTR_ERR_OR_ZERO(platform_device_register_full(&devinfo));
++}
++module_init(qcom_cpufreq_driver_init);
++
++MODULE_DESCRIPTION("Qualcomm CPUfreq driver");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/ipq806x/patches-4.1/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch b/target/linux/ipq806x/patches-4.1/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
new file mode 100644
index 0000000..46feec3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/144-ARM-dts-qcom-Add-necessary-DT-data-for-Krait-cpufreq.patch
@@ -0,0 +1,100 @@
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -25,6 +25,11 @@
+ 			next-level-cache = <&L2>;
+ 			qcom,acc = <&acc0>;
+ 			qcom,saw = <&saw0>;
++			clocks = <&kraitcc 0>;
++			clock-names = "cpu";
++			clock-latency = <100000>;
++			core-supply = <&smb208_s2a>;
++			voltage-tolerance = <5>;
+ 		};
+ 
+ 		cpu@1 {
+@@ -35,11 +40,24 @@
+ 			next-level-cache = <&L2>;
+ 			qcom,acc = <&acc1>;
+ 			qcom,saw = <&saw1>;
++			clocks = <&kraitcc 1>;
++			clock-names = "cpu";
++			clock-latency = <100000>;
++			core-supply = <&smb208_s2b>;
+ 		};
+ 
+ 		L2: l2-cache {
+ 			compatible = "cache";
+ 			cache-level = <2>;
++			clocks = <&kraitcc 4>;
++			clock-names = "cache";
++			cache-points-kHz = <
++				/* kHz    uV    CPU kHz */
++				1200000 1150000 1200000
++				1000000 1100000  600000
++				 384000 1100000  384000
++			>;
++			vdd_dig-supply = <&smb208_s1a>;
+ 		};
+ 	};
+ 
+@@ -195,6 +213,46 @@
+ 		};
+ 	};
+ 
++	kraitcc: clock-controller {
++		compatible = "qcom,krait-cc-v1";
++		#clock-cells = <1>;
++	};
++
++	qcom,pvs {
++		qcom,pvs-format-a;
++		qcom,speed0-pvs0-bin-v0 =
++			< 1400000000 1250000 >,
++			< 1200000000 1200000 >,
++			< 1000000000 1150000 >,
++			 < 800000000 1100000 >,
++			 < 600000000 1050000 >,
++			 < 384000000 1000000 >;
++
++		qcom,speed0-pvs1-bin-v0 =
++			< 1400000000 1175000 >,
++			< 1200000000 1125000 >,
++			< 1000000000 1075000 >,
++			 < 800000000 1025000 >,
++			 < 600000000  975000 >,
++			 < 384000000  925000 >;
++
++		qcom,speed0-pvs2-bin-v0 =
++			< 1400000000 1125000 >,
++			< 1200000000 1075000 >,
++			< 1000000000 1025000 >,
++			 < 800000000  995000 >,
++			 < 600000000  925000 >,
++			 < 384000000  875000 >;
++
++		qcom,speed0-pvs3-bin-v0 =
++			< 1400000000 1050000 >,
++			< 1200000000 1000000 >,
++			< 1000000000  950000 >,
++			 < 800000000  900000 >,
++			 < 600000000  850000 >,
++			 < 384000000  800000 >;
++	};
++
+ 	soc: soc {
+ 		#address-cells = <1>;
+ 		#size-cells = <1>;
+@@ -310,11 +368,13 @@
+ 		acc0: clock-controller@2088000 {
+ 			compatible = "qcom,kpss-acc-v1";
+ 			reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
++			clock-output-names = "acpu0_aux";
+ 		};
+ 
+ 		acc1: clock-controller@2098000 {
+ 			compatible = "qcom,kpss-acc-v1";
+ 			reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
++			clock-output-names = "acpu1_aux";
+ 		};
+ 
+ 		l2cc: clock-controller@2011000 {
diff --git a/target/linux/ipq806x/patches-4.1/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch b/target/linux/ipq806x/patches-4.1/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch
new file mode 100644
index 0000000..521adc5
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/145-cpufreq-Add-a-cpufreq-krait-based-on-cpufre.patch
@@ -0,0 +1,461 @@
+From dd77db4143290689d3a5e1ec61627233d0711b66 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd@codeaurora.org>
+Date: Fri, 30 May 2014 16:36:11 -0700
+Subject: [PATCH] FROMLIST: cpufreq: Add a cpufreq-krait based on cpufreq-cpu0
+
+Krait processors have individual clocks for each CPU that can
+scale independently from one another. cpufreq-cpu0 is fairly
+close to this, but assumes that there is only one clock for all
+CPUs. Add a driver to support the Krait configuration.
+
+TODO: Merge into cpufreq-cpu0? Or make generic?
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+
+---
+ drivers/cpufreq/Kconfig         |  13 +++
+ drivers/cpufreq/Makefile        |   1 +
+ drivers/cpufreq/cpufreq-krait.c | 190 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 204 insertions(+)
+ create mode 100644 drivers/cpufreq/cpufreq-krait.c
+
+--- a/drivers/cpufreq/Kconfig
++++ b/drivers/cpufreq/Kconfig
+@@ -198,6 +198,19 @@ config CPUFREQ_DT
+ 
+ 	  If in doubt, say N.
+ 
++config GENERIC_CPUFREQ_KRAIT
++	tristate "Krait cpufreq driver"
++	depends on HAVE_CLK && OF
++	# if CPU_THERMAL is on and THERMAL=m, CPU0 cannot be =y:
++	depends on !CPU_THERMAL || THERMAL
++	select PM_OPP
++	help
++	  This adds a generic cpufreq driver for CPU0 frequency management.
++	  It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
++	  systems which share clock and voltage across all CPUs.
++
++	  If in doubt, say N.
++
+ if X86
+ source "drivers/cpufreq/Kconfig.x86"
+ endif
+--- a/drivers/cpufreq/Makefile
++++ b/drivers/cpufreq/Makefile
+@@ -14,6 +14,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)
+ obj-$(CONFIG_CPU_FREQ_GOV_COMMON)		+= cpufreq_governor.o
+ 
+ obj-$(CONFIG_CPUFREQ_DT)		+= cpufreq-dt.o
++obj-$(CONFIG_GENERIC_CPUFREQ_KRAIT)	+= cpufreq-krait.o
+ 
+ ##################################################################################
+ # x86 drivers.
+--- /dev/null
++++ b/drivers/cpufreq/cpufreq-krait.c
+@@ -0,0 +1,390 @@
++/*
++ * Copyright (C) 2012 Freescale Semiconductor, Inc.
++ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
++ *
++ * The OPP code in function krait_set_target() is reused from
++ * drivers/cpufreq/omap-cpufreq.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/clk.h>
++#include <linux/cpu.h>
++#include <linux/cpu_cooling.h>
++#include <linux/cpufreq.h>
++#include <linux/cpumask.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/pm_opp.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++#include <linux/thermal.h>
++
++static unsigned int transition_latency;
++static unsigned int voltage_tolerance; /* in percentage */
++
++static struct device *cpu_dev;
++static DEFINE_PER_CPU(struct clk *, krait_cpu_clks);
++static DEFINE_PER_CPU(struct regulator *, krait_supply_core);
++static struct cpufreq_frequency_table *freq_table;
++static struct thermal_cooling_device *cdev;
++
++struct cache_points {
++	unsigned long cache_freq;
++	unsigned int cache_volt;
++	unsigned long cpu_freq;
++};
++
++static struct regulator *krait_l2_reg;
++static struct clk *krait_l2_clk;
++static struct cache_points *krait_l2_points;
++static int nr_krait_l2_points;
++
++static int krait_parse_cache_points(struct device *dev,
++		struct device_node *of_node)
++{
++	const struct property *prop;
++	const __be32 *val;
++	int nr, i;
++
++	prop = of_find_property(of_node, "cache-points-kHz", NULL);
++	if (!prop)
++		return -ENODEV;
++	if (!prop->value)
++		return -ENODATA;
++
++	/*
++	 * Each OPP is a set of tuples consisting of frequency and
++	 * cpu-frequency like <freq-kHz volt-uV freq-kHz>.
++	 */
++	nr = prop->length / sizeof(u32);
++	if (nr % 3) {
++		dev_err(dev, "%s: Invalid cache points\n", __func__);
++		return -EINVAL;
++	}
++	nr /= 3;
++
++	krait_l2_points = devm_kcalloc(dev, nr, sizeof(*krait_l2_points),
++				       GFP_KERNEL);
++	if (!krait_l2_points)
++		return -ENOMEM;
++	nr_krait_l2_points = nr;
++
++	for (i = 0, val = prop->value; i < nr; i++) {
++		unsigned long cache_freq = be32_to_cpup(val++) * 1000;
++		unsigned int cache_volt = be32_to_cpup(val++);
++		unsigned long cpu_freq = be32_to_cpup(val++) * 1000;
++
++		krait_l2_points[i].cache_freq = cache_freq;
++		krait_l2_points[i].cache_volt = cache_volt;
++		krait_l2_points[i].cpu_freq = cpu_freq;
++	}
++
++	return 0;
++}
++
++static int krait_set_target(struct cpufreq_policy *policy, unsigned int index)
++{
++	struct dev_pm_opp *opp;
++	unsigned long volt = 0, volt_old = 0, tol = 0;
++	unsigned long freq, max_cpu_freq = 0;
++	unsigned int old_freq, new_freq;
++	long freq_Hz, freq_exact;
++	int ret, i;
++	struct clk *cpu_clk;
++	struct regulator *core;
++	unsigned int cpu;
++
++	cpu_clk = per_cpu(krait_cpu_clks, policy->cpu);
++
++	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
++	if (freq_Hz <= 0)
++		freq_Hz = freq_table[index].frequency * 1000;
++
++	freq_exact = freq_Hz;
++	new_freq = freq_Hz / 1000;
++	old_freq = clk_get_rate(cpu_clk) / 1000;
++
++	core = per_cpu(krait_supply_core, policy->cpu);
++
++	rcu_read_lock();
++	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
++	if (IS_ERR(opp)) {
++		rcu_read_unlock();
++		pr_err("failed to find OPP for %ld\n", freq_Hz);
++		return PTR_ERR(opp);
++	}
++	volt = dev_pm_opp_get_voltage(opp);
++	rcu_read_unlock();
++	tol = volt * voltage_tolerance / 100;
++	volt_old = regulator_get_voltage(core);
++
++	pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
++		 old_freq / 1000, volt_old ? volt_old / 1000 : -1,
++		 new_freq / 1000, volt ? volt / 1000 : -1);
++
++	/* scaling up?  scale voltage before frequency */
++	if (new_freq > old_freq) {
++		ret = regulator_set_voltage_tol(core, volt, tol);
++		if (ret) {
++			pr_err("failed to scale voltage up: %d\n", ret);
++			return ret;
++		}
++	}
++
++	ret = clk_set_rate(cpu_clk, freq_exact);
++	if (ret) {
++		pr_err("failed to set clock rate: %d\n", ret);
++		return ret;
++	}
++
++	/* scaling down?  scale voltage after frequency */
++	if (new_freq < old_freq) {
++		ret = regulator_set_voltage_tol(core, volt, tol);
++		if (ret) {
++			pr_err("failed to scale voltage down: %d\n", ret);
++			clk_set_rate(cpu_clk, old_freq * 1000);
++		}
++	}
++
++	for_each_possible_cpu(cpu) {
++		freq = clk_get_rate(per_cpu(krait_cpu_clks, cpu));
++		max_cpu_freq = max(max_cpu_freq, freq);
++	}
++
++	for (i = 0; i < nr_krait_l2_points; i++) {
++		if (max_cpu_freq >= krait_l2_points[i].cpu_freq) {
++			if (krait_l2_reg) {
++				ret = regulator_set_voltage_tol(krait_l2_reg,
++						krait_l2_points[i].cache_volt,
++						tol);
++				if (ret) {
++					pr_err("failed to scale l2 voltage: %d\n",
++						ret);
++				}
++			}
++			ret = clk_set_rate(krait_l2_clk,
++					krait_l2_points[i].cache_freq);
++			if (ret)
++				pr_err("failed to scale l2 clk: %d\n", ret);
++			break;
++		}
++
++	}
++
++	return ret;
++}
++
++static int krait_cpufreq_init(struct cpufreq_policy *policy)
++{
++	int ret;
++
++	policy->clk = per_cpu(krait_cpu_clks, policy->cpu);
++
++	ret = cpufreq_table_validate_and_show(policy, freq_table);
++	if (ret) {
++		pr_err("%s: invalid frequency table: %d\n", __func__, ret);
++		return ret;
++	}
++
++	policy->cpuinfo.transition_latency = transition_latency;
++
++	return 0;
++}
++
++static struct cpufreq_driver krait_cpufreq_driver = {
++	.flags = CPUFREQ_STICKY,
++	.verify = cpufreq_generic_frequency_table_verify,
++	.target_index = krait_set_target,
++	.get = cpufreq_generic_get,
++	.init = krait_cpufreq_init,
++	.name = "generic_krait",
++	.attr = cpufreq_generic_attr,
++};
++
++static int krait_cpufreq_probe(struct platform_device *pdev)
++{
++	struct device_node *np, *cache;
++	int ret, i;
++	unsigned int cpu;
++	struct device *dev;
++	struct clk *clk;
++	struct regulator *core;
++	unsigned long freq_Hz, freq, max_cpu_freq;
++	struct dev_pm_opp *opp;
++	unsigned long volt, tol;
++
++	cpu_dev = get_cpu_device(0);
++	if (!cpu_dev) {
++		pr_err("failed to get krait device\n");
++		return -ENODEV;
++	}
++
++	np = of_node_get(cpu_dev->of_node);
++	if (!np) {
++		pr_err("failed to find krait node\n");
++		return -ENOENT;
++	}
++
++	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
++	if (ret) {
++		pr_err("failed to init cpufreq table: %d\n", ret);
++		goto out_put_node;
++	}
++
++	of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
++
++	if (of_property_read_u32(np, "clock-latency", &transition_latency))
++		transition_latency = CPUFREQ_ETERNAL;
++
++	cache = of_find_next_cache_node(np);
++	if (cache) {
++		struct device_node *vdd;
++
++		vdd = of_parse_phandle(cache, "vdd_dig-supply", 0);
++		if (vdd) {
++			krait_l2_reg = regulator_get(NULL, vdd->name);
++			if (IS_ERR(krait_l2_reg)) {
++				pr_warn("failed to get l2 vdd_dig supply\n");
++				krait_l2_reg = NULL;
++			}
++			of_node_put(vdd);
++		}
++
++		krait_l2_clk = of_clk_get(cache, 0);
++		if (!IS_ERR(krait_l2_clk)) {
++			ret = krait_parse_cache_points(&pdev->dev, cache);
++			if (ret)
++				clk_put(krait_l2_clk);
++		}
++		if (IS_ERR(krait_l2_clk) || ret)
++			krait_l2_clk = NULL;
++	}
++
++	for_each_possible_cpu(cpu) {
++		dev = get_cpu_device(cpu);
++		if (!dev) {
++			pr_err("failed to get krait device\n");
++			ret = -ENOENT;
++			goto out_free_table;
++		}
++		per_cpu(krait_cpu_clks, cpu) = clk = devm_clk_get(dev, NULL);
++		if (IS_ERR(clk)) {
++			ret = PTR_ERR(clk);
++			goto out_free_table;
++		}
++		core = devm_regulator_get(dev, "core");
++		if (IS_ERR(core)) {
++			pr_debug("failed to get core regulator\n");
++			ret = PTR_ERR(core);
++			goto out_free_table;
++		}
++		per_cpu(krait_supply_core, cpu) = core;
++
++		freq_Hz = clk_get_rate(clk);
++
++		rcu_read_lock();
++		opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
++		if (IS_ERR(opp)) {
++			rcu_read_unlock();
++			pr_err("failed to find OPP for %ld\n", freq_Hz);
++			ret = PTR_ERR(opp);
++			goto out_free_table;
++		}
++		volt = dev_pm_opp_get_voltage(opp);
++		rcu_read_unlock();
++
++		tol = volt * voltage_tolerance / 100;
++		ret = regulator_set_voltage_tol(core, volt, tol);
++		if (ret) {
++			pr_err("failed to scale voltage up: %d\n", ret);
++			goto out_free_table;
++		}
++		ret = regulator_enable(core);
++		if (ret) {
++			pr_err("failed to enable regulator: %d\n", ret);
++			goto out_free_table;
++		}
++		max_cpu_freq = max(max_cpu_freq, freq);
++	}
++
++	for (i = 0; i < nr_krait_l2_points; i++) {
++		if (max_cpu_freq >= krait_l2_points[i].cpu_freq) {
++			if (krait_l2_reg) {
++				ret = regulator_set_voltage_tol(krait_l2_reg,
++						krait_l2_points[i].cache_volt,
++						tol);
++				if (ret)
++					pr_err("failed to scale l2 voltage: %d\n",
++							ret);
++				ret = regulator_enable(krait_l2_reg);
++				if (ret)
++					pr_err("failed to enable l2 voltage: %d\n",
++							ret);
++			}
++			break;
++		}
++
++	}
++
++	ret = cpufreq_register_driver(&krait_cpufreq_driver);
++	if (ret) {
++		pr_err("failed register driver: %d\n", ret);
++		goto out_free_table;
++	}
++	of_node_put(np);
++
++	/*
++	 * For now, just loading the cooling device;
++	 * thermal DT code takes care of matching them.
++	 */
++	for_each_possible_cpu(cpu) {
++		dev = get_cpu_device(cpu);
++		np = of_node_get(dev->of_node);
++		if (of_find_property(np, "#cooling-cells", NULL)) {
++			cdev = of_cpufreq_cooling_register(np, cpumask_of(cpu));
++			if (IS_ERR(cdev))
++				pr_err("running cpufreq without cooling device: %ld\n",
++				       PTR_ERR(cdev));
++		}
++		of_node_put(np);
++	}
++
++	return 0;
++
++out_free_table:
++	regulator_put(krait_l2_reg);
++	clk_put(krait_l2_clk);
++	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
++out_put_node:
++	of_node_put(np);
++	return ret;
++}
++
++static int krait_cpufreq_remove(struct platform_device *pdev)
++{
++	cpufreq_cooling_unregister(cdev);
++	cpufreq_unregister_driver(&krait_cpufreq_driver);
++	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
++	clk_put(krait_l2_clk);
++	regulator_put(krait_l2_reg);
++
++	return 0;
++}
++
++static struct platform_driver krait_cpufreq_platdrv = {
++	.driver = {
++		.name	= "cpufreq-krait",
++		.owner	= THIS_MODULE,
++	},
++	.probe		= krait_cpufreq_probe,
++	.remove		= krait_cpufreq_remove,
++};
++module_platform_driver(krait_cpufreq_platdrv);
++
++MODULE_DESCRIPTION("Krait CPUfreq driver");
++MODULE_LICENSE("GPL v2");
+--- a/drivers/cpufreq/qcom-cpufreq.c
++++ b/drivers/cpufreq/qcom-cpufreq.c
+@@ -168,11 +168,8 @@ static int __init qcom_cpufreq_populate_
+ 
+ static int __init qcom_cpufreq_driver_init(void)
+ {
+-	struct cpufreq_dt_platform_data pdata = { .independent_clocks = true };
+ 	struct platform_device_info devinfo = {
+-		.name = "cpufreq-dt",
+-		.data = &pdata,
+-		.size_data = sizeof(pdata),
++		.name = "cpufreq-krait",
+ 	};
+ 	struct device *cpu_dev;
+ 	struct device_node *np;
diff --git a/target/linux/ipq806x/patches-4.1/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch b/target/linux/ipq806x/patches-4.1/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch
new file mode 100644
index 0000000..51ebc19
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/300-arch-arm-force-ZRELADDR-on-arch-qcom.patch
@@ -0,0 +1,62 @@
+From b12e230f09d4481424e6a5d7e2ae566b6954e83f Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Wed, 29 Apr 2015 15:21:46 -0700
+Subject: [PATCH] HACK: arch: arm: force ZRELADDR on arch-qcom
+
+ARCH_QCOM is using the ARCH_MULTIPLATFORM option, as now recommended
+on most ARM architectures. This automatically calculate ZRELADDR by
+masking PHYS_OFFSET with 0xf8000000.
+
+However, on IPQ806x, the first ~20MB of RAM is reserved for the hardware
+network accelerators, and the bootloader removes this section from the
+layout passed from the ATAGS (when used).
+
+For newer bootloader, when DT is used, this is not a problem, we just
+reserve this memory in the device tree. But if the bootloader doesn't
+have DT support, then ATAGS have to be used. In this case, the ARM
+decompressor will position the kernel in this low mem, which will not be
+in the RAM section mapped by the bootloader, which means the kernel will
+freeze in the middle of the boot process trying to map the memory.
+
+As a work around, this patch allows disabling AUTO_ZRELADDR when
+ARCH_QCOM is selected. It makes the zImage usage possible on bootloaders
+which don't support device-tree, which is the case on certain early
+IPQ806x based designs.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/Kconfig                 | 2 +-
+ arch/arm/Makefile                | 2 ++
+ arch/arm/mach-qcom/Makefile.boot | 1 +
+ 3 files changed, 4 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/mach-qcom/Makefile.boot
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -320,7 +320,7 @@ config ARCH_MULTIPLATFORM
+ 	select ARCH_WANT_OPTIONAL_GPIOLIB
+ 	select ARM_HAS_SG_CHAIN
+ 	select ARM_PATCH_PHYS_VIRT
+-	select AUTO_ZRELADDR
++	select AUTO_ZRELADDR if !ARCH_QCOM
+ 	select CLKSRC_OF
+ 	select COMMON_CLK
+ 	select GENERIC_CLOCKEVENTS
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -240,9 +240,11 @@ MACHINE  := arch/arm/mach-$(word 1,$(mac
+ else
+ MACHINE  :=
+ endif
++ifeq ($(CONFIG_ARCH_QCOM),)
+ ifeq ($(CONFIG_ARCH_MULTIPLATFORM),y)
+ MACHINE  :=
+ endif
++endif
+ 
+ machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
+ platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
+--- /dev/null
++++ b/arch/arm/mach-qcom/Makefile.boot
+@@ -0,0 +1 @@
++zreladdr-y+= 0x42208000
diff --git a/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch b/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
new file mode 100644
index 0000000..dfe7169
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/700-clk-qcom-Add-support-for-NSS-GMAC-clocks-and-resets.patch
@@ -0,0 +1,734 @@
+From 2fbb18f85826a9ba308fedb2cf90d3a661a39fd7 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <sboyd@codeaurora.org>
+Date: Fri, 27 Mar 2015 00:16:14 -0700
+Subject: [PATCH] clk: qcom: Add support for NSS/GMAC clocks and resets
+
+Add the NSS/GMAC clocks and the TCM clock and NSS resets.
+
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/qcom/gcc-ipq806x.c               | 594 ++++++++++++++++++++++++++-
+ drivers/clk/qcom/gcc-ipq806x.c.rej           |  50 +++
+ include/dt-bindings/clock/qcom,gcc-ipq806x.h |   2 +
+ include/dt-bindings/reset/qcom,gcc-ipq806x.h |  43 ++
+ 4 files changed, 688 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/qcom/gcc-ipq806x.c.rej
+
+--- a/drivers/clk/qcom/gcc-ipq806x.c
++++ b/drivers/clk/qcom/gcc-ipq806x.c
+@@ -220,12 +220,47 @@ static struct clk_regmap pll14_vote = {
+ 	},
+ };
+ 
++#define NSS_PLL_RATE(f, _l, _m, _n, i) \
++	{  \
++		.freq = f,  \
++		.l = _l, \
++		.m = _m, \
++		.n = _n, \
++		.ibits = i, \
++	}
++
++static struct pll_freq_tbl pll18_freq_tbl[] = {
++	NSS_PLL_RATE(550000000, 44, 0, 1, 0x01495625),
++	NSS_PLL_RATE(733000000, 58, 16, 25, 0x014b5625),
++};
++
++static struct clk_pll pll18 = {
++	.l_reg = 0x31a4,
++	.m_reg = 0x31a8,
++	.n_reg = 0x31ac,
++	.config_reg = 0x31b4,
++	.mode_reg = 0x31a0,
++	.status_reg = 0x31b8,
++	.status_bit = 16,
++	.post_div_shift = 16,
++	.post_div_width = 1,
++	.freq_tbl = pll18_freq_tbl,
++	.clkr.hw.init = &(struct clk_init_data){
++		.name = "pll18",
++		.parent_names = (const char *[]){ "pxo" },
++		.num_parents = 1,
++		.ops = &clk_pll_ops,
++	},
++};
++
+ enum {
+ 	P_PXO,
+ 	P_PLL8,
+ 	P_PLL3,
+ 	P_PLL0,
+ 	P_CXO,
++	P_PLL14,
++	P_PLL18,
+ };
+ 
+ static const struct parent_map gcc_pxo_pll8_map[] = {
+@@ -277,6 +312,22 @@ static const char *gcc_pxo_pll8_pll0_map
+ 	"pll0_vote",
+ };
+ 
++static const struct parent_map gcc_pxo_pll8_pll14_pll18_pll0_map[] = {
++	{ P_PXO, 0 },
++	{ P_PLL8, 4 },
++	{ P_PLL0, 2 },
++	{ P_PLL14, 5 },
++	{ P_PLL18, 1 },
++};
++
++static const char *gcc_pxo_pll8_pll14_pll18_pll0[] = {
++	"pxo",
++	"pll8_vote",
++	"pll0_vote",
++	"pll14",
++	"pll18",
++};
++
+ static struct freq_tbl clk_tbl_gsbi_uart[] = {
+ 	{  1843200, P_PLL8, 2,  6, 625 },
+ 	{  3686400, P_PLL8, 2, 12, 625 },
+@@ -2282,6 +2333,472 @@ static struct clk_branch ebi2_aon_clk =
+ 	},
+ };
+ 
++static const struct freq_tbl clk_tbl_gmac[] = {
++	{ 133000000, P_PLL0, 1,  50, 301 },
++	{ 266000000, P_PLL0, 1, 127, 382 },
++	{ }
++};
++
++static struct clk_dyn_rcg gmac_core1_src = {
++	.ns_reg[0] = 0x3cac,
++	.ns_reg[1] = 0x3cb0,
++	.md_reg[0] = 0x3ca4,
++	.md_reg[1] = 0x3ca8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ca0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core1_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 4,
++	.hwcg_reg = 0x3cb4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cb4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core1_clk",
++			.parent_names = (const char *[]){
++				"gmac_core1_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core2_src = {
++	.ns_reg[0] = 0x3ccc,
++	.ns_reg[1] = 0x3cd0,
++	.md_reg[0] = 0x3cc4,
++	.md_reg[1] = 0x3cc8,
++	.bank_reg = 0x3ca0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3cc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core2_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 5,
++	.hwcg_reg = 0x3cd4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cd4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core2_clk",
++			.parent_names = (const char *[]){
++				"gmac_core2_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core3_src = {
++	.ns_reg[0] = 0x3cec,
++	.ns_reg[1] = 0x3cf0,
++	.md_reg[0] = 0x3ce4,
++	.md_reg[1] = 0x3ce8,
++	.bank_reg = 0x3ce0,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3ce0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core3_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 6,
++	.hwcg_reg = 0x3cf4,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3cf4,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core3_clk",
++			.parent_names = (const char *[]){
++				"gmac_core3_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static struct clk_dyn_rcg gmac_core4_src = {
++	.ns_reg[0] = 0x3d0c,
++	.ns_reg[1] = 0x3d10,
++	.md_reg[0] = 0x3d04,
++	.md_reg[1] = 0x3d08,
++	.bank_reg = 0x3d00,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_gmac,
++	.clkr = {
++		.enable_reg = 0x3d00,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch gmac_core4_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 7,
++	.hwcg_reg = 0x3d14,
++	.hwcg_bit = 6,
++	.clkr = {
++		.enable_reg = 0x3d14,
++		.enable_mask = BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "gmac_core4_clk",
++			.parent_names = (const char *[]){
++				"gmac_core4_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss_tcm[] = {
++	{ 266000000, P_PLL0, 3, 0, 0 },
++	{ 400000000, P_PLL0, 2, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg nss_tcm_src = {
++	.ns_reg[0] = 0x3dc4,
++	.ns_reg[1] = 0x3dc8,
++	.bank_reg = 0x3dc0,
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 4,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss_tcm,
++	.clkr = {
++		.enable_reg = 0x3dc0,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_src",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++		},
++	},
++};
++
++static struct clk_branch nss_tcm_clk = {
++	.halt_reg = 0x3c20,
++	.halt_bit = 14,
++	.clkr = {
++		.enable_reg = 0x3dd0,
++		.enable_mask = BIT(6) | BIT(4),
++		.hw.init = &(struct clk_init_data){
++			.name = "nss_tcm_clk",
++			.parent_names = (const char *[]){
++				"nss_tcm_src",
++			},
++			.num_parents = 1,
++			.ops = &clk_branch_ops,
++			.flags = CLK_SET_RATE_PARENT,
++		},
++	},
++};
++
++static const struct freq_tbl clk_tbl_nss[] = {
++	{ 110000000, P_PLL18, 1, 1, 5 },
++	{ 275000000, P_PLL18, 2, 0, 0 },
++	{ 550000000, P_PLL18, 1, 0, 0 },
++	{ 733000000, P_PLL18, 1, 0, 0 },
++	{ }
++};
++
++static struct clk_dyn_rcg ubi32_core1_src_clk = {
++	.ns_reg[0] = 0x3d2c,
++	.ns_reg[1] = 0x3d30,
++	.md_reg[0] = 0x3d24,
++	.md_reg[1] = 0x3d28,
++	.bank_reg = 0x3d20,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d20,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core1_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
++static struct clk_dyn_rcg ubi32_core2_src_clk = {
++	.ns_reg[0] = 0x3d4c,
++	.ns_reg[1] = 0x3d50,
++	.md_reg[0] = 0x3d44,
++	.md_reg[1] = 0x3d48,
++	.bank_reg = 0x3d40,
++	.mn[0] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.mn[1] = {
++		.mnctr_en_bit = 8,
++		.mnctr_reset_bit = 7,
++		.mnctr_mode_shift = 5,
++		.n_val_shift = 16,
++		.m_val_shift = 16,
++		.width = 8,
++	},
++	.s[0] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.s[1] = {
++		.src_sel_shift = 0,
++		.parent_map = gcc_pxo_pll8_pll14_pll18_pll0_map,
++	},
++	.p[0] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.p[1] = {
++		.pre_div_shift = 3,
++		.pre_div_width = 2,
++	},
++	.mux_sel_bit = 0,
++	.freq_tbl = clk_tbl_nss,
++	.clkr = {
++		.enable_reg = 0x3d40,
++		.enable_mask = BIT(1),
++		.hw.init = &(struct clk_init_data){
++			.name = "ubi32_core2_src_clk",
++			.parent_names = gcc_pxo_pll8_pll14_pll18_pll0,
++			.num_parents = 5,
++			.ops = &clk_dyn_rcg_ops,
++			.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
++		},
++	},
++};
++
+ static struct clk_regmap *gcc_ipq806x_clks[] = {
+ 	[PLL0] = &pll0.clkr,
+ 	[PLL0_VOTE] = &pll0_vote,
+@@ -2291,6 +2808,7 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL8_VOTE] = &pll8_vote,
+ 	[PLL14] = &pll14.clkr,
+ 	[PLL14_VOTE] = &pll14_vote,
++	[PLL18] = &pll18.clkr,
+ 	[GSBI1_UART_SRC] = &gsbi1_uart_src.clkr,
+ 	[GSBI1_UART_CLK] = &gsbi1_uart_clk.clkr,
+ 	[GSBI2_UART_SRC] = &gsbi2_uart_src.clkr,
+@@ -2390,6 +2908,18 @@ static struct clk_regmap *gcc_ipq806x_cl
+ 	[PLL9] = &hfpll0.clkr,
+ 	[PLL10] = &hfpll1.clkr,
+ 	[PLL12] = &hfpll_l2.clkr,
++	[GMAC_CORE1_CLK_SRC] = &gmac_core1_src.clkr,
++	[GMAC_CORE1_CLK] = &gmac_core1_clk.clkr,
++	[GMAC_CORE2_CLK_SRC] = &gmac_core2_src.clkr,
++	[GMAC_CORE2_CLK] = &gmac_core2_clk.clkr,
++	[GMAC_CORE3_CLK_SRC] = &gmac_core3_src.clkr,
++	[GMAC_CORE3_CLK] = &gmac_core3_clk.clkr,
++	[GMAC_CORE4_CLK_SRC] = &gmac_core4_src.clkr,
++	[GMAC_CORE4_CLK] = &gmac_core4_clk.clkr,
++	[UBI32_CORE1_CLK_SRC] = &ubi32_core1_src_clk.clkr,
++	[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
++	[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
++	[NSSTCM_CLK] = &nss_tcm_clk.clkr,
+ };
+ 
+ static const struct qcom_reset_map gcc_ipq806x_resets[] = {
+@@ -2508,6 +3038,48 @@ static const struct qcom_reset_map gcc_i
+ 	[USB30_1_PHY_RESET] = { 0x3b58, 0 },
+ 	[NSSFB0_RESET] = { 0x3b60, 6 },
+ 	[NSSFB1_RESET] = { 0x3b60, 7 },
++	[UBI32_CORE1_CLKRST_CLAMP_RESET] = { 0x3d3c, 3},
++	[UBI32_CORE1_CLAMP_RESET] = { 0x3d3c, 2 },
++	[UBI32_CORE1_AHB_RESET] = { 0x3d3c, 1 },
++	[UBI32_CORE1_AXI_RESET] = { 0x3d3c, 0 },
++	[UBI32_CORE2_CLKRST_CLAMP_RESET] = { 0x3d5c, 3 },
++	[UBI32_CORE2_CLAMP_RESET] = { 0x3d5c, 2 },
++	[UBI32_CORE2_AHB_RESET] = { 0x3d5c, 1 },
++	[UBI32_CORE2_AXI_RESET] = { 0x3d5c, 0 },
++	[GMAC_CORE1_RESET] = { 0x3cbc, 0 },
++	[GMAC_CORE2_RESET] = { 0x3cdc, 0 },
++	[GMAC_CORE3_RESET] = { 0x3cfc, 0 },
++	[GMAC_CORE4_RESET] = { 0x3d1c, 0 },
++	[GMAC_AHB_RESET] = { 0x3e24, 0 },
++	[NSS_CH0_RST_RX_CLK_N_RESET] = { 0x3b60, 0 },
++	[NSS_CH0_RST_TX_CLK_N_RESET] = { 0x3b60, 1 },
++	[NSS_CH0_RST_RX_125M_N_RESET] = { 0x3b60, 2 },
++	[NSS_CH0_HW_RST_RX_125M_N_RESET] = { 0x3b60, 3 },
++	[NSS_CH0_RST_TX_125M_N_RESET] = { 0x3b60, 4 },
++	[NSS_CH1_RST_RX_CLK_N_RESET] = { 0x3b60, 5 },
++	[NSS_CH1_RST_TX_CLK_N_RESET] = { 0x3b60, 6 },
++	[NSS_CH1_RST_RX_125M_N_RESET] = { 0x3b60, 7 },
++	[NSS_CH1_HW_RST_RX_125M_N_RESET] = { 0x3b60, 8 },
++	[NSS_CH1_RST_TX_125M_N_RESET] = { 0x3b60, 9 },
++	[NSS_CH2_RST_RX_CLK_N_RESET] = { 0x3b60, 10 },
++	[NSS_CH2_RST_TX_CLK_N_RESET] = { 0x3b60, 11 },
++	[NSS_CH2_RST_RX_125M_N_RESET] = { 0x3b60, 12 },
++	[NSS_CH2_HW_RST_RX_125M_N_RESET] = { 0x3b60, 13 },
++	[NSS_CH2_RST_TX_125M_N_RESET] = { 0x3b60, 14 },
++	[NSS_CH3_RST_RX_CLK_N_RESET] = { 0x3b60, 15 },
++	[NSS_CH3_RST_TX_CLK_N_RESET] = { 0x3b60, 16 },
++	[NSS_CH3_RST_RX_125M_N_RESET] = { 0x3b60, 17 },
++	[NSS_CH3_HW_RST_RX_125M_N_RESET] = { 0x3b60, 18 },
++	[NSS_CH3_RST_TX_125M_N_RESET] = { 0x3b60, 19 },
++	[NSS_RST_RX_250M_125M_N_RESET] = { 0x3b60, 20 },
++	[NSS_RST_TX_250M_125M_N_RESET] = { 0x3b60, 21 },
++	[NSS_QSGMII_TXPI_RST_N_RESET] = { 0x3b60, 22 },
++	[NSS_QSGMII_CDR_RST_N_RESET] = { 0x3b60, 23 },
++	[NSS_SGMII2_CDR_RST_N_RESET] = { 0x3b60, 24 },
++	[NSS_SGMII3_CDR_RST_N_RESET] = { 0x3b60, 25 },
++	[NSS_CAL_PRBS_RST_N_RESET] = { 0x3b60, 26 },
++	[NSS_LCKDT_RST_N_RESET] = { 0x3b60, 27 },
++	[NSS_SRDS_N_RESET] = { 0x3b60, 28 },
+ };
+ 
+ static const struct regmap_config gcc_ipq806x_regmap_config = {
+@@ -2536,6 +3108,8 @@ static int gcc_ipq806x_probe(struct plat
+ {
+ 	struct clk *clk;
+ 	struct device *dev = &pdev->dev;
++	struct regmap *regmap;
++	int ret;
+ 
+ 	/* Temporary until RPM clocks supported */
+ 	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
+@@ -2546,7 +3120,25 @@ static int gcc_ipq806x_probe(struct plat
+ 	if (IS_ERR(clk))
+ 		return PTR_ERR(clk);
+ 
+-	return qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
++	if (ret)
++		return ret;
++
++	regmap = dev_get_regmap(dev, NULL);
++	if (!regmap)
++		return -ENODEV;
++
++	/* Setup PLL18 static bits */
++	regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400);
++	regmap_write(regmap, 0x31b0, 0x3080);
++
++	/* Set GMAC footswitch sleep/wakeup values */
++	regmap_write(regmap, 0x3cb8, 8);
++	regmap_write(regmap, 0x3cd8, 8);
++	regmap_write(regmap, 0x3cf8, 8);
++	regmap_write(regmap, 0x3d18, 8);
++
++	return 0;
+ }
+ 
+ static int gcc_ipq806x_remove(struct platform_device *pdev)
+--- a/include/dt-bindings/reset/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/reset/qcom,gcc-ipq806x.h
+@@ -129,4 +129,47 @@
+ #define USB30_1_PHY_RESET				112
+ #define NSSFB0_RESET					113
+ #define NSSFB1_RESET					114
++#define UBI32_CORE1_CLKRST_CLAMP_RESET			115
++#define UBI32_CORE1_CLAMP_RESET				116
++#define UBI32_CORE1_AHB_RESET				117
++#define UBI32_CORE1_AXI_RESET				118
++#define UBI32_CORE2_CLKRST_CLAMP_RESET			119
++#define UBI32_CORE2_CLAMP_RESET				120
++#define UBI32_CORE2_AHB_RESET				121
++#define UBI32_CORE2_AXI_RESET				122
++#define GMAC_CORE1_RESET				123
++#define GMAC_CORE2_RESET				124
++#define GMAC_CORE3_RESET				125
++#define GMAC_CORE4_RESET				126
++#define GMAC_AHB_RESET					127
++#define NSS_CH0_RST_RX_CLK_N_RESET			128
++#define NSS_CH0_RST_TX_CLK_N_RESET			129
++#define NSS_CH0_RST_RX_125M_N_RESET			130
++#define NSS_CH0_HW_RST_RX_125M_N_RESET			131
++#define NSS_CH0_RST_TX_125M_N_RESET			132
++#define NSS_CH1_RST_RX_CLK_N_RESET			133
++#define NSS_CH1_RST_TX_CLK_N_RESET			134
++#define NSS_CH1_RST_RX_125M_N_RESET			135
++#define NSS_CH1_HW_RST_RX_125M_N_RESET			136
++#define NSS_CH1_RST_TX_125M_N_RESET			137
++#define NSS_CH2_RST_RX_CLK_N_RESET			138
++#define NSS_CH2_RST_TX_CLK_N_RESET			139
++#define NSS_CH2_RST_RX_125M_N_RESET			140
++#define NSS_CH2_HW_RST_RX_125M_N_RESET			141
++#define NSS_CH2_RST_TX_125M_N_RESET			142
++#define NSS_CH3_RST_RX_CLK_N_RESET			143
++#define NSS_CH3_RST_TX_CLK_N_RESET			144
++#define NSS_CH3_RST_RX_125M_N_RESET			145
++#define NSS_CH3_HW_RST_RX_125M_N_RESET			146
++#define NSS_CH3_RST_TX_125M_N_RESET			147
++#define NSS_RST_RX_250M_125M_N_RESET			148
++#define NSS_RST_TX_250M_125M_N_RESET			149
++#define NSS_QSGMII_TXPI_RST_N_RESET			150
++#define NSS_QSGMII_CDR_RST_N_RESET			151
++#define NSS_SGMII2_CDR_RST_N_RESET			152
++#define NSS_SGMII3_CDR_RST_N_RESET			153
++#define NSS_CAL_PRBS_RST_N_RESET			154
++#define NSS_LCKDT_RST_N_RESET				155
++#define NSS_SRDS_N_RESET				156
++
+ #endif
+--- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h
++++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h
+@@ -289,5 +289,7 @@
+ #define UBI32_CORE1_CLK				279
+ #define UBI32_CORE2_CLK				280
+ #define EBI2_AON_CLK				281
++#define NSSTCM_CLK_SRC				282
++#define NSSTCM_CLK				283
+ 
+ #endif
diff --git a/target/linux/ipq806x/patches-4.1/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch b/target/linux/ipq806x/patches-4.1/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
new file mode 100644
index 0000000..3711e12
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/701-stmmac-add-phy-handle-support-to-the-platform-layer.patch
@@ -0,0 +1,105 @@
+From 4f09499bc1d9bb095caccbcd73ff951ee631e521 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Fri, 8 May 2015 15:42:40 -0700
+Subject: [PATCH 1/8] stmmac: add phy-handle support to the platform layer
+
+On stmmac driver, PHY specification in device-tree was done using the
+non-standard property "snps,phy-addr". Specifying a PHY on a different
+MDIO bus that the one within the stmmac controller doesn't seem to be
+possible when device-tree is used.
+
+This change adds support for the phy-handle property, as specified in
+Documentation/devicetree/bindings/net/ethernet.txt.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  | 28 ++++++++++++++--------
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |  6 ++++-
+ include/linux/stmmac.h                             |  1 +
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -52,6 +52,7 @@
+ #include "stmmac_ptp.h"
+ #include "stmmac.h"
+ #include <linux/reset.h>
++#include <linux/of_mdio.h>
+ 
+ #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
+ 
+@@ -816,18 +817,25 @@ static int stmmac_init_phy(struct net_de
+ 	priv->speed = 0;
+ 	priv->oldduplex = -1;
+ 
+-	if (priv->plat->phy_bus_name)
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
+-			 priv->plat->phy_bus_name, priv->plat->bus_id);
+-	else
+-		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
+-			 priv->plat->bus_id);
+-
+-	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
+-		 priv->plat->phy_addr);
+-	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
++	if (priv->plat->phy_node) {
++		phydev = of_phy_connect(dev, priv->plat->phy_node,
++					&stmmac_adjust_link, 0, interface);
++	} else {
++		if (priv->plat->phy_bus_name)
++			snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
++				 priv->plat->phy_bus_name, priv->plat->bus_id);
++		else
++			snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
++				 priv->plat->bus_id);
++
++		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
++			 priv->plat->phy_addr);
++		pr_debug("stmmac_init_phy:  trying to attach to %s\n",
++			 phy_id_fmt);
+ 
+-	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
++		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
++				     interface);
++	}
+ 
+ 	if (IS_ERR(phydev)) {
+ 		pr_err("%s: Could not attach to PHY\n", dev->name);
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -28,6 +28,7 @@
+ #include <linux/of.h>
+ #include <linux/of_net.h>
+ #include <linux/of_device.h>
++#include <linux/of_mdio.h>
+ 
+ #include "stmmac.h"
+ #include "stmmac_platform.h"
+@@ -168,13 +169,16 @@ static int stmmac_probe_config_dt(struct
+ 	/* Default to phy auto-detection */
+ 	plat->phy_addr = -1;
+ 
++	/* If we find a phy-handle property, use it as the PHY */
++	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+ 	if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
+ 		dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
+ 
+-	if (plat->phy_bus_name)
++	if (plat->phy_node || plat->phy_bus_name)
+ 		plat->mdio_bus_data = NULL;
+ 	else
+ 		plat->mdio_bus_data =
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -99,6 +99,7 @@ struct plat_stmmacenet_data {
+ 	int phy_addr;
+ 	int interface;
+ 	struct stmmac_mdio_bus_data *mdio_bus_data;
++	struct device_node *phy_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	int clk_csr;
+ 	int has_gmac;
diff --git a/target/linux/ipq806x/patches-4.1/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch b/target/linux/ipq806x/patches-4.1/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
new file mode 100644
index 0000000..37f1002
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/702-stmmac-move-error-path-at-the-end-of-stmmac_probe_co.patch
@@ -0,0 +1,65 @@
+From 0149d275415cd1b2382ce94e5eb32641590097d0 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Fri, 8 May 2015 15:57:12 -0700
+Subject: [PATCH 2/8] stmmac: move error path at the end of
+ stmmac_probe_config_dt()
+
+We will want to do additional clean-up on certain errors. Therefore,
+this change moves the error path at the end of the function for better
+code readability.
+
+This patch doesn't change anything functionally.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -130,13 +130,18 @@ static int stmmac_probe_config_dt(struct
+ 	struct device_node *np = pdev->dev.of_node;
+ 	struct stmmac_dma_cfg *dma_cfg;
+ 	const struct of_device_id *device;
++	int ret;
+ 
+-	if (!np)
+-		return -ENODEV;
++	if (!np) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	device = of_match_device(stmmac_dt_ids, &pdev->dev);
+-	if (!device)
+-		return -ENODEV;
++	if (!device) {
++		ret = -ENODEV;
++		goto err;
++	}
+ 
+ 	if (device->data) {
+ 		const struct stmmac_of_data *data = device->data;
+@@ -236,8 +241,10 @@ static int stmmac_probe_config_dt(struct
+ 	if (of_find_property(np, "snps,pbl", NULL)) {
+ 		dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
+ 				       GFP_KERNEL);
+-		if (!dma_cfg)
+-			return -ENOMEM;
++		if (!dma_cfg) {
++			ret = -ENOMEM;
++			goto err;
++		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+ 		dma_cfg->fixed_burst =
+@@ -255,6 +262,9 @@ static int stmmac_probe_config_dt(struct
+ 	}
+ 
+ 	return 0;
++
++err:
++	return ret;
+ }
+ #else
+ static int stmmac_probe_config_dt(struct platform_device *pdev,
diff --git a/target/linux/ipq806x/patches-4.1/703-stmmac-add-fixed-link-device-tree-support.patch b/target/linux/ipq806x/patches-4.1/703-stmmac-add-fixed-link-device-tree-support.patch
new file mode 100644
index 0000000..a05875b
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/703-stmmac-add-fixed-link-device-tree-support.patch
@@ -0,0 +1,64 @@
+From 3a95f75867be562cb919ff23a738f70357188fbd Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Fri, 8 May 2015 16:02:03 -0700
+Subject: [PATCH 3/8] stmmac: add fixed-link device-tree support
+
+In case DT is used, this change adds the ability to the stmmac driver to
+detect a fixed-link PHY, instanciate it, and use it during
+phy_connect().
+
+Fixed link PHYs DT usage is described in:
+Documentation/devicetree/bindings/net/fixed-link.txt
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c     |  2 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 12 +++++++++++-
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -856,7 +856,7 @@ static int stmmac_init_phy(struct net_de
+ 	 * device as well.
+ 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
+ 	 */
+-	if (phydev->phy_id == 0) {
++	if (!priv->plat->phy_node && phydev->phy_id == 0) {
+ 		phy_disconnect(phydev);
+ 		return -ENODEV;
+ 	}
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -177,6 +177,14 @@ static int stmmac_probe_config_dt(struct
+ 	/* If we find a phy-handle property, use it as the PHY */
+ 	plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
+ 
++	/* If phy-handle is not specified, check if we have a fixed-phy */
++	if (!plat->phy_node && of_phy_is_fixed_link(np)) {
++		if ((of_phy_register_fixed_link(np) < 0))
++			return -ENODEV;
++
++		plat->phy_node = of_node_get(np);
++	}
++
+ 	/* "snps,phy-addr" is not a standard property. Mark it as deprecated
+ 	 * and warn of its use. Remove this when phy node support is added.
+ 	 */
+@@ -243,7 +251,7 @@ static int stmmac_probe_config_dt(struct
+ 				       GFP_KERNEL);
+ 		if (!dma_cfg) {
+ 			ret = -ENOMEM;
+-			goto err;
++			goto err2;
+ 		}
+ 		plat->dma_cfg = dma_cfg;
+ 		of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+@@ -263,6 +271,8 @@ static int stmmac_probe_config_dt(struct
+ 
+ 	return 0;
+ 
++err2:
++	of_node_put(np);
+ err:
+ 	return ret;
+ }
diff --git a/target/linux/ipq806x/patches-4.1/704-stmmac-add-ipq806x-glue-layer.patch b/target/linux/ipq806x/patches-4.1/704-stmmac-add-ipq806x-glue-layer.patch
new file mode 100644
index 0000000..7fd72be
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/704-stmmac-add-ipq806x-glue-layer.patch
@@ -0,0 +1,407 @@
+From 69fb970ad3fe05af7cb99ea78230c69c7ca0d03b Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Fri, 8 May 2015 16:10:22 -0700
+Subject: [PATCH 4/8] stmmac: add ipq806x glue layer
+
+The ethernet controller available in IPQ806x is a Synopsys DesignWare
+Gigabit MAC IP core, already supported by the stmmac driver.
+
+This glue layer implements some platform specific settings required to
+get the controller working on an IPQ806x based platform.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/Kconfig        |   1 +
+ drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c    | 324 +++++++++++++++++++++
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   1 +
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.h  |   1 +
+ 5 files changed, 328 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-ipq.c
+
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -16,6 +16,7 @@ if STMMAC_ETH
+ config STMMAC_PLATFORM
+ 	tristate "STMMAC Platform bus support"
+ 	depends on STMMAC_ETH
++	select MFD_SYSCON
+ 	default y
+ 	---help---
+ 	  This selects the platform specific bus support for the stmmac driver.
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethto
+ 
+ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
+ stmmac-platform-objs:= stmmac_platform.o dwmac-meson.o dwmac-sunxi.o	\
+-		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o
++		       dwmac-sti.o dwmac-socfpga.o dwmac-rk.o dwmac-ipq806x.o
+ 
+ obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o
+ stmmac-pci-objs:= stmmac_pci.o
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -43,6 +43,7 @@ static const struct of_device_id stmmac_
+ 	{ .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
+ 	{ .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
+ 	{ .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
++	{ .compatible = "qcom,ipq806x-gmac", .data = &ipq806x_gmac_data },
+ 	{ .compatible = "st,spear600-gmac"},
+ 	{ .compatible = "snps,dwmac-3.610"},
+ 	{ .compatible = "snps,dwmac-3.70a"},
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
+@@ -25,5 +25,6 @@ extern const struct stmmac_of_data stih4
+ extern const struct stmmac_of_data stid127_dwmac_data;
+ extern const struct stmmac_of_data socfpga_gmac_data;
+ extern const struct stmmac_of_data rk3288_gmac_data;
++extern const struct stmmac_of_data ipq806x_gmac_data;
+ 
+ #endif /* __STMMAC_PLATFORM_H__ */
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+@@ -0,0 +1,343 @@
++/*
++ * Qualcomm Atheros IPQ806x GMAC glue layer
++ *
++ * Copyright (C) 2015 The Linux Foundation
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/phy.h>
++#include <linux/regmap.h>
++#include <linux/clk.h>
++#include <linux/reset.h>
++#include <linux/of_net.h>
++#include <linux/mfd/syscon.h>
++#include <linux/stmmac.h>
++#include <linux/of_mdio.h>
++
++#include "stmmac_platform.h"
++
++#define NSS_COMMON_CLK_GATE			0x8
++#define NSS_COMMON_CLK_GATE_PTP_EN(x)		BIT(0x10 + x)
++#define NSS_COMMON_CLK_GATE_RGMII_RX_EN(x)	BIT(0x9 + (x * 2))
++#define NSS_COMMON_CLK_GATE_RGMII_TX_EN(x)	BIT(0x8 + (x * 2))
++#define NSS_COMMON_CLK_GATE_GMII_RX_EN(x)	BIT(0x4 + x)
++#define NSS_COMMON_CLK_GATE_GMII_TX_EN(x)	BIT(0x0 + x)
++
++#define NSS_COMMON_CLK_DIV0			0xC
++#define NSS_COMMON_CLK_DIV_OFFSET(x)		(x * 8)
++#define NSS_COMMON_CLK_DIV_MASK			0x7f
++
++#define NSS_COMMON_CLK_SRC_CTRL			0x14
++#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x)	(1 << x)
++/* Mode is coded on 1 bit but is different depending on the MAC ID:
++ * MAC0: QSGMII=0 RGMII=1
++ * MAC1: QSGMII=0 SGMII=0 RGMII=1
++ * MAC2 & MAC3: QSGMII=0 SGMII=1
++ */
++#define NSS_COMMON_CLK_SRC_CTRL_RGMII(x)	1
++#define NSS_COMMON_CLK_SRC_CTRL_SGMII(x)	((x >= 2) ? 1 : 0)
++
++#define NSS_COMMON_MACSEC_CTL			0x28
++#define NSS_COMMON_MACSEC_CTL_EXT_BYPASS_EN(x)	(1 << x)
++
++#define NSS_COMMON_GMAC_CTL(x)			(0x30 + (x * 4))
++#define NSS_COMMON_GMAC_CTL_CSYS_REQ		BIT(19)
++#define NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL	BIT(16)
++#define NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET	8
++#define NSS_COMMON_GMAC_CTL_IFG_OFFSET		0
++#define NSS_COMMON_GMAC_CTL_IFG_MASK		0x3f
++
++#define NSS_COMMON_CLK_DIV_RGMII_1000		1
++#define NSS_COMMON_CLK_DIV_RGMII_100		9
++#define NSS_COMMON_CLK_DIV_RGMII_10		99
++#define NSS_COMMON_CLK_DIV_SGMII_1000		0
++#define NSS_COMMON_CLK_DIV_SGMII_100		4
++#define NSS_COMMON_CLK_DIV_SGMII_10		49
++
++#define QSGMII_PCS_MODE_CTL			0x68
++#define QSGMII_PCS_MODE_CTL_AUTONEG_EN(x)	BIT((x * 8) + 7)
++
++#define QSGMII_PCS_CAL_LCKDT_CTL		0x120
++#define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
++
++/* Only GMAC1/2/3 support SGMII and their CTL register are not contiguous */
++#define QSGMII_PHY_SGMII_CTL(x)			((x == 1) ? 0x134 : \
++						 (0x13c + (4 * (x - 2))))
++#define QSGMII_PHY_CDR_EN			BIT(0)
++#define QSGMII_PHY_RX_FRONT_EN			BIT(1)
++#define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
++#define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
++#define QSGMII_PHY_QSGMII_EN			BIT(7)
++#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
++#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		0x7
++#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
++#define QSGMII_PHY_RX_DC_BIAS_MASK		0x3
++#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
++#define QSGMII_PHY_RX_INPUT_EQU_MASK		0x3
++#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
++#define QSGMII_PHY_CDR_PI_SLEW_MASK		0x3
++#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
++#define QSGMII_PHY_TX_DRV_AMP_MASK		0xf
++
++struct ipq806x_gmac {
++	struct platform_device *pdev;
++	struct regmap *nss_common;
++	struct regmap *qsgmii_csr;
++	uint32_t id;
++	struct clk *core_clk;
++	phy_interface_t phy_mode;
++};
++
++static int get_clk_div_sgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_SGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_SGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_SGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in SGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int get_clk_div_rgmii(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	struct device *dev = &gmac->pdev->dev;
++	int div;
++
++	switch (speed) {
++	case SPEED_1000:
++		div = NSS_COMMON_CLK_DIV_RGMII_1000;
++		break;
++
++	case SPEED_100:
++		div = NSS_COMMON_CLK_DIV_RGMII_100;
++		break;
++
++	case SPEED_10:
++		div = NSS_COMMON_CLK_DIV_RGMII_10;
++		break;
++
++	default:
++		dev_err(dev, "Speed %dMbps not supported in RGMII\n", speed);
++		return -EINVAL;
++	}
++
++	return div;
++}
++
++static int ipq806x_gmac_set_speed(struct ipq806x_gmac *gmac, unsigned int speed)
++{
++	uint32_t clk_bits, val;
++	int div;
++
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		div = get_clk_div_rgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
++		break;
++
++	case PHY_INTERFACE_MODE_SGMII:
++		div = get_clk_div_sgmii(gmac, speed);
++		clk_bits = NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
++			   NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
++		break;
++
++	default:
++		dev_err(&gmac->pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return -EINVAL;
++	}
++
++	/* Disable the clocks */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val &= ~clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	/* Set the divider */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_DIV0, &val);
++	val &= ~(NSS_COMMON_CLK_DIV_MASK
++		 << NSS_COMMON_CLK_DIV_OFFSET(gmac->id));
++	val |= div << NSS_COMMON_CLK_DIV_OFFSET(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_DIV0, val);
++
++	/* Enable the clock back */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= clk_bits;
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	return 0;
++}
++
++static void *ipq806x_gmac_of_parse(struct ipq806x_gmac *gmac)
++{
++	struct device *dev = &gmac->pdev->dev;
++
++	gmac->phy_mode = of_get_phy_mode(dev->of_node);
++	if (gmac->phy_mode < 0) {
++		dev_err(dev, "missing phy mode property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	if (of_property_read_u32(dev->of_node, "qcom,id", &gmac->id) < 0) {
++		dev_err(dev, "missing qcom id property\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	/* The GMACs are called 1 to 4 in the documentation, but to simplify the
++	 * code and keep it consistent with the Linux convention, we'll number
++	 * them from 0 to 3 here.
++	 */
++	if (gmac->id < 0 || gmac->id > 3) {
++		dev_err(dev, "invalid gmac id\n");
++		return ERR_PTR(-EINVAL);
++	}
++
++	gmac->core_clk = devm_clk_get(dev, "stmmaceth");
++	if (IS_ERR(gmac->core_clk)) {
++		dev_err(dev, "missing stmmaceth clk property\n");
++		return gmac->core_clk;
++	}
++	clk_set_rate(gmac->core_clk, 266000000);
++
++	/* Setup the register map for the nss common registers */
++	gmac->nss_common = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,nss-common");
++	if (IS_ERR(gmac->nss_common)) {
++		dev_err(dev, "missing nss-common node\n");
++		return gmac->nss_common;
++	}
++
++	/* Setup the register map for the qsgmii csr registers */
++	gmac->qsgmii_csr = syscon_regmap_lookup_by_phandle(dev->of_node,
++							   "qcom,qsgmii-csr");
++	if (IS_ERR(gmac->qsgmii_csr)) {
++		dev_err(dev, "missing qsgmii-csr node\n");
++		return gmac->qsgmii_csr;
++	}
++
++	return NULL;
++}
++
++static void *ipq806x_gmac_setup(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct ipq806x_gmac *gmac;
++	int val;
++	void *err;
++
++	gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
++	if (!gmac)
++		return ERR_PTR(-ENOMEM);
++
++	gmac->pdev = pdev;
++
++	err = ipq806x_gmac_of_parse(gmac);
++	if (err) {
++		dev_err(dev, "device tree parsing error\n");
++		return err;
++	}
++
++	regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
++		     QSGMII_PCS_CAL_LCKDT_CTL_RST);
++
++	/* Inter frame gap is set to 12 */
++	val = 12 << NSS_COMMON_GMAC_CTL_IFG_OFFSET |
++	      12 << NSS_COMMON_GMAC_CTL_IFG_LIMIT_OFFSET;
++	/* We also initiate an AXI low power exit request */
++	val |= NSS_COMMON_GMAC_CTL_CSYS_REQ;
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
++
++	/* Configure the clock src according to the mode */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
++	val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++	switch (gmac->phy_mode) {
++	case PHY_INTERFACE_MODE_RGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	case PHY_INTERFACE_MODE_SGMII:
++		val |= NSS_COMMON_CLK_SRC_CTRL_SGMII(gmac->id) <<
++			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
++		break;
++	default:
++		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
++			phy_modes(gmac->phy_mode));
++		return NULL;
++	}
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
++
++	/* Enable PTP clock */
++	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
++	val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
++	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
++
++	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
++		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
++			     QSGMII_PHY_CDR_EN |
++			     QSGMII_PHY_RX_FRONT_EN |
++			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
++			     QSGMII_PHY_TX_DRIVER_EN |
++			     QSGMII_PHY_QSGMII_EN |
++			     0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
++			     0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET |
++			     0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
++			     0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
++			     0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET);
++	}
++
++	return gmac;
++}
++
++static void ipq806x_gmac_fix_mac_speed(void *priv, unsigned int speed)
++{
++	struct ipq806x_gmac *gmac = priv;
++
++	ipq806x_gmac_set_speed(gmac, speed);
++}
++
++const struct stmmac_of_data ipq806x_gmac_data = {
++	.has_gmac	= 1,
++	.setup		= ipq806x_gmac_setup,
++	.fix_mac_speed	= ipq806x_gmac_fix_mac_speed,
++};
diff --git a/target/linux/ipq806x/patches-4.1/705-net-stmmac-ipq806x-document-device-tree-bindings.patch b/target/linux/ipq806x/patches-4.1/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
new file mode 100644
index 0000000..3144fa3
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/705-net-stmmac-ipq806x-document-device-tree-bindings.patch
@@ -0,0 +1,52 @@
+From 0f9605d9409b77a89daef91cc68239fc2ff50457 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Fri, 8 May 2015 16:51:25 -0700
+Subject: [PATCH 5/8] net: stmmac: ipq806x: document device tree bindings
+
+Add the device tree bindings documentation for the QCA IPQ806x
+variant of the Synopsys DesignWare MAC.
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ .../devicetree/bindings/net/ipq806x-dwmac.txt      | 35 ++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/ipq806x-dwmac.txt
+@@ -0,0 +1,35 @@
++* IPQ806x DWMAC Ethernet controller
++
++The device inherits all the properties of the dwmac/stmmac devices
++described in the file net/stmmac.txt with the following changes.
++
++Required properties:
++
++- compatible: should be "qcom,ipq806x-gmac" along with "snps,dwmac"
++	      and any applicable more detailed version number
++	      described in net/stmmac.txt
++
++- qcom,nss-common: should contain a phandle to a syscon device mapping the
++		   nss-common registers.
++
++- qcom,qsgmii-csr: should contain a phandle to a syscon device mapping the
++		   qsgmii-csr registers.
++
++Example:
++
++	gmac: ethernet@37000000 {
++		device_type = "network";
++		compatible = "qcom,ipq806x-gmac";
++		reg = <0x37000000 0x200000>;
++		interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++		interrupt-names = "macirq";
++
++		qcom,nss-common = <&nss_common>;
++		qcom,qsgmii-csr = <&qsgmii_csr>;
++
++		clocks = <&gcc GMAC_CORE1_CLK>;
++		clock-names = "stmmaceth";
++
++		resets = <&gcc GMAC_CORE1_RESET>;
++		reset-names = "stmmaceth";
++	};
diff --git a/target/linux/ipq806x/patches-4.1/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch b/target/linux/ipq806x/patches-4.1/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
new file mode 100644
index 0000000..20d8502
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/707-ARM-dts-qcom-add-mdio-nodes-to-ap148-db149.patch
@@ -0,0 +1,145 @@
+From e81de9d28bd0421c236df322872e64edf4ee1852 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Mon, 11 May 2015 16:32:09 -0700
+Subject: [PATCH 7/8] ARM: dts: qcom: add mdio nodes to ap148 & db149
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 40 ++++++++++++++++++++++++++-
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 46 ++++++++++++++++++++++++++++++++
+ 2 files changed, 85 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -14,8 +14,9 @@
+ 		};
+ 	};
+ 
+-	alias {
++	aliases {
+ 		serial0 = &uart4;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -54,6 +55,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi@16300000 {
+@@ -139,5 +149,33 @@
+ 			pinctrl-0 = <&pcie2_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy@0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++					>;
++			};
++
++			phy4: ethernet-phy@4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -16,6 +16,7 @@
+ 
+ 	alias {
+ 		serial0 = &uart2;
++		mdio-gpio0 = &mdio0;
+ 	};
+ 
+ 	chosen {
+@@ -62,6 +63,15 @@
+ 					bias-none;
+ 				};
+ 			};
++
++			mdio0_pins: mdio0_pins {
++				mux {
++					pins = "gpio0", "gpio1";
++					function = "gpio";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi@12480000 {
+@@ -173,5 +183,44 @@
+ 			pinctrl-0 = <&pcie3_pins>;
+ 			pinctrl-names = "default";
+ 		};
++
++		mdio0: mdio {
++			compatible = "virtual,mdio-gpio";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>;
++
++			pinctrl-0 = <&mdio0_pins>;
++			pinctrl-names = "default";
++
++			phy0: ethernet-phy@0 {
++				device_type = "ethernet-phy";
++				reg = <0>;
++				qca,ar8327-initvals = <
++					0x00004 0x7600000   /* PAD0_MODE */
++					0x00008 0x1000000   /* PAD5_MODE */
++					0x0000c 0x80        /* PAD6_MODE */
++					0x000e4 0xaa545     /* MAC_POWER_SEL */
++					0x000e0 0xc74164de  /* SGMII_CTRL */
++					0x0007c 0x4e        /* PORT0_STATUS */
++					0x00094 0x4e        /* PORT6_STATUS */
++				>;
++			};
++
++			phy4: ethernet-phy@4 {
++				device_type = "ethernet-phy";
++				reg = <4>;
++			};
++
++			phy6: ethernet-phy@6 {
++				device_type = "ethernet-phy";
++				reg = <6>;
++			};
++
++			phy7: ethernet-phy@7 {
++				device_type = "ethernet-phy";
++				reg = <7>;
++			};
++		};
+ 	};
+ };
diff --git a/target/linux/ipq806x/patches-4.1/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch b/target/linux/ipq806x/patches-4.1/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
new file mode 100644
index 0000000..de68678
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/708-ARM-dts-qcom-add-gmac-nodes-to-ipq806x-platforms.patch
@@ -0,0 +1,210 @@
+From cab1f4720e82f2e17eaeed9a9ad9e4f07c742977 Mon Sep 17 00:00:00 2001
+From: Mathieu Olivari <mathieu@codeaurora.org>
+Date: Mon, 11 May 2015 12:29:18 -0700
+Subject: [PATCH 8/8] ARM: dts: qcom: add gmac nodes to ipq806x platforms
+
+Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
+---
+ arch/arm/boot/dts/qcom-ipq8064-ap148.dts | 31 ++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064-db149.dts | 43 ++++++++++++++++
+ arch/arm/boot/dts/qcom-ipq8064.dtsi      | 86 ++++++++++++++++++++++++++++++++
+ 3 files changed, 160 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+@@ -64,6 +64,16 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii2_pins: rgmii2_pins {
++				mux {
++					pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
++					       "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ;
++					function = "rgmii2";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi@16300000 {
+@@ -177,5 +187,26 @@
+ 				reg = <4>;
+ 			};
+ 		};
++
++		gmac1: ethernet@37200000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			phy-handle = <&phy4>;
++			qcom,id = <1>;
++
++			pinctrl-0 = <&rgmii2_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac2: ethernet@37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064-db149.dts
++++ b/arch/arm/boot/dts/qcom-ipq8064-db149.dts
+@@ -72,6 +72,14 @@
+ 					bias-disable;
+ 				};
+ 			};
++
++			rgmii0_pins: rgmii0_pins {
++				mux {
++					pins = "gpio2", "gpio66";
++					drive-strength = <8>;
++					bias-disable;
++				};
++			};
+ 		};
+ 
+ 		gsbi2: gsbi@12480000 {
+@@ -222,5 +230,40 @@
+ 				reg = <7>;
+ 			};
+ 		};
++
++		gmac0: ethernet@37000000 {
++			status = "ok";
++			phy-mode = "rgmii";
++			qcom,id = <0>;
++			phy-handle = <&phy4>;
++
++			pinctrl-0 = <&rgmii0_pins>;
++			pinctrl-names = "default";
++		};
++
++		gmac1: ethernet@37200000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <1>;
++
++			fixed-link {
++				speed = <1000>;
++				full-duplex;
++			};
++		};
++
++		gmac2: ethernet@37400000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <2>;
++			phy-handle = <&phy6>;
++		};
++
++		gmac3: ethernet@37600000 {
++			status = "ok";
++			phy-mode = "sgmii";
++			qcom,id = <3>;
++			phy-handle = <&phy7>;
++		};
+ 	};
+ };
+--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
+@@ -578,5 +578,91 @@
+ 			status = "disabled";
+ 		};
+ 
++		nss_common: syscon@03000000 {
++			compatible = "syscon";
++			reg = <0x03000000 0x0000FFFF>;
++		};
++
++		qsgmii_csr: syscon@1bb00000 {
++			compatible = "syscon";
++			reg = <0x1bb00000 0x000001FF>;
++		};
++
++		gmac0: ethernet@37000000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37000000 0x200000>;
++			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE1_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE1_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac1: ethernet@37200000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37200000 0x200000>;
++			interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE2_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE2_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac2: ethernet@37400000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37400000 0x200000>;
++			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE3_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE3_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
++		gmac3: ethernet@37600000 {
++			device_type = "network";
++			compatible = "qcom,ipq806x-gmac";
++			reg = <0x37600000 0x200000>;
++			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "macirq";
++
++			qcom,nss-common = <&nss_common>;
++			qcom,qsgmii-csr = <&qsgmii_csr>;
++
++			clocks = <&gcc GMAC_CORE4_CLK>;
++			clock-names = "stmmaceth";
++
++			resets = <&gcc GMAC_CORE4_RESET>;
++			reset-names = "stmmaceth";
++
++			status = "disabled";
++		};
++
+ 	};
+ };
