diff --git a/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt
new file mode 100644
index 000000000000..a8978ec94831
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/renesas,sh73a0-cpg-clocks.txt
@@ -0,0 +1,35 @@
+These bindings should be considered EXPERIMENTAL for now.
+
+* Renesas SH73A0 Clock Pulse Generator (CPG)
+
+The CPG generates core clocks for the SH73A0 SoC. It includes four PLLs
+and several fixed ratio dividers.
+
+Required Properties:
+
+  - compatible: Must be "renesas,sh73a0-cpg-clocks"
+
+  - reg: Base address and length of the memory resource used by the CPG
+
+  - clocks: Reference to the parent clocks ("extal1" and "extal2")
+
+  - #clock-cells: Must be 1
+
+  - clock-output-names: The names of the clocks. Supported clocks are "main",
+    "pll0", "pll1", "pll2", "pll3", "dsi0phy", "dsi1phy", "zg", "m3", "b",
+    "m1", "m2", "z", "zx", and "hp".
+
+
+Example
+-------
+
+        cpg_clocks: cpg_clocks@e6150000 {
+                compatible = "renesas,sh73a0-cpg-clocks";
+                reg = <0 0xe6150000 0 0x10000>;
+                clocks = <&extal1_clk>, <&extal2_clk>;
+                #clock-cells = <1>;
+                clock-output-names = "main", "pll0", "pll1", "pll2",
+                                     "pll3", "dsi0phy", "dsi1phy",
+                                     "zg", "m3", "b", "m1", "m2",
+                                     "z", "zx", "hp";
+        };
diff --git a/Documentation/devicetree/bindings/mfd/atmel-matrix.txt b/Documentation/devicetree/bindings/mfd/atmel-matrix.txt
new file mode 100644
index 000000000000..e3ef50ca02a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-matrix.txt
@@ -0,0 +1,24 @@
+* Device tree bindings for Atmel Bus Matrix
+
+The Bus Matrix registers are used to configure Atmel SoCs internal bus
+behavior (master/slave priorities, undefined burst length type, ...)
+
+Required properties:
+- compatible:		Should be one of the following
+			"atmel,at91sam9260-matrix", "syscon"
+			"atmel,at91sam9261-matrix", "syscon"
+			"atmel,at91sam9263-matrix", "syscon"
+			"atmel,at91sam9rl-matrix", "syscon"
+			"atmel,at91sam9g45-matrix", "syscon"
+			"atmel,at91sam9n12-matrix", "syscon"
+			"atmel,at91sam9x5-matrix", "syscon"
+			"atmel,sama5d3-matrix", "syscon"
+- reg:			Contains offset/length value of the Bus Matrix
+			memory region.
+
+Example:
+
+matrix: matrix@ffffec00 {
+	compatible = "atmel,sama5d3-matrix", "syscon";
+	reg = <0xffffec00 0x200>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/atmel-smc.txt b/Documentation/devicetree/bindings/mfd/atmel-smc.txt
new file mode 100644
index 000000000000..26eeed373934
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/atmel-smc.txt
@@ -0,0 +1,19 @@
+* Device tree bindings for Atmel SMC (Static Memory Controller)
+
+The SMC registers are used to configure Atmel EBI (External Bus Interface)
+to interface with standard memory devices (NAND, NOR, SRAM or specialized
+devices like FPGAs).
+
+Required properties:
+- compatible:		Should be one of the following
+			"atmel,at91sam9260-smc", "syscon"
+			"atmel,sama5d3-smc", "syscon"
+- reg:			Contains offset/length value of the SMC memory
+			region.
+
+Example:
+
+smc: smc@ffffc000 {
+	compatible = "atmel,sama5d3-smc", "syscon";
+	reg = <0xffffc000 0x1000>;
+};
diff --git a/Documentation/devicetree/bindings/usb/atmel-usb.txt b/Documentation/devicetree/bindings/usb/atmel-usb.txt
index 38fee0f66c12..e180d56c75db 100644
--- a/Documentation/devicetree/bindings/usb/atmel-usb.txt
+++ b/Documentation/devicetree/bindings/usb/atmel-usb.txt
@@ -33,9 +33,17 @@ usb1: ehci@00800000 {
 AT91 USB device controller
 
 Required properties:
- - compatible: Should be "atmel,at91rm9200-udc"
+ - compatible: Should be one of the following
+	       "atmel,at91rm9200-udc"
+	       "atmel,at91sam9260-udc"
+	       "atmel,at91sam9261-udc"
+	       "atmel,at91sam9263-udc"
  - reg: Address and length of the register set for the device
  - interrupts: Should contain macb interrupt
+ - clocks: Should reference the peripheral and the AHB clocks
+ - clock-names: Should contains two strings
+		"pclk" for the peripheral clock
+		"hclk" for the AHB clock
 
 Optional properties:
  - atmel,vbus-gpio: If present, specifies a gpio that needs to be
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
index 863dc4c7d7f6..6d32c87632d4 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -182,6 +182,10 @@
 	status = "okay";
 };
 
+&extal2_clk {
+	clock-frequency = <48000000>;
+};
+
 &i2c0 {
 	status = "okay";
 	as3711@40 {
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 37c8a761aeab..2dfd5b44255d 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -10,6 +10,7 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/clock/sh73a0-clock.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
@@ -71,6 +72,8 @@
 
 		renesas,channels-mask = <0x3f>;
 
+		clocks = <&mstp3_clks SH73A0_CLK_CMT1>;
+		clock-names = "fck";
 		status = "disabled";
 	};
 
@@ -160,6 +163,7 @@
 			      0 168 IRQ_TYPE_LEVEL_HIGH
 			      0 169 IRQ_TYPE_LEVEL_HIGH
 			      0 170 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp1_clks SH73A0_CLK_IIC0>;
 		status = "disabled";
 	};
 
@@ -172,6 +176,7 @@
 			      0 52 IRQ_TYPE_LEVEL_HIGH
 			      0 53 IRQ_TYPE_LEVEL_HIGH
 			      0 54 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_IIC1>;
 		status = "disabled";
 	};
 
@@ -184,6 +189,7 @@
 			      0 172 IRQ_TYPE_LEVEL_HIGH
 			      0 173 IRQ_TYPE_LEVEL_HIGH
 			      0 174 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp0_clks SH73A0_CLK_IIC2>;
 		status = "disabled";
 	};
 
@@ -196,6 +202,7 @@
 			      0 184 IRQ_TYPE_LEVEL_HIGH
 			      0 185 IRQ_TYPE_LEVEL_HIGH
 			      0 186 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp4_clks SH73A0_CLK_IIC3>;
 		status = "disabled";
 	};
 
@@ -208,6 +215,7 @@
 			      0 188 IRQ_TYPE_LEVEL_HIGH
 			      0 189 IRQ_TYPE_LEVEL_HIGH
 			      0 190 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp4_clks SH73A0_CLK_IIC4>;
 		status = "disabled";
 	};
 
@@ -216,6 +224,7 @@
 		reg = <0xe6bd0000 0x100>;
 		interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH
 			      0 141 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>;
 		reg-io-width = <4>;
 		status = "disabled";
 	};
@@ -226,6 +235,7 @@
 		interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH
 			      0 84 IRQ_TYPE_LEVEL_HIGH
 			      0 85 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_SDHI0>;
 		cap-sd-highspeed;
 		status = "disabled";
 	};
@@ -236,6 +246,7 @@
 		reg = <0xee120000 0x100>;
 		interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH
 			      0 89 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_SDHI1>;
 		toshiba,mmc-wrprotect-disable;
 		cap-sd-highspeed;
 		status = "disabled";
@@ -246,6 +257,7 @@
 		reg = <0xee140000 0x100>;
 		interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH
 			      0 105 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_SDHI2>;
 		toshiba,mmc-wrprotect-disable;
 		cap-sd-highspeed;
 		status = "disabled";
@@ -255,6 +267,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6c40000 0x100>;
 		interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA0>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -262,6 +276,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6c50000 0x100>;
 		interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA1>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -269,6 +285,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6c60000 0x100>;
 		interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA2>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -276,6 +294,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6c70000 0x100>;
 		interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA3>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -283,6 +303,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6c80000 0x100>;
 		interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -290,6 +312,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6cb0000 0x100>;
 		interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA5>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -297,6 +321,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6cc0000 0x100>;
 		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks SH73A0_CLK_SCIFA6>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -304,6 +330,8 @@
 		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
 		reg = <0xe6cd0000 0x100>;
 		interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA7>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -311,6 +339,8 @@
 		compatible = "renesas,scifb-sh73a0", "renesas,scifb";
 		reg = <0xe6c30000 0x100>;
 		interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFB>;
+		clock-names = "sci_ick";
 		status = "disabled";
 	};
 
@@ -338,4 +368,332 @@
 		interrupts = <0 146 0x4>;
 		status = "disabled";
 	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* External root clocks */
