Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC platform updates from Olof Johansson:
 "New and/or improved SoC support for this release:

  Marvell Berlin:
     - Enable standard DT-based cpufreq
     - Add CPU hotplug support

  Freescale:
     - Ethernet init for i.MX7D
     - Suspend/resume support for i.MX6UL

  Allwinner:
     - Support for R8 chipset (used on NTC's $9 C.H.I.P board)

  Mediatek:
     - SMP support for some platforms

  Uniphier:
     - L2 support
     - Cleaned up SMP support, etc.

  plus a handful of other patches around above functionality, and a few
  other smaller changes"

* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (42 commits)
  ARM: uniphier: rework SMP operations to use trampoline code
  ARM: uniphier: add outer cache support
  Documentation: EXYNOS: Update bootloader interface on exynos542x
  ARM: mvebu: add broken-idle option
  ARM: orion5x: use mac_pton() helper
  ARM: at91: pm: at91_pm_suspend_in_sram() must be 8-byte aligned
  ARM: sunxi: Add R8 support
  ARM: digicolor: select pinctrl/gpio driver
  arm: berlin: add CPU hotplug support
  arm: berlin: use non-self-cleared reset register to reset cpu
  ARM: mediatek: add smp bringup code
  ARM: mediatek: enable gpt6 on boot up to make arch timer working
  soc: mediatek: Fix random hang up issue while kernel init
  soc: ti: qmss: make acc queue support optional in the driver
  soc: ti: add firmware file name as part of the driver
  Documentation: dt: soc: Add description for knav qmss driver
  ARM: S3C64XX: Use PWM lookup table for mach-smartq
  ARM: S3C64XX: Use PWM lookup table for mach-hmt
  ARM: S3C64XX: Use PWM lookup table for mach-crag6410
  ARM: S3C64XX: Use PWM lookup table for smdk6410
  ...
diff --git a/Documentation/arm/Samsung/Bootloader-interface.txt b/Documentation/arm/Samsung/Bootloader-interface.txt
index df8d4fb..ed494ac 100644
--- a/Documentation/arm/Samsung/Bootloader-interface.txt
+++ b/Documentation/arm/Samsung/Bootloader-interface.txt
@@ -19,7 +19,7 @@
 Address:      sysram_ns_base_addr
 Offset        Value                                        Purpose
 =============================================================================
-0x08          exynos_cpu_resume_ns                         System suspend
+0x08          exynos_cpu_resume_ns, mcpm_entry_point       System suspend
 0x0c          0x00000bad (Magic cookie)                    System suspend
 0x1c          exynos4_secondary_startup                    Secondary CPU boot
 0x1c + 4*cpu  exynos4_secondary_startup (Exynos4412)       Secondary CPU boot
@@ -56,7 +56,8 @@
 Address:      pmu_base_addr
 Offset        Value                           Purpose
 =============================================================================
-0x0908        Non-zero (only Exynos3250)      Secondary CPU boot up indicator
+0x0908        Non-zero                        Secondary CPU boot up indicator
+                                              on Exynos3250 and Exynos542x
 
 
 4. Glossary
diff --git a/Documentation/arm/keystone/knav-qmss.txt b/Documentation/arm/keystone/knav-qmss.txt
new file mode 100644
index 0000000..fcdb9fd
--- /dev/null
+++ b/Documentation/arm/keystone/knav-qmss.txt
@@ -0,0 +1,56 @@
+* Texas Instruments Keystone Navigator Queue Management SubSystem driver
+
+Driver source code path
+  drivers/soc/ti/knav_qmss.c
+  drivers/soc/ti/knav_qmss_acc.c
+
+The QMSS (Queue Manager Sub System) found on Keystone SOCs is one of
+the main hardware sub system which forms the backbone of the Keystone
+multi-core Navigator. QMSS consist of queue managers, packed-data structure
+processors(PDSP), linking RAM, descriptor pools and infrastructure
+Packet DMA.
+The Queue Manager is a hardware module that is responsible for accelerating
+management of the packet queues. Packets are queued/de-queued by writing or
+reading descriptor address to a particular memory mapped location. The PDSPs
+perform QMSS related functions like accumulation, QoS, or event management.
+Linking RAM registers are used to link the descriptors which are stored in
+descriptor RAM. Descriptor RAM is configurable as internal or external memory.
+The QMSS driver manages the PDSP setups, linking RAM regions,
+queue pool management (allocation, push, pop and notify) and descriptor
+pool management.
+
+knav qmss driver provides a set of APIs to drivers to open/close qmss queues,
+allocate descriptor pools, map the descriptors, push/pop to queues etc. For
+details of the available APIs, please refers to include/linux/soc/ti/knav_qmss.h
+
+DT documentation is available at
+Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
+
+Accumulator QMSS queues using PDSP firmware
+============================================
+The QMSS PDSP firmware support accumulator channel that can monitor a single
+queue or multiple contiguous queues. drivers/soc/ti/knav_qmss_acc.c is the
+driver that interface with the accumulator PDSP. This configures
+accumulator channels defined in DTS (example in DT documentation) to monitor
+1 or 32 queues per channel. More description on the firmware is available in
+CPPI/QMSS Low Level Driver document (docs/CPPI_QMSS_LLD_SDS.pdf) at
+	git://git.ti.com/keystone-rtos/qmss-lld.git
+
+k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports upto 48 accumulator
+channels. This firmware is available under ti-keystone folder of
+firmware.git at
+   git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
+
+To use copy the firmware image to lib/firmware folder of the initramfs or
+ubifs file system and provide a sym link to k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin
+in the file system and boot up the kernel. User would see
+
+ "firmware file ks2_qmss_pdsp_acc48.bin downloaded for PDSP"
+
+in the boot up log if loading of firmware to PDSP is successful.
+
+Use of accumulated queues requires the firmware image to be present in the
+file system. The driver doesn't acc queues to the supported queue range if
+PDSP is not running in the SoC. The API call fails if there is a queue open
+request to an acc queue and PDSP is not running. So make sure to copy firmware
+to file system before using these queue types.
diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
index 5e38e158..430d279 100644
--- a/Documentation/arm/sunxi/README
+++ b/Documentation/arm/sunxi/README
@@ -25,7 +25,7 @@
         + Datasheet
           http://dl.linux-sunxi.org/A10s/A10s%20Datasheet%20-%20v1.20%20%282012-03-27%29.pdf
 
-      - Allwinner A13 (sun5i)
+      - Allwinner A13 / R8 (sun5i)
         + Datasheet
 	  http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
         + User Manual
diff --git a/Documentation/devicetree/bindings/arm/coherency-fabric.txt b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
index 8dd4661..9b5c3f6 100644
--- a/Documentation/devicetree/bindings/arm/coherency-fabric.txt
+++ b/Documentation/devicetree/bindings/arm/coherency-fabric.txt
@@ -27,6 +27,11 @@
  * For "marvell,armada-380-coherency-fabric", only one pair is needed
    for the per-CPU fabric registers.
 
+Optional properties:
+
+- broken-idle: boolean to set when the Idle mode is not supported by the
+  hardware.
+
 Examples:
 
 coherency-fabric@d0020200 {
diff --git a/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt
new file mode 100644
index 0000000..2cdcd71
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mvebu-cpu-config.txt
@@ -0,0 +1,20 @@
+MVEBU CPU Config registers
+--------------------------
+
+MVEBU (Marvell SOCs: Armada 370/XP)
+
+Required properties:
+
+- compatible: one of:
+	- "marvell,armada-370-cpu-config"
+	- "marvell,armada-xp-cpu-config"
+
+- reg: Should contain CPU config registers location and length, in
+  their per-CPU variant
+
+Example:
+
+	cpu-config@21000 {
+		compatible = "marvell,armada-xp-cpu-config";
+		reg = <0x21000 0x8>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
index 67da205..bb9b0faa 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.txt
+++ b/Documentation/devicetree/bindings/arm/sunxi.txt
@@ -6,6 +6,7 @@
   allwinner,sun4i-a10
   allwinner,sun5i-a10s
   allwinner,sun5i-a13
+  allwinner,sun5i-r8
   allwinner,sun6i-a31
   allwinner,sun7i-a20
   allwinner,sun8i-a23
diff --git a/Documentation/devicetree/bindings/arm/uniphier/cache-uniphier.txt b/Documentation/devicetree/bindings/arm/uniphier/cache-uniphier.txt
new file mode 100644
index 0000000..d27a646
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/uniphier/cache-uniphier.txt
@@ -0,0 +1,60 @@
+UniPhier outer cache controller
+
+UniPhier SoCs are integrated with a full-custom outer cache controller system.
+All of them have a level 2 cache controller, and some have a level 3 cache
+controller as well.
+
+Required properties:
+- compatible: should be "socionext,uniphier-system-cache"
+- reg: offsets and lengths of the register sets for the device.  It should
+  contain 3 regions: control register, revision register, operation register,
+  in this order.
+- cache-unified: specifies the cache is a unified cache.
+- cache-size: specifies the size in bytes of the cache
+- cache-sets: specifies the number of associativity sets of the cache
+- cache-line-size: specifies the line size in bytes
+- cache-level: specifies the level in the cache hierarchy.  The value should
+  be 2 for L2 cache, 3 for L3 cache, etc.
+
+Optional properties:
+- next-level-cache: phandle to the next level cache if present.  The next level
+  cache should be also compatible with "socionext,uniphier-system-cache".
+
+The L2 cache must exist to use the L3 cache; the cache hierarchy must be
+indicated correctly with "next-level-cache" properties.
+
+Example 1 (system with L2):
+	l2: l2-cache@500c0000 {
+		compatible = "socionext,uniphier-system-cache";
+		reg = <0x500c0000 0x2000>, <0x503c0100 0x4>,
+		      <0x506c0000 0x400>;
+		cache-unified;
+		cache-size = <0x80000>;
+		cache-sets = <256>;
+		cache-line-size = <128>;
+		cache-level = <2>;
+	};
+
+Example 2 (system with L2 and L3):
+	l2: l2-cache@500c0000 {
+		compatible = "socionext,uniphier-system-cache";
+		reg = <0x500c0000 0x2000>, <0x503c0100 0x8>,
+		      <0x506c0000 0x400>;
+		cache-unified;
+		cache-size = <0x200000>;
+		cache-sets = <512>;
+		cache-line-size = <128>;
+		cache-level = <2>;
+		next-level-cache = <&l3>;
+	};
+
+	l3: l3-cache@500c8000 {
+		compatible = "socionext,uniphier-system-cache";
+		reg = <0x500c8000 0x2000>, <0x503c8100 0x8>,
+		      <0x506c8000 0x400>;
+		cache-unified;
+		cache-size = <0x400000>;
+		cache-sets = <512>;
+		cache-line-size = <256>;
+		cache-level = <3>;
+	};
diff --git a/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt b/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
index d8e8cdb..d1ce21a 100644
--- a/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
+++ b/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
@@ -221,7 +221,6 @@
 		#size-cells = <1>;
 		ranges;
 		pdsp0@0x2a10000 {
-			firmware = "keystone/qmss_pdsp_acc48_k2_le_1_0_0_8.fw";
 			reg = <0x2a10000 0x1000>,
 			      <0x2a0f000 0x100>,
 			      <0x2a0c000 0x3c8>,
diff --git a/MAINTAINERS b/MAINTAINERS
index f68d840..9528537 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -920,7 +920,7 @@
 S:	Maintained
 F:	arch/arm/mach-alpine/
 
-ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
+ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M:	Nicolas Ferre <nicolas.ferre@atmel.com>
 M:	Alexandre Belloni <alexandre.belloni@free-electrons.com>
 M:	Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
@@ -1630,7 +1630,9 @@
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/boot/dts/uniphier*
+F:	arch/arm/include/asm/hardware/cache-uniphier.h
 F:	arch/arm/mach-uniphier/
+F:	arch/arm/mm/cache-uniphier.c
 F:	drivers/i2c/busses/i2c-uniphier*
 F:	drivers/pinctrl/uniphier/
 F:	drivers/tty/serial/8250/8250_uniphier.c
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 40a3c25..259c0ca 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -123,29 +123,23 @@
 		    0x80020000      | 0xf0020000     | UART8
 		    0x80024000      | 0xf0024000     | UART9
 
-	config AT91_DEBUG_LL_DBGU0
-		bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10, 9rl, 9x5, 9n12"
-		select DEBUG_AT91_UART
+	config DEBUG_AT91_UART
+		bool "Kernel low-level debugging on Atmel SoCs"
 		depends on ARCH_AT91
-		depends on SOC_AT91RM9200 || SOC_AT91SAM9
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on atmel devices.
 
-	config AT91_DEBUG_LL_DBGU1
-		bool "Kernel low-level debugging on 9263, 9g45 and sama5d3"
-		select DEBUG_AT91_UART
-		depends on ARCH_AT91
-		depends on SOC_AT91SAM9 || SOC_SAMA5
+		  SOC                  DEBUG_UART_PHYS   DEBUG_UART_VIRT  PORT
+		  rm9200, 9260/9g20,   0xfffff200        0xfefff200       DBGU
+		  9261/9g10, 9rl
+		  9263, 9g45, sama5d3  0xffffee00        0xfeffee00       DBGU
+		  sama5d4              0xfc00c000        0xfb00c000       USART3
+		  sama5d4              0xfc069000        0xfb069000       DBGU
+		  sama5d2              0xf8020000        0xf7020000       UART1
 
-	config AT91_DEBUG_LL_DBGU2
-		bool "Kernel low-level debugging on sama5d4"
-		select DEBUG_AT91_UART
-		depends on ARCH_AT91
-		depends on SOC_SAMA5
-
-	config AT91_DEBUG_LL_DBGU3
-		bool "Kernel low-level debugging on sama5d2"
-		select DEBUG_AT91_UART
-		depends on ARCH_AT91
-		depends on SOC_SAMA5
+		  Please adjust DEBUG_UART_PHYS configuration options based on
+		  your needs.
 
 	config DEBUG_BCM2835
 		bool "Kernel low-level debugging on BCM2835 PL011 UART"
@@ -1249,10 +1243,6 @@
 
 endchoice
 
-config DEBUG_AT91_UART
-	bool
-	depends on ARCH_AT91
-
 config DEBUG_EXYNOS_UART
 	bool
 
@@ -1485,7 +1475,8 @@
 		DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
 		DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
 		DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
-		DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0
+		DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
+		DEBUG_AT91_UART
 
 config DEBUG_UART_VIRT
 	hex "Virtual base address of debug UART"
diff --git a/arch/arm/include/asm/hardware/cache-uniphier.h b/arch/arm/include/asm/hardware/cache-uniphier.h
new file mode 100644
index 0000000..102e3fb
--- /dev/null
+++ b/arch/arm/include/asm/hardware/cache-uniphier.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CACHE_UNIPHIER_H
+#define __CACHE_UNIPHIER_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_CACHE_UNIPHIER
+int uniphier_cache_init(void);
+int uniphier_cache_l2_is_enabled(void);
+void uniphier_cache_l2_touch_range(unsigned long start, unsigned long end);
+void uniphier_cache_l2_set_locked_ways(u32 way_mask);
+#else
+static inline int uniphier_cache_init(void)
+{
+	return -ENODEV;
+}
+
+static inline int uniphier_cache_l2_is_enabled(void)
+{
+	return 0;
+}
+
+static inline void uniphier_cache_l2_touch_range(unsigned long start,
+						 unsigned long end)
+{
+}
+
+static inline void uniphier_cache_l2_set_locked_ways(u32 way_mask)
+{
+}
+#endif
+
+#endif /* __CACHE_UNIPHIER_H */
diff --git a/arch/arm/include/debug/at91.S b/arch/arm/include/debug/at91.S
index 2556a88..43243be 100644
--- a/arch/arm/include/debug/at91.S
+++ b/arch/arm/include/debug/at91.S
@@ -9,32 +9,22 @@
  *
 */
 
-#if defined(CONFIG_AT91_DEBUG_LL_DBGU0)
-#define AT91_DBGU 0xfffff200 /* AT91_BASE_DBGU0 */
-#elif defined(CONFIG_AT91_DEBUG_LL_DBGU1)
-#define AT91_DBGU 0xffffee00 /* AT91_BASE_DBGU1 */
-#elif defined(CONFIG_AT91_DEBUG_LL_DBGU2)
-/* On sama5d4, use USART3 as low level serial console */
-#define AT91_DBGU 0xfc00c000 /* SAMA5D4_BASE_USART3 */
-#else
-/* On sama5d2, use UART1 as low level serial console */
-#define AT91_DBGU 0xf8020000
-#endif
-
 #ifdef CONFIG_MMU
 #define AT91_IO_P2V(x) ((x) - 0x01000000)
 #else
 #define AT91_IO_P2V(x) (x)
 #endif
 
+#define CONFIG_DEBUG_UART_VIRT AT91_IO_P2V(CONFIG_DEBUG_UART_PHYS)
+
 #define AT91_DBGU_SR		(0x14)	/* Status Register */
 #define AT91_DBGU_THR		(0x1c)	/* Transmitter Holding Register */
 #define AT91_DBGU_TXRDY		(1 << 1)	/* Transmitter Ready */
 #define AT91_DBGU_TXEMPTY	(1 << 9)	/* Transmitter Empty */
 
 	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =AT91_DBGU				@ System peripherals (phys address)
-	ldr	\rv, =AT91_IO_P2V(AT91_DBGU)		@ System peripherals (virt address)
+	ldr	\rp, =CONFIG_DEBUG_UART_PHYS		@ System peripherals (phys address)
+	ldr	\rv, =CONFIG_DEBUG_UART_VIRT		@ System peripherals (virt address)
 	.endm
 
 	.macro	senduart,rd,rx
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2766183..1d45320 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -39,6 +39,7 @@
 #include <linux/export.h>
 
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/cache-uniphier.h>
 #include <asm/outercache.h>
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
@@ -97,6 +98,8 @@
 		if (ret)
 			pr_err("L2C: failed to init: %d\n", ret);
 	}
+
+	uniphier_cache_init();
 }
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index 0d95f48..a25defd 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -80,6 +80,8 @@
  *	@r2: base address of second SDRAM Controller or 0 if not present
  *	@r3: pm information
  */
+/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
+	.align 3
 ENTRY(at91_pm_suspend_in_sram)
 	/* Save registers on stack */
 	stmfd	sp!, {r4 - r12, lr}
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 84bd265..8c53c55 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -35,6 +35,20 @@
 	  BCM11300, BCM11320, BCM11350, BCM11360,
 	  BCM58300, BCM58302, BCM58303, BCM58305.
 
+config ARCH_BCM_NSP
+	bool "Broadcom Northstar Plus SoC Support" if ARCH_MULTI_V7
+	select ARCH_BCM_IPROC
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_775420
+	help
+	  Support for Broadcom Northstar Plus SoC.
+	  Broadcom Northstar Plus family of SoCs are used for switching control
+	  and management applications as well as residential router/gateway
+	  applications. The SoC features dual core Cortex A9 ARM CPUs,
+	  integrating several peripheral interfaces including multiple Gigabit
+	  Ethernet PHYs, DDR3 memory, PCIE Gen-2, USB 2.0 and USB 3.0, serial and
+	  NAND flash, SATA and several other IO controllers.
+
 config ARCH_BCM_5301X
 	bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7
 	select ARCH_BCM_IPROC
@@ -147,6 +161,7 @@
 	select BCM7120_L2_IRQ
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select SOC_BRCMSTB
 	help
 	  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
 	  chipset.
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index 1780a3f..892261f 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2012-2014 Broadcom Corporation
+# Copyright (C) 2012-2015 Broadcom Corporation
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License as
@@ -13,6 +13,9 @@
 # Cygnus
 obj-$(CONFIG_ARCH_BCM_CYGNUS) +=  bcm_cygnus.o
 
+# Northstar Plus
+obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o
+
 # BCM281XX
 obj-$(CONFIG_ARCH_BCM_281XX)	+= board_bcm281xx.o
 
diff --git a/arch/arm/mach-bcm/bcm_nsp.c b/arch/arm/mach-bcm/bcm_nsp.c
new file mode 100644
index 0000000..a1101a3
--- /dev/null
+++ b/arch/arm/mach-bcm/bcm_nsp.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach/arch.h>
+
+static const char *const bcm_nsp_dt_compat[] __initconst = {
+	"brcm,nsp",
+	NULL,
+};
+
+DT_MACHINE_START(NSP_DT, "Broadcom Northstar Plus SoC")
+	.l2c_aux_val	= 0,
+	.l2c_aux_mask	= ~0,
+	.dt_compat = bcm_nsp_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-bcm/brcmstb.c b/arch/arm/mach-bcm/brcmstb.c
index 3a60f7e..99a67cf 100644
--- a/arch/arm/mach-bcm/brcmstb.c
+++ b/arch/arm/mach-bcm/brcmstb.c
@@ -12,11 +12,19 @@
  */
 
 #include <linux/init.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
+#include <linux/soc/brcmstb/brcmstb.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+static void __init brcmstb_init_irq(void)
+{
+	irqchip_init();
+	brcmstb_biuctrl_init();
+}
+
 static const char *const brcmstb_match[] __initconst = {
 	"brcm,bcm7445",
 	"brcm,brcmstb",
@@ -25,4 +33,5 @@
 
 DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
 	.dt_compat	= brcmstb_match,
+	.init_irq	= brcmstb_init_irq,
 MACHINE_END
diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c
index ac181c6..25d7387 100644
--- a/arch/arm/mach-berlin/berlin.c
+++ b/arch/arm/mach-berlin/berlin.c
@@ -18,6 +18,11 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 
+static void __init berlin_init_late(void)
+{
+	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+}
+
 static const char * const berlin_dt_compat[] = {
 	"marvell,berlin",
 	NULL,
@@ -25,6 +30,7 @@
 
 DT_MACHINE_START(BERLIN_DT, "Marvell Berlin")
 	.dt_compat	= berlin_dt_compat,
+	.init_late	= berlin_init_late,
 	/*
 	 * with DT probing for L2CCs, berlin_init_machine can be removed.
 	 * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc
diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c
index 34a3753..405cd37 100644
--- a/arch/arm/mach-berlin/platsmp.c
+++ b/arch/arm/mach-berlin/platsmp.c
@@ -14,10 +14,16 @@
 #include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cp15.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 
-#define CPU_RESET		0x00
+/*
+ * There are two reset registers, one with self-clearing (SC)
+ * reset and one with non-self-clearing reset (NON_SC).
+ */
+#define CPU_RESET_SC		0x00
+#define CPU_RESET_NON_SC	0x20
 
 #define RESET_VECT		0x00
 #define SW_RESET_ADDR		0x94
@@ -30,9 +36,11 @@
 {
 	u32 val;
 
-	val = readl(cpu_ctrl + CPU_RESET);
+	val = readl(cpu_ctrl + CPU_RESET_NON_SC);
+	val &= ~BIT(cpu_logical_map(cpu));
+	writel(val, cpu_ctrl + CPU_RESET_NON_SC);
 	val |= BIT(cpu_logical_map(cpu));
-	writel(val, cpu_ctrl + CPU_RESET);
+	writel(val, cpu_ctrl + CPU_RESET_NON_SC);
 }
 
 static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -91,8 +99,32 @@
 	iounmap(scu_base);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void berlin_cpu_die(unsigned int cpu)
+{
+	v7_exit_coherency_flush(louis);
+	while (1)
+		cpu_do_idle();
+}
+
+static int berlin_cpu_kill(unsigned int cpu)
+{
+	u32 val;
+
+	val = readl(cpu_ctrl + CPU_RESET_NON_SC);
+	val &= ~BIT(cpu_logical_map(cpu));
+	writel(val, cpu_ctrl + CPU_RESET_NON_SC);
+
+	return 1;
+}
+#endif
+
 static struct smp_operations berlin_smp_ops __initdata = {
 	.smp_prepare_cpus	= berlin_smp_prepare_cpus,
 	.smp_boot_secondary	= berlin_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= berlin_cpu_die,
+	.cpu_kill		= berlin_cpu_kill,
+#endif
 };
 CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);
diff --git a/arch/arm/mach-digicolor/Kconfig b/arch/arm/mach-digicolor/Kconfig
index 4f36d8d..fc65b0f 100644
--- a/arch/arm/mach-digicolor/Kconfig
+++ b/arch/arm/mach-digicolor/Kconfig
@@ -1,7 +1,10 @@
 config ARCH_DIGICOLOR
 	bool "Conexant Digicolor SoC Support"
 	depends on ARCH_MULTI_V7
+	select ARCH_REQUIRE_GPIOLIB
 	select CLKSRC_MMIO
 	select DIGICOLOR_TIMER
 	select GENERIC_IRQ_CHIP
 	select MFD_SYSCON
+	select PINCTRL
+	select PINCTRL_DIGICOLOR
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 21e4e86..e2d5383 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -131,6 +131,7 @@
 void imx6dl_pm_init(void);
 void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
+void imx6ul_pm_init(void);
 
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index 1b97fe1..acaf705 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -67,6 +67,7 @@
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx6ul_enet_init();
 	imx_anatop_init();
+	imx6ul_pm_init();
 }
 
 static void __init imx6ul_init_irq(void)
@@ -74,6 +75,13 @@
 	imx_init_revision_from_anatop();
 	imx_src_init();
 	irqchip_init();
+	imx6_pm_ccm_init("fsl,imx6ul-ccm");
+}
+
+static void __init imx6ul_init_late(void)
+{
+	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
+		platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
 }
 
 static const char *imx6ul_dt_compat[] __initconst = {
@@ -84,5 +92,6 @@
 DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
 	.init_irq	= imx6ul_init_irq,
 	.init_machine	= imx6ul_init_machine,
+	.init_late	= imx6ul_init_late,
 	.dt_compat	= imx6ul_dt_compat,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index 62f3437..b450f52 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -6,12 +6,85 @@
  * published by the Free Software Foundation.
  */
 #include <linux/irqchip.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
 #include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/regmap.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
 
+static int ar8031_phy_fixup(struct phy_device *dev)
+{
+	u16 val;
+
+	/* Set RGMII IO voltage to 1.8V */
+	phy_write(dev, 0x1d, 0x1f);
+	phy_write(dev, 0x1e, 0x8);
+
+	/* disable phy AR8031 SmartEEE function. */
+	phy_write(dev, 0xd, 0x3);
+	phy_write(dev, 0xe, 0x805d);
+	phy_write(dev, 0xd, 0x4003);
+	val = phy_read(dev, 0xe);
+	val &= ~(0x1 << 8);
+	phy_write(dev, 0xe, val);
+
+	/* introduce tx clock delay */
+	phy_write(dev, 0x1d, 0x5);
+	val = phy_read(dev, 0x1e);
+	val |= 0x0100;
+	phy_write(dev, 0x1e, val);
+
+	return 0;
+}
+
+static int bcm54220_phy_fixup(struct phy_device *dev)
+{
+	/* enable RXC skew select RGMII copper mode */
+	phy_write(dev, 0x1e, 0x21);
+	phy_write(dev, 0x1f, 0x7ea8);
+	phy_write(dev, 0x1e, 0x2f);
+	phy_write(dev, 0x1f, 0x71b7);
+
+	return 0;
+}
+
+#define PHY_ID_AR8031	0x004dd074
+#define PHY_ID_BCM54220	0x600d8589
+
+static void __init imx7d_enet_phy_init(void)
+{
+	if (IS_BUILTIN(CONFIG_PHYLIB)) {
+		phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+					   ar8031_phy_fixup);
+		phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff,
+					   bcm54220_phy_fixup);
+	}
+}
+
+static void __init imx7d_enet_clk_sel(void)
+{
+	struct regmap *gpr;
+
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx7d-iomuxc-gpr");
+	if (!IS_ERR(gpr)) {
+		regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_TX_CLK_SEL_MASK, 0);
+		regmap_update_bits(gpr, IOMUXC_GPR1, IMX7D_GPR1_ENET_CLK_DIR_MASK, 0);
+	} else {
+		pr_err("failed to find fsl,imx7d-iomux-gpr regmap\n");
+	}
+}
+
+static inline void imx7d_enet_init(void)
+{
+	imx7d_enet_phy_init();
+	imx7d_enet_clk_sel();
+}
+
 static void __init imx7d_init_machine(void)
 {
 	struct device *parent;
@@ -22,6 +95,7 @@
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	imx_anatop_init();
+	imx7d_enet_init();
 }
 
 static void __init imx7d_init_irq(void)
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 8ff8fc0..4470376 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -93,6 +93,7 @@
 	const char *src_compat;
 	const char *iomuxc_compat;
 	const char *gpc_compat;