+		extalr_clk: extalr_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "extalr";
+		};
+		extal1_clk: extal1_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+			clock-output-names = "extal1";
+		};
+		extal2_clk: extal2_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "extal2";
+		};
+		extcki_clk: extcki_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "extcki";
+		};
+		fsiack_clk: fsiack_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "fsiack";
+		};
+		fsibck_clk: fsibck_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "fsibck";
+		};
+
+		/* Special CPG clocks */
+		cpg_clocks: cpg_clocks@e6150000 {
+			compatible = "renesas,sh73a0-cpg-clocks";
+			reg = <0xe6150000 0x10000>;
+			clocks = <&extal1_clk>, <&extal2_clk>;
+			#clock-cells = <1>;
+			clock-output-names = "main", "pll0", "pll1", "pll2",
+					     "pll3", "dsi0phy", "dsi1phy",
+					     "zg", "m3", "b", "m1", "m2",
+					     "z", "zx", "hp";
+		};
+
+		/* Variable factor clocks (DIV6) */
+		vclk1_clk: vclk1_clk@e6150008 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150008 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "vclk1";
+		};
+		vclk2_clk: vclk2_clk@e615000c {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe615000c 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "vclk2";
+		};
+		vclk3_clk: vclk3_clk@e615001c {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe615001c 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "vclk3";
+		};
+		zb_clk: zb_clk@e6150010 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150010 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "zb";
+		};
+		flctl_clk: flctl_clk@e6150014 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150014 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "flctlck";
+		};
+		sdhi0_clk: sdhi0_clk@e6150074 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150074 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "sdhi0ck";
+		};
+		sdhi1_clk: sdhi1_clk@e6150078 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150078 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "sdhi1ck";
+		};
+		sdhi2_clk: sdhi2_clk@e615007c {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe615007c 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "sdhi2ck";
+		};
+		fsia_clk: fsia_clk@e6150018 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150018 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "fsia";
+		};
+		fsib_clk: fsib_clk@e6150090 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150090 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "fsib";
+		};
+		sub_clk: sub_clk@e6150080 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150080 4>;
+			clocks = <&extal2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "sub";
+		};
+		spua_clk: spua_clk@e6150084 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150084 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "spua";
+		};
+		spuv_clk: spuv_clk@e6150094 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150094 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "spuv";
+		};
+		msu_clk: msu_clk@e6150088 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150088 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "msu";
+		};
+		hsi_clk: hsi_clk@e615008c {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe615008c 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "hsi";
+		};
+		mfg1_clk: mfg1_clk@e6150098 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150098 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "mfg1";
+		};
+		mfg2_clk: mfg2_clk@e615009c {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe615009c 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "mfg2";
+		};
+		dsit_clk: dsit_clk@e6150060 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150060 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "dsit";
+		};
+		dsi0p_clk: dsi0p_clk@e6150064 {
+			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
+			reg = <0xe6150064 4>;
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-output-names = "dsi0pck";
+		};
+
+		/* Fixed factor clocks */
+		main_div2_clk: main_div2_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks SH73A0_CLK_MAIN>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "main_div2";
+		};
+		pll1_div2_clk: pll1_div2_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clock-output-names = "pll1_div2";
+		};
+		pll1_div7_clk: pll1_div7_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <7>;
+			clock-mult = <1>;
+			clock-output-names = "pll1_div7";
+		};
+		pll1_div13_clk: pll1_div13_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
+			#clock-cells = <0>;
+			clock-div = <13>;
+			clock-mult = <1>;
+			clock-output-names = "pll1_div13";
+		};
+		twd_clk: twd_clk {
+			compatible = "fixed-factor-clock";
+			clocks = <&cpg_clocks SH73A0_CLK_Z>;
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clock-output-names = "twd";
+		};
+
+		/* Gate clocks */
+		mstp0_clks: mstp0_clks@e6150130 {
+			compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xe6150130 4>, <0xe6150030 4>;
+			clocks = <&cpg_clocks SH73A0_CLK_HP>;
+			#clock-cells = <1>;
+			clock-indices = <
+				SH73A0_CLK_IIC2
+			>;
+			clock-output-names =
+				"iic2";
+		};
+		mstp1_clks: mstp1_clks@e6150134 {
+			compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xe6150134 4>, <0xe6150038 4>;
+			clocks = <&cpg_clocks SH73A0_CLK_B>,
+				 <&cpg_clocks SH73A0_CLK_B>,
+				 <&cpg_clocks SH73A0_CLK_B>,
+				 <&cpg_clocks SH73A0_CLK_B>,
+				 <&sub_clk>, <&cpg_clocks SH73A0_CLK_B>,
+				 <&cpg_clocks SH73A0_CLK_HP>,
+				 <&cpg_clocks SH73A0_CLK_ZG>,
+				 <&cpg_clocks SH73A0_CLK_B>;
+			#clock-cells = <1>;
+			clock-indices = <
+				SH73A0_CLK_CEU1 SH73A0_CLK_CSI2_RX1
+				SH73A0_CLK_CEU0 SH73A0_CLK_CSI2_RX0
+				SH73A0_CLK_TMU0	SH73A0_CLK_DSITX0
+				SH73A0_CLK_IIC0 SH73A0_CLK_SGX
+				SH73A0_CLK_LCDC0
+			>;
+			clock-output-names =
+				"ceu1", "csi2_rx1", "ceu0", "csi2_rx0",
+				"tmu0", "dsitx0", "iic0", "sgx", "lcdc0";
+		};
+		mstp2_clks: mstp2_clks@e6150138 {
+			compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xe6150138 4>, <0xe6150040 4>;
+			clocks = <&sub_clk>, <&cpg_clocks SH73A0_CLK_HP>,
+				 <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>,
+				 <&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>,
+				 <&sub_clk>, <&sub_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				SH73A0_CLK_SCIFA7 SH73A0_CLK_SY_DMAC
+				SH73A0_CLK_MP_DMAC SH73A0_CLK_SCIFA5
+				SH73A0_CLK_SCIFB SH73A0_CLK_SCIFA0
+				SH73A0_CLK_SCIFA1 SH73A0_CLK_SCIFA2
+				SH73A0_CLK_SCIFA3 SH73A0_CLK_SCIFA4
+			>;
+			clock-output-names =
+				"scifa7", "sy_dmac", "mp_dmac", "scifa5",
+				"scifb", "scifa0", "scifa1", "scifa2",
+				"scifa3", "scifa4";
+		};
+		mstp3_clks: mstp3_clks@e615013c {
+			compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xe615013c 4>, <0xe6150048 4>;
+			clocks = <&sub_clk>, <&extalr_clk>,
+				 <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>,
+				 <&cpg_clocks SH73A0_CLK_HP>,
+				 <&cpg_clocks SH73A0_CLK_HP>, <&flctl_clk>,
+				 <&sdhi0_clk>, <&sdhi1_clk>,
+				 <&cpg_clocks SH73A0_CLK_HP>, <&sdhi2_clk>,
+				 <&main_div2_clk>, <&main_div2_clk>,
+				 <&main_div2_clk>, <&main_div2_clk>,
+				 <&main_div2_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				SH73A0_CLK_SCIFA6 SH73A0_CLK_CMT1
+				SH73A0_CLK_FSI SH73A0_CLK_IRDA
+				SH73A0_CLK_IIC1 SH73A0_CLK_USB SH73A0_CLK_FLCTL
+				SH73A0_CLK_SDHI0 SH73A0_CLK_SDHI1
+				SH73A0_CLK_MMCIF0 SH73A0_CLK_SDHI2
+				SH73A0_CLK_TPU0 SH73A0_CLK_TPU1
+				SH73A0_CLK_TPU2 SH73A0_CLK_TPU3
+				SH73A0_CLK_TPU4
+			>;
+			clock-output-names =
+				"scifa6", "cmt1", "fsi", "irda", "iic1",
+				"usb", "flctl", "sdhi0", "sdhi1", "mmcif0", "sdhi2",
+				"tpu0", "tpu1", "tpu2", "tpu3", "tpu4";
+		};
+		mstp4_clks: mstp4_clks@e6150140 {
+			compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xe6150140 4>, <0xe615004c 4>;
+			clocks = <&cpg_clocks SH73A0_CLK_HP>,
+				 <&cpg_clocks SH73A0_CLK_HP>, <&extalr_clk>;
+			#clock-cells = <1>;
+			clock-indices = <
+				SH73A0_CLK_IIC3 SH73A0_CLK_IIC4
+				SH73A0_CLK_KEYSC
+			>;
+			clock-output-names =
+				"iic3", "iic4", "keysc";
+		};
+	};
 };
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 865f878063cc..f70eca7ee705 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -13,6 +13,7 @@
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
 #include <linux/of.h>
+#include <linux/platform_data/cpuidle-exynos.h>
 
 #define EXYNOS3250_SOC_ID	0xE3472000
 #define EXYNOS3_SOC_MASK	0xFFFFF000
@@ -150,8 +151,11 @@ extern void exynos_pm_central_suspend(void);
 extern int exynos_pm_central_resume(void);
 extern void exynos_enter_aftr(void);
 
+extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data;
+
 extern void s5p_init_cpu(void __iomem *cpuid_addr);
 extern unsigned int samsung_rev(void);
+extern void __iomem *cpu_boot_reg_base(void);
 
 static inline void pmu_raw_writel(u32 val, u32 offset)
 {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 78eca99b98d1..2013f73797ed 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -211,6 +211,10 @@ static void __init exynos_dt_machine_init(void)
 	if (!IS_ENABLED(CONFIG_SMP))
 		exynos_sysram_init();
 
+#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
+	if (of_machine_is_compatible("samsung,exynos4210"))
+		exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
+#endif
 	if (of_machine_is_compatible("samsung,exynos4210") ||
 	    of_machine_is_compatible("samsung,exynos4212") ||
 	    (of_machine_is_compatible("samsung,exynos4412") &&
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 7a1ebfeeeeb8..3f32c47a6d74 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -194,7 +194,7 @@ int exynos_cluster_power_state(int cluster)
 		S5P_CORE_LOCAL_PWR_EN);
 }
 
-static inline void __iomem *cpu_boot_reg_base(void)
+void __iomem *cpu_boot_reg_base(void)
 {
 	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
 		return pmu_base_addr + S5P_INFORM5;
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index dfc8594e5b1f..e6209dadc00d 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -98,10 +98,6 @@ void exynos_pm_central_suspend(void)
 	tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
 	tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
 	pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
-
-	/* Setting SEQ_OPTION register */
-	pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
-		       S5P_CENTRAL_SEQ_OPTION);
 }
 
 int exynos_pm_central_resume(void)
@@ -165,6 +161,13 @@ void exynos_enter_aftr(void)
 
 	exynos_pm_central_suspend();
 
+	if (of_machine_is_compatible("samsung,exynos4212") ||
+	    of_machine_is_compatible("samsung,exynos4412")) {
+		/* Setting SEQ_OPTION register */
+		pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
+			       S5P_CENTRAL_SEQ_OPTION);
+	}
+
 	cpu_suspend(0, exynos_aftr_finisher);
 
 	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
@@ -177,3 +180,125 @@ void exynos_enter_aftr(void)
 
 	cpu_pm_exit();
 }
+
+static atomic_t cpu1_wakeup = ATOMIC_INIT(0);
+
+static int exynos_cpu0_enter_aftr(void)
+{
+	int ret = -1;
+
+	/*
+	 * If the other cpu is powered on, we have to power it off, because
+	 * the AFTR state won't work otherwise
+	 */
+	if (cpu_online(1)) {
+		/*
+		 * We reach a sync point with the coupled idle state, we know
+		 * the other cpu will power down itself or will abort the
+		 * sequence, let's wait for one of these to happen
+		 */
+		while (exynos_cpu_power_state(1)) {
+			/*
+			 * The other cpu may skip idle and boot back
+			 * up again
+			 */
+			if (atomic_read(&cpu1_wakeup))
+				goto abort;
+
+			/*
+			 * The other cpu may bounce through idle and
+			 * boot back up again, getting stuck in the
+			 * boot rom code
+			 */
+			if (__raw_readl(cpu_boot_reg_base()) == 0)
+				goto abort;
+
+			cpu_relax();
+		}
+	}
+
+	exynos_enter_aftr();
+	ret = 0;
+
+abort:
+	if (cpu_online(1)) {
+		/*
+		 * Set the boot vector to something non-zero
+		 */
+		__raw_writel(virt_to_phys(exynos_cpu_resume),
+			     cpu_boot_reg_base());
+		dsb();
+
+		/*
+		 * Turn on cpu1 and wait for it to be on
+		 */
+		exynos_cpu_power_up(1);
+		while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN)
+			cpu_relax();
+
+		while (!atomic_read(&cpu1_wakeup)) {
+			/*
+			 * Poke cpu1 out of the boot rom
+			 */
+			__raw_writel(virt_to_phys(exynos_cpu_resume),
+				     cpu_boot_reg_base());
+
+			arch_send_wakeup_ipi_mask(cpumask_of(1));
+		}
+	}
+
+	return ret;
+}
+
+static int exynos_wfi_finisher(unsigned long flags)
+{
+	cpu_do_idle();
+
+	return -1;
+}
+
+static int exynos_cpu1_powerdown(void)
+{
+	int ret = -1;
+
+	/*
+	 * Idle sequence for cpu1
+	 */
+	if (cpu_pm_enter())
+		goto cpu1_aborted;
+
+	/*
+	 * Turn off cpu 1
+	 */
+	exynos_cpu_power_down(1);
+
+	ret = cpu_suspend(0, exynos_wfi_finisher);
+
+	cpu_pm_exit();
+
+cpu1_aborted:
+	dsb();
+	/*
+	 * Notify cpu 0 that cpu 1 is awake
+	 */
+	atomic_set(&cpu1_wakeup, 1);
+
+	return ret;
+}
+
+static void exynos_pre_enter_aftr(void)
+{
+	__raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base());
+}
+
+static void exynos_post_enter_aftr(void)
+{
+	atomic_set(&cpu1_wakeup, 0);
+}
+
+struct cpuidle_exynos_data cpuidle_coupled_exynos_data = {
+	.cpu0_enter_aftr		= exynos_cpu0_enter_aftr,
+	.cpu1_powerdown		= exynos_cpu1_powerdown,
+	.pre_enter_aftr		= exynos_pre_enter_aftr,
+	.post_enter_aftr		= exynos_post_enter_aftr,
+};
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 82e6b6fba23f..666ec3e5b03f 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -319,6 +319,10 @@ static int exynos_pm_suspend(void)
 {
 	exynos_pm_central_suspend();
 
+	/* Setting SEQ_OPTION register */
+	pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
+		       S5P_CENTRAL_SEQ_OPTION);
+
 	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
 		exynos_cpu_save_register();
 
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index a8593d1241be..faea74a2151b 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -766,7 +766,9 @@ void __init __weak sh73a0_register_twd(void) { }
 void __init sh73a0_earlytimer_init(void)
 {
 	shmobile_init_delay();
+#ifndef CONFIG_COMMON_CLK
 	sh73a0_clock_init();
+#endif
 	shmobile_earlytimer_init();
 	sh73a0_register_twd();
 }
@@ -785,8 +787,9 @@ void __init sh73a0_add_early_devices(void)
 void __init sh73a0_add_standard_devices_dt(void)
 {
 	/* clocks are setup late during boot in the case of DT */
+#ifndef CONFIG_COMMON_CLK
 	sh73a0_clock_init();
-
+#endif
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff --git a/drivers/clk/shmobile/Makefile b/drivers/clk/shmobile/Makefile
index 960bf22d42ae..f83980f2b956 100644
--- a/drivers/clk/shmobile/Makefile
+++ b/drivers/clk/shmobile/Makefile
@@ -5,5 +5,6 @@ obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o
 obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o
 obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o
+obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o
 obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= clk-div6.o
 obj-$(CONFIG_ARCH_SHMOBILE_MULTI)	+= clk-mstp.o
diff --git a/drivers/clk/shmobile/clk-sh73a0.c b/drivers/clk/shmobile/clk-sh73a0.c
new file mode 100644
index 000000000000..cd529cfe412f
--- /dev/null
+++ b/drivers/clk/shmobile/clk-sh73a0.c
@@ -0,0 +1,218 @@
+/*
+ * sh73a0 Core CPG Clocks
+ *
+ * Copyright (C) 2014  Ulrich Hecht
+ *
+ * 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 of the License.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/shmobile.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spinlock.h>
+
+struct sh73a0_cpg {
+	struct clk_onecell_data data;
+	spinlock_t lock;
+	void __iomem *reg;
+};
+
+#define CPG_FRQCRA	0x00
+#define CPG_FRQCRB	0x04
+#define CPG_SD0CKCR	0x74
+#define CPG_SD1CKCR	0x78
+#define CPG_SD2CKCR	0x7c
+#define CPG_PLLECR	0xd0
+#define CPG_PLL0CR	0xd8
+#define CPG_PLL1CR	0x28
+#define CPG_PLL2CR	0x2c
+#define CPG_PLL3CR	0xdc
+#define CPG_CKSCR	0xc0
+#define CPG_DSI0PHYCR	0x6c
+#define CPG_DSI1PHYCR	0x70
+
+#define CLK_ENABLE_ON_INIT BIT(0)
+
+struct div4_clk {
+	const char *name;
+	const char *parent;
+	unsigned int reg;
+	unsigned int shift;
+};
+
+static struct div4_clk div4_clks[] = {
+	{ "zg", "pll0", CPG_FRQCRA, 16 },
+	{ "m3", "pll1", CPG_FRQCRA, 12 },
+	{ "b",  "pll1", CPG_FRQCRA,  8 },
+	{ "m1", "pll1", CPG_FRQCRA,  4 },
+	{ "m2", "pll1", CPG_FRQCRA,  0 },
+	{ "zx", "pll1", CPG_FRQCRB, 12 },
+	{ "hp", "pll1", CPG_FRQCRB,  4 },
+	{ NULL, NULL, 0, 0 },
+};
+
+static const struct clk_div_table div4_div_table[] = {
+	{ 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
+	{ 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
+	{ 12, 7 }, { 0, 0 }
+};
+
+static const struct clk_div_table z_div_table[] = {
+	/* ZSEL == 0 */
+	{ 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
+	{ 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 },
+	{ 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 },
+	/* ZSEL == 1 */
+	{ 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 },
+	{ 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 }
+};
+
+static struct clk * __init
+sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
+			     const char *name)
+{
+	const struct clk_div_table *table = NULL;
+	unsigned int shift, reg, width;
+	const char *parent_name;
+	unsigned int mult = 1;
+	unsigned int div = 1;
+
+	if (!strcmp(name, "main")) {
+		/* extal1, extal1_div2, extal2, extal2_div2 */
+		u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3;
+
+		parent_name = of_clk_get_parent_name(np, parent_idx >> 1);
+		div = (parent_idx & 1) + 1;
+	} else if (!strncmp(name, "pll", 3)) {
+		void __iomem *enable_reg = cpg->reg;
+		u32 enable_bit = name[3] - '0';
+
+		parent_name = "main";
+		switch (enable_bit) {
+		case 0:
+			enable_reg += CPG_PLL0CR;
+			break;
+		case 1:
+			enable_reg += CPG_PLL1CR;
+			break;
+		case 2:
+			enable_reg += CPG_PLL2CR;
+			break;
+		case 3:
+			enable_reg += CPG_PLL3CR;
+			break;
+		default:
+			return ERR_PTR(-EINVAL);
+		}
+		if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) {
+			mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1;
+			/* handle CFG bit for PLL1 and PLL2 */
+			if (enable_bit == 1 || enable_bit == 2)
+				if (clk_readl(enable_reg) & BIT(20))
+					mult *= 2;
+		}
+	} else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) {
+		u32 phy_no = name[3] - '0';
+		void __iomem *dsi_reg = cpg->reg +
+			(phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
+
+		parent_name = phy_no ? "dsi1pck" : "dsi0pck";
+		mult = __raw_readl(dsi_reg);
+		if (!(mult & 0x8000))
+			mult = 1;
+		else
+			mult = (mult & 0x3f) + 1;
+	} else if (!strcmp(name, "z")) {
+		parent_name = "pll0";
+		table = z_div_table;
+		reg = CPG_FRQCRB;
+		shift = 24;
+		width = 5;
+	} else {
+		struct div4_clk *c;
+
+		for (c = div4_clks; c->name; c++) {
+			if (!strcmp(name, c->name)) {
+				parent_name = c->parent;
+				table = div4_div_table;
+				reg = c->reg;
+				shift = c->shift;
+				width = 4;
+				break;
+			}
+		}
+		if (!c->name)
+			return ERR_PTR(-EINVAL);
+	}
+
+	if (!table) {
+		return clk_register_fixed_factor(NULL, name, parent_name, 0,
+						 mult, div);
+	} else {
+		return clk_register_divider_table(NULL, name, parent_name, 0,
+						  cpg->reg + reg, shift, width, 0,
+						  table, &cpg->lock);
+	}
+}
+
+static void __init sh73a0_cpg_clocks_init(struct device_node *np)
+{
+	struct sh73a0_cpg *cpg;
+	struct clk **clks;
+	unsigned int i;
+	int num_clks;
+
+	num_clks = of_property_count_strings(np, "clock-output-names");
+	if (num_clks < 0) {
+		pr_err("%s: failed to count clocks\n", __func__);
+		return;
+	}
+
+	cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
+	clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
+	if (cpg == NULL || clks == NULL) {
+		/* We're leaking memory on purpose, there's no point in cleaning
+		 * up as the system won't boot anyway.
+		 */
+		return;
+	}
+
+	spin_lock_init(&cpg->lock);
+
+	cpg->data.clks = clks;
+	cpg->data.clk_num = num_clks;
+
+	cpg->reg = of_iomap(np, 0);
+	if (WARN_ON(cpg->reg == NULL))
+		return;
+
+	/* Set SDHI clocks to a known state */
+	clk_writel(0x108, cpg->reg + CPG_SD0CKCR);
+	clk_writel(0x108, cpg->reg + CPG_SD1CKCR);
+	clk_writel(0x108, cpg->reg + CPG_SD2CKCR);
+
+	for (i = 0; i < num_clks; ++i) {
+		const char *name;
+		struct clk *clk;
+
+		of_property_read_string_index(np, "clock-output-names", i,
+					      &name);
+
+		clk = sh73a0_cpg_register_clock(np, cpg, name);
+		if (IS_ERR(clk))
+			pr_err("%s: failed to register %s %s clock (%ld)\n",
+			       __func__, np->name, name, PTR_ERR(clk));
+		else
+			cpg->data.clks[i] = clk;
+	}
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks",
+	       sh73a0_cpg_clocks_init);
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 8c16ab20fb15..8e07c9419153 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -55,6 +55,7 @@ config ARM_AT91_CPUIDLE
 config ARM_EXYNOS_CPUIDLE
 	bool "Cpu Idle Driver for the Exynos processors"
 	depends on ARCH_EXYNOS