+	const char *pl310_compat;
 	const u32 mmdc_io_num;
 	const u32 *mmdc_io_offset;
 };
@@ -137,11 +138,19 @@
 	0x330, 0x334, 0x338, 0x33c, /* SDQS0 ~ SDQS3 */
 };
 
+static const u32 imx6ul_mmdc_io_offset[] __initconst = {
+	0x244, 0x248, 0x24c, 0x250, /* DQM0, DQM1, RAS, CAS */
+	0x27c, 0x498, 0x4a4, 0x490, /* SDCLK0, GPR_B0DS-B1DS, GPR_ADDS */
+	0x280, 0x284, 0x260, 0x264, /* SDQS0~1, SODT0, SODT1 */
+	0x494, 0x4b0,	            /* MODE_CTL, MODE, */
+};
+
 static const struct imx6_pm_socdata imx6q_pm_data __initconst = {
 	.mmdc_compat = "fsl,imx6q-mmdc",
 	.src_compat = "fsl,imx6q-src",
 	.iomuxc_compat = "fsl,imx6q-iomuxc",
 	.gpc_compat = "fsl,imx6q-gpc",
+	.pl310_compat = "arm,pl310-cache",
 	.mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset),
 	.mmdc_io_offset = imx6q_mmdc_io_offset,
 };