+	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
 	help
 	  Select this to enable cpuidle for Exynos processors
 
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 4003a3160865..26f5f29fdb03 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -1,8 +1,11 @@
-/* linux/arch/arm/mach-exynos/cpuidle.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+/*
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
+ * Coupled cpuidle support based on the work of:
+ *	Colin Cross <ccross@android.com>
+ *	Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -13,13 +16,49 @@
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/platform_data/cpuidle-exynos.h>
 
 #include <asm/proc-fns.h>
 #include <asm/suspend.h>
 #include <asm/cpuidle.h>
 
+static atomic_t exynos_idle_barrier;
+
+static struct cpuidle_exynos_data *exynos_cpuidle_pdata;
 static void (*exynos_enter_aftr)(void);
 
+static int exynos_enter_coupled_lowpower(struct cpuidle_device *dev,
+					 struct cpuidle_driver *drv,
+					 int index)
+{
+	int ret;
+
+	exynos_cpuidle_pdata->pre_enter_aftr();
+
+	/*
+	 * Waiting all cpus to reach this point at the same moment
+	 */
+	cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
+
+	/*
+	 * Both cpus will reach this point at the same time
+	 */
+	ret = dev->cpu ? exynos_cpuidle_pdata->cpu1_powerdown()
+		       : exynos_cpuidle_pdata->cpu0_enter_aftr();
+	if (ret)
+		index = ret;
+
+	/*
+	 * Waiting all cpus to finish the power sequence before going further
+	 */
+	cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
+
+	exynos_cpuidle_pdata->post_enter_aftr();
+
+	return index;
+}
+
 static int exynos_enter_lowpower(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index)
@@ -55,13 +94,40 @@ static struct cpuidle_driver exynos_idle_driver = {
 	.safe_state_index = 0,
 };
 
+static struct cpuidle_driver exynos_coupled_idle_driver = {
+	.name			= "exynos_coupled_idle",
+	.owner			= THIS_MODULE,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE,
+		[1] = {
+			.enter			= exynos_enter_coupled_lowpower,
+			.exit_latency		= 5000,
+			.target_residency	= 10000,
+			.flags			= CPUIDLE_FLAG_COUPLED |
+						  CPUIDLE_FLAG_TIMER_STOP,
+			.name			= "C1",
+			.desc			= "ARM power down",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
 static int exynos_cpuidle_probe(struct platform_device *pdev)
 {
 	int ret;
 
-	exynos_enter_aftr = (void *)(pdev->dev.platform_data);
+	if (of_machine_is_compatible("samsung,exynos4210")) {
+		exynos_cpuidle_pdata = pdev->dev.platform_data;
+
+		ret = cpuidle_register(&exynos_coupled_idle_driver,
+				       cpu_possible_mask);
+	} else {
+		exynos_enter_aftr = (void *)(pdev->dev.platform_data);
+
+		ret = cpuidle_register(&exynos_idle_driver, NULL);
+	}
 
-	ret = cpuidle_register(&exynos_idle_driver, NULL);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register cpuidle driver\n");
 		return ret;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b0d50d70a8a1..b189733a1539 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -526,6 +526,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 		amba_device_unregister(to_amba_device(dev));
 #endif
 
+	of_dma_deconfigure(dev);
 	of_node_clear_flag(dev->of_node, OF_POPULATED);
 	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
 	return 0;
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 8843a678f200..3bb49252a098 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -279,6 +279,7 @@ config BFIN_CFPCMCIA
 config AT91_CF
 	tristate "AT91 CompactFlash Controller"
 	depends on PCMCIA && ARCH_AT91
+	depends on !ARCH_MULTIPLATFORM
 	help
 	  Say Y here to support the CompactFlash controller on AT91 chips.
 	  Or choose M to compile the driver as a module named "at91_cf".
diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile
index 6bed611e1934..135bdad7a6de 100644
--- a/drivers/soc/ti/Makefile
+++ b/drivers/soc/ti/Makefile
@@ -1,5 +1,6 @@
 #
 # TI Keystone SOC drivers
 #
-obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)	+= knav_qmss_queue.o knav_qmss_acc.o
+obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)	+= knav_qmss.o
+knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)	+= knav_dma.o
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index 6fbfde6e748f..ef6f69db0bd0 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -209,7 +209,7 @@ static irqreturn_t knav_acc_int_handler(int irq, void *_instdata)
 	return IRQ_HANDLED;
 }
 
-int knav_range_setup_acc_irq(struct knav_range_info *range,
+static int knav_range_setup_acc_irq(struct knav_range_info *range,
 				int queue, bool enabled)
 {
 	struct knav_device *kdev = range->kdev;
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 8e6a95d91d33..6d8646db52cc 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -626,6 +626,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma,
 	atomic_inc(&qh->stats.pushes);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(knav_queue_push);
 
 /**
  * knav_queue_pop()	- pop data (or descriptor) from the head of a queue
@@ -663,6 +664,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size)
 	atomic_inc(&qh->stats.pops);
 	return dma;
 }
+EXPORT_SYMBOL_GPL(knav_queue_pop);
 
 /* carve out descriptors and push into queue */
 static void kdesc_fill_pool(struct knav_pool *pool)
@@ -717,12 +719,14 @@ dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt)
 	struct knav_pool *pool = ph;
 	return pool->region->dma_start + (virt - pool->region->virt_start);
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_virt_to_dma);
 
 void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma)
 {
 	struct knav_pool *pool = ph;
 	return pool->region->virt_start + (dma - pool->region->dma_start);
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_dma_to_virt);
 
 /**
  * knav_pool_create()	- Create a pool of descriptors
@@ -878,6 +882,7 @@ void *knav_pool_desc_get(void *ph)
 	data = knav_pool_desc_dma_to_virt(pool, dma);
 	return data;
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_get);
 
 /**
  * knav_pool_desc_put()	- return a descriptor to the pool
@@ -890,6 +895,7 @@ void knav_pool_desc_put(void *ph, void *desc)
 	dma = knav_pool_desc_virt_to_dma(pool, desc);
 	knav_queue_push(pool->queue, dma, pool->region->desc_size, 0);
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_put);
 
 /**
  * knav_pool_desc_map()	- Map descriptor for DMA transfer
@@ -916,6 +922,7 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_map);
 
 /**
  * knav_pool_desc_unmap()	- Unmap descriptor after DMA transfer
@@ -938,6 +945,7 @@ void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz)
 	prefetch(desc);
 	return desc;
 }
+EXPORT_SYMBOL_GPL(knav_pool_desc_unmap);
 
 /**
  * knav_pool_count()	- Get the number of descriptors in pool.
@@ -949,6 +957,7 @@ int knav_pool_count(void *ph)
 	struct knav_pool *pool = ph;
 	return knav_queue_get_count(pool->queue);
 }
+EXPORT_SYMBOL_GPL(knav_pool_count);
 
 static void knav_queue_setup_region(struct knav_device *kdev,
 					struct knav_region *region)
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index b8e213eb36cc..366e551aeff0 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -32,6 +32,7 @@ menu "USB Peripheral Controller"
 config USB_AT91
 	tristate "Atmel AT91 USB Device Port"
 	depends on ARCH_AT91
+	depends on OF || COMPILE_TEST
 	help
 	   Many Atmel AT91 processors (such as the AT91RM2000) have a
 	   full speed USB Device Port with support for five configurable
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index c0ec5f71f16f..2fbedca3c2b4 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -31,16 +31,9 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_data/atmel.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/gpio.h>
-
-#include <mach/cpu.h>
-#include <mach/at91sam9261_matrix.h>
-#include <mach/at91_matrix.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-matrix.h>
 
 #include "at91_udc.h"
 
@@ -66,7 +59,15 @@
 #define	DRIVER_VERSION	"3 May 2006"
 
 static const char driver_name [] = "at91_udc";
-static const char ep0name[] = "ep0";
+static const char * const ep_names[] = {
+	"ep0",
+	"ep1",
+	"ep2",
+	"ep3-int",
+	"ep4",
+	"ep5",
+};
+#define ep0name		ep_names[0]
 
 #define VBUS_POLL_TIMEOUT	msecs_to_jiffies(1000)
 
@@ -895,8 +896,6 @@ static void clk_on(struct at91_udc *udc)
 		return;
 	udc->clocked = 1;
 
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_enable(udc->uclk);
 	clk_enable(udc->iclk);
 	clk_enable(udc->fclk);
 }
@@ -909,8 +908,6 @@ static void clk_off(struct at91_udc *udc)
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
 	clk_disable(udc->fclk);
 	clk_disable(udc->iclk);
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_disable(udc->uclk);
 }
 
 /*
@@ -919,8 +916,6 @@ static void clk_off(struct at91_udc *udc)
  */
 static void pullup(struct at91_udc *udc, int is_on)
 {
-	int	active = !udc->board.pullup_active_low;
-
 	if (!udc->enabled || !udc->vbus)
 		is_on = 0;
 	DBG("%sactive\n", is_on ? "" : "in");
@@ -929,40 +924,15 @@ static void pullup(struct at91_udc *udc, int is_on)
 		clk_on(udc);
 		at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, 0);