@@ -151,6 +160,7 @@
 	.src_compat = "fsl,imx6q-src",
 	.iomuxc_compat = "fsl,imx6dl-iomuxc",
 	.gpc_compat = "fsl,imx6q-gpc",
+	.pl310_compat = "arm,pl310-cache",
 	.mmdc_io_num = ARRAY_SIZE(imx6dl_mmdc_io_offset),
 	.mmdc_io_offset = imx6dl_mmdc_io_offset,
 };
@@ -160,6 +170,7 @@
 	.src_compat = "fsl,imx6sl-src",
 	.iomuxc_compat = "fsl,imx6sl-iomuxc",
 	.gpc_compat = "fsl,imx6sl-gpc",
+	.pl310_compat = "arm,pl310-cache",
 	.mmdc_io_num = ARRAY_SIZE(imx6sl_mmdc_io_offset),
 	.mmdc_io_offset = imx6sl_mmdc_io_offset,
 };
@@ -169,10 +180,21 @@
 	.src_compat = "fsl,imx6sx-src",
 	.iomuxc_compat = "fsl,imx6sx-iomuxc",
 	.gpc_compat = "fsl,imx6sx-gpc",
+	.pl310_compat = "arm,pl310-cache",
 	.mmdc_io_num = ARRAY_SIZE(imx6sx_mmdc_io_offset),
 	.mmdc_io_offset = imx6sx_mmdc_io_offset,
 };
 
+static const struct imx6_pm_socdata imx6ul_pm_data __initconst = {
+	.mmdc_compat = "fsl,imx6ul-mmdc",
+	.src_compat = "fsl,imx6ul-src",
+	.iomuxc_compat = "fsl,imx6ul-iomuxc",
+	.gpc_compat = "fsl,imx6ul-gpc",
+	.pl310_compat = NULL,
+	.mmdc_io_num = ARRAY_SIZE(imx6ul_mmdc_io_offset),
+	.mmdc_io_offset = imx6ul_mmdc_io_offset,
+};
+
 /*
  * This structure is for passing necessary data for low level ocram
  * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct
@@ -290,7 +312,7 @@
 		val |= BM_CLPCR_SBYOS;
 		if (cpu_is_imx6sl())
 			val |= BM_CLPCR_BYPASS_PMIC_READY;
-		if (cpu_is_imx6sl() || cpu_is_imx6sx())
+		if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul())
 			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
 		else
 			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -330,6 +352,10 @@
 		 * as we need to float DDR IO.
 		 */
 		local_flush_tlb_all();
+		/* check if need to flush internal L2 cache */
+		if (!((struct imx6_cpu_pm_info *)
+			suspend_ocram_base)->l2_base.vbase)
+			flush_cache_all();
 		imx6_suspend_in_ocram_fn(suspend_ocram_base);
 	}
 
@@ -470,6 +496,7 @@
 	suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
 		MX6Q_SUSPEND_OCRAM_SIZE, false);
 
+	memset(suspend_ocram_base, 0, sizeof(*pm_info));
 	pm_info = suspend_ocram_base;
 	pm_info->pbase = ocram_pbase;
 	pm_info->resume_addr = virt_to_phys(v7_cpu_resume);
@@ -505,11 +532,13 @@
 		goto gpc_map_failed;
 	}
 
-	ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
-	if (ret) {
-		pr_warn("%s: failed to get pl310-cache base %d!\n",
-			__func__, ret);
-		goto pl310_cache_map_failed;
+	if (socdata->pl310_compat) {
+		ret = imx6_pm_get_base(&pm_info->l2_base, socdata->pl310_compat);
+		if (ret) {
+			pr_warn("%s: failed to get pl310-cache base %d!\n",
+				__func__, ret);
+			goto pl310_cache_map_failed;
+		}
 	}
 
 	pm_info->ddr_type = imx_mmdc_get_ddr_type();
@@ -610,3 +639,8 @@
 {
 	imx6_pm_common_init(&imx6sx_pm_data);
 }
+
+void __init imx6ul_pm_init(void)
+{
+	imx6_pm_common_init(&imx6ul_pm_data);
+}
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index b99987b..76ee2ce 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -79,12 +79,15 @@
 	/* sync L2 cache to drain L2's buffers to DRAM. */
 #ifdef CONFIG_CACHE_L2X0
 	ldr	r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
+	teq	r11, #0
+	beq	6f
 	mov	r6, #0x0
 	str	r6, [r11, #L2X0_CACHE_SYNC]
 1:
 	ldr	r6, [r11, #L2X0_CACHE_SYNC]
 	ands	r6, r6, #0x1
 	bne	1b
+6:
 #endif
 
 	.endm
diff --git a/arch/arm/mach-mediatek/Makefile b/arch/arm/mach-mediatek/Makefile
index 43e619f..2116460 100644
--- a/arch/arm/mach-mediatek/Makefile
+++ b/arch/arm/mach-mediatek/Makefile
@@ -1 +1,4 @@
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
+endif
 obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
diff --git a/arch/arm/mach-mediatek/mediatek.c b/arch/arm/mach-mediatek/mediatek.c
index a954900..d019a08 100644
--- a/arch/arm/mach-mediatek/mediatek.c
+++ b/arch/arm/mach-mediatek/mediatek.c
@@ -16,6 +16,32 @@
  */
 #include <linux/init.h>
 #include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+
+
+#define GPT6_CON_MT65xx 0x10008060
+#define GPT_ENABLE      0x31
+
+static void __init mediatek_timer_init(void)
+{
+	void __iomem *gpt_base;
+
+	if (of_machine_is_compatible("mediatek,mt6589") ||
+	    of_machine_is_compatible("mediatek,mt8135") ||
+	    of_machine_is_compatible("mediatek,mt8127")) {
+		/* turn on GPT6 which ungates arch timer clocks */
+		gpt_base = ioremap(GPT6_CON_MT65xx, 0x04);
+
+		/* enable clock and set to free-run */
+		writel(GPT_ENABLE, gpt_base);
+		iounmap(gpt_base);
+	}
+
+	of_clk_init(NULL);
+	clocksource_probe();
+};
 
 static const char * const mediatek_board_dt_compat[] = {
 	"mediatek,mt6589",
@@ -27,4 +53,5 @@
 
 DT_MACHINE_START(MEDIATEK_DT, "Mediatek Cortex-A7 (Device Tree)")
 	.dt_compat	= mediatek_board_dt_compat,
+	.init_time	= mediatek_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-mediatek/platsmp.c b/arch/arm/mach-mediatek/platsmp.c
new file mode 100644
index 0000000..8141f3f
--- /dev/null
+++ b/arch/arm/mach-mediatek/platsmp.c
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-mediatek/platsmp.c
+ *
+ * Copyright (c) 2014 Mediatek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.com>
+ *         Yingjoe Chen <yingjoe.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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/io.h>
+#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/string.h>
+#include <linux/threads.h>
+
+#define MTK_MAX_CPU		8
+#define MTK_SMP_REG_SIZE	0x1000
+
+struct mtk_smp_boot_info {
+	unsigned long smp_base;
+	unsigned int jump_reg;
+	unsigned int core_keys[MTK_MAX_CPU - 1];
+	unsigned int core_regs[MTK_MAX_CPU - 1];
+};
+
+static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
+	0x80002000, 0x3fc,
+	{ 0x534c4131, 0x4c415332, 0x41534c33 },
+	{ 0x3f8, 0x3f8, 0x3f8 },
+};
+
+static const struct mtk_smp_boot_info mtk_mt6589_boot = {
+	0x10002000, 0x34,
+	{ 0x534c4131, 0x4c415332, 0x41534c33 },
+	{ 0x38, 0x3c, 0x40 },
+};
+
+static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
+	{ .compatible   = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
+	{ .compatible   = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
+};
+
+static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
+	{ .compatible   = "mediatek,mt6589", .data = &mtk_mt6589_boot },
+};
+
+static void __iomem *mtk_smp_base;
+static const struct mtk_smp_boot_info *mtk_smp_info;
+
+static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	if (!mtk_smp_base)
+		return -EINVAL;
+
+	if (!mtk_smp_info->core_keys[cpu-1])
+		return -EINVAL;
+
+	writel_relaxed(mtk_smp_info->core_keys[cpu-1],
+		mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
+
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	return 0;
+}
+
+static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
+{
+	int i, num;
+	const struct of_device_id *infos;
+
+	if (trustzone) {
+		num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
+		infos = mtk_tz_smp_boot_infos;
+	} else {
+		num = ARRAY_SIZE(mtk_smp_boot_infos);
+		infos = mtk_smp_boot_infos;
+	}
+
+	/* Find smp boot info for this SoC */
+	for (i = 0; i < num; i++) {
+		if (of_machine_is_compatible(infos[i].compatible)) {
+			mtk_smp_info = infos[i].data;
+			break;
+		}
+	}
+
+	if (!mtk_smp_info) {
+		pr_err("%s: Device is not supported\n", __func__);
+		return;
+	}
+
+	if (trustzone) {
+		/* smp_base(trustzone-bootinfo) is reserved by device tree */
+		mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
+	} else {
+		mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
+		if (!mtk_smp_base) {
+			pr_err("%s: Can't remap %lx\n", __func__,
+				mtk_smp_info->smp_base);
+			return;
+		}
+	}
+
+	/*
+	 * write the address of slave startup address into the system-wide
+	 * jump register
+	 */
+	writel_relaxed(virt_to_phys(secondary_startup_arm),
+			mtk_smp_base + mtk_smp_info->jump_reg);
+}
+
+static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
+{
+	__mtk_smp_prepare_cpus(max_cpus, 1);
+}
+
+static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
+{
+	__mtk_smp_prepare_cpus(max_cpus, 0);
+}
+
+static struct smp_operations mt81xx_tz_smp_ops __initdata = {
+	.smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
+	.smp_boot_secondary = mtk_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
+
+static struct smp_operations mt6589_smp_ops __initdata = {
+	.smp_prepare_cpus = mtk_smp_prepare_cpus,
+	.smp_boot_secondary = mtk_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops);
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index 0743e20..5d56f86 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -19,4 +19,9 @@
 	default ARCH_MESON
 	select MESON6_TIMER
 
+config MACH_MESON8B
+	bool "Amlogic Meson8b SoCs support"
+	default ARCH_MESON
+	select MESON6_TIMER
+
 endif
diff --git a/arch/arm/mach-meson/meson.c b/arch/arm/mach-meson/meson.c
index 5d6affe..4e23571 100644
--- a/arch/arm/mach-meson/meson.c
+++ b/arch/arm/mach-meson/meson.c
@@ -19,6 +19,7 @@
 static const char * const meson_common_board_compat[] = {
 	"amlogic,meson6",
 	"amlogic,meson8",
+	"amlogic,meson8b",
 	NULL,
 };
 
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 44eedf3..55348ee 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -40,6 +40,7 @@
 unsigned long coherency_phys_base;
 void __iomem *coherency_base;
 static void __iomem *coherency_cpu_base;
+static void __iomem *cpu_config_base;
 
 /* Coherency fabric registers */
 #define IO_SYNC_BARRIER_CTL_OFFSET		   0x0
@@ -65,6 +66,31 @@
 int ll_enable_coherency(void);
 void ll_add_cpu_to_smp_group(void);
 
+#define CPU_CONFIG_SHARED_L2 BIT(16)
+
+/*
+ * Disable the "Shared L2 Present" bit in CPU Configuration register
+ * on Armada XP.
+ *
+ * The "Shared L2 Present" bit affects the "level of coherence" value
+ * in the clidr CP15 register.  Cache operation functions such as
+ * "flush all" and "invalidate all" operate on all the cache levels
+ * that included in the defined level of coherence. When HW I/O
+ * coherency is used, this bit causes unnecessary flushes of the L2
+ * cache.
+ */
+static void armada_xp_clear_shared_l2(void)
+{
+	u32 reg;
+
+	if (!cpu_config_base)
+		return;
+
+	reg = readl(cpu_config_base);
+	reg &= ~CPU_CONFIG_SHARED_L2;
+	writel(reg, cpu_config_base);
+}
+
 static int mvebu_hwcc_notifier(struct notifier_block *nb,
 			       unsigned long event, void *__dev)
 {
@@ -85,9 +111,24 @@
 	.notifier_call = mvebu_hwcc_notifier,
 };
 
+static int armada_xp_clear_shared_l2_notifier_func(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
+{
+	if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+		armada_xp_clear_shared_l2();
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block armada_xp_clear_shared_l2_notifier = {
+	.notifier_call = armada_xp_clear_shared_l2_notifier_func,
+	.priority = 100,
+};
+
 static void __init armada_370_coherency_init(struct device_node *np)
 {
 	struct resource res;
+	struct device_node *cpu_config_np;
 
 	of_address_to_resource(np, 0, &res);
 	coherency_phys_base = res.start;
@@ -100,6 +141,23 @@
 	sync_cache_w(&coherency_phys_base);
 	coherency_base = of_iomap(np, 0);
 	coherency_cpu_base = of_iomap(np, 1);
+
+	cpu_config_np = of_find_compatible_node(NULL, NULL,
+						"marvell,armada-xp-cpu-config");
+	if (!cpu_config_np)
+		goto exit;
+
+	cpu_config_base = of_iomap(cpu_config_np, 0);
+	if (!cpu_config_base) {
+		of_node_put(cpu_config_np);
+		goto exit;
+	}
+
+	of_node_put(cpu_config_np);
+
+	register_cpu_notifier(&armada_xp_clear_shared_l2_notifier);
+
+exit:
 	set_cpu_coherent();
 }
 
@@ -204,6 +262,8 @@
 			pr_warn("Coherency fabric is not initialized\n");
 			return 1;
 		}
+
+		armada_xp_clear_shared_l2();
 		ll_add_cpu_to_smp_group();
 		return ll_enable_coherency();
 	}
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 9658b5a..ed8fda4 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -379,6 +379,16 @@
 
 static struct platform_device mvebu_v7_cpuidle_device;
 
+static int broken_idle(struct device_node *np)
+{
+	if (of_property_read_bool(np, "broken-idle")) {
+		pr_warn("CPU idle is currently broken: disabling\n");
+		return 1;
+	}
+
+	return 0;
+}
+
 static __init int armada_370_cpuidle_init(void)
 {
 	struct device_node *np;
@@ -387,7 +397,9 @@
 	np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
 	if (!np)
 		return -ENODEV;
-	of_node_put(np);
+
+	if (broken_idle(np))
+		goto end;
 
 	/*
 	 * On Armada 370, there is "a slow exit process from the deep
@@ -406,6 +418,8 @@
 	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
 	mvebu_v7_cpuidle_device.name = "cpuidle-armada-370";
 
+end:
+	of_node_put(np);
 	return 0;
 }
 
@@ -422,6 +436,10 @@
 				     "marvell,armada-380-coherency-fabric");
 	if (!np)
 		return -ENODEV;
+
+	if (broken_idle(np))
+		goto end;
+
 	of_node_put(np);
 
 	np = of_find_compatible_node(NULL, NULL,
@@ -430,7 +448,6 @@
 		return -ENODEV;
 	mpsoc_base = of_iomap(np, 0);
 	BUG_ON(!mpsoc_base);
-	of_node_put(np);
 
 	/* Set up reset mask when powering down the cpus */
 	reg = readl(mpsoc_base + MPCORE_RESET_CTL);
@@ -450,6 +467,8 @@
 	mvebu_v7_cpuidle_device.dev.platform_data = armada_38x_cpu_suspend;
 	mvebu_v7_cpuidle_device.name = "cpuidle-armada-38x";
 
+end:
+	of_node_put(np);
 	return 0;
 }
 
@@ -460,12 +479,16 @@
 	np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
 	if (!np)
 		return -ENODEV;
-	of_node_put(np);
+
+	if (broken_idle(np))
+		goto end;
 
 	mvebu_cpu_resume = armada_370_xp_cpu_resume;
 	mvebu_v7_cpuidle_device.dev.platform_data = armada_370_xp_cpu_suspend;
 	mvebu_v7_cpuidle_device.name = "cpuidle-armada-xp";
 
+end:
+	of_node_put(np);
 	return 0;
 }
 
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index 08d2be2..66f1c95 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -45,6 +45,7 @@
 
 config MACH_DNS323
 	bool "D-Link DNS-323"
+	select GENERIC_NET_UTILS
 	select I2C_BOARDINFO
 	help
 	  Say 'Y' here if you want your kernel to support the
@@ -52,6 +53,7 @@
 
 config MACH_TS209
 	bool "QNAP TS-109/TS-209"
+	select GENERIC_NET_UTILS
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  QNAP TS-109/TS-209 platform.
@@ -93,6 +95,7 @@
 
 config MACH_TS409
 	bool "QNAP TS-409"
+	select GENERIC_NET_UTILS
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  QNAP TS-409 platform.
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index f267e58..bc279a8 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -173,42 +173,10 @@
 	.phy_addr = MV643XX_ETH_PHY_ADDR(8),
 };
 
-/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these
- * functions be kept somewhere?
- */
-static int __init dns323_parse_hex_nibble(char n)
-{
-	if (n >= '0' && n <= '9')
-		return n - '0';
-
-	if (n >= 'A' && n <= 'F')
-		return n - 'A' + 10;
-
-	if (n >= 'a' && n <= 'f')
-		return n - 'a' + 10;
-
-	return -1;
-}
-
-static int __init dns323_parse_hex_byte(const char *b)
-{
-	int hi;
-	int lo;
-
-	hi = dns323_parse_hex_nibble(b[0]);
-	lo = dns323_parse_hex_nibble(b[1]);
-
-	if (hi < 0 || lo < 0)
-		return -1;
-
-	return (hi << 4) | lo;
-}
-
 static int __init dns323_read_mac_addr(void)
 {
 	u_int8_t addr[6];
-	int i;
-	char *mac_page;
+	void __iomem *mac_page;
 
 	/* MAC address is stored as a regular ol' string in /dev/mtdblock4
 	 * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80).
@@ -217,23 +185,8 @@
 	if (!mac_page)
 		return -ENOMEM;
 
-	/* Sanity check the string we're looking at */
-	for (i = 0; i < 5; i++) {
-		if (*(mac_page + (i * 3) + 2) != ':') {
-			goto error_fail;
-		}
-	}
-
-	for (i = 0; i < 6; i++)	{
-		int byte;
-
-		byte = dns323_parse_hex_byte(mac_page + (i * 3));
-		if (byte < 0) {
-			goto error_fail;
-		}
-
-		addr[i] = byte;
-	}
+	if (!mac_pton((__force const char *) mac_page, addr))
+		goto error_fail;
 
 	iounmap(mac_page);
 	printk("DNS-323: Found ethernet MAC address: %pM\n", addr);
diff --git a/arch/arm/mach-orion5x/tsx09-common.c b/arch/arm/mach-orion5x/tsx09-common.c
index 24b2959..d42e006 100644
--- a/arch/arm/mach-orion5x/tsx09-common.c
+++ b/arch/arm/mach-orion5x/tsx09-common.c
@@ -53,53 +53,12 @@
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static int __init qnap_tsx09_parse_hex_nibble(char n)
-{
-	if (n >= '0' && n <= '9')
-		return n - '0';
-
-	if (n >= 'A' && n <= 'F')
-		return n - 'A' + 10;
-
-	if (n >= 'a' && n <= 'f')
-		return n - 'a' + 10;
-
-	return -1;
-}
-
-static int __init qnap_tsx09_parse_hex_byte(const char *b)
-{
-	int hi;
-	int lo;
-
-	hi = qnap_tsx09_parse_hex_nibble(b[0]);
-	lo = qnap_tsx09_parse_hex_nibble(b[1]);
-
-	if (hi < 0 || lo < 0)
-		return -1;
-
-	return (hi << 4) | lo;
-}
-
 static int __init qnap_tsx09_check_mac_addr(const char *addr_str)
 {
 	u_int8_t addr[6];
-	int i;
 
-	for (i = 0; i < 6; i++) {
-		int byte;
-
-		/*
-		 * Enforce "xx:xx:xx:xx:xx:xx\n" format.
-		 */
-		if (addr_str[(i * 3) + 2] != ((i < 5) ? ':' : '\n'))
-			return -1;
-
-		byte = qnap_tsx09_parse_hex_byte(addr_str + (i * 3));
-		if (byte < 0)
-			return -1;
-		addr[i] = byte;
-	}
+	if (!mac_pton(addr_str, addr))
+		return -1;
 
 	printk(KERN_INFO "tsx09: found ethernet mac address %pM\n", addr);
 
@@ -118,12 +77,12 @@
 	unsigned long addr;
 
 	for (addr = mem_base; addr < (mem_base + size); addr += 1024) {
-		char *nor_page;
+		void __iomem *nor_page;
 		int ret = 0;
 
 		nor_page = ioremap(addr, 1024);
 		if (nor_page != NULL) {
-			ret = qnap_tsx09_check_mac_addr(nor_page);
+			ret = qnap_tsx09_check_mac_addr((__force const char *)nor_page);
 			iounmap(nor_page);
 		}
 
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index d40d4f5..9f54300 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
@@ -469,6 +470,11 @@
 	.ocr_avail     = MMC_VDD_32_33,
 };
 
+static struct pwm_lookup h1940_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 36296,
+		   PWM_POLARITY_NORMAL),
+};
+
 static int h1940_backlight_init(struct device *dev)
 {
 	gpio_request(S3C2410_GPB(0), "Backlight");
@@ -503,11 +509,8 @@
 
 
 static struct platform_pwm_backlight_data backlight_data = {
-	.pwm_id         = 0,
 	.max_brightness = 100,
 	.dft_brightness = 50,
-	/* tcnt = 0x31 */
-	.pwm_period_ns  = 36296,
 	.enable_gpio    = -1,
 	.init           = h1940_backlight_init,
 	.notify		= h1940_backlight_notify,
@@ -725,6 +728,7 @@
 	gpio_request(H1940_LATCH_SD_POWER, "SD power");
 	gpio_direction_output(H1940_LATCH_SD_POWER, 0);
 
+	pwm_add_table(h1940_pwm_lookup, ARRAY_SIZE(h1940_pwm_lookup));
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 
 	gpio_request(S3C2410_GPA(1), "Red LED blink");
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 1d35ff3..774c982 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -375,6 +375,11 @@
 
 };
 
+static struct pwm_lookup rx1950_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight.0", NULL, 48000,
+		   PWM_POLARITY_NORMAL),
+};
+
 static struct pwm_device *lcd_pwm;
 
 static void rx1950_lcd_power(int enable)
@@ -520,10 +525,8 @@
 }
 
 static struct platform_pwm_backlight_data rx1950_backlight_data = {
-	.pwm_id = 0,
 	.max_brightness = 24,
 	.dft_brightness = 4,
-	.pwm_period_ns = 48000,
 	.enable_gpio = -1,
 	.init = rx1950_backlight_init,
 	.notify = rx1950_backlight_notify,
@@ -792,6 +795,7 @@
 	gpio_direction_output(S3C2410_GPA(4), 0);
 	gpio_direction_output(S3C2410_GPJ(6), 0);
 
+	pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup));
 	platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
 
 	i2c_register_board_info(0, rx1950_i2c_devices,
diff --git a/arch/arm/mach-s3c64xx/dev-backlight.c b/arch/arm/mach-s3c64xx/dev-backlight.c
index 38c323e..e62e789 100644
--- a/arch/arm/mach-s3c64xx/dev-backlight.c
+++ b/arch/arm/mach-s3c64xx/dev-backlight.c
@@ -69,7 +69,6 @@
 	.plat_data = {
 		.max_brightness = 255,
 		.dft_brightness = 255,
-		.pwm_period_ns  = 78770,
 		.enable_gpio    = -1,
 		.init           = samsung_bl_init,
 		.exit           = samsung_bl_exit,
@@ -111,7 +110,6 @@
 	samsung_bl_data = &samsung_bl_drvdata->plat_data;
 
 	/* Copy board specific data provided by user */
-	samsung_bl_data->pwm_id = bl_data->pwm_id;
 	samsung_bl_device->dev.parent = &samsung_device_pwm.dev;
 
 	if (bl_data->max_brightness)
@@ -120,8 +118,6 @@
 		samsung_bl_data->dft_brightness = bl_data->dft_brightness;
 	if (bl_data->lth_brightness)
 		samsung_bl_data->lth_brightness = bl_data->lth_brightness;
-	if (bl_data->pwm_period_ns)
-		samsung_bl_data->pwm_period_ns = bl_data->pwm_period_ns;
 	if (bl_data->enable_gpio >= 0)
 		samsung_bl_data->enable_gpio = bl_data->enable_gpio;
 	if (bl_data->init)
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 14bd9ae..f776adc 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -25,6 +25,7 @@
 #include <linux/mmc/host.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/dm9000.h>
 #include <linux/gpio_keys.h>
@@ -108,11 +109,14 @@
 	},
 };
 
+static struct pwm_lookup crag6410_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 100000,
+		   PWM_POLARITY_NORMAL),
+};
+
 static struct platform_pwm_backlight_data crag6410_backlight_data = {
-	.pwm_id		= 0,
 	.max_brightness	= 1000,
 	.dft_brightness	= 600,
-	.pwm_period_ns	= 100000,	/* about 1kHz */
 	.enable_gpio	= -1,
 };
 
@@ -843,6 +847,7 @@
 	samsung_keypad_set_platdata(&crag6410_keypad_data);
 	s3c64xx_spi0_set_platdata(NULL, 0, 2);
 
+	pwm_add_table(crag6410_pwm_lookup, ARRAY_SIZE(crag6410_pwm_lookup));
 	platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
 	gpio_led_register_device(-1, &gpio_leds_pdata);
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index e4b087c..816b39d 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/leds.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -73,6 +74,11 @@
 	},
 };
 
+static struct pwm_lookup hmt_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
+		   1000000000 / (100 * 256 * 20), PWM_POLARITY_NORMAL),
+};
+
 static int hmt_bl_init(struct device *dev)
 {
 	int ret;
@@ -110,10 +116,8 @@
 }
 
 static struct platform_pwm_backlight_data hmt_backlight_data = {
-	.pwm_id		= 1,
 	.max_brightness	= 100 * 256,
 	.dft_brightness	= 40 * 256,
-	.pwm_period_ns	= 1000000000 / (100 * 256 * 20),
 	.enable_gpio	= -1,
 	.init		= hmt_bl_init,
 	.notify		= hmt_bl_notify,
@@ -268,6 +272,7 @@
 	gpio_request(S3C64XX_GPF(13), "usb power");
 	gpio_direction_output(S3C64XX_GPF(13), 1);
 
+	pwm_add_table(hmt_pwm_lookup, ARRAY_SIZE(hmt_pwm_lookup));
 	platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices));
 }
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 719843d..acdfb5f 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -14,6 +14,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/serial_core.h>
 #include <linux/serial_s3c.h>
@@ -139,6 +140,11 @@
 	.dev.platform_data	= &smartq_usb_otg_vbus_pdata,
 };
 
+static struct pwm_lookup smartq_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL,
+		   1000000000 / (1000 * 20), PWM_POLARITY_NORMAL),
+};
+
 static int smartq_bl_init(struct device *dev)
 {
     s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
@@ -147,10 +153,8 @@
 }
 
 static struct platform_pwm_backlight_data smartq_backlight_data = {
-	.pwm_id		= 1,
 	.max_brightness	= 1000,
 	.dft_brightness	= 600,
-	.pwm_period_ns	= 1000000000 / (1000 * 20),
 	.enable_gpio	= -1,
 	.init		= smartq_bl_init,
 };