-		if (cpu_is_at91rm9200())
-			gpio_set_value(udc->board.pullup_pin, active);
-		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
-			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
-
-			txvc |= AT91_UDP_TXVC_PUON;
-			at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-		} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-			u32	usbpucr;
-
-			usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
-			usbpucr |= AT91_MATRIX_USBPUCR_PUON;
-			at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
-		}
 	} else {
 		stop_activity(udc);
 		at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
 		at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
-		if (cpu_is_at91rm9200())
-			gpio_set_value(udc->board.pullup_pin, !active);
-		else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
-			u32	txvc = at91_udp_read(udc, AT91_UDP_TXVC);
-
-			txvc &= ~AT91_UDP_TXVC_PUON;
-			at91_udp_write(udc, AT91_UDP_TXVC, txvc);
-		} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-			u32	usbpucr;
-
-			usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
-			usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
-			at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
-		}
 		clk_off(udc);
 	}
+
+	if (udc->caps && udc->caps->pullup)
+		udc->caps->pullup(udc, is_on);
 }
 
 /* vbus is here!  turn everything on that's ready */
@@ -1535,74 +1505,6 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
 
 /*-------------------------------------------------------------------------*/
 
-static struct at91_udc controller = {
-	.gadget = {
-		.ops	= &at91_udc_ops,
-		.ep0	= &controller.ep[0].ep,
-		.name	= driver_name,
-	},
-	.ep[0] = {
-		.ep = {
-			.name	= ep0name,
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.maxpacket	= 8,
-		.int_mask	= 1 << 0,
-	},
-	.ep[1] = {
-		.ep = {
-			.name	= "ep1",
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.is_pingpong	= 1,
-		.maxpacket	= 64,
-		.int_mask	= 1 << 1,
-	},
-	.ep[2] = {
-		.ep = {
-			.name	= "ep2",
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.is_pingpong	= 1,
-		.maxpacket	= 64,
-		.int_mask	= 1 << 2,
-	},
-	.ep[3] = {
-		.ep = {
-			/* could actually do bulk too */
-			.name	= "ep3-int",
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.maxpacket	= 8,
-		.int_mask	= 1 << 3,
-	},
-	.ep[4] = {
-		.ep = {
-			.name	= "ep4",
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.is_pingpong	= 1,
-		.maxpacket	= 256,
-		.int_mask	= 1 << 4,
-	},
-	.ep[5] = {
-		.ep = {
-			.name	= "ep5",
-			.ops	= &at91_ep_ops,
-		},
-		.udc		= &controller,
-		.is_pingpong	= 1,
-		.maxpacket	= 256,
-		.int_mask	= 1 << 5,
-	},
-	/* ep6 and ep7 are also reserved (custom silicon might use them) */
-};
-
 static void at91_vbus_update(struct at91_udc *udc, unsigned value)
 {
 	value ^= udc->board.vbus_active_low;
@@ -1687,12 +1589,202 @@ static void at91udc_shutdown(struct platform_device *dev)
 	spin_unlock_irqrestore(&udc->lock, flags);
 }
 
-static void at91udc_of_init(struct at91_udc *udc,
-				     struct device_node *np)
+static int at91rm9200_udc_init(struct at91_udc *udc)
+{
+	struct at91_ep *ep;
+	int ret;
+	int i;
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+
+		switch (i) {
+		case 0:
+		case 3:
+			ep->maxpacket = 8;
+			break;
+		case 1 ... 2:
+			ep->maxpacket = 64;
+			break;
+		case 4 ... 5:
+			ep->maxpacket = 256;
+			break;
+		}
+	}
+
+	if (!gpio_is_valid(udc->board.pullup_pin)) {
+		DBG("no D+ pullup?\n");
+		return -ENODEV;
+	}
+
+	ret = devm_gpio_request(&udc->pdev->dev, udc->board.pullup_pin,
+				"udc_pullup");
+	if (ret) {
+		DBG("D+ pullup is busy\n");
+		return ret;
+	}
+
+	gpio_direction_output(udc->board.pullup_pin,
+			      udc->board.pullup_active_low);
+
+	return 0;
+}
+
+static void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on)
+{
+	int active = !udc->board.pullup_active_low;
+
+	if (is_on)
+		gpio_set_value(udc->board.pullup_pin, active);
+	else
+		gpio_set_value(udc->board.pullup_pin, !active);
+}
+
+static const struct at91_udc_caps at91rm9200_udc_caps = {
+	.init = at91rm9200_udc_init,
+	.pullup = at91rm9200_udc_pullup,
+};
+
+static int at91sam9260_udc_init(struct at91_udc *udc)
+{
+	struct at91_ep *ep;
+	int i;
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+
+		switch (i) {
+		case 0 ... 3:
+			ep->maxpacket = 64;
+			break;
+		case 4 ... 5:
+			ep->maxpacket = 512;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on)
+{
+	u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+	if (is_on)
+		txvc |= AT91_UDP_TXVC_PUON;
+	else
+		txvc &= ~AT91_UDP_TXVC_PUON;
+
+	at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+}
+
+static const struct at91_udc_caps at91sam9260_udc_caps = {
+	.init = at91sam9260_udc_init,
+	.pullup = at91sam9260_udc_pullup,
+};
+
+static int at91sam9261_udc_init(struct at91_udc *udc)
+{
+	struct at91_ep *ep;
+	int i;
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+
+		switch (i) {
+		case 0:
+			ep->maxpacket = 8;
+			break;
+		case 1 ... 3:
+			ep->maxpacket = 64;
+			break;
+		case 4 ... 5:
+			ep->maxpacket = 256;
+			break;
+		}
+	}
+
+	udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node,
+						      "atmel,matrix");
+	if (IS_ERR(udc->matrix))
+		return PTR_ERR(udc->matrix);
+
+	return 0;
+}
+
+static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on)
+{
+	u32 usbpucr = 0;
+
+	if (is_on)
+		usbpucr = AT91_MATRIX_USBPUCR_PUON;
+
+	regmap_update_bits(udc->matrix, AT91SAM9261_MATRIX_USBPUCR,
+			   AT91_MATRIX_USBPUCR_PUON, usbpucr);
+}
+
+static const struct at91_udc_caps at91sam9261_udc_caps = {
+	.init = at91sam9261_udc_init,
+	.pullup = at91sam9261_udc_pullup,
+};
+
+static int at91sam9263_udc_init(struct at91_udc *udc)
+{
+	struct at91_ep *ep;
+	int i;
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+
+		switch (i) {
+		case 0:
+		case 1:
+		case 2:
+		case 3:
+			ep->maxpacket = 64;
+			break;
+		case 4:
+		case 5:
+			ep->maxpacket = 256;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static const struct at91_udc_caps at91sam9263_udc_caps = {
+	.init = at91sam9263_udc_init,
+	.pullup = at91sam9260_udc_pullup,
+};
+
+static const struct of_device_id at91_udc_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-udc",
+		.data = &at91rm9200_udc_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9260-udc",
+		.data = &at91sam9260_udc_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9261-udc",
+		.data = &at91sam9261_udc_caps,
+	},
+	{
+		.compatible = "atmel,at91sam9263-udc",
+		.data = &at91sam9263_udc_caps,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
+
+static void at91udc_of_init(struct at91_udc *udc, struct device_node *np)
 {
 	struct at91_udc_data *board = &udc->board;
-	u32 val;
+	const struct of_device_id *match;
 	enum of_gpio_flags flags;
+	u32 val;
 
 	if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
 		board->vbus_polled = 1;
@@ -1705,6 +1797,10 @@ static void at91udc_of_init(struct at91_udc *udc,
 						  &flags);
 
 	board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
+
+	match = of_match_node(at91_udc_dt_ids, np);
+	if (match)
+		udc->caps = match->data;
 }
 
 static int at91udc_probe(struct platform_device *pdev)
@@ -1713,97 +1809,67 @@ static int at91udc_probe(struct platform_device *pdev)
 	struct at91_udc	*udc;
 	int		retval;
 	struct resource	*res;
+	struct at91_ep	*ep;
+	int		i;
 
-	if (!dev_get_platdata(dev) && !pdev->dev.of_node) {
-		/* small (so we copy it) but critical! */
-		DBG("missing platform_data\n");
-		return -ENODEV;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
-
-	if (!request_mem_region(res->start, resource_size(res), driver_name)) {
-		DBG("someone's using UDC memory\n");
-		return -EBUSY;
-	}
+	udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
+	if (!udc)
+		return -ENOMEM;
 
 	/* init software state */
-	udc = &controller;
 	udc->gadget.dev.parent = dev;
-	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
-		at91udc_of_init(udc, pdev->dev.of_node);
-	else
-		memcpy(&udc->board, dev_get_platdata(dev),
-		       sizeof(struct at91_udc_data));
+	at91udc_of_init(udc, pdev->dev.of_node);
 	udc->pdev = pdev;
 	udc->enabled = 0;
 	spin_lock_init(&udc->lock);
 
-	/* rm9200 needs manual D+ pullup; off by default */
-	if (cpu_is_at91rm9200()) {
-		if (!gpio_is_valid(udc->board.pullup_pin)) {
-			DBG("no D+ pullup?\n");
-			retval = -ENODEV;
-			goto fail0;
-		}
-		retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
-		if (retval) {
-			DBG("D+ pullup is busy\n");
-			goto fail0;
-		}
-		gpio_direction_output(udc->board.pullup_pin,
-				udc->board.pullup_active_low);
+	udc->gadget.ops = &at91_udc_ops;
+	udc->gadget.ep0 = &udc->ep[0].ep;
+	udc->gadget.name = driver_name;
+	udc->gadget.dev.init_name = "gadget";
+
+	for (i = 0; i < NUM_ENDPOINTS; i++) {
+		ep = &udc->ep[i];
+		ep->ep.name = ep_names[i];
+		ep->ep.ops = &at91_ep_ops;
+		ep->udc = udc;
+		ep->int_mask = BIT(i);
+		if (i != 0 && i != 3)
+			ep->is_pingpong = 1;
 	}
 
-	/* newer chips have more FIFO memory than rm9200 */
-	if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
-		udc->ep[0].maxpacket = 64;
-		udc->ep[3].maxpacket = 64;
-		udc->ep[4].maxpacket = 512;
-		udc->ep[5].maxpacket = 512;
-	} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
-		udc->ep[3].maxpacket = 64;
-	} else if (cpu_is_at91sam9263()) {
-		udc->ep[0].maxpacket = 64;
-		udc->ep[3].maxpacket = 64;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	udc->udp_baseaddr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(udc->udp_baseaddr))
+		return PTR_ERR(udc->udp_baseaddr);
 
-	udc->udp_baseaddr = ioremap(res->start, resource_size(res));
-	if (!udc->udp_baseaddr) {
-		retval = -ENOMEM;
-		goto fail0a;
+	if (udc->caps && udc->caps->init) {
+		retval = udc->caps->init(udc);
+		if (retval)
+			return retval;
 	}
 
 	udc_reinit(udc);
 
 	/* get interface and function clocks */
-	udc->iclk = clk_get(dev, "udc_clk");
-	udc->fclk = clk_get(dev, "udpck");
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		udc->uclk = clk_get(dev, "usb_clk");
-	if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) ||
-	    (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) {
-		DBG("clocks missing\n");
-		retval = -ENODEV;
-		goto fail1;
-	}
+	udc->iclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(udc->iclk))
+		return PTR_ERR(udc->iclk);
+
+	udc->fclk = devm_clk_get(dev, "hclk");
+	if (IS_ERR(udc->fclk))
+		return PTR_ERR(udc->fclk);
 
 	/* don't do anything until we have both gadget driver and VBUS */
-	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-		clk_set_rate(udc->uclk, 48000000);
-		retval = clk_prepare(udc->uclk);
-		if (retval)
-			goto fail1;
-	}
+	clk_set_rate(udc->fclk, 48000000);
 	retval = clk_prepare(udc->fclk);
 	if (retval)
-		goto fail1a;
+		return retval;
 
 	retval = clk_prepare_enable(udc->iclk);
 	if (retval)
-		goto fail1b;
+		goto err_unprepare_fclk;
+
 	at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 	at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
 	/* Clear all pending interrupts - UDP may be used by bootloader. */
@@ -1812,18 +1878,21 @@ static int at91udc_probe(struct platform_device *pdev)
 
 	/* request UDC and maybe VBUS irqs */
 	udc->udp_irq = platform_get_irq(pdev, 0);
-	retval = request_irq(udc->udp_irq, at91_udc_irq,
-			0, driver_name, udc);
-	if (retval < 0) {
+	retval = devm_request_irq(dev, udc->udp_irq, at91_udc_irq, 0,
+				  driver_name, udc);
+	if (retval) {
 		DBG("request irq %d failed\n", udc->udp_irq);
-		goto fail1c;
+		goto err_unprepare_iclk;
 	}
+
 	if (gpio_is_valid(udc->board.vbus_pin)) {
-		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
-		if (retval < 0) {
+		retval = devm_gpio_request(dev, udc->board.vbus_pin,
+					   "udc_vbus");
+		if (retval) {
 			DBG("request vbus pin failed\n");
-			goto fail2;
+			goto err_unprepare_iclk;
 		}
+
 		gpio_direction_input(udc->board.vbus_pin);
 
 		/*
@@ -1840,12 +1909,13 @@ static int at91udc_probe(struct platform_device *pdev)
 			mod_timer(&udc->vbus_timer,
 				  jiffies + VBUS_POLL_TIMEOUT);
 		} else {
-			if (request_irq(gpio_to_irq(udc->board.vbus_pin),
-					at91_vbus_irq, 0, driver_name, udc)) {
+			retval = devm_request_irq(dev,
+					gpio_to_irq(udc->board.vbus_pin),
+					at91_vbus_irq, 0, driver_name, udc);
+			if (retval) {
 				DBG("request vbus irq %d failed\n",
 				    udc->board.vbus_pin);
-				retval = -EBUSY;
-				goto fail3;
+				goto err_unprepare_iclk;
 			}
 		}
 	} else {
@@ -1854,49 +1924,27 @@ static int at91udc_probe(struct platform_device *pdev)
 	}
 	retval = usb_add_gadget_udc(dev, &udc->gadget);
 	if (retval)
-		goto fail4;
+		goto err_unprepare_iclk;
 	dev_set_drvdata(dev, udc);
 	device_init_wakeup(dev, 1);
 	create_debug_file(udc);
 
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
 	return 0;
-fail4:
-	if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
-		free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
-fail3:
-	if (gpio_is_valid(udc->board.vbus_pin))
-		gpio_free(udc->board.vbus_pin);
-fail2:
-	free_irq(udc->udp_irq, udc);
-fail1c:
+
+err_unprepare_iclk:
 	clk_unprepare(udc->iclk);
-fail1b:
+err_unprepare_fclk:
 	clk_unprepare(udc->fclk);
-fail1a:
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_unprepare(udc->uclk);
-fail1:
-	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
-		clk_put(udc->uclk);
-	if (!IS_ERR(udc->fclk))
-		clk_put(udc->fclk);
-	if (!IS_ERR(udc->iclk))
-		clk_put(udc->iclk);
-	iounmap(udc->udp_baseaddr);
-fail0a:
-	if (cpu_is_at91rm9200())
-		gpio_free(udc->board.pullup_pin);
-fail0:
-	release_mem_region(res->start, resource_size(res));
+
 	DBG("%s probe failed, %d\n", driver_name, retval);
+
 	return retval;
 }
 
 static int __exit at91udc_remove(struct platform_device *pdev)
 {
 	struct at91_udc *udc = platform_get_drvdata(pdev);
-	struct resource *res;
 	unsigned long	flags;
 
 	DBG("remove\n");
@@ -1911,29 +1959,9 @@ static int __exit at91udc_remove(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 0);
 	remove_debug_file(udc);
-	if (gpio_is_valid(udc->board.vbus_pin)) {
-		free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
-		gpio_free(udc->board.vbus_pin);
-	}
-	free_irq(udc->udp_irq, udc);
-	iounmap(udc->udp_baseaddr);
-
-	if (cpu_is_at91rm9200())
-		gpio_free(udc->board.pullup_pin);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_unprepare(udc->uclk);
 	clk_unprepare(udc->fclk);
 	clk_unprepare(udc->iclk);
 
-	clk_put(udc->iclk);
-	clk_put(udc->fclk);
-	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_put(udc->uclk);
-
 	return 0;
 }
 
@@ -1989,15 +2017,6 @@ static int at91udc_resume(struct platform_device *pdev)
 #define	at91udc_resume	NULL
 #endif
 
-#if defined(CONFIG_OF)
-static const struct of_device_id at91_udc_dt_ids[] = {
-	{ .compatible = "atmel,at91rm9200-udc" },
-	{ /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
-#endif
-
 static struct platform_driver at91_udc_driver = {
 	.remove		= __exit_p(at91udc_remove),
 	.shutdown	= at91udc_shutdown,
@@ -2005,7 +2024,7 @@ static struct platform_driver at91_udc_driver = {
 	.resume		= at91udc_resume,
 	.driver		= {
 		.name	= (char *) driver_name,
-		.of_match_table	= of_match_ptr(at91_udc_dt_ids),
+		.of_match_table	= at91_udc_dt_ids,
 	},
 };
 
diff --git a/drivers/usb/gadget/udc/at91_udc.h b/drivers/usb/gadget/udc/at91_udc.h
index 467dcfb74a51..2679c8b217cc 100644
--- a/drivers/usb/gadget/udc/at91_udc.h
+++ b/drivers/usb/gadget/udc/at91_udc.h
@@ -107,6 +107,11 @@ struct at91_ep {
 	unsigned			fifo_bank:1;
 };
 
+struct at91_udc_caps {
+	int (*init)(struct at91_udc *udc);
+	void (*pullup)(struct at91_udc *udc, int is_on);
+};
+
 /*
  * driver is non-SMP, and just blocks IRQs whenever it needs
  * access protection for chip registers or driver state
@@ -115,6 +120,7 @@ struct at91_udc {
 	struct usb_gadget		gadget;
 	struct at91_ep			ep[NUM_ENDPOINTS];
 	struct usb_gadget_driver	*driver;
+	const struct at91_udc_caps	*caps;
 	unsigned			vbus:1;
 	unsigned			enabled:1;
 	unsigned			clocked:1;
@@ -125,7 +131,7 @@ struct at91_udc {
 	unsigned			active_suspend:1;
 	u8				addr;
 	struct at91_udc_data		board;
-	struct clk			*iclk, *fclk, *uclk;
+	struct clk			*iclk, *fclk;
 	struct platform_device		*pdev;
 	struct proc_dir_entry		*pde;
 	void __iomem			*udp_baseaddr;
@@ -133,6 +139,7 @@ struct at91_udc {
 	spinlock_t			lock;
 	struct timer_list		vbus_timer;
 	struct work_struct		vbus_timer_work;
+	struct regmap			*matrix;
 };
 
 static inline struct at91_udc *to_udc(struct usb_gadget *g)
diff --git a/include/dt-bindings/clock/sh73a0-clock.h b/include/dt-bindings/clock/sh73a0-clock.h
new file mode 100644
index 000000000000..1dd3eb2b7d90
--- /dev/null
+++ b/include/dt-bindings/clock/sh73a0-clock.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014 Ulrich Hecht
+ *
+ * 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.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_SH73A0_H__
+#define __DT_BINDINGS_CLOCK_SH73A0_H__
+
+/* CPG */
+#define SH73A0_CLK_MAIN		0
+#define SH73A0_CLK_PLL0		1
+#define SH73A0_CLK_PLL1		2
+#define SH73A0_CLK_PLL2		3
+#define SH73A0_CLK_PLL3		4
+#define SH73A0_CLK_DSI0PHY	5
+#define SH73A0_CLK_DSI1PHY	6
+#define SH73A0_CLK_ZG		7
+#define SH73A0_CLK_M3		8
+#define SH73A0_CLK_B		9
+#define SH73A0_CLK_M1		10
+#define SH73A0_CLK_M2		11
+#define SH73A0_CLK_Z		12
+#define SH73A0_CLK_ZX		13
+#define SH73A0_CLK_HP		14
+
+/* MSTP0 */
+#define SH73A0_CLK_IIC2	1
+
+/* MSTP1 */
+#define SH73A0_CLK_CEU1		29
+#define SH73A0_CLK_CSI2_RX1	28
+#define SH73A0_CLK_CEU0		27
+#define SH73A0_CLK_CSI2_RX0	26
+#define SH73A0_CLK_TMU0		25
+#define SH73A0_CLK_DSITX0	18
+#define SH73A0_CLK_IIC0		16
+#define SH73A0_CLK_SGX		12
+#define SH73A0_CLK_LCDC0	0
+
+/* MSTP2 */
+#define SH73A0_CLK_SCIFA7	19
+#define SH73A0_CLK_SY_DMAC	18
+#define SH73A0_CLK_MP_DMAC	17
+#define SH73A0_CLK_SCIFA5	7
+#define SH73A0_CLK_SCIFB	6
+#define SH73A0_CLK_SCIFA0	4
+#define SH73A0_CLK_SCIFA1	3
+#define SH73A0_CLK_SCIFA2	2
+#define SH73A0_CLK_SCIFA3	1
+#define SH73A0_CLK_SCIFA4	0
+
+/* MSTP3 */
+#define SH73A0_CLK_SCIFA6	31
+#define SH73A0_CLK_CMT1		29
+#define SH73A0_CLK_FSI		28
+#define SH73A0_CLK_IRDA		25
+#define SH73A0_CLK_IIC1		23
+#define SH73A0_CLK_USB		22
+#define SH73A0_CLK_FLCTL	15
+#define SH73A0_CLK_SDHI0	14
+#define SH73A0_CLK_SDHI1	13
+#define SH73A0_CLK_MMCIF0	12
+#define SH73A0_CLK_SDHI2	11
+#define SH73A0_CLK_TPU0		4
+#define SH73A0_CLK_TPU1		3
+#define SH73A0_CLK_TPU2		2
+#define SH73A0_CLK_TPU3		1
+#define SH73A0_CLK_TPU4		0
+
+/* MSTP4 */
+#define SH73A0_CLK_IIC3		11
+#define SH73A0_CLK_IIC4		10
+#define SH73A0_CLK_KEYSC	3
+
+#endif
diff --git a/include/linux/mfd/syscon/atmel-matrix.h b/include/linux/mfd/syscon/atmel-matrix.h
new file mode 100644
index 000000000000..8293c3e2a82a
--- /dev/null
+++ b/include/linux/mfd/syscon/atmel-matrix.h
@@ -0,0 +1,117 @@
+/*
+ *  Copyright (C) 2014 Atmel Corporation.
+ *
+ * Memory Controllers (MATRIX, EBI) - System peripherals registers.
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
+#define _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
+
+#define AT91SAM9260_MATRIX_MCFG			0x00
+#define AT91SAM9260_MATRIX_SCFG			0x40
+#define AT91SAM9260_MATRIX_PRS			0x80
+#define AT91SAM9260_MATRIX_MRCR			0x100
+#define AT91SAM9260_MATRIX_EBICSA		0x11c
+
+#define AT91SAM9261_MATRIX_MRCR			0x0
+#define AT91SAM9261_MATRIX_SCFG			0x4
+#define AT91SAM9261_MATRIX_TCR			0x24
+#define AT91SAM9261_MATRIX_EBICSA		0x30
+#define AT91SAM9261_MATRIX_USBPUCR		0x34
+
+#define AT91SAM9263_MATRIX_MCFG			0x00
+#define AT91SAM9263_MATRIX_SCFG			0x40
+#define AT91SAM9263_MATRIX_PRS			0x80
+#define AT91SAM9263_MATRIX_MRCR			0x100
+#define AT91SAM9263_MATRIX_TCR			0x114
+#define AT91SAM9263_MATRIX_EBI0CSA		0x120
+#define AT91SAM9263_MATRIX_EBI1CSA		0x124
+
+#define AT91SAM9RL_MATRIX_MCFG			0x00
+#define AT91SAM9RL_MATRIX_SCFG			0x40
+#define AT91SAM9RL_MATRIX_PRS			0x80
+#define AT91SAM9RL_MATRIX_MRCR			0x100
+#define AT91SAM9RL_MATRIX_TCR			0x114
+#define AT91SAM9RL_MATRIX_EBICSA		0x120
+
+#define AT91SAM9G45_MATRIX_MCFG			0x00
+#define AT91SAM9G45_MATRIX_SCFG			0x40
+#define AT91SAM9G45_MATRIX_PRS			0x80
+#define AT91SAM9G45_MATRIX_MRCR			0x100
+#define AT91SAM9G45_MATRIX_TCR			0x110
+#define AT91SAM9G45_MATRIX_DDRMPR		0x118
+#define AT91SAM9G45_MATRIX_EBICSA		0x128
+
+#define AT91SAM9N12_MATRIX_MCFG			0x00
+#define AT91SAM9N12_MATRIX_SCFG			0x40
+#define AT91SAM9N12_MATRIX_PRS			0x80
+#define AT91SAM9N12_MATRIX_MRCR			0x100
+#define AT91SAM9N12_MATRIX_EBICSA		0x118
+
+#define AT91SAM9X5_MATRIX_MCFG			0x00
+#define AT91SAM9X5_MATRIX_SCFG			0x40
+#define AT91SAM9X5_MATRIX_PRS			0x80
+#define AT91SAM9X5_MATRIX_MRCR			0x100
+#define AT91SAM9X5_MATRIX_EBICSA		0x120
+
+#define SAMA5D3_MATRIX_MCFG			0x00
+#define SAMA5D3_MATRIX_SCFG			0x40
+#define SAMA5D3_MATRIX_PRS			0x80
+#define SAMA5D3_MATRIX_MRCR			0x100
+
+#define AT91_MATRIX_MCFG(o, x)			((o) + ((x) * 0x4))
+#define AT91_MATRIX_ULBT			GENMASK(2, 0)
+#define AT91_MATRIX_ULBT_INFINITE		(0 << 0)
+#define AT91_MATRIX_ULBT_SINGLE			(1 << 0)
+#define AT91_MATRIX_ULBT_FOUR			(2 << 0)
+#define AT91_MATRIX_ULBT_EIGHT			(3 << 0)
+#define AT91_MATRIX_ULBT_SIXTEEN		(4 << 0)
+
+#define AT91_MATRIX_SCFG(o, x)			((o) + ((x) * 0x4))
+#define AT91_MATRIX_SLOT_CYCLE			GENMASK(7,  0)
+#define AT91_MATRIX_DEFMSTR_TYPE		GENMASK(17, 16)
+#define AT91_MATRIX_DEFMSTR_TYPE_NONE		(0 << 16)
+#define AT91_MATRIX_DEFMSTR_TYPE_LAST		(1 << 16)
+#define AT91_MATRIX_DEFMSTR_TYPE_FIXED		(2 << 16)
+#define AT91_MATRIX_FIXED_DEFMSTR		GENMASK(20, 18)
+#define AT91_MATRIX_ARBT			GENMASK(25, 24)
+#define AT91_MATRIX_ARBT_ROUND_ROBIN		(0 << 24)
+#define AT91_MATRIX_ARBT_FIXED_PRIORITY		(1 << 24)
+
+#define AT91_MATRIX_ITCM_SIZE			GENMASK(3, 0)
+#define AT91_MATRIX_ITCM_0			(0 << 0)
+#define AT91_MATRIX_ITCM_16			(5 << 0)
+#define AT91_MATRIX_ITCM_32			(6 << 0)
+#define AT91_MATRIX_ITCM_64			(7 << 0)
+#define	AT91_MATRIX_DTCM_SIZE			GENMASK(7, 4)
+#define	AT91_MATRIX_DTCM_0			(0 << 4)
+#define	AT91_MATRIX_DTCM_16			(5 << 4)
+#define AT91_MATRIX_DTCM_32			(6 << 4)
+#define AT91_MATRIX_DTCM_64			(7 << 4)
+
+#define AT91_MATRIX_PRAS(o, x)			((o) + ((x) * 0x8))
+#define AT91_MATRIX_PRBS(o, x)			((o) + ((x) * 0x8) + 0x4)
+#define AT91_MATRIX_MPR(x)			GENMASK(((x) * 0x4) + 1, ((x) * 0x4))
+
+#define AT91_MATRIX_RCB(x)			BIT(x)
+
+#define AT91_MATRIX_CSA(cs, val)		(val << (cs))
+#define AT91_MATRIX_DBPUC			BIT(8)
+#define AT91_MATRIX_DBPDC			BIT(9)
+#define AT91_MATRIX_VDDIOMSEL			BIT(16)
+#define AT91_MATRIX_VDDIOMSEL_1_8V		(0 << 16)
+#define AT91_MATRIX_VDDIOMSEL_3_3V		(1 << 16)
+#define AT91_MATRIX_EBI_IOSR			BIT(17)
+#define AT91_MATRIX_DDR_IOSR			BIT(18)
+#define AT91_MATRIX_NFD0_SELECT			BIT(24)
+#define AT91_MATRIX_DDR_MP_EN			BIT(25)
+#define AT91_MATRIX_EBI_NUM_CS			8
+
+#define AT91_MATRIX_USBPUCR_PUON		BIT(30)
+
+#endif /* _LINUX_MFD_SYSCON_ATMEL_MATRIX_H */
diff --git a/include/linux/mfd/syscon/atmel-smc.h b/include/linux/mfd/syscon/atmel-smc.h
new file mode 100644
index 000000000000..be6ebe64eebe
--- /dev/null
+++ b/include/linux/mfd/syscon/atmel-smc.h
@@ -0,0 +1,173 @@
+/*
+ * Atmel SMC (Static Memory Controller) register offsets and bit definitions.
+ *
+ * Copyright (C) 2014 Atmel
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_
+#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_
+
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+
+#define AT91SAM9_SMC_GENERIC		0x00
+#define AT91SAM9_SMC_GENERIC_BLK_SZ	0x10
+
+#define SAMA5_SMC_GENERIC		0x600
+#define SAMA5_SMC_GENERIC_BLK_SZ	0x14
+
+#define AT91SAM9_SMC_SETUP(o)		((o) + 0x00)
+#define AT91SAM9_SMC_NWESETUP(x)	(x)
+#define AT91SAM9_SMC_NCS_WRSETUP(x)	((x) << 8)
+#define AT91SAM9_SMC_NRDSETUP(x)	((x) << 16)
+#define AT91SAM9_SMC_NCS_NRDSETUP(x)	((x) << 24)
+
+#define AT91SAM9_SMC_PULSE(o)		((o) + 0x04)
+#define AT91SAM9_SMC_NWEPULSE(x)	(x)
+#define AT91SAM9_SMC_NCS_WRPULSE(x)	((x) << 8)
+#define AT91SAM9_SMC_NRDPULSE(x)	((x) << 16)
+#define AT91SAM9_SMC_NCS_NRDPULSE(x)	((x) << 24)
+
+#define AT91SAM9_SMC_CYCLE(o)		((o) + 0x08)
+#define AT91SAM9_SMC_NWECYCLE(x)	(x)
+#define AT91SAM9_SMC_NRDCYCLE(x)	((x) << 16)
+
+#define AT91SAM9_SMC_MODE(o)		((o) + 0x0c)
+#define SAMA5_SMC_MODE(o)		((o) + 0x10)
+#define AT91_SMC_READMODE		BIT(0)
+#define AT91_SMC_READMODE_NCS		(0 << 0)
+#define AT91_SMC_READMODE_NRD		(1 << 0)
+#define AT91_SMC_WRITEMODE		BIT(1)
+#define AT91_SMC_WRITEMODE_NCS		(0 << 1)
+#define AT91_SMC_WRITEMODE_NWE		(1 << 1)
+#define AT91_SMC_EXNWMODE		GENMASK(5, 4)
+#define AT91_SMC_EXNWMODE_DISABLE	(0 << 4)
+#define AT91_SMC_EXNWMODE_FROZEN	(2 << 4)
+#define AT91_SMC_EXNWMODE_READY		(3 << 4)
+#define AT91_SMC_BAT			BIT(8)
+#define AT91_SMC_BAT_SELECT		(0 << 8)
+#define AT91_SMC_BAT_WRITE		(1 << 8)
+#define AT91_SMC_DBW			GENMASK(13, 12)
+#define AT91_SMC_DBW_8			(0 << 12)
+#define AT91_SMC_DBW_16			(1 << 12)
+#define AT91_SMC_DBW_32			(2 << 12)
+#define AT91_SMC_TDF			GENMASK(19, 16)
+#define AT91_SMC_TDF_(x)		((((x) - 1) << 16) & AT91_SMC_TDF)
+#define AT91_SMC_TDF_MAX		16
+#define AT91_SMC_TDFMODE_OPTIMIZED	BIT(20)
+#define AT91_SMC_PMEN			BIT(24)
+#define AT91_SMC_PS			GENMASK(29, 28)
+#define AT91_SMC_PS_4			(0 << 28)
+#define AT91_SMC_PS_8			(1 << 28)
+#define AT91_SMC_PS_16			(2 << 28)
+#define AT91_SMC_PS_32			(3 << 28)
+
+
+/*
+ * This function converts a setup timing expressed in nanoseconds into an
+ * encoded value that can be written in the SMC_SETUP register.
+ *
+ * The following formula is described in atmel datasheets (section
+ * "SMC Setup Register"):
+ *
+ * setup length = (128* SETUP[5] + SETUP[4:0])
+ *
+ * where setup length is the timing expressed in cycles.
+ */
+static inline u32 at91sam9_smc_setup_ns_to_cycles(unsigned int clk_rate,
+						  u32 timing_ns)
+{
+	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
+	u32 coded_cycles = 0;
+	u32 cycles;
+
+	cycles = DIV_ROUND_UP(timing_ns, clk_period);
+	if (cycles / 32) {
+		coded_cycles |= 1 << 5;
+		if (cycles < 128)
+			cycles = 0;
+	}
+
+	coded_cycles |= cycles % 32;
+
+	return coded_cycles;
+}
+
+/*
+ * This function converts a pulse timing expressed in nanoseconds into an
+ * encoded value that can be written in the SMC_PULSE register.
+ *
+ * The following formula is described in atmel datasheets (section
+ * "SMC Pulse Register"):
+ *
+ * pulse length = (256* PULSE[6] + PULSE[5:0])
+ *
+ * where pulse length is the timing expressed in cycles.
+ */
+static inline u32 at91sam9_smc_pulse_ns_to_cycles(unsigned int clk_rate,
+						  u32 timing_ns)
+{
+	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
+	u32 coded_cycles = 0;
+	u32 cycles;
+
+	cycles = DIV_ROUND_UP(timing_ns, clk_period);
+	if (cycles / 64) {
+		coded_cycles |= 1 << 6;
+		if (cycles < 256)
+			cycles = 0;
+	}
+
+	coded_cycles |= cycles % 64;
+
+	return coded_cycles;
+}
+
+/*
+ * This function converts a cycle timing expressed in nanoseconds into an
+ * encoded value that can be written in the SMC_CYCLE register.
+ *
+ * The following formula is described in atmel datasheets (section
+ * "SMC Cycle Register"):
+ *
+ * cycle length = (CYCLE[8:7]*256 + CYCLE[6:0])
+ *
+ * where cycle length is the timing expressed in cycles.
+ */
+static inline u32 at91sam9_smc_cycle_ns_to_cycles(unsigned int clk_rate,
+						  u32 timing_ns)
+{
+	u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
+	u32 coded_cycles = 0;
+	u32 cycles;
+
+	cycles = DIV_ROUND_UP(timing_ns, clk_period);
+	if (cycles / 128) {
+		coded_cycles = cycles / 256;
+		cycles %= 256;
+		if (cycles >= 128) {
+			coded_cycles++;
+			cycles = 0;
+		}
+
+		if (coded_cycles > 0x3) {
+			coded_cycles = 0x3;
+			cycles = 0x7f;
+		}
+
+		coded_cycles <<= 7;
+	}
+
+	coded_cycles |= cycles % 128;
+
+	return coded_cycles;
+}
+
+#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */
diff --git a/include/linux/platform_data/cpuidle-exynos.h b/include/linux/platform_data/cpuidle-exynos.h
new file mode 100644
index 000000000000..bfa40e4c5d5f
--- /dev/null
+++ b/include/linux/platform_data/cpuidle-exynos.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __CPUIDLE_EXYNOS_H
+#define __CPUIDLE_EXYNOS_H
+
+struct cpuidle_exynos_data {
+	int (*cpu0_enter_aftr)(void);
+	int (*cpu1_powerdown)(void);
+	void (*pre_enter_aftr)(void);
+	void (*post_enter_aftr)(void);
+};
+
+#endif