@@ -396,5 +400,6 @@
 	WARN_ON(smartq_usb_host_init());
 	WARN_ON(smartq_wifi_init());
 
+	pwm_add_table(smartq_pwm_lookup, ARRAY_SIZE(smartq_pwm_lookup));
 	platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
 }
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 286c9bd..30fd278 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -30,6 +30,7 @@
 #include <linux/smsc911x.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
@@ -623,8 +624,12 @@
 	.func = S3C_GPIO_SFN(2),
 };
 
+static struct pwm_lookup smdk6410_pwm_lookup[] = {
+	PWM_LOOKUP("samsung-pwm", 1, "pwm-backlight.0", NULL, 78770,
+		   PWM_POLARITY_NORMAL),
+};
+
 static struct platform_pwm_backlight_data smdk6410_bl_data = {
-	.pwm_id = 1,
 	.enable_gpio = -1,
 };
 
@@ -695,6 +700,7 @@
 
 	platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
 
+	pwm_add_table(smdk6410_pwm_lookup, ARRAY_SIZE(smdk6410_pwm_lookup));
 	samsung_bl_set(&smdk6410_bl_gpio_info, &smdk6410_bl_data);
 }
 
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
index 424155b..46d0a1d 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.c
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -12,6 +12,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#include <linux/clk/shmobile.h>
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/of.h>
@@ -124,36 +125,6 @@
 	return true;
 }
 
-static int rmobile_pd_attach_dev(struct generic_pm_domain *domain,
-				 struct device *dev)
-{
-	int error;
-
-	error = pm_clk_create(dev);
-	if (error) {
-		dev_err(dev, "pm_clk_create failed %d\n", error);
-		return error;
-	}
-
-	error = pm_clk_add(dev, NULL);
-	if (error) {
-		dev_err(dev, "pm_clk_add failed %d\n", error);
-		goto fail;
-	}
-
-	return 0;
-
-fail:
-	pm_clk_destroy(dev);
-	return error;
-}
-
-static void rmobile_pd_detach_dev(struct generic_pm_domain *domain,
-				  struct device *dev)
-{
-	pm_clk_destroy(dev);
-}
-
 static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
 {
 	struct generic_pm_domain *genpd = &rmobile_pd->genpd;
@@ -164,8 +135,8 @@
 	genpd->dev_ops.active_wakeup	= rmobile_pd_active_wakeup;
 	genpd->power_off		= rmobile_pd_power_down;
 	genpd->power_on			= rmobile_pd_power_up;
-	genpd->attach_dev		= rmobile_pd_attach_dev;
-	genpd->detach_dev		= rmobile_pd_detach_dev;
+	genpd->attach_dev		= cpg_mstp_attach_dev;
+	genpd->detach_dev		= cpg_mstp_detach_dev;
 	__rmobile_pd_power_up(rmobile_pd, false);
 }
 
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index 223c9e9..c2be98f 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -26,10 +26,11 @@
 	"allwinner,sun4i-a10",
 	"allwinner,sun5i-a10s",
 	"allwinner,sun5i-a13",
+	"allwinner,sun5i-r8",
 	NULL,
 };
 
-DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
+DT_MACHINE_START(SUNXI_DT, "Allwinner sun4i/sun5i Families")
 	.dt_compat	= sunxi_board_dt_compat,
 	.init_late	= sunxi_dt_cpufreq_init,
 MACHINE_END
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index fbe74c6..49d1110 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -39,8 +39,8 @@
 static struct gpiod_lookup_table wifi_gpio_lookup = {
 	.dev_id = "rfkill_gpio",
 	.table = {
-		GPIO_LOOKUP_IDX("tegra-gpio", 25, NULL, 0, 0),
-		GPIO_LOOKUP_IDX("tegra-gpio", 85, NULL, 1, 0),
+		GPIO_LOOKUP("tegra-gpio", 25, "reset", 0),
+		GPIO_LOOKUP("tegra-gpio", 85, "shutdown", 0),
 		{ },
 	},
 };
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile
index 60bd226..1233f9b 100644
--- a/arch/arm/mach-uniphier/Makefile
+++ b/arch/arm/mach-uniphier/Makefile
@@ -1,2 +1,2 @@
 obj-y			:= uniphier.o
-obj-$(CONFIG_SMP)	+= platsmp.o
+obj-$(CONFIG_SMP)	+= platsmp.o headsmp.o
diff --git a/arch/arm/mach-uniphier/headsmp.S b/arch/arm/mach-uniphier/headsmp.S
new file mode 100644
index 0000000..c819dff
--- /dev/null
+++ b/arch/arm/mach-uniphier/headsmp.S
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/cp15.h>
+
+ENTRY(uniphier_smp_trampoline)
+ARM_BE8(setend	be)			@ ensure we are in BE8 mode
+	mrc	p15, 0, r0, c0, c0, 5	@ MPIDR (Multiprocessor Affinity Reg)
+	and  	r2, r0, #0x3		@ CPU ID
+	ldr	r1, uniphier_smp_trampoline_jump
+	ldr	r3, uniphier_smp_trampoline_poll_addr
+	mrc	p15, 0, r0, c1, c0, 0	@ SCTLR (System Control Register)
+	orr	r0, r0, #CR_I		@ Enable ICache
+	bic	r0, r0, #(CR_C | CR_M)	@ Disable MMU and Dcache
+	mcr	p15, 0, r0, c1, c0, 0
+	b	1f			@ cache the following 5 instructions
+0:	wfe
+1:	ldr	r0, [r3]
+	cmp	r0, r2
+	bxeq	r1			@ branch to secondary_startup
+	b	0b
+	.globl	uniphier_smp_trampoline_jump
+uniphier_smp_trampoline_jump:
+	.word	0			@ set virt_to_phys(secondary_startup)
+	.globl	uniphier_smp_trampoline_poll_addr
+uniphier_smp_trampoline_poll_addr:
+	.word	0			@ set CPU ID to be kicked to this reg
+	.globl	uniphier_smp_trampoline_end
+uniphier_smp_trampoline_end:
+ENDPROC(uniphier_smp_trampoline)
diff --git a/arch/arm/mach-uniphier/platsmp.c b/arch/arm/mach-uniphier/platsmp.c
index 4b784f7..f057766 100644
--- a/arch/arm/mach-uniphier/platsmp.c
+++ b/arch/arm/mach-uniphier/platsmp.c
@@ -12,73 +12,198 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/sizes.h>
-#include <linux/compiler.h>
+#define pr_fmt(fmt)		"uniphier: " fmt
+
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/regmap.h>
-#include <linux/mfd/syscon.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/sizes.h>
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-uniphier.h>
+#include <asm/pgtable.h>
 #include <asm/smp.h>
 #include <asm/smp_scu.h>
 
-static struct regmap *sbcm_regmap;
+/*
+ * The secondary CPUs check this register from the boot ROM for the jump
+ * destination.  After that, it can be reused as a scratch register.
+ */
+#define UNIPHIER_SBC_ROM_BOOT_RSV2	0x1208
 
-static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
+static void __iomem *uniphier_smp_rom_boot_rsv2;
+static unsigned int uniphier_smp_max_cpus;
+
+extern char uniphier_smp_trampoline;
+extern char uniphier_smp_trampoline_jump;
+extern char uniphier_smp_trampoline_poll_addr;
+extern char uniphier_smp_trampoline_end;
+
+/*
+ * Copy trampoline code to the tail of the 1st section of the page table used
+ * in the boot ROM.  This area is directly accessible by the secondary CPUs
+ * for all the UniPhier SoCs.
+ */
+static const phys_addr_t uniphier_smp_trampoline_dest_end = SECTION_SIZE;
+static phys_addr_t uniphier_smp_trampoline_dest;
+
+static int __init uniphier_smp_copy_trampoline(phys_addr_t poll_addr)
 {
-	static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
+	size_t trmp_size;
+	static void __iomem *trmp_base;
+
+	if (!uniphier_cache_l2_is_enabled()) {
+		pr_warn("outer cache is needed for SMP, but not enabled\n");
+		return -ENODEV;
+	}
+
+	uniphier_cache_l2_set_locked_ways(1);
+
+	outer_flush_all();
+
+	trmp_size = &uniphier_smp_trampoline_end - &uniphier_smp_trampoline;
+	uniphier_smp_trampoline_dest = uniphier_smp_trampoline_dest_end -
+								trmp_size;
+
+	uniphier_cache_l2_touch_range(uniphier_smp_trampoline_dest,
+				      uniphier_smp_trampoline_dest_end);
+
+	trmp_base = ioremap_cache(uniphier_smp_trampoline_dest, trmp_size);
+	if (!trmp_base) {
+		pr_err("failed to map trampoline destination area\n");
+		return -ENOMEM;
+	}
+
+	memcpy(trmp_base, &uniphier_smp_trampoline, trmp_size);
+
+	writel(virt_to_phys(secondary_startup),
+	       trmp_base + (&uniphier_smp_trampoline_jump -
+			    &uniphier_smp_trampoline));
+
+	writel(poll_addr, trmp_base + (&uniphier_smp_trampoline_poll_addr -
+				       &uniphier_smp_trampoline));
+
+	flush_cache_all();	/* flush out trampoline code to outer cache */
+
+	iounmap(trmp_base);
+
+	return 0;
+}
+
+static int __init uniphier_smp_prepare_trampoline(unsigned int max_cpus)
+{
+	struct device_node *np;
+	struct resource res;
+	phys_addr_t rom_rsv2_phys;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL,
+				"socionext,uniphier-system-bus-controller");
+	ret = of_address_to_resource(np, 1, &res);
+	if (ret) {
+		pr_err("failed to get resource of system-bus-controller\n");
+		return ret;
+	}
+
+	rom_rsv2_phys = res.start + UNIPHIER_SBC_ROM_BOOT_RSV2;
+
+	ret = uniphier_smp_copy_trampoline(rom_rsv2_phys);
+	if (ret)
+		return ret;
+
+	uniphier_smp_rom_boot_rsv2 = ioremap(rom_rsv2_phys, sizeof(SZ_4));
+	if (!uniphier_smp_rom_boot_rsv2) {
+		pr_err("failed to map ROM_BOOT_RSV2 register\n");
+		return -ENOMEM;
+	}
+
+	writel(uniphier_smp_trampoline_dest, uniphier_smp_rom_boot_rsv2);
+	asm("sev"); /* Bring up all secondary CPUs to the trampoline code */
+
+	uniphier_smp_max_cpus = max_cpus;	/* save for later use */
+
+	return 0;
+}
+
+static void __init uniphier_smp_unprepare_trampoline(void)
+{
+	iounmap(uniphier_smp_rom_boot_rsv2);
+
+	if (uniphier_smp_trampoline_dest)
+		outer_inv_range(uniphier_smp_trampoline_dest,
+				uniphier_smp_trampoline_dest_end);
+
+	uniphier_cache_l2_set_locked_ways(0);
+}
+
+static int __init uniphier_smp_enable_scu(void)
+{
 	unsigned long scu_base_phys = 0;
 	void __iomem *scu_base;
 
-	sbcm_regmap = syscon_regmap_lookup_by_compatible(
-			"socionext,uniphier-system-bus-controller-misc");
-	if (IS_ERR(sbcm_regmap)) {
-		pr_err("failed to regmap system-bus-controller-misc\n");
-		goto err;
-	}
-
 	if (scu_a9_has_base())
 		scu_base_phys = scu_a9_get_base();
 
 	if (!scu_base_phys) {
 		pr_err("failed to get scu base\n");
-		goto err;
+		return -ENODEV;
 	}
 
 	scu_base = ioremap(scu_base_phys, SZ_128);
 	if (!scu_base) {
-		pr_err("failed to remap scu base (0x%08lx)\n", scu_base_phys);
-		goto err;
+		pr_err("failed to map scu base\n");
+		return -ENOMEM;
 	}
 
 	scu_enable(scu_base);
 	iounmap(scu_base);
 
+	return 0;
+}
+
+static void __init uniphier_smp_prepare_cpus(unsigned int max_cpus)
+{
+	static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
+	int ret;
+
+	ret = uniphier_smp_prepare_trampoline(max_cpus);
+	if (ret)
+		goto err;
+
+	ret = uniphier_smp_enable_scu();
+	if (ret)
+		goto err;
+
 	return;
 err:
 	pr_warn("disabling SMP\n");
 	init_cpu_present(&only_cpu_0);
-	sbcm_regmap = NULL;
+	uniphier_smp_unprepare_trampoline();
 }
 
-static int uniphier_boot_secondary(unsigned int cpu,
-				   struct task_struct *idle)
+static int __init uniphier_smp_boot_secondary(unsigned int cpu,
+					      struct task_struct *idle)
 {
-	int ret;
+	if (WARN_ON_ONCE(!uniphier_smp_rom_boot_rsv2))
+		return -EFAULT;
 
-	if (!sbcm_regmap)
-		return -ENODEV;
+	writel(cpu, uniphier_smp_rom_boot_rsv2);
+	readl(uniphier_smp_rom_boot_rsv2); /* relax */
 
-	ret = regmap_write(sbcm_regmap, 0x1208,
-			   virt_to_phys(secondary_startup));
-	if (!ret)
-		asm("sev"); /* wake up secondary CPU */
+	asm("sev"); /* wake up secondary CPUs sleeping in the trampoline */
 
-	return ret;
+	if (cpu == uniphier_smp_max_cpus - 1) {
+		/* clean up resources if this is the last CPU */
+		uniphier_smp_unprepare_trampoline();
+	}
+
+	return 0;
 }
 
-struct smp_operations uniphier_smp_ops __initdata = {
+static struct smp_operations uniphier_smp_ops __initdata = {
 	.smp_prepare_cpus	= uniphier_smp_prepare_cpus,
-	.smp_boot_secondary	= uniphier_boot_secondary,
+	.smp_boot_secondary	= uniphier_smp_boot_secondary,
 };
 CPU_METHOD_OF_DECLARE(uniphier_smp, "socionext,uniphier-smp",
 		      &uniphier_smp_ops);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c219413..4121886 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -974,6 +974,16 @@
 	  This option enables the Tauros2 L2 cache controller (as
 	  found on PJ1/PJ4).
 
+config CACHE_UNIPHIER
+	bool "Enable the UniPhier outer cache controller"
+	depends on ARCH_UNIPHIER
+	default y
+	select OUTER_CACHE
+	select OUTER_CACHE_SYNC
+	help
+	  This option enables the UniPhier outer cache (system cache)
+	  controller.
+
 config CACHE_XSC3L2
 	bool "Enable the L2 cache on XScale3"
 	depends on CPU_XSC3
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 57c8df5..7f76d96 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -103,3 +103,4 @@
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o l2c-l2x0-resume.o
 obj-$(CONFIG_CACHE_XSC3L2)	+= cache-xsc3l2.o
 obj-$(CONFIG_CACHE_TAUROS2)	+= cache-tauros2.o
+obj-$(CONFIG_CACHE_UNIPHIER)	+= cache-uniphier.o
diff --git a/arch/arm/mm/cache-uniphier.c b/arch/arm/mm/cache-uniphier.c
new file mode 100644
index 0000000..0502ba1
--- /dev/null
+++ b/arch/arm/mm/cache-uniphier.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)		"uniphier: " fmt
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <asm/hardware/cache-uniphier.h>
+#include <asm/outercache.h>
+
+/* control registers */
+#define UNIPHIER_SSCC		0x0	/* Control Register */
+#define    UNIPHIER_SSCC_BST			BIT(20)	/* UCWG burst read */
+#define    UNIPHIER_SSCC_ACT			BIT(19)	/* Inst-Data separate */
+#define    UNIPHIER_SSCC_WTG			BIT(18)	/* WT gathering on */
+#define    UNIPHIER_SSCC_PRD			BIT(17)	/* enable pre-fetch */
+#define    UNIPHIER_SSCC_ON			BIT(0)	/* enable cache */
+#define UNIPHIER_SSCLPDAWCR	0x30	/* Unified/Data Active Way Control */
+#define UNIPHIER_SSCLPIAWCR	0x34	/* Instruction Active Way Control */
+
+/* revision registers */
+#define UNIPHIER_SSCID		0x0	/* ID Register */
+
+/* operation registers */
+#define UNIPHIER_SSCOPE		0x244	/* Cache Operation Primitive Entry */
+#define    UNIPHIER_SSCOPE_CM_INV		0x0	/* invalidate */
+#define    UNIPHIER_SSCOPE_CM_CLEAN		0x1	/* clean */
+#define    UNIPHIER_SSCOPE_CM_FLUSH		0x2	/* flush */
+#define    UNIPHIER_SSCOPE_CM_SYNC		0x8	/* sync (drain bufs) */
+#define    UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH	0x9	/* flush p-fetch buf */
+#define UNIPHIER_SSCOQM		0x248	/* Cache Operation Queue Mode */
+#define    UNIPHIER_SSCOQM_TID_MASK		(0x3 << 21)
+#define    UNIPHIER_SSCOQM_TID_LRU_DATA		(0x0 << 21)
+#define    UNIPHIER_SSCOQM_TID_LRU_INST		(0x1 << 21)
+#define    UNIPHIER_SSCOQM_TID_WAY		(0x2 << 21)
+#define    UNIPHIER_SSCOQM_S_MASK		(0x3 << 17)
+#define    UNIPHIER_SSCOQM_S_RANGE		(0x0 << 17)
+#define    UNIPHIER_SSCOQM_S_ALL		(0x1 << 17)
+#define    UNIPHIER_SSCOQM_S_WAY		(0x2 << 17)
+#define    UNIPHIER_SSCOQM_CE			BIT(15)	/* notify completion */
+#define    UNIPHIER_SSCOQM_CM_INV		0x0	/* invalidate */
+#define    UNIPHIER_SSCOQM_CM_CLEAN		0x1	/* clean */
+#define    UNIPHIER_SSCOQM_CM_FLUSH		0x2	/* flush */
+#define    UNIPHIER_SSCOQM_CM_PREFETCH		0x3	/* prefetch to cache */
+#define    UNIPHIER_SSCOQM_CM_PREFETCH_BUF	0x4	/* prefetch to pf-buf */
+#define    UNIPHIER_SSCOQM_CM_TOUCH		0x5	/* touch */
+#define    UNIPHIER_SSCOQM_CM_TOUCH_ZERO	0x6	/* touch to zero */
+#define    UNIPHIER_SSCOQM_CM_TOUCH_DIRTY	0x7	/* touch with dirty */
+#define UNIPHIER_SSCOQAD	0x24c	/* Cache Operation Queue Address */
+#define UNIPHIER_SSCOQSZ	0x250	/* Cache Operation Queue Size */
+#define UNIPHIER_SSCOQMASK	0x254	/* Cache Operation Queue Address Mask */
+#define UNIPHIER_SSCOQWN	0x258	/* Cache Operation Queue Way Number */
+#define UNIPHIER_SSCOPPQSEF	0x25c	/* Cache Operation Queue Set Complete*/
+#define    UNIPHIER_SSCOPPQSEF_FE		BIT(1)
+#define    UNIPHIER_SSCOPPQSEF_OE		BIT(0)
+#define UNIPHIER_SSCOLPQS	0x260	/* Cache Operation Queue Status */
+#define    UNIPHIER_SSCOLPQS_EF			BIT(2)
+#define    UNIPHIER_SSCOLPQS_EST		BIT(1)
+#define    UNIPHIER_SSCOLPQS_QST		BIT(0)
+
+/* Is the touch/pre-fetch destination specified by ways? */
+#define UNIPHIER_SSCOQM_TID_IS_WAY(op) \
+		((op & UNIPHIER_SSCOQM_TID_MASK) == UNIPHIER_SSCOQM_TID_WAY)
+/* Is the operation region specified by address range? */
+#define UNIPHIER_SSCOQM_S_IS_RANGE(op) \
+		((op & UNIPHIER_SSCOQM_S_MASK) == UNIPHIER_SSCOQM_S_RANGE)
+
+/**
+ * uniphier_cache_data - UniPhier outer cache specific data
+ *
+ * @ctrl_base: virtual base address of control registers
+ * @rev_base: virtual base address of revision registers
+ * @op_base: virtual base address of operation registers
+ * @way_present_mask: each bit specifies if the way is present
+ * @way_locked_mask: each bit specifies if the way is locked
+ * @nsets: number of associativity sets
+ * @line_size: line size in bytes
+ * @range_op_max_size: max size that can be handled by a single range operation
+ * @list: list node to include this level in the whole cache hierarchy
+ */
+struct uniphier_cache_data {
+	void __iomem *ctrl_base;
+	void __iomem *rev_base;
+	void __iomem *op_base;
+	u32 way_present_mask;
+	u32 way_locked_mask;
+	u32 nsets;
+	u32 line_size;
+	u32 range_op_max_size;
+	struct list_head list;
+};
+
+/*
+ * List of the whole outer cache hierarchy.  This list is only modified during
+ * the early boot stage, so no mutex is taken for the access to the list.
+ */
+static LIST_HEAD(uniphier_cache_list);
+
+/**
+ * __uniphier_cache_sync - perform a sync point for a particular cache level
+ *
+ * @data: cache controller specific data
+ */
+static void __uniphier_cache_sync(struct uniphier_cache_data *data)
+{
+	/* This sequence need not be atomic.  Do not disable IRQ. */
+	writel_relaxed(UNIPHIER_SSCOPE_CM_SYNC,
+		       data->op_base + UNIPHIER_SSCOPE);
+	/* need a read back to confirm */
+	readl_relaxed(data->op_base + UNIPHIER_SSCOPE);
+}
+
+/**
+ * __uniphier_cache_maint_common - run a queue operation for a particular level
+ *
+ * @data: cache controller specific data
+ * @start: start address of range operation (don't care for "all" operation)
+ * @size: data size of range operation (don't care for "all" operation)
+ * @operation: flags to specify the desired cache operation
+ */
+static void __uniphier_cache_maint_common(struct uniphier_cache_data *data,
+					  unsigned long start,
+					  unsigned long size,
+					  u32 operation)
+{
+	unsigned long flags;
+
+	/*
+	 * No spin lock is necessary here because:
+	 *
+	 * [1] This outer cache controller is able to accept maintenance
+	 * operations from multiple CPUs at a time in an SMP system; if a
+	 * maintenance operation is under way and another operation is issued,
+	 * the new one is stored in the queue.  The controller performs one
+	 * operation after another.  If the queue is full, the status register,
+	 * UNIPHIER_SSCOPPQSEF, indicates that the queue registration has
+	 * failed.  The status registers, UNIPHIER_{SSCOPPQSEF, SSCOLPQS}, have
+	 * different instances for each CPU, i.e. each CPU can track the status
+	 * of the maintenance operations triggered by itself.
+	 *
+	 * [2] The cache command registers, UNIPHIER_{SSCOQM, SSCOQAD, SSCOQSZ,
+	 * SSCOQWN}, are shared between multiple CPUs, but the hardware still
+	 * guarantees the registration sequence is atomic; the write access to
+	 * them are arbitrated by the hardware.  The first accessor to the
+	 * register, UNIPHIER_SSCOQM, holds the access right and it is released
+	 * by reading the status register, UNIPHIER_SSCOPPQSEF.  While one CPU
+	 * is holding the access right, other CPUs fail to register operations.
+	 * One CPU should not hold the access right for a long time, so local
+	 * IRQs should be disabled while the following sequence.
+	 */
+	local_irq_save(flags);
+
+	/* clear the complete notification flag */
+	writel_relaxed(UNIPHIER_SSCOLPQS_EF, data->op_base + UNIPHIER_SSCOLPQS);
+
+	do {
+		/* set cache operation */
+		writel_relaxed(UNIPHIER_SSCOQM_CE | operation,
+			       data->op_base + UNIPHIER_SSCOQM);
+
+		/* set address range if needed */
+		if (likely(UNIPHIER_SSCOQM_S_IS_RANGE(operation))) {
+			writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD);
+			writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ);
+		}
+
+		/* set target ways if needed */
+		if (unlikely(UNIPHIER_SSCOQM_TID_IS_WAY(operation)))
+			writel_relaxed(data->way_locked_mask,
+				       data->op_base + UNIPHIER_SSCOQWN);
+	} while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) &
+			  (UNIPHIER_SSCOPPQSEF_FE | UNIPHIER_SSCOPPQSEF_OE)));
+
+	/* wait until the operation is completed */
+	while (likely(readl_relaxed(data->op_base + UNIPHIER_SSCOLPQS) !=
+		      UNIPHIER_SSCOLPQS_EF))
+		cpu_relax();
+
+	local_irq_restore(flags);
+}
+
+static void __uniphier_cache_maint_all(struct uniphier_cache_data *data,
+				       u32 operation)
+{
+	__uniphier_cache_maint_common(data, 0, 0,
+				      UNIPHIER_SSCOQM_S_ALL | operation);
+
+	__uniphier_cache_sync(data);
+}
+
+static void __uniphier_cache_maint_range(struct uniphier_cache_data *data,
+					 unsigned long start, unsigned long end,
+					 u32 operation)
+{
+	unsigned long size;
+
+	/*
+	 * If the start address is not aligned,
+	 * perform a cache operation for the first cache-line
+	 */
+	start = start & ~(data->line_size - 1);
+
+	size = end - start;
+
+	if (unlikely(size >= (unsigned long)(-data->line_size))) {
+		/* this means cache operation for all range */
+		__uniphier_cache_maint_all(data, operation);
+		return;
+	}
+
+	/*
+	 * If the end address is not aligned,
+	 * perform a cache operation for the last cache-line
+	 */
+	size = ALIGN(size, data->line_size);
+
+	while (size) {
+		unsigned long chunk_size = min_t(unsigned long, size,
+						 data->range_op_max_size);
+
+		__uniphier_cache_maint_common(data, start, chunk_size,
+					UNIPHIER_SSCOQM_S_RANGE | operation);
+
+		start += chunk_size;
+		size -= chunk_size;
+	}
+
+	__uniphier_cache_sync(data);
+}
+
+static void __uniphier_cache_enable(struct uniphier_cache_data *data, bool on)
+{
+	u32 val = 0;
+
+	if (on)
+		val = UNIPHIER_SSCC_WTG | UNIPHIER_SSCC_PRD | UNIPHIER_SSCC_ON;
+
+	writel_relaxed(val, data->ctrl_base + UNIPHIER_SSCC);
+}
+
+static void __init __uniphier_cache_set_locked_ways(
+					struct uniphier_cache_data *data,
+					u32 way_mask)
+{
+	data->way_locked_mask = way_mask & data->way_present_mask;
+
+	writel_relaxed(~data->way_locked_mask & data->way_present_mask,
+		       data->ctrl_base + UNIPHIER_SSCLPDAWCR);
+}
+
+static void uniphier_cache_maint_range(unsigned long start, unsigned long end,
+				       u32 operation)
+{
+	struct uniphier_cache_data *data;
+
+	list_for_each_entry(data, &uniphier_cache_list, list)
+		__uniphier_cache_maint_range(data, start, end, operation);
+}
+
+static void uniphier_cache_maint_all(u32 operation)
+{
+	struct uniphier_cache_data *data;
+
+	list_for_each_entry(data, &uniphier_cache_list, list)
+		__uniphier_cache_maint_all(data, operation);
+}
+
+static void uniphier_cache_inv_range(unsigned long start, unsigned long end)
+{
+	uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_INV);
+}
+
+static void uniphier_cache_clean_range(unsigned long start, unsigned long end)
+{
+	uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_CLEAN);
+}
+
+static void uniphier_cache_flush_range(unsigned long start, unsigned long end)
+{
+	uniphier_cache_maint_range(start, end, UNIPHIER_SSCOQM_CM_FLUSH);
+}
+
+static void __init uniphier_cache_inv_all(void)
+{
+	uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_INV);
+}
+
+static void uniphier_cache_flush_all(void)
+{
+	uniphier_cache_maint_all(UNIPHIER_SSCOQM_CM_FLUSH);
+}
+
+static void uniphier_cache_disable(void)
+{
+	struct uniphier_cache_data *data;
+
+	list_for_each_entry_reverse(data, &uniphier_cache_list, list)
+		__uniphier_cache_enable(data, false);
+
+	uniphier_cache_flush_all();
+}
+
+static void __init uniphier_cache_enable(void)
+{
+	struct uniphier_cache_data *data;
+
+	uniphier_cache_inv_all();
+
+	list_for_each_entry(data, &uniphier_cache_list, list) {
+		__uniphier_cache_enable(data, true);
+		__uniphier_cache_set_locked_ways(data, 0);
+	}
+}
+
+static void uniphier_cache_sync(void)
+{
+	struct uniphier_cache_data *data;
+
+	list_for_each_entry(data, &uniphier_cache_list, list)
+		__uniphier_cache_sync(data);
+}
+
+int __init uniphier_cache_l2_is_enabled(void)
+{
+	struct uniphier_cache_data *data;
+
+	data = list_first_entry_or_null(&uniphier_cache_list,
+					struct uniphier_cache_data, list);
+	if (!data)
+		return 0;
+
+	return !!(readl_relaxed(data->ctrl_base + UNIPHIER_SSCC) &
+		  UNIPHIER_SSCC_ON);
+}
+
+void __init uniphier_cache_l2_touch_range(unsigned long start,
+					  unsigned long end)
+{
+	struct uniphier_cache_data *data;
+
+	data = list_first_entry_or_null(&uniphier_cache_list,
+					struct uniphier_cache_data, list);
+	if (data)
+		__uniphier_cache_maint_range(data, start, end,
+					     UNIPHIER_SSCOQM_TID_WAY |
+					     UNIPHIER_SSCOQM_CM_TOUCH);
+}
+
+void __init uniphier_cache_l2_set_locked_ways(u32 way_mask)
+{
+	struct uniphier_cache_data *data;
+
+	data = list_first_entry_or_null(&uniphier_cache_list,
+					struct uniphier_cache_data, list);
+	if (data)
+		__uniphier_cache_set_locked_ways(data, way_mask);
+}
+
+static const struct of_device_id uniphier_cache_match[] __initconst = {
+	{
+		.compatible = "socionext,uniphier-system-cache",
+	},
+	{ /* sentinel */ }
+};
+
+static struct device_node * __init uniphier_cache_get_next_level_node(
+							struct device_node *np)
+{
+	u32 phandle;
+
+	if (of_property_read_u32(np, "next-level-cache", &phandle))
+		return NULL;
+
+	return of_find_node_by_phandle(phandle);
+}
+
+static int __init __uniphier_cache_init(struct device_node *np,
+					unsigned int *cache_level)
+{
+	struct uniphier_cache_data *data;
+	u32 level, cache_size;
+	struct device_node *next_np;
+	int ret = 0;
+
+	if (!of_match_node(uniphier_cache_match, np)) {
+		pr_err("L%d: not compatible with uniphier cache\n",
+		       *cache_level);
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(np, "cache-level", &level)) {
+		pr_err("L%d: cache-level is not specified\n", *cache_level);
+		return -EINVAL;
+	}
+
+	if (level != *cache_level) {
+		pr_err("L%d: cache-level is unexpected value %d\n",
+		       *cache_level, level);
+		return -EINVAL;
+	}
+
+	if (!of_property_read_bool(np, "cache-unified")) {
+		pr_err("L%d: cache-unified is not specified\n", *cache_level);
+		return -EINVAL;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (of_property_read_u32(np, "cache-line-size", &data->line_size) ||
+	    !is_power_of_2(data->line_size)) {
+		pr_err("L%d: cache-line-size is unspecified or invalid\n",
+		       *cache_level);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (of_property_read_u32(np, "cache-sets", &data->nsets) ||
+	    !is_power_of_2(data->nsets)) {
+		pr_err("L%d: cache-sets is unspecified or invalid\n",
+		       *cache_level);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (of_property_read_u32(np, "cache-size", &cache_size) ||
+	    cache_size == 0 || cache_size % (data->nsets * data->line_size)) {
+		pr_err("L%d: cache-size is unspecified or invalid\n",
+		       *cache_level);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	data->way_present_mask =
+		((u32)1 << cache_size / data->nsets / data->line_size) - 1;
+
+	data->ctrl_base = of_iomap(np, 0);
+	if (!data->ctrl_base) {
+		pr_err("L%d: failed to map control register\n", *cache_level);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	data->rev_base = of_iomap(np, 1);
+	if (!data->rev_base) {
+		pr_err("L%d: failed to map revision register\n", *cache_level);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	data->op_base = of_iomap(np, 2);
+	if (!data->op_base) {
+		pr_err("L%d: failed to map operation register\n", *cache_level);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (*cache_level == 2) {
+		u32 revision = readl(data->rev_base + UNIPHIER_SSCID);
+		/*
+		 * The size of range operation is limited to (1 << 22) or less
+		 * for PH-sLD8 or older SoCs.
+		 */
+		if (revision <= 0x16)
+			data->range_op_max_size = (u32)1 << 22;
+	}
+
+	data->range_op_max_size -= data->line_size;
+
+	INIT_LIST_HEAD(&data->list);
+	list_add_tail(&data->list, &uniphier_cache_list); /* no mutex */
+
+	/*
+	 * OK, this level has been successfully initialized.  Look for the next
+	 * level cache.  Do not roll back even if the initialization of the
+	 * next level cache fails because we want to continue with available
+	 * cache levels.
+	 */
+	next_np = uniphier_cache_get_next_level_node(np);
+	if (next_np) {
+		(*cache_level)++;
+		ret = __uniphier_cache_init(next_np, cache_level);
+	}
+	of_node_put(next_np);
+
+	return ret;
+err:
+	iounmap(data->op_base);
+	iounmap(data->rev_base);
+	iounmap(data->ctrl_base);
+	kfree(data);
+
+	return ret;
+}
+
+int __init uniphier_cache_init(void)
+{
+	struct device_node *np = NULL;
+	unsigned int cache_level;
+	int ret = 0;
+
+	/* look for level 2 cache */
+	while ((np = of_find_matching_node(np, uniphier_cache_match)))
+		if (!of_property_read_u32(np, "cache-level", &cache_level) &&
+		    cache_level == 2)
+			break;
+
+	if (!np)
+		return -ENODEV;
+
+	ret = __uniphier_cache_init(np, &cache_level);
+	of_node_put(np);
+
+	if (ret) {
+		/*
+		 * Error out iif L2 initialization fails.  Continue with any
+		 * error on L3 or outer because they are optional.
+		 */
+		if (cache_level == 2) {
+			pr_err("failed to initialize L2 cache\n");
+			return ret;
+		}
+
+		cache_level--;
+		ret = 0;
+	}
+
+	outer_cache.inv_range = uniphier_cache_inv_range;
+	outer_cache.clean_range = uniphier_cache_clean_range;
+	outer_cache.flush_range = uniphier_cache_flush_range;
+	outer_cache.flush_all = uniphier_cache_flush_all;
+	outer_cache.disable = uniphier_cache_disable;
+	outer_cache.sync = uniphier_cache_sync;
+
+	uniphier_cache_enable();
+
+	pr_info("enabled outer cache (cache level: %d)\n", cache_level);
+
+	return ret;
+}
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 23800a1..c6e2c75 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -7,6 +7,7 @@
 
 config ARCH_BERLIN
 	bool "Marvell Berlin SoC Family"
+	select ARCH_REQUIRE_GPIOLIB
 	select DW_APB_ICTL
 	help
 	  This enables support for Marvell Berlin SoC Family
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
index 4abf211..3b09716 100644
--- a/drivers/clk/shmobile/clk-mstp.c
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -259,6 +259,10 @@
 					    "renesas,cpg-mstp-clocks"))
 			goto found;
 
+		/* BSC on r8a73a4/sh73a0 uses zb_clk instead of an mstp clock */
+		if (!strcmp(clkspec.np->name, "zb_clk"))
+			goto found;
+
 		of_node_put(clkspec.np);
 		i++;
 	}
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 413070d..9c79af0c 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1196,6 +1196,7 @@
 }
 CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
 CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
+CLK_OF_DECLARE(sun5i_r8_clk_init, "allwinner,sun5i-r8", sun5i_init_clocks);
 CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
 
 static const char *sun6i_critical_clocks[] __initdata = {
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 96ddecb..c9c0fcc 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/brcmstb/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/sunxi/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 0b12d77..4e27f10 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_SOC_BRCMSTB)	+= brcmstb/
 obj-$(CONFIG_MACH_DOVE)		+= dove/
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
new file mode 100644
index 0000000..39cab3b
--- /dev/null
+++ b/drivers/soc/brcmstb/Kconfig
@@ -0,0 +1,9 @@
+menuconfig SOC_BRCMSTB
+	bool "Broadcom STB SoC drivers"
+	depends on ARM
+	help
+	  Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
+	  This option alone enables only some support code, while the drivers
+	  can be enabled individually within this menu.
+
+	  If unsure, say N.
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile
new file mode 100644
index 0000000..9120b27
--- /dev/null
+++ b/drivers/soc/brcmstb/Makefile
@@ -0,0 +1 @@
+obj-y				+= common.o biuctrl.o
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/brcmstb/biuctrl.c
new file mode 100644
index 0000000..9049c076f
--- /dev/null
+++ b/drivers/soc/brcmstb/biuctrl.c
@@ -0,0 +1,116 @@
+/*
+ * Broadcom STB SoCs Bus Unit Interface controls
+ *
+ * Copyright (C) 2015, Broadcom Corporation
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt)	"brcmstb: " KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define CPU_CREDIT_REG_OFFSET			0x184
+#define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK	0x70000000
+
+static void __iomem *cpubiuctrl_base;
+static bool mcp_wr_pairing_en;
+
+static int __init mcp_write_pairing_set(void)
+{
+	u32 creds = 0;
+
+	if (!cpubiuctrl_base)
+		return -1;
+
+	creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+	if (mcp_wr_pairing_en) {
+		pr_info("MCP: Enabling write pairing\n");
+		writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+			     cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+	} else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
+		pr_info("MCP: Disabling write pairing\n");
+		writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
+				cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+	} else {
+		pr_info("MCP: Write pairing already disabled\n");
+	}
+
+	return 0;
+}
+
+static int __init setup_hifcpubiuctrl_regs(void)
+{
+	struct device_node *np;
+	int ret = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
+	if (!np) {
+		pr_err("missing BIU control node\n");
+		return -ENODEV;
+	}
+
+	cpubiuctrl_base = of_iomap(np, 0);
+	if (!cpubiuctrl_base) {
+		pr_err("failed to remap BIU control base\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
+out:
+	of_node_put(np);
+	return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static u32 cpu_credit_reg_dump;  /* for save/restore */
+
+static int brcmstb_cpu_credit_reg_suspend(void)
+{
+	if (cpubiuctrl_base)
+		cpu_credit_reg_dump =
+			readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+	return 0;
+}
+
+static void brcmstb_cpu_credit_reg_resume(void)
+{
+	if (cpubiuctrl_base)
+		writel_relaxed(cpu_credit_reg_dump,
+				cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
+}
+
+static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
+	.suspend = brcmstb_cpu_credit_reg_suspend,
+	.resume = brcmstb_cpu_credit_reg_resume,
+};
+#endif
+
+
+void __init brcmstb_biuctrl_init(void)
+{
+	int ret;
+
+	setup_hifcpubiuctrl_regs();
+
+	ret = mcp_write_pairing_set();
+	if (ret) {
+		pr_err("MCP: Unable to disable write pairing!\n");
+		return;
+	}
+
+#ifdef CONFIG_PM_SLEEP
+	register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
+#endif
+}
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
new file mode 100644
index 0000000..c262c02
--- /dev/null
+++ b/drivers/soc/brcmstb/common.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * 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.
+ *
+ * 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/of.h>
+
+#include <soc/brcmstb/common.h>
+
+static const struct of_device_id brcmstb_machine_match[] = {
+	{ .compatible = "brcm,brcmstb", },
+	{ }
+};
+
+bool soc_is_brcmstb(void)
+{
+	struct device_node *root;
+
+	root = of_find_node_by_path("/");
+	if (!root)
+		return false;
+
+	return of_match_node(brcmstb_machine_match, root) != NULL;
+}
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 8bc7b41..105597a 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -725,10 +725,6 @@
 	pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
 	pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
 	pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
-	pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
-	pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
-	pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
-	pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
 
 	if (pwrap_is_mt8135(wrp)) {
 		/* enable pwrap events and pwrap bridge in AP side */
@@ -896,6 +892,12 @@
 		return -ENODEV;
 	}
 
+	/* Initialize watchdog, may not be done by the bootloader */
+	pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+	pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+	pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+	pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
+
 	irq = platform_get_irq(pdev, 0);
 	ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
 			"mt-pmic-pwrap", wrp);
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 164a7d8..4d4203c 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -54,12 +54,16 @@
 #define PWR_STATUS_USB			BIT(25)
 
 enum clk_id {
+	MT8173_CLK_NONE,
 	MT8173_CLK_MM,
 	MT8173_CLK_MFG,
-	MT8173_CLK_NONE,
-	MT8173_CLK_MAX = MT8173_CLK_NONE,
+	MT8173_CLK_VENC,
+	MT8173_CLK_VENC_LT,
+	MT8173_CLK_MAX,
 };
 
+#define MAX_CLKS	2
+
 struct scp_domain_data {
 	const char *name;
 	u32 sta_mask;
@@ -67,7 +71,8 @@
 	u32 sram_pdn_bits;
 	u32 sram_pdn_ack_bits;
 	u32 bus_prot_mask;
-	enum clk_id clk_id;
+	enum clk_id clk_id[MAX_CLKS];
+	bool active_wakeup;
 };
 
 static const struct scp_domain_data scp_domain_data[] __initconst = {
@@ -77,7 +82,7 @@
 		.ctl_offs = SPM_VDE_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(12, 12),
-		.clk_id = MT8173_CLK_MM,
+		.clk_id = {MT8173_CLK_MM},
 	},
 	[MT8173_POWER_DOMAIN_VENC] = {
 		.name = "venc",
@@ -85,7 +90,7 @@
 		.ctl_offs = SPM_VEN_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = MT8173_CLK_MM,
+		.clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
 	},
 	[MT8173_POWER_DOMAIN_ISP] = {
 		.name = "isp",
@@ -93,7 +98,7 @@
 		.ctl_offs = SPM_ISP_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(13, 12),
-		.clk_id = MT8173_CLK_MM,
+		.clk_id = {MT8173_CLK_MM},
 	},
 	[MT8173_POWER_DOMAIN_MM] = {
 		.name = "mm",
@@ -101,7 +106,7 @@
 		.ctl_offs = SPM_DIS_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(12, 12),
-		.clk_id = MT8173_CLK_MM,
+		.clk_id = {MT8173_CLK_MM},
 		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
 			MT8173_TOP_AXI_PROT_EN_MM_M1,
 	},
@@ -111,7 +116,7 @@
 		.ctl_offs = SPM_VEN2_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = MT8173_CLK_MM,
+		.clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
 	},
 	[MT8173_POWER_DOMAIN_AUDIO] = {
 		.name = "audio",
@@ -119,7 +124,7 @@
 		.ctl_offs = SPM_AUDIO_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = MT8173_CLK_NONE,
+		.clk_id = {MT8173_CLK_NONE},
 	},
 	[MT8173_POWER_DOMAIN_USB] = {
 		.name = "usb",
@@ -127,7 +132,8 @@
 		.ctl_offs = SPM_USB_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(15, 12),
-		.clk_id = MT8173_CLK_NONE,
+		.clk_id = {MT8173_CLK_NONE},
+		.active_wakeup = true,
 	},
 	[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
 		.name = "mfg_async",
@@ -135,7 +141,7 @@
 		.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = 0,
-		.clk_id = MT8173_CLK_MFG,
+		.clk_id = {MT8173_CLK_MFG},
 	},
 	[MT8173_POWER_DOMAIN_MFG_2D] = {
 		.name = "mfg_2d",
@@ -143,7 +149,7 @@
 		.ctl_offs = SPM_MFG_2D_PWR_CON,
 		.sram_pdn_bits = GENMASK(11, 8),
 		.sram_pdn_ack_bits = GENMASK(13, 12),
-		.clk_id = MT8173_CLK_NONE,
+		.clk_id = {MT8173_CLK_NONE},
 	},
 	[MT8173_POWER_DOMAIN_MFG] = {
 		.name = "mfg",
@@ -151,7 +157,7 @@
 		.ctl_offs = SPM_MFG_PWR_CON,
 		.sram_pdn_bits = GENMASK(13, 8),
 		.sram_pdn_ack_bits = GENMASK(21, 16),
-		.clk_id = MT8173_CLK_NONE,
+		.clk_id = {MT8173_CLK_NONE},
 		.bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
 			MT8173_TOP_AXI_PROT_EN_MFG_M0 |
 			MT8173_TOP_AXI_PROT_EN_MFG_M1 |
@@ -166,12 +172,13 @@
 struct scp_domain {
 	struct generic_pm_domain genpd;
 	struct scp *scp;
-	struct clk *clk;
+	struct clk *clk[MAX_CLKS];
 	u32 sta_mask;
 	void __iomem *ctl_addr;
 	u32 sram_pdn_bits;
 	u32 sram_pdn_ack_bits;
 	u32 bus_prot_mask;
+	bool active_wakeup;
 };
 
 struct scp {
@@ -212,11 +219,16 @@
 	u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
 	u32 val;
 	int ret;
+	int i;
 
-	if (scpd->clk) {
-		ret = clk_prepare_enable(scpd->clk);
-		if (ret)
+	for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
+		ret = clk_prepare_enable(scpd->clk[i]);
+		if (ret) {
+			for (--i; i >= 0; i--)
+				clk_disable_unprepare(scpd->clk[i]);
+
 			goto err_clk;
+		}
 	}
 
 	val = readl(ctl_addr);
@@ -282,7 +294,10 @@
 	return 0;
 
 err_pwr_ack:
-	clk_disable_unprepare(scpd->clk);
+	for (i = MAX_CLKS - 1; i >= 0; i--) {
+		if (scpd->clk[i])
+			clk_disable_unprepare(scpd->clk[i]);
+	}
 err_clk:
 	dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
 
@@ -299,6 +314,7 @@
 	u32 pdn_ack = scpd->sram_pdn_ack_bits;
 	u32 val;
 	int ret;
+	int i;
 
 	if (scpd->bus_prot_mask) {
 		ret = mtk_infracfg_set_bus_protection(scp->infracfg,
@@ -360,8 +376,8 @@
 			expired = true;
 	}
 
-	if (scpd->clk)
-		clk_disable_unprepare(scpd->clk);
+	for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
+		clk_disable_unprepare(scpd->clk[i]);
 
 	return 0;
 
@@ -371,11 +387,22 @@
 	return ret;
 }
 
+static bool scpsys_active_wakeup(struct device *dev)
+{
+	struct generic_pm_domain *genpd;
+	struct scp_domain *scpd;
+
+	genpd = pd_to_genpd(dev->pm_domain);
+	scpd = container_of(genpd, struct scp_domain, genpd);
+
+	return scpd->active_wakeup;
+}
+
 static int __init scpsys_probe(struct platform_device *pdev)
 {
 	struct genpd_onecell_data *pd_data;
 	struct resource *res;
-	int i, ret;
+	int i, j, ret;
 	struct scp *scp;
 	struct clk *clk[MT8173_CLK_MAX];
 
@@ -405,6 +432,14 @@
 	if (IS_ERR(clk[MT8173_CLK_MFG]))
 		return PTR_ERR(clk[MT8173_CLK_MFG]);
 
+	clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
+	if (IS_ERR(clk[MT8173_CLK_VENC]))
+		return PTR_ERR(clk[MT8173_CLK_VENC]);
+
+	clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
+	if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
+		return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
+
 	scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 			"infracfg");
 	if (IS_ERR(scp->infracfg)) {
@@ -428,12 +463,14 @@
 		scpd->sram_pdn_bits = data->sram_pdn_bits;
 		scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
 		scpd->bus_prot_mask = data->bus_prot_mask;
-		if (data->clk_id != MT8173_CLK_NONE)
-			scpd->clk = clk[data->clk_id];
+		scpd->active_wakeup = data->active_wakeup;
+		for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
+			scpd->clk[j] = clk[data->clk_id[j]];
 
 		genpd->name = data->name;
 		genpd->power_off = scpsys_power_off;
 		genpd->power_on = scpsys_power_on;
+		genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
 
 		/*
 		 * Initially turn on all domains to make the domains usable
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h
index 51da234..6ff936c 100644
--- a/drivers/soc/ti/knav_qmss.h
+++ b/drivers/soc/ti/knav_qmss.h
@@ -135,9 +135,10 @@
 	};
 	void __iomem					*intd;
 	u32 __iomem					*iram;
-	const char					*firmware;
 	u32						id;
 	struct list_head				list;
+	bool						loaded;
+	bool						started;
 };
 
 struct knav_qmgr_info {
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index b98fe56..d2d48f2 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -486,8 +486,8 @@
  * Return 0 on success or error
  */
 int knav_init_acc_range(struct knav_device *kdev,
-				struct device_node *node,
-				struct knav_range_info *range)
+			struct device_node *node,
+			struct knav_range_info *range)
 {
 	struct knav_acc_channel *acc;
 	struct knav_pdsp_info *pdsp;
@@ -530,6 +530,12 @@
 		return -EINVAL;
 	}
 
+	if (!pdsp->started) {
+		dev_err(kdev->dev, "pdsp id %d not started for range %s\n",
+			info->pdsp_id, range->name);
+		return -ENODEV;
+	}
+
 	info->pdsp = pdsp;
 	channels = range->num_queues;
 	if (of_get_property(node, "multi-queue", NULL)) {
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 6d8646d..f3a0b6a 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -68,6 +68,12 @@
 	     idx < (kdev)->num_queues_in_use;			\
 	     idx++, inst = knav_queue_idx_to_inst(kdev, idx))
 
+/* All firmware file names end up here. List the firmware file names below.
+ * Newest followed by older ones. Search is done from start of the array
+ * until a firmware file is found.
+ */
+const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"};
+
 /**
  * knav_queue_notify: qmss queue notfier call
  *
@@ -1439,7 +1445,6 @@
 	struct device *dev = kdev->dev;
 	struct knav_pdsp_info *pdsp;
 	struct device_node *child;
-	int ret;
 
 	for_each_child_of_node(pdsps, child) {
 		pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
@@ -1448,17 +1453,6 @@
 			return -ENOMEM;
 		}
 		pdsp->name = knav_queue_find_name(child);
-		ret = of_property_read_string(child, "firmware",
-					      &pdsp->firmware);
-		if (ret < 0 || !pdsp->firmware) {
-			dev_err(dev, "unknown firmware for pdsp %s\n",
-				pdsp->name);
-			devm_kfree(dev, pdsp);
-			continue;
-		}
-		dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name,
-			pdsp->firmware);
-
 		pdsp->iram =
 			knav_queue_map_reg(kdev, child,
 					   KNAV_QUEUE_PDSP_IRAM_REG_INDEX);
@@ -1489,9 +1483,9 @@
 		}
 		of_property_read_u32(child, "id", &pdsp->id);
 		list_add_tail(&pdsp->list, &kdev->pdsps);
-		dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n",
+		dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n",
 			pdsp->name, pdsp->command, pdsp->iram, pdsp->regs,
-			pdsp->intd, pdsp->firmware);
+			pdsp->intd);
 	}
 	return 0;
 }
@@ -1510,6 +1504,8 @@
 		dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name);
 		return ret;
 	}
+	pdsp->loaded = false;
+	pdsp->started = false;
 	return 0;
 }
 
@@ -1518,14 +1514,29 @@
 {
 	int i, ret, fwlen;
 	const struct firmware *fw;
+	bool found = false;
 	u32 *fwdata;
 
-	ret = request_firmware(&fw, pdsp->firmware, kdev->dev);
-	if (ret) {
-		dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n",
-			pdsp->firmware, pdsp->name);
-		return ret;
+	for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
+		if (knav_acc_firmwares[i]) {
+			ret = request_firmware(&fw,
+					       knav_acc_firmwares[i],
+					       kdev->dev);
+			if (!ret) {
+				found = true;
+				break;
+			}
+		}
 	}
+
+	if (!found) {
+		dev_err(kdev->dev, "failed to get firmware for pdsp\n");
+		return -ENODEV;
+	}
+
+	dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n",
+		 knav_acc_firmwares[i]);
+
 	writel_relaxed(pdsp->id + 1, pdsp->command + 0x18);
 	/* download the firmware */
 	fwdata = (u32 *)fw->data;
@@ -1583,16 +1594,24 @@
 	int ret;
 
 	knav_queue_stop_pdsps(kdev);
-	/* now load them all */
+	/* now load them all. We return success even if pdsp
+	 * is not loaded as acc channels are optional on having
+	 * firmware availability in the system. We set the loaded
+	 * and stated flag and when initialize the acc range, check
+	 * it and init the range only if pdsp is started.
+	 */
 	for_each_pdsp(kdev, pdsp) {
 		ret = knav_queue_load_pdsp(kdev, pdsp);
-		if (ret < 0)
-			return ret;
+		if (!ret)
+			pdsp->loaded = true;
 	}
 
 	for_each_pdsp(kdev, pdsp) {
-		ret = knav_queue_start_pdsp(kdev, pdsp);
-		WARN_ON(ret);
+		if (pdsp->loaded) {
+			ret = knav_queue_start_pdsp(kdev, pdsp);
+			if (!ret)
+				pdsp->started = true;
+		}
 	}
 	return 0;
 }
diff --git a/include/linux/mfd/syscon/imx7-iomuxc-gpr.h b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h
new file mode 100644
index 0000000..4585d61
--- /dev/null
+++ b/include/linux/mfd/syscon/imx7-iomuxc-gpr.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_IMX7_IOMUXC_GPR_H
+#define __LINUX_IMX7_IOMUXC_GPR_H
+
+#define IOMUXC_GPR0	0x00
+#define IOMUXC_GPR1	0x04
+#define IOMUXC_GPR2	0x08
+#define IOMUXC_GPR3	0x0c
+#define IOMUXC_GPR4	0x10
+#define IOMUXC_GPR5	0x14
+#define IOMUXC_GPR6	0x18
+#define IOMUXC_GPR7	0x1c
+#define IOMUXC_GPR8	0x20
+#define IOMUXC_GPR9	0x24
+#define IOMUXC_GPR10	0x28
+#define IOMUXC_GPR11	0x2c
+#define IOMUXC_GPR12	0x30
+#define IOMUXC_GPR13	0x34
+#define IOMUXC_GPR14	0x38
+#define IOMUXC_GPR15	0x3c
+#define IOMUXC_GPR16	0x40
+#define IOMUXC_GPR17	0x44
+#define IOMUXC_GPR18	0x48
+#define IOMUXC_GPR19	0x4c
+#define IOMUXC_GPR20	0x50
+#define IOMUXC_GPR21	0x54
+#define IOMUXC_GPR22	0x58
+
+/* For imx7d iomux gpr register field define */
+#define IMX7D_GPR1_IRQ_MASK			(0x1 << 12)
+#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK	(0x1 << 13)
+#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK	(0x1 << 14)
+#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK		(0x3 << 13)
+#define IMX7D_GPR1_ENET1_CLK_DIR_MASK		(0x1 << 17)
+#define IMX7D_GPR1_ENET2_CLK_DIR_MASK		(0x1 << 18)
+#define IMX7D_GPR1_ENET_CLK_DIR_MASK		(0x3 << 17)
+
+#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI		(0x1 << 4)
+
+#endif /* __LINUX_IMX7_IOMUXC_GPR_H */
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 91b16ad..3c8825b 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -9,15 +9,7 @@
 
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/spi/spi.h>
-#include <linux/usb/atmel_usba_udc.h>
-#include <linux/atmel-mci.h>
-#include <sound/atmel-ac97c.h>
 #include <linux/serial.h>
-#include <linux/platform_data/macb.h>
 
  /* Compact Flash */
 struct at91_cf_data {
diff --git a/include/linux/soc/brcmstb/brcmstb.h b/include/linux/soc/brcmstb/brcmstb.h
new file mode 100644
index 0000000..337ce41
--- /dev/null
+++ b/include/linux/soc/brcmstb/brcmstb.h
@@ -0,0 +1,10 @@
+#ifndef __BRCMSTB_SOC_H
+#define __BRCMSTB_SOC_H
+
+/*
+ * Bus Interface Unit control register setup, must happen early during boot,
+ * before SMP is brought up, called by machine entry point.
+ */
+void brcmstb_biuctrl_init(void);
+
+#endif /* __BRCMSTB_SOC_H */
diff --git a/include/soc/brcmstb/common.h b/include/soc/brcmstb/common.h
new file mode 100644
index 0000000..cfb5335
--- /dev/null
+++ b/include/soc/brcmstb/common.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright © 2014 NVIDIA Corporation
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SOC_BRCMSTB_COMMON_H__
+#define __SOC_BRCMSTB_COMMON_H__
+
+bool soc_is_brcmstb(void);
+
+#endif /* __SOC_BRCMSTB_COMMON_H__ */