Browse Source

update to 3.15, rb532 pci patch no longer required

Waldemar Brodkorb 11 years ago
parent
commit
0b9f665205
32 changed files with 6647 additions and 12470 deletions
  1. 4 4
      mk/kernel-ver.mk
  2. 0 12452
      target/arm/cubox-i/patches/3.15-rc7/rmk.patch
  3. 6640 0
      target/arm/cubox-i/patches/3.15/rmk.patch
  4. 0 0
      target/arm/cubox-i/patches/3.15/sdma-firmware-cubox-i.patch
  5. 2 2
      target/config/Config.in.kernelversion.choice
  6. 1 1
      target/config/Config.in.kernelversion.default
  7. 0 0
      target/linux/patches/3.15-rc8/bsd-compatibility.patch
  8. 0 0
      target/linux/patches/3.15-rc8/cleankernel.patch
  9. 0 0
      target/linux/patches/3.15-rc8/defaults.patch
  10. 0 0
      target/linux/patches/3.15-rc8/disable-netfilter.patch
  11. 0 0
      target/linux/patches/3.15-rc8/export-symbol-for-exmap.patch
  12. 0 0
      target/linux/patches/3.15-rc8/gemalto.patch
  13. 0 0
      target/linux/patches/3.15-rc8/initramfs-nosizelimit.patch
  14. 0 0
      target/linux/patches/3.15-rc8/lemote-rfkill.patch
  15. 0 0
      target/linux/patches/3.15-rc8/microblaze-axi.patch
  16. 0 0
      target/linux/patches/3.15-rc8/microblaze-ethernet.patch
  17. 0 0
      target/linux/patches/3.15-rc8/mkpiggy.patch
  18. 0 0
      target/linux/patches/3.15-rc8/mtd-rootfs.patch
  19. 0 0
      target/linux/patches/3.15-rc8/nfsv3-tcp.patch
  20. 0 0
      target/linux/patches/3.15-rc8/non-static.patch
  21. 0 0
      target/linux/patches/3.15-rc8/patch-yaffs2
  22. 0 0
      target/linux/patches/3.15-rc8/ppc64-missing-zlib.patch
  23. 0 0
      target/linux/patches/3.15-rc8/relocs.patch
  24. 0 0
      target/linux/patches/3.15-rc8/sgidefs.patch
  25. 0 0
      target/linux/patches/3.15-rc8/sortext.patch
  26. 0 0
      target/linux/patches/3.15-rc8/startup.patch
  27. 0 0
      target/linux/patches/3.15-rc8/tcp-fastopen.patch
  28. 0 0
      target/linux/patches/3.15-rc8/uuid.patch
  29. 0 0
      target/linux/patches/3.15-rc8/wlan-cf.patch
  30. 0 0
      target/linux/patches/3.15-rc8/xargs.patch
  31. 0 11
      target/mips/mikrotik-rb532/patches/3.15-rc7/rb532-pci.patch
  32. 0 0
      target/mips/mikrotik-rb532/patches/3.15-rc8/rb532-serial.patch

+ 4 - 4
mk/kernel-ver.mk

@@ -1,8 +1,8 @@
-ifeq ($(ADK_KERNEL_VERSION_3_15_RC7),y)
-KERNEL_VERSION:=	3.15-rc7
-KERNEL_MOD_VERSION:=	3.15.0-rc7
+ifeq ($(ADK_KERNEL_VERSION_3_15),y)
+KERNEL_VERSION:=	3.15
+KERNEL_MOD_VERSION:=	3.15.0
 KERNEL_RELEASE:=	1
-KERNEL_MD5SUM:=		a56d456b69b2e984aea0329bed0bda4d
+KERNEL_MD5SUM:=		97ca1625bb40368dc41b9a7971549071
 endif
 ifeq ($(ADK_KERNEL_VERSION_3_14_5),y)
 KERNEL_VERSION:=	3.14.5

+ 0 - 12452
target/arm/cubox-i/patches/3.15-rc7/rmk.patch

@@ -1,12452 +0,0 @@
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts linux-3.15-rc6/arch/arm/boot/dts/imx6dl-hummingboard.dts
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6dl-hummingboard.dts	2014-05-23 11:26:48.244939835 +0200
-@@ -67,6 +67,14 @@
- 	status = "okay";
- };
- 
-+&hdmi {
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_hummingboard_hdmi>;
-+	ddc-i2c-bus = <&i2c2>;
-+	status = "okay";
-+	crtcs = <&ipu1 0>;
-+};
-+
- &i2c1 {
- 	pinctrl-names = "default";
- 	pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
-@@ -82,6 +90,13 @@
- 	 */
- };
- 
-+&i2c2 {
-+	clock-frequency = <100000>;
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_hummingboard_i2c2>;
-+	status = "okay";
-+};
-+
- &iomuxc {
- 	hummingboard {
- 		pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 {
-@@ -97,6 +112,12 @@
- 			>;
- 		};
- 
-+		pinctrl_hummingboard_hdmi: hummingboard-hdmi {
-+			fsl,pins = <
-+				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
-+			>;
-+		};
-+
- 		pinctrl_hummingboard_i2c1: hummingboard-i2c1 {
- 			fsl,pins = <
- 				MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
-@@ -104,6 +125,13 @@
- 			>;
- 		};
- 
-+		pinctrl_hummingboard_i2c2: hummingboard-i2c2 {
-+			fsl,pins = <
-+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
-+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-+			>;
-+		};
-+
- 		pinctrl_hummingboard_spdif: hummingboard-spdif {
- 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- 		};
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6q-cubox-i.dts linux-3.15-rc6/arch/arm/boot/dts/imx6q-cubox-i.dts
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6q-cubox-i.dts	2014-05-23 11:26:48.244939835 +0200
-@@ -13,4 +13,8 @@
- 
- &sata {
- 	status = "okay";
-+	fsl,transmit-level-mV = <1104>;
-+	fsl,transmit-boost-mdB = <0>;
-+	fsl,transmit-atten-16ths = <9>;
-+	fsl,no-spread-spectrum;
- };
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.15-rc6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -12,6 +12,19 @@
- 		pinctrl-0 = <&pinctrl_cubox_i_ir>;
- 	};
- 
-+	pwmleds {
-+		compatible = "pwm-leds";
-+		pinctrl-names = "default";
-+		pinctrl-0 = <&pinctrl_cubox_i_pwm1>;
-+
-+		front {
-+			active-low;
-+			label = "imx6:red:front";
-+			max-brightness = <248>;
-+			pwms = <&pwm1 0 50000>;
-+		};
-+	};
-+
- 	regulators {
- 		compatible = "simple-bus";
- 
-@@ -55,6 +68,21 @@
- 	};
- };
- 
-+&hdmi {
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_cubox_i_hdmi>;
-+	ddc-i2c-bus = <&i2c2>;
-+	status = "okay";
-+	crtcs = <&ipu1 0>;
-+};
-+
-+&i2c2 {
-+	clock-frequency = <100000>;
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_cubox_i_i2c2>;
-+	status = "okay";
-+};
-+
- &i2c3 {
- 	pinctrl-names = "default";
- 	pinctrl-0 = <&pinctrl_cubox_i_i2c3>;
-@@ -69,6 +97,19 @@
- 
- &iomuxc {
- 	cubox_i {
-+		pinctrl_cubox_i_hdmi: cubox-i-hdmi {
-+			fsl,pins = <
-+				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
-+			>;
-+		};
-+
-+		pinctrl_cubox_i_i2c2: cubox-i-i2c2 {
-+			fsl,pins = <
-+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
-+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
-+			>;
-+		};
-+
- 		pinctrl_cubox_i_i2c3: cubox-i-i2c3 {
- 			fsl,pins = <
- 				MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
-@@ -82,6 +123,10 @@
- 			>;
- 		};
- 
-+		pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
-+			fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
-+		};
-+
- 		pinctrl_cubox_i_spdif: cubox-i-spdif {
- 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
- 		};
-@@ -111,6 +156,28 @@
- 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
- 			>;
- 		};
-+
-+		pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz {
-+			fsl,pins = <
-+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170b9
-+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100b9
-+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
-+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
-+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
-+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
-+			>;
-+		};
-+
-+		pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz {
-+			fsl,pins = <
-+				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170f9
-+				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100f9
-+				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
-+				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
-+				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
-+				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
-+			>;
-+		};
- 	};
- };
- 
-@@ -130,9 +197,19 @@
- 	status = "okay";
- };
- 
-+&uart4 {
-+	status = "okay";
-+};
-+
-+&usdhc1 {
-+	status = "okay";
-+};
-+
- &usdhc2 {
--	pinctrl-names = "default";
-+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
- 	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
-+	pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>;
-+	pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>;
- 	vmmc-supply = <&reg_3p3v>;
- 	cd-gpios = <&gpio1 4 0>;
- 	status = "okay";
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl.dtsi linux-3.15-rc6/arch/arm/boot/dts/imx6qdl.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6qdl.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -128,6 +128,8 @@
- 			cache-level = <2>;
- 			arm,tag-latency = <4 2 3>;
- 			arm,data-latency = <4 2 3>;
-+			arm,dynamic-clk-gating;
-+			arm,standby-mode;
- 		};
- 
- 		pcie: pcie@0x01000000 {
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.15-rc6/arch/arm/boot/dts/imx6qdl-microsom.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6qdl-microsom.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -1,9 +1,69 @@
- /*
-  * Copyright (C) 2013,2014 Russell King
-  */
-+#include <dt-bindings/gpio/gpio.h>
-+/ {
-+	regulators {
-+		compatible = "simple-bus";
-+
-+		reg_brcm_osc: brcm-osc-reg {
-+			compatible = "regulator-fixed";
-+			enable-active-high;
-+			gpio = <&gpio5 5 0>;
-+			pinctrl-names = "default";
-+			pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>;
-+			regulator-name = "brcm_osc_reg";
-+			regulator-min-microvolt = <3300000>;
-+			regulator-max-microvolt = <3300000>;
-+			regulator-always-on;
-+			regulator-boot-on;
-+		};
-+
-+		reg_brcm: brcm-reg {
-+			compatible = "regulator-fixed";
-+			enable-active-high;
-+			gpio = <&gpio3 19 0>;
-+			pinctrl-names = "default";
-+			pinctrl-0 = <&pinctrl_microsom_brcm_reg>;
-+			regulator-name = "brcm_reg";
-+			regulator-min-microvolt = <3300000>;
-+			regulator-max-microvolt = <3300000>;
-+			startup-delay-us = <200000>;
-+		};
-+	};
-+};
- 
- &iomuxc {
- 	microsom {
-+		pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg {
-+			fsl,pins = <
-+				MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_reg: microsom-brcm-reg {
-+			fsl,pins = <
-+				MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
-+			fsl,pins = <
-+				MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K	0x1b0b0
-+				MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20	0x40013070
-+				MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26	0x40013070
-+				MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27	0x40013070
-+			>;
-+		};
-+
-+		pinctrl_microsom_brcm_bt: microsom-brcm-bt {
-+			fsl,pins = <
-+				MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00	0x40013070
-+				MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01	0x40013070
-+				MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04	0x40013070
-+			>;
-+		};
-+
- 		pinctrl_microsom_uart1: microsom-uart1 {
- 			fsl,pins = <
- 				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
-@@ -11,6 +71,15 @@
- 			>;
- 		};
- 
-+		pinctrl_microsom_uart4_1: microsom-uart4 {
-+			fsl,pins = <
-+				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
-+				MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
-+			>;
-+		};
-+
- 		pinctrl_microsom_usbotg: microsom-usbotg {
- 			/*
- 			 * Similar to pinctrl_usbotg_2, but we want it
-@@ -18,6 +87,17 @@
- 			 */
- 			fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
- 		};
-+
-+		pinctrl_microsom_usdhc1: microsom-usdhc1 {
-+			fsl,pins = <
-+				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
-+				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
-+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
-+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
-+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
-+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
-+			>;
-+		};
- 	};
- };
- 
-@@ -27,7 +107,25 @@
- 	status = "okay";
- };
- 
-+/* UART4 - Connected to optional BRCM Wifi/BT/FM */
-+&uart4 {
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>;
-+	fsl,uart-has-rtscts;
-+};
-+
- &usbotg {
- 	pinctrl-names = "default";
- 	pinctrl-0 = <&pinctrl_microsom_usbotg>;
- };
-+
-+/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */
-+&usdhc1 {
-+	card-external-vcc-supply = <&reg_brcm>;
-+	card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>;
-+	keep-power-in-suspend;
-+	non-removable;
-+	pinctrl-names = "default";
-+	pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>;
-+	vmmc-supply = <&reg_brcm>;
-+};
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/imx6sl.dtsi linux-3.15-rc6/arch/arm/boot/dts/imx6sl.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/imx6sl.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/imx6sl.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -111,6 +111,8 @@
- 			cache-level = <2>;
- 			arm,tag-latency = <4 2 3>;
- 			arm,data-latency = <4 2 3>;
-+			arm,dynamic-clk-gating;
-+			arm,standby-mode;
- 		};
- 
- 		pmu {
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/marco.dtsi linux-3.15-rc6/arch/arm/boot/dts/marco.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/marco.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/marco.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -36,7 +36,7 @@
- 		ranges = <0x40000000 0x40000000 0xa0000000>;
- 
- 		l2-cache-controller@c0030000 {
--			compatible = "sirf,marco-pl310-cache", "arm,pl310-cache";
-+			compatible = "arm,pl310-cache";
- 			reg = <0xc0030000 0x1000>;
- 			interrupts = <0 59 0>;
- 			arm,tag-latency = <1 1 1>;
-diff -Nur linux-3.15-rc6.orig/arch/arm/boot/dts/prima2.dtsi linux-3.15-rc6/arch/arm/boot/dts/prima2.dtsi
---- linux-3.15-rc6.orig/arch/arm/boot/dts/prima2.dtsi	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/boot/dts/prima2.dtsi	2014-05-23 11:26:48.244939835 +0200
-@@ -48,7 +48,7 @@
- 		ranges = <0x40000000 0x40000000 0x80000000>;
- 
- 		l2-cache-controller@80040000 {
--			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
-+			compatible = "arm,pl310-cache";
- 			reg = <0x80040000 0x1000>;
- 			interrupts = <59>;
- 			arm,tag-latency = <1 1 1>;
-diff -Nur linux-3.15-rc6.orig/arch/arm/configs/imx_v6_v7_defconfig linux-3.15-rc6/arch/arm/configs/imx_v6_v7_defconfig
---- linux-3.15-rc6.orig/arch/arm/configs/imx_v6_v7_defconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/configs/imx_v6_v7_defconfig	2014-05-23 11:26:48.248939848 +0200
-@@ -245,6 +245,7 @@
- CONFIG_DRM_IMX_LDB=y
- CONFIG_DRM_IMX_IPUV3_CORE=y
- CONFIG_DRM_IMX_IPUV3=y
-+CONFIG_DRM_IMX_HDMI=y
- CONFIG_COMMON_CLK_DEBUG=y
- # CONFIG_IOMMU_SUPPORT is not set
- CONFIG_PWM=y
-diff -Nur linux-3.15-rc6.orig/arch/arm/include/asm/hardware/cache-l2x0.h linux-3.15-rc6/arch/arm/include/asm/hardware/cache-l2x0.h
---- linux-3.15-rc6.orig/arch/arm/include/asm/hardware/cache-l2x0.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/include/asm/hardware/cache-l2x0.h	2014-05-23 11:26:48.248939848 +0200
-@@ -26,8 +26,8 @@
- #define L2X0_CACHE_TYPE			0x004
- #define L2X0_CTRL			0x100
- #define L2X0_AUX_CTRL			0x104
--#define L2X0_TAG_LATENCY_CTRL		0x108
--#define L2X0_DATA_LATENCY_CTRL		0x10C
-+#define L310_TAG_LATENCY_CTRL		0x108
-+#define L310_DATA_LATENCY_CTRL		0x10C
- #define L2X0_EVENT_CNT_CTRL		0x200
- #define L2X0_EVENT_CNT1_CFG		0x204
- #define L2X0_EVENT_CNT0_CFG		0x208
-@@ -54,53 +54,93 @@
- #define L2X0_LOCKDOWN_WAY_D_BASE	0x900
- #define L2X0_LOCKDOWN_WAY_I_BASE	0x904
- #define L2X0_LOCKDOWN_STRIDE		0x08
--#define L2X0_ADDR_FILTER_START		0xC00
--#define L2X0_ADDR_FILTER_END		0xC04
-+#define L310_ADDR_FILTER_START		0xC00
-+#define L310_ADDR_FILTER_END		0xC04
- #define L2X0_TEST_OPERATION		0xF00
- #define L2X0_LINE_DATA			0xF10
- #define L2X0_LINE_TAG			0xF30
- #define L2X0_DEBUG_CTRL			0xF40
--#define L2X0_PREFETCH_CTRL		0xF60
--#define L2X0_POWER_CTRL			0xF80
--#define   L2X0_DYNAMIC_CLK_GATING_EN	(1 << 1)
--#define   L2X0_STNDBY_MODE_EN		(1 << 0)
-+#define L310_PREFETCH_CTRL		0xF60
-+#define L310_POWER_CTRL			0xF80
-+#define   L310_DYNAMIC_CLK_GATING_EN	(1 << 1)
-+#define   L310_STNDBY_MODE_EN		(1 << 0)
- 
- /* Registers shifts and masks */
- #define L2X0_CACHE_ID_PART_MASK		(0xf << 6)
- #define L2X0_CACHE_ID_PART_L210		(1 << 6)
-+#define L2X0_CACHE_ID_PART_L220		(2 << 6)
- #define L2X0_CACHE_ID_PART_L310		(3 << 6)
- #define L2X0_CACHE_ID_RTL_MASK          0x3f
--#define L2X0_CACHE_ID_RTL_R0P0          0x0
--#define L2X0_CACHE_ID_RTL_R1P0          0x2
--#define L2X0_CACHE_ID_RTL_R2P0          0x4
--#define L2X0_CACHE_ID_RTL_R3P0          0x5
--#define L2X0_CACHE_ID_RTL_R3P1          0x6
--#define L2X0_CACHE_ID_RTL_R3P2          0x8
--
--#define L2X0_AUX_CTRL_MASK			0xc0000fff
-+#define L210_CACHE_ID_RTL_R0P2_02	0x00
-+#define L210_CACHE_ID_RTL_R0P1		0x01
-+#define L210_CACHE_ID_RTL_R0P2_01	0x02
-+#define L210_CACHE_ID_RTL_R0P3		0x03
-+#define L210_CACHE_ID_RTL_R0P4		0x0b
-+#define L210_CACHE_ID_RTL_R0P5		0x0f
-+#define L220_CACHE_ID_RTL_R1P7_01REL0	0x06
-+#define L310_CACHE_ID_RTL_R0P0		0x00
-+#define L310_CACHE_ID_RTL_R1P0		0x02
-+#define L310_CACHE_ID_RTL_R2P0		0x04
-+#define L310_CACHE_ID_RTL_R3P0		0x05
-+#define L310_CACHE_ID_RTL_R3P1		0x06
-+#define L310_CACHE_ID_RTL_R3P1_50REL0	0x07
-+#define L310_CACHE_ID_RTL_R3P2		0x08
-+#define L310_CACHE_ID_RTL_R3P3		0x09
-+
-+/* L2C auxiliary control register - bits common to L2C-210/220/310 */
-+#define L2C_AUX_CTRL_WAY_SIZE_SHIFT		17
-+#define L2C_AUX_CTRL_WAY_SIZE_MASK		(7 << 17)
-+#define L2C_AUX_CTRL_WAY_SIZE(n)		((n) << 17)
-+#define L2C_AUX_CTRL_EVTMON_ENABLE		BIT(20)
-+#define L2C_AUX_CTRL_PARITY_ENABLE		BIT(21)
-+#define L2C_AUX_CTRL_SHARED_OVERRIDE		BIT(22)
-+/* L2C-210/220 common bits */
- #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT	0
--#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK	0x7
-+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK	(7 << 0)
- #define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT	3
--#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK	(0x7 << 3)
-+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK	(7 << 3)
- #define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT		6
--#define L2X0_AUX_CTRL_TAG_LATENCY_MASK		(0x7 << 6)
-+#define L2X0_AUX_CTRL_TAG_LATENCY_MASK		(7 << 6)
- #define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT	9
--#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK	(0x7 << 9)
--#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT	16
--#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT		17
--#define L2X0_AUX_CTRL_WAY_SIZE_MASK		(0x7 << 17)
--#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT	22
--#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT		26
--#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT		27
--#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT	28
--#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT	29
--#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT		30
--
--#define L2X0_LATENCY_CTRL_SETUP_SHIFT	0
--#define L2X0_LATENCY_CTRL_RD_SHIFT	4
--#define L2X0_LATENCY_CTRL_WR_SHIFT	8
--
--#define L2X0_ADDR_FILTER_EN		1
-+#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK	(7 << 9)
-+#define L2X0_AUX_CTRL_ASSOC_SHIFT		13
-+#define L2X0_AUX_CTRL_ASSOC_MASK		(15 << 13)
-+/* L2C-210 specific bits */
-+#define L210_AUX_CTRL_WRAP_DISABLE		BIT(12)
-+#define L210_AUX_CTRL_WA_OVERRIDE		BIT(23)
-+#define L210_AUX_CTRL_EXCLUSIVE_ABORT		BIT(24)
-+/* L2C-220 specific bits */
-+#define L220_AUX_CTRL_EXCLUSIVE_CACHE		BIT(12)
-+#define L220_AUX_CTRL_FWA_SHIFT			23
-+#define L220_AUX_CTRL_FWA_MASK			(3 << 23)
-+#define L220_AUX_CTRL_NS_LOCKDOWN		BIT(26)
-+#define L220_AUX_CTRL_NS_INT_CTRL		BIT(27)
-+/* L2C-310 specific bits */
-+#define L310_AUX_CTRL_FULL_LINE_ZERO		BIT(0)	/* R2P0+ */
-+#define L310_AUX_CTRL_HIGHPRIO_SO_DEV		BIT(10)	/* R2P0+ */
-+#define L310_AUX_CTRL_STORE_LIMITATION		BIT(11)	/* R2P0+ */
-+#define L310_AUX_CTRL_EXCLUSIVE_CACHE		BIT(12)
-+#define L310_AUX_CTRL_ASSOCIATIVITY_16		BIT(16)
-+#define L310_AUX_CTRL_CACHE_REPLACE_RR		BIT(25)	/* R2P0+ */
-+#define L310_AUX_CTRL_NS_LOCKDOWN		BIT(26)
-+#define L310_AUX_CTRL_NS_INT_CTRL		BIT(27)
-+#define L310_AUX_CTRL_DATA_PREFETCH		BIT(28)
-+#define L310_AUX_CTRL_INSTR_PREFETCH		BIT(29)
-+#define L310_AUX_CTRL_EARLY_BRESP		BIT(30)	/* R2P0+ */
-+
-+#define L310_LATENCY_CTRL_SETUP(n)		((n) << 0)
-+#define L310_LATENCY_CTRL_RD(n)			((n) << 4)
-+#define L310_LATENCY_CTRL_WR(n)			((n) << 8)
-+
-+#define L310_ADDR_FILTER_EN		1
-+
-+#define L310_PREFETCH_CTRL_OFFSET_MASK		0x1f
-+#define L310_PREFETCH_CTRL_DBL_LINEFILL_INCR	BIT(23)
-+#define L310_PREFETCH_CTRL_PREFETCH_DROP	BIT(24)
-+#define L310_PREFETCH_CTRL_DBL_LINEFILL_WRAP	BIT(27)
-+#define L310_PREFETCH_CTRL_DATA_PREFETCH	BIT(28)
-+#define L310_PREFETCH_CTRL_INSTR_PREFETCH	BIT(29)
-+#define L310_PREFETCH_CTRL_DBL_LINEFILL		BIT(30)
- 
- #define L2X0_CTRL_EN			1
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/include/asm/outercache.h linux-3.15-rc6/arch/arm/include/asm/outercache.h
---- linux-3.15-rc6.orig/arch/arm/include/asm/outercache.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/include/asm/outercache.h	2014-05-23 11:26:48.248939848 +0200
-@@ -21,6 +21,7 @@
- #ifndef __ASM_OUTERCACHE_H
- #define __ASM_OUTERCACHE_H
- 
-+#include <linux/bug.h>
- #include <linux/types.h>
- 
- struct outer_cache_fns {
-@@ -28,53 +29,84 @@
- 	void (*clean_range)(unsigned long, unsigned long);
- 	void (*flush_range)(unsigned long, unsigned long);
- 	void (*flush_all)(void);
--	void (*inv_all)(void);
- 	void (*disable)(void);
- #ifdef CONFIG_OUTER_CACHE_SYNC
- 	void (*sync)(void);
- #endif
--	void (*set_debug)(unsigned long);
- 	void (*resume)(void);
-+
-+	/* This is an ARM L2C thing */
-+	void (*write_sec)(unsigned long, unsigned);
- };
- 
- extern struct outer_cache_fns outer_cache;
- 
- #ifdef CONFIG_OUTER_CACHE
--
-+/**
-+ * outer_inv_range - invalidate range of outer cache lines
-+ * @start: starting physical address, inclusive
-+ * @end: end physical address, exclusive
-+ */
- static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
- {
- 	if (outer_cache.inv_range)
- 		outer_cache.inv_range(start, end);
- }
-+
-+/**
-+ * outer_clean_range - clean dirty outer cache lines
-+ * @start: starting physical address, inclusive
-+ * @end: end physical address, exclusive
-+ */
- static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
- {
- 	if (outer_cache.clean_range)
- 		outer_cache.clean_range(start, end);
- }
-+
-+/**
-+ * outer_flush_range - clean and invalidate outer cache lines
-+ * @start: starting physical address, inclusive
-+ * @end: end physical address, exclusive
-+ */
- static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
- {
- 	if (outer_cache.flush_range)
- 		outer_cache.flush_range(start, end);
- }
- 
-+/**
-+ * outer_flush_all - clean and invalidate all cache lines in the outer cache
-+ *
-+ * Note: depending on implementation, this may not be atomic - it must
-+ * only be called with interrupts disabled and no other active outer
-+ * cache masters.
-+ *
-+ * It is intended that this function is only used by implementations
-+ * needing to override the outer_cache.disable() method due to security.
-+ * (Some implementations perform this as a clean followed by an invalidate.)
-+ */
- static inline void outer_flush_all(void)
- {
- 	if (outer_cache.flush_all)
- 		outer_cache.flush_all();
- }
- 
--static inline void outer_inv_all(void)
--{
--	if (outer_cache.inv_all)
--		outer_cache.inv_all();
--}
--
--static inline void outer_disable(void)
--{
--	if (outer_cache.disable)
--		outer_cache.disable();
--}
--
-+/**
-+ * outer_disable - clean, invalidate and disable the outer cache
-+ *
-+ * Disable the outer cache, ensuring that any data contained in the outer
-+ * cache is pushed out to lower levels of system memory.  The note and
-+ * conditions above concerning outer_flush_all() applies here.
-+ */
-+extern void outer_disable(void);
-+
-+/**
-+ * outer_resume - restore the cache configuration and re-enable outer cache
-+ *
-+ * Restore any configuration that the cache had when previously enabled,
-+ * and re-enable the outer cache.
-+ */
- static inline void outer_resume(void)
- {
- 	if (outer_cache.resume)
-@@ -90,13 +122,18 @@
- static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
- { }
- static inline void outer_flush_all(void) { }
--static inline void outer_inv_all(void) { }
- static inline void outer_disable(void) { }
- static inline void outer_resume(void) { }
- 
- #endif
- 
- #ifdef CONFIG_OUTER_CACHE_SYNC
-+/**
-+ * outer_sync - perform a sync point for outer cache
-+ *
-+ * Ensure that all outer cache operations are complete and any store
-+ * buffers are drained.
-+ */
- static inline void outer_sync(void)
- {
- 	if (outer_cache.sync)
-diff -Nur linux-3.15-rc6.orig/arch/arm/Kconfig linux-3.15-rc6/arch/arm/Kconfig
---- linux-3.15-rc6.orig/arch/arm/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/Kconfig	2014-05-23 11:26:48.248939848 +0200
-@@ -1230,19 +1230,6 @@
- 	  register of the Cortex-A9 which reduces the linefill issuing
- 	  capabilities of the processor.
- 
--config PL310_ERRATA_588369
--	bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
--	depends on CACHE_L2X0
--	help
--	   The PL310 L2 cache controller implements three types of Clean &
--	   Invalidate maintenance operations: by Physical Address
--	   (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
--	   They are architecturally defined to behave as the execution of a
--	   clean operation followed immediately by an invalidate operation,
--	   both performing to the same memory location. This functionality
--	   is not correctly implemented in PL310 as clean lines are not
--	   invalidated as a result of these operations.
--
- config ARM_ERRATA_643719
- 	bool "ARM errata: LoUIS bit field in CLIDR register is incorrect"
- 	depends on CPU_V7 && SMP
-@@ -1265,17 +1252,6 @@
- 	  tables. The workaround changes the TLB flushing routines to invalidate
- 	  entries regardless of the ASID.
- 
--config PL310_ERRATA_727915
--	bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
--	depends on CACHE_L2X0
--	help
--	  PL310 implements the Clean & Invalidate by Way L2 cache maintenance
--	  operation (offset 0x7FC). This operation runs in background so that
--	  PL310 can handle normal accesses while it is in progress. Under very
--	  rare circumstances, due to this erratum, write data can be lost when
--	  PL310 treats a cacheable write transaction during a Clean &
--	  Invalidate by Way operation.
--
- config ARM_ERRATA_743622
- 	bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
- 	depends on CPU_V7
-@@ -1301,21 +1277,6 @@
- 	  operation is received by a CPU before the ICIALLUIS has completed,
- 	  potentially leading to corrupted entries in the cache or TLB.
- 
--config PL310_ERRATA_753970
--	bool "PL310 errata: cache sync operation may be faulty"
--	depends on CACHE_PL310
--	help
--	  This option enables the workaround for the 753970 PL310 (r3p0) erratum.
--
--	  Under some condition the effect of cache sync operation on
--	  the store buffer still remains when the operation completes.
--	  This means that the store buffer is always asked to drain and
--	  this prevents it from merging any further writes. The workaround
--	  is to replace the normal offset of cache sync operation (0x730)
--	  by another offset targeting an unmapped PL310 register 0x740.
--	  This has the same effect as the cache sync operation: store buffer
--	  drain and waiting for all buffers empty.
--
- config ARM_ERRATA_754322
- 	bool "ARM errata: possible faulty MMU translations following an ASID switch"
- 	depends on CPU_V7
-@@ -1364,18 +1325,6 @@
- 	  relevant cache maintenance functions and sets a specific bit
- 	  in the diagnostic control register of the SCU.
- 
--config PL310_ERRATA_769419
--	bool "PL310 errata: no automatic Store Buffer drain"
--	depends on CACHE_L2X0
--	help
--	  On revisions of the PL310 prior to r3p2, the Store Buffer does
--	  not automatically drain. This can cause normal, non-cacheable
--	  writes to be retained when the memory system is idle, leading
--	  to suboptimal I/O performance for drivers using coherent DMA.
--	  This option adds a write barrier to the cpu_idle loop so that,
--	  on systems with an outer cache, the store buffer is drained
--	  explicitly.
--
- config ARM_ERRATA_775420
-        bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
-        depends on CPU_V7
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-berlin/berlin.c linux-3.15-rc6/arch/arm/mach-berlin/berlin.c
---- linux-3.15-rc6.orig/arch/arm/mach-berlin/berlin.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-berlin/berlin.c	2014-05-23 11:26:48.256939874 +0200
-@@ -24,7 +24,7 @@
- 	 * with DT probing for L2CCs, berlin_init_machine can be removed.
- 	 * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc
- 	 */
--	l2x0_of_init(0x70c00000, 0xfeffffff);
-+	l2x0_of_init(0x30c00000, 0xfeffffff);
- 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-cns3xxx/core.c linux-3.15-rc6/arch/arm/mach-cns3xxx/core.c
---- linux-3.15-rc6.orig/arch/arm/mach-cns3xxx/core.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-cns3xxx/core.c	2014-05-23 11:26:48.256939874 +0200
-@@ -272,9 +272,9 @@
- 	 *
- 	 * 1 cycle of latency for setup, read and write accesses
- 	 */
--	val = readl(base + L2X0_TAG_LATENCY_CTRL);
-+	val = readl(base + L310_TAG_LATENCY_CTRL);
- 	val &= 0xfffff888;
--	writel(val, base + L2X0_TAG_LATENCY_CTRL);
-+	writel(val, base + L310_TAG_LATENCY_CTRL);
- 
- 	/*
- 	 * Data RAM Control register
-@@ -285,12 +285,12 @@
- 	 *
- 	 * 1 cycle of latency for setup, read and write accesses
- 	 */
--	val = readl(base + L2X0_DATA_LATENCY_CTRL);
-+	val = readl(base + L310_DATA_LATENCY_CTRL);
- 	val &= 0xfffff888;
--	writel(val, base + L2X0_DATA_LATENCY_CTRL);
-+	writel(val, base + L310_DATA_LATENCY_CTRL);
- 
- 	/* 32 KiB, 8-way, parity disable */
--	l2x0_init(base, 0x00540000, 0xfe000fff);
-+	l2x0_init(base, 0x00500000, 0xfe0f0fff);
- }
- 
- #endif /* CONFIG_CACHE_L2X0 */
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-exynos/common.h linux-3.15-rc6/arch/arm/mach-exynos/common.h
---- linux-3.15-rc6.orig/arch/arm/mach-exynos/common.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-exynos/common.h	2014-05-23 11:26:48.256939874 +0200
-@@ -55,7 +55,6 @@
- 	NUM_SYS_POWERDOWN,
- };
- 
--extern unsigned long l2x0_regs_phys;
- struct exynos_pmu_conf {
- 	void __iomem *reg;
- 	unsigned int val[NUM_SYS_POWERDOWN];
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-exynos/exynos.c linux-3.15-rc6/arch/arm/mach-exynos/exynos.c
---- linux-3.15-rc6.orig/arch/arm/mach-exynos/exynos.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-exynos/exynos.c	2014-05-23 11:26:48.256939874 +0200
-@@ -32,9 +32,6 @@
- #include "mfc.h"
- #include "regs-pmu.h"
- 
--#define L2_AUX_VAL 0x7C470001
--#define L2_AUX_MASK 0xC200ffff
--
- static struct map_desc exynos4_iodesc[] __initdata = {
- 	{
- 		.virtual	= (unsigned long)S3C_VA_SYS,
-@@ -321,17 +318,7 @@
- 
- static int __init exynos4_l2x0_cache_init(void)
- {
--	int ret;
--
--	ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
--	if (ret)
--		return ret;
--
--	if (IS_ENABLED(CONFIG_S5P_SLEEP)) {
--		l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
--		clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long));
--	}
--	return 0;
-+	return l2x0_of_init(0x3c400001, 0xc20fffff);
- }
- early_initcall(exynos4_l2x0_cache_init);
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-exynos/sleep.S linux-3.15-rc6/arch/arm/mach-exynos/sleep.S
---- linux-3.15-rc6.orig/arch/arm/mach-exynos/sleep.S	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-exynos/sleep.S	2014-05-23 11:26:48.256939874 +0200
-@@ -16,8 +16,6 @@
-  */
- 
- #include <linux/linkage.h>
--#include <asm/asm-offsets.h>
--#include <asm/hardware/cache-l2x0.h>
- 
- #define CPU_MASK	0xff0ffff0
- #define CPU_CORTEX_A9	0x410fc090
-@@ -53,33 +51,7 @@
- 	and	r0, r0, r1
- 	ldr	r1, =CPU_CORTEX_A9
- 	cmp	r0, r1
--	bne	skip_l2_resume
--	adr	r0, l2x0_regs_phys
--	ldr	r0, [r0]
--	cmp	r0, #0
--	beq	skip_l2_resume
--	ldr	r1, [r0, #L2X0_R_PHY_BASE]
--	ldr	r2, [r1, #L2X0_CTRL]
--	tst	r2, #0x1
--	bne	skip_l2_resume
--	ldr	r2, [r0, #L2X0_R_AUX_CTRL]
--	str	r2, [r1, #L2X0_AUX_CTRL]
--	ldr	r2, [r0, #L2X0_R_TAG_LATENCY]
--	str	r2, [r1, #L2X0_TAG_LATENCY_CTRL]
--	ldr	r2, [r0, #L2X0_R_DATA_LATENCY]
--	str	r2, [r1, #L2X0_DATA_LATENCY_CTRL]
--	ldr	r2, [r0, #L2X0_R_PREFETCH_CTRL]
--	str	r2, [r1, #L2X0_PREFETCH_CTRL]
--	ldr	r2, [r0, #L2X0_R_PWR_CTRL]
--	str	r2, [r1, #L2X0_POWER_CTRL]
--	mov	r2, #1
--	str	r2, [r1, #L2X0_CTRL]
--skip_l2_resume:
-+	bleq	l2c310_early_resume
- #endif
- 	b	cpu_resume
- ENDPROC(exynos_cpu_resume)
--#ifdef CONFIG_CACHE_L2X0
--	.globl l2x0_regs_phys
--l2x0_regs_phys:
--	.long	0
--#endif
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-highbank/highbank.c linux-3.15-rc6/arch/arm/mach-highbank/highbank.c
---- linux-3.15-rc6.orig/arch/arm/mach-highbank/highbank.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-highbank/highbank.c	2014-05-23 11:26:48.256939874 +0200
-@@ -51,11 +51,13 @@
- }
- 
- 
--static void highbank_l2x0_disable(void)
-+static void highbank_l2c310_write_sec(unsigned long val, unsigned reg)
- {
--	outer_flush_all();
--	/* Disable PL310 L2 Cache controller */
--	highbank_smc1(0x102, 0x0);
-+	if (reg == L2X0_CTRL)
-+		highbank_smc1(0x102, val);
-+	else
-+		WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n",
-+			  reg);
- }
- 
- static void __init highbank_init_irq(void)
-@@ -66,11 +68,9 @@
- 		highbank_scu_map_io();
- 
- 	/* Enable PL310 L2 Cache controller */
--	if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
--	    of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) {
--		highbank_smc1(0x102, 0x1);
--		l2x0_of_init(0, ~0UL);
--		outer_cache.disable = highbank_l2x0_disable;
-+	if (IS_ENABLED(CONFIG_CACHE_L2X0)) {
-+		outer_cache.write_sec = highbank_l2c310_write_sec;
-+		l2x0_of_init(0, ~0);
- 	}
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-imx/clk-pllv3.c linux-3.15-rc6/arch/arm/mach-imx/clk-pllv3.c
---- linux-3.15-rc6.orig/arch/arm/mach-imx/clk-pllv3.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-imx/clk-pllv3.c	2014-05-23 11:26:48.256939874 +0200
-@@ -273,9 +273,10 @@
- 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
- 	unsigned long min_rate = parent_rate * 27;
- 	unsigned long max_rate = parent_rate * 54;
--	u32 val, div;
-+	u32 val, newval, div;
- 	u32 mfn, mfd = 1000000;
- 	s64 temp64;
-+	int ret;
- 
- 	if (rate < min_rate || rate > max_rate)
- 		return -EINVAL;
-@@ -287,13 +288,27 @@
- 	mfn = temp64;
- 
- 	val = readl_relaxed(pll->base);
--	val &= ~pll->div_mask;
--	val |= div;
--	writel_relaxed(val, pll->base);
-+
-+	/* set the PLL into bypass mode */
-+	newval = val | BM_PLL_BYPASS;
-+	writel_relaxed(newval, pll->base);
-+
-+	/* configure the new frequency */
-+	newval &= ~pll->div_mask;
-+	newval |= div;
-+	writel_relaxed(newval, pll->base);
- 	writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
--	writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
-+	writel(mfd, pll->base + PLL_DENOM_OFFSET);
-+
-+	ret = clk_pllv3_wait_lock(pll);
-+	if (ret == 0 && val & BM_PLL_POWER) {
-+		/* only if it locked can we switch back to the PLL */
-+		newval &= ~BM_PLL_BYPASS;
-+		newval |= val & BM_PLL_BYPASS;
-+		writel(newval, pll->base);
-+	}
- 
--	return clk_pllv3_wait_lock(pll);
-+	return ret;
- }
- 
- static const struct clk_ops clk_pllv3_av_ops = {
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-imx/mach-vf610.c linux-3.15-rc6/arch/arm/mach-imx/mach-vf610.c
---- linux-3.15-rc6.orig/arch/arm/mach-imx/mach-vf610.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-imx/mach-vf610.c	2014-05-23 11:26:48.256939874 +0200
-@@ -22,7 +22,7 @@
- 
- static void __init vf610_init_irq(void)
- {
--	l2x0_of_init(0, ~0UL);
-+	l2x0_of_init(0, ~0);
- 	irqchip_init();
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-imx/suspend-imx6.S linux-3.15-rc6/arch/arm/mach-imx/suspend-imx6.S
---- linux-3.15-rc6.orig/arch/arm/mach-imx/suspend-imx6.S	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-imx/suspend-imx6.S	2014-05-23 11:26:48.256939874 +0200
-@@ -334,28 +334,10 @@
-  * turned into relative ones.
-  */
- 
--#ifdef CONFIG_CACHE_L2X0
--	.macro	pl310_resume
--	adr	r0, l2x0_saved_regs_offset
--	ldr	r2, [r0]
--	add	r2, r2, r0
--	ldr	r0, [r2, #L2X0_R_PHY_BASE]	@ get physical base of l2x0
--	ldr	r1, [r2, #L2X0_R_AUX_CTRL]	@ get aux_ctrl value
--	str	r1, [r0, #L2X0_AUX_CTRL]	@ restore aux_ctrl
--	mov	r1, #0x1
--	str	r1, [r0, #L2X0_CTRL]		@ re-enable L2
--	.endm
--
--l2x0_saved_regs_offset:
--	.word	l2x0_saved_regs - .
--
--#else
--	.macro	pl310_resume
--	.endm
--#endif
--
- ENTRY(v7_cpu_resume)
- 	bl	v7_invalidate_l1
--	pl310_resume
-+#ifdef CONFIG_CACHE_L2X0
-+	bl	l2c310_early_resume
-+#endif
- 	b	cpu_resume
- ENDPROC(v7_cpu_resume)
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-imx/system.c linux-3.15-rc6/arch/arm/mach-imx/system.c
---- linux-3.15-rc6.orig/arch/arm/mach-imx/system.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-imx/system.c	2014-05-23 11:26:48.260939887 +0200
-@@ -124,7 +124,7 @@
- 	}
- 
- 	/* Configure the L2 PREFETCH and POWER registers */
--	val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
-+	val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL);
- 	val |= 0x70800000;
- 	/*
- 	 * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
-@@ -137,14 +137,12 @@
- 	 */
- 	if (cpu_is_imx6q())
- 		val &= ~(1 << 30 | 1 << 23);
--	writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL);
--	val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
--	writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL);
-+	writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL);
- 
- 	iounmap(l2x0_base);
- 	of_node_put(np);
- 
- out:
--	l2x0_of_init(0, ~0UL);
-+	l2x0_of_init(0, ~0);
- }
- #endif
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-mvebu/board-v7.c linux-3.15-rc6/arch/arm/mach-mvebu/board-v7.c
---- linux-3.15-rc6.orig/arch/arm/mach-mvebu/board-v7.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-mvebu/board-v7.c	2014-05-23 11:26:48.260939887 +0200
-@@ -60,7 +60,7 @@
- 	coherency_init();
- 	BUG_ON(mvebu_mbus_dt_init());
- #ifdef CONFIG_CACHE_L2X0
--	l2x0_of_init(0, ~0UL);
-+	l2x0_of_init(0, ~0);
- #endif
- 
- 	if (of_machine_is_compatible("marvell,armada375"))
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-nomadik/cpu-8815.c linux-3.15-rc6/arch/arm/mach-nomadik/cpu-8815.c
---- linux-3.15-rc6.orig/arch/arm/mach-nomadik/cpu-8815.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-nomadik/cpu-8815.c	2014-05-23 11:26:48.260939887 +0200
-@@ -147,7 +147,7 @@
- {
- #ifdef CONFIG_CACHE_L2X0
- 	/* At full speed latency must be >=2, so 0x249 in low bits */
--	l2x0_of_init(0x00730249, 0xfe000fff);
-+	l2x0_of_init(0x00700249, 0xfe0fefff);
- #endif
- 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-omap2/common.h linux-3.15-rc6/arch/arm/mach-omap2/common.h
---- linux-3.15-rc6.orig/arch/arm/mach-omap2/common.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-omap2/common.h	2014-05-23 11:26:48.260939887 +0200
-@@ -91,6 +91,7 @@
- extern void omap3_secure_sync32k_timer_init(void);
- extern void omap3_gptimer_timer_init(void);
- extern void omap4_local_timer_init(void);
-+int omap_l2_cache_init(void);
- extern void omap5_realtime_timer_init(void);
- 
- void omap2420_init_early(void);
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-omap2/io.c linux-3.15-rc6/arch/arm/mach-omap2/io.c
---- linux-3.15-rc6.orig/arch/arm/mach-omap2/io.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-omap2/io.c	2014-05-23 11:26:48.260939887 +0200
-@@ -609,6 +609,7 @@
- 	am43xx_clockdomains_init();
- 	am43xx_hwmod_init();
- 	omap_hwmod_init_postsetup();
-+	omap_l2_cache_init();
- 	omap_clk_soc_init = am43xx_dt_clk_init;
- }
- 
-@@ -640,6 +641,7 @@
- 	omap44xx_clockdomains_init();
- 	omap44xx_hwmod_init();
- 	omap_hwmod_init_postsetup();
-+	omap_l2_cache_init();
- 	omap_clk_soc_init = omap4xxx_dt_clk_init;
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-omap2/Kconfig linux-3.15-rc6/arch/arm/mach-omap2/Kconfig
---- linux-3.15-rc6.orig/arch/arm/mach-omap2/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-omap2/Kconfig	2014-05-23 11:26:48.260939887 +0200
-@@ -65,6 +65,7 @@
- 	select ARCH_HAS_OPP
- 	select ARM_GIC
- 	select MACH_OMAP_GENERIC
-+	select MIGHT_HAVE_CACHE_L2X0
- 
- config SOC_DRA7XX
- 	bool "TI DRA7XX"
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-omap2/omap4-common.c linux-3.15-rc6/arch/arm/mach-omap2/omap4-common.c
---- linux-3.15-rc6.orig/arch/arm/mach-omap2/omap4-common.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-omap2/omap4-common.c	2014-05-23 11:26:48.260939887 +0200
-@@ -167,75 +167,57 @@
- 	return l2cache_base;
- }
- 
--static void omap4_l2x0_disable(void)
-+static void omap4_l2c310_write_sec(unsigned long val, unsigned reg)
- {
--	outer_flush_all();
--	/* Disable PL310 L2 Cache controller */
--	omap_smc1(0x102, 0x0);
--}
-+	unsigned smc_op;
- 
--static void omap4_l2x0_set_debug(unsigned long val)
--{
--	/* Program PL310 L2 Cache controller debug register */
--	omap_smc1(0x100, val);
-+	switch (reg) {
-+	case L2X0_CTRL:
-+		smc_op = OMAP4_MON_L2X0_CTRL_INDEX;
-+		break;
-+
-+	case L2X0_AUX_CTRL:
-+		smc_op = OMAP4_MON_L2X0_AUXCTRL_INDEX;
-+		break;
-+
-+	case L2X0_DEBUG_CTRL:
-+		smc_op = OMAP4_MON_L2X0_DBG_CTRL_INDEX;
-+		break;
-+
-+	case L310_PREFETCH_CTRL:
-+		smc_op = OMAP4_MON_L2X0_PREFETCH_INDEX;
-+		break;
-+
-+	default:
-+		WARN_ONCE(1, "OMAP L2C310: ignoring write to reg 0x%x\n", reg);
-+		return;
-+	}
-+
-+	omap_smc1(smc_op, val);
- }
- 
--static int __init omap_l2_cache_init(void)
-+int __init omap_l2_cache_init(void)
- {
--	u32 aux_ctrl = 0;
--
--	/*
--	 * To avoid code running on other OMAPs in
--	 * multi-omap builds
--	 */
--	if (!cpu_is_omap44xx())
--		return -ENODEV;
-+	u32 aux_ctrl;
- 
- 	/* Static mapping, never released */
- 	l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K);
- 	if (WARN_ON(!l2cache_base))
- 		return -ENOMEM;
- 
--	/*
--	 * 16-way associativity, parity disabled
--	 * Way size - 32KB (es1.0)
--	 * Way size - 64KB (es2.0 +)
--	 */
--	aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) |
--			(0x1 << 25) |
--			(0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) |
--			(0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT));
--
--	if (omap_rev() == OMAP4430_REV_ES1_0) {
--		aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT;
--	} else {
--		aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
--			(1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
--			(1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
--			(1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
--			(1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT));
--	}
--	if (omap_rev() != OMAP4430_REV_ES1_0)
--		omap_smc1(0x109, aux_ctrl);
--
--	/* Enable PL310 L2 Cache controller */
--	omap_smc1(0x102, 0x1);
-+	/* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */
-+	aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE |
-+		   L310_AUX_CTRL_DATA_PREFETCH |
-+		   L310_AUX_CTRL_INSTR_PREFETCH;
- 
-+	outer_cache.write_sec = omap4_l2c310_write_sec;
- 	if (of_have_populated_dt())
--		l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
-+		l2x0_of_init(aux_ctrl, 0xcf9fffff);
- 	else
--		l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
--
--	/*
--	 * Override default outer_cache.disable with a OMAP4
--	 * specific one
--	*/
--	outer_cache.disable = omap4_l2x0_disable;
--	outer_cache.set_debug = omap4_l2x0_set_debug;
-+		l2x0_init(l2cache_base, aux_ctrl, 0xcf9fffff);
- 
- 	return 0;
- }
--omap_early_initcall(omap_l2_cache_init);
- #endif
- 
- void __iomem *omap4_get_sar_ram_base(void)
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c linux-3.15-rc6/arch/arm/mach-omap2/omap-mpuss-lowpower.c
---- linux-3.15-rc6.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2014-05-23 11:26:48.268939913 +0200
-@@ -187,19 +187,15 @@
-  * in every restore MPUSS OFF path.
-  */
- #ifdef CONFIG_CACHE_L2X0
--static void save_l2x0_context(void)
-+static void __init save_l2x0_context(void)
- {
--	u32 val;
--	void __iomem *l2x0_base = omap4_get_l2cache_base();
--	if (l2x0_base) {
--		val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
--		__raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
--		val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
--		__raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
--	}
-+	__raw_writel(l2x0_saved_regs.aux_ctrl,
-+		     sar_base + L2X0_AUXCTRL_OFFSET);
-+	__raw_writel(l2x0_saved_regs.prefetch_ctrl,
-+		     sar_base + L2X0_PREFETCH_CTRL_OFFSET);
- }
- #else
--static void save_l2x0_context(void)
-+static void __init save_l2x0_context(void)
- {}
- #endif
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-prima2/l2x0.c linux-3.15-rc6/arch/arm/mach-prima2/l2x0.c
---- linux-3.15-rc6.orig/arch/arm/mach-prima2/l2x0.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-prima2/l2x0.c	2014-05-23 11:26:48.268939913 +0200
-@@ -8,42 +8,10 @@
- 
- #include <linux/init.h>
- #include <linux/kernel.h>
--#include <linux/of.h>
- #include <asm/hardware/cache-l2x0.h>
- 
--struct l2x0_aux {
--	u32 val;
--	u32 mask;
--};
--
--static const struct l2x0_aux prima2_l2x0_aux __initconst = {
--	.val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT,
--	.mask =	0,
--};
--
--static const struct l2x0_aux marco_l2x0_aux __initconst = {
--	.val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
--		(1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
--	.mask = L2X0_AUX_CTRL_MASK,
--};
--
--static const struct of_device_id sirf_l2x0_ids[] __initconst = {
--	{ .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, },
--	{ .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, },
--	{},
--};
--
- static int __init sirfsoc_l2x0_init(void)
- {
--	struct device_node *np;
--	const struct l2x0_aux *aux;
--
--	np = of_find_matching_node(NULL, sirf_l2x0_ids);
--	if (np) {
--		aux = of_match_node(sirf_l2x0_ids, np)->data;
--		return l2x0_of_init(aux->val, aux->mask);
--	}
--
--	return 0;
-+	return l2x0_of_init(0, ~0);
- }
- early_initcall(sirfsoc_l2x0_init);
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-prima2/pm.c linux-3.15-rc6/arch/arm/mach-prima2/pm.c
---- linux-3.15-rc6.orig/arch/arm/mach-prima2/pm.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-prima2/pm.c	2014-05-23 11:26:48.268939913 +0200
-@@ -71,7 +71,6 @@
- 	case PM_SUSPEND_MEM:
- 		sirfsoc_pre_suspend_power_off();
- 
--		outer_flush_all();
- 		outer_disable();
- 		/* go zzz */
- 		cpu_suspend(0, sirfsoc_finish_suspend);
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-realview/realview_eb.c linux-3.15-rc6/arch/arm/mach-realview/realview_eb.c
---- linux-3.15-rc6.orig/arch/arm/mach-realview/realview_eb.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-realview/realview_eb.c	2014-05-23 11:26:48.268939913 +0200
-@@ -442,8 +442,13 @@
- 		realview_eb11mp_fixup();
- 
- #ifdef CONFIG_CACHE_L2X0
--		/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
--		 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
-+		/*
-+		 * The PL220 needs to be manually configured as the hardware
-+		 * doesn't report the correct sizes.
-+		 * 1MB (128KB/way), 8-way associativity, event monitor and
-+		 * parity enabled, ignore share bit, no force write allocate
-+		 * Bits:  .... ...0 0111 1001 0000 .... .... ....
-+		 */
- 		l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
- #endif
- 		platform_device_register(&pmu_device);
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pb1176.c linux-3.15-rc6/arch/arm/mach-realview/realview_pb1176.c
---- linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pb1176.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-realview/realview_pb1176.c	2014-05-23 11:26:48.268939913 +0200
-@@ -355,7 +355,13 @@
- 	int i;
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */
-+	/*
-+	 * The PL220 needs to be manually configured as the hardware
-+	 * doesn't report the correct sizes.
-+	 * 128kB (16kB/way), 8-way associativity, event monitor and
-+	 * parity enabled, ignore share bit, no force write allocate
-+	 * Bits:  .... ...0 0111 0011 0000 .... .... ....
-+	 */
- 	l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff);
- #endif
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pb11mp.c linux-3.15-rc6/arch/arm/mach-realview/realview_pb11mp.c
---- linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pb11mp.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-realview/realview_pb11mp.c	2014-05-23 11:26:48.268939913 +0200
-@@ -337,8 +337,13 @@
- 	int i;
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
--	 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
-+	/*
-+	 * The PL220 needs to be manually configured as the hardware
-+	 * doesn't report the correct sizes.
-+	 * 1MB (128KB/way), 8-way associativity, event monitor and
-+	 * parity enabled, ignore share bit, no force write allocate
-+	 * Bits:  .... ...0 0111 1001 0000 .... .... ....
-+	 */
- 	l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff);
- #endif
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pbx.c linux-3.15-rc6/arch/arm/mach-realview/realview_pbx.c
---- linux-3.15-rc6.orig/arch/arm/mach-realview/realview_pbx.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-realview/realview_pbx.c	2014-05-23 11:26:48.268939913 +0200
-@@ -370,8 +370,8 @@
- 			__io_address(REALVIEW_PBX_TILE_L220_BASE);
- 
- 		/* set RAM latencies to 1 cycle for eASIC */
--		writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
--		writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
-+		writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
-+		writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
- 
- 		/* 16KB way size, 8-way associativity, parity disabled
- 		 * Bits:  .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-rockchip/rockchip.c linux-3.15-rc6/arch/arm/mach-rockchip/rockchip.c
---- linux-3.15-rc6.orig/arch/arm/mach-rockchip/rockchip.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-rockchip/rockchip.c	2014-05-23 11:26:48.268939913 +0200
-@@ -26,7 +26,7 @@
- 
- static void __init rockchip_dt_init(void)
- {
--	l2x0_of_init(0, ~0UL);
-+	l2x0_of_init(0, ~0);
- 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-armadillo800eva.c linux-3.15-rc6/arch/arm/mach-shmobile/board-armadillo800eva.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-armadillo800eva.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/board-armadillo800eva.c	2014-05-23 11:26:48.272939927 +0200
-@@ -1271,8 +1271,8 @@
- 
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* Early BRESP enable, Shared attribute override enable, 32K*8way */
--	l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
-+	/* Shared attribute override enable, 32K*8way */
-+	l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
- #endif
- 
- 	i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c linux-3.15-rc6/arch/arm/mach-shmobile/board-armadillo800eva-reference.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/board-armadillo800eva-reference.c	2014-05-23 11:26:48.272939927 +0200
-@@ -164,8 +164,8 @@
- 	r8a7740_meram_workaround();
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* Early BRESP enable, Shared attribute override enable, 32K*8way */
--	l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
-+	/* Shared attribute override enable, 32K*8way */
-+	l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff);
- #endif
- 
- 	r8a7740_add_standard_devices_dt();
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-kzm9g.c linux-3.15-rc6/arch/arm/mach-shmobile/board-kzm9g.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-kzm9g.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/board-kzm9g.c	2014-05-23 11:26:48.272939927 +0200
-@@ -876,8 +876,8 @@
- 	gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
--	l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
-+	/* Shared attribute override enable, 64K*8way */
-+	l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
- 
- 	i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c linux-3.15-rc6/arch/arm/mach-shmobile/board-kzm9g-reference.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/board-kzm9g-reference.c	2014-05-23 11:26:48.272939927 +0200
-@@ -36,8 +36,8 @@
- 	sh73a0_add_standard_devices_dt();
- 
- #ifdef CONFIG_CACHE_L2X0
--	/* Early BRESP enable, Shared attribute override enable, 64K*8way */
--	l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff);
-+	/* Shared attribute override enable, 64K*8way */
-+	l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/setup-r8a7778.c linux-3.15-rc6/arch/arm/mach-shmobile/setup-r8a7778.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/setup-r8a7778.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/setup-r8a7778.c	2014-05-23 11:26:48.272939927 +0200
-@@ -298,10 +298,10 @@
- 	void __iomem *base = ioremap_nocache(0xf0100000, 0x1000);
- 	if (base) {
- 		/*
--		 * Early BRESP enable, Shared attribute override enable, 64K*16way
-+		 * Shared attribute override enable, 64K*16way
- 		 * don't call iounmap(base)
- 		 */
--		l2x0_init(base, 0x40470000, 0x82000fff);
-+		l2x0_init(base, 0x00400000, 0xc20f0fff);
- 	}
- #endif
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-shmobile/setup-r8a7779.c linux-3.15-rc6/arch/arm/mach-shmobile/setup-r8a7779.c
---- linux-3.15-rc6.orig/arch/arm/mach-shmobile/setup-r8a7779.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-shmobile/setup-r8a7779.c	2014-05-23 11:26:48.272939927 +0200
-@@ -700,8 +700,8 @@
- void __init r8a7779_add_standard_devices(void)
- {
- #ifdef CONFIG_CACHE_L2X0
--	/* Early BRESP enable, Shared attribute override enable, 64K*16way */
--	l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
-+	/* Shared attribute override enable, 64K*16way */
-+	l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
- #endif
- 	r8a7779_pm_init();
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-socfpga/socfpga.c linux-3.15-rc6/arch/arm/mach-socfpga/socfpga.c
---- linux-3.15-rc6.orig/arch/arm/mach-socfpga/socfpga.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-socfpga/socfpga.c	2014-05-23 11:26:48.272939927 +0200
-@@ -100,7 +100,7 @@
- 
- static void __init socfpga_cyclone5_init(void)
- {
--	l2x0_of_init(0, ~0UL);
-+	l2x0_of_init(0, ~0);
- 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-spear/platsmp.c linux-3.15-rc6/arch/arm/mach-spear/platsmp.c
---- linux-3.15-rc6.orig/arch/arm/mach-spear/platsmp.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-spear/platsmp.c	2014-05-23 11:26:48.272939927 +0200
-@@ -20,6 +20,18 @@
- #include <mach/spear.h>
- #include "generic.h"
- 
-+/*
-+ * Write pen_release in a way that is guaranteed to be visible to all
-+ * observers, irrespective of whether they're taking part in coherency
-+ * or not.  This is necessary for the hotplug code to work reliably.
-+ */
-+static void write_pen_release(int val)
-+{
-+	pen_release = val;
-+	smp_wmb();
-+	sync_cache_w(&pen_release);
-+}
-+
- static DEFINE_SPINLOCK(boot_lock);
- 
- static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
-@@ -30,8 +42,7 @@
- 	 * let the primary processor know we're out of the
- 	 * pen, then head off into the C entry point
- 	 */
--	pen_release = -1;
--	smp_wmb();
-+	write_pen_release(-1);
- 
- 	/*
- 	 * Synchronise with the boot thread.
-@@ -58,9 +69,7 @@
- 	 * Note that "pen_release" is the hardware CPU ID, whereas
- 	 * "cpu" is Linux's internal ID.
- 	 */
--	pen_release = cpu;
--	flush_cache_all();
--	outer_flush_all();
-+	write_pen_release(cpu);
- 
- 	timeout = jiffies + (1 * HZ);
- 	while (time_before(jiffies, timeout)) {
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-spear/spear13xx.c linux-3.15-rc6/arch/arm/mach-spear/spear13xx.c
---- linux-3.15-rc6.orig/arch/arm/mach-spear/spear13xx.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-spear/spear13xx.c	2014-05-23 11:26:48.272939927 +0200
-@@ -38,15 +38,15 @@
- 	if (!IS_ENABLED(CONFIG_CACHE_L2X0))
- 		return;
- 
--	writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
-+	writel_relaxed(0x06, VA_L2CC_BASE + L310_PREFETCH_CTRL);
- 
- 	/*
- 	 * Program following latencies in order to make
- 	 * SPEAr1340 work at 600 MHz
- 	 */
--	writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
--	writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
--	l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
-+	writel_relaxed(0x221, VA_L2CC_BASE + L310_TAG_LATENCY_CTRL);
-+	writel_relaxed(0x441, VA_L2CC_BASE + L310_DATA_LATENCY_CTRL);
-+	l2x0_init(VA_L2CC_BASE, 0x30a00001, 0xfe0fffff);
- }
- 
- /*
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-sti/board-dt.c linux-3.15-rc6/arch/arm/mach-sti/board-dt.c
---- linux-3.15-rc6.orig/arch/arm/mach-sti/board-dt.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-sti/board-dt.c	2014-05-23 11:26:48.272939927 +0200
-@@ -16,15 +16,9 @@
- 
- void __init stih41x_l2x0_init(void)
- {
--	u32 way_size = 0x4;
--	u32 aux_ctrl;
--	/* may be this can be encoded in macros like BIT*() */
--	aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
--		(0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
--		(0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
--		(way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
--
--	l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
-+	l2x0_of_init(L2C_AUX_CTRL_SHARED_OVERRIDE |
-+		     L310_AUX_CTRL_DATA_PREFETCH |
-+		     L310_AUX_CTRL_INSTR_PREFETCH, 0xc00f0fff);
- }
- 
- static void __init stih41x_machine_init(void)
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-tegra/pm.h linux-3.15-rc6/arch/arm/mach-tegra/pm.h
---- linux-3.15-rc6.orig/arch/arm/mach-tegra/pm.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-tegra/pm.h	2014-05-23 11:26:48.272939927 +0200
-@@ -35,8 +35,6 @@
- void tegra30_lp1_iram_hook(void);
- void tegra30_sleep_core_init(void);
- 
--extern unsigned long l2x0_saved_regs_addr;
--
- void tegra_clear_cpu_in_lp2(void);
- bool tegra_set_cpu_in_lp2(void);
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-tegra/reset-handler.S linux-3.15-rc6/arch/arm/mach-tegra/reset-handler.S
---- linux-3.15-rc6.orig/arch/arm/mach-tegra/reset-handler.S	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-tegra/reset-handler.S	2014-05-23 11:26:48.276939940 +0200
-@@ -19,7 +19,6 @@
- 
- #include <asm/cache.h>
- #include <asm/asm-offsets.h>
--#include <asm/hardware/cache-l2x0.h>
- 
- #include "flowctrl.h"
- #include "fuse.h"
-@@ -78,8 +77,10 @@
- 	str	r1, [r0]
- #endif
- 
-+#ifdef CONFIG_CACHE_L2X0
- 	/* L2 cache resume & re-enable */
--	l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
-+	bl	l2c310_early_resume
-+#endif
- end_ca9_scu_l2_resume:
- 	mov32	r9, 0xc0f
- 	cmp	r8, r9
-@@ -89,12 +90,6 @@
- ENDPROC(tegra_resume)
- #endif
- 
--#ifdef CONFIG_CACHE_L2X0
--	.globl	l2x0_saved_regs_addr
--l2x0_saved_regs_addr:
--	.long	0
--#endif
--
- 	.align L1_CACHE_SHIFT
- ENTRY(__tegra_cpu_reset_handler_start)
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-tegra/sleep.h linux-3.15-rc6/arch/arm/mach-tegra/sleep.h
---- linux-3.15-rc6.orig/arch/arm/mach-tegra/sleep.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-tegra/sleep.h	2014-05-23 11:26:48.276939940 +0200
-@@ -120,37 +120,6 @@
- 	mov	\tmp1, \tmp1, lsr #8
- .endm
- 
--/* Macro to resume & re-enable L2 cache */
--#ifndef L2X0_CTRL_EN
--#define L2X0_CTRL_EN	1
--#endif
--
--#ifdef CONFIG_CACHE_L2X0
--.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
--	W(adr)	\tmp1, \phys_l2x0_saved_regs
--	ldr	\tmp1, [\tmp1]
--	ldr	\tmp2, [\tmp1, #L2X0_R_PHY_BASE]
--	ldr	\tmp3, [\tmp2, #L2X0_CTRL]
--	tst	\tmp3, #L2X0_CTRL_EN
--	bne	exit_l2_resume
--	ldr	\tmp3, [\tmp1, #L2X0_R_TAG_LATENCY]
--	str	\tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL]
--	ldr	\tmp3, [\tmp1, #L2X0_R_DATA_LATENCY]
--	str	\tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL]
--	ldr	\tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL]
--	str	\tmp3, [\tmp2, #L2X0_PREFETCH_CTRL]
--	ldr	\tmp3, [\tmp1, #L2X0_R_PWR_CTRL]
--	str	\tmp3, [\tmp2, #L2X0_POWER_CTRL]
--	ldr	\tmp3, [\tmp1, #L2X0_R_AUX_CTRL]
--	str	\tmp3, [\tmp2, #L2X0_AUX_CTRL]
--	mov	\tmp3, #L2X0_CTRL_EN
--	str	\tmp3, [\tmp2, #L2X0_CTRL]
--exit_l2_resume:
--.endm
--#else /* CONFIG_CACHE_L2X0 */
--.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs
--.endm
--#endif /* CONFIG_CACHE_L2X0 */
- #else
- void tegra_pen_lock(void);
- void tegra_pen_unlock(void);
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-tegra/tegra.c linux-3.15-rc6/arch/arm/mach-tegra/tegra.c
---- linux-3.15-rc6.orig/arch/arm/mach-tegra/tegra.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-tegra/tegra.c	2014-05-23 11:26:48.276939940 +0200
-@@ -73,27 +73,7 @@
- static void __init tegra_init_cache(void)
- {
- #ifdef CONFIG_CACHE_L2X0
--	static const struct of_device_id pl310_ids[] __initconst = {
--		{ .compatible = "arm,pl310-cache",  },
--		{}
--	};
--
--	struct device_node *np;
--	int ret;
--	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
--	u32 aux_ctrl, cache_type;
--
--	np = of_find_matching_node(NULL, pl310_ids);
--	if (!np)
--		return;
--
--	cache_type = readl(p + L2X0_CACHE_TYPE);
--	aux_ctrl = (cache_type & 0x700) << (17-8);
--	aux_ctrl |= 0x7C400001;
--
--	ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
--	if (!ret)
--		l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
-+	l2x0_of_init(0x3c400001, 0xc20fc3fe);
- #endif
- }
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-ux500/cache-l2x0.c linux-3.15-rc6/arch/arm/mach-ux500/cache-l2x0.c
---- linux-3.15-rc6.orig/arch/arm/mach-ux500/cache-l2x0.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-ux500/cache-l2x0.c	2014-05-23 11:26:48.276939940 +0200
-@@ -35,10 +35,16 @@
- 	return 0;
- }
- 
--static int __init ux500_l2x0_init(void)
-+static void ux500_l2c310_write_sec(unsigned long val, unsigned reg)
- {
--	u32 aux_val = 0x3e000000;
-+	/*
-+	 * We can't write to secure registers as we are in non-secure
-+	 * mode, until we have some SMI service available.
-+	 */
-+}
- 
-+static int __init ux500_l2x0_init(void)
-+{
- 	if (cpu_is_u8500_family() || cpu_is_ux540_family())
- 		l2x0_base = __io_address(U8500_L2CC_BASE);
- 	else
-@@ -48,28 +54,12 @@
- 	/* Unlock before init */
- 	ux500_l2x0_unlock();
- 
--	/* DBx540's L2 has 128KB way size */
--	if (cpu_is_ux540_family())
--		/* 128KB way size */
--		aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
--	else
--		/* 64KB way size */
--		aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT);
-+	outer_cache.write_sec = ux500_l2c310_write_sec;
- 
--	/* 64KB way size, 8 way associativity, force WA */
- 	if (of_have_populated_dt())
--		l2x0_of_init(aux_val, 0xc0000fff);
-+		l2x0_of_init(0, ~0);
- 	else
--		l2x0_init(l2x0_base, aux_val, 0xc0000fff);
--
--	/*
--	 * We can't disable l2 as we are in non secure mode, currently
--	 * this seems be called only during kexec path. So let's
--	 * override outer.disable with nasty assignment until we have
--	 * some SMI service available.
--	 */
--	outer_cache.disable = NULL;
--	outer_cache.set_debug = NULL;
-+		l2x0_init(l2x0_base, 0, ~0);
- 
- 	return 0;
- }
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-vexpress/ct-ca9x4.c linux-3.15-rc6/arch/arm/mach-vexpress/ct-ca9x4.c
---- linux-3.15-rc6.orig/arch/arm/mach-vexpress/ct-ca9x4.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-vexpress/ct-ca9x4.c	2014-05-23 11:26:48.276939940 +0200
-@@ -45,6 +45,23 @@
- 	iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
- }
- 
-+static void __init ca9x4_l2_init(void)
-+{
-+#ifdef CONFIG_CACHE_L2X0
-+	void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
-+
-+	if (l2x0_base) {
-+		/* set RAM latencies to 1 cycle for this core tile. */
-+		writel(0, l2x0_base + L310_TAG_LATENCY_CTRL);
-+		writel(0, l2x0_base + L310_DATA_LATENCY_CTRL);
-+
-+		l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
-+	} else {
-+		pr_err("L2C: unable to map L2 cache controller\n");
-+	}
-+#endif
-+}
-+
- #ifdef CONFIG_HAVE_ARM_TWD
- static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER);
- 
-@@ -63,6 +80,7 @@
- 	gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K),
- 		 ioremap(A9_MPCORE_GIC_CPU, SZ_256));
- 	ca9x4_twd_init();
-+	ca9x4_l2_init();
- }
- 
- static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
-@@ -141,16 +159,6 @@
- {
- 	int i;
- 
--#ifdef CONFIG_CACHE_L2X0
--	void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
--
--	/* set RAM latencies to 1 cycle for this core tile. */
--	writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL);
--	writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL);
--
--	l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
--#endif
--
- 	for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
- 		amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mach-zynq/common.c linux-3.15-rc6/arch/arm/mach-zynq/common.c
---- linux-3.15-rc6.orig/arch/arm/mach-zynq/common.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mach-zynq/common.c	2014-05-23 11:26:48.276939940 +0200
-@@ -70,7 +70,7 @@
- 	/*
- 	 * 64KB way size, 8-way associativity, parity disabled
- 	 */
--	l2x0_of_init(0x02060000, 0xF0F0FFFF);
-+	l2x0_of_init(0x02000000, 0xf0ffffff);
- 
- 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/cache-feroceon-l2.c linux-3.15-rc6/arch/arm/mm/cache-feroceon-l2.c
---- linux-3.15-rc6.orig/arch/arm/mm/cache-feroceon-l2.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mm/cache-feroceon-l2.c	2014-05-23 11:26:48.280939953 +0200
-@@ -350,7 +350,6 @@
- 	outer_cache.inv_range = feroceon_l2_inv_range;
- 	outer_cache.clean_range = feroceon_l2_clean_range;
- 	outer_cache.flush_range = feroceon_l2_flush_range;
--	outer_cache.inv_all = l2_inv_all;
- 
- 	enable_l2();
- 
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/cache-l2x0.c linux-3.15-rc6/arch/arm/mm/cache-l2x0.c
---- linux-3.15-rc6.orig/arch/arm/mm/cache-l2x0.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mm/cache-l2x0.c	2014-05-23 11:26:48.280939953 +0200
-@@ -16,18 +16,33 @@
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-  */
-+#include <linux/cpu.h>
- #include <linux/err.h>
- #include <linux/init.h>
-+#include <linux/smp.h>
- #include <linux/spinlock.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- 
- #include <asm/cacheflush.h>
-+#include <asm/cp15.h>
-+#include <asm/cputype.h>
- #include <asm/hardware/cache-l2x0.h>
- #include "cache-tauros3.h"
- #include "cache-aurora-l2.h"
- 
-+struct l2c_init_data {
-+	const char *type;
-+	unsigned way_size_0;
-+	unsigned num_lock;
-+	void (*of_parse)(const struct device_node *, u32 *, u32 *);
-+	void (*enable)(void __iomem *, u32, unsigned);
-+	void (*fixup)(void __iomem *, u32, struct outer_cache_fns *);
-+	void (*save)(void __iomem *);
-+	struct outer_cache_fns outer_cache;
-+};
-+
- #define CACHE_LINE_SIZE		32
- 
- static void __iomem *l2x0_base;
-@@ -36,96 +51,116 @@
- static u32 l2x0_size;
- static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
- 
--/* Aurora don't have the cache ID register available, so we have to
-- * pass it though the device tree */
--static u32  cache_id_part_number_from_dt;
--
- struct l2x0_regs l2x0_saved_regs;
- 
--struct l2x0_of_data {
--	void (*setup)(const struct device_node *, u32 *, u32 *);
--	void (*save)(void);
--	struct outer_cache_fns outer_cache;
--};
--
--static bool of_init = false;
--
--static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
-+/*
-+ * Common code for all cache controllers.
-+ */
-+static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask)
- {
- 	/* wait for cache operation by line or way to complete */
- 	while (readl_relaxed(reg) & mask)
- 		cpu_relax();
- }
- 
--#ifdef CONFIG_CACHE_PL310
--static inline void cache_wait(void __iomem *reg, unsigned long mask)
-+/*
-+ * By default, we write directly to secure registers.  Platforms must
-+ * override this if they are running non-secure.
-+ */
-+static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg)
- {
--	/* cache operations by line are atomic on PL310 */
-+	if (val == readl_relaxed(base + reg))
-+		return;
-+	if (outer_cache.write_sec)
-+		outer_cache.write_sec(val, reg);
-+	else
-+		writel_relaxed(val, base + reg);
- }
--#else
--#define cache_wait	cache_wait_way
--#endif
- 
--static inline void cache_sync(void)
-+/*
-+ * This should only be called when we have a requirement that the
-+ * register be written due to a work-around, as platforms running
-+ * in non-secure mode may not be able to access this register.
-+ */
-+static inline void l2c_set_debug(void __iomem *base, unsigned long val)
- {
--	void __iomem *base = l2x0_base;
--
--	writel_relaxed(0, base + sync_reg_offset);
--	cache_wait(base + L2X0_CACHE_SYNC, 1);
-+	l2c_write_sec(val, base, L2X0_DEBUG_CTRL);
- }
- 
--static inline void l2x0_clean_line(unsigned long addr)
-+static void __l2c_op_way(void __iomem *reg)
- {
--	void __iomem *base = l2x0_base;
--	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
--	writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
-+	writel_relaxed(l2x0_way_mask, reg);
-+	l2c_wait_mask(reg, l2x0_way_mask);
- }
- 
--static inline void l2x0_inv_line(unsigned long addr)
-+static inline void l2c_unlock(void __iomem *base, unsigned num)
- {
--	void __iomem *base = l2x0_base;
--	cache_wait(base + L2X0_INV_LINE_PA, 1);
--	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
-+	unsigned i;
-+
-+	for (i = 0; i < num; i++) {
-+		writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_D_BASE +
-+			       i * L2X0_LOCKDOWN_STRIDE);
-+		writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_I_BASE +
-+			       i * L2X0_LOCKDOWN_STRIDE);
-+	}
- }
- 
--#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
--static inline void debug_writel(unsigned long val)
-+/*
-+ * Enable the L2 cache controller.  This function must only be
-+ * called when the cache controller is known to be disabled.
-+ */
-+static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock)
- {
--	if (outer_cache.set_debug)
--		outer_cache.set_debug(val);
-+	unsigned long flags;
-+
-+	l2c_write_sec(aux, base, L2X0_AUX_CTRL);
-+
-+	l2c_unlock(base, num_lock);
-+
-+	local_irq_save(flags);
-+	__l2c_op_way(base + L2X0_INV_WAY);
-+	writel_relaxed(0, base + sync_reg_offset);
-+	l2c_wait_mask(base + sync_reg_offset, 1);
-+	local_irq_restore(flags);
-+
-+	l2c_write_sec(L2X0_CTRL_EN, base, L2X0_CTRL);
- }
- 
--static void pl310_set_debug(unsigned long val)
-+static void l2c_disable(void)
- {
--	writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
-+	void __iomem *base = l2x0_base;
-+
-+	outer_cache.flush_all();
-+	l2c_write_sec(0, base, L2X0_CTRL);
-+	dsb(st);
- }
--#else
--/* Optimised out for non-errata case */
--static inline void debug_writel(unsigned long val)
-+
-+#ifdef CONFIG_CACHE_PL310
-+static inline void cache_wait(void __iomem *reg, unsigned long mask)
- {
-+	/* cache operations by line are atomic on PL310 */
- }
--
--#define pl310_set_debug	NULL
-+#else
-+#define cache_wait	l2c_wait_mask
- #endif
- 
--#ifdef CONFIG_PL310_ERRATA_588369
--static inline void l2x0_flush_line(unsigned long addr)
-+static inline void cache_sync(void)
- {
- 	void __iomem *base = l2x0_base;
- 
--	/* Clean by PA followed by Invalidate by PA */
--	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
--	writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
--	cache_wait(base + L2X0_INV_LINE_PA, 1);
--	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
-+	writel_relaxed(0, base + sync_reg_offset);
-+	cache_wait(base + L2X0_CACHE_SYNC, 1);
- }
--#else
- 
--static inline void l2x0_flush_line(unsigned long addr)
-+#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
-+static inline void debug_writel(unsigned long val)
-+{
-+	l2c_set_debug(l2x0_base, val);
-+}
-+#else
-+/* Optimised out for non-errata case */
-+static inline void debug_writel(unsigned long val)
- {
--	void __iomem *base = l2x0_base;
--	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
--	writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA);
- }
- #endif
- 
-@@ -141,8 +176,7 @@
- static void __l2x0_flush_all(void)
- {
- 	debug_writel(0x03);
--	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
--	cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
-+	__l2c_op_way(l2x0_base + L2X0_CLEAN_INV_WAY);
- 	cache_sync();
- 	debug_writel(0x00);
- }
-@@ -157,274 +191,882 @@
- 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
- 
--static void l2x0_clean_all(void)
-+static void l2x0_disable(void)
- {
- 	unsigned long flags;
- 
--	/* clean all ways */
- 	raw_spin_lock_irqsave(&l2x0_lock, flags);
--	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
--	cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
--	cache_sync();
-+	__l2x0_flush_all();
-+	l2c_write_sec(0, l2x0_base, L2X0_CTRL);
-+	dsb(st);
- 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
- 
--static void l2x0_inv_all(void)
-+static void l2c_save(void __iomem *base)
- {
--	unsigned long flags;
-+	l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
-+}
- 
--	/* invalidate all ways */
--	raw_spin_lock_irqsave(&l2x0_lock, flags);
--	/* Invalidating when L2 is enabled is a nono */
--	BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
--	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
--	cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
--	cache_sync();
--	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+/*
-+ * L2C-210 specific code.
-+ *
-+ * The L2C-2x0 PA, set/way and sync operations are atomic, but we must
-+ * ensure that no background operation is running.  The way operations
-+ * are all background tasks.
-+ *
-+ * While a background operation is in progress, any new operation is
-+ * ignored (unspecified whether this causes an error.)  Thankfully, not
-+ * used on SMP.
-+ *
-+ * Never has a different sync register other than L2X0_CACHE_SYNC, but
-+ * we use sync_reg_offset here so we can share some of this with L2C-310.
-+ */
-+static void __l2c210_cache_sync(void __iomem *base)
-+{
-+	writel_relaxed(0, base + sync_reg_offset);
- }
- 
--static void l2x0_inv_range(unsigned long start, unsigned long end)
-+static void __l2c210_op_pa_range(void __iomem *reg, unsigned long start,
-+	unsigned long end)
-+{
-+	while (start < end) {
-+		writel_relaxed(start, reg);
-+		start += CACHE_LINE_SIZE;
-+	}
-+}
-+
-+static void l2c210_inv_range(unsigned long start, unsigned long end)
- {
- 	void __iomem *base = l2x0_base;
--	unsigned long flags;
- 
--	raw_spin_lock_irqsave(&l2x0_lock, flags);
- 	if (start & (CACHE_LINE_SIZE - 1)) {
- 		start &= ~(CACHE_LINE_SIZE - 1);
--		debug_writel(0x03);
--		l2x0_flush_line(start);
--		debug_writel(0x00);
-+		writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA);
- 		start += CACHE_LINE_SIZE;
- 	}
- 
- 	if (end & (CACHE_LINE_SIZE - 1)) {
- 		end &= ~(CACHE_LINE_SIZE - 1);
--		debug_writel(0x03);
--		l2x0_flush_line(end);
--		debug_writel(0x00);
-+		writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA);
- 	}
- 
-+	__l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end);
-+	__l2c210_cache_sync(base);
-+}
-+
-+static void l2c210_clean_range(unsigned long start, unsigned long end)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	start &= ~(CACHE_LINE_SIZE - 1);
-+	__l2c210_op_pa_range(base + L2X0_CLEAN_LINE_PA, start, end);
-+	__l2c210_cache_sync(base);
-+}
-+
-+static void l2c210_flush_range(unsigned long start, unsigned long end)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	start &= ~(CACHE_LINE_SIZE - 1);
-+	__l2c210_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, start, end);
-+	__l2c210_cache_sync(base);
-+}
-+
-+static void l2c210_flush_all(void)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	BUG_ON(!irqs_disabled());
-+
-+	__l2c_op_way(base + L2X0_CLEAN_INV_WAY);
-+	__l2c210_cache_sync(base);
-+}
-+
-+static void l2c210_sync(void)
-+{
-+	__l2c210_cache_sync(l2x0_base);
-+}
-+
-+static void l2c210_resume(void)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN))
-+		l2c_enable(base, l2x0_saved_regs.aux_ctrl, 1);
-+}
-+
-+static const struct l2c_init_data l2c210_data __initconst = {
-+	.type = "L2C-210",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 1,
-+	.enable = l2c_enable,
-+	.save = l2c_save,
-+	.outer_cache = {
-+		.inv_range = l2c210_inv_range,
-+		.clean_range = l2c210_clean_range,
-+		.flush_range = l2c210_flush_range,
-+		.flush_all = l2c210_flush_all,
-+		.disable = l2c_disable,
-+		.sync = l2c210_sync,
-+		.resume = l2c210_resume,
-+	},
-+};
-+
-+/*
-+ * L2C-220 specific code.
-+ *
-+ * All operations are background operations: they have to be waited for.
-+ * Conflicting requests generate a slave error (which will cause an
-+ * imprecise abort.)  Never uses sync_reg_offset, so we hard-code the
-+ * sync register here.
-+ *
-+ * However, we can re-use the l2c210_resume call.
-+ */
-+static inline void __l2c220_cache_sync(void __iomem *base)
-+{
-+	writel_relaxed(0, base + L2X0_CACHE_SYNC);
-+	l2c_wait_mask(base + L2X0_CACHE_SYNC, 1);
-+}
-+
-+static void l2c220_op_way(void __iomem *base, unsigned reg)
-+{
-+	unsigned long flags;
-+
-+	raw_spin_lock_irqsave(&l2x0_lock, flags);
-+	__l2c_op_way(base + reg);
-+	__l2c220_cache_sync(base);
-+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+}
-+
-+static unsigned long l2c220_op_pa_range(void __iomem *reg, unsigned long start,
-+	unsigned long end, unsigned long flags)
-+{
-+	raw_spinlock_t *lock = &l2x0_lock;
-+
- 	while (start < end) {
- 		unsigned long blk_end = start + min(end - start, 4096UL);
- 
- 		while (start < blk_end) {
--			l2x0_inv_line(start);
-+			l2c_wait_mask(reg, 1);
-+			writel_relaxed(start, reg);
- 			start += CACHE_LINE_SIZE;
- 		}
- 
- 		if (blk_end < end) {
--			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
--			raw_spin_lock_irqsave(&l2x0_lock, flags);
-+			raw_spin_unlock_irqrestore(lock, flags);
-+			raw_spin_lock_irqsave(lock, flags);
- 		}
- 	}
--	cache_wait(base + L2X0_INV_LINE_PA, 1);
--	cache_sync();
--	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+
-+	return flags;
- }
- 
--static void l2x0_clean_range(unsigned long start, unsigned long end)
-+static void l2c220_inv_range(unsigned long start, unsigned long end)
- {
- 	void __iomem *base = l2x0_base;
- 	unsigned long flags;
- 
--	if ((end - start) >= l2x0_size) {
--		l2x0_clean_all();
--		return;
--	}
--
- 	raw_spin_lock_irqsave(&l2x0_lock, flags);
--	start &= ~(CACHE_LINE_SIZE - 1);
--	while (start < end) {
--		unsigned long blk_end = start + min(end - start, 4096UL);
--
--		while (start < blk_end) {
--			l2x0_clean_line(start);
-+	if ((start | end) & (CACHE_LINE_SIZE - 1)) {
-+		if (start & (CACHE_LINE_SIZE - 1)) {
-+			start &= ~(CACHE_LINE_SIZE - 1);
-+			writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA);
- 			start += CACHE_LINE_SIZE;
- 		}
- 
--		if (blk_end < end) {
--			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
--			raw_spin_lock_irqsave(&l2x0_lock, flags);
-+		if (end & (CACHE_LINE_SIZE - 1)) {
-+			end &= ~(CACHE_LINE_SIZE - 1);
-+			l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
-+			writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA);
- 		}
- 	}
--	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
--	cache_sync();
-+
-+	flags = l2c220_op_pa_range(base + L2X0_INV_LINE_PA,
-+				   start, end, flags);
-+	l2c_wait_mask(base + L2X0_INV_LINE_PA, 1);
-+	__l2c220_cache_sync(base);
- 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
- 
--static void l2x0_flush_range(unsigned long start, unsigned long end)
-+static void l2c220_clean_range(unsigned long start, unsigned long end)
- {
- 	void __iomem *base = l2x0_base;
- 	unsigned long flags;
- 
-+	start &= ~(CACHE_LINE_SIZE - 1);
- 	if ((end - start) >= l2x0_size) {
--		l2x0_flush_all();
-+		l2c220_op_way(base, L2X0_CLEAN_WAY);
- 		return;
- 	}
- 
- 	raw_spin_lock_irqsave(&l2x0_lock, flags);
-+	flags = l2c220_op_pa_range(base + L2X0_CLEAN_LINE_PA,
-+				   start, end, flags);
-+	l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
-+	__l2c220_cache_sync(base);
-+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+}
-+
-+static void l2c220_flush_range(unsigned long start, unsigned long end)
-+{
-+	void __iomem *base = l2x0_base;
-+	unsigned long flags;
-+
- 	start &= ~(CACHE_LINE_SIZE - 1);
-+	if ((end - start) >= l2x0_size) {
-+		l2c220_op_way(base, L2X0_CLEAN_INV_WAY);
-+		return;
-+	}
-+
-+	raw_spin_lock_irqsave(&l2x0_lock, flags);
-+	flags = l2c220_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA,
-+				   start, end, flags);
-+	l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1);
-+	__l2c220_cache_sync(base);
-+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+}
-+
-+static void l2c220_flush_all(void)
-+{
-+	l2c220_op_way(l2x0_base, L2X0_CLEAN_INV_WAY);
-+}
-+
-+static void l2c220_sync(void)
-+{
-+	unsigned long flags;
-+
-+	raw_spin_lock_irqsave(&l2x0_lock, flags);
-+	__l2c220_cache_sync(l2x0_base);
-+	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+}
-+
-+static void l2c220_enable(void __iomem *base, u32 aux, unsigned num_lock)
-+{
-+	/*
-+	 * Always enable non-secure access to the lockdown registers -
-+	 * we write to them as part of the L2C enable sequence so they
-+	 * need to be accessible.
-+	 */
-+	aux |= L220_AUX_CTRL_NS_LOCKDOWN;
-+
-+	l2c_enable(base, aux, num_lock);
-+}
-+
-+static const struct l2c_init_data l2c220_data = {
-+	.type = "L2C-220",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 1,
-+	.enable = l2c220_enable,
-+	.save = l2c_save,
-+	.outer_cache = {
-+		.inv_range = l2c220_inv_range,
-+		.clean_range = l2c220_clean_range,
-+		.flush_range = l2c220_flush_range,
-+		.flush_all = l2c220_flush_all,
-+		.disable = l2c_disable,
-+		.sync = l2c220_sync,
-+		.resume = l2c210_resume,
-+	},
-+};
-+
-+/*
-+ * L2C-310 specific code.
-+ *
-+ * Very similar to L2C-210, the PA, set/way and sync operations are atomic,
-+ * and the way operations are all background tasks.  However, issuing an
-+ * operation while a background operation is in progress results in a
-+ * SLVERR response.  We can reuse:
-+ *
-+ *  __l2c210_cache_sync (using sync_reg_offset)
-+ *  l2c210_sync
-+ *  l2c210_inv_range (if 588369 is not applicable)
-+ *  l2c210_clean_range
-+ *  l2c210_flush_range (if 588369 is not applicable)
-+ *  l2c210_flush_all (if 727915 is not applicable)
-+ *
-+ * Errata:
-+ * 588369: PL310 R0P0->R1P0, fixed R2P0.
-+ *	Affects: all clean+invalidate operations
-+ *	clean and invalidate skips the invalidate step, so we need to issue
-+ *	separate operations.  We also require the above debug workaround
-+ *	enclosing this code fragment on affected parts.  On unaffected parts,
-+ *	we must not use this workaround without the debug register writes
-+ *	to avoid exposing a problem similar to 727915.
-+ *
-+ * 727915: PL310 R2P0->R3P0, fixed R3P1.
-+ *	Affects: clean+invalidate by way
-+ *	clean and invalidate by way runs in the background, and a store can
-+ *	hit the line between the clean operation and invalidate operation,
-+ *	resulting in the store being lost.
-+ *
-+ * 752271: PL310 R3P0->R3P1-50REL0, fixed R3P2.
-+ *	Affects: 8x64-bit (double fill) line fetches
-+ *	double fill line fetches can fail to cause dirty data to be evicted
-+ *	from the cache before the new data overwrites the second line.
-+ *
-+ * 753970: PL310 R3P0, fixed R3P1.
-+ *	Affects: sync
-+ *	prevents merging writes after the sync operation, until another L2C
-+ *	operation is performed (or a number of other conditions.)
-+ *
-+ * 769419: PL310 R0P0->R3P1, fixed R3P2.
-+ *	Affects: store buffer
-+ *	store buffer is not automatically drained.
-+ */
-+static void l2c310_inv_range_erratum(unsigned long start, unsigned long end)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	if ((start | end) & (CACHE_LINE_SIZE - 1)) {
-+		unsigned long flags;
-+
-+		/* Erratum 588369 for both clean+invalidate operations */
-+		raw_spin_lock_irqsave(&l2x0_lock, flags);
-+		l2c_set_debug(base, 0x03);
-+
-+		if (start & (CACHE_LINE_SIZE - 1)) {
-+			start &= ~(CACHE_LINE_SIZE - 1);
-+			writel_relaxed(start, base + L2X0_CLEAN_LINE_PA);
-+			writel_relaxed(start, base + L2X0_INV_LINE_PA);
-+			start += CACHE_LINE_SIZE;
-+		}
-+
-+		if (end & (CACHE_LINE_SIZE - 1)) {
-+			end &= ~(CACHE_LINE_SIZE - 1);
-+			writel_relaxed(end, base + L2X0_CLEAN_LINE_PA);
-+			writel_relaxed(end, base + L2X0_INV_LINE_PA);
-+		}
-+
-+		l2c_set_debug(base, 0x00);
-+		raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+	}
-+
-+	__l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end);
-+	__l2c210_cache_sync(base);
-+}
-+
-+static void l2c310_flush_range_erratum(unsigned long start, unsigned long end)
-+{
-+	raw_spinlock_t *lock = &l2x0_lock;
-+	unsigned long flags;
-+	void __iomem *base = l2x0_base;
-+
-+	raw_spin_lock_irqsave(lock, flags);
- 	while (start < end) {
- 		unsigned long blk_end = start + min(end - start, 4096UL);
- 
--		debug_writel(0x03);
-+		l2c_set_debug(base, 0x03);
- 		while (start < blk_end) {
--			l2x0_flush_line(start);
-+			writel_relaxed(start, base + L2X0_CLEAN_LINE_PA);
-+			writel_relaxed(start, base + L2X0_INV_LINE_PA);
- 			start += CACHE_LINE_SIZE;
- 		}
--		debug_writel(0x00);
-+		l2c_set_debug(base, 0x00);
- 
- 		if (blk_end < end) {
--			raw_spin_unlock_irqrestore(&l2x0_lock, flags);
--			raw_spin_lock_irqsave(&l2x0_lock, flags);
-+			raw_spin_unlock_irqrestore(lock, flags);
-+			raw_spin_lock_irqsave(lock, flags);
- 		}
- 	}
--	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
--	cache_sync();
--	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
-+	raw_spin_unlock_irqrestore(lock, flags);
-+	__l2c210_cache_sync(base);
- }
- 
--static void l2x0_disable(void)
-+static void l2c310_flush_all_erratum(void)
- {
-+	void __iomem *base = l2x0_base;
- 	unsigned long flags;
- 
- 	raw_spin_lock_irqsave(&l2x0_lock, flags);
--	__l2x0_flush_all();
--	writel_relaxed(0, l2x0_base + L2X0_CTRL);
--	dsb(st);
-+	l2c_set_debug(base, 0x03);
-+	__l2c_op_way(base + L2X0_CLEAN_INV_WAY);
-+	l2c_set_debug(base, 0x00);
-+	__l2c210_cache_sync(base);
- 	raw_spin_unlock_irqrestore(&l2x0_lock, flags);
- }
- 
--static void l2x0_unlock(u32 cache_id)
-+static void __init l2c310_save(void __iomem *base)
- {
--	int lockregs;
--	int i;
-+	unsigned revision;
- 
--	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
--	case L2X0_CACHE_ID_PART_L310:
--		lockregs = 8;
--		break;
--	case AURORA_CACHE_ID:
--		lockregs = 4;
-+	l2c_save(base);
-+
-+	l2x0_saved_regs.tag_latency = readl_relaxed(base +
-+		L310_TAG_LATENCY_CTRL);
-+	l2x0_saved_regs.data_latency = readl_relaxed(base +
-+		L310_DATA_LATENCY_CTRL);
-+	l2x0_saved_regs.filter_end = readl_relaxed(base +
-+		L310_ADDR_FILTER_END);
-+	l2x0_saved_regs.filter_start = readl_relaxed(base +
-+		L310_ADDR_FILTER_START);
-+
-+	revision = readl_relaxed(base + L2X0_CACHE_ID) &
-+			L2X0_CACHE_ID_RTL_MASK;
-+
-+	/* From r2p0, there is Prefetch offset/control register */
-+	if (revision >= L310_CACHE_ID_RTL_R2P0)
-+		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base +
-+							L310_PREFETCH_CTRL);
-+
-+	/* From r3p0, there is Power control register */
-+	if (revision >= L310_CACHE_ID_RTL_R3P0)
-+		l2x0_saved_regs.pwr_ctrl = readl_relaxed(base +
-+							L310_POWER_CTRL);
-+}
-+
-+static void l2c310_resume(void)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
-+		unsigned revision;
-+
-+		/* restore pl310 setup */
-+		writel_relaxed(l2x0_saved_regs.tag_latency,
-+			       base + L310_TAG_LATENCY_CTRL);
-+		writel_relaxed(l2x0_saved_regs.data_latency,
-+			       base + L310_DATA_LATENCY_CTRL);
-+		writel_relaxed(l2x0_saved_regs.filter_end,
-+			       base + L310_ADDR_FILTER_END);
-+		writel_relaxed(l2x0_saved_regs.filter_start,
-+			       base + L310_ADDR_FILTER_START);
-+
-+		revision = readl_relaxed(base + L2X0_CACHE_ID) &
-+				L2X0_CACHE_ID_RTL_MASK;
-+
-+		if (revision >= L310_CACHE_ID_RTL_R2P0)
-+			l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base,
-+				      L310_PREFETCH_CTRL);
-+		if (revision >= L310_CACHE_ID_RTL_R3P0)
-+			l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base,
-+				      L310_POWER_CTRL);
-+
-+		l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
-+
-+		/* Re-enable full-line-of-zeros for Cortex-A9 */
-+		if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
-+			set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
-+	}
-+}
-+
-+static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data)
-+{
-+	switch (act & ~CPU_TASKS_FROZEN) {
-+	case CPU_STARTING:
-+		set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
- 		break;
--	default:
--		/* L210 and unknown types */
--		lockregs = 1;
-+	case CPU_DYING:
-+		set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1)));
- 		break;
- 	}
-+	return NOTIFY_OK;
-+}
- 
--	for (i = 0; i < lockregs; i++) {
--		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
--			       i * L2X0_LOCKDOWN_STRIDE);
--		writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
--			       i * L2X0_LOCKDOWN_STRIDE);
-+static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock)
-+{
-+	unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK;
-+	bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
-+
-+	if (rev >= L310_CACHE_ID_RTL_R2P0) {
-+		if (cortex_a9) {
-+			aux |= L310_AUX_CTRL_EARLY_BRESP;
-+			pr_info("L2C-310 enabling early BRESP for Cortex-A9\n");
-+		} else if (aux & L310_AUX_CTRL_EARLY_BRESP) {
-+			pr_warn("L2C-310 early BRESP only supported with Cortex-A9\n");
-+			aux &= ~L310_AUX_CTRL_EARLY_BRESP;
-+		}
-+	}
-+
-+	if (cortex_a9) {
-+		u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL);
-+		u32 acr = get_auxcr();
-+
-+		pr_debug("Cortex-A9 ACR=0x%08x\n", acr);
-+
-+		if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO))
-+			pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n");
-+
-+		if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3)))
-+			pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n");
-+
-+		if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) {
-+			aux |= L310_AUX_CTRL_FULL_LINE_ZERO;
-+			pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n");
-+		}
-+	} else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) {
-+		pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n");
-+		aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP);
-+	}
-+
-+	if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) {
-+		u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL);
-+
-+		pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n",
-+			aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "",
-+			aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "",
-+			1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK));
-+	}
-+
-+	/* r3p0 or later has power control register */
-+	if (rev >= L310_CACHE_ID_RTL_R3P0) {
-+		u32 power_ctrl;
-+
-+		l2c_write_sec(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN,
-+			      base, L310_POWER_CTRL);
-+		power_ctrl = readl_relaxed(base + L310_POWER_CTRL);
-+		pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n",
-+			power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis",
-+			power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis");
-+	}
-+
-+	/*
-+	 * Always enable non-secure access to the lockdown registers -
-+	 * we write to them as part of the L2C enable sequence so they
-+	 * need to be accessible.
-+	 */
-+	aux |= L310_AUX_CTRL_NS_LOCKDOWN;
-+
-+	l2c_enable(base, aux, num_lock);
-+
-+	if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) {
-+		set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1));
-+		cpu_notifier(l2c310_cpu_enable_flz, 0);
- 	}
- }
- 
--void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
-+static void __init l2c310_fixup(void __iomem *base, u32 cache_id,
-+	struct outer_cache_fns *fns)
- {
--	u32 aux;
--	u32 cache_id;
--	u32 way_size = 0;
--	int ways;
--	int way_size_shift = L2X0_WAY_SIZE_SHIFT;
--	const char *type;
-+	unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK;
-+	const char *errata[8];
-+	unsigned n = 0;
- 
--	l2x0_base = base;
--	if (cache_id_part_number_from_dt)
--		cache_id = cache_id_part_number_from_dt;
--	else
--		cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
--	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
-+	if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) &&
-+	    revision < L310_CACHE_ID_RTL_R2P0 &&
-+	    /* For bcm compatibility */
-+	    fns->inv_range == l2c210_inv_range) {
-+		fns->inv_range = l2c310_inv_range_erratum;
-+		fns->flush_range = l2c310_flush_range_erratum;
-+		errata[n++] = "588369";
-+	}
-+
-+	if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) &&
-+	    revision >= L310_CACHE_ID_RTL_R2P0 &&
-+	    revision < L310_CACHE_ID_RTL_R3P1) {
-+		fns->flush_all = l2c310_flush_all_erratum;
-+		errata[n++] = "727915";
-+	}
-+
-+	if (revision >= L310_CACHE_ID_RTL_R3P0 &&
-+	    revision < L310_CACHE_ID_RTL_R3P2) {
-+		u32 val = readl_relaxed(base + L310_PREFETCH_CTRL);
-+		/* I don't think bit23 is required here... but iMX6 does so */
-+		if (val & (BIT(30) | BIT(23))) {
-+			val &= ~(BIT(30) | BIT(23));
-+			l2c_write_sec(val, base, L310_PREFETCH_CTRL);
-+			errata[n++] = "752271";
-+		}
-+	}
-+
-+	if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) &&
-+	    revision == L310_CACHE_ID_RTL_R3P0) {
-+		sync_reg_offset = L2X0_DUMMY_REG;
-+		errata[n++] = "753970";
-+	}
-+
-+	if (IS_ENABLED(CONFIG_PL310_ERRATA_769419))
-+		errata[n++] = "769419";
-+
-+	if (n) {
-+		unsigned i;
-+
-+		pr_info("L2C-310 errat%s", n > 1 ? "a" : "um");
-+		for (i = 0; i < n; i++)
-+			pr_cont(" %s", errata[i]);
-+		pr_cont(" enabled\n");
-+	}
-+}
-+
-+static void l2c310_disable(void)
-+{
-+	/*
-+	 * If full-line-of-zeros is enabled, we must first disable it in the
-+	 * Cortex-A9 auxiliary control register before disabling the L2 cache.
-+	 */
-+	if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO)
-+		set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1)));
- 
-+	l2c_disable();
-+}
-+
-+static const struct l2c_init_data l2c310_init_fns __initconst = {
-+	.type = "L2C-310",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 8,
-+	.enable = l2c310_enable,
-+	.fixup = l2c310_fixup,
-+	.save = l2c310_save,
-+	.outer_cache = {
-+		.inv_range = l2c210_inv_range,
-+		.clean_range = l2c210_clean_range,
-+		.flush_range = l2c210_flush_range,
-+		.flush_all = l2c210_flush_all,
-+		.disable = l2c310_disable,
-+		.sync = l2c210_sync,
-+		.resume = l2c310_resume,
-+	},
-+};
-+
-+static void __init __l2c_init(const struct l2c_init_data *data,
-+	u32 aux_val, u32 aux_mask, u32 cache_id)
-+{
-+	struct outer_cache_fns fns;
-+	unsigned way_size_bits, ways;
-+	u32 aux, old_aux;
-+
-+	/*
-+	 * Sanity check the aux values.  aux_mask is the bits we preserve
-+	 * from reading the hardware register, and aux_val is the bits we
-+	 * set.
-+	 */
-+	if (aux_val & aux_mask)
-+		pr_alert("L2C: platform provided aux values permit register corruption.\n");
-+
-+	old_aux = aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
- 	aux &= aux_mask;
- 	aux |= aux_val;
- 
-+	if (old_aux != aux)
-+		pr_warn("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n",
-+		        old_aux, aux);
-+
- 	/* Determine the number of ways */
- 	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
- 	case L2X0_CACHE_ID_PART_L310:
-+		if ((aux_val | ~aux_mask) & (L2C_AUX_CTRL_WAY_SIZE_MASK | L310_AUX_CTRL_ASSOCIATIVITY_16))
-+			pr_warn("L2C: DT/platform tries to modify or specify cache size\n");
- 		if (aux & (1 << 16))
- 			ways = 16;
- 		else
- 			ways = 8;
--		type = "L310";
--#ifdef CONFIG_PL310_ERRATA_753970
--		/* Unmapped register. */
--		sync_reg_offset = L2X0_DUMMY_REG;
--#endif
--		if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
--			outer_cache.set_debug = pl310_set_debug;
- 		break;
-+
- 	case L2X0_CACHE_ID_PART_L210:
-+	case L2X0_CACHE_ID_PART_L220:
- 		ways = (aux >> 13) & 0xf;
--		type = "L210";
- 		break;
- 
- 	case AURORA_CACHE_ID:
--		sync_reg_offset = AURORA_SYNC_REG;
- 		ways = (aux >> 13) & 0xf;
- 		ways = 2 << ((ways + 1) >> 2);
--		way_size_shift = AURORA_WAY_SIZE_SHIFT;
--		type = "Aurora";
- 		break;
-+
- 	default:
- 		/* Assume unknown chips have 8 ways */
- 		ways = 8;
--		type = "L2x0 series";
- 		break;
- 	}
- 
- 	l2x0_way_mask = (1 << ways) - 1;
- 
- 	/*
--	 * L2 cache Size =  Way size * Number of ways
-+	 * way_size_0 is the size that a way_size value of zero would be
-+	 * given the calculation: way_size = way_size_0 << way_size_bits.
-+	 * So, if way_size_bits=0 is reserved, but way_size_bits=1 is 16k,
-+	 * then way_size_0 would be 8k.
-+	 *
-+	 * L2 cache size = number of ways * way size.
-+	 */
-+	way_size_bits = (aux & L2C_AUX_CTRL_WAY_SIZE_MASK) >>
-+			L2C_AUX_CTRL_WAY_SIZE_SHIFT;
-+	l2x0_size = ways * (data->way_size_0 << way_size_bits);
-+
-+	fns = data->outer_cache;
-+	fns.write_sec = outer_cache.write_sec;
-+	if (data->fixup)
-+		data->fixup(l2x0_base, cache_id, &fns);
-+
-+	/*
-+	 * Check if l2x0 controller is already enabled.  If we are booting
-+	 * in non-secure mode accessing the below registers will fault.
- 	 */
--	way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
--	way_size = 1 << (way_size + way_size_shift);
-+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN))
-+		data->enable(l2x0_base, aux, data->num_lock);
- 
--	l2x0_size = ways * way_size * SZ_1K;
-+	outer_cache = fns;
- 
- 	/*
--	 * Check if l2x0 controller is already enabled.
--	 * If you are booting from non-secure mode
--	 * accessing the below registers will fault.
-+	 * It is strange to save the register state before initialisation,
-+	 * but hey, this is what the DT implementations decided to do.
- 	 */
--	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
--		/* Make sure that I&D is not locked down when starting */
--		l2x0_unlock(cache_id);
-+	if (data->save)
-+		data->save(l2x0_base);
-+
-+	/* Re-read it in case some bits are reserved. */
-+	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
-+
-+	pr_info("%s cache controller enabled, %d ways, %d kB\n",
-+		data->type, ways, l2x0_size >> 10);
-+	pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
-+		data->type, cache_id, aux);
-+}
- 
--		/* l2x0 controller is disabled */
--		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
-+void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
-+{
-+	const struct l2c_init_data *data;
-+	u32 cache_id;
- 
--		l2x0_inv_all();
-+	l2x0_base = base;
- 
--		/* enable L2X0 */
--		writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
-+	cache_id = readl_relaxed(base + L2X0_CACHE_ID);
-+
-+	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
-+	default:
-+	case L2X0_CACHE_ID_PART_L210:
-+		data = &l2c210_data;
-+		break;
-+
-+	case L2X0_CACHE_ID_PART_L220:
-+		data = &l2c220_data;
-+		break;
-+
-+	case L2X0_CACHE_ID_PART_L310:
-+		data = &l2c310_init_fns;
-+		break;
- 	}
- 
--	/* Re-read it in case some bits are reserved. */
--	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
-+	__l2c_init(data, aux_val, aux_mask, cache_id);
-+}
-+
-+#ifdef CONFIG_OF
-+static int l2_wt_override;
-+
-+/* Aurora don't have the cache ID register available, so we have to
-+ * pass it though the device tree */
-+static u32 cache_id_part_number_from_dt;
-+
-+static void __init l2x0_of_parse(const struct device_node *np,
-+				 u32 *aux_val, u32 *aux_mask)
-+{
-+	u32 data[2] = { 0, 0 };
-+	u32 tag = 0;
-+	u32 dirty = 0;
-+	u32 val = 0, mask = 0;
-+
-+	of_property_read_u32(np, "arm,tag-latency", &tag);
-+	if (tag) {
-+		mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
-+		val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
-+	}
-+
-+	of_property_read_u32_array(np, "arm,data-latency",
-+				   data, ARRAY_SIZE(data));
-+	if (data[0] && data[1]) {
-+		mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
-+			L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
-+		val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
-+		       ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
-+	}
-+
-+	of_property_read_u32(np, "arm,dirty-latency", &dirty);
-+	if (dirty) {
-+		mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
-+		val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
-+	}
- 
--	/* Save the value for resuming. */
--	l2x0_saved_regs.aux_ctrl = aux;
-+	*aux_val &= ~mask;
-+	*aux_val |= val;
-+	*aux_mask &= ~mask;
-+}
-+
-+static const struct l2c_init_data of_l2c210_data __initconst = {
-+	.type = "L2C-210",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 1,
-+	.of_parse = l2x0_of_parse,
-+	.enable = l2c_enable,
-+	.save = l2c_save,
-+	.outer_cache = {
-+		.inv_range   = l2c210_inv_range,
-+		.clean_range = l2c210_clean_range,
-+		.flush_range = l2c210_flush_range,
-+		.flush_all   = l2c210_flush_all,
-+		.disable     = l2c_disable,
-+		.sync        = l2c210_sync,
-+		.resume      = l2c210_resume,
-+	},
-+};
-+
-+static const struct l2c_init_data of_l2c220_data __initconst = {
-+	.type = "L2C-220",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 1,
-+	.of_parse = l2x0_of_parse,
-+	.enable = l2c220_enable,
-+	.save = l2c_save,
-+	.outer_cache = {
-+		.inv_range   = l2c220_inv_range,
-+		.clean_range = l2c220_clean_range,
-+		.flush_range = l2c220_flush_range,
-+		.flush_all   = l2c220_flush_all,
-+		.disable     = l2c_disable,
-+		.sync        = l2c220_sync,
-+		.resume      = l2c210_resume,
-+	},
-+};
-+
-+static void __init l2c310_of_parse(const struct device_node *np,
-+	u32 *aux_val, u32 *aux_mask)
-+{
-+	u32 data[3] = { 0, 0, 0 };
-+	u32 tag[3] = { 0, 0, 0 };
-+	u32 filter[2] = { 0, 0 };
-+
-+	of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
-+	if (tag[0] && tag[1] && tag[2])
-+		writel_relaxed(
-+			L310_LATENCY_CTRL_RD(tag[0] - 1) |
-+			L310_LATENCY_CTRL_WR(tag[1] - 1) |
-+			L310_LATENCY_CTRL_SETUP(tag[2] - 1),
-+			l2x0_base + L310_TAG_LATENCY_CTRL);
-+
-+	of_property_read_u32_array(np, "arm,data-latency",
-+				   data, ARRAY_SIZE(data));
-+	if (data[0] && data[1] && data[2])
-+		writel_relaxed(
-+			L310_LATENCY_CTRL_RD(data[0] - 1) |
-+			L310_LATENCY_CTRL_WR(data[1] - 1) |
-+			L310_LATENCY_CTRL_SETUP(data[2] - 1),
-+			l2x0_base + L310_DATA_LATENCY_CTRL);
- 
--	if (!of_init) {
--		outer_cache.inv_range = l2x0_inv_range;
--		outer_cache.clean_range = l2x0_clean_range;
--		outer_cache.flush_range = l2x0_flush_range;
--		outer_cache.sync = l2x0_cache_sync;
--		outer_cache.flush_all = l2x0_flush_all;
--		outer_cache.inv_all = l2x0_inv_all;
--		outer_cache.disable = l2x0_disable;
--	}
--
--	pr_info("%s cache controller enabled\n", type);
--	pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
--		ways, cache_id, aux, l2x0_size >> 10);
-+	of_property_read_u32_array(np, "arm,filter-ranges",
-+				   filter, ARRAY_SIZE(filter));
-+	if (filter[1]) {
-+		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
-+			       l2x0_base + L310_ADDR_FILTER_END);
-+		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN,
-+			       l2x0_base + L310_ADDR_FILTER_START);
-+	}
- }
- 
--#ifdef CONFIG_OF
--static int l2_wt_override;
-+static const struct l2c_init_data of_l2c310_data __initconst = {
-+	.type = "L2C-310",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 8,
-+	.of_parse = l2c310_of_parse,
-+	.enable = l2c310_enable,
-+	.fixup = l2c310_fixup,
-+	.save  = l2c310_save,
-+	.outer_cache = {
-+		.inv_range   = l2c210_inv_range,
-+		.clean_range = l2c210_clean_range,
-+		.flush_range = l2c210_flush_range,
-+		.flush_all   = l2c210_flush_all,
-+		.disable     = l2c310_disable,
-+		.sync        = l2c210_sync,
-+		.resume      = l2c310_resume,
-+	},
-+};
- 
- /*
-  * Note that the end addresses passed to Linux primitives are
-@@ -524,6 +1166,100 @@
- 	}
- }
- 
-+static void aurora_save(void __iomem *base)
-+{
-+	l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL);
-+	l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL);
-+}
-+
-+static void aurora_resume(void)
-+{
-+	void __iomem *base = l2x0_base;
-+
-+	if (!(readl(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
-+		writel_relaxed(l2x0_saved_regs.aux_ctrl, base + L2X0_AUX_CTRL);
-+		writel_relaxed(l2x0_saved_regs.ctrl, base + L2X0_CTRL);
-+	}
-+}
-+
-+/*
-+ * For Aurora cache in no outer mode, enable via the CP15 coprocessor
-+ * broadcasting of cache commands to L2.
-+ */
-+static void __init aurora_enable_no_outer(void __iomem *base, u32 aux,
-+	unsigned num_lock)
-+{
-+	u32 u;
-+
-+	asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u));
-+	u |= AURORA_CTRL_FW;		/* Set the FW bit */
-+	asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u));
-+
-+	isb();
-+
-+	l2c_enable(base, aux, num_lock);
-+}
-+
-+static void __init aurora_fixup(void __iomem *base, u32 cache_id,
-+	struct outer_cache_fns *fns)
-+{
-+	sync_reg_offset = AURORA_SYNC_REG;
-+}
-+
-+static void __init aurora_of_parse(const struct device_node *np,
-+				u32 *aux_val, u32 *aux_mask)
-+{
-+	u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
-+	u32 mask =  AURORA_ACR_REPLACEMENT_MASK;
-+
-+	of_property_read_u32(np, "cache-id-part",
-+			&cache_id_part_number_from_dt);
-+
-+	/* Determine and save the write policy */
-+	l2_wt_override = of_property_read_bool(np, "wt-override");
-+
-+	if (l2_wt_override) {
-+		val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
-+		mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
-+	}
-+
-+	*aux_val &= ~mask;
-+	*aux_val |= val;
-+	*aux_mask &= ~mask;
-+}
-+
-+static const struct l2c_init_data of_aurora_with_outer_data __initconst = {
-+	.type = "Aurora",
-+	.way_size_0 = SZ_4K,
-+	.num_lock = 4,
-+	.of_parse = aurora_of_parse,
-+	.enable = l2c_enable,
-+	.fixup = aurora_fixup,
-+	.save  = aurora_save,
-+	.outer_cache = {
-+		.inv_range   = aurora_inv_range,
-+		.clean_range = aurora_clean_range,
-+		.flush_range = aurora_flush_range,
-+		.flush_all   = l2x0_flush_all,
-+		.disable     = l2x0_disable,
-+		.sync        = l2x0_cache_sync,
-+		.resume      = aurora_resume,
-+	},
-+};
-+
-+static const struct l2c_init_data of_aurora_no_outer_data __initconst = {
-+	.type = "Aurora",
-+	.way_size_0 = SZ_4K,
-+	.num_lock = 4,
-+	.of_parse = aurora_of_parse,
-+	.enable = aurora_enable_no_outer,
-+	.fixup = aurora_fixup,
-+	.save  = aurora_save,
-+	.outer_cache = {
-+		.resume      = aurora_resume,
-+	},
-+};
-+
- /*
-  * For certain Broadcom SoCs, depending on the address range, different offsets
-  * need to be added to the address before passing it to L2 for
-@@ -588,16 +1324,16 @@
- 
- 	/* normal case, no cross section between start and end */
- 	if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
--		l2x0_inv_range(new_start, new_end);
-+		l2c210_inv_range(new_start, new_end);
- 		return;
- 	}
- 
- 	/* They cross sections, so it can only be a cross from section
- 	 * 2 to section 3
- 	 */
--	l2x0_inv_range(new_start,
-+	l2c210_inv_range(new_start,
- 		bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
--	l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
-+	l2c210_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- 		new_end);
- }
- 
-@@ -610,26 +1346,21 @@
- 	if (unlikely(end <= start))
- 		return;
- 
--	if ((end - start) >= l2x0_size) {
--		l2x0_clean_all();
--		return;
--	}
--
- 	new_start = bcm_l2_phys_addr(start);
- 	new_end = bcm_l2_phys_addr(end);
- 
- 	/* normal case, no cross section between start and end */
- 	if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
--		l2x0_clean_range(new_start, new_end);
-+		l2c210_clean_range(new_start, new_end);
- 		return;
- 	}
- 
- 	/* They cross sections, so it can only be a cross from section
- 	 * 2 to section 3
- 	 */
--	l2x0_clean_range(new_start,
-+	l2c210_clean_range(new_start,
- 		bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
--	l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
-+	l2c210_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- 		new_end);
- }
- 
-@@ -643,7 +1374,7 @@
- 		return;
- 
- 	if ((end - start) >= l2x0_size) {
--		l2x0_flush_all();
-+		outer_cache.flush_all();
- 		return;
- 	}
- 
-@@ -652,283 +1383,67 @@
- 
- 	/* normal case, no cross section between start and end */
- 	if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
--		l2x0_flush_range(new_start, new_end);
-+		l2c210_flush_range(new_start, new_end);
- 		return;
- 	}
- 
- 	/* They cross sections, so it can only be a cross from section
- 	 * 2 to section 3
- 	 */
--	l2x0_flush_range(new_start,
-+	l2c210_flush_range(new_start,
- 		bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
--	l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
-+	l2c210_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
- 		new_end);
- }
- 
--static void __init l2x0_of_setup(const struct device_node *np,
--				 u32 *aux_val, u32 *aux_mask)
--{
--	u32 data[2] = { 0, 0 };
--	u32 tag = 0;
--	u32 dirty = 0;
--	u32 val = 0, mask = 0;
--
--	of_property_read_u32(np, "arm,tag-latency", &tag);
--	if (tag) {
--		mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
--		val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
--	}
--
--	of_property_read_u32_array(np, "arm,data-latency",
--				   data, ARRAY_SIZE(data));
--	if (data[0] && data[1]) {
--		mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
--			L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
--		val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
--		       ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
--	}
--
--	of_property_read_u32(np, "arm,dirty-latency", &dirty);
--	if (dirty) {
--		mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
--		val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
--	}
--
--	*aux_val &= ~mask;
--	*aux_val |= val;
--	*aux_mask &= ~mask;
--}
--
--static void __init pl310_of_setup(const struct device_node *np,
--				  u32 *aux_val, u32 *aux_mask)
--{
--	u32 data[3] = { 0, 0, 0 };
--	u32 tag[3] = { 0, 0, 0 };
--	u32 filter[2] = { 0, 0 };
--
--	of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
--	if (tag[0] && tag[1] && tag[2])
--		writel_relaxed(
--			((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
--			((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
--			((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
--			l2x0_base + L2X0_TAG_LATENCY_CTRL);
--
--	of_property_read_u32_array(np, "arm,data-latency",
--				   data, ARRAY_SIZE(data));
--	if (data[0] && data[1] && data[2])
--		writel_relaxed(
--			((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
--			((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
--			((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
--			l2x0_base + L2X0_DATA_LATENCY_CTRL);
--
--	of_property_read_u32_array(np, "arm,filter-ranges",
--				   filter, ARRAY_SIZE(filter));
--	if (filter[1]) {
--		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
--			       l2x0_base + L2X0_ADDR_FILTER_END);
--		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
--			       l2x0_base + L2X0_ADDR_FILTER_START);
--	}
--}
--
--static void __init pl310_save(void)
--{
--	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
--		L2X0_CACHE_ID_RTL_MASK;
--
--	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
--		L2X0_TAG_LATENCY_CTRL);
--	l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
--		L2X0_DATA_LATENCY_CTRL);
--	l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
--		L2X0_ADDR_FILTER_END);
--	l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
--		L2X0_ADDR_FILTER_START);
--
--	if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
--		/*
--		 * From r2p0, there is Prefetch offset/control register
--		 */
--		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
--			L2X0_PREFETCH_CTRL);
--		/*
--		 * From r3p0, there is Power control register
--		 */
--		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
--			l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
--				L2X0_POWER_CTRL);
--	}
--}
-+/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */
-+static const struct l2c_init_data of_bcm_l2x0_data __initconst = {
-+	.type = "BCM-L2C-310",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 8,
-+	.of_parse = l2c310_of_parse,
-+	.enable = l2c310_enable,
-+	.save  = l2c310_save,
-+	.outer_cache = {
-+		.inv_range   = bcm_inv_range,
-+		.clean_range = bcm_clean_range,
-+		.flush_range = bcm_flush_range,
-+		.flush_all   = l2c210_flush_all,
-+		.disable     = l2c310_disable,
-+		.sync        = l2c210_sync,
-+		.resume      = l2c310_resume,
-+	},
-+};
- 
--static void aurora_save(void)
-+static void __init tauros3_save(void __iomem *base)
- {
--	l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
--	l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
--}
-+	l2c_save(base);
- 
--static void __init tauros3_save(void)
--{
- 	l2x0_saved_regs.aux2_ctrl =
--		readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL);
-+		readl_relaxed(base + TAUROS3_AUX2_CTRL);
- 	l2x0_saved_regs.prefetch_ctrl =
--		readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
--}
--
--static void l2x0_resume(void)
--{
--	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
--		/* restore aux ctrl and enable l2 */
--		l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
--
--		writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
--			L2X0_AUX_CTRL);
--
--		l2x0_inv_all();
--
--		writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
--	}
--}
--
--static void pl310_resume(void)
--{
--	u32 l2x0_revision;
--
--	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
--		/* restore pl310 setup */
--		writel_relaxed(l2x0_saved_regs.tag_latency,
--			l2x0_base + L2X0_TAG_LATENCY_CTRL);
--		writel_relaxed(l2x0_saved_regs.data_latency,
--			l2x0_base + L2X0_DATA_LATENCY_CTRL);
--		writel_relaxed(l2x0_saved_regs.filter_end,
--			l2x0_base + L2X0_ADDR_FILTER_END);
--		writel_relaxed(l2x0_saved_regs.filter_start,
--			l2x0_base + L2X0_ADDR_FILTER_START);
--
--		l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
--			L2X0_CACHE_ID_RTL_MASK;
--
--		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
--			writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
--				l2x0_base + L2X0_PREFETCH_CTRL);
--			if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
--				writel_relaxed(l2x0_saved_regs.pwr_ctrl,
--					l2x0_base + L2X0_POWER_CTRL);
--		}
--	}
--
--	l2x0_resume();
--}
--
--static void aurora_resume(void)
--{
--	if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
--		writel_relaxed(l2x0_saved_regs.aux_ctrl,
--				l2x0_base + L2X0_AUX_CTRL);
--		writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
--	}
-+		readl_relaxed(base + L310_PREFETCH_CTRL);
- }
- 
- static void tauros3_resume(void)
- {
--	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
-+	void __iomem *base = l2x0_base;
-+
-+	if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- 		writel_relaxed(l2x0_saved_regs.aux2_ctrl,
--			       l2x0_base + TAUROS3_AUX2_CTRL);
-+			       base + TAUROS3_AUX2_CTRL);
- 		writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
--			       l2x0_base + L2X0_PREFETCH_CTRL);
--	}
--
--	l2x0_resume();
--}
--
--static void __init aurora_broadcast_l2_commands(void)
--{
--	__u32 u;
--	/* Enable Broadcasting of cache commands to L2*/
--	__asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
--	u |= AURORA_CTRL_FW;		/* Set the FW bit */
--	__asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
--	isb();
--}
--
--static void __init aurora_of_setup(const struct device_node *np,
--				u32 *aux_val, u32 *aux_mask)
--{
--	u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
--	u32 mask =  AURORA_ACR_REPLACEMENT_MASK;
-+			       base + L310_PREFETCH_CTRL);
- 
--	of_property_read_u32(np, "cache-id-part",
--			&cache_id_part_number_from_dt);
--
--	/* Determine and save the write policy */
--	l2_wt_override = of_property_read_bool(np, "wt-override");
--
--	if (l2_wt_override) {
--		val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
--		mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
-+		l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8);
- 	}
--
--	*aux_val &= ~mask;
--	*aux_val |= val;
--	*aux_mask &= ~mask;
- }
- 
--static const struct l2x0_of_data pl310_data = {
--	.setup = pl310_of_setup,
--	.save  = pl310_save,
--	.outer_cache = {
--		.resume      = pl310_resume,
--		.inv_range   = l2x0_inv_range,
--		.clean_range = l2x0_clean_range,
--		.flush_range = l2x0_flush_range,
--		.sync        = l2x0_cache_sync,
--		.flush_all   = l2x0_flush_all,
--		.inv_all     = l2x0_inv_all,
--		.disable     = l2x0_disable,
--	},
--};
--
--static const struct l2x0_of_data l2x0_data = {
--	.setup = l2x0_of_setup,
--	.save  = NULL,
--	.outer_cache = {
--		.resume      = l2x0_resume,
--		.inv_range   = l2x0_inv_range,
--		.clean_range = l2x0_clean_range,
--		.flush_range = l2x0_flush_range,
--		.sync        = l2x0_cache_sync,
--		.flush_all   = l2x0_flush_all,
--		.inv_all     = l2x0_inv_all,
--		.disable     = l2x0_disable,
--	},
--};
--
--static const struct l2x0_of_data aurora_with_outer_data = {
--	.setup = aurora_of_setup,
--	.save  = aurora_save,
--	.outer_cache = {
--		.resume      = aurora_resume,
--		.inv_range   = aurora_inv_range,
--		.clean_range = aurora_clean_range,
--		.flush_range = aurora_flush_range,
--		.sync        = l2x0_cache_sync,
--		.flush_all   = l2x0_flush_all,
--		.inv_all     = l2x0_inv_all,
--		.disable     = l2x0_disable,
--	},
--};
--
--static const struct l2x0_of_data aurora_no_outer_data = {
--	.setup = aurora_of_setup,
--	.save  = aurora_save,
--	.outer_cache = {
--		.resume      = aurora_resume,
--	},
--};
--
--static const struct l2x0_of_data tauros3_data = {
--	.setup = NULL,
-+static const struct l2c_init_data of_tauros3_data __initconst = {
-+	.type = "Tauros3",
-+	.way_size_0 = SZ_8K,
-+	.num_lock = 8,
-+	.enable = l2c_enable,
- 	.save  = tauros3_save,
- 	/* Tauros3 broadcasts L1 cache operations to L2 */
- 	.outer_cache = {
-@@ -936,43 +1451,26 @@
- 	},
- };
- 
--static const struct l2x0_of_data bcm_l2x0_data = {
--	.setup = pl310_of_setup,
--	.save  = pl310_save,
--	.outer_cache = {
--		.resume      = pl310_resume,
--		.inv_range   = bcm_inv_range,
--		.clean_range = bcm_clean_range,
--		.flush_range = bcm_flush_range,
--		.sync        = l2x0_cache_sync,
--		.flush_all   = l2x0_flush_all,
--		.inv_all     = l2x0_inv_all,
--		.disable     = l2x0_disable,
--	},
--};
--
-+#define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns }
- static const struct of_device_id l2x0_ids[] __initconst = {
--	{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
--	{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
--	{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
--	{ .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */
--	  .data = (void *)&bcm_l2x0_data},
--	{ .compatible = "brcm,bcm11351-a2-pl310-cache",
--	  .data = (void *)&bcm_l2x0_data},
--	{ .compatible = "marvell,aurora-outer-cache",
--	  .data = (void *)&aurora_with_outer_data},
--	{ .compatible = "marvell,aurora-system-cache",
--	  .data = (void *)&aurora_no_outer_data},
--	{ .compatible = "marvell,tauros3-cache",
--	  .data = (void *)&tauros3_data },
-+	L2C_ID("arm,l210-cache", of_l2c210_data),
-+	L2C_ID("arm,l220-cache", of_l2c220_data),
-+	L2C_ID("arm,pl310-cache", of_l2c310_data),
-+	L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data),
-+	L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data),
-+	L2C_ID("marvell,aurora-system-cache", of_aurora_no_outer_data),
-+	L2C_ID("marvell,tauros3-cache", of_tauros3_data),
-+	/* Deprecated IDs */
-+	L2C_ID("bcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data),
- 	{}
- };
- 
- int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
- {
-+	const struct l2c_init_data *data;
- 	struct device_node *np;
--	const struct l2x0_of_data *data;
- 	struct resource res;
-+	u32 cache_id, old_aux;
- 
- 	np = of_find_matching_node(NULL, l2x0_ids);
- 	if (!np)
-@@ -989,23 +1487,29 @@
- 
- 	data = of_match_node(l2x0_ids, np)->data;
- 
--	/* L2 configuration can only be changed if the cache is disabled */
--	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
--		if (data->setup)
--			data->setup(np, &aux_val, &aux_mask);
--
--		/* For aurora cache in no outer mode select the
--		 * correct mode using the coprocessor*/
--		if (data == &aurora_no_outer_data)
--			aurora_broadcast_l2_commands();
-+	old_aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
-+	if (old_aux != ((old_aux & aux_mask) | aux_val)) {
-+		pr_warn("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n",
-+		        old_aux, (old_aux & aux_mask) | aux_val);
-+	} else if (aux_mask != ~0U && aux_val != 0) {
-+		pr_alert("L2C: platform provided aux values match the hardware, so have no effect.  Please remove them.\n");
- 	}
- 
--	if (data->save)
--		data->save();
-+	/* All L2 caches are unified, so this property should be specified */
-+	if (!of_property_read_bool(np, "cache-unified"))
-+		pr_err("L2C: device tree omits to specify unified cache\n");
-+
-+	/* L2 configuration can only be changed if the cache is disabled */
-+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN))
-+		if (data->of_parse)
-+			data->of_parse(np, &aux_val, &aux_mask);
-+
-+	if (cache_id_part_number_from_dt)
-+		cache_id = cache_id_part_number_from_dt;
-+	else
-+		cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
- 
--	of_init = true;
--	memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
--	l2x0_init(l2x0_base, aux_val, aux_mask);
-+	__l2c_init(data, aux_val, aux_mask, cache_id);
- 
- 	return 0;
- }
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/Kconfig linux-3.15-rc6/arch/arm/mm/Kconfig
---- linux-3.15-rc6.orig/arch/arm/mm/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mm/Kconfig	2014-05-23 11:26:48.280939953 +0200
-@@ -897,6 +897,57 @@
- 	  This option enables optimisations for the PL310 cache
- 	  controller.
- 
-+config PL310_ERRATA_588369
-+	bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
-+	depends on CACHE_L2X0
-+	help
-+	   The PL310 L2 cache controller implements three types of Clean &
-+	   Invalidate maintenance operations: by Physical Address
-+	   (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
-+	   They are architecturally defined to behave as the execution of a
-+	   clean operation followed immediately by an invalidate operation,
-+	   both performing to the same memory location. This functionality
-+	   is not correctly implemented in PL310 as clean lines are not
-+	   invalidated as a result of these operations.
-+
-+config PL310_ERRATA_727915
-+	bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
-+	depends on CACHE_L2X0
-+	help
-+	  PL310 implements the Clean & Invalidate by Way L2 cache maintenance
-+	  operation (offset 0x7FC). This operation runs in background so that
-+	  PL310 can handle normal accesses while it is in progress. Under very
-+	  rare circumstances, due to this erratum, write data can be lost when
-+	  PL310 treats a cacheable write transaction during a Clean &
-+	  Invalidate by Way operation.
-+
-+config PL310_ERRATA_753970
-+	bool "PL310 errata: cache sync operation may be faulty"
-+	depends on CACHE_PL310
-+	help
-+	  This option enables the workaround for the 753970 PL310 (r3p0) erratum.
-+
-+	  Under some condition the effect of cache sync operation on
-+	  the store buffer still remains when the operation completes.
-+	  This means that the store buffer is always asked to drain and
-+	  this prevents it from merging any further writes. The workaround
-+	  is to replace the normal offset of cache sync operation (0x730)
-+	  by another offset targeting an unmapped PL310 register 0x740.
-+	  This has the same effect as the cache sync operation: store buffer
-+	  drain and waiting for all buffers empty.
-+
-+config PL310_ERRATA_769419
-+	bool "PL310 errata: no automatic Store Buffer drain"
-+	depends on CACHE_L2X0
-+	help
-+	  On revisions of the PL310 prior to r3p2, the Store Buffer does
-+	  not automatically drain. This can cause normal, non-cacheable
-+	  writes to be retained when the memory system is idle, leading
-+	  to suboptimal I/O performance for drivers using coherent DMA.
-+	  This option adds a write barrier to the cpu_idle loop so that,
-+	  on systems with an outer cache, the store buffer is drained
-+	  explicitly.
-+
- config CACHE_TAUROS2
- 	bool "Enable the Tauros2 L2 cache controller"
- 	depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4)
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/l2c-common.c linux-3.15-rc6/arch/arm/mm/l2c-common.c
---- linux-3.15-rc6.orig/arch/arm/mm/l2c-common.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/arch/arm/mm/l2c-common.c	2014-05-23 11:26:48.284939966 +0200
-@@ -0,0 +1,20 @@
-+/*
-+ * Copyright (C) 2010 ARM Ltd.
-+ * Written by Catalin Marinas <catalin.marinas@arm.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.
-+ */
-+#include <linux/bug.h>
-+#include <linux/smp.h>
-+#include <asm/outercache.h>
-+
-+void outer_disable(void)
-+{
-+	WARN_ON(!irqs_disabled());
-+	WARN_ON(num_online_cpus() > 1);
-+
-+	if (outer_cache.disable)
-+		outer_cache.disable();
-+}
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/l2c-l2x0-resume.S linux-3.15-rc6/arch/arm/mm/l2c-l2x0-resume.S
---- linux-3.15-rc6.orig/arch/arm/mm/l2c-l2x0-resume.S	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/arch/arm/mm/l2c-l2x0-resume.S	2014-05-23 11:26:48.284939966 +0200
-@@ -0,0 +1,58 @@
-+/*
-+ * L2C-310 early resume code.  This can be used by platforms to restore
-+ * the settings of their L2 cache controller before restoring the
-+ * processor state.
-+ *
-+ * This code can only be used to if you are running in the secure world.
-+ */
-+#include <linux/linkage.h>
-+#include <asm/hardware/cache-l2x0.h>
-+
-+	.text
-+
-+ENTRY(l2c310_early_resume)
-+	adr	r0, 1f
-+	ldr	r2, [r0]
-+	add	r0, r2, r0
-+
-+	ldmia	r0, {r1, r2, r3, r4, r5, r6, r7, r8}
-+	@ r1 = phys address of L2C-310 controller
-+	@ r2 = aux_ctrl
-+	@ r3 = tag_latency
-+	@ r4 = data_latency
-+	@ r5 = filter_start
-+	@ r6 = filter_end
-+	@ r7 = prefetch_ctrl
-+	@ r8 = pwr_ctrl
-+
-+	@ Check that the address has been initialised
-+	teq	r1, #0
-+	moveq	pc, lr
-+
-+	@ The prefetch and power control registers are revision dependent
-+	@ and can be written whether or not the L2 cache is enabled
-+	ldr	r0, [r1, #L2X0_CACHE_ID]
-+	and	r0, r0, #L2X0_CACHE_ID_RTL_MASK
-+	cmp	r0, #L310_CACHE_ID_RTL_R2P0
-+	strcs	r7, [r1, #L310_PREFETCH_CTRL]
-+	cmp	r0, #L310_CACHE_ID_RTL_R3P0
-+	strcs	r8, [r1, #L310_POWER_CTRL]
-+
-+	@ Don't setup the L2 cache if it is already enabled
-+	ldr	r0, [r1, #L2X0_CTRL]
-+	tst	r0, #L2X0_CTRL_EN
-+	movne	pc, lr
-+
-+	str	r3, [r1, #L310_TAG_LATENCY_CTRL]
-+	str	r4, [r1, #L310_DATA_LATENCY_CTRL]
-+	str	r6, [r1, #L310_ADDR_FILTER_END]
-+	str	r5, [r1, #L310_ADDR_FILTER_START]
-+
-+	str	r2, [r1, #L2X0_AUX_CTRL]
-+	mov	r9, #L2X0_CTRL_EN
-+	str	r9, [r1, #L2X0_CTRL]
-+	mov	pc, lr
-+ENDPROC(l2c310_early_resume)
-+
-+	.align
-+1:	.long	l2x0_saved_regs - .
-diff -Nur linux-3.15-rc6.orig/arch/arm/mm/Makefile linux-3.15-rc6/arch/arm/mm/Makefile
---- linux-3.15-rc6.orig/arch/arm/mm/Makefile	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/mm/Makefile	2014-05-23 11:26:48.284939966 +0200
-@@ -95,7 +95,8 @@
- AFLAGS_proc-v6.o	:=-Wa,-march=armv6
- AFLAGS_proc-v7.o	:=-Wa,-march=armv7-a
- 
-+obj-$(CONFIG_OUTER_CACHE)	+= l2c-common.o
- obj-$(CONFIG_CACHE_FEROCEON_L2)	+= cache-feroceon-l2.o
--obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
-+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
-diff -Nur linux-3.15-rc6.orig/arch/arm/plat-samsung/s5p-sleep.S linux-3.15-rc6/arch/arm/plat-samsung/s5p-sleep.S
---- linux-3.15-rc6.orig/arch/arm/plat-samsung/s5p-sleep.S	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/arch/arm/plat-samsung/s5p-sleep.S	2014-05-23 11:26:48.284939966 +0200
-@@ -22,7 +22,6 @@
- */
- 
- #include <linux/linkage.h>
--#include <asm/asm-offsets.h>
- 
- 	.data
- 	.align
-diff -Nur linux-3.15-rc6.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt linux-3.15-rc6/Documentation/devicetree/bindings/leds/leds-pwm.txt
---- linux-3.15-rc6.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/Documentation/devicetree/bindings/leds/leds-pwm.txt	2014-05-23 11:26:48.284939966 +0200
-@@ -13,6 +13,8 @@
-   For the pwms and pwm-names property please refer to:
-   Documentation/devicetree/bindings/pwm/pwm.txt
- - max-brightness : Maximum brightness possible for the LED
-+- active-low : (optional) For PWMs where the LED is wired to supply
-+  rather than ground.
- - label :  (optional)
-   see Documentation/devicetree/bindings/leds/common.txt
- - linux,default-trigger :  (optional)
-diff -Nur linux-3.15-rc6.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.15-rc6/Documentation/devicetree/bindings/mmc/mmc.txt
---- linux-3.15-rc6.orig/Documentation/devicetree/bindings/mmc/mmc.txt	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/Documentation/devicetree/bindings/mmc/mmc.txt	2014-05-23 11:26:48.284939966 +0200
-@@ -5,6 +5,8 @@
- Interpreted by the OF core:
- - reg: Registers location and length.
- - interrupts: Interrupts used by the MMC controller.
-+- clocks: Clocks needed for the host controller, if any.
-+- clock-names: Goes with clocks above.
- 
- Card detection:
- If no property below is supplied, host native card detect is used.
-@@ -39,6 +41,15 @@
- - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
- - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
- 
-+Card power and reset control:
-+The following properties can be specified for cases where the MMC
-+peripheral needs additional reset, regulator and clock lines. It is for
-+example common for WiFi/BT adapters to have these separate from the main
-+MMC bus:
-+  - card-reset-gpios: Specify GPIOs for card reset (reset active low)
-+  - card-external-vcc-supply: Regulator to drive (independent) card VCC
-+  - clock with name "card_ext_clock": External clock provided to the card
-+
- *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
- polarity properties, we have to fix the meaning of the "normal" and "inverted"
- line levels. We choose to follow the SDHCI standard, which specifies both those
-diff -Nur linux-3.15-rc6.orig/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt linux-3.15-rc6/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
---- linux-3.15-rc6.orig/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt	2014-05-23 11:26:48.288939979 +0200
-@@ -60,7 +60,8 @@
- - compatible: Should be "fsl,imx-parallel-display"
- Optional properties:
- - interface_pix_fmt: How this display is connected to the
--  display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
-+  display interface. Currently supported types: "rgb24", "rgb565", "bgr666",
-+  "rgb666"
- - edid: verbatim EDID data block describing attached display.
- - ddc: phandle describing the i2c bus handling the display data
-   channel
-diff -Nur linux-3.15-rc6.orig/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml linux-3.15-rc6/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
---- linux-3.15-rc6.orig/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml	2014-05-23 11:26:48.288939979 +0200
-@@ -279,6 +279,45 @@
- 	    <entry></entry>
- 	    <entry></entry>
- 	  </row>
-+	  <row id="V4L2-PIX-FMT-RGB666">
-+	    <entry><constant>V4L2_PIX_FMT_RGB666</constant></entry>
-+	    <entry>'RGBH'</entry>
-+	    <entry></entry>
-+	    <entry>r<subscript>5</subscript></entry>
-+	    <entry>r<subscript>4</subscript></entry>
-+	    <entry>r<subscript>3</subscript></entry>
-+	    <entry>r<subscript>2</subscript></entry>
-+	    <entry>r<subscript>1</subscript></entry>
-+	    <entry>r<subscript>0</subscript></entry>
-+	    <entry>g<subscript>5</subscript></entry>
-+	    <entry>g<subscript>4</subscript></entry>
-+	    <entry></entry>
-+	    <entry>g<subscript>3</subscript></entry>
-+	    <entry>g<subscript>2</subscript></entry>
-+	    <entry>g<subscript>1</subscript></entry>
-+	    <entry>g<subscript>0</subscript></entry>
-+	    <entry>b<subscript>5</subscript></entry>
-+	    <entry>b<subscript>4</subscript></entry>
-+	    <entry>b<subscript>3</subscript></entry>
-+	    <entry>b<subscript>2</subscript></entry>
-+	    <entry></entry>
-+	    <entry>b<subscript>1</subscript></entry>
-+	    <entry>b<subscript>0</subscript></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	    <entry></entry>
-+	  </row>
- 	  <row id="V4L2-PIX-FMT-BGR24">
- 	    <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
- 	    <entry>'BGR3'</entry>
-diff -Nur linux-3.15-rc6.orig/drivers/ata/ahci_imx.c linux-3.15-rc6/drivers/ata/ahci_imx.c
---- linux-3.15-rc6.orig/drivers/ata/ahci_imx.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/ata/ahci_imx.c	2014-05-23 11:26:48.288939979 +0200
-@@ -62,6 +62,7 @@
- 	struct regmap *gpr;
- 	bool no_device;
- 	bool first_time;
-+	u32 phy_params;
- };
- 
- static int ahci_imx_hotplug;
-@@ -246,14 +247,7 @@
- 				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
- 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
- 				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
--				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
--				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
--				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
--				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
--				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
--				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
--				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
--				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
-+				   imxpriv->phy_params);
- 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
- 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
- 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-@@ -324,6 +318,10 @@
- 	writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
- 	imx_sata_disable(hpriv);
- 	imxpriv->no_device = true;
-+
-+	dev_info(ap->dev, "no device found, disabling link.\n");
-+	dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX
-+		 ".hotplug=1 to enable hotplug\n");
- }
- 
- static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
-@@ -364,6 +362,165 @@
- };
- MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
- 
-+struct reg_value {
-+	u32 of_value;
-+	u32 reg_value;
-+};
-+
-+struct reg_property {
-+	const char *name;
-+	const struct reg_value *values;
-+	size_t num_values;
-+	u32 def_value;
-+	u32 set_value;
-+};
-+
-+static const struct reg_value gpr13_tx_level[] = {
-+	{  937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
-+	{  947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
-+	{  957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
-+	{  966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
-+	{  976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
-+	{  986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
-+	{  996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
-+	{ 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
-+	{ 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
-+	{ 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
-+	{ 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
-+	{ 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
-+	{ 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
-+	{ 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
-+	{ 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
-+	{ 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
-+	{ 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
-+	{ 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
-+	{ 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
-+	{ 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
-+	{ 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
-+	{ 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
-+	{ 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
-+	{ 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
-+	{ 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
-+	{ 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
-+	{ 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
-+	{ 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
-+	{ 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
-+	{ 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
-+	{ 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
-+	{ 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
-+};
-+
-+static const struct reg_value gpr13_tx_boost[] = {
-+	{    0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
-+	{  370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
-+	{  740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
-+	{  111, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
-+	{  148, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
-+	{  185, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
-+	{  222, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
-+	{  259, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
-+	{  296, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
-+	{  333, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
-+	{  370, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
-+	{  407, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
-+	{  444, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
-+	{  481, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
-+	{  528, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
-+	{  575, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
-+};
-+
-+static const struct reg_value gpr13_tx_atten[] = {
-+	{  8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
-+	{  9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
-+	{ 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
-+	{ 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
-+	{ 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
-+	{ 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
-+};
-+
-+static const struct reg_value gpr13_rx_eq[] = {
-+	{  500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
-+	{ 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
-+	{ 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
-+	{ 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
-+	{ 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
-+	{ 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
-+	{ 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
-+	{ 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
-+};
-+
-+static const struct reg_property gpr13_props[] = {
-+	{
-+		.name = "fsl,transmit-level-mV",
-+		.values = gpr13_tx_level,
-+		.num_values = ARRAY_SIZE(gpr13_tx_level),
-+		.def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
-+	}, {
-+		.name = "fsl,transmit-boost-mdB",
-+		.values = gpr13_tx_boost,
-+		.num_values = ARRAY_SIZE(gpr13_tx_boost),
-+		.def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
-+	}, {
-+		.name = "fsl,transmit-atten-16ths",
-+		.values = gpr13_tx_atten,
-+		.num_values = ARRAY_SIZE(gpr13_tx_atten),
-+		.def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
-+	}, {
-+		.name = "fsl,receive-eq-mdB",
-+		.values = gpr13_rx_eq,
-+		.num_values = ARRAY_SIZE(gpr13_rx_eq),
-+		.def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
-+	}, {
-+		.name = "fsl,no-spread-spectrum",
-+		.def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
-+		.set_value = 0,
-+	},
-+};
-+
-+static u32 imx_ahci_parse_props(struct device *dev,
-+				const struct reg_property *prop, size_t num)
-+{
-+	struct device_node *np = dev->of_node;
-+	u32 reg_value = 0;
-+	int i, j;
-+
-+	for (i = 0; i < num; i++, prop++) {
-+		u32 of_val;
-+
-+		if (prop->num_values == 0) {
-+			if (of_property_read_bool(np, prop->name))
-+				reg_value |= prop->set_value;
-+			else
-+				reg_value |= prop->def_value;
-+			continue;
-+		}
-+
-+		if (of_property_read_u32(np, prop->name, &of_val)) {
-+			dev_info(dev, "%s not specified, using %08x\n",
-+				prop->name, prop->def_value);
-+			reg_value |= prop->def_value;
-+			continue;
-+		}
-+
-+		for (j = 0; j < prop->num_values; j++) {
-+			if (prop->values[j].of_value == of_val) {
-+				dev_info(dev, "%s value %u, using %08x\n",
-+					prop->name, of_val, prop->values[j].reg_value);
-+				reg_value |= prop->values[j].reg_value;
-+				break;
-+			}
-+		}
-+
-+		if (j == prop->num_values) {
-+			dev_err(dev, "DT property %s is not a valid value\n",
-+				prop->name);
-+			reg_value |= prop->def_value;
-+		}
-+	}
-+
-+	return reg_value;
-+}
-+
- static int imx_ahci_probe(struct platform_device *pdev)
- {
- 	struct device *dev = &pdev->dev;
-@@ -392,6 +549,8 @@
- 	}
- 
- 	if (imxpriv->type == AHCI_IMX6Q) {
-+		u32 reg_value;
-+
- 		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
- 							"fsl,imx6q-iomuxc-gpr");
- 		if (IS_ERR(imxpriv->gpr)) {
-@@ -399,6 +558,15 @@
- 				"failed to find fsl,imx6q-iomux-gpr regmap\n");
- 			return PTR_ERR(imxpriv->gpr);
- 		}
-+
-+		reg_value = imx_ahci_parse_props(dev, gpr13_props,
-+						 ARRAY_SIZE(gpr13_props));
-+
-+		imxpriv->phy_params =
-+				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
-+				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
-+				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
-+				   reg_value;
- 	}
- 
- 	hpriv = ahci_platform_get_resources(pdev);
-diff -Nur linux-3.15-rc6.orig/drivers/cec/cec-dev.c linux-3.15-rc6/drivers/cec/cec-dev.c
---- linux-3.15-rc6.orig/drivers/cec/cec-dev.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/cec/cec-dev.c	2014-05-23 11:26:48.296940005 +0200
-@@ -0,0 +1,384 @@
-+/*
-+ * HDMI Consumer Electronics Control
-+ *
-+ * This provides the user API for communication with HDMI CEC complaint
-+ * devices in kernel drivers, and is based upon the protocol developed
-+ * by Freescale for their i.MX SoCs.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/cec-dev.h>
-+#include <linux/device.h>
-+#include <linux/fs.h>
-+#include <linux/module.h>
-+#include <linux/poll.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+
-+struct cec_event {
-+	struct cec_user_event usr;
-+	struct list_head node;
-+};
-+
-+static struct class *cec_class;
-+static int cec_major;
-+
-+static void cec_dev_send_message(struct cec_dev *cec_dev, u8 *msg,
-+	size_t count)
-+{
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&cec_dev->lock, flags);
-+	cec_dev->retries = 5;
-+	cec_dev->write_busy = 1;
-+	cec_dev->send_message(cec_dev, msg, count);
-+	spin_unlock_irqrestore(&cec_dev->lock, flags);
-+}
-+
-+void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len)
-+{
-+	struct cec_event *event;
-+	unsigned long flags;
-+
-+	event = kzalloc(sizeof(*event), GFP_ATOMIC);
-+	if (event) {
-+		event->usr.event_type = type;
-+		event->usr.msg_len = len;
-+		if (msg)
-+			memcpy(event->usr.msg, msg, len);
-+
-+		spin_lock_irqsave(&cec_dev->lock, flags);
-+		list_add_tail(&event->node, &cec_dev->events);
-+		spin_unlock_irqrestore(&cec_dev->lock, flags);
-+		wake_up(&cec_dev->waitq);
-+	}
-+}
-+EXPORT_SYMBOL_GPL(cec_dev_event);
-+
-+static int cec_dev_lock_write(struct cec_dev *cec_dev, struct file *file)
-+	__acquires(cec_dev->mutex)
-+{
-+	int ret;
-+
-+	do {
-+		if (file->f_flags & O_NONBLOCK) {
-+			if (cec_dev->write_busy)
-+				return -EAGAIN;
-+		} else {
-+			ret = wait_event_interruptible(cec_dev->waitq,
-+						       !cec_dev->write_busy);
-+			if (ret)
-+				break;
-+		}
-+
-+		ret = mutex_lock_interruptible(&cec_dev->mutex);
-+		if (ret)
-+			break;
-+
-+		if (!cec_dev->write_busy)
-+			break;
-+
-+		mutex_unlock(&cec_dev->mutex);
-+	} while (1);
-+
-+	return ret;
-+}
-+
-+static ssize_t cec_dev_read(struct file *file, char __user *buf,
-+	size_t count, loff_t *ppos)
-+{
-+	struct cec_dev *cec_dev = file->private_data;
-+	ssize_t ret;
-+
-+	if (count > sizeof(struct cec_user_event))
-+		count = sizeof(struct cec_user_event);
-+
-+	if (!access_ok(VERIFY_WRITE, buf, count))
-+		return -EFAULT;
-+
-+	do {
-+		struct cec_event *event = NULL;
-+		unsigned long flags;
-+
-+		spin_lock_irqsave(&cec_dev->lock, flags);
-+		if (!list_empty(&cec_dev->events)) {
-+			event = list_first_entry(&cec_dev->events,
-+					struct cec_event, node);
-+			list_del(&event->node);
-+		}
-+		spin_unlock_irqrestore(&cec_dev->lock, flags);
-+
-+		if (event) {
-+			ret = __copy_to_user(buf, &event->usr, count) ?
-+				 -EFAULT : count;
-+			kfree(event);
-+			break;
-+		}
-+
-+		if (file->f_flags & O_NONBLOCK) {
-+			ret = -EAGAIN;
-+			break;
-+		}
-+
-+		ret = wait_event_interruptible(cec_dev->waitq,
-+					       !list_empty(&cec_dev->events));
-+		if (ret)
-+			break;
-+	} while (1);
-+
-+	return ret;
-+}
-+
-+static ssize_t cec_dev_write(struct file *file, const char __user *buf,
-+	size_t count, loff_t *ppos)
-+{
-+	struct cec_dev *cec_dev = file->private_data;
-+	u8 msg[MAX_MESSAGE_LEN];
-+	int ret;
-+
-+	if (count > sizeof(msg))
-+		return -E2BIG;
-+
-+	if (copy_from_user(msg, buf, count))
-+		return -EFAULT;
-+
-+	ret = cec_dev_lock_write(cec_dev, file);
-+	if (ret)
-+		return ret;
-+
-+	cec_dev_send_message(cec_dev, msg, count);
-+
-+	mutex_unlock(&cec_dev->mutex);
-+
-+	return count;
-+}
-+
-+static long cec_dev_ioctl(struct file *file, u_int cmd, unsigned long arg)
-+{
-+	struct cec_dev *cec_dev = file->private_data;
-+	int ret;
-+
-+	switch (cmd) {
-+	case HDMICEC_IOC_O_SETLOGICALADDRESS:
-+	case HDMICEC_IOC_SETLOGICALADDRESS:
-+		if (arg > 15) {
-+			ret = -EINVAL;
-+			break;
-+		}
-+
-+		ret = cec_dev_lock_write(cec_dev, file);
-+		if (ret == 0) {
-+			unsigned char msg[1];
-+
-+			cec_dev->addresses = BIT(arg);
-+			cec_dev->set_address(cec_dev, cec_dev->addresses);
-+
-+			/*
-+			 * Send a ping message with the source and destination
-+			 * set to our address; the result indicates whether
-+			 * unit has chosen our address simultaneously.
-+			 */
-+			msg[0] = arg << 4 | arg;
-+			cec_dev_send_message(cec_dev, msg, sizeof(msg));
-+			mutex_unlock(&cec_dev->mutex);
-+		}
-+		break;
-+
-+	case HDMICEC_IOC_STARTDEVICE:
-+		ret = mutex_lock_interruptible(&cec_dev->mutex);
-+		if (ret == 0) {
-+			cec_dev->addresses = BIT(15);
-+			cec_dev->set_address(cec_dev, cec_dev->addresses);
-+			mutex_unlock(&cec_dev->mutex);
-+		}
-+		break;
-+
-+	case HDMICEC_IOC_STOPDEVICE:
-+		ret = 0;
-+		break;
-+
-+	case HDMICEC_IOC_GETPHYADDRESS:
-+		ret = put_user(cec_dev->physical, (u16 __user *)arg);
-+		ret = -ENOIOCTLCMD;
-+		break;
-+
-+	default:
-+		ret = -ENOIOCTLCMD;
-+		break;
-+	}
-+
-+	return ret;
-+}
-+
-+static unsigned cec_dev_poll(struct file *file, poll_table *wait)
-+{
-+	struct cec_dev *cec_dev = file->private_data;
-+	unsigned mask = 0;
-+
-+	poll_wait(file, &cec_dev->waitq, wait);
-+
-+	if (cec_dev->write_busy == 0)
-+		mask |= POLLOUT | POLLWRNORM;
-+	if (!list_empty(&cec_dev->events))
-+		mask |= POLLIN | POLLRDNORM;
-+
-+	return mask;
-+}
-+
-+static int cec_dev_release(struct inode *inode, struct file *file)
-+{
-+	struct cec_dev *cec_dev = file->private_data;
-+
-+	mutex_lock(&cec_dev->mutex);
-+	if (cec_dev->users >= 1)
-+		cec_dev->users -= 1;
-+	if (cec_dev->users == 0) {
-+		/*
-+		 * Wait for any write to complete before shutting down.
-+		 * A message should complete in a maximum of 2.75ms *
-+		 * 160 bits + 4.7ms, or 444.7ms.  Let's call that 500ms.
-+		 * If we time out, shutdown anyway.
-+		 */
-+		wait_event_timeout(cec_dev->waitq, !cec_dev->write_busy,
-+				   msecs_to_jiffies(500));
-+
-+		cec_dev->release(cec_dev);
-+
-+		while (!list_empty(&cec_dev->events)) {
-+			struct cec_event *event;
-+
-+			event = list_first_entry(&cec_dev->events,
-+					struct cec_event, node);
-+			list_del(&event->node);
-+			kfree(event);
-+		}
-+	}
-+	mutex_unlock(&cec_dev->mutex);
-+	return 0;
-+}
-+
-+static int cec_dev_open(struct inode *inode, struct file *file)
-+{
-+	struct cec_dev *cec_dev = container_of(inode->i_cdev, struct cec_dev,
-+					       cdev);
-+	int ret = 0;
-+
-+	nonseekable_open(inode, file);
-+
-+	file->private_data = cec_dev;
-+
-+	ret = mutex_lock_interruptible(&cec_dev->mutex);
-+	if (ret)
-+		return ret;
-+
-+	if (cec_dev->users++ == 0) {
-+		cec_dev->addresses = BIT(15);
-+
-+		ret = cec_dev->open(cec_dev);
-+		if (ret < 0)
-+			cec_dev->users = 0;
-+	}
-+	mutex_unlock(&cec_dev->mutex);
-+
-+	return ret;
-+}
-+
-+static const struct file_operations hdmi_cec_fops = {
-+	.owner = THIS_MODULE,
-+	.read = cec_dev_read,
-+	.write = cec_dev_write,
-+	.open = cec_dev_open,
-+	.unlocked_ioctl = cec_dev_ioctl,
-+	.release = cec_dev_release,
-+	.poll = cec_dev_poll,
-+};
-+
-+void cec_dev_init(struct cec_dev *cec_dev, struct module *module)
-+{
-+	cec_dev->devn = MKDEV(cec_major, 0);
-+
-+	INIT_LIST_HEAD(&cec_dev->events);
-+	init_waitqueue_head(&cec_dev->waitq);
-+	spin_lock_init(&cec_dev->lock);
-+	mutex_init(&cec_dev->mutex);
-+
-+	cec_dev->addresses = BIT(15);
-+
-+	cdev_init(&cec_dev->cdev, &hdmi_cec_fops);
-+	cec_dev->cdev.owner = module;
-+}
-+EXPORT_SYMBOL_GPL(cec_dev_init);
-+
-+int cec_dev_add(struct cec_dev *cec_dev, struct device *dev, const char *name)
-+{
-+	struct device *cd;
-+	int ret;
-+
-+	ret = cdev_add(&cec_dev->cdev, cec_dev->devn, 1);
-+	if (ret < 0)
-+		goto err_cdev;
-+
-+	cd = device_create(cec_class, dev, cec_dev->devn, NULL, name);
-+	if (IS_ERR(cd)) {
-+		ret = PTR_ERR(cd);
-+		dev_err(dev, "can't create device: %d\n", ret);
-+		goto err_dev;
-+	}
-+
-+	return 0;
-+
-+ err_dev:
-+	cdev_del(&cec_dev->cdev);
-+ err_cdev:
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(cec_dev_add);
-+
-+void cec_dev_remove(struct cec_dev *cec_dev)
-+{
-+	device_destroy(cec_class, cec_dev->devn);
-+	cdev_del(&cec_dev->cdev);
-+}
-+EXPORT_SYMBOL_GPL(cec_dev_remove);
-+
-+static int cec_init(void)
-+{
-+	dev_t dev;
-+	int ret;
-+
-+	cec_class = class_create(THIS_MODULE, "hdmi-cec");
-+	if (IS_ERR(cec_class)) {
-+		ret = PTR_ERR(cec_class);
-+		pr_err("cec: can't create cec class: %d\n", ret);
-+		goto err_class;
-+	}
-+
-+	ret = alloc_chrdev_region(&dev, 0, 1, "hdmi-cec");
-+	if (ret) {
-+		pr_err("cec: can't create character devices: %d\n", ret);
-+		goto err_chrdev;
-+	}
-+
-+	cec_major = MAJOR(dev);
-+
-+	return 0;
-+
-+ err_chrdev:
-+	class_destroy(cec_class);
-+ err_class:
-+	return ret;
-+}
-+subsys_initcall(cec_init);
-+
-+static void cec_exit(void)
-+{
-+	unregister_chrdev_region(MKDEV(cec_major, 0), 1);
-+	class_destroy(cec_class);
-+}
-+module_exit(cec_exit);
-+
-+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Generic HDMI CEC driver");
-+MODULE_LICENSE("GPL");
-diff -Nur linux-3.15-rc6.orig/drivers/cec/Kconfig linux-3.15-rc6/drivers/cec/Kconfig
---- linux-3.15-rc6.orig/drivers/cec/Kconfig	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/cec/Kconfig	2014-05-23 11:26:48.296940005 +0200
-@@ -0,0 +1,14 @@
-+#
-+# Consumer Electroncs Control support
-+#
-+
-+menu "Consumer Electronics Control devices"
-+
-+config CEC
-+	bool
-+
-+config HDMI_CEC_CORE
-+	tristate
-+	select CEC
-+
-+endmenu
-diff -Nur linux-3.15-rc6.orig/drivers/cec/Makefile linux-3.15-rc6/drivers/cec/Makefile
---- linux-3.15-rc6.orig/drivers/cec/Makefile	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/cec/Makefile	2014-05-23 11:26:48.296940005 +0200
-@@ -0,0 +1 @@
-+obj-$(CONFIG_HDMI_CEC_CORE) += cec-dev.o
-diff -Nur linux-3.15-rc6.orig/drivers/gpu/drm/drm_crtc_helper.c linux-3.15-rc6/drivers/gpu/drm/drm_crtc_helper.c
---- linux-3.15-rc6.orig/drivers/gpu/drm/drm_crtc_helper.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/gpu/drm/drm_crtc_helper.c	2014-05-23 11:26:48.296940005 +0200
-@@ -140,16 +140,10 @@
- static void __drm_helper_disable_unused_functions(struct drm_device *dev)
- {
- 	struct drm_encoder *encoder;
--	struct drm_connector *connector;
- 	struct drm_crtc *crtc;
- 
- 	drm_warn_on_modeset_not_all_locked(dev);
- 
--	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
--		if (!connector->encoder)
--			continue;
--	}
--
- 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
- 		if (!drm_helper_encoder_in_use(encoder)) {
- 			drm_encoder_disable(encoder);
-diff -Nur linux-3.15-rc6.orig/drivers/Kconfig linux-3.15-rc6/drivers/Kconfig
---- linux-3.15-rc6.orig/drivers/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/Kconfig	2014-05-23 11:26:48.296940005 +0200
-@@ -174,4 +174,6 @@
- 
- source "drivers/mcb/Kconfig"
- 
-+source "drivers/cec/Kconfig"
-+
- endmenu
-diff -Nur linux-3.15-rc6.orig/drivers/leds/leds-pwm.c linux-3.15-rc6/drivers/leds/leds-pwm.c
---- linux-3.15-rc6.orig/drivers/leds/leds-pwm.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/leds/leds-pwm.c	2014-05-23 11:26:48.296940005 +0200
-@@ -69,6 +69,10 @@
- 
- 	duty *= brightness;
- 	do_div(duty, max);
-+
-+	if (led_dat->active_low)
-+		duty = led_dat->period - duty;
-+
- 	led_dat->duty = duty;
- 
- 	if (led_dat->can_sleep)
-@@ -92,55 +96,75 @@
- 	}
- }
- 
--static int led_pwm_create_of(struct platform_device *pdev,
--			     struct led_pwm_priv *priv)
-+static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
-+		       struct led_pwm *led, struct device_node *child)
- {
--	struct device_node *child;
-+	struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
- 	int ret;
- 
--	for_each_child_of_node(pdev->dev.of_node, child) {
--		struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
-+	led_data->active_low = led->active_low;
-+	led_data->period = led->pwm_period_ns;
-+	led_data->cdev.name = led->name;
-+	led_data->cdev.default_trigger = led->default_trigger;
-+	led_data->cdev.brightness_set = led_pwm_set;
-+	led_data->cdev.brightness = LED_OFF;
-+	led_data->cdev.max_brightness = led->max_brightness;
-+	led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
-+
-+	if (child)
-+		led_data->pwm = devm_of_pwm_get(dev, child, NULL);
-+	else
-+		led_data->pwm = devm_pwm_get(dev, led->name);
-+	if (IS_ERR(led_data->pwm)) {
-+		ret = PTR_ERR(led_data->pwm);
-+		dev_err(dev, "unable to request PWM for %s: %d\n",
-+			led->name, ret);
-+		return ret;
-+	}
- 
--		led_dat->cdev.name = of_get_property(child, "label",
--						     NULL) ? : child->name;
-+	if (child)
-+		led_data->period = pwm_get_period(led_data->pwm);
- 
--		led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
--		if (IS_ERR(led_dat->pwm)) {
--			dev_err(&pdev->dev, "unable to request PWM for %s\n",
--				led_dat->cdev.name);
--			ret = PTR_ERR(led_dat->pwm);
--			goto err;
--		}
--		/* Get the period from PWM core when n*/
--		led_dat->period = pwm_get_period(led_dat->pwm);
-+	led_data->can_sleep = pwm_can_sleep(led_data->pwm);
-+	if (led_data->can_sleep)
-+		INIT_WORK(&led_data->work, led_pwm_work);
- 
--		led_dat->cdev.default_trigger = of_get_property(child,
-+	ret = led_classdev_register(dev, &led_data->cdev);
-+	if (ret == 0) {
-+		priv->num_leds++;
-+	} else {
-+		dev_err(dev, "failed to register PWM led for %s: %d\n",
-+			led->name, ret);
-+	}
-+
-+	return ret;
-+}
-+
-+static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
-+{
-+	struct device_node *child;
-+	struct led_pwm led;
-+	int ret = 0;
-+
-+	memset(&led, 0, sizeof(led));
-+
-+	for_each_child_of_node(dev->of_node, child) {
-+		led.name = of_get_property(child, "label", NULL) ? :
-+			   child->name;
-+
-+		led.default_trigger = of_get_property(child,
- 						"linux,default-trigger", NULL);
-+		led.active_low = of_property_read_bool(child, "active-low");
- 		of_property_read_u32(child, "max-brightness",
--				     &led_dat->cdev.max_brightness);
-+				     &led.max_brightness);
- 
--		led_dat->cdev.brightness_set = led_pwm_set;
--		led_dat->cdev.brightness = LED_OFF;
--		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
--
--		led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
--		if (led_dat->can_sleep)
--			INIT_WORK(&led_dat->work, led_pwm_work);
--
--		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
--		if (ret < 0) {
--			dev_err(&pdev->dev, "failed to register for %s\n",
--				led_dat->cdev.name);
-+		ret = led_pwm_add(dev, priv, &led, child);
-+		if (ret) {
- 			of_node_put(child);
--			goto err;
-+			break;
- 		}
--		priv->num_leds++;
- 	}
- 
--	return 0;
--err:
--	led_pwm_cleanup(priv);
--
- 	return ret;
- }
- 
-@@ -166,51 +190,23 @@
- 
- 	if (pdata) {
- 		for (i = 0; i < count; i++) {
--			struct led_pwm *cur_led = &pdata->leds[i];
--			struct led_pwm_data *led_dat = &priv->leds[i];
--
--			led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
--			if (IS_ERR(led_dat->pwm)) {
--				ret = PTR_ERR(led_dat->pwm);
--				dev_err(&pdev->dev,
--					"unable to request PWM for %s\n",
--					cur_led->name);
--				goto err;
--			}
--
--			led_dat->cdev.name = cur_led->name;
--			led_dat->cdev.default_trigger = cur_led->default_trigger;
--			led_dat->active_low = cur_led->active_low;
--			led_dat->period = cur_led->pwm_period_ns;
--			led_dat->cdev.brightness_set = led_pwm_set;
--			led_dat->cdev.brightness = LED_OFF;
--			led_dat->cdev.max_brightness = cur_led->max_brightness;
--			led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
--
--			led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
--			if (led_dat->can_sleep)
--				INIT_WORK(&led_dat->work, led_pwm_work);
--
--			ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
--			if (ret < 0)
--				goto err;
-+			ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i],
-+					  NULL);
-+			if (ret)
-+				break;
- 		}
--		priv->num_leds = count;
- 	} else {
--		ret = led_pwm_create_of(pdev, priv);
--		if (ret)
--			return ret;
-+		ret = led_pwm_create_of(&pdev->dev, priv);
-+	}
-+
-+	if (ret) {
-+		led_pwm_cleanup(priv);
-+		return ret;
- 	}
- 
- 	platform_set_drvdata(pdev, priv);
- 
- 	return 0;
--
--err:
--	priv->num_leds = i;
--	led_pwm_cleanup(priv);
--
--	return ret;
- }
- 
- static int led_pwm_remove(struct platform_device *pdev)
-diff -Nur linux-3.15-rc6.orig/drivers/Makefile linux-3.15-rc6/drivers/Makefile
---- linux-3.15-rc6.orig/drivers/Makefile	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/Makefile	2014-05-23 11:26:48.296940005 +0200
-@@ -157,3 +157,4 @@
- obj-$(CONFIG_FMC)		+= fmc/
- obj-$(CONFIG_POWERCAP)		+= powercap/
- obj-$(CONFIG_MCB)		+= mcb/
-+obj-$(CONFIG_CEC)		+= cec/
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/core/core.c linux-3.15-rc6/drivers/mmc/core/core.c
---- linux-3.15-rc6.orig/drivers/mmc/core/core.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/core/core.c	2014-05-23 11:26:48.300940018 +0200
-@@ -13,11 +13,13 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
-+#include <linux/clk.h>
- #include <linux/completion.h>
- #include <linux/device.h>
- #include <linux/delay.h>
- #include <linux/pagemap.h>
- #include <linux/err.h>
-+#include <linux/gpio.h>
- #include <linux/leds.h>
- #include <linux/scatterlist.h>
- #include <linux/log2.h>
-@@ -1504,6 +1506,43 @@
- 	mmc_host_clk_release(host);
- }
- 
-+static void mmc_card_power_up(struct mmc_host *host)
-+{
-+	int i;
-+	struct gpio_desc **gds = host->card_reset_gpios;
-+
-+	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+		if (gds[i]) {
-+			dev_dbg(host->parent, "Asserting reset line %d", i);
-+			gpiod_set_value(gds[i], 1);
-+		}
-+	}
-+
-+	if (host->card_regulator) {
-+		dev_dbg(host->parent, "Enabling external regulator");
-+		if (regulator_enable(host->card_regulator))
-+			dev_err(host->parent, "Failed to enable external regulator");
-+	}
-+
-+	if (host->card_clk) {
-+		dev_dbg(host->parent, "Enabling external clock");
-+		clk_prepare_enable(host->card_clk);
-+	}
-+
-+	/* 2ms delay to let clocks and power settle */
-+	mmc_delay(20);
-+
-+	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+		if (gds[i]) {
-+			dev_dbg(host->parent, "Deasserting reset line %d", i);
-+			gpiod_set_value(gds[i], 0);
-+		}
-+	}
-+
-+	/* 2ms delay to after reset release */
-+	mmc_delay(20);
-+}
-+
- /*
-  * Apply power to the MMC stack.  This is a two-stage process.
-  * First, we enable power to the card without the clock running.
-@@ -1520,6 +1559,9 @@
- 	if (host->ios.power_mode == MMC_POWER_ON)
- 		return;
- 
-+	/* Power up the card/module first, if needed */
-+	mmc_card_power_up(host);
-+
- 	mmc_host_clk_hold(host);
- 
- 	host->ios.vdd = fls(ocr) - 1;
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/core/host.c linux-3.15-rc6/drivers/mmc/core/host.c
---- linux-3.15-rc6.orig/drivers/mmc/core/host.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/core/host.c	2014-05-23 11:26:48.300940018 +0200
-@@ -12,14 +12,18 @@
-  *  MMC host class device management
-  */
- 
-+#include <linux/kernel.h>
-+#include <linux/clk.h>
- #include <linux/device.h>
- #include <linux/err.h>
-+#include <linux/gpio/consumer.h>
- #include <linux/idr.h>
- #include <linux/of.h>
- #include <linux/of_gpio.h>
- #include <linux/pagemap.h>
- #include <linux/export.h>
- #include <linux/leds.h>
-+#include <linux/regulator/consumer.h>
- #include <linux/slab.h>
- #include <linux/suspend.h>
- 
-@@ -457,6 +461,66 @@
- 
- EXPORT_SYMBOL(mmc_of_parse);
- 
-+static int mmc_of_parse_child(struct mmc_host *host)
-+{
-+	struct device_node *np;
-+	struct clk *clk;
-+	int i;
-+
-+	if (!host->parent || !host->parent->of_node)
-+		return 0;
-+
-+	np = host->parent->of_node;
-+
-+	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
-+	if (IS_ERR(host->card_regulator)) {
-+		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
-+			return PTR_ERR(host->card_regulator);
-+		host->card_regulator = NULL;
-+	}
-+
-+	/* Parse card power/reset/clock control */
-+	if (of_find_property(np, "card-reset-gpios", NULL)) {
-+		struct gpio_desc *gpd;
-+		int level = 0;
-+
-+		/*
-+		 * If the regulator is enabled, then we can hold the
-+		 * card in reset with an active high resets.  Otherwise,
-+		 * hold the resets low.
-+		 */
-+		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
-+			level = 1;
-+
-+		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
-+			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
-+			if (IS_ERR(gpd)) {
-+				if (PTR_ERR(gpd) == -EPROBE_DEFER)
-+					return PTR_ERR(gpd);
-+				break;
-+			}
-+			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
-+			host->card_reset_gpios[i] = gpd;
-+		}
-+
-+		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
-+		if (!IS_ERR(gpd)) {
-+			dev_warn(host->parent, "More reset gpios than we can handle");
-+			gpiod_put(gpd);
-+		}
-+	}
-+
-+	clk = of_clk_get_by_name(np, "card_ext_clock");
-+	if (IS_ERR(clk)) {
-+		if (PTR_ERR(clk) == -EPROBE_DEFER)
-+			return PTR_ERR(clk);
-+		clk = NULL;
-+	}
-+	host->card_clk = clk;
-+
-+	return 0;
-+}
-+
- /**
-  *	mmc_alloc_host - initialise the per-host structure.
-  *	@extra: sizeof private data structure
-@@ -536,6 +600,10 @@
- {
- 	int err;
- 
-+	err = mmc_of_parse_child(host);
-+	if (err)
-+		return err;
-+
- 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
- 		!host->ops->enable_sdio_irq);
- 
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/core/sdio_irq.c linux-3.15-rc6/drivers/mmc/core/sdio_irq.c
---- linux-3.15-rc6.orig/drivers/mmc/core/sdio_irq.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/core/sdio_irq.c	2014-05-23 11:26:48.300940018 +0200
-@@ -90,6 +90,15 @@
- 	return ret;
- }
- 
-+void sdio_run_irqs(struct mmc_host *host)
-+{
-+	mmc_claim_host(host);
-+	host->sdio_irq_pending = true;
-+	process_sdio_pending_irqs(host);
-+	mmc_release_host(host);
-+}
-+EXPORT_SYMBOL_GPL(sdio_run_irqs);
-+
- static int sdio_irq_thread(void *_host)
- {
- 	struct mmc_host *host = _host;
-@@ -189,14 +198,20 @@
- 	WARN_ON(!host->claimed);
- 
- 	if (!host->sdio_irqs++) {
--		atomic_set(&host->sdio_irq_thread_abort, 0);
--		host->sdio_irq_thread =
--			kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
--				mmc_hostname(host));
--		if (IS_ERR(host->sdio_irq_thread)) {
--			int err = PTR_ERR(host->sdio_irq_thread);
--			host->sdio_irqs--;
--			return err;
-+		if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
-+			atomic_set(&host->sdio_irq_thread_abort, 0);
-+			host->sdio_irq_thread =
-+				kthread_run(sdio_irq_thread, host,
-+					    "ksdioirqd/%s", mmc_hostname(host));
-+			if (IS_ERR(host->sdio_irq_thread)) {
-+				int err = PTR_ERR(host->sdio_irq_thread);
-+				host->sdio_irqs--;
-+				return err;
-+			}
-+		} else {
-+			mmc_host_clk_hold(host);
-+			host->ops->enable_sdio_irq(host, 1);
-+			mmc_host_clk_release(host);
- 		}
- 	}
- 
-@@ -211,8 +226,14 @@
- 	BUG_ON(host->sdio_irqs < 1);
- 
- 	if (!--host->sdio_irqs) {
--		atomic_set(&host->sdio_irq_thread_abort, 1);
--		kthread_stop(host->sdio_irq_thread);
-+		if (!(host->caps2 & MMC_CAP2_SDIO_NOTHREAD)) {
-+			atomic_set(&host->sdio_irq_thread_abort, 1);
-+			kthread_stop(host->sdio_irq_thread);
-+		} else {
-+			mmc_host_clk_hold(host);
-+			host->ops->enable_sdio_irq(host, 0);
-+			mmc_host_clk_release(host);
-+		}
- 	}
- 
- 	return 0;
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/dw_mmc.c linux-3.15-rc6/drivers/mmc/host/dw_mmc.c
---- linux-3.15-rc6.orig/drivers/mmc/host/dw_mmc.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/dw_mmc.c	2014-05-23 11:26:48.300940018 +0200
-@@ -2140,6 +2140,8 @@
- 	if (!mmc)
- 		return -ENOMEM;
- 
-+	mmc_of_parse(mmc);
-+
- 	slot = mmc_priv(mmc);
- 	slot->id = id;
- 	slot->mmc = mmc;
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/Kconfig linux-3.15-rc6/drivers/mmc/host/Kconfig
---- linux-3.15-rc6.orig/drivers/mmc/host/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/Kconfig	2014-05-23 11:26:48.300940018 +0200
-@@ -25,8 +25,7 @@
- 	  If unsure, say N.
- 
- config MMC_SDHCI
--	tristate "Secure Digital Host Controller Interface support"
--	depends on HAS_DMA
-+	tristate
- 	help
- 	  This selects the generic Secure Digital Host Controller Interface.
- 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
-@@ -59,7 +58,8 @@
- 
- config MMC_SDHCI_PCI
- 	tristate "SDHCI support on PCI bus"
--	depends on MMC_SDHCI && PCI
-+	depends on PCI && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the PCI Secure Digital Host Controller Interface.
- 	  Most controllers found today are PCI devices.
-@@ -83,7 +83,8 @@
- 
- config MMC_SDHCI_ACPI
- 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
--	depends on MMC_SDHCI && ACPI
-+	depends on ACPI && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects support for ACPI enumerated SDHCI controllers,
- 	  identified by ACPI Compatibility ID PNP0D40 or specific
-@@ -94,8 +95,8 @@
- 	  If unsure, say N.
- 
- config MMC_SDHCI_PLTFM
--	tristate "SDHCI platform and OF driver helper"
--	depends on MMC_SDHCI
-+	tristate
-+	select MMC_SDHCI
- 	help
- 	  This selects the common helper functions support for Secure Digital
- 	  Host Controller Interface based platform and OF drivers.
-@@ -106,8 +107,8 @@
- 
- config MMC_SDHCI_OF_ARASAN
- 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
--	depends on MMC_SDHCI_PLTFM
--	depends on OF
-+	depends on OF && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Arasan Secure Digital Host Controller Interface
- 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
-@@ -118,9 +119,9 @@
- 
- config MMC_SDHCI_OF_ESDHC
- 	tristate "SDHCI OF support for the Freescale eSDHC controller"
--	depends on MMC_SDHCI_PLTFM
--	depends on PPC_OF
-+	depends on PPC_OF && HAS_DMA
- 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Freescale eSDHC controller support.
- 
-@@ -130,9 +131,9 @@
- 
- config MMC_SDHCI_OF_HLWD
- 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
--	depends on MMC_SDHCI_PLTFM
--	depends on PPC_OF
-+	depends on PPC_OF && HAS_DMA
- 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  found in the "Hollywood" chipset of the Nintendo Wii video game
-@@ -144,8 +145,8 @@
- 
- config MMC_SDHCI_CNS3XXX
- 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
--	depends on ARCH_CNS3XXX
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_CNS3XXX && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
- 
-@@ -155,9 +156,9 @@
- 
- config MMC_SDHCI_ESDHC_IMX
- 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
--	depends on ARCH_MXC
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_MXC && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Freescale eSDHC/uSDHC controller support
- 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
-@@ -168,9 +169,9 @@
- 
- config MMC_SDHCI_DOVE
- 	tristate "SDHCI support on Marvell's Dove SoC"
--	depends on ARCH_DOVE
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_DOVE && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Secure Digital Host Controller Interface in
- 	  Marvell's Dove SoC.
-@@ -181,9 +182,9 @@
- 
- config MMC_SDHCI_TEGRA
- 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
--	depends on ARCH_TEGRA
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_TEGRA && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Tegra SD/MMC controller. If you have a Tegra
- 	  platform with SD or MMC devices, say Y or M here.
-@@ -192,7 +193,8 @@
- 
- config MMC_SDHCI_S3C
- 	tristate "SDHCI support on Samsung S3C SoC"
--	depends on MMC_SDHCI && PLAT_SAMSUNG
-+	depends on PLAT_SAMSUNG && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  often referrered to as the HSMMC block in some of the Samsung S3C
-@@ -204,8 +206,8 @@
- 
- config MMC_SDHCI_SIRF
- 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
--	depends on ARCH_SIRF
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_SIRF && HAS_DMA
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the SDHCI support for SiRF System-on-Chip devices.
- 
-@@ -215,8 +217,7 @@
- 
- config MMC_SDHCI_PXAV3
- 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
--	depends on CLKDEV_LOOKUP
--	select MMC_SDHCI
-+	depends on CLKDEV_LOOKUP && HAS_DMA
- 	select MMC_SDHCI_PLTFM
- 	default CPU_MMP2
- 	help
-@@ -228,8 +229,7 @@
- 
- config MMC_SDHCI_PXAV2
- 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
--	depends on CLKDEV_LOOKUP
--	select MMC_SDHCI
-+	depends on CLKDEV_LOOKUP && HAS_DMA
- 	select MMC_SDHCI_PLTFM
- 	default CPU_PXA910
- 	help
-@@ -241,7 +241,8 @@
- 
- config MMC_SDHCI_SPEAR
- 	tristate "SDHCI support on ST SPEAr platform"
--	depends on MMC_SDHCI && PLAT_SPEAR
-+	depends on PLAT_SPEAR && HAS_DMA
-+	select MMC_SDHCI
- 	help
- 	  This selects the Secure Digital Host Controller Interface (SDHCI)
- 	  often referrered to as the HSMMC block in some of the ST SPEAR range
-@@ -263,7 +264,7 @@
- 
- config MMC_SDHCI_BCM_KONA
- 	tristate "SDHCI support on Broadcom KONA platform"
--	depends on ARCH_BCM_MOBILE
-+	depends on ARCH_BCM_MOBILE && HAS_DMA
- 	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the Broadcom Kona Secure Digital Host Controller
-@@ -274,9 +275,9 @@
- 
- config MMC_SDHCI_BCM2835
- 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
--	depends on ARCH_BCM2835
--	depends on MMC_SDHCI_PLTFM
-+	depends on ARCH_BCM2835 && HAS_DMA
- 	select MMC_SDHCI_IO_ACCESSORS
-+	select MMC_SDHCI_PLTFM
- 	help
- 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
- 	  platform with SD or MMC devices, say Y or M here.
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-acpi.c linux-3.15-rc6/drivers/mmc/host/sdhci-acpi.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-acpi.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-acpi.c	2014-05-23 11:26:48.300940018 +0200
-@@ -102,11 +102,19 @@
- }
- 
- static const struct sdhci_ops sdhci_acpi_ops_dflt = {
-+	.set_clock = sdhci_set_clock,
- 	.enable_dma = sdhci_acpi_enable_dma,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_ops sdhci_acpi_ops_int = {
-+	.set_clock = sdhci_set_clock,
- 	.enable_dma = sdhci_acpi_enable_dma,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- 	.hw_reset   = sdhci_acpi_int_hw_reset,
- };
- 
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-bcm2835.c linux-3.15-rc6/drivers/mmc/host/sdhci-bcm2835.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-bcm2835.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-bcm2835.c	2014-05-23 11:26:48.300940018 +0200
-@@ -131,8 +131,12 @@
- 	.read_l = bcm2835_sdhci_readl,
- 	.read_w = bcm2835_sdhci_readw,
- 	.read_b = bcm2835_sdhci_readb,
-+	.set_clock = sdhci_set_clock,
- 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
- 	.get_min_clock = bcm2835_sdhci_get_min_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-bcm-kona.c linux-3.15-rc6/drivers/mmc/host/sdhci-bcm-kona.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-bcm-kona.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-bcm-kona.c	2014-05-23 11:26:48.300940018 +0200
-@@ -206,9 +206,13 @@
- }
- 
- static struct sdhci_ops sdhci_bcm_kona_ops = {
-+	.set_clock = sdhci_set_clock,
- 	.get_max_clock = sdhci_bcm_kona_get_max_clk,
- 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
- 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- 	.card_event = sdhci_bcm_kona_card_event,
- };
- 
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci.c linux-3.15-rc6/drivers/mmc/host/sdhci.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci.c	2014-05-23 11:26:48.304940032 +0200
-@@ -44,6 +44,8 @@
- 
- #define MAX_TUNING_LOOP 40
- 
-+#define ADMA_SIZE	((128 * 2 + 1) * 4)
-+
- static unsigned int debug_quirks = 0;
- static unsigned int debug_quirks2;
- 
-@@ -131,43 +133,26 @@
-  *                                                                           *
- \*****************************************************************************/
- 
--static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
--{
--	u32 ier;
--
--	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
--	ier &= ~clear;
--	ier |= set;
--	sdhci_writel(host, ier, SDHCI_INT_ENABLE);
--	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
--}
--
--static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
--{
--	sdhci_clear_set_irqs(host, 0, irqs);
--}
--
--static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
--{
--	sdhci_clear_set_irqs(host, irqs, 0);
--}
--
- static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
- {
--	u32 present, irqs;
-+	u32 present;
- 
- 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
- 	    (host->mmc->caps & MMC_CAP_NONREMOVABLE))
- 		return;
- 
--	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
--			      SDHCI_CARD_PRESENT;
--	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
-+	if (enable) {
-+		present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-+				      SDHCI_CARD_PRESENT;
- 
--	if (enable)
--		sdhci_unmask_irqs(host, irqs);
--	else
--		sdhci_mask_irqs(host, irqs);
-+		host->ier |= present ? SDHCI_INT_CARD_REMOVE :
-+				       SDHCI_INT_CARD_INSERT;
-+	} else {
-+		host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
-+	}
-+
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
- 
- static void sdhci_enable_card_detection(struct sdhci_host *host)
-@@ -180,22 +165,9 @@
- 	sdhci_set_card_detection(host, false);
- }
- 
--static void sdhci_reset(struct sdhci_host *host, u8 mask)
-+void sdhci_reset(struct sdhci_host *host, u8 mask)
- {
- 	unsigned long timeout;
--	u32 uninitialized_var(ier);
--
--	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
--		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
--			SDHCI_CARD_PRESENT))
--			return;
--	}
--
--	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
--		ier = sdhci_readl(host, SDHCI_INT_ENABLE);
--
--	if (host->ops->platform_reset_enter)
--		host->ops->platform_reset_enter(host, mask);
- 
- 	sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
- 
-@@ -220,16 +192,27 @@
- 		timeout--;
- 		mdelay(1);
- 	}
-+}
-+EXPORT_SYMBOL_GPL(sdhci_reset);
-+
-+static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
-+{
-+	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
-+		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
-+			SDHCI_CARD_PRESENT))
-+			return;
-+	}
- 
--	if (host->ops->platform_reset_exit)
--		host->ops->platform_reset_exit(host, mask);
-+	host->ops->reset(host, mask);
- 
--	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
--		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
-+	if (mask & SDHCI_RESET_ALL) {
-+		if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
-+			if (host->ops->enable_dma)
-+				host->ops->enable_dma(host);
-+		}
- 
--	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
--		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
--			host->ops->enable_dma(host);
-+		/* Resetting the controller clears many */
-+		host->preset_enabled = false;
- 	}
- }
- 
-@@ -238,15 +221,18 @@
- static void sdhci_init(struct sdhci_host *host, int soft)
- {
- 	if (soft)
--		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
-+		sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
- 	else
--		sdhci_reset(host, SDHCI_RESET_ALL);
-+		sdhci_do_reset(host, SDHCI_RESET_ALL);
-+
-+	host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
-+		    SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
-+		    SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
-+		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
-+		    SDHCI_INT_RESPONSE;
- 
--	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
--		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
--		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
--		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
--		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- 
- 	if (soft) {
- 		/* force clock reconfiguration */
-@@ -502,11 +488,6 @@
- 	else
- 		direction = DMA_TO_DEVICE;
- 
--	/*
--	 * The ADMA descriptor table is mapped further down as we
--	 * need to fill it with data first.
--	 */
--
- 	host->align_addr = dma_map_single(mmc_dev(host->mmc),
- 		host->align_buffer, 128 * 4, direction);
- 	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
-@@ -567,7 +548,7 @@
- 		 * If this triggers then we have a calculation bug
- 		 * somewhere. :/
- 		 */
--		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
-+		WARN_ON((desc - host->adma_desc) > ADMA_SIZE);
- 	}
- 
- 	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
-@@ -595,17 +576,8 @@
- 			host->align_addr, 128 * 4, direction);
- 	}
- 
--	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
--		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
--	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
--		goto unmap_entries;
--	BUG_ON(host->adma_addr & 0x3);
--
- 	return 0;
- 
--unmap_entries:
--	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
--		data->sg_len, direction);
- unmap_align:
- 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
- 		128 * 4, direction);
-@@ -623,19 +595,25 @@
- 	u8 *align;
- 	char *buffer;
- 	unsigned long flags;
-+	bool has_unaligned;
- 
- 	if (data->flags & MMC_DATA_READ)
- 		direction = DMA_FROM_DEVICE;
- 	else
- 		direction = DMA_TO_DEVICE;
- 
--	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
--		(128 * 2 + 1) * 4, DMA_TO_DEVICE);
--
- 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
- 		128 * 4, direction);
- 
--	if (data->flags & MMC_DATA_READ) {
-+	/* Do a quick scan of the SG list for any unaligned mappings */
-+	has_unaligned = false;
-+	for_each_sg(data->sg, sg, host->sg_count, i)
-+		if (sg_dma_address(sg) & 3) {
-+			has_unaligned = true;
-+			break;
-+		}
-+
-+	if (has_unaligned && data->flags & MMC_DATA_READ) {
- 		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
- 			data->sg_len, direction);
- 
-@@ -721,9 +699,12 @@
- 	u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
- 
- 	if (host->flags & SDHCI_REQ_USE_DMA)
--		sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
-+		host->ier = (host->ier & ~pio_irqs) | dma_irqs;
- 	else
--		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
-+		host->ier = (host->ier & ~dma_irqs) | pio_irqs;
-+
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
- 
- static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
-@@ -976,8 +957,8 @@
- 		 * upon error conditions.
- 		 */
- 		if (data->error) {
--			sdhci_reset(host, SDHCI_RESET_CMD);
--			sdhci_reset(host, SDHCI_RESET_DATA);
-+			sdhci_do_reset(host, SDHCI_RESET_CMD);
-+			sdhci_do_reset(host, SDHCI_RESET_DATA);
- 		}
- 
- 		sdhci_send_command(host, data->stop);
-@@ -1107,24 +1088,23 @@
- 
- static u16 sdhci_get_preset_value(struct sdhci_host *host)
- {
--	u16 ctrl, preset = 0;
-+	u16 preset = 0;
- 
--	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--
--	switch (ctrl & SDHCI_CTRL_UHS_MASK) {
--	case SDHCI_CTRL_UHS_SDR12:
-+	switch (host->timing) {
-+	case MMC_TIMING_UHS_SDR12:
- 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
- 		break;
--	case SDHCI_CTRL_UHS_SDR25:
-+	case MMC_TIMING_UHS_SDR25:
- 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
- 		break;
--	case SDHCI_CTRL_UHS_SDR50:
-+	case MMC_TIMING_UHS_SDR50:
- 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
- 		break;
--	case SDHCI_CTRL_UHS_SDR104:
-+	case MMC_TIMING_UHS_SDR104:
-+	case MMC_TIMING_MMC_HS200:
- 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
- 		break;
--	case SDHCI_CTRL_UHS_DDR50:
-+	case MMC_TIMING_UHS_DDR50:
- 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
- 		break;
- 	default:
-@@ -1136,32 +1116,22 @@
- 	return preset;
- }
- 
--static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
-+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
- {
- 	int div = 0; /* Initialized for compiler warning */
- 	int real_div = div, clk_mul = 1;
- 	u16 clk = 0;
- 	unsigned long timeout;
- 
--	if (clock && clock == host->clock)
--		return;
--
- 	host->mmc->actual_clock = 0;
- 
--	if (host->ops->set_clock) {
--		host->ops->set_clock(host, clock);
--		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
--			return;
--	}
--
- 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- 
- 	if (clock == 0)
--		goto out;
-+		return;
- 
- 	if (host->version >= SDHCI_SPEC_300) {
--		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
--			SDHCI_CTRL_PRESET_VAL_ENABLE) {
-+		if (host->preset_enabled) {
- 			u16 pre_val;
- 
- 			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-@@ -1247,26 +1217,16 @@
- 
- 	clk |= SDHCI_CLOCK_CARD_EN;
- 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
--
--out:
--	host->clock = clock;
--}
--
--static inline void sdhci_update_clock(struct sdhci_host *host)
--{
--	unsigned int clock;
--
--	clock = host->clock;
--	host->clock = 0;
--	sdhci_set_clock(host, clock);
- }
-+EXPORT_SYMBOL_GPL(sdhci_set_clock);
- 
--static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
-+static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
-+			    unsigned short vdd)
- {
- 	u8 pwr = 0;
- 
--	if (power != (unsigned short)-1) {
--		switch (1 << power) {
-+	if (mode != MMC_POWER_OFF) {
-+		switch (1 << vdd) {
- 		case MMC_VDD_165_195:
- 			pwr = SDHCI_POWER_180;
- 			break;
-@@ -1284,7 +1244,7 @@
- 	}
- 
- 	if (host->pwr == pwr)
--		return -1;
-+		return;
- 
- 	host->pwr = pwr;
- 
-@@ -1292,38 +1252,43 @@
- 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
- 			sdhci_runtime_pm_bus_off(host);
--		return 0;
--	}
--
--	/*
--	 * Spec says that we should clear the power reg before setting
--	 * a new value. Some controllers don't seem to like this though.
--	 */
--	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
--		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-+		vdd = 0;
-+	} else {
-+		/*
-+		 * Spec says that we should clear the power reg before setting
-+		 * a new value. Some controllers don't seem to like this though.
-+		 */
-+		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
-+			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
- 
--	/*
--	 * At least the Marvell CaFe chip gets confused if we set the voltage
--	 * and set turn on power at the same time, so set the voltage first.
--	 */
--	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
--		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-+		/*
-+		 * At least the Marvell CaFe chip gets confused if we set the
-+		 * voltage and set turn on power at the same time, so set the
-+		 * voltage first.
-+		 */
-+		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
-+			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- 
--	pwr |= SDHCI_POWER_ON;
-+		pwr |= SDHCI_POWER_ON;
- 
--	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
-+		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
- 
--	if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
--		sdhci_runtime_pm_bus_on(host);
-+		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
-+			sdhci_runtime_pm_bus_on(host);
- 
--	/*
--	 * Some controllers need an extra 10ms delay of 10ms before they
--	 * can apply clock after applying power
--	 */
--	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
--		mdelay(10);
-+		/*
-+		 * Some controllers need an extra 10ms delay of 10ms before
-+		 * they can apply clock after applying power
-+		 */
-+		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
-+			mdelay(10);
-+	}
- 
--	return power;
-+	if (host->vmmc) {
-+		spin_unlock_irq(&host->lock);
-+		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
-+		spin_lock_irq(&host->lock);
-+	}
- }
- 
- /*****************************************************************************\
-@@ -1427,10 +1392,52 @@
- 	spin_unlock_irqrestore(&host->lock, flags);
- }
- 
-+void sdhci_set_bus_width(struct sdhci_host *host, int width)
-+{
-+	u8 ctrl;
-+
-+	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
-+	if (width == MMC_BUS_WIDTH_8) {
-+		ctrl &= ~SDHCI_CTRL_4BITBUS;
-+		if (host->version >= SDHCI_SPEC_300)
-+			ctrl |= SDHCI_CTRL_8BITBUS;
-+	} else {
-+		if (host->version >= SDHCI_SPEC_300)
-+			ctrl &= ~SDHCI_CTRL_8BITBUS;
-+		if (width == MMC_BUS_WIDTH_4)
-+			ctrl |= SDHCI_CTRL_4BITBUS;
-+		else
-+			ctrl &= ~SDHCI_CTRL_4BITBUS;
-+	}
-+	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-+}
-+EXPORT_SYMBOL_GPL(sdhci_set_bus_width);
-+
-+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
-+{
-+	u16 ctrl_2;
-+
-+	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-+	/* Select Bus Speed Mode for host */
-+	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
-+	if ((timing == MMC_TIMING_MMC_HS200) ||
-+	    (timing == MMC_TIMING_UHS_SDR104))
-+		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
-+	else if (timing == MMC_TIMING_UHS_SDR12)
-+		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-+	else if (timing == MMC_TIMING_UHS_SDR25)
-+		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
-+	else if (timing == MMC_TIMING_UHS_SDR50)
-+		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
-+	else if (timing == MMC_TIMING_UHS_DDR50)
-+		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
-+	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
-+}
-+EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
-+
- static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
- {
- 	unsigned long flags;
--	int vdd_bit = -1;
- 	u8 ctrl;
- 
- 	spin_lock_irqsave(&host->lock, flags);
-@@ -1456,45 +1463,17 @@
- 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
- 		sdhci_enable_preset_value(host, false);
- 
--	sdhci_set_clock(host, ios->clock);
--
--	if (ios->power_mode == MMC_POWER_OFF)
--		vdd_bit = sdhci_set_power(host, -1);
--	else
--		vdd_bit = sdhci_set_power(host, ios->vdd);
--
--	if (host->vmmc && vdd_bit != -1) {
--		spin_unlock_irqrestore(&host->lock, flags);
--		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
--		spin_lock_irqsave(&host->lock, flags);
-+	if (!ios->clock || ios->clock != host->clock) {
-+		host->ops->set_clock(host, ios->clock);
-+		host->clock = ios->clock;
- 	}
- 
-+	sdhci_set_power(host, ios->power_mode, ios->vdd);
-+
- 	if (host->ops->platform_send_init_74_clocks)
- 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
- 
--	/*
--	 * If your platform has 8-bit width support but is not a v3 controller,
--	 * or if it requires special setup code, you should implement that in
--	 * platform_bus_width().
--	 */
--	if (host->ops->platform_bus_width) {
--		host->ops->platform_bus_width(host, ios->bus_width);
--	} else {
--		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
--		if (ios->bus_width == MMC_BUS_WIDTH_8) {
--			ctrl &= ~SDHCI_CTRL_4BITBUS;
--			if (host->version >= SDHCI_SPEC_300)
--				ctrl |= SDHCI_CTRL_8BITBUS;
--		} else {
--			if (host->version >= SDHCI_SPEC_300)
--				ctrl &= ~SDHCI_CTRL_8BITBUS;
--			if (ios->bus_width == MMC_BUS_WIDTH_4)
--				ctrl |= SDHCI_CTRL_4BITBUS;
--			else
--				ctrl &= ~SDHCI_CTRL_4BITBUS;
--		}
--		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
--	}
-+	host->ops->set_bus_width(host, ios->bus_width);
- 
- 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
- 
-@@ -1516,13 +1495,13 @@
- 		    (ios->timing == MMC_TIMING_UHS_SDR25))
- 			ctrl |= SDHCI_CTRL_HISPD;
- 
--		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--		if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
-+		if (!host->preset_enabled) {
- 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- 			/*
- 			 * We only need to set Driver Strength if the
- 			 * preset value enable is not set.
- 			 */
-+			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- 			ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
- 			if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
- 				ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
-@@ -1546,34 +1525,11 @@
- 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- 
- 			/* Re-enable SD Clock */
--			sdhci_update_clock(host);
-+			host->ops->set_clock(host, host->clock);
- 		}
- 
--
--		/* Reset SD Clock Enable */
--		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
--		clk &= ~SDHCI_CLOCK_CARD_EN;
--		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
--
--		if (host->ops->set_uhs_signaling)
--			host->ops->set_uhs_signaling(host, ios->timing);
--		else {
--			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--			/* Select Bus Speed Mode for host */
--			ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
--			if ((ios->timing == MMC_TIMING_MMC_HS200) ||
--			    (ios->timing == MMC_TIMING_UHS_SDR104))
--				ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
--			else if (ios->timing == MMC_TIMING_UHS_SDR12)
--				ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
--			else if (ios->timing == MMC_TIMING_UHS_SDR25)
--				ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
--			else if (ios->timing == MMC_TIMING_UHS_SDR50)
--				ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
--			else if (ios->timing == MMC_TIMING_UHS_DDR50)
--				ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
--			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
--		}
-+		host->ops->set_uhs_signaling(host, ios->timing);
-+		host->timing = ios->timing;
- 
- 		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
- 				((ios->timing == MMC_TIMING_UHS_SDR12) ||
-@@ -1588,9 +1544,6 @@
- 			ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
- 				>> SDHCI_PRESET_DRV_SHIFT;
- 		}
--
--		/* Re-enable SD Clock */
--		sdhci_update_clock(host);
- 	} else
- 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
- 
-@@ -1600,7 +1553,7 @@
- 	 * it on each ios seems to solve the problem.
- 	 */
- 	if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
--		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
-+		sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
- 
- 	mmiowb();
- 	spin_unlock_irqrestore(&host->lock, flags);
-@@ -1709,24 +1662,16 @@
- 
- static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
- {
--	if (host->flags & SDHCI_DEVICE_DEAD)
--		goto out;
--
--	if (enable)
--		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
--	else
--		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
--
--	/* SDIO IRQ will be enabled as appropriate in runtime resume */
--	if (host->runtime_suspended)
--		goto out;
-+	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
-+		if (enable)
-+			host->ier |= SDHCI_INT_CARD_INT;
-+		else
-+			host->ier &= ~SDHCI_INT_CARD_INT;
- 
--	if (enable)
--		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
--	else
--		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
--out:
--	mmiowb();
-+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
-+		mmiowb();
-+	}
- }
- 
- static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
-@@ -1734,9 +1679,18 @@
- 	struct sdhci_host *host = mmc_priv(mmc);
- 	unsigned long flags;
- 
-+	sdhci_runtime_pm_get(host);
-+
- 	spin_lock_irqsave(&host->lock, flags);
-+	if (enable)
-+		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
-+	else
-+		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
-+
- 	sdhci_enable_sdio_irq_nolock(host, enable);
- 	spin_unlock_irqrestore(&host->lock, flags);
-+
-+	sdhci_runtime_pm_put(host);
- }
- 
- static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
-@@ -1798,9 +1752,6 @@
- 		ctrl |= SDHCI_CTRL_VDD_180;
- 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- 
--		/* Wait for 5ms */
--		usleep_range(5000, 5500);
--
- 		/* 1.8V regulator output should be stable within 5 ms */
- 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
- 		if (ctrl & SDHCI_CTRL_VDD_180)
-@@ -1855,22 +1806,16 @@
- 
- static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
- {
--	struct sdhci_host *host;
-+	struct sdhci_host *host = mmc_priv(mmc);
- 	u16 ctrl;
--	u32 ier;
- 	int tuning_loop_counter = MAX_TUNING_LOOP;
- 	unsigned long timeout;
- 	int err = 0;
--	bool requires_tuning_nonuhs = false;
- 	unsigned long flags;
- 
--	host = mmc_priv(mmc);
--
- 	sdhci_runtime_pm_get(host);
- 	spin_lock_irqsave(&host->lock, flags);
- 
--	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--
- 	/*
- 	 * The Host Controller needs tuning only in case of SDR104 mode
- 	 * and for SDR50 mode when Use Tuning for SDR50 is set in the
-@@ -1878,15 +1823,18 @@
- 	 * If the Host Controller supports the HS200 mode then the
- 	 * tuning function has to be executed.
- 	 */
--	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
--	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
--	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
--		requires_tuning_nonuhs = true;
--
--	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
--	    requires_tuning_nonuhs)
--		ctrl |= SDHCI_CTRL_EXEC_TUNING;
--	else {
-+	switch (host->timing) {
-+	case MMC_TIMING_MMC_HS200:
-+	case MMC_TIMING_UHS_SDR104:
-+		break;
-+
-+	case MMC_TIMING_UHS_SDR50:
-+		if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
-+		    host->flags & SDHCI_SDR104_NEEDS_TUNING)
-+			break;
-+		/* FALLTHROUGH */
-+
-+	default:
- 		spin_unlock_irqrestore(&host->lock, flags);
- 		sdhci_runtime_pm_put(host);
- 		return 0;
-@@ -1899,6 +1847,8 @@
- 		return err;
- 	}
- 
-+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
- 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
- 
- 	/*
-@@ -1911,8 +1861,8 @@
- 	 * to make sure we don't hit a controller bug, we _only_
- 	 * enable Buffer Read Ready interrupt here.
- 	 */
--	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
--	sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
-+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
- 
- 	/*
- 	 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
-@@ -2044,7 +1994,8 @@
- 	if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
- 		err = 0;
- 
--	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- 	spin_unlock_irqrestore(&host->lock, flags);
- 	sdhci_runtime_pm_put(host);
- 
-@@ -2054,26 +2005,30 @@
- 
- static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
- {
--	u16 ctrl;
--
- 	/* Host Controller v3.00 defines preset value registers */
- 	if (host->version < SDHCI_SPEC_300)
- 		return;
- 
--	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
--
- 	/*
- 	 * We only enable or disable Preset Value if they are not already
- 	 * enabled or disabled respectively. Otherwise, we bail out.
- 	 */
--	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
--		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
--		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
--		host->flags |= SDHCI_PV_ENABLED;
--	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
--		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
-+	if (host->preset_enabled != enable) {
-+		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-+
-+		if (enable)
-+			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
-+		else
-+			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
-+
- 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
--		host->flags &= ~SDHCI_PV_ENABLED;
-+
-+		if (enable)
-+			host->flags |= SDHCI_PV_ENABLED;
-+		else
-+			host->flags &= ~SDHCI_PV_ENABLED;
-+
-+		host->preset_enabled = enable;
- 	}
- }
- 
-@@ -2095,8 +2050,8 @@
- 		pr_err("%s: Resetting controller.\n",
- 			mmc_hostname(host->mmc));
- 
--		sdhci_reset(host, SDHCI_RESET_CMD);
--		sdhci_reset(host, SDHCI_RESET_DATA);
-+		sdhci_do_reset(host, SDHCI_RESET_CMD);
-+		sdhci_do_reset(host, SDHCI_RESET_DATA);
- 
- 		host->mrq->cmd->error = -ENOMEDIUM;
- 		tasklet_schedule(&host->finish_tasklet);
-@@ -2124,15 +2079,6 @@
-  *                                                                           *
- \*****************************************************************************/
- 
--static void sdhci_tasklet_card(unsigned long param)
--{
--	struct sdhci_host *host = (struct sdhci_host*)param;
--
--	sdhci_card_event(host->mmc);
--
--	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
--}
--
- static void sdhci_tasklet_finish(unsigned long param)
- {
- 	struct sdhci_host *host;
-@@ -2169,12 +2115,12 @@
- 		/* Some controllers need this kick or reset won't work here */
- 		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
- 			/* This is to force an update */
--			sdhci_update_clock(host);
-+			host->ops->set_clock(host, host->clock);
- 
- 		/* Spec says we should do both at the same time, but Ricoh
- 		   controllers do not like that. */
--		sdhci_reset(host, SDHCI_RESET_CMD);
--		sdhci_reset(host, SDHCI_RESET_DATA);
-+		sdhci_do_reset(host, SDHCI_RESET_CMD);
-+		sdhci_do_reset(host, SDHCI_RESET_DATA);
- 	}
- 
- 	host->mrq = NULL;
-@@ -2424,101 +2370,94 @@
- 
- static irqreturn_t sdhci_irq(int irq, void *dev_id)
- {
--	irqreturn_t result;
-+	irqreturn_t result = IRQ_NONE;
- 	struct sdhci_host *host = dev_id;
--	u32 intmask, unexpected = 0;
--	int cardint = 0, max_loops = 16;
-+	u32 intmask, mask, unexpected = 0;
-+	int max_loops = 16;
- 
- 	spin_lock(&host->lock);
- 
--	if (host->runtime_suspended) {
-+	if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) {
- 		spin_unlock(&host->lock);
- 		return IRQ_NONE;
- 	}
- 
- 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
--
- 	if (!intmask || intmask == 0xffffffff) {
- 		result = IRQ_NONE;
- 		goto out;
- 	}
- 
--again:
--	DBG("*** %s got interrupt: 0x%08x\n",
--		mmc_hostname(host->mmc), intmask);
--
--	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
--		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
--			      SDHCI_CARD_PRESENT;
--
--		/*
--		 * There is a observation on i.mx esdhc.  INSERT bit will be
--		 * immediately set again when it gets cleared, if a card is
--		 * inserted.  We have to mask the irq to prevent interrupt
--		 * storm which will freeze the system.  And the REMOVE gets
--		 * the same situation.
--		 *
--		 * More testing are needed here to ensure it works for other
--		 * platforms though.
--		 */
--		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
--						SDHCI_INT_CARD_REMOVE);
--		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
--						  SDHCI_INT_CARD_INSERT);
--
--		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
--			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
--		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
--		tasklet_schedule(&host->card_tasklet);
--	}
--
--	if (intmask & SDHCI_INT_CMD_MASK) {
--		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
--			SDHCI_INT_STATUS);
--		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
--	}
-+	do {
-+		/* Clear selected interrupts. */
-+		mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
-+				  SDHCI_INT_BUS_POWER);
-+		sdhci_writel(host, mask, SDHCI_INT_STATUS);
-+
-+		DBG("*** %s got interrupt: 0x%08x\n",
-+			mmc_hostname(host->mmc), intmask);
-+
-+		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-+			u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
-+				      SDHCI_CARD_PRESENT;
- 
--	if (intmask & SDHCI_INT_DATA_MASK) {
--		sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
--			SDHCI_INT_STATUS);
--		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
--	}
-+			/*
-+			 * There is a observation on i.mx esdhc.  INSERT
-+			 * bit will be immediately set again when it gets
-+			 * cleared, if a card is inserted.  We have to mask
-+			 * the irq to prevent interrupt storm which will
-+			 * freeze the system.  And the REMOVE gets the
-+			 * same situation.
-+			 *
-+			 * More testing are needed here to ensure it works
-+			 * for other platforms though.
-+			 */
-+			host->ier &= ~(SDHCI_INT_CARD_INSERT |
-+				       SDHCI_INT_CARD_REMOVE);
-+			host->ier |= present ? SDHCI_INT_CARD_REMOVE :
-+					       SDHCI_INT_CARD_INSERT;
-+			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- 
--	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
-+			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
-+				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
- 
--	intmask &= ~SDHCI_INT_ERROR;
-+			host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
-+						       SDHCI_INT_CARD_REMOVE);
-+			result = IRQ_WAKE_THREAD;
-+		}
- 
--	if (intmask & SDHCI_INT_BUS_POWER) {
--		pr_err("%s: Card is consuming too much power!\n",
--			mmc_hostname(host->mmc));
--		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
--	}
-+		if (intmask & SDHCI_INT_CMD_MASK)
-+			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
- 
--	intmask &= ~SDHCI_INT_BUS_POWER;
-+		if (intmask & SDHCI_INT_DATA_MASK)
-+			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
- 
--	if (intmask & SDHCI_INT_CARD_INT)
--		cardint = 1;
-+		if (intmask & SDHCI_INT_BUS_POWER)
-+			pr_err("%s: Card is consuming too much power!\n",
-+				mmc_hostname(host->mmc));
- 
--	intmask &= ~SDHCI_INT_CARD_INT;
-+		if (intmask & SDHCI_INT_CARD_INT) {
-+			sdhci_enable_sdio_irq_nolock(host, false);
-+			host->thread_isr |= SDHCI_INT_CARD_INT;
-+			result = IRQ_WAKE_THREAD;
-+		}
- 
--	if (intmask) {
--		unexpected |= intmask;
--		sdhci_writel(host, intmask, SDHCI_INT_STATUS);
--	}
-+		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
-+			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
-+			     SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
-+			     SDHCI_INT_CARD_INT);
- 
--	result = IRQ_HANDLED;
-+		if (intmask) {
-+			unexpected |= intmask;
-+			sdhci_writel(host, intmask, SDHCI_INT_STATUS);
-+		}
- 
--	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-+		if (result == IRQ_NONE)
-+			result = IRQ_HANDLED;
- 
--	/*
--	 * If we know we'll call the driver to signal SDIO IRQ, disregard
--	 * further indications of Card Interrupt in the status to avoid a
--	 * needless loop.
--	 */
--	if (cardint)
--		intmask &= ~SDHCI_INT_CARD_INT;
--	if (intmask && --max_loops)
--		goto again;
-+		intmask = sdhci_readl(host, SDHCI_INT_STATUS);
-+	} while (intmask && --max_loops);
- out:
- 	spin_unlock(&host->lock);
- 
-@@ -2527,15 +2466,38 @@
- 			   mmc_hostname(host->mmc), unexpected);
- 		sdhci_dumpregs(host);
- 	}
--	/*
--	 * We have to delay this as it calls back into the driver.
--	 */
--	if (cardint)
--		mmc_signal_sdio_irq(host->mmc);
- 
- 	return result;
- }
- 
-+static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
-+{
-+	struct sdhci_host *host = dev_id;
-+	unsigned long flags;
-+	u32 isr;
-+
-+	spin_lock_irqsave(&host->lock, flags);
-+	isr = host->thread_isr;
-+	host->thread_isr = 0;
-+	spin_unlock_irqrestore(&host->lock, flags);
-+
-+	if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-+		sdhci_card_event(host->mmc);
-+		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
-+	}
-+
-+	if (isr & SDHCI_INT_CARD_INT) {
-+		sdio_run_irqs(host->mmc);
-+
-+		spin_lock_irqsave(&host->lock, flags);
-+		if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
-+			sdhci_enable_sdio_irq_nolock(host, true);
-+		spin_unlock_irqrestore(&host->lock, flags);
-+	}
-+
-+	return isr ? IRQ_HANDLED : IRQ_NONE;
-+}
-+
- /*****************************************************************************\
-  *                                                                           *
-  * Suspend/resume                                                            *
-@@ -2572,9 +2534,6 @@
- 
- int sdhci_suspend_host(struct sdhci_host *host)
- {
--	if (host->ops->platform_suspend)
--		host->ops->platform_suspend(host);
--
- 	sdhci_disable_card_detection(host);
- 
- 	/* Disable tuning since we are suspending */
-@@ -2584,7 +2543,9 @@
- 	}
- 
- 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
--		sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
-+		host->ier = 0;
-+		sdhci_writel(host, 0, SDHCI_INT_ENABLE);
-+		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- 		free_irq(host->irq, host);
- 	} else {
- 		sdhci_enable_irq_wakeups(host);
-@@ -2605,8 +2566,9 @@
- 	}
- 
- 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
--		ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
--				  mmc_hostname(host->mmc), host);
-+		ret = request_threaded_irq(host->irq, sdhci_irq,
-+					   sdhci_thread_irq, IRQF_SHARED,
-+					   mmc_hostname(host->mmc), host);
- 		if (ret)
- 			return ret;
- 	} else {
-@@ -2628,9 +2590,6 @@
- 
- 	sdhci_enable_card_detection(host);
- 
--	if (host->ops->platform_resume)
--		host->ops->platform_resume(host);
--
- 	/* Set the re-tuning expiration flag */
- 	if (host->flags & SDHCI_USING_RETUNING_TIMER)
- 		host->flags |= SDHCI_NEEDS_RETUNING;
-@@ -2682,10 +2641,12 @@
- 	}
- 
- 	spin_lock_irqsave(&host->lock, flags);
--	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
-+	host->ier &= SDHCI_INT_CARD_INT;
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- 	spin_unlock_irqrestore(&host->lock, flags);
- 
--	synchronize_irq(host->irq);
-+	synchronize_hardirq(host->irq);
- 
- 	spin_lock_irqsave(&host->lock, flags);
- 	host->runtime_suspended = true;
-@@ -2729,7 +2690,7 @@
- 	host->runtime_suspended = false;
- 
- 	/* Enable SDIO IRQ */
--	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
-+	if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
- 		sdhci_enable_sdio_irq_nolock(host, true);
- 
- 	/* Enable Card Detection */
-@@ -2788,7 +2749,7 @@
- 	if (debug_quirks2)
- 		host->quirks2 = debug_quirks2;
- 
--	sdhci_reset(host, SDHCI_RESET_ALL);
-+	sdhci_do_reset(host, SDHCI_RESET_ALL);
- 
- 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- 	host->version = (host->version & SDHCI_SPEC_VER_MASK)
-@@ -2848,15 +2809,29 @@
- 		 * (128) and potentially one alignment transfer for
- 		 * each of those entries.
- 		 */
--		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
-+		host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
-+						     ADMA_SIZE, &host->adma_addr,
-+						     GFP_KERNEL);
- 		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
- 		if (!host->adma_desc || !host->align_buffer) {
--			kfree(host->adma_desc);
-+			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
-+					  host->adma_desc, host->adma_addr);
- 			kfree(host->align_buffer);
- 			pr_warning("%s: Unable to allocate ADMA "
- 				"buffers. Falling back to standard DMA.\n",
- 				mmc_hostname(mmc));
- 			host->flags &= ~SDHCI_USE_ADMA;
-+			host->adma_desc = NULL;
-+			host->align_buffer = NULL;
-+		} else if (host->adma_addr & 3) {
-+			pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
-+				   mmc_hostname(mmc));
-+			host->flags &= ~SDHCI_USE_ADMA;
-+			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
-+					  host->adma_desc, host->adma_addr);
-+			kfree(host->align_buffer);
-+			host->adma_desc = NULL;
-+			host->align_buffer = NULL;
- 		}
- 	}
- 
-@@ -2941,6 +2916,7 @@
- 	mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
- 
- 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
-+	mmc->caps2 |= MMC_CAP2_SDIO_NOTHREAD;
- 
- 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
- 		host->flags |= SDHCI_AUTO_CMD12;
-@@ -3212,8 +3188,6 @@
- 	/*
- 	 * Init tasklets.
- 	 */
--	tasklet_init(&host->card_tasklet,
--		sdhci_tasklet_card, (unsigned long)host);
- 	tasklet_init(&host->finish_tasklet,
- 		sdhci_tasklet_finish, (unsigned long)host);
- 
-@@ -3230,8 +3204,8 @@
- 
- 	sdhci_init(host, 0);
- 
--	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
--		mmc_hostname(mmc), host);
-+	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
-+				   IRQF_SHARED,	mmc_hostname(mmc), host);
- 	if (ret) {
- 		pr_err("%s: Failed to request IRQ %d: %d\n",
- 		       mmc_hostname(mmc), host->irq, ret);
-@@ -3273,12 +3247,12 @@
- 
- #ifdef SDHCI_USE_LEDS_CLASS
- reset:
--	sdhci_reset(host, SDHCI_RESET_ALL);
--	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
-+	sdhci_do_reset(host, SDHCI_RESET_ALL);
-+	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- 	free_irq(host->irq, host);
- #endif
- untasklet:
--	tasklet_kill(&host->card_tasklet);
- 	tasklet_kill(&host->finish_tasklet);
- 
- 	return ret;
-@@ -3315,14 +3289,14 @@
- #endif
- 
- 	if (!dead)
--		sdhci_reset(host, SDHCI_RESET_ALL);
-+		sdhci_do_reset(host, SDHCI_RESET_ALL);
- 
--	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
-+	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- 	free_irq(host->irq, host);
- 
- 	del_timer_sync(&host->timer);
- 
--	tasklet_kill(&host->card_tasklet);
- 	tasklet_kill(&host->finish_tasklet);
- 
- 	if (host->vmmc) {
-@@ -3335,7 +3309,9 @@
- 		regulator_put(host->vqmmc);
- 	}
- 
--	kfree(host->adma_desc);
-+	if (host->adma_desc)
-+		dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
-+				  host->adma_desc, host->adma_addr);
- 	kfree(host->align_buffer);
- 
- 	host->adma_desc = NULL;
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-cns3xxx.c linux-3.15-rc6/drivers/mmc/host/sdhci-cns3xxx.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-cns3xxx.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-cns3xxx.c	2014-05-23 11:26:48.304940032 +0200
-@@ -30,13 +30,12 @@
- 	u16 clk;
- 	unsigned long timeout;
- 
--	if (clock == host->clock)
--		return;
-+	host->mmc->actual_clock = 0;
- 
- 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- 
- 	if (clock == 0)
--		goto out;
-+		return;
- 
- 	while (host->max_clk / div > clock) {
- 		/*
-@@ -75,13 +74,14 @@
- 
- 	clk |= SDHCI_CLOCK_CARD_EN;
- 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
--out:
--	host->clock = clock;
- }
- 
- static const struct sdhci_ops sdhci_cns3xxx_ops = {
- 	.get_max_clock	= sdhci_cns3xxx_get_max_clk,
- 	.set_clock	= sdhci_cns3xxx_set_clock,
-+	.set_bus_width	= sdhci_set_bus_width,
-+	.reset          = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
-@@ -90,8 +90,7 @@
- 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
- 		  SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
- 		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
--		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
--		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
-+		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
- };
- 
- static int sdhci_cns3xxx_probe(struct platform_device *pdev)
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-dove.c linux-3.15-rc6/drivers/mmc/host/sdhci-dove.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-dove.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-dove.c	2014-05-23 11:26:48.304940032 +0200
-@@ -86,6 +86,10 @@
- static const struct sdhci_ops sdhci_dove_ops = {
- 	.read_w	= sdhci_dove_readw,
- 	.read_l	= sdhci_dove_readl,
-+	.set_clock = sdhci_set_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_pltfm_data sdhci_dove_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-esdhc.h linux-3.15-rc6/drivers/mmc/host/sdhci-esdhc.h
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-esdhc.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-esdhc.h	2014-05-23 11:26:48.304940032 +0200
-@@ -20,10 +20,8 @@
- 
- #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
- 				SDHCI_QUIRK_NO_BUSY_IRQ | \
--				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
- 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
--				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
--				SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
-+				SDHCI_QUIRK_PIO_NEEDS_DELAY)
- 
- #define ESDHC_SYSTEM_CONTROL	0x2c
- #define ESDHC_CLOCK_MASK	0x0000fff0
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-esdhc-imx.c linux-3.15-rc6/drivers/mmc/host/sdhci-esdhc-imx.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-esdhc-imx.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-esdhc-imx.c	2014-05-23 11:26:48.304940032 +0200
-@@ -160,7 +160,6 @@
- 		MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
- 		WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
- 	} multiblock_status;
--	u32 uhs_mode;
- 	u32 is_ddr;
- };
- 
-@@ -382,7 +381,6 @@
- 		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
- 			ret |= SDHCI_CTRL_TUNED_CLK;
- 
--		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
- 		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
- 
- 		return ret;
-@@ -429,7 +427,6 @@
- 		else
- 			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
- 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
--		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
- 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
- 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
- 			if (val & SDHCI_CTRL_TUNED_CLK)
-@@ -600,12 +597,14 @@
- 	u32 temp, val;
- 
- 	if (clock == 0) {
-+		host->mmc->actual_clock = 0;
-+
- 		if (esdhc_is_usdhc(imx_data)) {
- 			val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
- 			writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
- 					host->ioaddr + ESDHC_VENDOR_SPEC);
- 		}
--		goto out;
-+		return;
- 	}
- 
- 	if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
-@@ -645,8 +644,6 @@
- 	}
- 
- 	mdelay(1);
--out:
--	host->clock = clock;
- }
- 
- static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
-@@ -668,7 +665,7 @@
- 	return -ENOSYS;
- }
- 
--static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
-+static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
- {
- 	u32 ctrl;
- 
-@@ -686,8 +683,6 @@
- 
- 	esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl,
- 			SDHCI_HOST_CONTROL);
--
--	return 0;
- }
- 
- static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
-@@ -697,6 +692,7 @@
- 	/* FIXME: delay a bit for card to be ready for next tuning due to errors */
- 	mdelay(1);
- 
-+	/* This is balanced by the runtime put in sdhci_tasklet_finish */
- 	pm_runtime_get_sync(host->mmc->parent);
- 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
- 	reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
-@@ -713,13 +709,12 @@
- 	complete(&mrq->completion);
- }
- 
--static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
-+static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
-+				 struct scatterlist *sg)
- {
- 	struct mmc_command cmd = {0};
- 	struct mmc_request mrq = {NULL};
- 	struct mmc_data data = {0};
--	struct scatterlist sg;
--	char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
- 
- 	cmd.opcode = opcode;
- 	cmd.arg = 0;
-@@ -728,11 +723,9 @@
- 	data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
- 	data.blocks = 1;
- 	data.flags = MMC_DATA_READ;
--	data.sg = &sg;
-+	data.sg = sg;
- 	data.sg_len = 1;
- 
--	sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
--
- 	mrq.cmd = &cmd;
- 	mrq.cmd->mrq = &mrq;
- 	mrq.data = &data;
-@@ -742,14 +735,12 @@
- 	mrq.done = esdhc_request_done;
- 	init_completion(&(mrq.completion));
- 
--	disable_irq(host->irq);
--	spin_lock(&host->lock);
-+	spin_lock_irq(&host->lock);
- 	host->mrq = &mrq;
- 
- 	sdhci_send_command(host, mrq.cmd);
- 
--	spin_unlock(&host->lock);
--	enable_irq(host->irq);
-+	spin_unlock_irq(&host->lock);
- 
- 	wait_for_completion(&mrq.completion);
- 
-@@ -772,13 +763,21 @@
- 
- static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
- {
-+	struct scatterlist sg;
-+	char *tuning_pattern;
- 	int min, max, avg, ret;
- 
-+	tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
-+	if (!tuning_pattern)
-+		return -ENOMEM;
-+
-+	sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
-+
- 	/* find the mininum delay first which can pass tuning */
- 	min = ESDHC_TUNE_CTRL_MIN;
- 	while (min < ESDHC_TUNE_CTRL_MAX) {
- 		esdhc_prepare_tuning(host, min);
--		if (!esdhc_send_tuning_cmd(host, opcode))
-+		if (!esdhc_send_tuning_cmd(host, opcode, &sg))
- 			break;
- 		min += ESDHC_TUNE_CTRL_STEP;
- 	}
-@@ -787,7 +786,7 @@
- 	max = min + ESDHC_TUNE_CTRL_STEP;
- 	while (max < ESDHC_TUNE_CTRL_MAX) {
- 		esdhc_prepare_tuning(host, max);
--		if (esdhc_send_tuning_cmd(host, opcode)) {
-+		if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
- 			max -= ESDHC_TUNE_CTRL_STEP;
- 			break;
- 		}
-@@ -797,9 +796,11 @@
- 	/* use average delay to get the best timing */
- 	avg = (min + max) / 2;
- 	esdhc_prepare_tuning(host, avg);
--	ret = esdhc_send_tuning_cmd(host, opcode);
-+	ret = esdhc_send_tuning_cmd(host, opcode, &sg);
- 	esdhc_post_tuning(host);
- 
-+	kfree(tuning_pattern);
-+
- 	dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
- 		ret ? "failed" : "passed", avg, ret);
- 
-@@ -837,28 +838,20 @@
- 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
- }
- 
--static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
-+static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
- {
- 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
- 	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
- 
--	switch (uhs) {
-+	switch (timing) {
- 	case MMC_TIMING_UHS_SDR12:
--		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
--		break;
- 	case MMC_TIMING_UHS_SDR25:
--		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
--		break;
- 	case MMC_TIMING_UHS_SDR50:
--		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
--		break;
- 	case MMC_TIMING_UHS_SDR104:
- 	case MMC_TIMING_MMC_HS200:
--		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
- 		break;
- 	case MMC_TIMING_UHS_DDR50:
--		imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
- 		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
- 				ESDHC_MIX_CTRL_DDREN,
- 				host->ioaddr + ESDHC_MIX_CTRL);
-@@ -875,7 +868,15 @@
- 		break;
- 	}
- 
--	return esdhc_change_pinstate(host, uhs);
-+	esdhc_change_pinstate(host, timing);
-+}
-+
-+static void esdhc_reset(struct sdhci_host *host, u8 mask)
-+{
-+	sdhci_reset(host, mask);
-+
-+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
- }
- 
- static struct sdhci_ops sdhci_esdhc_ops = {
-@@ -888,8 +889,9 @@
- 	.get_max_clock = esdhc_pltfm_get_max_clock,
- 	.get_min_clock = esdhc_pltfm_get_min_clock,
- 	.get_ro = esdhc_pltfm_get_ro,
--	.platform_bus_width = esdhc_pltfm_bus_width,
-+	.set_bus_width = esdhc_pltfm_set_bus_width,
- 	.set_uhs_signaling = esdhc_set_uhs_signaling,
-+	.reset = esdhc_reset,
- };
- 
- static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-@@ -1170,8 +1172,10 @@
- 
- 	ret = sdhci_runtime_suspend_host(host);
- 
--	clk_disable_unprepare(imx_data->clk_per);
--	clk_disable_unprepare(imx_data->clk_ipg);
-+	if (!sdhci_sdio_irq_enabled(host)) {
-+		clk_disable_unprepare(imx_data->clk_per);
-+		clk_disable_unprepare(imx_data->clk_ipg);
-+	}
- 	clk_disable_unprepare(imx_data->clk_ahb);
- 
- 	return ret;
-@@ -1183,8 +1187,10 @@
- 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
- 
--	clk_prepare_enable(imx_data->clk_per);
--	clk_prepare_enable(imx_data->clk_ipg);
-+	if (!sdhci_sdio_irq_enabled(host)) {
-+		clk_prepare_enable(imx_data->clk_per);
-+		clk_prepare_enable(imx_data->clk_ipg);
-+	}
- 	clk_prepare_enable(imx_data->clk_ahb);
- 
- 	return sdhci_runtime_resume_host(host);
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci.h linux-3.15-rc6/drivers/mmc/host/sdhci.h
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci.h	2014-05-23 11:26:48.304940032 +0200
-@@ -281,18 +281,14 @@
- 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
- 	unsigned int	(*get_min_clock)(struct sdhci_host *host);
- 	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
--	int		(*platform_bus_width)(struct sdhci_host *host,
--					       int width);
-+	void		(*set_bus_width)(struct sdhci_host *host, int width);
- 	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
- 					     u8 power_mode);
- 	unsigned int    (*get_ro)(struct sdhci_host *host);
--	void	(*platform_reset_enter)(struct sdhci_host *host, u8 mask);
--	void	(*platform_reset_exit)(struct sdhci_host *host, u8 mask);
-+	void		(*reset)(struct sdhci_host *host, u8 mask);
- 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
--	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
-+	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
- 	void	(*hw_reset)(struct sdhci_host *host);
--	void	(*platform_suspend)(struct sdhci_host *host);
--	void	(*platform_resume)(struct sdhci_host *host);
- 	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
- 	void	(*platform_init)(struct sdhci_host *host);
- 	void    (*card_event)(struct sdhci_host *host);
-@@ -397,6 +393,16 @@
- extern void sdhci_send_command(struct sdhci_host *host,
- 				struct mmc_command *cmd);
- 
-+static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
-+{
-+	return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
-+}
-+
-+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
-+void sdhci_set_bus_width(struct sdhci_host *host, int width);
-+void sdhci_reset(struct sdhci_host *host, u8 mask);
-+void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
-+
- #ifdef CONFIG_PM
- extern int sdhci_suspend_host(struct sdhci_host *host);
- extern int sdhci_resume_host(struct sdhci_host *host);
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-arasan.c linux-3.15-rc6/drivers/mmc/host/sdhci-of-arasan.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-arasan.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-of-arasan.c	2014-05-23 11:26:48.304940032 +0200
-@@ -52,8 +52,12 @@
- }
- 
- static struct sdhci_ops sdhci_arasan_ops = {
-+	.set_clock = sdhci_set_clock,
- 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
- 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static struct sdhci_pltfm_data sdhci_arasan_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-esdhc.c linux-3.15-rc6/drivers/mmc/host/sdhci-of-esdhc.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-esdhc.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-of-esdhc.c	2014-05-23 11:26:48.304940032 +0200
-@@ -199,13 +199,14 @@
- 
- static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
- {
--
- 	int pre_div = 2;
- 	int div = 1;
- 	u32 temp;
- 
-+	host->mmc->actual_clock = 0;
-+
- 	if (clock == 0)
--		goto out;
-+		return;
- 
- 	/* Workaround to reduce the clock frequency for p1010 esdhc */
- 	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
-@@ -238,24 +239,8 @@
- 		| (pre_div << ESDHC_PREDIV_SHIFT));
- 	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- 	mdelay(1);
--out:
--	host->clock = clock;
- }
- 
--#ifdef CONFIG_PM
--static u32 esdhc_proctl;
--static void esdhc_of_suspend(struct sdhci_host *host)
--{
--	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
--}
--
--static void esdhc_of_resume(struct sdhci_host *host)
--{
--	esdhc_of_enable_dma(host);
--	sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
--}
--#endif
--
- static void esdhc_of_platform_init(struct sdhci_host *host)
- {
- 	u32 vvn;
-@@ -269,7 +254,7 @@
- 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
- }
- 
--static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
-+static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
- {
- 	u32 ctrl;
- 
-@@ -289,8 +274,6 @@
- 
- 	clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
- 			ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
--
--	return 0;
- }
- 
- static const struct sdhci_ops sdhci_esdhc_ops = {
-@@ -305,13 +288,46 @@
- 	.get_max_clock = esdhc_of_get_max_clock,
- 	.get_min_clock = esdhc_of_get_min_clock,
- 	.platform_init = esdhc_of_platform_init,
--#ifdef CONFIG_PM
--	.platform_suspend = esdhc_of_suspend,
--	.platform_resume = esdhc_of_resume,
--#endif
- 	.adma_workaround = esdhci_of_adma_workaround,
--	.platform_bus_width = esdhc_pltfm_bus_width,
-+	.set_bus_width = esdhc_pltfm_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
-+};
-+
-+#ifdef CONFIG_PM
-+
-+static u32 esdhc_proctl;
-+static int esdhc_of_suspend(struct device *dev)
-+{
-+	struct sdhci_host *host = dev_get_drvdata(dev);
-+
-+	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
-+
-+	return sdhci_suspend_host(host);
-+}
-+
-+static void esdhc_of_resume(device *dev)
-+{
-+	struct sdhci_host *host = dev_get_drvdata(dev);
-+	int ret = sdhci_resume_host(host);
-+
-+	if (ret == 0) {
-+		/* Isn't this already done by sdhci_resume_host() ? --rmk */
-+		esdhc_of_enable_dma(host);
-+		sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
-+	}
-+
-+	return ret;
-+}
-+
-+static const struct dev_pm_ops esdhc_pmops = {
-+	.suspend	= esdhci_of_suspend,
-+	.resume		= esdhci_of_resume,
- };
-+#define ESDHC_PMOPS (&esdhc_pmops)
-+#else
-+#define ESDHC_PMOPS NULL
-+#endif
- 
- static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
- 	/*
-@@ -374,7 +390,7 @@
- 		.name = "sdhci-esdhc",
- 		.owner = THIS_MODULE,
- 		.of_match_table = sdhci_esdhc_of_match,
--		.pm = SDHCI_PLTFM_PMOPS,
-+		.pm = ESDHC_PMOPS,
- 	},
- 	.probe = sdhci_esdhc_probe,
- 	.remove = sdhci_esdhc_remove,
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-hlwd.c linux-3.15-rc6/drivers/mmc/host/sdhci-of-hlwd.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-of-hlwd.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-of-hlwd.c	2014-05-23 11:26:48.304940032 +0200
-@@ -58,6 +58,10 @@
- 	.write_l = sdhci_hlwd_writel,
- 	.write_w = sdhci_hlwd_writew,
- 	.write_b = sdhci_hlwd_writeb,
-+	.set_clock = sdhci_set_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pci.c linux-3.15-rc6/drivers/mmc/host/sdhci-pci.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pci.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-pci.c	2014-05-23 11:26:48.304940032 +0200
-@@ -1031,7 +1031,7 @@
- 	return 0;
- }
- 
--static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
-+static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width)
- {
- 	u8 ctrl;
- 
-@@ -1052,8 +1052,6 @@
- 	}
- 
- 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
--
--	return 0;
- }
- 
- static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host)
-@@ -1080,8 +1078,11 @@
- }
- 
- static const struct sdhci_ops sdhci_pci_ops = {
-+	.set_clock	= sdhci_set_clock,
- 	.enable_dma	= sdhci_pci_enable_dma,
--	.platform_bus_width	= sdhci_pci_bus_width,
-+	.set_bus_width	= sdhci_pci_set_bus_width,
-+	.reset		= sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- 	.hw_reset		= sdhci_pci_hw_reset,
- };
- 
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pltfm.c linux-3.15-rc6/drivers/mmc/host/sdhci-pltfm.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pltfm.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-pltfm.c	2014-05-23 11:26:48.308940045 +0200
-@@ -45,6 +45,10 @@
- EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
- 
- static const struct sdhci_ops sdhci_pltfm_ops = {
-+	.set_clock = sdhci_set_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- #ifdef CONFIG_OF
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pxav2.c linux-3.15-rc6/drivers/mmc/host/sdhci-pxav2.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pxav2.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-pxav2.c	2014-05-23 11:26:48.308940045 +0200
-@@ -51,11 +51,13 @@
- #define MMC_CARD		0x1000
- #define MMC_WIDTH		0x0100
- 
--static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
-+static void pxav2_reset(struct sdhci_host *host, u8 mask)
- {
- 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
- 
-+	sdhci_reset(host, mask);
-+
- 	if (mask == SDHCI_RESET_ALL) {
- 		u16 tmp = 0;
- 
-@@ -88,7 +90,7 @@
- 	}
- }
- 
--static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
-+static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
- {
- 	u8 ctrl;
- 	u16 tmp;
-@@ -107,14 +109,14 @@
- 	}
- 	writew(tmp, host->ioaddr + SD_CE_ATA_2);
- 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
--
--	return 0;
- }
- 
- static const struct sdhci_ops pxav2_sdhci_ops = {
-+	.set_clock     = sdhci_set_clock,
- 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
--	.platform_reset_exit = pxav2_set_private_registers,
--	.platform_bus_width = pxav2_mmc_set_width,
-+	.set_bus_width = pxav2_mmc_set_bus_width,
-+	.reset         = pxav2_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- #ifdef CONFIG_OF
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pxav3.c linux-3.15-rc6/drivers/mmc/host/sdhci-pxav3.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-pxav3.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-pxav3.c	2014-05-23 11:26:48.308940045 +0200
-@@ -112,11 +112,13 @@
- 	return 0;
- }
- 
--static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
-+static void pxav3_reset(struct sdhci_host *host, u8 mask)
- {
- 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
- 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
- 
-+	sdhci_reset(host, mask);
-+
- 	if (mask == SDHCI_RESET_ALL) {
- 		/*
- 		 * tune timing of read data/command when crc error happen
-@@ -184,7 +186,7 @@
- 	pxa->power_mode = power_mode;
- }
- 
--static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
-+static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
- {
- 	u16 ctrl_2;
- 
-@@ -218,15 +220,16 @@
- 	dev_dbg(mmc_dev(host->mmc),
- 		"%s uhs = %d, ctrl_2 = %04X\n",
- 		__func__, uhs, ctrl_2);
--
--	return 0;
- }
- 
- static const struct sdhci_ops pxav3_sdhci_ops = {
--	.platform_reset_exit = pxav3_set_private_registers,
-+	.set_clock = sdhci_set_clock,
- 	.set_uhs_signaling = pxav3_set_uhs_signaling,
- 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
- 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = pxav3_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-s3c.c linux-3.15-rc6/drivers/mmc/host/sdhci-s3c.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-s3c.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-s3c.c	2014-05-23 11:26:48.308940045 +0200
-@@ -58,6 +58,8 @@
- 	struct clk		*clk_io;
- 	struct clk		*clk_bus[MAX_BUS_CLK];
- 	unsigned long		clk_rates[MAX_BUS_CLK];
-+
-+	bool			no_divider;
- };
- 
- /**
-@@ -70,6 +72,7 @@
-  */
- struct sdhci_s3c_drv_data {
- 	unsigned int	sdhci_quirks;
-+	bool		no_divider;
- };
- 
- static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
-@@ -119,7 +122,7 @@
- 	 * If controller uses a non-standard clock division, find the best clock
- 	 * speed possible with selected clock source and skip the division.
- 	 */
--	if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
-+	if (ourhost->no_divider) {
- 		rate = clk_round_rate(clksrc, wanted);
- 		return wanted - rate;
- 	}
-@@ -161,9 +164,13 @@
- 	int src;
- 	u32 ctrl;
- 
-+	host->mmc->actual_clock = 0;
-+
- 	/* don't bother if the clock is going off. */
--	if (clock == 0)
-+	if (clock == 0) {
-+		sdhci_set_clock(host, clock);
- 		return;
-+	}
- 
- 	for (src = 0; src < MAX_BUS_CLK; src++) {
- 		delta = sdhci_s3c_consider_clock(ourhost, src, clock);
-@@ -215,6 +222,8 @@
- 	if (clock < 25 * 1000000)
- 		ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
- 	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
-+
-+	sdhci_set_clock(host, clock);
- }
- 
- /**
-@@ -295,10 +304,11 @@
- 	unsigned long timeout;
- 	u16 clk = 0;
- 
-+	host->mmc->actual_clock = 0;
-+
- 	/* If the clock is going off, set to 0 at clock control register */
- 	if (clock == 0) {
- 		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
--		host->clock = clock;
- 		return;
- 	}
- 
-@@ -306,8 +316,6 @@
- 
- 	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
- 
--	host->clock = clock;
--
- 	clk = SDHCI_CLOCK_INT_EN;
- 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- 
-@@ -329,14 +337,14 @@
- }
- 
- /**
-- * sdhci_s3c_platform_bus_width - support 8bit buswidth
-+ * sdhci_s3c_set_bus_width - support 8bit buswidth
-  * @host: The SDHCI host being queried
-  * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
-  *
-  * We have 8-bit width support but is not a v3 controller.
-  * So we add platform_bus_width() and support 8bit width.
-  */
--static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
-+static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width)
- {
- 	u8 ctrl;
- 
-@@ -358,15 +366,15 @@
- 	}
- 
- 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
--
--	return 0;
- }
- 
- static struct sdhci_ops sdhci_s3c_ops = {
- 	.get_max_clock		= sdhci_s3c_get_max_clk,
- 	.set_clock		= sdhci_s3c_set_clock,
- 	.get_min_clock		= sdhci_s3c_get_min_clock,
--	.platform_bus_width	= sdhci_s3c_platform_bus_width,
-+	.set_bus_width		= sdhci_s3c_set_bus_width,
-+	.reset			= sdhci_reset,
-+	.set_uhs_signaling	= sdhci_set_uhs_signaling,
- };
- 
- static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
-@@ -606,8 +614,10 @@
- 	/* Setup quirks for the controller */
- 	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
- 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
--	if (drv_data)
-+	if (drv_data) {
- 		host->quirks |= drv_data->sdhci_quirks;
-+		sc->no_divider = drv_data->no_divider;
-+	}
- 
- #ifndef CONFIG_MMC_SDHCI_S3C_DMA
- 
-@@ -656,7 +666,7 @@
- 	 * If controller does not have internal clock divider,
- 	 * we can use overriding functions instead of default.
- 	 */
--	if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
-+	if (sc->no_divider) {
- 		sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
- 		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
- 		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
-@@ -797,7 +807,7 @@
- 
- #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
- static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
--	.sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
-+	.no_divider = true,
- };
- #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
- #else
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-sirf.c linux-3.15-rc6/drivers/mmc/host/sdhci-sirf.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-sirf.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-sirf.c	2014-05-23 11:26:48.308940045 +0200
-@@ -28,7 +28,11 @@
- }
- 
- static struct sdhci_ops sdhci_sirf_ops = {
-+	.set_clock = sdhci_set_clock,
- 	.get_max_clock	= sdhci_sirf_get_max_clk,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static struct sdhci_pltfm_data sdhci_sirf_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-spear.c linux-3.15-rc6/drivers/mmc/host/sdhci-spear.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-spear.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-spear.c	2014-05-23 11:26:48.308940045 +0200
-@@ -38,7 +38,10 @@
- 
- /* sdhci ops */
- static const struct sdhci_ops sdhci_pltfm_ops = {
--	/* Nothing to do for now. */
-+	.set_clock = sdhci_set_clock,
-+	.set_bus_width = sdhci_set_bus_width,
-+	.reset = sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- #ifdef CONFIG_OF
-diff -Nur linux-3.15-rc6.orig/drivers/mmc/host/sdhci-tegra.c linux-3.15-rc6/drivers/mmc/host/sdhci-tegra.c
---- linux-3.15-rc6.orig/drivers/mmc/host/sdhci-tegra.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/mmc/host/sdhci-tegra.c	2014-05-23 11:26:48.308940045 +0200
-@@ -48,19 +48,6 @@
- 	int power_gpio;
- };
- 
--static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
--{
--	u32 val;
--
--	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
--		/* Use wp_gpio here instead? */
--		val = readl(host->ioaddr + reg);
--		return val | SDHCI_WRITE_PROTECT;
--	}
--
--	return readl(host->ioaddr + reg);
--}
--
- static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
- {
- 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-@@ -108,12 +95,14 @@
- 	return mmc_gpio_get_ro(host->mmc);
- }
- 
--static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
-+static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
- {
- 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- 	struct sdhci_tegra *tegra_host = pltfm_host->priv;
- 	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
- 
-+	sdhci_reset(host, mask);
-+
- 	if (!(mask & SDHCI_RESET_ALL))
- 		return;
- 
-@@ -127,7 +116,7 @@
- 	}
- }
- 
--static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
-+static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
- {
- 	u32 ctrl;
- 
-@@ -144,16 +133,16 @@
- 			ctrl &= ~SDHCI_CTRL_4BITBUS;
- 	}
- 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
--	return 0;
- }
- 
- static const struct sdhci_ops tegra_sdhci_ops = {
- 	.get_ro     = tegra_sdhci_get_ro,
--	.read_l     = tegra_sdhci_readl,
- 	.read_w     = tegra_sdhci_readw,
- 	.write_l    = tegra_sdhci_writel,
--	.platform_bus_width = tegra_sdhci_buswidth,
--	.platform_reset_exit = tegra_sdhci_reset_exit,
-+	.set_clock  = sdhci_set_clock,
-+	.set_bus_width = tegra_sdhci_set_bus_width,
-+	.reset      = tegra_sdhci_reset,
-+	.set_uhs_signaling = sdhci_set_uhs_signaling,
- };
- 
- static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
-diff -Nur linux-3.15-rc6.orig/drivers/net/ethernet/freescale/fec.h linux-3.15-rc6/drivers/net/ethernet/freescale/fec.h
---- linux-3.15-rc6.orig/drivers/net/ethernet/freescale/fec.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/net/ethernet/freescale/fec.h	2014-05-23 11:26:48.308940045 +0200
-@@ -14,6 +14,7 @@
- /****************************************************************************/
- 
- #include <linux/clocksource.h>
-+#include <linux/mutex.h>
- #include <linux/net_tstamp.h>
- #include <linux/ptp_clock_kernel.h>
- 
-@@ -170,6 +171,11 @@
- 	unsigned short res0[4];
- };
- 
-+union bufdesc_u {
-+	struct bufdesc bd;
-+	struct bufdesc_ex ebd;
-+};
-+
- /*
-  *	The following definitions courtesy of commproc.h, which where
-  *	Copyright (c) 1997 Dan Malek (dmalek@jlc.net).
-@@ -202,6 +208,7 @@
- #define BD_ENET_RX_OV           ((ushort)0x0002)
- #define BD_ENET_RX_CL           ((ushort)0x0001)
- #define BD_ENET_RX_STATS        ((ushort)0x013f)        /* All status bits */
-+#define BD_ENET_RX_ERROR	((ushort)0x003f)
- 
- /* Enhanced buffer descriptor control/status used by Ethernet receive */
- #define BD_ENET_RX_VLAN         0x00000004
-@@ -224,10 +231,17 @@
- #define BD_ENET_TX_STATS        ((ushort)0x03ff)        /* All status bits */
- 
- /*enhanced buffer descriptor control/status used by Ethernet transmit*/
--#define BD_ENET_TX_INT          0x40000000
--#define BD_ENET_TX_TS           0x20000000
--#define BD_ENET_TX_PINS         0x10000000
--#define BD_ENET_TX_IINS         0x08000000
-+#define BD_ENET_TX_INT          BIT(30)
-+#define BD_ENET_TX_TS           BIT(29)
-+#define BD_ENET_TX_PINS         BIT(28)
-+#define BD_ENET_TX_IINS         BIT(27)
-+#define BD_ENET_TX_TXE		BIT(15)
-+#define BD_ENET_TX_UE		BIT(13)
-+#define BD_ENET_TX_EE		BIT(12)
-+#define BD_ENET_TX_FE		BIT(11)
-+#define BD_ENET_TX_LCE		BIT(10)
-+#define BD_ENET_TX_OE		BIT(9)
-+#define BD_ENET_TX_TSE		BIT(8)
- 
- 
- /* This device has up to three irqs on some platforms */
-@@ -240,28 +254,20 @@
-  * the skbuffer directly.
-  */
- 
--#define FEC_ENET_RX_PAGES	8
-+#define FEC_ENET_RX_PAGES	64
- #define FEC_ENET_RX_FRSIZE	2048
- #define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
- #define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
- #define FEC_ENET_TX_FRSIZE	2048
- #define FEC_ENET_TX_FRPPG	(PAGE_SIZE / FEC_ENET_TX_FRSIZE)
--#define TX_RING_SIZE		16	/* Must be power of two */
--#define TX_RING_MOD_MASK	15	/*   for this to work */
-+#define TX_RING_SIZE		128	/* Must be power of two */
- 
- #define BD_ENET_RX_INT          0x00800000
- #define BD_ENET_RX_PTP          ((ushort)0x0400)
- #define BD_ENET_RX_ICE		0x00000020
- #define BD_ENET_RX_PCR		0x00000010
--#define FLAG_RX_CSUM_ENABLED	(BD_ENET_RX_ICE | BD_ENET_RX_PCR)
- #define FLAG_RX_CSUM_ERROR	(BD_ENET_RX_ICE | BD_ENET_RX_PCR)
- 
--struct fec_enet_delayed_work {
--	struct delayed_work delay_work;
--	bool timeout;
--	bool trig_tx;
--};
--
- /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
-  * tx_bd_base always point to the base of the buffer descriptors.  The
-  * cur_rx and cur_tx point to the currently available buffer.
-@@ -281,27 +287,33 @@
- 	struct clk *clk_enet_out;
- 	struct clk *clk_ptp;
- 
-+	unsigned char tx_page_map[TX_RING_SIZE];
- 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
- 	unsigned char *tx_bounce[TX_RING_SIZE];
- 	struct	sk_buff *tx_skbuff[TX_RING_SIZE];
- 	struct	sk_buff *rx_skbuff[RX_RING_SIZE];
- 
- 	/* CPM dual port RAM relative addresses */
--	dma_addr_t	bd_dma;
-+	dma_addr_t	rx_bd_dma;
-+	dma_addr_t	tx_bd_dma;
- 	/* Address of Rx and Tx buffers */
--	struct bufdesc	*rx_bd_base;
--	struct bufdesc	*tx_bd_base;
-+	union bufdesc_u	*rx_bd_base;
-+	union bufdesc_u	*tx_bd_base;
- 	/* The next free ring entry */
--	struct bufdesc	*cur_rx, *cur_tx;
--	/* The ring entries to be free()ed */
--	struct bufdesc	*dirty_tx;
-+	unsigned short tx_next;
-+	unsigned short tx_dirty;
-+	unsigned short tx_min;
-+	unsigned short rx_next;
- 
- 	unsigned short tx_ring_size;
- 	unsigned short rx_ring_size;
- 
-+	unsigned char flags;
-+
-+	struct mutex mutex;
-+
- 	struct	platform_device *pdev;
- 
--	int	opened;
- 	int	dev_id;
- 
- 	/* Phylib and MDIO interface */
-@@ -315,11 +327,12 @@
- 	int	speed;
- 	struct	completion mdio_done;
- 	int	irq[FEC_IRQ_NUM];
--	int	bufdesc_ex;
--	int	pause_flag;
-+	unsigned short pause_flag;
-+	unsigned short pause_mode;
- 
- 	struct	napi_struct napi;
--	int	csum_flags;
-+
-+	struct work_struct tx_timeout_work;
- 
- 	struct ptp_clock *ptp_clock;
- 	struct ptp_clock_info ptp_caps;
-@@ -333,8 +346,8 @@
- 	int hwts_rx_en;
- 	int hwts_tx_en;
- 	struct timer_list time_keep;
--	struct fec_enet_delayed_work delay_work;
- 	struct regulator *reg_phy;
-+	unsigned long quirks;
- };
- 
- void fec_ptp_init(struct platform_device *pdev);
-diff -Nur linux-3.15-rc6.orig/drivers/net/ethernet/freescale/fec_main.c linux-3.15-rc6/drivers/net/ethernet/freescale/fec_main.c
---- linux-3.15-rc6.orig/drivers/net/ethernet/freescale/fec_main.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/net/ethernet/freescale/fec_main.c	2014-05-23 11:26:48.312940058 +0200
-@@ -33,12 +33,6 @@
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
--#include <linux/in.h>
--#include <linux/ip.h>
--#include <net/ip.h>
--#include <linux/tcp.h>
--#include <linux/udp.h>
--#include <linux/icmp.h>
- #include <linux/spinlock.h>
- #include <linux/workqueue.h>
- #include <linux/bitops.h>
-@@ -91,16 +85,8 @@
- #define FEC_QUIRK_HAS_CSUM		(1 << 5)
- /* Controller has hardware vlan support */
- #define FEC_QUIRK_HAS_VLAN		(1 << 6)
--/* ENET IP errata ERR006358
-- *
-- * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
-- * detected as not set during a prior frame transmission, then the
-- * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
-- * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
-- * frames not being transmitted until there is a 0-to-1 transition on
-- * ENET_TDAR[TDAR].
-- */
--#define FEC_QUIRK_ERR006358            (1 << 7)
-+/* Controller has ability to offset rx packets */
-+#define FEC_QUIRK_RX_SHIFT16            (1 << 8)
- 
- static struct platform_device_id fec_devtype[] = {
- 	{
-@@ -120,7 +106,7 @@
- 		.name = "imx6q-fec",
- 		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
- 				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
--				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358,
-+				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_RX_SHIFT16,
- 	}, {
- 		.name = "mvf600-fec",
- 		.driver_data = FEC_QUIRK_ENET_MAC,
-@@ -172,9 +158,15 @@
- #endif
- #endif /* CONFIG_M5272 */
- 
--#if (((RX_RING_SIZE + TX_RING_SIZE) * 32) > PAGE_SIZE)
--#error "FEC: descriptor ring size constants too large"
-+#if RX_RING_SIZE * 32 > PAGE_SIZE
-+#error "FEC: receive descriptor ring size too large"
- #endif
-+#if TX_RING_SIZE * 32 > PAGE_SIZE
-+#error "FEC: transmit descriptor ring size too large"
-+#endif
-+
-+/* Minimum TX ring size when using NETIF_F_SG */
-+#define TX_RING_SIZE_MIN_SG (2 * (MAX_SKB_FRAGS + 1))
- 
- /* Interrupt events/masks. */
- #define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
-@@ -200,6 +192,7 @@
- /* FEC receive acceleration */
- #define FEC_RACC_IPDIS		(1 << 1)
- #define FEC_RACC_PRODIS		(1 << 2)
-+#define FEC_RACC_SHIFT16	BIT(7)
- #define FEC_RACC_OPTIONS	(FEC_RACC_IPDIS | FEC_RACC_PRODIS)
- 
- /*
-@@ -228,62 +221,60 @@
- /* Transmitter timeout */
- #define TX_TIMEOUT (2 * HZ)
- 
--#define FEC_PAUSE_FLAG_AUTONEG	0x1
--#define FEC_PAUSE_FLAG_ENABLE	0x2
-+/* pause mode/flag */
-+#define FEC_PAUSE_FLAG_AUTONEG	BIT(0)
-+#define FEC_PAUSE_FLAG_RX	BIT(1)
-+#define FEC_PAUSE_FLAG_TX	BIT(2)
-+
-+/* flags */
-+#define FEC_FLAG_BUFDESC_EX	BIT(0)
-+#define FEC_FLAG_RX_CSUM	BIT(1)
-+#define FEC_FLAG_RX_VLAN	BIT(2)
- 
- static int mii_cnt;
- 
--static inline
--struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
-+static unsigned copybreak = 200;
-+module_param(copybreak, uint, 0644);
-+MODULE_PARM_DESC(copybreak,
-+		 "Maximum size of packet that is copied to a new buffer on receive");
-+
-+static bool fec_enet_rx_zerocopy(struct fec_enet_private *fep, unsigned pktlen)
- {
--	struct bufdesc *new_bd = bdp + 1;
--	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1;
--	struct bufdesc_ex *ex_base;
--	struct bufdesc *base;
--	int ring_size;
--
--	if (bdp >= fep->tx_bd_base) {
--		base = fep->tx_bd_base;
--		ring_size = fep->tx_ring_size;
--		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
--	} else {
--		base = fep->rx_bd_base;
--		ring_size = fep->rx_ring_size;
--		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
--	}
-+#ifndef CONFIG_M5272
-+	if (fep->quirks & FEC_QUIRK_RX_SHIFT16 && pktlen >= copybreak)
-+		return true;
-+#endif
-+	return false;
-+}
- 
--	if (fep->bufdesc_ex)
--		return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ?
--			ex_base : ex_new_bd);
-+static union bufdesc_u *
-+fec_enet_tx_get(unsigned index, struct fec_enet_private *fep)
-+{
-+	union bufdesc_u *base = fep->tx_bd_base;
-+	union bufdesc_u *bdp;
-+
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX)
-+		bdp = (union bufdesc_u *)(&base->ebd + index);
- 	else
--		return (new_bd >= (base + ring_size)) ?
--			base : new_bd;
-+		bdp = (union bufdesc_u *)(&base->bd + index);
-+
-+	return bdp;
- }
- 
--static inline
--struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct fec_enet_private *fep)
-+static union bufdesc_u *
-+fec_enet_rx_get(unsigned index, struct fec_enet_private *fep)
- {
--	struct bufdesc *new_bd = bdp - 1;
--	struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1;
--	struct bufdesc_ex *ex_base;
--	struct bufdesc *base;
--	int ring_size;
--
--	if (bdp >= fep->tx_bd_base) {
--		base = fep->tx_bd_base;
--		ring_size = fep->tx_ring_size;
--		ex_base = (struct bufdesc_ex *)fep->tx_bd_base;
--	} else {
--		base = fep->rx_bd_base;
--		ring_size = fep->rx_ring_size;
--		ex_base = (struct bufdesc_ex *)fep->rx_bd_base;
--	}
-+	union bufdesc_u *base = fep->rx_bd_base;
-+	union bufdesc_u *bdp;
-+
-+	index &= fep->rx_ring_size - 1;
- 
--	if (fep->bufdesc_ex)
--		return (struct bufdesc *)((ex_new_bd < ex_base) ?
--			(ex_new_bd + ring_size) : ex_new_bd);
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX)
-+		bdp = (union bufdesc_u *)(&base->ebd + index);
- 	else
--		return (new_bd < base) ? (new_bd + ring_size) : new_bd;
-+		bdp = (union bufdesc_u *)(&base->bd + index);
-+
-+	return bdp;
- }
- 
- static void *swap_buffer(void *bufaddr, int len)
-@@ -297,13 +288,47 @@
- 	return bufaddr;
- }
- 
-+static void fec_dump(struct net_device *ndev)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	union bufdesc_u *bdp;
-+	unsigned index = 0;
-+
-+	netdev_info(ndev, "TX ring dump\n");
-+	pr_info("Nr     SC     addr       len  SKB\n");
-+
-+	for (index = 0; index < fep->tx_ring_size; index++) {
-+		bdp = fec_enet_tx_get(index, fep);
-+
-+		pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p",
-+			index,
-+			index == fep->tx_next ? 'S' : ' ',
-+			index == fep->tx_dirty ? 'H' : ' ',
-+			bdp->bd.cbd_sc, bdp->bd.cbd_bufaddr,
-+			bdp->bd.cbd_datlen,
-+			fep->tx_skbuff[index]);
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX)
-+			pr_cont(" %08lx", bdp->ebd.cbd_esc);
-+		pr_cont("\n");
-+	}
-+}
-+
- static int
- fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
- {
-+	int csum_start;
-+
- 	/* Only run for packets requiring a checksum. */
- 	if (skb->ip_summed != CHECKSUM_PARTIAL)
- 		return 0;
- 
-+	csum_start = skb_checksum_start_offset(skb);
-+	if (csum_start + skb->csum_offset > skb_headlen(skb)) {
-+		netdev_err(ndev, "checksum outside skb head: headlen %u start %u offset %u\n",
-+			   skb_headlen(skb), csum_start, skb->csum_offset);
-+		return -1;
-+	}
-+
- 	if (unlikely(skb_cow_head(skb, 0)))
- 		return -1;
- 
-@@ -312,23 +337,56 @@
- 	return 0;
- }
- 
-+static void
-+fec_enet_tx_unmap(unsigned index, union bufdesc_u *bdp, struct fec_enet_private *fep)
-+{
-+	dma_addr_t addr = bdp->bd.cbd_bufaddr;
-+	unsigned length = bdp->bd.cbd_datlen;
-+
-+	bdp->bd.cbd_bufaddr = 0;
-+
-+	if (fep->tx_page_map[index])
-+		dma_unmap_page(&fep->pdev->dev, addr, length, DMA_TO_DEVICE);
-+	else
-+		dma_unmap_single(&fep->pdev->dev, addr, length, DMA_TO_DEVICE);
-+}
-+
-+static void
-+fec_enet_tx_unmap_range(unsigned index, unsigned last, struct fec_enet_private *fep)
-+{
-+	union bufdesc_u *bdp;
-+
-+	do {
-+		if (last == 0)
-+			last = fep->tx_ring_size;
-+		last--;
-+
-+		bdp = fec_enet_tx_get(last, fep);
-+		fec_enet_tx_unmap(last, bdp, fep);
-+	} while (index != last);
-+}
-+
-+static unsigned ring_free(unsigned ins, unsigned rem, unsigned size)
-+{
-+	int num = rem - ins;
-+	return num < 0 ? num + size : num;
-+}
-+
- static netdev_tx_t
- fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
--	struct bufdesc *bdp, *bdp_pre;
-+	union bufdesc_u *bdp;
- 	void *bufaddr;
- 	unsigned short	status;
--	unsigned int index;
-+	unsigned index, last, length, cbd_esc;
-+	int f, nr_frags = skb_shinfo(skb)->nr_frags;
-+	dma_addr_t addr;
- 
- 	/* Fill in a Tx ring entry */
--	bdp = fep->cur_tx;
--
--	status = bdp->cbd_sc;
-+	index = fep->tx_next;
- 
--	if (status & BD_ENET_TX_READY) {
-+	if (ring_free(index, fep->tx_dirty, fep->tx_ring_size) < 1 + nr_frags) {
- 		/* Ooops.  All transmit buffers are full.  Bail out.
- 		 * This should not happen, since ndev->tbusy should be set.
- 		 */
-@@ -342,26 +400,17 @@
- 		return NETDEV_TX_OK;
- 	}
- 
--	/* Clear all of the status flags */
--	status &= ~BD_ENET_TX_STATS;
--
- 	/* Set buffer length and buffer pointer */
- 	bufaddr = skb->data;
--	bdp->cbd_datlen = skb->len;
-+	length = skb_headlen(skb);
- 
- 	/*
- 	 * On some FEC implementations data must be aligned on
- 	 * 4-byte boundaries. Use bounce buffers to copy data
- 	 * and get it aligned. Ugh.
- 	 */
--	if (fep->bufdesc_ex)
--		index = (struct bufdesc_ex *)bdp -
--			(struct bufdesc_ex *)fep->tx_bd_base;
--	else
--		index = bdp - fep->tx_bd_base;
--
- 	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
--		memcpy(fep->tx_bounce[index], skb->data, skb->len);
-+		memcpy(fep->tx_bounce[index], skb->data, length);
- 		bufaddr = fep->tx_bounce[index];
- 	}
- 
-@@ -370,75 +419,127 @@
- 	 * the system that it's running on. As the result, driver has to
- 	 * swap every frame going to and coming from the controller.
- 	 */
--	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
--		swap_buffer(bufaddr, skb->len);
-+	if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
-+		swap_buffer(bufaddr, length);
- 
--	/* Save skb pointer */
--	fep->tx_skbuff[index] = skb;
-+	/* Push the data cache so the CPM does not get stale memory data. */
-+	addr = dma_map_single(&fep->pdev->dev, bufaddr, length, DMA_TO_DEVICE);
-+	if (dma_mapping_error(&fep->pdev->dev, addr))
-+		goto release;
-+
-+	bdp = fec_enet_tx_get(index, fep);
-+	bdp->bd.cbd_datlen = length;
-+	bdp->bd.cbd_bufaddr = addr;
- 
--	/* Push the data cache so the CPM does not get stale memory
--	 * data.
--	 */
--	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
--			skb->len, DMA_TO_DEVICE);
--	if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
--		bdp->cbd_bufaddr = 0;
--		fep->tx_skbuff[index] = NULL;
--		dev_kfree_skb_any(skb);
--		if (net_ratelimit())
--			netdev_err(ndev, "Tx DMA memory map failed\n");
--		return NETDEV_TX_OK;
--	}
-+	fep->tx_page_map[index] = 0;
- 
--	if (fep->bufdesc_ex) {
--
--		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
--		ebdp->cbd_bdu = 0;
-+	cbd_esc = BD_ENET_TX_INT;
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX) {
- 		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
- 			fep->hwts_tx_en)) {
--			ebdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
-+			cbd_esc |= BD_ENET_TX_TS;
- 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
- 		} else {
--			ebdp->cbd_esc = BD_ENET_TX_INT;
--
- 			/* Enable protocol checksum flags
- 			 * We do not bother with the IP Checksum bits as they
- 			 * are done by the kernel
- 			 */
- 			if (skb->ip_summed == CHECKSUM_PARTIAL)
--				ebdp->cbd_esc |= BD_ENET_TX_PINS;
-+				cbd_esc |= BD_ENET_TX_PINS;
-+		}
-+		bdp->ebd.cbd_bdu = 0;
-+		bdp->ebd.cbd_esc = cbd_esc;
-+	}
-+
-+	for (last = index, f = 0; f < nr_frags; f++) {
-+		const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[f];
-+
-+		if (++last >= fep->tx_ring_size)
-+			last = 0;
-+
-+		length = skb_frag_size(frag);
-+
-+		/* If the alignment is unsuitable, we need to bounce. */
-+		if (frag->page_offset & FEC_ALIGNMENT) {
-+			unsigned char *bounce = fep->tx_bounce[last];
-+
-+			/* FIXME: highdma? */
-+			memcpy(bounce, skb_frag_address(frag), length);
-+
-+			addr = dma_map_single(&fep->pdev->dev, bounce,
-+					      length, DMA_TO_DEVICE);
-+			fep->tx_page_map[last] = 0;
-+		} else {
-+			addr = skb_frag_dma_map(&fep->pdev->dev, frag, 0,
-+						length, DMA_TO_DEVICE);
-+			fep->tx_page_map[last] = 1;
-+		}
-+
-+		if (dma_mapping_error(&fep->pdev->dev, addr))
-+			goto release_frags;
-+
-+		bdp = fec_enet_tx_get(last, fep);
-+		bdp->bd.cbd_datlen = length;
-+		bdp->bd.cbd_bufaddr = addr;
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX) {
-+			bdp->ebd.cbd_esc = cbd_esc;
-+			bdp->ebd.cbd_bdu = 0;
- 		}
- 	}
- 
-+	/* Save skb pointer */
-+	fep->tx_skbuff[last] = skb;
-+
-+	/*
-+	 * We need the preceding stores to the descriptor to complete
-+	 * before updating the status field, which hands it over to the
-+	 * hardware.  The corresponding rmb() is "in the hardware".
-+	 */
-+	wmb();
-+
- 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
- 	 * it's the last BD of the frame, and to put the CRC on the end.
- 	 */
--	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
--			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
--	bdp->cbd_sc = status;
--
--	bdp_pre = fec_enet_get_prevdesc(bdp, fep);
--	if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
--	    !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
--		fep->delay_work.trig_tx = true;
--		schedule_delayed_work(&(fep->delay_work.delay_work),
--					msecs_to_jiffies(1));
-+	status = bdp->bd.cbd_sc & BD_ENET_TX_WRAP;
-+	bdp->bd.cbd_sc = status | BD_ENET_TX_READY | BD_ENET_TX_INTR |
-+			 BD_ENET_TX_LAST | BD_ENET_TX_TC;
-+
-+	/* Now walk backwards setting the TX_READY on each fragment */
-+	for (f = nr_frags - 1; f >= 0; f--) {
-+		unsigned i = index + f;
-+
-+		if (i >= fep->tx_ring_size)
-+			i -= fep->tx_ring_size;
-+
-+		bdp = fec_enet_tx_get(i, fep);
-+		status = bdp->bd.cbd_sc & BD_ENET_TX_WRAP;
-+		bdp->bd.cbd_sc = status | BD_ENET_TX_READY | BD_ENET_TX_INTR;
- 	}
- 
--	/* If this was the last BD in the ring, start at the beginning again. */
--	bdp = fec_enet_get_nextdesc(bdp, fep);
--
- 	skb_tx_timestamp(skb);
-+	netdev_sent_queue(ndev, skb->len);
-+
-+	if (++last >= fep->tx_ring_size)
-+		last = 0;
- 
--	fep->cur_tx = bdp;
-+	fep->tx_next = last;
- 
--	if (fep->cur_tx == fep->dirty_tx)
-+	if (ring_free(last, fep->tx_dirty, fep->tx_ring_size) < fep->tx_min)
- 		netif_stop_queue(ndev);
- 
- 	/* Trigger transmission start */
--	writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-+	if (readl(fep->hwp + FEC_X_DES_ACTIVE) == 0)
-+		writel(0, fep->hwp + FEC_X_DES_ACTIVE);
- 
- 	return NETDEV_TX_OK;
-+
-+ release_frags:
-+	fec_enet_tx_unmap_range(index, last, fep);
-+ release:
-+	dev_kfree_skb_any(skb);
-+	if (net_ratelimit())
-+		netdev_err(ndev, "Tx DMA memory map failed\n");
-+	return NETDEV_TX_OK;
- }
- 
- /* Init RX & TX buffer descriptors
-@@ -446,71 +547,60 @@
- static void fec_enet_bd_init(struct net_device *dev)
- {
- 	struct fec_enet_private *fep = netdev_priv(dev);
--	struct bufdesc *bdp;
-+	union bufdesc_u *bdp;
- 	unsigned int i;
- 
- 	/* Initialize the receive buffer descriptors. */
--	bdp = fep->rx_bd_base;
- 	for (i = 0; i < fep->rx_ring_size; i++) {
-+		bdp = fec_enet_rx_get(i, fep);
- 
- 		/* Initialize the BD for every fragment in the page. */
--		if (bdp->cbd_bufaddr)
--			bdp->cbd_sc = BD_ENET_RX_EMPTY;
-+		if (bdp->bd.cbd_bufaddr)
-+			bdp->bd.cbd_sc = BD_ENET_RX_EMPTY;
- 		else
--			bdp->cbd_sc = 0;
--		bdp = fec_enet_get_nextdesc(bdp, fep);
--	}
-+			bdp->bd.cbd_sc = 0;
- 
--	/* Set the last buffer to wrap */
--	bdp = fec_enet_get_prevdesc(bdp, fep);
--	bdp->cbd_sc |= BD_SC_WRAP;
-+		if (i == fep->rx_ring_size - 1)
-+			bdp->bd.cbd_sc |= BD_SC_WRAP;
-+	}
- 
--	fep->cur_rx = fep->rx_bd_base;
-+	fep->rx_next = 0;
- 
- 	/* ...and the same for transmit */
--	bdp = fep->tx_bd_base;
--	fep->cur_tx = bdp;
- 	for (i = 0; i < fep->tx_ring_size; i++) {
-+		bdp = fec_enet_tx_get(i, fep);
- 
- 		/* Initialize the BD for every fragment in the page. */
--		bdp->cbd_sc = 0;
--		if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
-+		if (i == fep->tx_ring_size - 1)
-+			bdp->bd.cbd_sc = BD_SC_WRAP;
-+		else
-+			bdp->bd.cbd_sc = 0;
-+		if (bdp->bd.cbd_bufaddr)
-+			fec_enet_tx_unmap(i, bdp, fep);
-+		if (fep->tx_skbuff[i]) {
- 			dev_kfree_skb_any(fep->tx_skbuff[i]);
- 			fep->tx_skbuff[i] = NULL;
- 		}
--		bdp->cbd_bufaddr = 0;
--		bdp = fec_enet_get_nextdesc(bdp, fep);
- 	}
- 
--	/* Set the last buffer to wrap */
--	bdp = fec_enet_get_prevdesc(bdp, fep);
--	bdp->cbd_sc |= BD_SC_WRAP;
--	fep->dirty_tx = bdp;
-+	fep->tx_next = 0;
-+	fep->tx_dirty = fep->tx_ring_size - 1;
- }
- 
--/* This function is called to start or restart the FEC during a link
-- * change.  This only happens when switching between half and full
-- * duplex.
-+/*
-+ * This function is called to start or restart the FEC during a link
-+ * change, transmit timeout, or to reconfigure the FEC.  The network
-+ * packet processing for this device must be stopped before this call.
-  */
- static void
--fec_restart(struct net_device *ndev, int duplex)
-+fec_restart(struct net_device *ndev)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
--	int i;
- 	u32 val;
- 	u32 temp_mac[2];
- 	u32 rcntl = OPT_FRAME_SIZE | 0x04;
- 	u32 ecntl = 0x2; /* ETHEREN */
- 
--	if (netif_running(ndev)) {
--		netif_device_detach(ndev);
--		napi_disable(&fep->napi);
--		netif_stop_queue(ndev);
--		netif_tx_lock_bh(ndev);
--	}
--
- 	/* Whack a reset.  We should wait for this. */
- 	writel(1, fep->hwp + FEC_ECNTRL);
- 	udelay(10);
-@@ -519,7 +609,7 @@
- 	 * enet-mac reset will reset mac address registers too,
- 	 * so need to reconfigure it.
- 	 */
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
- 		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
- 		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
- 		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
-@@ -531,27 +621,16 @@
- 	/* Set maximum receive buffer size. */
- 	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
- 
--	fec_enet_bd_init(ndev);
-+	if (fep->rx_bd_base)
-+		fec_enet_bd_init(ndev);
-+	netdev_reset_queue(ndev);
- 
- 	/* Set receive and transmit descriptor base. */
--	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
--	if (fep->bufdesc_ex)
--		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc_ex)
--			* fep->rx_ring_size, fep->hwp + FEC_X_DES_START);
--	else
--		writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
--			* fep->rx_ring_size,	fep->hwp + FEC_X_DES_START);
--
--
--	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
--		if (fep->tx_skbuff[i]) {
--			dev_kfree_skb_any(fep->tx_skbuff[i]);
--			fep->tx_skbuff[i] = NULL;
--		}
--	}
-+	writel(fep->rx_bd_dma, fep->hwp + FEC_R_DES_START);
-+	writel(fep->tx_bd_dma, fep->hwp + FEC_X_DES_START);
- 
- 	/* Enable MII mode */
--	if (duplex) {
-+	if (fep->full_duplex == DUPLEX_FULL) {
- 		/* FD enable */
- 		writel(0x04, fep->hwp + FEC_X_CNTRL);
- 	} else {
-@@ -560,15 +639,15 @@
- 		writel(0x0, fep->hwp + FEC_X_CNTRL);
- 	}
- 
--	fep->full_duplex = duplex;
--
- 	/* Set MII speed */
- 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
- 
- #if !defined(CONFIG_M5272)
- 	/* set RX checksum */
- 	val = readl(fep->hwp + FEC_RACC);
--	if (fep->csum_flags & FLAG_RX_CSUM_ENABLED)
-+	if (fep->quirks & FEC_QUIRK_RX_SHIFT16)
-+		val |= FEC_RACC_SHIFT16;
-+	if (fep->flags & FEC_FLAG_RX_CSUM)
- 		val |= FEC_RACC_OPTIONS;
- 	else
- 		val &= ~FEC_RACC_OPTIONS;
-@@ -579,9 +658,9 @@
- 	 * The phy interface and speed need to get configured
- 	 * differently on enet-mac.
- 	 */
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
- 		/* Enable flow control and length check */
--		rcntl |= 0x40000000 | 0x00000020;
-+		rcntl |= 0x40000000;
- 
- 		/* RGMII, RMII or MII */
- 		if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
-@@ -602,7 +681,7 @@
- 		}
- 	} else {
- #ifdef FEC_MIIGSK_ENR
--		if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
-+		if (fep->quirks & FEC_QUIRK_USE_GASKET) {
- 			u32 cfgr;
- 			/* disable the gasket and wait */
- 			writel(0, fep->hwp + FEC_MIIGSK_ENR);
-@@ -627,22 +706,24 @@
- 	}
- 
- #if !defined(CONFIG_M5272)
--	/* enable pause frame*/
--	if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) ||
--	    ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) &&
--	     fep->phy_dev && fep->phy_dev->pause)) {
--		rcntl |= FEC_ENET_FCE;
--
--		/* set FIFO threshold parameter to reduce overrun */
--		writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
--		writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
--		writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
--		writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
-+	if (fep->full_duplex == DUPLEX_FULL) {
-+		/*
-+		 * Configure pause modes according to the current status.
-+		 * Must only be enabled for full duplex links.
-+		 */
-+		if (fep->pause_mode & FEC_PAUSE_FLAG_RX)
-+			rcntl |= FEC_ENET_FCE;
- 
--		/* OPD */
--		writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
--	} else {
--		rcntl &= ~FEC_ENET_FCE;
-+		if (fep->pause_mode & FEC_PAUSE_FLAG_TX) {
-+			/* set FIFO threshold parameter to reduce overrun */
-+			writel(FEC_ENET_RSEM_V, fep->hwp + FEC_R_FIFO_RSEM);
-+			writel(FEC_ENET_RSFL_V, fep->hwp + FEC_R_FIFO_RSFL);
-+			writel(FEC_ENET_RAEM_V, fep->hwp + FEC_R_FIFO_RAEM);
-+			writel(FEC_ENET_RAFL_V, fep->hwp + FEC_R_FIFO_RAFL);
-+
-+			/* OPD */
-+			writel(FEC_ENET_OPD_V, fep->hwp + FEC_OPD);
-+		}
- 	}
- #endif /* !defined(CONFIG_M5272) */
- 
-@@ -655,14 +736,14 @@
- 	writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
- #endif
- 
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
- 		/* enable ENET endian swap */
- 		ecntl |= (1 << 8);
- 		/* enable ENET store and forward mode */
- 		writel(1 << 8, fep->hwp + FEC_X_WMRK);
- 	}
- 
--	if (fep->bufdesc_ex)
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX)
- 		ecntl |= (1 << 4);
- 
- #ifndef CONFIG_M5272
-@@ -674,26 +755,17 @@
- 	writel(ecntl, fep->hwp + FEC_ECNTRL);
- 	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
- 
--	if (fep->bufdesc_ex)
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX)
- 		fec_ptp_start_cyclecounter(ndev);
- 
- 	/* Enable interrupts we wish to service */
- 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
--
--	if (netif_running(ndev)) {
--		netif_tx_unlock_bh(ndev);
--		netif_wake_queue(ndev);
--		napi_enable(&fep->napi);
--		netif_device_attach(ndev);
--	}
- }
- 
- static void
- fec_stop(struct net_device *ndev)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
- 	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
- 
- 	/* We cannot expect a graceful transmit stop without link !!! */
-@@ -711,7 +783,7 @@
- 	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
- 
- 	/* We have to keep ENET enabled to have MII interrupt stay working */
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
- 		writel(2, fep->hwp + FEC_ECNTRL);
- 		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
- 	}
-@@ -723,127 +795,312 @@
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
-+	fec_dump(ndev);
-+
- 	ndev->stats.tx_errors++;
- 
--	fep->delay_work.timeout = true;
--	schedule_delayed_work(&(fep->delay_work.delay_work), 0);
-+	schedule_work(&fep->tx_timeout_work);
- }
- 
--static void fec_enet_work(struct work_struct *work)
-+static void fec_enet_timeout_work(struct work_struct *work)
- {
- 	struct fec_enet_private *fep =
--		container_of(work,
--			     struct fec_enet_private,
--			     delay_work.delay_work.work);
--
--	if (fep->delay_work.timeout) {
--		fep->delay_work.timeout = false;
--		fec_restart(fep->netdev, fep->full_duplex);
--		netif_wake_queue(fep->netdev);
--	}
-+		container_of(work, struct fec_enet_private, tx_timeout_work);
-+	struct net_device *ndev = fep->netdev;
- 
--	if (fep->delay_work.trig_tx) {
--		fep->delay_work.trig_tx = false;
--		writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-+	rtnl_lock();
-+	if (netif_device_present(ndev) || netif_running(ndev)) {
-+		mutex_lock(&fep->mutex);
-+		napi_disable(&fep->napi);
-+		netif_tx_lock_bh(ndev);
-+		fec_restart(ndev);
-+		netif_wake_queue(ndev);
-+		netif_tx_unlock_bh(ndev);
-+		napi_enable(&fep->napi);
-+		mutex_unlock(&fep->mutex);
- 	}
-+	rtnl_unlock();
- }
- 
- static void
-+fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
-+	struct skb_shared_hwtstamps *hwtstamps)
-+{
-+	unsigned long flags;
-+	u64 ns;
-+
-+	spin_lock_irqsave(&fep->tmreg_lock, flags);
-+	ns = timecounter_cyc2time(&fep->tc, ts);
-+	spin_unlock_irqrestore(&fep->tmreg_lock, flags);
-+
-+	memset(hwtstamps, 0, sizeof(*hwtstamps));
-+	hwtstamps->hwtstamp = ns_to_ktime(ns);
-+}
-+
-+static void noinline
- fec_enet_tx(struct net_device *ndev)
- {
--	struct	fec_enet_private *fep;
--	struct bufdesc *bdp;
--	unsigned short status;
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	union bufdesc_u *bdp;
- 	struct	sk_buff	*skb;
--	int	index = 0;
--
--	fep = netdev_priv(ndev);
--	bdp = fep->dirty_tx;
-+	unsigned index = fep->tx_dirty;
-+	unsigned pkts_compl, bytes_compl;
- 
--	/* get next bdp of dirty_tx */
--	bdp = fec_enet_get_nextdesc(bdp, fep);
-+	pkts_compl = bytes_compl = 0;
-+	do {
-+		unsigned status, cbd_esc;
- 
--	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
-+		if (++index >= fep->tx_ring_size)
-+			index = 0;
- 
- 		/* current queue is empty */
--		if (bdp == fep->cur_tx)
-+		if (index == fep->tx_next)
- 			break;
- 
--		if (fep->bufdesc_ex)
--			index = (struct bufdesc_ex *)bdp -
--				(struct bufdesc_ex *)fep->tx_bd_base;
--		else
--			index = bdp - fep->tx_bd_base;
-+		bdp = fec_enet_tx_get(index, fep);
-+
-+		status = bdp->bd.cbd_sc;
-+		if (status & BD_ENET_TX_READY)
-+			break;
-+
-+		fec_enet_tx_unmap(index, bdp, fep);
- 
- 		skb = fep->tx_skbuff[index];
--		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, skb->len,
--				DMA_TO_DEVICE);
--		bdp->cbd_bufaddr = 0;
-+		fep->tx_skbuff[index] = NULL;
- 
- 		/* Check for errors. */
--		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
--				   BD_ENET_TX_RL | BD_ENET_TX_UN |
--				   BD_ENET_TX_CSL)) {
--			ndev->stats.tx_errors++;
--			if (status & BD_ENET_TX_HB)  /* No heartbeat */
--				ndev->stats.tx_heartbeat_errors++;
--			if (status & BD_ENET_TX_LC)  /* Late collision */
--				ndev->stats.tx_window_errors++;
--			if (status & BD_ENET_TX_RL)  /* Retrans limit */
--				ndev->stats.tx_aborted_errors++;
--			if (status & BD_ENET_TX_UN)  /* Underrun */
--				ndev->stats.tx_fifo_errors++;
--			if (status & BD_ENET_TX_CSL) /* Carrier lost */
--				ndev->stats.tx_carrier_errors++;
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX) {
-+			cbd_esc = bdp->ebd.cbd_esc;
-+			if (cbd_esc & BD_ENET_TX_TXE) {
-+				ndev->stats.tx_errors++;
-+				if (cbd_esc & BD_ENET_TX_EE) { /* excess collision */
-+					ndev->stats.collisions += 16;
-+					ndev->stats.tx_aborted_errors++;
-+				}
-+				if (cbd_esc & BD_ENET_TX_LCE) /* late collision error */
-+					ndev->stats.tx_window_errors++;
-+				if (cbd_esc & (BD_ENET_TX_UE | BD_ENET_TX_FE | BD_ENET_TX_OE))
-+					ndev->stats.tx_fifo_errors++;
-+				goto next;
-+			}
- 		} else {
--			ndev->stats.tx_packets++;
--			ndev->stats.tx_bytes += bdp->cbd_datlen;
-+			if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
-+					   BD_ENET_TX_RL | BD_ENET_TX_UN |
-+					   BD_ENET_TX_CSL)) {
-+				ndev->stats.tx_errors++;
-+				if (status & BD_ENET_TX_HB)  /* No heartbeat */
-+					ndev->stats.tx_heartbeat_errors++;
-+				if (status & BD_ENET_TX_LC)  /* Late collision */
-+					ndev->stats.tx_window_errors++;
-+				if (status & BD_ENET_TX_RL)  /* Retrans limit */
-+					ndev->stats.tx_aborted_errors++;
-+				if (status & BD_ENET_TX_UN)  /* Underrun */
-+					ndev->stats.tx_fifo_errors++;
-+				if (status & BD_ENET_TX_CSL) /* Carrier lost */
-+					ndev->stats.tx_carrier_errors++;
-+				goto next;
-+			}
- 		}
- 
--		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) &&
--			fep->bufdesc_ex) {
--			struct skb_shared_hwtstamps shhwtstamps;
--			unsigned long flags;
--			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
--
--			memset(&shhwtstamps, 0, sizeof(shhwtstamps));
--			spin_lock_irqsave(&fep->tmreg_lock, flags);
--			shhwtstamps.hwtstamp = ns_to_ktime(
--				timecounter_cyc2time(&fep->tc, ebdp->ts));
--			spin_unlock_irqrestore(&fep->tmreg_lock, flags);
--			skb_tstamp_tx(skb, &shhwtstamps);
-+		if (skb) {
-+			ndev->stats.tx_packets++;
-+			ndev->stats.tx_bytes += skb->len;
- 		}
- 
--		if (status & BD_ENET_TX_READY)
--			netdev_err(ndev, "HEY! Enet xmit interrupt and TX_READY\n");
--
- 		/* Deferred means some collisions occurred during transmit,
- 		 * but we eventually sent the packet OK.
- 		 */
- 		if (status & BD_ENET_TX_DEF)
- 			ndev->stats.collisions++;
-+ next:
-+		if (skb) {
-+			if (fep->flags & FEC_FLAG_BUFDESC_EX &&
-+			    unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
-+				struct skb_shared_hwtstamps shhwtstamps;
- 
--		/* Free the sk buffer associated with this last transmit */
--		dev_kfree_skb_any(skb);
--		fep->tx_skbuff[index] = NULL;
-+				fec_enet_hwtstamp(fep, bdp->ebd.ts, &shhwtstamps);
-+				skb_tstamp_tx(skb, &shhwtstamps);
-+			}
- 
--		fep->dirty_tx = bdp;
-+			pkts_compl++;
-+			bytes_compl += skb->len;
- 
--		/* Update pointer to next buffer descriptor to be transmitted */
--		bdp = fec_enet_get_nextdesc(bdp, fep);
-+			/* Free the sk buffer associated with this last transmit */
-+			dev_kfree_skb_any(skb);
-+		}
- 
--		/* Since we have freed up a buffer, the ring is no longer full
--		 */
--		if (fep->dirty_tx != fep->cur_tx) {
--			if (netif_queue_stopped(ndev))
--				netif_wake_queue(ndev);
-+		fep->tx_dirty = index;
-+	} while (1);
-+
-+	netdev_completed_queue(ndev, pkts_compl, bytes_compl);
-+
-+	/* ERR006538: Keep the transmitter going */
-+	if (index != fep->tx_next && readl(fep->hwp + FEC_X_DES_ACTIVE) == 0)
-+		writel(0, fep->hwp + FEC_X_DES_ACTIVE);
-+
-+	if (netif_queue_stopped(ndev) &&
-+	    ring_free(fep->tx_next, fep->tx_dirty, fep->tx_ring_size) >=
-+	      fep->tx_min)
-+		netif_wake_queue(ndev);
-+}
-+
-+
-+static void
-+fec_enet_receive(struct sk_buff *skb, union bufdesc_u *bdp, struct net_device *ndev)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+
-+	skb->protocol = eth_type_trans(skb, ndev);
-+
-+	/* Get receive timestamp from the skb */
-+	if (fep->hwts_rx_en && fep->flags & FEC_FLAG_BUFDESC_EX)
-+		fec_enet_hwtstamp(fep, bdp->ebd.ts, skb_hwtstamps(skb));
-+
-+	if (fep->flags & FEC_FLAG_RX_CSUM) {
-+		if (!(bdp->ebd.cbd_esc & FLAG_RX_CSUM_ERROR)) {
-+			/* don't check it */
-+			skb->ip_summed = CHECKSUM_UNNECESSARY;
-+		} else {
-+			skb_checksum_none_assert(skb);
- 		}
- 	}
--	return;
-+
-+	napi_gro_receive(&fep->napi, skb);
-+}
-+
-+static void
-+fec_enet_receive_copy(unsigned pkt_len, unsigned index, union bufdesc_u *bdp, struct net_device *ndev)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	struct sk_buff *skb;
-+	unsigned char *data;
-+	bool vlan_packet_rcvd = false;
-+
-+	/*
-+	 * Detect the presence of the VLAN tag, and adjust
-+	 * the packet length appropriately.
-+	 */
-+	if (fep->flags & FEC_FLAG_RX_VLAN &&
-+	    bdp->ebd.cbd_esc & BD_ENET_RX_VLAN) {
-+		pkt_len -= VLAN_HLEN;
-+		vlan_packet_rcvd = true;
-+	}
-+
-+	/* This does 16 byte alignment, exactly what we need. */
-+	skb = netdev_alloc_skb(ndev, pkt_len + NET_IP_ALIGN);
-+	if (unlikely(!skb)) {
-+		ndev->stats.rx_dropped++;
-+		return;
-+	}
-+
-+	dma_sync_single_for_cpu(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
-+				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-+
-+	data = fep->rx_skbuff[index]->data;
-+
-+#ifndef CONFIG_M5272
-+	/*
-+	 * If we have enabled this feature, we need to discard
-+	 * the two bytes at the beginning of the packet before
-+	 * copying it.
-+	 */
-+	if (fep->quirks & FEC_QUIRK_RX_SHIFT16) {
-+		pkt_len -= 2;
-+		data += 2;
-+	}
-+#endif
-+
-+	if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
-+		swap_buffer(data, pkt_len);
-+
-+	skb_reserve(skb, NET_IP_ALIGN);
-+	skb_put(skb, pkt_len);	/* Make room */
-+
-+	/* If this is a VLAN packet remove the VLAN Tag */
-+	if (vlan_packet_rcvd) {
-+		struct vlan_hdr *vlan = (struct vlan_hdr *)(data + ETH_HLEN);
-+
-+		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
-+				       ntohs(vlan->h_vlan_TCI));
-+
-+		/* Extract the frame data without the VLAN header. */
-+		skb_copy_to_linear_data(skb, data, 2 * ETH_ALEN);
-+		skb_copy_to_linear_data_offset(skb, 2 * ETH_ALEN,
-+					       data + 2 * ETH_ALEN + VLAN_HLEN,
-+					       pkt_len - 2 * ETH_ALEN);
-+	} else {
-+		skb_copy_to_linear_data(skb, data, pkt_len);
-+	}
-+
-+	dma_sync_single_for_device(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
-+				   FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-+
-+	fec_enet_receive(skb, bdp, ndev);
- }
- 
-+static void
-+fec_enet_receive_nocopy(unsigned pkt_len, unsigned index, union bufdesc_u *bdp,
-+	struct net_device *ndev)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	struct sk_buff *skb, *skb_new;
-+	unsigned char *data;
-+	dma_addr_t addr;
-+
-+	skb_new = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
-+	if (!skb_new) {
-+		ndev->stats.rx_dropped++;
-+		return;
-+	}
-+
-+	addr = dma_map_single(&fep->pdev->dev, skb_new->data,
-+			      FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-+	if (dma_mapping_error(&fep->pdev->dev, addr)) {
-+		dev_kfree_skb(skb_new);
-+		ndev->stats.rx_dropped++;
-+		return;
-+	}
- 
--/* During a receive, the cur_rx points to the current incoming buffer.
-+	/* We have the new skb, so proceed to deal with the received data. */
-+	dma_unmap_single(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
-+			 FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
-+
-+	skb = fep->rx_skbuff[index];
-+
-+	/* Now subsitute in the new skb */
-+	fep->rx_skbuff[index] = skb_new;
-+	bdp->bd.cbd_bufaddr = addr;
-+
-+	/*
-+	 * Update the skb length according to the raw packet length.
-+	 * Then remove the two bytes of additional padding.
-+	 */
-+	skb_put(skb, pkt_len);
-+	data = skb_pull_inline(skb, 2);
-+
-+	if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
-+		swap_buffer(data, skb->len);
-+
-+	/*
-+	 * Now juggle things for the VLAN tag - if the hardware
-+	 * flags this as present, we need to read the tag, and
-+	 * then shuffle the ethernet addresses up.
-+	 */
-+	if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX &&
-+	    bdp->ebd.cbd_esc & BD_ENET_RX_VLAN) {
-+		struct vlan_hdr *vlan = (struct vlan_hdr *)(data + ETH_HLEN);
-+
-+		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
-+				       ntohs(vlan->h_vlan_TCI));
-+
-+		memmove(data + VLAN_HLEN, data, 2 * ETH_ALEN);
-+		skb_pull_inline(skb, VLAN_HLEN);
-+	}
-+
-+	fec_enet_receive(skb, bdp, ndev);
-+}
-+
-+/* During a receive, the rx_next points to the current incoming buffer.
-  * When we update through the ring, if the next incoming buffer has
-  * not been given to the system, we just set the empty indicator,
-  * effectively tossing the packet.
-@@ -852,18 +1109,9 @@
- fec_enet_rx(struct net_device *ndev, int budget)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
--	struct bufdesc *bdp;
--	unsigned short status;
--	struct	sk_buff	*skb;
- 	ushort	pkt_len;
--	__u8 *data;
- 	int	pkt_received = 0;
--	struct	bufdesc_ex *ebdp = NULL;
--	bool	vlan_packet_rcvd = false;
--	u16	vlan_tag;
--	int	index = 0;
-+	unsigned index = fep->rx_next;
- 
- #ifdef CONFIG_M532x
- 	flush_cache_all();
-@@ -872,12 +1120,17 @@
- 	/* First, grab all of the stats for the incoming packet.
- 	 * These get messed up if we get called due to a busy condition.
- 	 */
--	bdp = fep->cur_rx;
-+	do {
-+		union bufdesc_u *bdp = fec_enet_rx_get(index, fep);
-+		unsigned status;
- 
--	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
-+		status = bdp->bd.cbd_sc;
-+		if (status & BD_ENET_RX_EMPTY)
-+			break;
- 
- 		if (pkt_received >= budget)
- 			break;
-+
- 		pkt_received++;
- 
- 		/* Since we have allocated space to hold a complete frame,
-@@ -886,155 +1139,81 @@
- 		if ((status & BD_ENET_RX_LAST) == 0)
- 			netdev_err(ndev, "rcv is not +last\n");
- 
--		if (!fep->opened)
--			goto rx_processing_done;
-+		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
- 
- 		/* Check for errors. */
--		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
--			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-+		if (status & BD_ENET_RX_ERROR) {
- 			ndev->stats.rx_errors++;
--			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
--				/* Frame too long or too short. */
--				ndev->stats.rx_length_errors++;
--			}
--			if (status & BD_ENET_RX_NO)	/* Frame alignment */
--				ndev->stats.rx_frame_errors++;
--			if (status & BD_ENET_RX_CR)	/* CRC Error */
--				ndev->stats.rx_crc_errors++;
--			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
--				ndev->stats.rx_fifo_errors++;
--		}
- 
--		/* Report late collisions as a frame error.
--		 * On this error, the BD is closed, but we don't know what we
--		 * have in the buffer.  So, just drop this frame on the floor.
--		 */
--		if (status & BD_ENET_RX_CL) {
--			ndev->stats.rx_errors++;
--			ndev->stats.rx_frame_errors++;
-+			/*
-+			 * Report late collisions as a frame error.  On this
-+			 * error, the BD is closed, but we don't know what we
-+			 * have in the buffer.  So, just drop this frame on
-+			 * the floor.
-+			 */
-+			if (status & BD_ENET_RX_CL) {
-+				ndev->stats.rx_frame_errors++;
-+			} else {
-+				if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-+					/* Frame too long or too short. */
-+					ndev->stats.rx_length_errors++;
-+				if (status & BD_ENET_RX_NO)	/* Frame alignment */
-+					ndev->stats.rx_frame_errors++;
-+				if (status & BD_ENET_RX_CR)	/* CRC Error */
-+					ndev->stats.rx_crc_errors++;
-+				if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-+					ndev->stats.rx_fifo_errors++;
-+			}
- 			goto rx_processing_done;
- 		}
- 
- 		/* Process the incoming frame. */
- 		ndev->stats.rx_packets++;
--		pkt_len = bdp->cbd_datlen;
--		ndev->stats.rx_bytes += pkt_len;
--
--		if (fep->bufdesc_ex)
--			index = (struct bufdesc_ex *)bdp -
--				(struct bufdesc_ex *)fep->rx_bd_base;
--		else
--			index = bdp - fep->rx_bd_base;
--		data = fep->rx_skbuff[index]->data;
--		dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
--					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
--
--		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
--			swap_buffer(data, pkt_len);
- 
--		/* Extract the enhanced buffer descriptor */
--		ebdp = NULL;
--		if (fep->bufdesc_ex)
--			ebdp = (struct bufdesc_ex *)bdp;
--
--		/* If this is a VLAN packet remove the VLAN Tag */
--		vlan_packet_rcvd = false;
--		if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
--		    fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) {
--			/* Push and remove the vlan tag */
--			struct vlan_hdr *vlan_header =
--					(struct vlan_hdr *) (data + ETH_HLEN);
--			vlan_tag = ntohs(vlan_header->h_vlan_TCI);
--			pkt_len -= VLAN_HLEN;
--
--			vlan_packet_rcvd = true;
--		}
--
--		/* This does 16 byte alignment, exactly what we need.
--		 * The packet length includes FCS, but we don't want to
--		 * include that when passing upstream as it messes up
--		 * bridging applications.
-+		/*
-+		 * The packet length includes FCS, but we don't want
-+		 * to include that when passing upstream as it messes
-+		 * up bridging applications.
- 		 */
--		skb = netdev_alloc_skb(ndev, pkt_len - 4 + NET_IP_ALIGN);
-+		pkt_len = bdp->bd.cbd_datlen - 4;
-+		ndev->stats.rx_bytes += pkt_len;
- 
--		if (unlikely(!skb)) {
--			ndev->stats.rx_dropped++;
-+		if (fec_enet_rx_zerocopy(fep, pkt_len)) {
-+			fec_enet_receive_nocopy(pkt_len, index, bdp, ndev);
- 		} else {
--			int payload_offset = (2 * ETH_ALEN);
--			skb_reserve(skb, NET_IP_ALIGN);
--			skb_put(skb, pkt_len - 4);	/* Make room */
--
--			/* Extract the frame data without the VLAN header. */
--			skb_copy_to_linear_data(skb, data, (2 * ETH_ALEN));
--			if (vlan_packet_rcvd)
--				payload_offset = (2 * ETH_ALEN) + VLAN_HLEN;
--			skb_copy_to_linear_data_offset(skb, (2 * ETH_ALEN),
--						       data + payload_offset,
--						       pkt_len - 4 - (2 * ETH_ALEN));
--
--			skb->protocol = eth_type_trans(skb, ndev);
--
--			/* Get receive timestamp from the skb */
--			if (fep->hwts_rx_en && fep->bufdesc_ex) {
--				struct skb_shared_hwtstamps *shhwtstamps =
--							    skb_hwtstamps(skb);
--				unsigned long flags;
--
--				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
--
--				spin_lock_irqsave(&fep->tmreg_lock, flags);
--				shhwtstamps->hwtstamp = ns_to_ktime(
--				    timecounter_cyc2time(&fep->tc, ebdp->ts));
--				spin_unlock_irqrestore(&fep->tmreg_lock, flags);
--			}
--
--			if (fep->bufdesc_ex &&
--			    (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) {
--				if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) {
--					/* don't check it */
--					skb->ip_summed = CHECKSUM_UNNECESSARY;
--				} else {
--					skb_checksum_none_assert(skb);
--				}
--			}
--
--			/* Handle received VLAN packets */
--			if (vlan_packet_rcvd)
--				__vlan_hwaccel_put_tag(skb,
--						       htons(ETH_P_8021Q),
--						       vlan_tag);
--
--			napi_gro_receive(&fep->napi, skb);
-+			fec_enet_receive_copy(pkt_len, index, bdp, ndev);
- 		}
- 
--		dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
--					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
- rx_processing_done:
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX) {
-+			bdp->ebd.cbd_esc = BD_ENET_RX_INT;
-+			bdp->ebd.cbd_prot = 0;
-+			bdp->ebd.cbd_bdu = 0;
-+		}
-+
-+		/*
-+		 * Ensure that the previous writes have completed before
-+		 * the status update becomes visible.
-+		 */
-+		wmb();
-+
- 		/* Clear the status flags for this buffer */
- 		status &= ~BD_ENET_RX_STATS;
- 
- 		/* Mark the buffer empty */
- 		status |= BD_ENET_RX_EMPTY;
--		bdp->cbd_sc = status;
--
--		if (fep->bufdesc_ex) {
--			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
--
--			ebdp->cbd_esc = BD_ENET_RX_INT;
--			ebdp->cbd_prot = 0;
--			ebdp->cbd_bdu = 0;
--		}
--
--		/* Update BD pointer to next entry */
--		bdp = fec_enet_get_nextdesc(bdp, fep);
-+		bdp->bd.cbd_sc = status;
- 
- 		/* Doing this here will keep the FEC running while we process
- 		 * incoming frames.  On a heavily loaded network, we should be
- 		 * able to keep up at the expense of system resources.
- 		 */
- 		writel(0, fep->hwp + FEC_R_DES_ACTIVE);
--	}
--	fep->cur_rx = bdp;
-+
-+		if (++index >= fep->rx_ring_size)
-+			index = 0;
-+	} while (1);
-+	fep->rx_next = index;
- 
- 	return pkt_received;
- }
-@@ -1044,29 +1223,25 @@
- {
- 	struct net_device *ndev = dev_id;
- 	struct fec_enet_private *fep = netdev_priv(ndev);
-+	const unsigned napi_mask = FEC_ENET_RXF | FEC_ENET_TXF;
- 	uint int_events;
- 	irqreturn_t ret = IRQ_NONE;
- 
--	do {
--		int_events = readl(fep->hwp + FEC_IEVENT);
--		writel(int_events, fep->hwp + FEC_IEVENT);
-+	int_events = readl(fep->hwp + FEC_IEVENT);
-+	writel(int_events & ~napi_mask, fep->hwp + FEC_IEVENT);
- 
--		if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
--			ret = IRQ_HANDLED;
-+	if (int_events & napi_mask) {
-+		ret = IRQ_HANDLED;
- 
--			/* Disable the RX interrupt */
--			if (napi_schedule_prep(&fep->napi)) {
--				writel(FEC_RX_DISABLED_IMASK,
--					fep->hwp + FEC_IMASK);
--				__napi_schedule(&fep->napi);
--			}
--		}
-+		/* Disable the NAPI interrupts */
-+		writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
-+		napi_schedule(&fep->napi);
-+	}
- 
--		if (int_events & FEC_ENET_MII) {
--			ret = IRQ_HANDLED;
--			complete(&fep->mdio_done);
--		}
--	} while (int_events);
-+	if (int_events & FEC_ENET_MII) {
-+		ret = IRQ_HANDLED;
-+		complete(&fep->mdio_done);
-+	}
- 
- 	return ret;
- }
-@@ -1074,8 +1249,16 @@
- static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
- {
- 	struct net_device *ndev = napi->dev;
--	int pkts = fec_enet_rx(ndev, budget);
- 	struct fec_enet_private *fep = netdev_priv(ndev);
-+	int pkts;
-+
-+	/*
-+	 * Clear any pending transmit or receive interrupts before
-+	 * processing the rings to avoid racing with the hardware.
-+	 */
-+	writel(FEC_ENET_RXF | FEC_ENET_TXF, fep->hwp + FEC_IEVENT);
-+
-+	pkts = fec_enet_rx(ndev, budget);
- 
- 	fec_enet_tx(ndev);
- 
-@@ -1173,26 +1356,78 @@
- 		return;
- 	}
- 
--	if (phy_dev->link) {
-+	/*
-+	 * If the netdev is down, or is going down, we're not interested
-+	 * in link state events, so just mark our idea of the link as down
-+	 * and ignore the event.
-+	 */
-+	if (!netif_running(ndev) || !netif_device_present(ndev)) {
-+		fep->link = 0;
-+	} else if (phy_dev->link) {
- 		if (!fep->link) {
- 			fep->link = phy_dev->link;
- 			status_change = 1;
- 		}
- 
--		if (fep->full_duplex != phy_dev->duplex)
-+		if (fep->full_duplex != phy_dev->duplex) {
-+			fep->full_duplex = phy_dev->duplex;
- 			status_change = 1;
-+		}
- 
- 		if (phy_dev->speed != fep->speed) {
- 			fep->speed = phy_dev->speed;
- 			status_change = 1;
- 		}
- 
-+		if (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) {
-+			u32 lcl_adv = phy_dev->advertising;
-+			u32 rmt_adv = phy_dev->lp_advertising;
-+			unsigned mode = 0;
-+
-+			if (lcl_adv & rmt_adv & ADVERTISED_Pause) {
-+				/*
-+				 * Local Device  Link Partner
-+				 * Pause AsymDir Pause AsymDir Result
-+				 *   1     X       1     X     TX+RX
-+				 */
-+				mode = FEC_PAUSE_FLAG_TX | FEC_PAUSE_FLAG_RX;
-+			} else if (lcl_adv & rmt_adv & ADVERTISED_Asym_Pause) {
-+				/*
-+				 *   0     1       1     1     RX
-+				 *   1     1       0     1     TX
-+				 */
-+				if (rmt_adv & ADVERTISED_Pause)
-+					mode = FEC_PAUSE_FLAG_RX;
-+				else
-+					mode = FEC_PAUSE_FLAG_TX;
-+			}
-+
-+			if (mode != fep->pause_mode) {
-+				fep->pause_mode = mode;
-+				status_change = 1;
-+			}
-+		}
-+
- 		/* if any of the above changed restart the FEC */
--		if (status_change)
--			fec_restart(ndev, phy_dev->duplex);
-+		if (status_change) {
-+			mutex_lock(&fep->mutex);
-+			napi_disable(&fep->napi);
-+			netif_tx_lock_bh(ndev);
-+			fec_restart(ndev);
-+			netif_wake_queue(ndev);
-+			netif_tx_unlock_bh(ndev);
-+			napi_enable(&fep->napi);
-+			mutex_unlock(&fep->mutex);
-+		}
- 	} else {
- 		if (fep->link) {
-+			mutex_lock(&fep->mutex);
-+			napi_disable(&fep->napi);
-+			netif_tx_lock_bh(ndev);
- 			fec_stop(ndev);
-+			netif_tx_unlock_bh(ndev);
-+			napi_enable(&fep->napi);
-+			mutex_unlock(&fep->mutex);
- 			fep->link = phy_dev->link;
- 			status_change = 1;
- 		}
-@@ -1202,23 +1437,35 @@
- 		phy_print_status(phy_dev);
- }
- 
--static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-+static unsigned long fec_enet_mdio_op(struct fec_enet_private *fep,
-+	unsigned data)
- {
--	struct fec_enet_private *fep = bus->priv;
- 	unsigned long time_left;
- 
- 	fep->mii_timeout = 0;
- 	init_completion(&fep->mdio_done);
- 
--	/* start a read op */
--	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
--		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
--		FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
-+	mutex_lock(&fep->mutex);
-+
-+	/* start operation */
-+	writel(data, fep->hwp + FEC_MII_DATA);
- 
- 	/* wait for end of transfer */
- 	time_left = wait_for_completion_timeout(&fep->mdio_done,
- 			usecs_to_jiffies(FEC_MII_TIMEOUT));
--	if (time_left == 0) {
-+
-+	mutex_unlock(&fep->mutex);
-+
-+	return time_left;
-+}
-+
-+static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-+{
-+	struct fec_enet_private *fep = bus->priv;
-+
-+	if (fec_enet_mdio_op(fep, FEC_MMFR_ST | FEC_MMFR_OP_READ |
-+				  FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
-+				  FEC_MMFR_TA) == 0) {
- 		fep->mii_timeout = 1;
- 		netdev_err(fep->netdev, "MDIO read timeout\n");
- 		return -ETIMEDOUT;
-@@ -1232,21 +1479,10 @@
- 			   u16 value)
- {
- 	struct fec_enet_private *fep = bus->priv;
--	unsigned long time_left;
--
--	fep->mii_timeout = 0;
--	init_completion(&fep->mdio_done);
--
--	/* start a write op */
--	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
--		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
--		FEC_MMFR_TA | FEC_MMFR_DATA(value),
--		fep->hwp + FEC_MII_DATA);
- 
--	/* wait for end of transfer */
--	time_left = wait_for_completion_timeout(&fep->mdio_done,
--			usecs_to_jiffies(FEC_MII_TIMEOUT));
--	if (time_left == 0) {
-+	if (fec_enet_mdio_op(fep, FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
-+				  FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) |
-+				  FEC_MMFR_TA | FEC_MMFR_DATA(value)) == 0) {
- 		fep->mii_timeout = 1;
- 		netdev_err(fep->netdev, "MDIO write timeout\n");
- 		return -ETIMEDOUT;
-@@ -1255,11 +1491,37 @@
- 	return 0;
- }
- 
-+static void fec_enet_phy_config(struct net_device *ndev)
-+{
-+#ifndef CONFIG_M5272
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	struct phy_device *phy = fep->phy_dev;
-+	unsigned pause = 0;
-+
-+	/*
-+	 * Pause advertisment logic is weird.  We don't advertise the raw
-+	 * "can tx" and "can rx" modes, but instead it is whether we support
-+	 * symmetric flow or asymmetric flow.
-+	 *
-+	 * Symmetric flow means we can only support both transmit and receive
-+	 * flow control frames together.  Asymmetric flow means we can
-+	 * independently control each.  Note that there is no bit encoding
-+	 * for "I can only receive flow control frames."
-+	 */
-+	if (fep->pause_flag & FEC_PAUSE_FLAG_RX)
-+		pause |= ADVERTISED_Asym_Pause | ADVERTISED_Pause;
-+	if (fep->pause_flag & FEC_PAUSE_FLAG_TX)
-+		pause |= ADVERTISED_Asym_Pause;
-+
-+	pause &= phy->supported;
-+	pause |= phy->advertising & ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
-+	phy->advertising = pause;
-+#endif
-+}
-+
- static int fec_enet_mii_probe(struct net_device *ndev)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
- 	struct phy_device *phy_dev = NULL;
- 	char mdio_bus_id[MII_BUS_ID_SIZE];
- 	char phy_name[MII_BUS_ID_SIZE + 3];
-@@ -1297,10 +1559,11 @@
- 	}
- 
- 	/* mask with MAC supported features */
--	if (id_entry->driver_data & FEC_QUIRK_HAS_GBIT) {
-+	if (fep->quirks & FEC_QUIRK_HAS_GBIT) {
- 		phy_dev->supported &= PHY_GBIT_FEATURES;
-+		phy_dev->supported &= ~SUPPORTED_1000baseT_Half;
- #if !defined(CONFIG_M5272)
--		phy_dev->supported |= SUPPORTED_Pause;
-+		phy_dev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
- #endif
- 	}
- 	else
-@@ -1312,6 +1575,8 @@
- 	fep->link = 0;
- 	fep->full_duplex = 0;
- 
-+	fec_enet_phy_config(ndev);
-+
- 	netdev_info(ndev, "Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
- 		    fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
- 		    fep->phy_dev->irq);
-@@ -1324,8 +1589,6 @@
- 	static struct mii_bus *fec0_mii_bus;
- 	struct net_device *ndev = platform_get_drvdata(pdev);
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
- 	int err = -ENXIO, i;
- 
- 	/*
-@@ -1344,7 +1607,7 @@
- 	 * mdio interface in board design, and need to be configured by
- 	 * fec0 mii_bus.
- 	 */
--	if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
-+	if ((fep->quirks & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
- 		/* fec1 uses fec0 mii_bus */
- 		if (mii_cnt && fec0_mii_bus) {
- 			fep->mii_bus = fec0_mii_bus;
-@@ -1365,7 +1628,7 @@
- 	 * document.
- 	 */
- 	fep->phy_speed = DIV_ROUND_UP(clk_get_rate(fep->clk_ahb), 5000000);
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC)
- 		fep->phy_speed--;
- 	fep->phy_speed <<= 1;
- 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-@@ -1399,7 +1662,7 @@
- 	mii_cnt++;
- 
- 	/* save fec0 mii_bus */
--	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
-+	if (fep->quirks & FEC_QUIRK_ENET_MAC)
- 		fec0_mii_bus = fep->mii_bus;
- 
- 	return 0;
-@@ -1461,7 +1724,7 @@
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
--	if (fep->bufdesc_ex) {
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX) {
- 
- 		info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
- 					SOF_TIMESTAMPING_RX_SOFTWARE |
-@@ -1485,6 +1748,51 @@
- 	}
- }
- 
-+static void fec_enet_get_ringparam(struct net_device *ndev,
-+				   struct ethtool_ringparam *ring)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+
-+	ring->rx_max_pending = RX_RING_SIZE;
-+	ring->tx_max_pending = TX_RING_SIZE;
-+	ring->rx_pending = fep->rx_ring_size;
-+	ring->tx_pending = fep->tx_ring_size;
-+}
-+
-+static int fec_enet_set_ringparam(struct net_device *ndev,
-+				   struct ethtool_ringparam *ring)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+	unsigned rx, tx, tx_min;
-+
-+	tx_min = ndev->features & NETIF_F_SG ? TX_RING_SIZE_MIN_SG : 16;
-+
-+	rx = clamp_t(u32, ring->rx_pending, 16, RX_RING_SIZE);
-+	tx = clamp_t(u32, ring->tx_pending, tx_min, TX_RING_SIZE);
-+
-+	if (tx == fep->tx_ring_size && rx == fep->rx_ring_size)
-+		return 0;
-+
-+	/* Setting the ring size while the interface is down is easy */
-+	if (!netif_running(ndev)) {
-+		fep->tx_ring_size = tx;
-+		fep->rx_ring_size = rx;
-+	} else {
-+		return -EINVAL;
-+
-+		napi_disable(&fep->napi);
-+		netif_tx_lock_bh(ndev);
-+		fec_stop(ndev);
-+		/* reallocate ring */
-+		fec_restart(ndev);
-+		netif_wake_queue(ndev);
-+		netif_tx_unlock_bh(ndev);
-+		napi_enable(&fep->napi);
-+	}
-+
-+	return 0;
-+}
-+
- #if !defined(CONFIG_M5272)
- 
- static void fec_enet_get_pauseparam(struct net_device *ndev,
-@@ -1493,42 +1801,81 @@
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
- 	pause->autoneg = (fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) != 0;
--	pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) != 0;
--	pause->rx_pause = pause->tx_pause;
-+	pause->rx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_RX) != 0;
-+	pause->tx_pause = (fep->pause_flag & FEC_PAUSE_FLAG_TX) != 0;
- }
- 
- static int fec_enet_set_pauseparam(struct net_device *ndev,
- 				   struct ethtool_pauseparam *pause)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
-+	unsigned pause_flag, changed;
-+	struct phy_device *phy = fep->phy_dev;
- 
--	if (pause->tx_pause != pause->rx_pause) {
--		netdev_info(ndev,
--			"hardware only support enable/disable both tx and rx");
-+	if (!phy)
-+		return -ENODEV;
-+	if (!(phy->supported & SUPPORTED_Pause))
-+		return -EINVAL;
-+	if (!(phy->supported & SUPPORTED_Asym_Pause) &&
-+	    pause->rx_pause != pause->tx_pause)
- 		return -EINVAL;
--	}
- 
--	fep->pause_flag = 0;
-+	pause_flag = 0;
-+	if (pause->autoneg)
-+		pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
-+	if (pause->rx_pause)
-+		pause_flag |= FEC_PAUSE_FLAG_RX;
-+	if (pause->tx_pause)
-+		pause_flag |= FEC_PAUSE_FLAG_TX;
-+
-+	changed = fep->pause_flag ^ pause_flag;
-+	fep->pause_flag = pause_flag;
-+
-+	/* configure the phy advertisment according to our new options */
-+	fec_enet_phy_config(ndev);
-+
-+	if (changed) {
-+		if (pause_flag & FEC_PAUSE_FLAG_AUTONEG) {
-+			if (netif_running(ndev))
-+				phy_start_aneg(fep->phy_dev);
-+		} else {
-+			int adv, old_adv;
- 
--	/* tx pause must be same as rx pause */
--	fep->pause_flag |= pause->rx_pause ? FEC_PAUSE_FLAG_ENABLE : 0;
--	fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0;
--
--	if (pause->rx_pause || pause->autoneg) {
--		fep->phy_dev->supported |= ADVERTISED_Pause;
--		fep->phy_dev->advertising |= ADVERTISED_Pause;
--	} else {
--		fep->phy_dev->supported &= ~ADVERTISED_Pause;
--		fep->phy_dev->advertising &= ~ADVERTISED_Pause;
--	}
-+			/*
-+			 * Even if we are not in autonegotiate mode, we
-+			 * still update the phy with our capabilities so
-+			 * our link parter can make the appropriate
-+			 * decision.  PHYLIB provides no way to do this.
-+			 */
-+			adv = phy_read(phy, MII_ADVERTISE);
-+			if (adv >= 0) {
-+				old_adv = adv;
-+				adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-+				if (phy->advertising & ADVERTISED_Pause)
-+					adv |= ADVERTISE_PAUSE_CAP;
-+				if (phy->advertising & ADVERTISED_Asym_Pause)
-+					adv |= ADVERTISE_PAUSE_ASYM;
- 
--	if (pause->autoneg) {
--		if (netif_running(ndev))
--			fec_stop(ndev);
--		phy_start_aneg(fep->phy_dev);
-+				if (old_adv != adv)
-+					phy_write(phy, MII_ADVERTISE, adv);
-+			}
-+
-+			/* Forced pause mode */
-+			fep->pause_mode = fep->pause_flag;
-+
-+			if (netif_running(ndev)) {
-+				mutex_lock(&fep->mutex);
-+				napi_disable(&fep->napi);
-+				netif_tx_lock_bh(ndev);
-+				fec_stop(ndev);
-+				fec_restart(ndev);
-+				netif_wake_queue(ndev);
-+				netif_tx_unlock_bh(ndev);
-+				napi_enable(&fep->napi);
-+				mutex_unlock(&fep->mutex);
-+			}
-+		}
- 	}
--	if (netif_running(ndev))
--		fec_restart(ndev, 0);
- 
- 	return 0;
- }
-@@ -1645,21 +1992,21 @@
- }
- 
- static const struct ethtool_ops fec_enet_ethtool_ops = {
--#if !defined(CONFIG_M5272)
--	.get_pauseparam		= fec_enet_get_pauseparam,
--	.set_pauseparam		= fec_enet_set_pauseparam,
--#endif
- 	.get_settings		= fec_enet_get_settings,
- 	.set_settings		= fec_enet_set_settings,
- 	.get_drvinfo		= fec_enet_get_drvinfo,
--	.get_link		= ethtool_op_get_link,
--	.get_ts_info		= fec_enet_get_ts_info,
- 	.nway_reset		= fec_enet_nway_reset,
-+	.get_link		= ethtool_op_get_link,
-+	.get_ringparam		= fec_enet_get_ringparam,
-+	.set_ringparam		= fec_enet_set_ringparam,
- #ifndef CONFIG_M5272
--	.get_ethtool_stats	= fec_enet_get_ethtool_stats,
-+	.get_pauseparam		= fec_enet_get_pauseparam,
-+	.set_pauseparam		= fec_enet_set_pauseparam,
- 	.get_strings		= fec_enet_get_strings,
-+	.get_ethtool_stats	= fec_enet_get_ethtool_stats,
- 	.get_sset_count		= fec_enet_get_sset_count,
- #endif
-+	.get_ts_info		= fec_enet_get_ts_info,
- };
- 
- static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
-@@ -1673,7 +2020,7 @@
- 	if (!phydev)
- 		return -ENODEV;
- 
--	if (fep->bufdesc_ex) {
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX) {
- 		if (cmd == SIOCSHWTSTAMP)
- 			return fec_ptp_set(ndev, rq);
- 		if (cmd == SIOCGHWTSTAMP)
-@@ -1688,23 +2035,33 @@
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 	unsigned int i;
- 	struct sk_buff *skb;
--	struct bufdesc	*bdp;
-+	union bufdesc_u *bdp;
- 
--	bdp = fep->rx_bd_base;
- 	for (i = 0; i < fep->rx_ring_size; i++) {
--		skb = fep->rx_skbuff[i];
-+		bdp = fec_enet_rx_get(i, fep);
- 
--		if (bdp->cbd_bufaddr)
--			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
-+		skb = fep->rx_skbuff[i];
-+		fep->rx_skbuff[i] = NULL;
-+		if (skb) {
-+			dma_unmap_single(&fep->pdev->dev, bdp->bd.cbd_bufaddr,
- 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
--		if (skb)
- 			dev_kfree_skb(skb);
--		bdp = fec_enet_get_nextdesc(bdp, fep);
-+		}
- 	}
- 
--	bdp = fep->tx_bd_base;
--	for (i = 0; i < fep->tx_ring_size; i++)
-+	for (i = 0; i < fep->tx_ring_size; i++) {
-+		bdp = fec_enet_tx_get(i, fep);
-+		if (bdp->bd.cbd_bufaddr)
-+			fec_enet_tx_unmap(i, bdp, fep);
- 		kfree(fep->tx_bounce[i]);
-+		fep->tx_bounce[i] = NULL;
-+		skb = fep->tx_skbuff[i];
-+		fep->tx_skbuff[i] = NULL;
-+		if (skb)
-+			dev_kfree_skb(skb);
-+	}
-+
-+	dma_free_coherent(NULL, PAGE_SIZE, fep->rx_bd_base, fep->rx_bd_dma);
- }
- 
- static int fec_enet_alloc_buffers(struct net_device *ndev)
-@@ -1712,59 +2069,82 @@
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 	unsigned int i;
- 	struct sk_buff *skb;
--	struct bufdesc	*bdp;
-+	union bufdesc_u *bdp;
-+	union bufdesc_u *rx_cbd_cpu, *tx_cbd_cpu;
-+	dma_addr_t rx_cbd_dma, tx_cbd_dma;
-+
-+	/* Allocate memory for buffer descriptors. */
-+	rx_cbd_cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &rx_cbd_dma,
-+					GFP_KERNEL);
-+	tx_cbd_cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &tx_cbd_dma,
-+					GFP_KERNEL);
-+	if (!rx_cbd_cpu || !tx_cbd_cpu) {
-+		if (rx_cbd_cpu)
-+			dma_free_coherent(NULL, PAGE_SIZE, rx_cbd_cpu, rx_cbd_dma);
-+		if (tx_cbd_cpu)
-+			dma_free_coherent(NULL, PAGE_SIZE, tx_cbd_cpu, tx_cbd_dma);
-+		return -ENOMEM;
-+	}
-+
-+	memset(rx_cbd_cpu, 0, PAGE_SIZE);
-+	memset(tx_cbd_cpu, 0, PAGE_SIZE);
-+
-+	/* Set receive and transmit descriptor base. */
-+	fep->rx_bd_base = rx_cbd_cpu;
-+	fep->rx_bd_dma = rx_cbd_dma;
-+	fep->tx_bd_base = tx_cbd_cpu;
-+	fep->tx_bd_dma = tx_cbd_dma;
- 
--	bdp = fep->rx_bd_base;
- 	for (i = 0; i < fep->rx_ring_size; i++) {
-+		dma_addr_t addr;
-+
- 		skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE);
--		if (!skb) {
--			fec_enet_free_buffers(ndev);
--			return -ENOMEM;
--		}
--		fep->rx_skbuff[i] = skb;
-+		if (!skb)
-+			goto err_alloc;
- 
--		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
-+		addr = dma_map_single(&fep->pdev->dev, skb->data,
- 				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
--		if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
--			fec_enet_free_buffers(ndev);
-+		if (dma_mapping_error(&fep->pdev->dev, addr)) {
-+			dev_kfree_skb(skb);
- 			if (net_ratelimit())
- 				netdev_err(ndev, "Rx DMA memory map failed\n");
--			return -ENOMEM;
-+			goto err_alloc;
- 		}
--		bdp->cbd_sc = BD_ENET_RX_EMPTY;
- 
--		if (fep->bufdesc_ex) {
--			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
--			ebdp->cbd_esc = BD_ENET_RX_INT;
--		}
-+		fep->rx_skbuff[i] = skb;
-+		bdp = fec_enet_rx_get(i, fep);
-+		bdp->bd.cbd_bufaddr = addr;
-+		bdp->bd.cbd_sc = BD_ENET_RX_EMPTY;
-+		/* Set the last buffer to wrap. */
-+		if (i == fep->rx_ring_size - 1)
-+			bdp->bd.cbd_sc |= BD_SC_WRAP;
- 
--		bdp = fec_enet_get_nextdesc(bdp, fep);
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX)
-+			bdp->ebd.cbd_esc = BD_ENET_RX_INT;
- 	}
- 
--	/* Set the last buffer to wrap. */
--	bdp = fec_enet_get_prevdesc(bdp, fep);
--	bdp->cbd_sc |= BD_SC_WRAP;
--
--	bdp = fep->tx_bd_base;
- 	for (i = 0; i < fep->tx_ring_size; i++) {
-+		bdp = fec_enet_tx_get(i, fep);
- 		fep->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
-+		if (!fep->tx_bounce[i])
-+			goto err_alloc;
- 
--		bdp->cbd_sc = 0;
--		bdp->cbd_bufaddr = 0;
--
--		if (fep->bufdesc_ex) {
--			struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
--			ebdp->cbd_esc = BD_ENET_TX_INT;
--		}
-+		/* Set the last buffer to wrap. */
-+		if (i == fep->tx_ring_size - 1)
-+			bdp->bd.cbd_sc = BD_SC_WRAP;
-+		else
-+			bdp->bd.cbd_sc = 0;
-+		bdp->bd.cbd_bufaddr = 0;
- 
--		bdp = fec_enet_get_nextdesc(bdp, fep);
-+		if (fep->flags & FEC_FLAG_BUFDESC_EX)
-+			bdp->ebd.cbd_esc = BD_ENET_TX_INT;
- 	}
- 
--	/* Set the last buffer to wrap. */
--	bdp = fec_enet_get_prevdesc(bdp, fep);
--	bdp->cbd_sc |= BD_SC_WRAP;
--
- 	return 0;
-+
-+ err_alloc:
-+	fec_enet_free_buffers(ndev);
-+	return -ENOMEM;
- }
- 
- static int
-@@ -1788,10 +2168,12 @@
- 		return ret;
- 	}
- 
-+	mutex_lock(&fep->mutex);
-+	fec_restart(ndev);
-+	mutex_unlock(&fep->mutex);
- 	napi_enable(&fep->napi);
- 	phy_start(fep->phy_dev);
- 	netif_start_queue(ndev);
--	fep->opened = 1;
- 	return 0;
- }
- 
-@@ -1800,17 +2182,19 @@
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
--	/* Don't know what to do yet. */
--	napi_disable(&fep->napi);
--	fep->opened = 0;
--	netif_stop_queue(ndev);
--	fec_stop(ndev);
-+	phy_stop(fep->phy_dev);
- 
--	if (fep->phy_dev) {
--		phy_stop(fep->phy_dev);
--		phy_disconnect(fep->phy_dev);
-+	if (netif_device_present(ndev)) {
-+		napi_disable(&fep->napi);
-+		netif_tx_disable(ndev);
-+		mutex_lock(&fep->mutex);
-+		fec_stop(ndev);
-+		mutex_unlock(&fep->mutex);
- 	}
- 
-+	phy_disconnect(fep->phy_dev);
-+	fep->phy_dev = NULL;
-+
- 	fec_enet_free_buffers(ndev);
- 
- 	return 0;
-@@ -1935,28 +2319,67 @@
- }
- #endif
- 
-+static netdev_features_t fec_fix_features(struct net_device *ndev,
-+	netdev_features_t features)
-+{
-+	struct fec_enet_private *fep = netdev_priv(ndev);
-+
-+	/*
-+	 * NETIF_F_SG requires a minimum transmit ring size.  If we
-+	 * have less than this size, we can't support this feature.
-+	 */
-+	if (fep->tx_ring_size < TX_RING_SIZE_MIN_SG)
-+		features &= ~NETIF_F_SG;
-+
-+	return features;
-+}
-+
-+#define FEATURES_NEED_QUIESCE (NETIF_F_RXCSUM | NETIF_F_SG)
-+
- static int fec_set_features(struct net_device *netdev,
- 	netdev_features_t features)
- {
- 	struct fec_enet_private *fep = netdev_priv(netdev);
- 	netdev_features_t changed = features ^ netdev->features;
- 
-+	/* Quiesce the device if necessary */
-+	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
-+		mutex_lock(&fep->mutex);
-+		napi_disable(&fep->napi);
-+		netif_tx_lock_bh(netdev);
-+		fec_stop(netdev);
-+	}
-+
- 	netdev->features = features;
- 
- 	/* Receive checksum has been changed */
- 	if (changed & NETIF_F_RXCSUM) {
- 		if (features & NETIF_F_RXCSUM)
--			fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
-+			fep->flags |= FEC_FLAG_RX_CSUM;
- 		else
--			fep->csum_flags &= ~FLAG_RX_CSUM_ENABLED;
-+			fep->flags &= ~FEC_FLAG_RX_CSUM;
-+	}
- 
--		if (netif_running(netdev)) {
--			fec_stop(netdev);
--			fec_restart(netdev, fep->phy_dev->duplex);
--			netif_wake_queue(netdev);
--		} else {
--			fec_restart(netdev, fep->phy_dev->duplex);
--		}
-+	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
-+		if (features & NETIF_F_HW_VLAN_CTAG_RX)
-+			fep->flags |= FEC_FLAG_RX_VLAN;
-+		else
-+			fep->flags &= ~FEC_FLAG_RX_VLAN;
-+	}
-+
-+	/* Set the appropriate minimum transmit ring free threshold */
-+	if (features & NETIF_F_SG)
-+		fep->tx_min = MAX_SKB_FRAGS + 1;
-+	else
-+		fep->tx_min = 1;
-+
-+	/* Resume the device after updates */
-+	if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) {
-+		fec_restart(netdev);
-+		netif_wake_queue(netdev);
-+		netif_tx_unlock_bh(netdev);
-+		napi_enable(&fep->napi);
-+		mutex_unlock(&fep->mutex);
- 	}
- 
- 	return 0;
-@@ -1975,27 +2398,13 @@
- #ifdef CONFIG_NET_POLL_CONTROLLER
- 	.ndo_poll_controller	= fec_poll_controller,
- #endif
-+	.ndo_fix_features	= fec_fix_features,
- 	.ndo_set_features	= fec_set_features,
- };
- 
-- /*
--  * XXX:  We need to clean up on failure exits here.
--  *
--  */
--static int fec_enet_init(struct net_device *ndev)
-+static void fec_enet_init(struct net_device *ndev)
- {
- 	struct fec_enet_private *fep = netdev_priv(ndev);
--	const struct platform_device_id *id_entry =
--				platform_get_device_id(fep->pdev);
--	struct bufdesc *cbd_base;
--
--	/* Allocate memory for buffer descriptors. */
--	cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
--				      GFP_KERNEL);
--	if (!cbd_base)
--		return -ENOMEM;
--
--	memset(cbd_base, 0, PAGE_SIZE);
- 
- 	fep->netdev = ndev;
- 
-@@ -2008,13 +2417,8 @@
- 	fep->tx_ring_size = TX_RING_SIZE;
- 	fep->rx_ring_size = RX_RING_SIZE;
- 
--	/* Set receive and transmit descriptor base. */
--	fep->rx_bd_base = cbd_base;
--	if (fep->bufdesc_ex)
--		fep->tx_bd_base = (struct bufdesc *)
--			(((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size);
--	else
--		fep->tx_bd_base = cbd_base + fep->rx_ring_size;
-+	fep->rx_bd_base = fep->tx_bd_base = NULL;
-+	fep->rx_bd_dma = fep->tx_bd_dma = 0;
- 
- 	/* The FEC Ethernet specific entries in the device structure */
- 	ndev->watchdog_timeo = TX_TIMEOUT;
-@@ -2024,24 +2428,37 @@
- 	writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
- 	netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, NAPI_POLL_WEIGHT);
- 
--	if (id_entry->driver_data & FEC_QUIRK_HAS_VLAN) {
--		/* enable hw VLAN support */
--		ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
--		ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
--	}
--
--	if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) {
--		/* enable hw accelerator */
--		ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
--				| NETIF_F_RXCSUM);
--		ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
--				| NETIF_F_RXCSUM);
--		fep->csum_flags |= FLAG_RX_CSUM_ENABLED;
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX) {
-+		/* Features which require the enhanced buffer descriptors */
-+		if (fep->quirks & FEC_QUIRK_HAS_VLAN) {
-+			/* enable hw VLAN support */
-+			ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
-+			ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
-+			fep->flags |= FEC_FLAG_RX_VLAN;
-+		}
-+
-+		if (fep->quirks & FEC_QUIRK_HAS_CSUM) {
-+			/* enable hw accelerator */
-+			ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-+					| NETIF_F_RXCSUM);
-+			ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
-+					| NETIF_F_RXCSUM);
-+			fep->flags |= FEC_FLAG_RX_CSUM;
-+		}
- 	}
- 
--	fec_restart(ndev, 0);
-+	if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME)) {
-+		/* don't enable SG if we need to swap frames */
-+		ndev->features |= NETIF_F_SG;
-+		ndev->hw_features |= NETIF_F_SG;
-+	}
- 
--	return 0;
-+	if (ndev->features & NETIF_F_SG)
-+		fep->tx_min = MAX_SKB_FRAGS + 1;
-+	else
-+		fep->tx_min = 1;
-+
-+	fec_restart(ndev);
- }
- 
- #ifdef CONFIG_OF
-@@ -2107,11 +2524,16 @@
- 	/* setup board info structure */
- 	fep = netdev_priv(ndev);
- 
-+	mutex_init(&fep->mutex);
-+
-+	if (pdev->id_entry)
-+		fep->quirks = pdev->id_entry->driver_data;
- #if !defined(CONFIG_M5272)
- 	/* default enable pause frame auto negotiation */
--	if (pdev->id_entry &&
--	    (pdev->id_entry->driver_data & FEC_QUIRK_HAS_GBIT))
--		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG;
-+	if (fep->quirks & FEC_QUIRK_HAS_GBIT)
-+		fep->pause_flag |= FEC_PAUSE_FLAG_AUTONEG |
-+				   FEC_PAUSE_FLAG_TX |
-+				   FEC_PAUSE_FLAG_RX;
- #endif
- 
- 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-@@ -2124,7 +2546,9 @@
- 	fep->pdev = pdev;
- 	fep->dev_id = dev_id++;
- 
--	fep->bufdesc_ex = 0;
-+	fep->flags = 0;
-+	if (pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX)
-+		fep->flags |= FEC_FLAG_BUFDESC_EX;
- 
- 	platform_set_drvdata(pdev, ndev);
- 
-@@ -2157,11 +2581,9 @@
- 		fep->clk_enet_out = NULL;
- 
- 	fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
--	fep->bufdesc_ex =
--		pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX;
- 	if (IS_ERR(fep->clk_ptp)) {
- 		fep->clk_ptp = NULL;
--		fep->bufdesc_ex = 0;
-+		fep->flags &= ~FEC_FLAG_BUFDESC_EX;
- 	}
- 
- 	ret = clk_prepare_enable(fep->clk_ahb);
-@@ -2198,12 +2620,10 @@
- 
- 	fec_reset_phy(pdev);
- 
--	if (fep->bufdesc_ex)
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX)
- 		fec_ptp_init(pdev);
- 
--	ret = fec_enet_init(ndev);
--	if (ret)
--		goto failed_init;
-+	fec_enet_init(ndev);
- 
- 	for (i = 0; i < FEC_IRQ_NUM; i++) {
- 		irq = platform_get_irq(pdev, i);
-@@ -2230,17 +2650,16 @@
- 	if (ret)
- 		goto failed_register;
- 
--	if (fep->bufdesc_ex && fep->ptp_clock)
-+	if (fep->flags & FEC_FLAG_BUFDESC_EX && fep->ptp_clock)
- 		netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
- 
--	INIT_DELAYED_WORK(&(fep->delay_work.delay_work), fec_enet_work);
-+	INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
- 	return 0;
- 
- failed_register:
- 	fec_enet_mii_remove(fep);
- failed_mii_init:
- failed_irq:
--failed_init:
- 	if (fep->reg_phy)
- 		regulator_disable(fep->reg_phy);
- failed_regulator:
-@@ -2266,7 +2685,7 @@
- 	struct net_device *ndev = platform_get_drvdata(pdev);
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
--	cancel_delayed_work_sync(&(fep->delay_work.delay_work));
-+	cancel_work_sync(&fep->tx_timeout_work);
- 	unregister_netdev(ndev);
- 	fec_enet_mii_remove(fep);
- 	del_timer_sync(&fep->time_keep);
-@@ -2292,10 +2711,19 @@
- 	struct net_device *ndev = dev_get_drvdata(dev);
- 	struct fec_enet_private *fep = netdev_priv(ndev);
- 
-+	rtnl_lock();
- 	if (netif_running(ndev)) {
--		fec_stop(ndev);
-+		phy_stop(fep->phy_dev);
-+		napi_disable(&fep->napi);
-+		netif_tx_lock_bh(ndev);
- 		netif_device_detach(ndev);
-+		netif_tx_unlock_bh(ndev);
-+		mutex_lock(&fep->mutex);
-+		fec_stop(ndev);
-+		mutex_unlock(&fep->mutex);
- 	}
-+	rtnl_unlock();
-+
- 	if (fep->clk_ptp)
- 		clk_disable_unprepare(fep->clk_ptp);
- 	if (fep->clk_enet_out)
-@@ -2342,10 +2770,18 @@
- 			goto failed_clk_ptp;
- 	}
- 
-+	rtnl_lock();
- 	if (netif_running(ndev)) {
--		fec_restart(ndev, fep->full_duplex);
-+		mutex_lock(&fep->mutex);
-+		fec_restart(ndev);
-+		mutex_unlock(&fep->mutex);
-+		netif_tx_lock_bh(ndev);
- 		netif_device_attach(ndev);
-+		netif_tx_unlock_bh(ndev);
-+		napi_enable(&fep->napi);
-+		phy_start(fep->phy_dev);
- 	}
-+	rtnl_unlock();
- 
- 	return 0;
- 
-diff -Nur linux-3.15-rc6.orig/drivers/regulator/anatop-regulator.c linux-3.15-rc6/drivers/regulator/anatop-regulator.c
---- linux-3.15-rc6.orig/drivers/regulator/anatop-regulator.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/regulator/anatop-regulator.c	2014-05-23 11:26:48.312940058 +0200
-@@ -267,6 +267,7 @@
- 	config.driver_data = sreg;
- 	config.of_node = pdev->dev.of_node;
- 	config.regmap = sreg->anatop;
-+	config.ena_gpio = -EINVAL;
- 
- 	/* Only core regulators have the ramp up delay configuration. */
- 	if (sreg->control_reg && sreg->delay_bit_width) {
-diff -Nur linux-3.15-rc6.orig/drivers/regulator/core.c linux-3.15-rc6/drivers/regulator/core.c
---- linux-3.15-rc6.orig/drivers/regulator/core.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/regulator/core.c	2014-05-23 11:26:48.312940058 +0200
-@@ -3459,7 +3459,7 @@
- 
- 	dev_set_drvdata(&rdev->dev, rdev);
- 
--	if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
-+	if (gpio_is_valid(config->ena_gpio)) {
- 		ret = regulator_ena_gpio_request(rdev, config);
- 		if (ret != 0) {
- 			rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
-diff -Nur linux-3.15-rc6.orig/drivers/regulator/dummy.c linux-3.15-rc6/drivers/regulator/dummy.c
---- linux-3.15-rc6.orig/drivers/regulator/dummy.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/regulator/dummy.c	2014-05-23 11:26:48.312940058 +0200
-@@ -48,6 +48,7 @@
- 
- 	config.dev = &pdev->dev;
- 	config.init_data = &dummy_initdata;
-+	config.ena_gpio = -EINVAL;
- 
- 	dummy_regulator_rdev = regulator_register(&dummy_desc, &config);
- 	if (IS_ERR(dummy_regulator_rdev)) {
-diff -Nur linux-3.15-rc6.orig/drivers/regulator/fixed.c linux-3.15-rc6/drivers/regulator/fixed.c
---- linux-3.15-rc6.orig/drivers/regulator/fixed.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/regulator/fixed.c	2014-05-23 11:26:48.312940058 +0200
-@@ -161,9 +161,7 @@
- 		drvdata->desc.n_voltages = 1;
- 
- 	drvdata->desc.fixed_uV = config->microvolts;
--
--	if (config->gpio >= 0)
--		cfg.ena_gpio = config->gpio;
-+	cfg.ena_gpio = config->gpio;
- 	cfg.ena_gpio_invert = !config->enable_high;
- 	if (config->enabled_at_boot) {
- 		if (config->enable_high)
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/drm-ddc-connector.c linux-3.15-rc6/drivers/staging/imx-drm/drm-ddc-connector.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/drm-ddc-connector.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/drm-ddc-connector.c	2014-05-23 11:26:48.312940058 +0200
-@@ -0,0 +1,92 @@
-+#include <linux/i2c.h>
-+#include <linux/module.h>
-+#include <drm/drmP.h>
-+#include <drm/drm_crtc_helper.h>
-+#include <drm/drm_edid.h>
-+
-+#include "drm-ddc-connector.h"
-+
-+static enum drm_connector_status
-+drm_ddc_connector_detect(struct drm_connector *connector, bool force)
-+{
-+	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
-+
-+	return ddc_conn->detect ? ddc_conn->detect(connector, force) :
-+		connector_status_connected;
-+}
-+
-+int drm_ddc_connector_get_modes(struct drm_connector *connector)
-+{
-+	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
-+	struct edid *edid;
-+	int ret = 0;
-+
-+	if (!ddc_conn->ddc)
-+		return 0;
-+
-+	edid = drm_get_edid(connector, ddc_conn->ddc);
-+	if (edid) {
-+		drm_mode_connector_update_edid_property(connector, edid);
-+		ret = drm_add_edid_modes(connector, edid);
-+		/* Store the ELD */
-+		drm_edid_to_eld(connector, edid);
-+		kfree(edid);
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(drm_ddc_connector_get_modes);
-+
-+static void drm_ddc_connector_destroy(struct drm_connector *connector)
-+{
-+	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
-+
-+	drm_sysfs_connector_remove(connector);
-+	drm_connector_cleanup(connector);
-+	if (ddc_conn->ddc)
-+		i2c_put_adapter(ddc_conn->ddc);
-+}
-+
-+static const struct drm_connector_funcs drm_ddc_connector_funcs = {
-+	.dpms = drm_helper_connector_dpms,
-+	.fill_modes = drm_helper_probe_single_connector_modes,
-+	.detect = drm_ddc_connector_detect,
-+	.destroy = drm_ddc_connector_destroy,
-+};
-+
-+int drm_ddc_connector_add(struct drm_device *drm,
-+	struct drm_ddc_connector *ddc_conn, int connector_type)
-+{
-+	drm_connector_init(drm, &ddc_conn->connector, &drm_ddc_connector_funcs,
-+			   connector_type);
-+	return 0;
-+}
-+EXPORT_SYMBOL_GPL(drm_ddc_connector_add);
-+
-+struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
-+	struct device_node *np, void *private)
-+{
-+	struct drm_ddc_connector *ddc_conn;
-+	struct device_node *ddc_node;
-+
-+	ddc_conn = devm_kzalloc(drm->dev, sizeof(*ddc_conn), GFP_KERNEL);
-+	if (!ddc_conn)
-+		return ERR_PTR(-ENOMEM);
-+
-+	ddc_conn->private = private;
-+
-+	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
-+	if (ddc_node) {
-+		ddc_conn->ddc = of_find_i2c_adapter_by_node(ddc_node);
-+		of_node_put(ddc_node);
-+		if (!ddc_conn->ddc)
-+			return ERR_PTR(-EPROBE_DEFER);
-+	}
-+
-+	return ddc_conn;
-+}
-+EXPORT_SYMBOL_GPL(drm_ddc_connector_create);
-+
-+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Generic DRM DDC connector module");
-+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/drm-ddc-connector.h linux-3.15-rc6/drivers/staging/imx-drm/drm-ddc-connector.h
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/drm-ddc-connector.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/drm-ddc-connector.h	2014-05-23 11:26:48.312940058 +0200
-@@ -0,0 +1,26 @@
-+#ifndef DRM_DDC_CONNECTOR_H
-+#define DRM_DDC_CONNECTOR_H
-+
-+struct drm_ddc_connector {
-+	struct i2c_adapter *ddc;
-+	struct drm_connector connector;
-+	enum drm_connector_status (*detect)(struct drm_connector *, bool);
-+	void *private;
-+};
-+
-+#define to_ddc_conn(c) container_of(c, struct drm_ddc_connector, connector)
-+
-+int drm_ddc_connector_get_modes(struct drm_connector *connector);
-+int drm_ddc_connector_add(struct drm_device *drm,
-+	struct drm_ddc_connector *ddc_conn, int connector_type);
-+struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
-+	struct device_node *np, void *private);
-+
-+static inline void *drm_ddc_private(struct drm_connector *connector)
-+{
-+	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
-+
-+	return ddc_conn->private;
-+}
-+
-+#endif
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-audio.c linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-audio.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-audio.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-audio.c	2014-05-23 11:26:48.316940071 +0200
-@@ -0,0 +1,654 @@
-+/*
-+ * DesignWare HDMI audio driver
-+ *
-+ * 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.
-+ *
-+ * Written and tested against the (alleged) DW HDMI Tx found in iMX6S.
-+ */
-+#include <linux/delay.h>
-+#include <linux/io.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include <sound/asoundef.h>
-+#include <sound/core.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+
-+#include "dw-hdmi-audio.h"
-+
-+#define DRIVER_NAME "dw-hdmi-audio"
-+
-+/* Provide some bits rather than bit offsets */
-+enum {
-+	HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
-+	HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
-+	HDMI_AHB_DMA_START_START = BIT(0),
-+	HDMI_AHB_DMA_STOP_STOP = BIT(0),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
-+		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
-+	HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
-+	HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
-+	HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
-+	HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
-+	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
-+	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
-+	HDMI_IH_AHBDMAAUD_STAT0_ALL =
-+		HDMI_IH_AHBDMAAUD_STAT0_ERROR |
-+		HDMI_IH_AHBDMAAUD_STAT0_LOST |
-+		HDMI_IH_AHBDMAAUD_STAT0_RETRY |
-+		HDMI_IH_AHBDMAAUD_STAT0_DONE |
-+		HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
-+		HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
-+	HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
-+	HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
-+	HDMI_AHB_DMA_CONF0_INCR4 = 0,
-+	HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
-+	HDMI_AHB_DMA_MASK_DONE = BIT(7),
-+	HDMI_REVISION_ID = 0x0001,
-+	HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
-+	HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
-+	HDMI_AUD_N1 = 0x3200,
-+	HDMI_AUD_CTS1 = 0x3203,
-+	HDMI_AHB_DMA_CONF0 = 0x3600,
-+	HDMI_AHB_DMA_START = 0x3601,
-+	HDMI_AHB_DMA_STOP = 0x3602,
-+	HDMI_AHB_DMA_THRSLD = 0x3603,
-+	HDMI_AHB_DMA_STRADDR0 = 0x3604,
-+	HDMI_AHB_DMA_STPADDR0 = 0x3608,
-+	HDMI_AHB_DMA_STAT = 0x3612,
-+	HDMI_AHB_DMA_STAT_FULL = BIT(1),
-+	HDMI_AHB_DMA_MASK = 0x3614,
-+	HDMI_AHB_DMA_POL = 0x3615,
-+	HDMI_AHB_DMA_CONF1 = 0x3616,
-+	HDMI_AHB_DMA_BUFFPOL = 0x361a,
-+};
-+
-+struct snd_dw_hdmi {
-+	struct snd_card *card;
-+	struct snd_pcm *pcm;
-+	struct dw_hdmi_audio_data data;
-+	struct snd_pcm_substream *substream;
-+	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
-+	void *buf_src;
-+	void *buf_dst;
-+	dma_addr_t buf_addr;
-+	unsigned buf_offset;
-+	unsigned buf_period;
-+	unsigned buf_size;
-+	unsigned channels;
-+	uint8_t revision;
-+	uint8_t iec_offset;
-+	uint8_t cs[192][8];
-+};
-+
-+static void dw_hdmi_writel(unsigned long val, void __iomem *ptr)
-+{
-+	writeb_relaxed(val, ptr);
-+	writeb_relaxed(val >> 8, ptr + 1);
-+	writeb_relaxed(val >> 16, ptr + 2);
-+	writeb_relaxed(val >> 24, ptr + 3);
-+}
-+
-+/*
-+ * Convert to hardware format: The userspace buffer contains IEC958 samples,
-+ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
-+ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
-+ * samples in 23..0.
-+ *
-+ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
-+ *
-+ * Ideally, we could do with having the data properly formatted in userspace.
-+ */
-+static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
-+	size_t offset, size_t bytes)
-+{
-+	uint32_t *src = dw->buf_src + offset;
-+	uint32_t *dst = dw->buf_dst + offset;
-+	uint32_t *end = dw->buf_src + offset + bytes;
-+
-+	do {
-+		uint32_t b, sample = *src++;
-+
-+		b = (sample & 8) << (28 - 3);
-+
-+		sample >>= 4;
-+
-+		*dst++ = sample | b;
-+	} while (src < end);
-+}
-+
-+static uint32_t parity(uint32_t sample)
-+{
-+	sample ^= sample >> 16;
-+	sample ^= sample >> 8;
-+	sample ^= sample >> 4;
-+	sample ^= sample >> 2;
-+	sample ^= sample >> 1;
-+	return (sample & 1) << 27;
-+}
-+
-+static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
-+	size_t offset, size_t bytes)
-+{
-+	uint32_t *src = dw->buf_src + offset;
-+	uint32_t *dst = dw->buf_dst + offset;
-+	uint32_t *end = dw->buf_src + offset + bytes;
-+
-+	do {
-+		unsigned i;
-+		uint8_t *cs;
-+
-+		cs = dw->cs[dw->iec_offset++];
-+		if (dw->iec_offset >= 192)
-+			dw->iec_offset = 0;
-+
-+		i = dw->channels;
-+		do {
-+			uint32_t sample = *src++;
-+
-+			sample &= ~0xff000000;
-+			sample |= *cs++ << 24;
-+			sample |= parity(sample & ~0xf8000000);
-+
-+			*dst++ = sample;
-+		} while (--i);
-+	} while (src < end);
-+}
-+
-+static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
-+	struct snd_pcm_runtime *runtime)
-+{
-+	uint8_t cs[4];
-+	unsigned ch, i, j;
-+
-+	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
-+	cs[1] = IEC958_AES1_CON_GENERAL;
-+	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC;
-+	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM;
-+
-+	switch (runtime->rate) {
-+	case 32000:
-+		cs[3] |= IEC958_AES3_CON_FS_32000;
-+		break;
-+	case 44100:
-+		cs[3] |= IEC958_AES3_CON_FS_44100;
-+		break;
-+	case 48000:
-+		cs[3] |= IEC958_AES3_CON_FS_48000;
-+		break;
-+	case 88200:
-+		cs[3] |= IEC958_AES3_CON_FS_88200;
-+		break;
-+	case 96000:
-+		cs[3] |= IEC958_AES3_CON_FS_96000;
-+		break;
-+	case 176400:
-+		cs[3] |= IEC958_AES3_CON_FS_176400;
-+		break;
-+	case 192000:
-+		cs[3] |= IEC958_AES3_CON_FS_192000;
-+		break;
-+	}
-+
-+	memset(dw->cs, 0, sizeof(dw->cs));
-+
-+	for (ch = 0; ch < 8; ch++) {
-+		cs[2] &= ~IEC958_AES2_CON_CHANNEL;
-+		cs[2] |= (ch + 1) << 4;
-+
-+		for (i = 0; i < ARRAY_SIZE(cs); i++) {
-+			unsigned c = cs[i];
-+
-+			for (j = 0; j < 8; j++, c >>= 1)
-+				dw->cs[i * 8 + j][ch] = (c & 1) << 2;
-+		}
-+	}
-+	dw->cs[0][0] |= BIT(4);
-+}
-+
-+static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
-+{
-+	void __iomem *base = dw->data.base;
-+	unsigned offset = dw->buf_offset;
-+	unsigned period = dw->buf_period;
-+	u32 start, stop;
-+
-+	dw->reformat(dw, offset, period);
-+
-+	/* Clear all irqs before enabling irqs and starting DMA */
-+	writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
-+		       base + HDMI_IH_AHBDMAAUD_STAT0);
-+
-+	start = dw->buf_addr + offset;
-+	stop = start + period - 1;
-+
-+	/* Setup the hardware start/stop addresses */
-+	dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
-+	dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
-+
-+	writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
-+	writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
-+
-+	offset += period;
-+	if (offset >= dw->buf_size)
-+		offset = 0;
-+	dw->buf_offset = offset;
-+}
-+
-+static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
-+{
-+	dw->substream = NULL;
-+
-+	/* Disable interrupts before disabling DMA */
-+	writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
-+	writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
-+}
-+
-+static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
-+{
-+	struct snd_dw_hdmi *dw = data;
-+	struct snd_pcm_substream *substream;
-+	unsigned stat;
-+
-+	stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
-+	if (!stat)
-+		return IRQ_NONE;
-+
-+	writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
-+
-+	substream = dw->substream;
-+	if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
-+		snd_pcm_period_elapsed(substream);
-+		if (dw->substream)
-+			dw_hdmi_start_dma(dw);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+
-+static struct snd_pcm_hardware dw_hdmi_hw = {
-+	.info = SNDRV_PCM_INFO_INTERLEAVED |
-+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+		SNDRV_PCM_INFO_MMAP |
-+		SNDRV_PCM_INFO_MMAP_VALID,
-+	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
-+		   SNDRV_PCM_FMTBIT_S24_LE,
-+	.rates = SNDRV_PCM_RATE_32000 |
-+		 SNDRV_PCM_RATE_44100 |
-+		 SNDRV_PCM_RATE_48000 |
-+		 SNDRV_PCM_RATE_88200 |
-+		 SNDRV_PCM_RATE_96000 |
-+		 SNDRV_PCM_RATE_176400 |
-+		 SNDRV_PCM_RATE_192000,
-+	.channels_min = 2,
-+	.channels_max = 8,
-+	.buffer_bytes_max = 64 * 1024,
-+	.period_bytes_min = 256,
-+	.period_bytes_max = 8192,	/* ERR004323: must limit to 8k */
-+	.periods_min = 2,
-+	.periods_max = 16,
-+	.fifo_size = 0,
-+};
-+
-+static unsigned rates_mask[] = {
-+	SNDRV_PCM_RATE_32000,
-+	SNDRV_PCM_RATE_44100,
-+	SNDRV_PCM_RATE_48000,
-+	SNDRV_PCM_RATE_88200,
-+	SNDRV_PCM_RATE_96000,
-+	SNDRV_PCM_RATE_176400,
-+	SNDRV_PCM_RATE_192000,
-+};
-+
-+static void dw_hdmi_parse_eld(struct snd_dw_hdmi *dw,
-+	struct snd_pcm_runtime *runtime)
-+{
-+	u8 *sad, *eld = dw->data.eld;
-+	unsigned eld_ver,  mnl, sad_count, rates, rate_mask, i;
-+	unsigned max_channels;
-+
-+	eld_ver = eld[0] >> 3;
-+	if (eld_ver != 2 && eld_ver != 31)
-+		return;
-+
-+	mnl = eld[4] & 0x1f;
-+	if (mnl > 16)
-+		return;
-+
-+	sad_count = eld[5] >> 4;
-+	sad = eld + 20 + mnl;
-+
-+	/* Start from the basic audio settings */
-+	max_channels = 2;
-+	rates = 7;
-+	while (sad_count > 0) {
-+		switch (sad[0] & 0x78) {
-+		case 0x08: /* PCM */
-+			max_channels = max(max_channels, (sad[0] & 7) + 1u);
-+			rates |= sad[1];
-+			break;
-+		}
-+		sad += 3;
-+		sad_count -= 1;
-+	}
-+
-+	for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
-+		if (rates & 1 << i)
-+			rate_mask |= rates_mask[i];
-+
-+	runtime->hw.rates &= rate_mask;
-+	runtime->hw.channels_max = min(runtime->hw.channels_max, max_channels);
-+}
-+
-+static int dw_hdmi_open(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_dw_hdmi *dw = substream->private_data;
-+	void __iomem *base = dw->data.base;
-+	int ret;
-+
-+	/* Clear FIFO */
-+	writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
-+		       base + HDMI_AHB_DMA_CONF0);
-+
-+	/* Configure interrupt polarities */
-+	writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
-+	writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
-+
-+	/* Keep interrupts masked, and clear any pending */
-+	writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
-+	writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
-+
-+	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
-+			  "dw-hdmi-audio", dw);
-+	if (ret)
-+		return ret;
-+
-+	/* Un-mute done interrupt */
-+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
-+		       ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
-+		       base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
-+
-+	runtime->hw = dw_hdmi_hw;
-+	dw_hdmi_parse_eld(dw, runtime);
-+	snd_pcm_limit_hw_rates(runtime);
-+
-+	return 0;
-+}
-+
-+static int dw_hdmi_close(struct snd_pcm_substream *substream)
-+{
-+	struct snd_dw_hdmi *dw = substream->private_data;
-+
-+	/* Mute all interrupts */
-+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
-+		       dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
-+
-+	free_irq(dw->data.irq, dw);
-+
-+	return 0;
-+}
-+
-+static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
-+{
-+	return snd_pcm_lib_free_vmalloc_buffer(substream);
-+}
-+
-+static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
-+	struct snd_pcm_hw_params *params)
-+{
-+	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
-+						params_buffer_bytes(params));
-+}
-+
-+static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_dw_hdmi *dw = substream->private_data;
-+	uint8_t threshold, conf0, conf1;
-+
-+	/* Setup as per 3.0.5 FSL 4.1.0 BSP */
-+	switch (dw->revision) {
-+	case 0x0a:
-+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
-+			HDMI_AHB_DMA_CONF0_INCR4;
-+		if (runtime->channels == 2)
-+			threshold = 126;
-+		else
-+			threshold = 124;
-+		break;
-+	case 0x1a:
-+		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
-+			HDMI_AHB_DMA_CONF0_INCR8;
-+		threshold = 128;
-+		break;
-+	default:
-+		/* NOTREACHED */
-+		return -EINVAL;
-+	}
-+
-+	dw->data.set_sample_rate(dw->data.hdmi, runtime->rate);
-+
-+	/* Minimum number of bytes in the fifo. */
-+	runtime->hw.fifo_size = threshold * 32;
-+
-+	conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
-+	conf1 = (1 << runtime->channels) - 1;
-+
-+	writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
-+	writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
-+	writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
-+
-+	switch (runtime->format) {
-+	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-+		dw->reformat = dw_hdmi_reformat_iec958;
-+		break;
-+	case SNDRV_PCM_FORMAT_S24_LE:
-+		dw_hdmi_create_cs(dw, runtime);
-+		dw->reformat = dw_hdmi_reformat_s24;
-+		break;
-+	}
-+	dw->iec_offset = 0;
-+	dw->channels = runtime->channels;
-+	dw->buf_src  = runtime->dma_area;
-+	dw->buf_dst  = substream->dma_buffer.area;
-+	dw->buf_addr = substream->dma_buffer.addr;
-+	dw->buf_period = snd_pcm_lib_period_bytes(substream);
-+	dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
-+
-+	return 0;
-+}
-+
-+static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
-+{
-+	struct snd_dw_hdmi *dw = substream->private_data;
-+	void __iomem *base = dw->data.base;
-+	unsigned n[3], cts[3];
-+	int ret = 0, i;
-+	bool err005174;
-+
-+	switch (cmd) {
-+	case SNDRV_PCM_TRIGGER_START:
-+		err005174 = dw->revision == 0x0a;
-+		if (err005174) {
-+			for (i = 2; i >= 1; i--) {
-+				n[i] = readb_relaxed(base + HDMI_AUD_N1 + i);
-+				cts[i] = readb_relaxed(base + HDMI_AUD_CTS1 + i);
-+				writeb_relaxed(0, base + HDMI_AUD_N1 + i);
-+				writeb_relaxed(0, base + HDMI_AUD_CTS1 + i);
-+			}
-+		}
-+
-+		dw->buf_offset = 0;
-+		dw->substream = substream;
-+		dw_hdmi_start_dma(dw);
-+
-+		if (err005174) {
-+			for (i = 2; i >= 1; i--)
-+				writeb_relaxed(cts[i], base + HDMI_AUD_CTS1 + i);
-+			for (i = 2; i >= 1; i--)
-+				writeb_relaxed(n[i], base + HDMI_AUD_N1 + i);
-+		}
-+
-+		substream->runtime->delay = substream->runtime->period_size;
-+		break;
-+
-+	case SNDRV_PCM_TRIGGER_STOP:
-+		dw_hdmi_stop_dma(dw);
-+		break;
-+
-+	default:
-+		ret = -EINVAL;
-+		break;
-+	}
-+
-+	return ret;
-+}
-+
-+static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
-+{
-+	struct snd_pcm_runtime *runtime = substream->runtime;
-+	struct snd_dw_hdmi *dw = substream->private_data;
-+
-+	return bytes_to_frames(runtime, dw->buf_offset);
-+}
-+
-+static struct snd_pcm_ops snd_dw_hdmi_ops = {
-+	.open = dw_hdmi_open,
-+	.close = dw_hdmi_close,
-+	.ioctl = snd_pcm_lib_ioctl,
-+	.hw_params = dw_hdmi_hw_params,
-+	.hw_free = dw_hdmi_hw_free,
-+	.prepare = dw_hdmi_prepare,
-+	.trigger = dw_hdmi_trigger,
-+	.pointer = dw_hdmi_pointer,
-+	.page = snd_pcm_lib_get_vmalloc_page,
-+};
-+
-+static int snd_dw_hdmi_probe(struct platform_device *pdev)
-+{
-+	const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
-+	struct device *dev = pdev->dev.parent;
-+	struct snd_dw_hdmi *dw;
-+	struct snd_card *card;
-+	struct snd_pcm *pcm;
-+	unsigned revision;
-+	int ret;
-+
-+	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
-+		       data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
-+	revision = readb_relaxed(data->base + HDMI_REVISION_ID);
-+	if (revision != 0x0a && revision != 0x1a) {
-+		dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
-+			revision);
-+		return -ENXIO;
-+	}
-+
-+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-+			      THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
-+	if (ret < 0)
-+		return ret;
-+
-+	snd_card_set_dev(card, dev);
-+
-+	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
-+	strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
-+	snprintf(card->longname, sizeof(card->longname),
-+		 "%s rev 0x%02x, irq %d", card->shortname, revision,
-+		 data->irq);
-+
-+	dw = card->private_data;
-+	dw->card = card;
-+	dw->data = *data;
-+	dw->revision = revision;
-+
-+	ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
-+	if (ret < 0)
-+		goto err;
-+
-+	dw->pcm = pcm;
-+	pcm->private_data = dw;
-+	strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
-+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
-+
-+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-+			dev, 64 * 1024, 64 * 1024);
-+
-+	ret = snd_card_register(card);
-+	if (ret < 0)
-+		goto err;
-+
-+	platform_set_drvdata(pdev, dw);
-+
-+	return 0;
-+
-+err:
-+	snd_card_free(card);
-+	return ret;
-+}
-+
-+static int snd_dw_hdmi_remove(struct platform_device *pdev)
-+{
-+	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
-+
-+	snd_card_free(dw->card);
-+
-+	return 0;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int snd_dw_hdmi_suspend(struct device *dev)
-+{
-+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
-+
-+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
-+	snd_pcm_suspend_all(dw->pcm);
-+
-+	return 0;
-+}
-+
-+static int snd_dw_hdmi_resume(struct device *dev)
-+{
-+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
-+
-+	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
-+
-+	return 0;
-+}
-+
-+static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
-+			 snd_dw_hdmi_resume);
-+#define PM_OPS &snd_dw_hdmi_pm
-+#else
-+#define PM_OPS NULL
-+#endif
-+
-+static struct platform_driver snd_dw_hdmi_driver = {
-+	.probe	= snd_dw_hdmi_probe,
-+	.remove	= snd_dw_hdmi_remove,
-+	.driver	= {
-+		.name = "dw-hdmi-audio",
-+		.owner = THIS_MODULE,
-+		.pm = PM_OPS,
-+	},
-+};
-+
-+module_platform_driver(snd_dw_hdmi_driver);
-+
-+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
-+MODULE_LICENSE("GPL");
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-audio.h linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-audio.h
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-audio.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-audio.h	2014-05-23 11:26:48.316940071 +0200
-@@ -0,0 +1,15 @@
-+#ifndef DW_HDMI_AUDIO_H
-+#define DW_HDMI_AUDIO_H
-+
-+struct imx_hdmi;
-+
-+struct dw_hdmi_audio_data {
-+	phys_addr_t phys;
-+	void __iomem *base;
-+	int irq;
-+	struct imx_hdmi *hdmi;
-+	u8 *eld;
-+	void (*set_sample_rate)(struct imx_hdmi *, unsigned);
-+};
-+
-+#endif
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-cec.c linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-cec.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-cec.c	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-cec.c	2014-05-23 11:26:48.316940071 +0200
-@@ -0,0 +1,205 @@
-+/* http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c?h=imx_3.0.35_4.1.0 */
-+#include <linux/cec-dev.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+
-+#include "imx-hdmi.h"
-+#include "dw-hdmi-cec.h"
-+
-+#define DEV_NAME "mxc_hdmi_cec"
-+
-+enum {
-+	CEC_STAT_DONE		= BIT(0),
-+	CEC_STAT_EOM		= BIT(1),
-+	CEC_STAT_NACK		= BIT(2),
-+	CEC_STAT_ARBLOST	= BIT(3),
-+	CEC_STAT_ERROR_INIT	= BIT(4),
-+	CEC_STAT_ERROR_FOLL	= BIT(5),
-+	CEC_STAT_WAKEUP		= BIT(6),
-+
-+	CEC_CTRL_START		= BIT(0),
-+	CEC_CTRL_NORMAL		= 1 << 1,
-+};
-+
-+struct dw_hdmi_cec {
-+	struct cec_dev cec;
-+
-+	struct device *dev;
-+	void __iomem *base;
-+	const struct dw_hdmi_cec_ops *ops;
-+	void *ops_data;
-+	int irq;
-+};
-+
-+static void dw_hdmi_set_address(struct cec_dev *cec_dev, unsigned addresses)
-+{
-+	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
-+
-+	writeb(addresses & 255, cec->base + HDMI_CEC_ADDR_L);
-+	writeb(addresses >> 8, cec->base + HDMI_CEC_ADDR_H);
-+}
-+
-+static void dw_hdmi_send_message(struct cec_dev *cec_dev, u8 *msg,
-+	size_t count)
-+{
-+	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
-+	unsigned i;
-+
-+	for (i = 0; i < count; i++)
-+		writeb(msg[i], cec->base + HDMI_CEC_TX_DATA0 + i);
-+
-+	writeb(count, cec->base + HDMI_CEC_TX_CNT);
-+	writeb(CEC_CTRL_NORMAL | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
-+}
-+
-+static irqreturn_t dw_hdmi_cec_irq(int irq, void *data)
-+{
-+	struct dw_hdmi_cec *cec = data;
-+	struct cec_dev *cec_dev = &cec->cec;
-+	unsigned stat = readb(cec->base + HDMI_IH_CEC_STAT0);
-+
-+	if (stat == 0)
-+		return IRQ_NONE;
-+
-+	writeb(stat, cec->base + HDMI_IH_CEC_STAT0);
-+
-+	if (stat & CEC_STAT_ERROR_INIT) {
-+		if (cec->cec.retries) {
-+			unsigned v = readb(cec->base + HDMI_CEC_CTRL);
-+			writeb(v | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
-+			cec->cec.retries -= 1;
-+		} else {
-+			cec->cec.write_busy = 0;
-+			cec_dev_event(cec_dev, MESSAGE_TYPE_SEND_ERROR, NULL, 0);
-+		}
-+	} else if (stat & (CEC_STAT_DONE | CEC_STAT_NACK))
-+		cec_dev_send_complete(cec_dev, stat & CEC_STAT_DONE);
-+
-+	if (stat & CEC_STAT_EOM) {
-+		unsigned len, i;
-+		u8 msg[MAX_MESSAGE_LEN];
-+
-+		len = readb(cec->base + HDMI_CEC_RX_CNT);
-+		if (len > sizeof(msg))
-+			len = sizeof(msg);
-+
-+		for (i = 0; i < len; i++)
-+			msg[i] = readb(cec->base + HDMI_CEC_RX_DATA0 + i);
-+
-+		writeb(0, cec->base + HDMI_CEC_LOCK);
-+
-+		cec_dev_receive(cec_dev, msg, len);
-+	}
-+
-+	return IRQ_HANDLED;
-+}
-+EXPORT_SYMBOL(dw_hdmi_cec_irq);
-+
-+static void dw_hdmi_cec_release(struct cec_dev *cec_dev)
-+{
-+	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
-+
-+	writeb(~0, cec->base + HDMI_CEC_MASK);
-+	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
-+	writeb(0, cec->base + HDMI_CEC_POLARITY);
-+
-+	free_irq(cec->irq, cec);
-+
-+	cec->ops->disable(cec->ops_data);
-+}
-+
-+static int dw_hdmi_cec_open(struct cec_dev *cec_dev)
-+{
-+	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
-+	unsigned irqs;
-+	int ret;
-+
-+	writeb(0, cec->base + HDMI_CEC_CTRL);
-+	writeb(~0, cec->base + HDMI_IH_CEC_STAT0);
-+	writeb(0, cec->base + HDMI_CEC_LOCK);
-+
-+	ret = request_irq(cec->irq, dw_hdmi_cec_irq, IRQF_SHARED,
-+			  DEV_NAME, cec);
-+	if (ret < 0)
-+		return ret;
-+
-+	dw_hdmi_set_address(cec_dev, cec_dev->addresses);
-+
-+	cec->ops->enable(cec->ops_data);
-+
-+	irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
-+	       CEC_STAT_DONE;
-+	writeb(irqs, cec->base + HDMI_CEC_POLARITY);
-+	writeb(~irqs, cec->base + HDMI_CEC_MASK);
-+	writeb(~irqs, cec->base + HDMI_IH_MUTE_CEC_STAT0);
-+
-+	return 0;
-+}
-+
-+static int dw_hdmi_cec_probe(struct platform_device *pdev)
-+{
-+	struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev);
-+	struct dw_hdmi_cec *cec;
-+
-+	if (!data)
-+		return -ENXIO;
-+
-+	cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
-+	if (!cec)
-+		return -ENOMEM;
-+
-+	cec->dev = &pdev->dev;
-+	cec->base = data->base;
-+	cec->irq = data->irq;
-+	cec->ops = data->ops;
-+	cec->ops_data = data->ops_data;
-+	cec->cec.open = dw_hdmi_cec_open;
-+	cec->cec.release = dw_hdmi_cec_release;
-+	cec->cec.send_message = dw_hdmi_send_message;
-+	cec->cec.set_address = dw_hdmi_set_address;
-+
-+	cec_dev_init(&cec->cec, THIS_MODULE);
-+
-+	/* FIXME: soft-reset the CEC interface */
-+
-+	dw_hdmi_set_address(&cec->cec, cec->cec.addresses);
-+	writeb(0, cec->base + HDMI_CEC_TX_CNT);
-+	writeb(~0, cec->base + HDMI_CEC_MASK);
-+	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
-+	writeb(0, cec->base + HDMI_CEC_POLARITY);
-+
-+	/*
-+	 * Our device is just a convenience - we want to link to the real
-+	 * hardware device here, so that userspace can see the association
-+	 * between the HDMI hardware and its associated CEC chardev.
-+	 */
-+	return cec_dev_add(&cec->cec, cec->dev->parent, DEV_NAME);
-+}
-+
-+static int dw_hdmi_cec_remove(struct platform_device *pdev)
-+{
-+	struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
-+
-+	cec_dev_remove(&cec->cec);
-+
-+	return 0;
-+}
-+
-+static struct platform_driver dw_hdmi_cec_driver = {
-+	.probe	= dw_hdmi_cec_probe,
-+	.remove	= dw_hdmi_cec_remove,
-+	.driver = {
-+		.name = "dw-hdmi-cec",
-+		.owner = THIS_MODULE,
-+	},
-+};
-+module_platform_driver(dw_hdmi_cec_driver);
-+
-+MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
-+MODULE_DESCRIPTION("Synopsis Designware HDMI CEC driver for i.MX");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec");
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-cec.h linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-cec.h
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/dw-hdmi-cec.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/drivers/staging/imx-drm/dw-hdmi-cec.h	2014-05-23 11:26:48.316940071 +0200
-@@ -0,0 +1,16 @@
-+#ifndef DW_HDMI_CEC_H
-+#define DW_HDMI_CEC_H
-+
-+struct dw_hdmi_cec_ops {
-+	void (*enable)(void *);
-+	void (*disable)(void *);
-+};
-+
-+struct dw_hdmi_cec_data {
-+	void __iomem *base;
-+	int irq;
-+	const struct dw_hdmi_cec_ops *ops;
-+	void *ops_data;
-+};
-+
-+#endif
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-hdmi.c linux-3.15-rc6/drivers/staging/imx-drm/imx-hdmi.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-hdmi.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/imx-hdmi.c	2014-05-23 11:26:48.316940071 +0200
-@@ -28,6 +28,9 @@
- #include <drm/drm_edid.h>
- #include <drm/drm_encoder_slave.h>
- 
-+#include "drm-ddc-connector.h"
-+#include "dw-hdmi-audio.h"
-+#include "dw-hdmi-cec.h"
- #include "ipu-v3/imx-ipu-v3.h"
- #include "imx-hdmi.h"
- #include "imx-drm.h"
-@@ -112,27 +115,27 @@
- };
- 
- struct imx_hdmi {
--	struct drm_connector connector;
-+	struct drm_ddc_connector *ddc_conn;
- 	struct drm_encoder encoder;
- 
-+	struct platform_device *audio;
-+	struct platform_device *cec;
- 	enum imx_hdmi_devtype dev_type;
- 	struct device *dev;
- 	struct clk *isfr_clk;
- 	struct clk *iahb_clk;
- 
--	enum drm_connector_status connector_status;
--
- 	struct hdmi_data_info hdmi_data;
- 	int vic;
- 
- 	u8 edid[HDMI_EDID_LEN];
-+	u8 mc_clkdis;
- 	bool cable_plugin;
- 
- 	bool phy_enabled;
- 	struct drm_display_mode previous_mode;
- 
- 	struct regmap *regmap;
--	struct i2c_adapter *ddc;
- 	void __iomem *regs;
- 
- 	unsigned int sample_rate;
-@@ -362,6 +365,12 @@
- 	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
- }
- 
-+static void imx_hdmi_set_sample_rate(struct imx_hdmi *hdmi, unsigned rate)
-+{
-+	hdmi->sample_rate = rate;
-+	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
-+}
-+
- /*
-  * this submodule is responsible for the video data synchronization.
-  * for example, for RGB 4:4:4 input, the data map is defined as
-@@ -1148,8 +1157,6 @@
- /* HDMI Initialization Step B.4 */
- static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
- {
--	u8 clkdis;
--
- 	/* control period minimum duration */
- 	hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
- 	hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
-@@ -1161,23 +1168,28 @@
- 	hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
- 
- 	/* Enable pixel clock and tmds data path */
--	clkdis = 0x7F;
--	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
--	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-+	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
-+			   HDMI_MC_CLKDIS_CSCCLK_DISABLE |
-+			   HDMI_MC_CLKDIS_AUDCLK_DISABLE |
-+			   HDMI_MC_CLKDIS_PREPCLK_DISABLE |
-+			   HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
-+	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
-+	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- 
--	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
--	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-+	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
-+	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- 
- 	/* Enable csc path */
- 	if (is_color_space_conversion(hdmi)) {
--		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
--		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
-+		hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
-+		hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- 	}
- }
- 
- static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
- {
--	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
-+	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
-+	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
- }
- 
- /* Workaround to clear the overflow condition */
-@@ -1380,41 +1392,16 @@
- static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
- 							*connector, bool force)
- {
--	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
--					     connector);
--	return hdmi->connector_status;
--}
--
--static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
--{
--	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
--					     connector);
--	struct edid *edid;
--	int ret;
-+	struct imx_hdmi *hdmi = drm_ddc_private(connector);
- 
--	if (!hdmi->ddc)
--		return 0;
--
--	edid = drm_get_edid(connector, hdmi->ddc);
--	if (edid) {
--		dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
--			edid->width_cm, edid->height_cm);
--
--		drm_mode_connector_update_edid_property(connector, edid);
--		ret = drm_add_edid_modes(connector, edid);
--		kfree(edid);
--	} else {
--		dev_dbg(hdmi->dev, "failed to get edid\n");
--	}
--
--	return 0;
-+	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
-+		connector_status_connected : connector_status_disconnected;
- }
- 
- static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
- 							   *connector)
- {
--	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
--					     connector);
-+	struct imx_hdmi *hdmi = drm_ddc_private(connector);
- 
- 	return &hdmi->encoder;
- }
-@@ -1483,15 +1470,8 @@
- 	.disable = imx_hdmi_encoder_disable,
- };
- 
--static struct drm_connector_funcs imx_hdmi_connector_funcs = {
--	.dpms = drm_helper_connector_dpms,
--	.fill_modes = drm_helper_probe_single_connector_modes,
--	.detect = imx_hdmi_connector_detect,
--	.destroy = imx_drm_connector_destroy,
--};
--
- static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
--	.get_modes = imx_hdmi_connector_get_modes,
-+	.get_modes = drm_ddc_connector_get_modes,
- 	.mode_valid = imx_drm_connector_mode_valid,
- 	.best_encoder = imx_hdmi_connector_best_encoder,
- };
-@@ -1524,7 +1504,6 @@
- 
- 			hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
- 
--			hdmi->connector_status = connector_status_connected;
- 			imx_hdmi_poweron(hdmi);
- 		} else {
- 			dev_dbg(hdmi->dev, "EVENT=plugout\n");
-@@ -1532,10 +1511,9 @@
- 			hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD,
- 				HDMI_PHY_POL0);
- 
--			hdmi->connector_status = connector_status_disconnected;
- 			imx_hdmi_poweroff(hdmi);
- 		}
--		drm_helper_hpd_irq_event(hdmi->connector.dev);
-+		drm_helper_hpd_irq_event(hdmi->ddc_conn->connector.dev);
- 	}
- 
- 	hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
-@@ -1553,24 +1531,42 @@
- 	if (ret)
- 		return ret;
- 
--	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
-+	hdmi->ddc_conn->connector.polled = DRM_CONNECTOR_POLL_HPD;
- 
- 	drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
- 	drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
- 			 DRM_MODE_ENCODER_TMDS);
- 
--	drm_connector_helper_add(&hdmi->connector,
-+	drm_connector_helper_add(&hdmi->ddc_conn->connector,
- 			&imx_hdmi_connector_helper_funcs);
--	drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
--			   DRM_MODE_CONNECTOR_HDMIA);
--
--	hdmi->connector.encoder = &hdmi->encoder;
-+	drm_ddc_connector_add(drm, hdmi->ddc_conn, DRM_MODE_CONNECTOR_HDMIA);
- 
--	drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
-+	drm_mode_connector_attach_encoder(&hdmi->ddc_conn->connector, &hdmi->encoder);
- 
- 	return 0;
- }
- 
-+static void imx_hdmi_cec_enable(void *data)
-+{
-+	struct imx_hdmi *hdmi = data;
-+
-+	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
-+	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
-+}
-+
-+static void imx_hdmi_cec_disable(void *data)
-+{
-+	struct imx_hdmi *hdmi = data;
-+
-+	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
-+	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
-+}
-+
-+static const struct dw_hdmi_cec_ops imx_hdmi_cec_ops = {
-+	.enable = imx_hdmi_cec_enable,
-+	.disable = imx_hdmi_cec_disable,
-+};
-+
- static struct platform_device_id imx_hdmi_devtype[] = {
- 	{
- 		.name = "imx6q-hdmi",
-@@ -1592,11 +1588,13 @@
- static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
- {
- 	struct platform_device *pdev = to_platform_device(dev);
-+	struct platform_device_info pdevinfo;
- 	const struct of_device_id *of_id =
- 				of_match_device(imx_hdmi_dt_ids, dev);
- 	struct drm_device *drm = data;
- 	struct device_node *np = dev->of_node;
--	struct device_node *ddc_node;
-+	struct dw_hdmi_audio_data audio;
-+	struct dw_hdmi_cec_data cec;
- 	struct imx_hdmi *hdmi;
- 	struct resource *iores;
- 	int ret, irq;
-@@ -1605,27 +1603,22 @@
- 	if (!hdmi)
- 		return -ENOMEM;
- 
-+	hdmi->ddc_conn = drm_ddc_connector_create(drm, np, hdmi);
-+	if (IS_ERR(hdmi->ddc_conn))
-+		return PTR_ERR(hdmi->ddc_conn);
-+
-+	hdmi->ddc_conn->detect = imx_hdmi_connector_detect;
-+
- 	hdmi->dev = dev;
--	hdmi->connector_status = connector_status_disconnected;
- 	hdmi->sample_rate = 48000;
- 	hdmi->ratio = 100;
-+	hdmi->mc_clkdis = 0x7f;
- 
- 	if (of_id) {
- 		const struct platform_device_id *device_id = of_id->data;
- 		hdmi->dev_type = device_id->driver_data;
- 	}
- 
--	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
--	if (ddc_node) {
--		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
--		if (!hdmi->ddc)
--			dev_dbg(hdmi->dev, "failed to read ddc node\n");
--
--		of_node_put(ddc_node);
--	} else {
--		dev_dbg(hdmi->dev, "no ddc property found\n");
--	}
--
- 	irq = platform_get_irq(pdev, 0);
- 	if (irq < 0)
- 		return -EINVAL;
-@@ -1711,6 +1704,35 @@
- 	/* Unmute interrupts */
- 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
- 
-+	memset(&pdevinfo, 0, sizeof(pdevinfo));
-+	pdevinfo.parent = dev;
-+	pdevinfo.id = PLATFORM_DEVID_AUTO;
-+
-+	audio.phys = iores->start;
-+	audio.base = hdmi->regs;
-+	audio.irq = irq;
-+	audio.hdmi = hdmi;
-+	audio.eld = hdmi->ddc_conn->connector.eld;
-+	audio.set_sample_rate = imx_hdmi_set_sample_rate;
-+
-+	pdevinfo.name = "dw-hdmi-audio";
-+	pdevinfo.data = &audio;
-+	pdevinfo.size_data = sizeof(audio);
-+	pdevinfo.dma_mask = DMA_BIT_MASK(32);
-+	hdmi->audio = platform_device_register_full(&pdevinfo);
-+
-+	cec.base = hdmi->regs;
-+	cec.irq = irq;
-+	cec.ops = &imx_hdmi_cec_ops;
-+	cec.ops_data = hdmi;
-+
-+	pdevinfo.name = "dw-hdmi-cec";
-+	pdevinfo.data = &cec;
-+	pdevinfo.size_data = sizeof(cec);
-+	pdevinfo.dma_mask = 0;
-+
-+	hdmi->cec = platform_device_register_full(&pdevinfo);
-+
- 	dev_set_drvdata(dev, hdmi);
- 
- 	return 0;
-@@ -1728,15 +1750,19 @@
- {
- 	struct imx_hdmi *hdmi = dev_get_drvdata(dev);
- 
-+	if (!IS_ERR(hdmi->audio))
-+		platform_device_unregister(hdmi->audio);
-+	if (!IS_ERR(hdmi->cec))
-+		platform_device_unregister(hdmi->cec);
-+
- 	/* Disable all interrupts */
- 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
- 
--	hdmi->connector.funcs->destroy(&hdmi->connector);
-+	hdmi->ddc_conn->connector.funcs->destroy(&hdmi->ddc_conn->connector);
- 	hdmi->encoder.funcs->destroy(&hdmi->encoder);
- 
- 	clk_disable_unprepare(hdmi->iahb_clk);
- 	clk_disable_unprepare(hdmi->isfr_clk);
--	i2c_put_adapter(hdmi->ddc);
- }
- 
- static const struct component_ops hdmi_ops = {
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-ldb.c linux-3.15-rc6/drivers/staging/imx-drm/imx-ldb.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-ldb.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/imx-ldb.c	2014-05-23 11:26:48.316940071 +0200
-@@ -24,6 +24,7 @@
- #include <drm/drmP.h>
- #include <drm/drm_fb_helper.h>
- #include <drm/drm_crtc_helper.h>
-+#include <drm/drm_panel.h>
- #include <linux/mfd/syscon.h>
- #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
- #include <linux/of_address.h>
-@@ -60,6 +61,7 @@
- 	struct imx_ldb *ldb;
- 	struct drm_connector connector;
- 	struct drm_encoder encoder;
-+	struct drm_panel *panel;
- 	struct device_node *child;
- 	int chno;
- 	void *edid;
-@@ -96,6 +98,13 @@
- 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
- 	int num_modes = 0;
- 
-+	if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
-+	    imx_ldb_ch->panel->funcs->get_modes) {
-+		num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
-+		if (num_modes > 0)
-+			return num_modes;
-+	}
-+
- 	if (imx_ldb_ch->edid) {
- 		drm_mode_connector_update_edid_property(connector,
- 							imx_ldb_ch->edid);
-@@ -243,6 +252,8 @@
- 	}
- 
- 	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
-+
-+	drm_panel_enable(imx_ldb_ch->panel);
- }
- 
- static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
-@@ -294,6 +305,8 @@
- 		 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
- 		return;
- 
-+	drm_panel_disable(imx_ldb_ch->panel);
-+
- 	if (imx_ldb_ch == &ldb->channel[0])
- 		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
- 	else if (imx_ldb_ch == &ldb->channel[1])
-@@ -379,6 +392,9 @@
- 	drm_connector_init(drm, &imx_ldb_ch->connector,
- 			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
- 
-+	if (imx_ldb_ch->panel)
-+		drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector);
-+
- 	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
- 			&imx_ldb_ch->encoder);
- 
-@@ -493,6 +509,7 @@
- 
- 	for_each_child_of_node(np, child) {
- 		struct imx_ldb_channel *channel;
-+		struct device_node *panel_node;
- 
- 		ret = of_property_read_u32(child, "reg", &i);
- 		if (ret || i < 0 || i > 1)
-@@ -556,6 +573,10 @@
- 			return -EINVAL;
- 		}
- 
-+		panel_node = of_parse_phandle(child, "fsl,panel", 0);
-+		if (panel_node)
-+			channel->panel = of_drm_find_panel(panel_node);
-+
- 		ret = imx_ldb_register(drm, channel);
- 		if (ret)
- 			return ret;
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-tve.c linux-3.15-rc6/drivers/staging/imx-drm/imx-tve.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/imx-tve.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/imx-tve.c	2014-05-23 11:28:50.689342803 +0200
-@@ -22,7 +22,6 @@
- #include <linux/clk-provider.h>
- #include <linux/component.h>
- #include <linux/module.h>
--#include <linux/i2c.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- #include <linux/spinlock.h>
-@@ -31,6 +30,7 @@
- #include <drm/drm_fb_helper.h>
- #include <drm/drm_crtc_helper.h>
- 
-+#include "drm-ddc-connector.h"
- #include "ipu-v3/imx-ipu-v3.h"
- #include "imx-drm.h"
- 
-@@ -111,7 +111,7 @@
- };
- 
- struct imx_tve {
--	struct drm_connector connector;
-+	struct drm_ddc_connector *ddc_conn;
- 	struct drm_encoder encoder;
- 	struct device *dev;
- 	spinlock_t lock;	/* register lock */
-@@ -120,7 +120,6 @@
- 
- 	struct regmap *regmap;
- 	struct regulator *dac_reg;
--	struct i2c_adapter *ddc;
- 	struct clk *clk;
- 	struct clk *di_sel_clk;
- 	struct clk_hw clk_hw_di;
-@@ -219,35 +218,10 @@
- 	return 0;
- }
- 
--static enum drm_connector_status imx_tve_connector_detect(
--				struct drm_connector *connector, bool force)
--{
--	return connector_status_connected;
--}
--
--static int imx_tve_connector_get_modes(struct drm_connector *connector)
--{
--	struct imx_tve *tve = con_to_tve(connector);
--	struct edid *edid;
--	int ret = 0;
--
--	if (!tve->ddc)
--		return 0;
--
--	edid = drm_get_edid(connector, tve->ddc);
--	if (edid) {
--		drm_mode_connector_update_edid_property(connector, edid);
--		ret = drm_add_edid_modes(connector, edid);
--		kfree(edid);
--	}
--
--	return ret;
--}
--
- static int imx_tve_connector_mode_valid(struct drm_connector *connector,
- 					struct drm_display_mode *mode)
- {
--	struct imx_tve *tve = con_to_tve(connector);
-+	struct imx_tve *tve = to_ddc_conn(connector)->private;
- 	unsigned long rate;
- 	int ret;
- 
-@@ -274,7 +248,7 @@
- static struct drm_encoder *imx_tve_connector_best_encoder(
- 		struct drm_connector *connector)
- {
--	struct imx_tve *tve = con_to_tve(connector);
-+	struct imx_tve *tve = drm_ddc_private(connector);
- 
- 	return &tve->encoder;
- }
-@@ -362,15 +336,8 @@
- 	tve_disable(tve);
- }
- 
--static struct drm_connector_funcs imx_tve_connector_funcs = {
--	.dpms = drm_helper_connector_dpms,
--	.fill_modes = drm_helper_probe_single_connector_modes,
--	.detect = imx_tve_connector_detect,
--	.destroy = imx_drm_connector_destroy,
--};
--
- static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
--	.get_modes = imx_tve_connector_get_modes,
-+	.get_modes = drm_ddc_connector_get_modes,
- 	.best_encoder = imx_tve_connector_best_encoder,
- 	.mode_valid = imx_tve_connector_mode_valid,
- };
-@@ -513,12 +480,11 @@
- 	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
- 			 encoder_type);
- 
--	drm_connector_helper_add(&tve->connector,
-+	drm_connector_helper_add(&tve->ddc_conn->connector,
- 			&imx_tve_connector_helper_funcs);
--	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
--			   DRM_MODE_CONNECTOR_VGA);
-+	drm_ddc_connector_add(drm, tve->ddc_conn, DRM_MODE_CONNECTOR_VGA);
- 
--	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
-+	drm_mode_connector_attach_encoder(&tve->ddc_conn->connector, &tve->encoder);
- 
- 	return 0;
- }
-@@ -567,7 +533,6 @@
- 	struct platform_device *pdev = to_platform_device(dev);
- 	struct drm_device *drm = data;
- 	struct device_node *np = dev->of_node;
--	struct device_node *ddc_node;
- 	struct imx_tve *tve;
- 	struct resource *res;
- 	void __iomem *base;
-@@ -579,15 +544,13 @@
- 	if (!tve)
- 		return -ENOMEM;
- 
-+	tve->ddc_conn = drm_ddc_connector_create(drm, np, tve);
-+	if (IS_ERR(tve->ddc_conn))
-+		return PTR_ERR(tve->ddc_conn);
-+
- 	tve->dev = dev;
- 	spin_lock_init(&tve->lock);
- 
--	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
--	if (ddc_node) {
--		tve->ddc = of_find_i2c_adapter_by_node(ddc_node);
--		of_node_put(ddc_node);
--	}
--
- 	tve->mode = of_get_tve_mode(np);
- 	if (tve->mode != TVE_MODE_VGA) {
- 		dev_err(dev, "only VGA mode supported, currently\n");
-@@ -694,7 +657,7 @@
- {
- 	struct imx_tve *tve = dev_get_drvdata(dev);
- 
--	tve->connector.funcs->destroy(&tve->connector);
-+	tve->ddc_conn->connector.funcs->destroy(&tve->ddc_conn->connector);
- 	tve->encoder.funcs->destroy(&tve->encoder);
- 
- 	if (!IS_ERR(tve->dac_reg))
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h	2014-05-23 11:26:48.316940071 +0200
-@@ -76,6 +76,7 @@
- 	IPU_IRQ_EOS = 192,
- };
- 
-+int ipu_map_irq(struct ipu_soc *ipu, int irq);
- int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
- 		enum ipu_channel_irq irq);
- 
-@@ -114,8 +115,10 @@
- void ipu_dc_put(struct ipu_dc *dc);
- int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
- 		u32 pixel_fmt, u32 width);
-+void ipu_dc_enable(struct ipu_soc *ipu);
- void ipu_dc_enable_channel(struct ipu_dc *dc);
- void ipu_dc_disable_channel(struct ipu_dc *dc);
-+void ipu_dc_disable(struct ipu_soc *ipu);
- 
- /*
-  * IPU Display Interface (di) functions
-@@ -152,8 +155,10 @@
- 
- struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
- void ipu_dp_put(struct ipu_dp *);
-+int ipu_dp_enable(struct ipu_soc *ipu);
- int ipu_dp_enable_channel(struct ipu_dp *dp);
- void ipu_dp_disable_channel(struct ipu_dp *dp);
-+void ipu_dp_disable(struct ipu_soc *ipu);
- int ipu_dp_setup_channel(struct ipu_dp *dp,
- 		enum ipu_color_space in, enum ipu_color_space out);
- int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-common.c linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-common.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-common.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-common.c	2014-05-23 11:26:48.352940189 +0200
-@@ -697,6 +697,12 @@
- }
- EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
- 
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
-+{
-+	return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
-+}
-+EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
-+
- int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
- {
- 	struct ipu_soc *ipu = channel->ipu;
-@@ -714,6 +720,22 @@
- }
- EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
- 
-+int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
-+{
-+	unsigned long timeout;
-+
-+	timeout = jiffies + msecs_to_jiffies(ms);
-+	ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
-+	while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) {
-+		if (time_after(jiffies, timeout))
-+			return -ETIMEDOUT;
-+		cpu_relax();
-+	}
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
-+
- int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
- {
- 	struct ipu_soc *ipu = channel->ipu;
-@@ -933,15 +955,22 @@
- 	chained_irq_exit(chip, desc);
- }
- 
--int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
--		enum ipu_channel_irq irq_type)
-+int ipu_map_irq(struct ipu_soc *ipu, int irq)
- {
--	int irq = irq_linear_revmap(ipu->domain, irq_type + channel->num);
-+	int virq;
- 
--	if (!irq)
--		irq = irq_create_mapping(ipu->domain, irq_type + channel->num);
-+	virq = irq_linear_revmap(ipu->domain, irq);
-+	if (!virq)
-+		virq = irq_create_mapping(ipu->domain, irq);
- 
--	return irq;
-+	return virq;
-+}
-+EXPORT_SYMBOL_GPL(ipu_map_irq);
-+
-+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
-+		enum ipu_channel_irq irq_type)
-+{
-+	return ipu_map_irq(ipu, irq_type + channel->num);
- }
- EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
- 
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dc.c linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dc.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dc.c	2014-05-23 11:26:48.360940215 +0200
-@@ -18,6 +18,7 @@
- #include <linux/types.h>
- #include <linux/errno.h>
- #include <linux/delay.h>
-+#include <linux/interrupt.h>
- #include <linux/io.h>
- 
- #include "../imx-drm.h"
-@@ -92,6 +93,7 @@
- 	IPU_DC_MAP_GBR24, /* TVEv2 */
- 	IPU_DC_MAP_BGR666,
- 	IPU_DC_MAP_BGR24,
-+	IPU_DC_MAP_RGB666,
- };
- 
- struct ipu_dc {
-@@ -110,6 +112,9 @@
- 	struct device		*dev;
- 	struct ipu_dc		channels[IPU_DC_NUM_CHANNELS];
- 	struct mutex		mutex;
-+	struct completion	comp;
-+	int			dc_irq;
-+	int			dp_irq;
- };
- 
- static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
-@@ -155,6 +160,8 @@
- 		return IPU_DC_MAP_BGR666;
- 	case V4L2_PIX_FMT_BGR24:
- 		return IPU_DC_MAP_BGR24;
-+	case V4L2_PIX_FMT_RGB666:
-+		return IPU_DC_MAP_RGB666;
- 	default:
- 		return -EINVAL;
- 	}
-@@ -220,12 +227,16 @@
- 	writel(0x0, dc->base + DC_WR_CH_ADDR);
- 	writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
- 
--	ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
--
- 	return 0;
- }
- EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
- 
-+void ipu_dc_enable(struct ipu_soc *ipu)
-+{
-+	ipu_module_enable(ipu, IPU_CONF_DC_EN);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_enable);
-+
- void ipu_dc_enable_channel(struct ipu_dc *dc)
- {
- 	int di;
-@@ -239,41 +250,55 @@
- }
- EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
- 
-+static irqreturn_t dc_irq_handler(int irq, void *dev_id)
-+{
-+	struct ipu_dc *dc = dev_id;
-+	u32 reg;
-+
-+	reg = readl(dc->base + DC_WR_CH_CONF);
-+	reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-+	writel(reg, dc->base + DC_WR_CH_CONF);
-+
-+	/* The Freescale BSP kernel clears DIx_COUNTER_RELEASE here */
-+
-+	complete(&dc->priv->comp);
-+	return IRQ_HANDLED;
-+}
-+
- void ipu_dc_disable_channel(struct ipu_dc *dc)
- {
- 	struct ipu_dc_priv *priv = dc->priv;
-+	int irq, ret;
- 	u32 val;
--	int irq = 0, timeout = 50;
- 
-+	/* TODO: Handle MEM_FG_SYNC differently from MEM_BG_SYNC */
- 	if (dc->chno == 1)
--		irq = IPU_IRQ_DC_FC_1;
-+		irq = priv->dc_irq;
- 	else if (dc->chno == 5)
--		irq = IPU_IRQ_DP_SF_END;
-+		irq = priv->dp_irq;
- 	else
- 		return;
- 
--	/* should wait for the interrupt here */
--	mdelay(50);
--
--	if (dc->di == 0)
--		val = 0x00000002;
--	else
--		val = 0x00000020;
--
--	/* Wait for DC triple buffer to empty */
--	while ((readl(priv->dc_reg + DC_STAT) & val) != val) {
--		usleep_range(2000, 20000);
--		timeout -= 2;
--		if (timeout <= 0)
--			break;
-+	init_completion(&priv->comp);
-+	enable_irq(irq);
-+	ret = wait_for_completion_timeout(&priv->comp, msecs_to_jiffies(50));
-+	disable_irq(irq);
-+	if (ret <= 0) {
-+		dev_warn(priv->dev, "DC stop timeout after 50 ms\n");
-+
-+		val = readl(dc->base + DC_WR_CH_CONF);
-+		val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
-+		writel(val, dc->base + DC_WR_CH_CONF);
- 	}
--
--	val = readl(dc->base + DC_WR_CH_CONF);
--	val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
--	writel(val, dc->base + DC_WR_CH_CONF);
- }
- EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
- 
-+void ipu_dc_disable(struct ipu_soc *ipu)
-+{
-+	ipu_module_disable(ipu, IPU_CONF_DC_EN);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dc_disable);
-+
- static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
- 		int byte_num, int offset, int mask)
- {
-@@ -340,7 +365,7 @@
- 	struct ipu_dc_priv *priv;
- 	static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
- 		0x78, 0, 0x94, 0xb4};
--	int i;
-+	int i, ret;
- 
- 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- 	if (!priv)
-@@ -361,6 +386,23 @@
- 		priv->channels[i].base = priv->dc_reg + channel_offsets[i];
- 	}
- 
-+	priv->dc_irq = ipu_map_irq(ipu, IPU_IRQ_DC_FC_1);
-+	if (!priv->dc_irq)
-+		return -EINVAL;
-+	ret = devm_request_irq(dev, priv->dc_irq, dc_irq_handler, 0, NULL,
-+			       &priv->channels[1]);
-+	if (ret < 0)
-+		return ret;
-+	disable_irq(priv->dc_irq);
-+	priv->dp_irq = ipu_map_irq(ipu, IPU_IRQ_DP_SF_END);
-+	if (!priv->dp_irq)
-+		return -EINVAL;
-+	ret = devm_request_irq(dev, priv->dp_irq, dc_irq_handler, 0, NULL,
-+			       &priv->channels[5]);
-+	if (ret < 0)
-+		return ret;
-+	disable_irq(priv->dp_irq);
-+
- 	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
- 			DC_WR_CH_CONF_PROG_DI_ID,
- 			priv->channels[1].base + DC_WR_CH_CONF);
-@@ -404,6 +446,12 @@
- 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
- 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
- 
-+	/* rgb666 */
-+	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB666);
-+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 0, 5, 0xfc); /* blue */
-+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 1, 11, 0xfc); /* green */
-+	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 2, 17, 0xfc); /* red */
-+
- 	return 0;
- }
- 
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-di.c linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-di.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-di.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-di.c	2014-05-23 11:26:48.372940255 +0200
-@@ -595,7 +595,7 @@
- 		}
- 	}
- 
--	if (!sig->clk_pol)
-+	if (sig->clk_pol)
- 		di_gen |= DI_GEN_POLARITY_DISP_CLK;
- 
- 	ipu_di_write(di, di_gen, DI_GENERAL);
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c	2014-05-23 11:26:48.380940281 +0200
-@@ -28,7 +28,12 @@
- #define DMFC_GENERAL1		0x0014
- #define DMFC_GENERAL2		0x0018
- #define DMFC_IC_CTRL		0x001c
--#define DMFC_STAT		0x0020
-+#define DMFC_WR_CHAN_ALT	0x0020
-+#define DMFC_WR_CHAN_DEF_ALT	0x0024
-+#define DMFC_DP_CHAN_ALT	0x0028
-+#define DMFC_DP_CHAN_DEF_ALT	0x002c
-+#define DMFC_GENERAL1_ALT	0x0030
-+#define DMFC_STAT		0x0034
- 
- #define DMFC_WR_CHAN_1_28		0
- #define DMFC_WR_CHAN_2_41		8
-@@ -133,6 +138,20 @@
- }
- EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
- 
-+static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
-+{
-+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-+
-+	while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
-+		if (time_after(jiffies, timeout)) {
-+			dev_warn(priv->dev,
-+				 "Timeout waiting for DMFC FIFOs to clear\n");
-+			break;
-+		}
-+		cpu_relax();
-+	}
-+}
-+
- void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
- {
- 	struct ipu_dmfc_priv *priv = dmfc->priv;
-@@ -141,8 +160,10 @@
- 
- 	priv->use_count--;
- 
--	if (!priv->use_count)
-+	if (!priv->use_count) {
-+		ipu_dmfc_wait_fifos(priv);
- 		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
-+	}
- 
- 	if (priv->use_count < 0)
- 		priv->use_count = 0;
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dp.c linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-dp.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-dp.c	2014-05-23 11:26:48.388940307 +0200
-@@ -215,10 +215,9 @@
- }
- EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
- 
--int ipu_dp_enable_channel(struct ipu_dp *dp)
-+int ipu_dp_enable(struct ipu_soc *ipu)
- {
--	struct ipu_flow *flow = to_flow(dp);
--	struct ipu_dp_priv *priv = flow->priv;
-+	struct ipu_dp_priv *priv = ipu->dp_priv;
- 
- 	mutex_lock(&priv->mutex);
- 
-@@ -227,15 +226,28 @@
- 
- 	priv->use_count++;
- 
--	if (dp->foreground) {
--		u32 reg;
-+	mutex_unlock(&priv->mutex);
-+
-+	return 0;
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_enable);
-+
-+int ipu_dp_enable_channel(struct ipu_dp *dp)
-+{
-+	struct ipu_flow *flow = to_flow(dp);
-+	struct ipu_dp_priv *priv = flow->priv;
-+	u32 reg;
-+
-+	if (!dp->foreground)
-+		return 0;
-+
-+	mutex_lock(&priv->mutex);
- 
--		reg = readl(flow->base + DP_COM_CONF);
--		reg |= DP_COM_CONF_FG_EN;
--		writel(reg, flow->base + DP_COM_CONF);
-+	reg = readl(flow->base + DP_COM_CONF);
-+	reg |= DP_COM_CONF_FG_EN;
-+	writel(reg, flow->base + DP_COM_CONF);
- 
--		ipu_srm_dp_sync_update(priv->ipu);
--	}
-+	ipu_srm_dp_sync_update(priv->ipu);
- 
- 	mutex_unlock(&priv->mutex);
- 
-@@ -247,25 +259,38 @@
- {
- 	struct ipu_flow *flow = to_flow(dp);
- 	struct ipu_dp_priv *priv = flow->priv;
-+	u32 reg, csc;
-+
-+	if (!dp->foreground)
-+		return;
- 
- 	mutex_lock(&priv->mutex);
- 
--	priv->use_count--;
-+	reg = readl(flow->base + DP_COM_CONF);
-+	csc = reg & DP_COM_CONF_CSC_DEF_MASK;
-+	if (csc == DP_COM_CONF_CSC_DEF_FG)
-+		reg &= ~DP_COM_CONF_CSC_DEF_MASK;
-+
-+	reg &= ~DP_COM_CONF_FG_EN;
-+	writel(reg, flow->base + DP_COM_CONF);
-+
-+	writel(0, flow->base + DP_FG_POS);
-+	ipu_srm_dp_sync_update(priv->ipu);
-+
-+	if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC))
-+		ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50);
-+
-+	mutex_unlock(&priv->mutex);
-+}
-+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
- 
--	if (dp->foreground) {
--		u32 reg, csc;
-+void ipu_dp_disable(struct ipu_soc *ipu)
-+{
-+	struct ipu_dp_priv *priv = ipu->dp_priv;
- 
--		reg = readl(flow->base + DP_COM_CONF);
--		csc = reg & DP_COM_CONF_CSC_DEF_MASK;
--		if (csc == DP_COM_CONF_CSC_DEF_FG)
--			reg &= ~DP_COM_CONF_CSC_DEF_MASK;
--
--		reg &= ~DP_COM_CONF_FG_EN;
--		writel(reg, flow->base + DP_COM_CONF);
--
--		writel(0, flow->base + DP_FG_POS);
--		ipu_srm_dp_sync_update(priv->ipu);
--	}
-+	mutex_lock(&priv->mutex);
-+
-+	priv->use_count--;
- 
- 	if (!priv->use_count)
- 		ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
-@@ -275,7 +300,7 @@
- 
- 	mutex_unlock(&priv->mutex);
- }
--EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
-+EXPORT_SYMBOL_GPL(ipu_dp_disable);
- 
- struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
- {
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-prv.h linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipu-v3/ipu-prv.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipu-v3/ipu-prv.h	2014-05-23 11:26:48.396940333 +0200
-@@ -185,6 +185,9 @@
- int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
- int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
- 
-+bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
-+int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
-+
- int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
- 		unsigned long base, u32 module, struct clk *ipu_clk);
- void ipu_di_exit(struct ipu_soc *ipu, int id);
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipuv3-crtc.c linux-3.15-rc6/drivers/staging/imx-drm/ipuv3-crtc.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipuv3-crtc.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipuv3-crtc.c	2014-05-23 11:26:48.396940333 +0200
-@@ -60,24 +60,32 @@
- 
- static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
- {
-+	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-+
- 	if (ipu_crtc->enabled)
- 		return;
- 
--	ipu_di_enable(ipu_crtc->di);
--	ipu_dc_enable_channel(ipu_crtc->dc);
-+	ipu_dc_enable(ipu);
- 	ipu_plane_enable(ipu_crtc->plane[0]);
-+	/* Start DC channel and DI after IDMAC */
-+	ipu_dc_enable_channel(ipu_crtc->dc);
-+	ipu_di_enable(ipu_crtc->di);
- 
- 	ipu_crtc->enabled = 1;
- }
- 
- static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
- {
-+	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
-+
- 	if (!ipu_crtc->enabled)
- 		return;
- 
--	ipu_plane_disable(ipu_crtc->plane[0]);
-+	/* Stop DC channel and DI before IDMAC */
- 	ipu_dc_disable_channel(ipu_crtc->dc);
- 	ipu_di_disable(ipu_crtc->di);
-+	ipu_plane_disable(ipu_crtc->plane[0]);
-+	ipu_dc_disable(ipu);
- 
- 	ipu_crtc->enabled = 0;
- }
-@@ -158,7 +166,7 @@
- 		sig_cfg.Vsync_pol = 1;
- 
- 	sig_cfg.enable_pol = 1;
--	sig_cfg.clk_pol = 1;
-+	sig_cfg.clk_pol = 0;
- 	sig_cfg.width = mode->hdisplay;
- 	sig_cfg.height = mode->vdisplay;
- 	sig_cfg.pixel_fmt = out_pixel_fmt;
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/ipuv3-plane.c linux-3.15-rc6/drivers/staging/imx-drm/ipuv3-plane.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/ipuv3-plane.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/ipuv3-plane.c	2014-05-23 11:26:48.396940333 +0200
-@@ -239,6 +239,8 @@
- 
- void ipu_plane_enable(struct ipu_plane *ipu_plane)
- {
-+	if (ipu_plane->dp)
-+		ipu_dp_enable(ipu_plane->ipu);
- 	ipu_dmfc_enable_channel(ipu_plane->dmfc);
- 	ipu_idmac_enable_channel(ipu_plane->ipu_ch);
- 	if (ipu_plane->dp)
-@@ -257,6 +259,8 @@
- 		ipu_dp_disable_channel(ipu_plane->dp);
- 	ipu_idmac_disable_channel(ipu_plane->ipu_ch);
- 	ipu_dmfc_disable_channel(ipu_plane->dmfc);
-+	if (ipu_plane->dp)
-+		ipu_dp_disable(ipu_plane->ipu);
- }
- 
- static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/Kconfig linux-3.15-rc6/drivers/staging/imx-drm/Kconfig
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/Kconfig	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/Kconfig	2014-05-23 11:26:48.396940333 +0200
-@@ -35,6 +35,7 @@
- config DRM_IMX_LDB
- 	tristate "Support for LVDS displays"
- 	depends on DRM_IMX && MFD_SYSCON
-+	select DRM_PANEL
- 	help
- 	  Choose this to enable the internal LVDS Display Bridge (LDB)
- 	  found on i.MX53 and i.MX6 processors.
-@@ -60,3 +61,20 @@
- 	depends on DRM_IMX
- 	help
- 	  Choose this if you want to use HDMI on i.MX6.
-+
-+config DRM_DW_HDMI_AUDIO
-+	tristate "Synopsis Designware Audio interface"
-+	depends on DRM_IMX_HDMI != n
-+	help
-+	  Support the Audio interface which is part of the Synopsis
-+	  Designware HDMI block.  This is used in conjunction with
-+	  the i.MX HDMI driver.
-+
-+config DRM_DW_HDMI_CEC
-+	tristate "Synopsis Designware CEC interface"
-+	depends on DRM_IMX_HDMI != n
-+	select HDMI_CEC_CORE
-+	help
-+	  Support the CEC interface which is part of the Synposis
-+	  Designware HDMI block.  This is used in conjunction with
-+	  the i.MX HDMI driver.
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/Makefile linux-3.15-rc6/drivers/staging/imx-drm/Makefile
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/Makefile	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/Makefile	2014-05-23 11:26:48.396940333 +0200
-@@ -3,6 +3,7 @@
- 
- obj-$(CONFIG_DRM_IMX) += imxdrm.o
- 
-+obj-$(CONFIG_DRM_IMX) += drm-ddc-connector.o
- obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
- obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
- obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
-@@ -11,3 +12,5 @@
- imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
- obj-$(CONFIG_DRM_IMX_IPUV3)	+= imx-ipuv3-crtc.o
- obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o
-+obj-$(CONFIG_DRM_DW_HDMI_AUDIO) += dw-hdmi-audio.o
-+obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o
-diff -Nur linux-3.15-rc6.orig/drivers/staging/imx-drm/parallel-display.c linux-3.15-rc6/drivers/staging/imx-drm/parallel-display.c
---- linux-3.15-rc6.orig/drivers/staging/imx-drm/parallel-display.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/drivers/staging/imx-drm/parallel-display.c	2014-05-23 11:26:48.396940333 +0200
-@@ -219,6 +219,8 @@
- 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
- 		else if (!strcmp(fmt, "bgr666"))
- 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
-+		else if (!strcmp(fmt, "rgb666"))
-+			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB666;
- 	}
- 
- 	panel_node = of_parse_phandle(np, "fsl,panel", 0);
-diff -Nur linux-3.15-rc6.orig/include/linux/cec-dev.h linux-3.15-rc6/include/linux/cec-dev.h
---- linux-3.15-rc6.orig/include/linux/cec-dev.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/include/linux/cec-dev.h	2014-05-23 11:26:48.396940333 +0200
-@@ -0,0 +1,69 @@
-+#ifndef _LINUX_CEC_DEV_H
-+#define _LINUX_CEC_DEV_H
-+
-+#include <linux/cdev.h>
-+#include <linux/list.h>
-+#include <linux/mutex.h>
-+#include <linux/spinlock.h>
-+#include <linux/wait.h>
-+
-+#include <uapi/linux/cec-dev.h>
-+
-+struct device;
-+
-+struct cec_dev {
-+	struct cdev cdev;
-+	dev_t devn;
-+
-+	struct mutex mutex;
-+	unsigned users;
-+
-+	spinlock_t lock;
-+	wait_queue_head_t waitq;
-+	struct list_head events;
-+	u8 write_busy;
-+
-+	u8 retries;
-+	u16 addresses;
-+	u16 physical;
-+
-+	int (*open)(struct cec_dev *);
-+	void (*release)(struct cec_dev *);
-+	void (*send_message)(struct cec_dev *, u8 *, size_t);
-+	void (*set_address)(struct cec_dev *, unsigned);
-+};
-+
-+void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len);
-+
-+static inline void cec_dev_receive(struct cec_dev *cec_dev, u8 *msg,
-+	unsigned len)
-+{
-+	cec_dev_event(cec_dev, MESSAGE_TYPE_RECEIVE_SUCCESS, msg, len);
-+}
-+
-+static inline void cec_dev_send_complete(struct cec_dev *cec_dev, int ack)
-+{
-+	cec_dev->retries = 0;
-+	cec_dev->write_busy = 0;
-+
-+	cec_dev_event(cec_dev, ack ? MESSAGE_TYPE_SEND_SUCCESS :
-+		      MESSAGE_TYPE_NOACK, NULL, 0);
-+}
-+
-+static inline void cec_dev_disconnect(struct cec_dev *cec_dev)
-+{
-+	cec_dev->physical = 0;
-+	cec_dev_event(cec_dev, MESSAGE_TYPE_DISCONNECTED, NULL, 0);
-+}
-+
-+static inline void cec_dev_connect(struct cec_dev *cec_dev, u32 phys)
-+{
-+	cec_dev->physical = phys;
-+	cec_dev_event(cec_dev, MESSAGE_TYPE_CONNECTED, NULL, 0);
-+}
-+
-+void cec_dev_init(struct cec_dev *cec_dev, struct module *);
-+int cec_dev_add(struct cec_dev *cec_dev, struct device *, const char *name);
-+void cec_dev_remove(struct cec_dev *cec_dev);
-+
-+#endif
-diff -Nur linux-3.15-rc6.orig/include/linux/mmc/host.h linux-3.15-rc6/include/linux/mmc/host.h
---- linux-3.15-rc6.orig/include/linux/mmc/host.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/include/linux/mmc/host.h	2014-05-23 11:26:48.400940347 +0200
-@@ -278,6 +278,7 @@
- #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
- 				 MMC_CAP2_PACKED_WR)
- #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
-+#define MMC_CAP2_SDIO_NOTHREAD	(1 << 15)
- 
- 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
- 
-@@ -293,6 +294,11 @@
- 	unsigned long           clkgate_delay;
- #endif
- 
-+	/* card specific properties to deal with power and reset */
-+	struct regulator	*card_regulator; /* External VCC needed by the card */
-+	struct gpio_desc	*card_reset_gpios[2]; /* External resets, active low */
-+	struct clk		*card_clk;	/* External clock needed by the card */
-+
- 	/* host specific block data */
- 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
- 	unsigned short		max_segs;	/* see blk_queue_max_segments */
-@@ -391,6 +397,8 @@
- 	wake_up_process(host->sdio_irq_thread);
- }
- 
-+void sdio_run_irqs(struct mmc_host *host);
-+
- #ifdef CONFIG_REGULATOR
- int mmc_regulator_get_ocrmask(struct regulator *supply);
- int mmc_regulator_set_ocr(struct mmc_host *mmc,
-diff -Nur linux-3.15-rc6.orig/include/linux/mmc/sdhci.h linux-3.15-rc6/include/linux/mmc/sdhci.h
---- linux-3.15-rc6.orig/include/linux/mmc/sdhci.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/include/linux/mmc/sdhci.h	2014-05-23 11:26:48.400940347 +0200
-@@ -57,12 +57,8 @@
- #define SDHCI_QUIRK_BROKEN_CARD_DETECTION		(1<<15)
- /* Controller reports inverted write-protect state */
- #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT		(1<<16)
--/* Controller has nonstandard clock management */
--#define SDHCI_QUIRK_NONSTANDARD_CLOCK			(1<<17)
- /* Controller does not like fast PIO transfers */
- #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)
--/* Controller losing signal/interrupt enable states after reset */
--#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET		(1<<19)
- /* Controller has to be forced to use block size of 2048 bytes */
- #define SDHCI_QUIRK_FORCE_BLK_SZ_2048			(1<<20)
- /* Controller cannot do multi-block transfers */
-@@ -147,6 +143,7 @@
- 
- 	bool runtime_suspended;	/* Host is runtime suspended */
- 	bool bus_on;		/* Bus power prevents runtime suspend */
-+	bool preset_enabled;	/* Preset is enabled */
- 
- 	struct mmc_request *mrq;	/* Current request */
- 	struct mmc_command *cmd;	/* Current command */
-@@ -164,8 +161,7 @@
- 	dma_addr_t adma_addr;	/* Mapped ADMA descr. table */
- 	dma_addr_t align_addr;	/* Mapped bounce buffer */
- 
--	struct tasklet_struct card_tasklet;	/* Tasklet structures */
--	struct tasklet_struct finish_tasklet;
-+	struct tasklet_struct finish_tasklet;	/* Tasklet structures */
- 
- 	struct timer_list timer;	/* Timer for timeouts */
- 
-@@ -177,6 +173,13 @@
- 	unsigned int            ocr_avail_mmc;
- 	u32 ocr_mask;		/* available voltages */
- 
-+	unsigned		timing;		/* Current timing */
-+
-+	u32			thread_isr;
-+
-+	/* cached registers */
-+	u32			ier;
-+
- 	wait_queue_head_t	buf_ready_int;	/* Waitqueue for Buffer Read Ready interrupt */
- 	unsigned int		tuning_done;	/* Condition flag set when CMD19 succeeds */
- 
-diff -Nur linux-3.15-rc6.orig/include/uapi/linux/cec-dev.h linux-3.15-rc6/include/uapi/linux/cec-dev.h
---- linux-3.15-rc6.orig/include/uapi/linux/cec-dev.h	1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.15-rc6/include/uapi/linux/cec-dev.h	2014-05-23 11:26:48.400940347 +0200
-@@ -0,0 +1,34 @@
-+#ifndef _UAPI_LINUX_CEC_DEV_H
-+#define _UAPI_LINUX_CEC_DEV_H
-+
-+#include <linux/ioctl.h>
-+#include <linux/types.h>
-+
-+#define MAX_MESSAGE_LEN 16
-+
-+enum {
-+	HDMICEC_IOC_MAGIC = 'H',
-+	/* This is wrong: we pass the argument as a number, not a pointer */
-+	HDMICEC_IOC_O_SETLOGICALADDRESS	= _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char),
-+	HDMICEC_IOC_SETLOGICALADDRESS	= _IO(HDMICEC_IOC_MAGIC, 1),
-+	HDMICEC_IOC_STARTDEVICE		= _IO(HDMICEC_IOC_MAGIC, 2),
-+	HDMICEC_IOC_STOPDEVICE		= _IO(HDMICEC_IOC_MAGIC, 3),
-+	HDMICEC_IOC_GETPHYADDRESS	= _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]),
-+};
-+
-+enum {
-+	MESSAGE_TYPE_RECEIVE_SUCCESS = 1,
-+	MESSAGE_TYPE_NOACK,
-+	MESSAGE_TYPE_DISCONNECTED,
-+	MESSAGE_TYPE_CONNECTED,
-+	MESSAGE_TYPE_SEND_SUCCESS,
-+	MESSAGE_TYPE_SEND_ERROR,
-+};
-+
-+struct cec_user_event {
-+	__u32 event_type;
-+	__u32 msg_len;
-+	__u8 msg[MAX_MESSAGE_LEN];
-+};
-+
-+#endif
-diff -Nur linux-3.15-rc6.orig/include/uapi/linux/videodev2.h linux-3.15-rc6/include/uapi/linux/videodev2.h
---- linux-3.15-rc6.orig/include/uapi/linux/videodev2.h	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/include/uapi/linux/videodev2.h	2014-05-23 11:26:48.400940347 +0200
-@@ -299,6 +299,7 @@
- #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
- #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
- #define V4L2_PIX_FMT_BGR666  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6	  */
-+#define V4L2_PIX_FMT_RGB666  v4l2_fourcc('R', 'G', 'B', 'H') /* 18  RGB-6-6-6	  */
- #define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
- #define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
- #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
-diff -Nur linux-3.15-rc6.orig/sound/soc/fsl/imx-pcm-dma.c linux-3.15-rc6/sound/soc/fsl/imx-pcm-dma.c
---- linux-3.15-rc6.orig/sound/soc/fsl/imx-pcm-dma.c	2014-05-21 23:42:02.000000000 +0200
-+++ linux-3.15-rc6/sound/soc/fsl/imx-pcm-dma.c	2014-05-23 11:26:48.400940347 +0200
-@@ -44,7 +44,7 @@
- 	.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
- 	.period_bytes_min = 128,
- 	.period_bytes_max = 65535, /* Limited by SDMA engine */
--	.periods_min = 2,
-+	.periods_min = 4,
- 	.periods_max = 255,
- 	.fifo_size = 0,
- };

+ 6640 - 0
target/arm/cubox-i/patches/3.15/rmk.patch

@@ -0,0 +1,6640 @@
+ .../DocBook/media/v4l/pixfmt-packed-rgb.xml        |  39 ++
+ .../devicetree/bindings/leds/leds-pwm.txt          |   2 +
+ Documentation/devicetree/bindings/mmc/mmc.txt      |  11 +
+ .../bindings/staging/imx-drm/fsl-imx-drm.txt       |   3 +-
+ arch/arm/boot/dts/imx6dl-hummingboard.dts          |  27 +
+ arch/arm/boot/dts/imx6q-cubox-i.dts                |   4 +
+ arch/arm/boot/dts/imx6qdl-cubox-i.dtsi             |  78 ++-
+ arch/arm/boot/dts/imx6qdl-microsom.dtsi            |  98 +++
+ arch/arm/configs/imx_v6_v7_defconfig               |   1 +
+ arch/arm/mach-imx/clk-imx6q.c                      |  12 +
+ arch/arm/mach-imx/clk-pllv3.c                      |  27 +-
+ drivers/Kconfig                                    |   2 +
+ drivers/Makefile                                   |   1 +
+ drivers/ata/ahci_imx.c                             | 184 +++++-
+ drivers/cec/Kconfig                                |  14 +
+ drivers/cec/Makefile                               |   1 +
+ drivers/cec/cec-dev.c                              | 384 +++++++++++
+ drivers/gpu/drm/drm_crtc_helper.c                  |   6 -
+ drivers/leds/leds-pwm.c                            | 144 ++--
+ drivers/mmc/core/core.c                            |  42 ++
+ drivers/mmc/core/host.c                            |  68 ++
+ drivers/mmc/core/sdio_irq.c                        |  41 +-
+ drivers/mmc/host/Kconfig                           |  63 +-
+ drivers/mmc/host/dw_mmc.c                          |   2 +
+ drivers/mmc/host/sdhci-acpi.c                      |   8 +
+ drivers/mmc/host/sdhci-bcm-kona.c                  |   4 +
+ drivers/mmc/host/sdhci-bcm2835.c                   |   4 +
+ drivers/mmc/host/sdhci-cns3xxx.c                   |  13 +-
+ drivers/mmc/host/sdhci-dove.c                      |   4 +
+ drivers/mmc/host/sdhci-esdhc-imx.c                 |  82 +--
+ drivers/mmc/host/sdhci-esdhc.h                     |   4 +-
+ drivers/mmc/host/sdhci-of-arasan.c                 |   4 +
+ drivers/mmc/host/sdhci-of-esdhc.c                  |  70 +-
+ drivers/mmc/host/sdhci-of-hlwd.c                   |   4 +
+ drivers/mmc/host/sdhci-pci.c                       |   9 +-
+ drivers/mmc/host/sdhci-pltfm.c                     |   4 +
+ drivers/mmc/host/sdhci-pxav2.c                     |  14 +-
+ drivers/mmc/host/sdhci-pxav3.c                     |  13 +-
+ drivers/mmc/host/sdhci-s3c.c                       |  36 +-
+ drivers/mmc/host/sdhci-sirf.c                      |   4 +
+ drivers/mmc/host/sdhci-spear.c                     |   5 +-
+ drivers/mmc/host/sdhci-tegra.c                     |  27 +-
+ drivers/mmc/host/sdhci.c                           | 722 ++++++++++-----------
+ drivers/mmc/host/sdhci.h                           |  20 +-
+ drivers/regulator/anatop-regulator.c               |   1 +
+ drivers/regulator/core.c                           |   2 +-
+ drivers/regulator/dummy.c                          |   1 +
+ drivers/regulator/fixed.c                          |   4 +-
+ drivers/staging/imx-drm/Kconfig                    |  18 +
+ drivers/staging/imx-drm/Makefile                   |   3 +
+ drivers/staging/imx-drm/drm-ddc-connector.c        |  92 +++
+ drivers/staging/imx-drm/drm-ddc-connector.h        |  26 +
+ drivers/staging/imx-drm/dw-hdmi-audio.c            | 652 +++++++++++++++++++
+ drivers/staging/imx-drm/dw-hdmi-audio.h            |  15 +
+ drivers/staging/imx-drm/dw-hdmi-cec.c              | 205 ++++++
+ drivers/staging/imx-drm/dw-hdmi-cec.h              |  16 +
+ drivers/staging/imx-drm/imx-hdmi.c                 | 178 ++---
+ drivers/staging/imx-drm/imx-ldb.c                  |  21 +
+ drivers/staging/imx-drm/imx-tve.c                  |  63 +-
+ drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h        |   5 +
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        |  41 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dc.c            |  94 ++-
+ drivers/staging/imx-drm/ipu-v3/ipu-di.c            |   2 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c          |  25 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-dp.c            |  71 +-
+ drivers/staging/imx-drm/ipu-v3/ipu-prv.h           |   3 +
+ drivers/staging/imx-drm/ipuv3-crtc.c               |  16 +-
+ drivers/staging/imx-drm/ipuv3-plane.c              |   4 +
+ drivers/staging/imx-drm/parallel-display.c         |   2 +
+ include/linux/cec-dev.h                            |  69 ++
+ include/linux/mmc/host.h                           |   8 +
+ include/linux/mmc/sdhci.h                          |  15 +-
+ include/uapi/linux/cec-dev.h                       |  34 +
+ include/uapi/linux/videodev2.h                     |   1 +
+ sound/soc/fsl/imx-pcm-dma.c                        |   2 +-
+ 75 files changed, 3162 insertions(+), 832 deletions(-)
+
+diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+index e1c4f8b4c0b3..88a7fe1ecaf1 100644
+--- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
++++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+@@ -279,6 +279,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
+ 	    <entry></entry>
+ 	    <entry></entry>
+ 	  </row>
++	  <row id="V4L2-PIX-FMT-RGB666">
++	    <entry><constant>V4L2_PIX_FMT_RGB666</constant></entry>
++	    <entry>'RGBH'</entry>
++	    <entry></entry>
++	    <entry>r<subscript>5</subscript></entry>
++	    <entry>r<subscript>4</subscript></entry>
++	    <entry>r<subscript>3</subscript></entry>
++	    <entry>r<subscript>2</subscript></entry>
++	    <entry>r<subscript>1</subscript></entry>
++	    <entry>r<subscript>0</subscript></entry>
++	    <entry>g<subscript>5</subscript></entry>
++	    <entry>g<subscript>4</subscript></entry>
++	    <entry></entry>
++	    <entry>g<subscript>3</subscript></entry>
++	    <entry>g<subscript>2</subscript></entry>
++	    <entry>g<subscript>1</subscript></entry>
++	    <entry>g<subscript>0</subscript></entry>
++	    <entry>b<subscript>5</subscript></entry>
++	    <entry>b<subscript>4</subscript></entry>
++	    <entry>b<subscript>3</subscript></entry>
++	    <entry>b<subscript>2</subscript></entry>
++	    <entry></entry>
++	    <entry>b<subscript>1</subscript></entry>
++	    <entry>b<subscript>0</subscript></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	    <entry></entry>
++	  </row>
+ 	  <row id="V4L2-PIX-FMT-BGR24">
+ 	    <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
+ 	    <entry>'BGR3'</entry>
+diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.txt b/Documentation/devicetree/bindings/leds/leds-pwm.txt
+index 7297107cf832..6c6583c35f2f 100644
+--- a/Documentation/devicetree/bindings/leds/leds-pwm.txt
++++ b/Documentation/devicetree/bindings/leds/leds-pwm.txt
+@@ -13,6 +13,8 @@ node's name represents the name of the corresponding LED.
+   For the pwms and pwm-names property please refer to:
+   Documentation/devicetree/bindings/pwm/pwm.txt
+ - max-brightness : Maximum brightness possible for the LED
++- active-low : (optional) For PWMs where the LED is wired to supply
++  rather than ground.
+ - label :  (optional)
+   see Documentation/devicetree/bindings/leds/common.txt
+ - linux,default-trigger :  (optional)
+diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
+index 9dce540771fb..b9b534ebc0c5 100644
+--- a/Documentation/devicetree/bindings/mmc/mmc.txt
++++ b/Documentation/devicetree/bindings/mmc/mmc.txt
+@@ -5,6 +5,8 @@ these definitions.
+ Interpreted by the OF core:
+ - reg: Registers location and length.
+ - interrupts: Interrupts used by the MMC controller.
++- clocks: Clocks needed for the host controller, if any.
++- clock-names: Goes with clocks above.
+ 
+ Card detection:
+ If no property below is supplied, host native card detect is used.
+@@ -39,6 +41,15 @@ If no property below is supplied, host native card detect is used.
+ - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported
+ - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported
+ 
++Card power and reset control:
++The following properties can be specified for cases where the MMC
++peripheral needs additional reset, regulator and clock lines. It is for
++example common for WiFi/BT adapters to have these separate from the main
++MMC bus:
++  - card-reset-gpios: Specify GPIOs for card reset (reset active low)
++  - card-external-vcc-supply: Regulator to drive (independent) card VCC
++  - clock with name "card_ext_clock": External clock provided to the card
++
+ *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
+ polarity properties, we have to fix the meaning of the "normal" and "inverted"
+ line levels. We choose to follow the SDHCI standard, which specifies both those
+diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+index 3be5ce7a9654..83137ef5a1ba 100644
+--- a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
++++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+@@ -60,7 +60,8 @@ Parallel display support
+ - compatible: Should be "fsl,imx-parallel-display"
+ Optional properties:
+ - interface_pix_fmt: How this display is connected to the
+-  display interface. Currently supported types: "rgb24", "rgb565", "bgr666"
++  display interface. Currently supported types: "rgb24", "rgb565", "bgr666",
++  "rgb666"
+ - edid: verbatim EDID data block describing attached display.
+ - ddc: phandle describing the i2c bus handling the display data
+   channel
+diff --git a/arch/arm/boot/dts/imx6dl-hummingboard.dts b/arch/arm/boot/dts/imx6dl-hummingboard.dts
+index 5bfae54fb780..5cfab68fe43d 100644
+--- a/arch/arm/boot/dts/imx6dl-hummingboard.dts
++++ b/arch/arm/boot/dts/imx6dl-hummingboard.dts
+@@ -67,6 +67,13 @@
+ 	status = "okay";
+ };
+ 
++&hdmi {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_hummingboard_hdmi>;
++	ddc-i2c-bus = <&i2c2>;
++	status = "okay";
++};
++
+ &i2c1 {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
+@@ -82,6 +89,13 @@
+ 	 */
+ };
+ 
++&i2c2 {
++	clock-frequency = <100000>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_hummingboard_i2c2>;
++	status = "okay";
++};
++
+ &iomuxc {
+ 	hummingboard {
+ 		pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 {
+@@ -97,6 +111,12 @@
+ 			>;
+ 		};
+ 
++		pinctrl_hummingboard_hdmi: hummingboard-hdmi {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
++			>;
++		};
++
+ 		pinctrl_hummingboard_i2c1: hummingboard-i2c1 {
+ 			fsl,pins = <
+ 				MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+@@ -104,6 +124,13 @@
+ 			>;
+ 		};
+ 
++		pinctrl_hummingboard_i2c2: hummingboard-i2c2 {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
++				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
++			>;
++		};
++
+ 		pinctrl_hummingboard_spdif: hummingboard-spdif {
+ 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ 		};
+diff --git a/arch/arm/boot/dts/imx6q-cubox-i.dts b/arch/arm/boot/dts/imx6q-cubox-i.dts
+index bc5f31e3e892..9efd8b0c8011 100644
+--- a/arch/arm/boot/dts/imx6q-cubox-i.dts
++++ b/arch/arm/boot/dts/imx6q-cubox-i.dts
+@@ -13,4 +13,8 @@
+ 
+ &sata {
+ 	status = "okay";
++	fsl,transmit-level-mV = <1104>;
++	fsl,transmit-boost-mdB = <0>;
++	fsl,transmit-atten-16ths = <9>;
++	fsl,no-spread-spectrum;
+ };
+diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+index c2a24888a276..f45380073973 100644
+--- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
++++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+@@ -12,6 +12,19 @@
+ 		pinctrl-0 = <&pinctrl_cubox_i_ir>;
+ 	};
+ 
++	pwmleds {
++		compatible = "pwm-leds";
++		pinctrl-names = "default";
++		pinctrl-0 = <&pinctrl_cubox_i_pwm1>;
++
++		front {
++			active-low;
++			label = "imx6:red:front";
++			max-brightness = <248>;
++			pwms = <&pwm1 0 50000>;
++		};
++	};
++
+ 	regulators {
+ 		compatible = "simple-bus";
+ 
+@@ -55,6 +68,20 @@
+ 	};
+ };
+ 
++&hdmi {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_hdmi>;
++	ddc-i2c-bus = <&i2c2>;
++	status = "okay";
++};
++
++&i2c2 {
++	clock-frequency = <100000>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_cubox_i_i2c2>;
++	status = "okay";
++};
++
+ &i2c3 {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_cubox_i_i2c3>;
+@@ -69,6 +96,19 @@
+ 
+ &iomuxc {
+ 	cubox_i {
++		pinctrl_cubox_i_hdmi: cubox-i-hdmi {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0
++			>;
++		};
++
++		pinctrl_cubox_i_i2c2: cubox-i-i2c2 {
++			fsl,pins = <
++				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
++				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
++			>;
++		};
++
+ 		pinctrl_cubox_i_i2c3: cubox-i-i2c3 {
+ 			fsl,pins = <
+ 				MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
+@@ -82,6 +122,10 @@
+ 			>;
+ 		};
+ 
++		pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
++			fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
++		};
++
+ 		pinctrl_cubox_i_spdif: cubox-i-spdif {
+ 			fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
+ 		};
+@@ -111,6 +155,28 @@
+ 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
+ 			>;
+ 		};
++
++		pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz {
++			fsl,pins = <
++				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170b9
++				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100b9
++				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
++				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
++				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
++				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9
++			>;
++		};
++
++		pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz {
++			fsl,pins = <
++				MX6QDL_PAD_SD2_CMD__SD2_CMD    0x170f9
++				MX6QDL_PAD_SD2_CLK__SD2_CLK    0x100f9
++				MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
++				MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
++				MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
++				MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9
++			>;
++		};
+ 	};
+ };
+ 
+@@ -130,9 +196,19 @@
+ 	status = "okay";
+ };
+ 
++&uart4 {
++	status = "okay";
++};
++
++&usdhc1 {
++	status = "okay";
++};
++
+ &usdhc2 {
+-	pinctrl-names = "default";
++	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ 	pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
++	pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>;
++	pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>;
+ 	vmmc-supply = <&reg_3p3v>;
+ 	cd-gpios = <&gpio1 4 0>;
+ 	status = "okay";
+diff --git a/arch/arm/boot/dts/imx6qdl-microsom.dtsi b/arch/arm/boot/dts/imx6qdl-microsom.dtsi
+index d729d0b15f25..a5d72895d9ce 100644
+--- a/arch/arm/boot/dts/imx6qdl-microsom.dtsi
++++ b/arch/arm/boot/dts/imx6qdl-microsom.dtsi
+@@ -1,9 +1,69 @@
+ /*
+  * Copyright (C) 2013,2014 Russell King
+  */
++#include <dt-bindings/gpio/gpio.h>
++/ {
++	regulators {
++		compatible = "simple-bus";
++
++		reg_brcm_osc: brcm-osc-reg {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio5 5 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>;
++			regulator-name = "brcm_osc_reg";
++			regulator-min-microvolt = <3300000>;
++			regulator-max-microvolt = <3300000>;
++			regulator-always-on;
++			regulator-boot-on;
++		};
++
++		reg_brcm: brcm-reg {
++			compatible = "regulator-fixed";
++			enable-active-high;
++			gpio = <&gpio3 19 0>;
++			pinctrl-names = "default";
++			pinctrl-0 = <&pinctrl_microsom_brcm_reg>;
++			regulator-name = "brcm_reg";
++			regulator-min-microvolt = <3300000>;
++			regulator-max-microvolt = <3300000>;
++			startup-delay-us = <200000>;
++		};
++	};
++};
+ 
+ &iomuxc {
+ 	microsom {
++		pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg {
++			fsl,pins = <
++				MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_reg: microsom-brcm-reg {
++			fsl,pins = <
++				MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_wifi: microsom-brcm-wifi {
++			fsl,pins = <
++				MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K	0x1b0b0
++				MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20	0x40013070
++				MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26	0x40013070
++				MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27	0x40013070
++			>;
++		};
++
++		pinctrl_microsom_brcm_bt: microsom-brcm-bt {
++			fsl,pins = <
++				MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00	0x40013070
++				MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01	0x40013070
++				MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04	0x40013070
++			>;
++		};
++
+ 		pinctrl_microsom_uart1: microsom-uart1 {
+ 			fsl,pins = <
+ 				MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+@@ -11,6 +71,15 @@
+ 			>;
+ 		};
+ 
++		pinctrl_microsom_uart4_1: microsom-uart4 {
++			fsl,pins = <
++				MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
++				MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
++			>;
++		};
++
+ 		pinctrl_microsom_usbotg: microsom-usbotg {
+ 			/*
+ 			 * Similar to pinctrl_usbotg_2, but we want it
+@@ -18,6 +87,17 @@
+ 			 */
+ 			fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+ 		};
++
++		pinctrl_microsom_usdhc1: microsom-usdhc1 {
++			fsl,pins = <
++				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17059
++				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10059
++				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
++				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
++				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
++				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
++			>;
++		};
+ 	};
+ };
+ 
+@@ -27,7 +107,25 @@
+ 	status = "okay";
+ };
+ 
++/* UART4 - Connected to optional BRCM Wifi/BT/FM */
++&uart4 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>;
++	fsl,uart-has-rtscts;
++};
++
+ &usbotg {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_microsom_usbotg>;
+ };
++
++/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */
++&usdhc1 {
++	card-external-vcc-supply = <&reg_brcm>;
++	card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>;
++	keep-power-in-suspend;
++	non-removable;
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>;
++	vmmc-supply = <&reg_brcm>;
++};
+diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
+index 09e974392fa1..ea50d34f7944 100644
+--- a/arch/arm/configs/imx_v6_v7_defconfig
++++ b/arch/arm/configs/imx_v6_v7_defconfig
+@@ -245,6 +245,7 @@ CONFIG_DRM_IMX_TVE=y
+ CONFIG_DRM_IMX_LDB=y
+ CONFIG_DRM_IMX_IPUV3_CORE=y
+ CONFIG_DRM_IMX_IPUV3=y
++CONFIG_DRM_IMX_HDMI=y
+ CONFIG_COMMON_CLK_DEBUG=y
+ # CONFIG_IOMMU_SUPPORT is not set
+ CONFIG_PWM=y
+diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
+index 2b4d6acfa34a..fefa6c3d4c86 100644
+--- a/arch/arm/mach-imx/clk-imx6q.c
++++ b/arch/arm/mach-imx/clk-imx6q.c
+@@ -454,6 +454,18 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
+ 	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
+ 	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
+ 
++	if (cpu_is_imx6dl())
++		clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]);
++
++	clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]);
++	clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]);
++	clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]);
++	clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]);
++	clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]);
++	clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]);
++	clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]);
++	clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]);
++
+ 	/*
+ 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
+ 	 * We can not get the 100MHz from the pll2_pfd0_352m.
+diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
+index 61364050fccd..3776f974d1dc 100644
+--- a/arch/arm/mach-imx/clk-pllv3.c
++++ b/arch/arm/mach-imx/clk-pllv3.c
+@@ -273,9 +273,10 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
+ 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
+ 	unsigned long min_rate = parent_rate * 27;
+ 	unsigned long max_rate = parent_rate * 54;
+-	u32 val, div;
++	u32 val, newval, div;
+ 	u32 mfn, mfd = 1000000;
+ 	s64 temp64;
++	int ret;
+ 
+ 	if (rate < min_rate || rate > max_rate)
+ 		return -EINVAL;
+@@ -287,13 +288,27 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
+ 	mfn = temp64;
+ 
+ 	val = readl_relaxed(pll->base);
+-	val &= ~pll->div_mask;
+-	val |= div;
+-	writel_relaxed(val, pll->base);
++
++	/* set the PLL into bypass mode */
++	newval = val | BM_PLL_BYPASS;
++	writel_relaxed(newval, pll->base);
++
++	/* configure the new frequency */
++	newval &= ~pll->div_mask;
++	newval |= div;
++	writel_relaxed(newval, pll->base);
+ 	writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
+-	writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
++	writel(mfd, pll->base + PLL_DENOM_OFFSET);
+ 
+-	return clk_pllv3_wait_lock(pll);
++	ret = clk_pllv3_wait_lock(pll);
++	if (ret == 0 && val & BM_PLL_POWER) {
++		/* only if it locked can we switch back to the PLL */
++		newval &= ~BM_PLL_BYPASS;
++		newval |= val & BM_PLL_BYPASS;
++		writel(newval, pll->base);
++	}
++
++	return ret;
+ }
+ 
+ static const struct clk_ops clk_pllv3_av_ops = {
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index 0a0a90f52d26..05a21b857996 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -174,4 +174,6 @@ source "drivers/powercap/Kconfig"
+ 
+ source "drivers/mcb/Kconfig"
+ 
++source "drivers/cec/Kconfig"
++
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 7183b6af5dac..470eec2238ca 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -157,3 +157,4 @@ obj-$(CONFIG_NTB)		+= ntb/
+ obj-$(CONFIG_FMC)		+= fmc/
+ obj-$(CONFIG_POWERCAP)		+= powercap/
+ obj-$(CONFIG_MCB)		+= mcb/
++obj-$(CONFIG_CEC)		+= cec/
+diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
+index 8befeb69eeb1..54e2972fc6da 100644
+--- a/drivers/ata/ahci_imx.c
++++ b/drivers/ata/ahci_imx.c
+@@ -62,6 +62,7 @@ struct imx_ahci_priv {
+ 	struct regmap *gpr;
+ 	bool no_device;
+ 	bool first_time;
++	u32 phy_params;
+ };
+ 
+ static int ahci_imx_hotplug;
+@@ -246,14 +247,7 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
+ 				   IMX6Q_GPR13_SATA_TX_LVL_MASK |
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN |
+ 				   IMX6Q_GPR13_SATA_TX_EDGE_RATE,
+-				   IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB |
+-				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
+-				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
+-				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
+-				   IMX6Q_GPR13_SATA_MPLL_SS_EN |
+-				   IMX6Q_GPR13_SATA_TX_ATTEN_9_16 |
+-				   IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB |
+-				   IMX6Q_GPR13_SATA_TX_LVL_1_025_V);
++				   imxpriv->phy_params);
+ 		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+ 				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+@@ -324,6 +318,10 @@ static void ahci_imx_error_handler(struct ata_port *ap)
+ 	writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
+ 	imx_sata_disable(hpriv);
+ 	imxpriv->no_device = true;
++
++	dev_info(ap->dev, "no device found, disabling link.\n");
++	dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX
++		 ".hotplug=1 to enable hotplug\n");
+ }
+ 
+ static int ahci_imx_softreset(struct ata_link *link, unsigned int *class,
+@@ -364,6 +362,165 @@ static const struct of_device_id imx_ahci_of_match[] = {
+ };
+ MODULE_DEVICE_TABLE(of, imx_ahci_of_match);
+ 
++struct reg_value {
++	u32 of_value;
++	u32 reg_value;
++};
++
++struct reg_property {
++	const char *name;
++	const struct reg_value *values;
++	size_t num_values;
++	u32 def_value;
++	u32 set_value;
++};
++
++static const struct reg_value gpr13_tx_level[] = {
++	{  937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V },
++	{  947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V },
++	{  957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V },
++	{  966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V },
++	{  976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V },
++	{  986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V },
++	{  996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V },
++	{ 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V },
++	{ 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V },
++	{ 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V },
++	{ 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V },
++	{ 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V },
++	{ 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V },
++	{ 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V },
++	{ 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V },
++	{ 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V },
++	{ 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V },
++	{ 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V },
++	{ 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V },
++	{ 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V },
++	{ 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V },
++	{ 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V },
++	{ 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V },
++	{ 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V },
++	{ 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V },
++	{ 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V },
++	{ 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V },
++	{ 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V },
++	{ 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V },
++	{ 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V },
++	{ 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V },
++	{ 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V }
++};
++
++static const struct reg_value gpr13_tx_boost[] = {
++	{    0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB },
++	{  370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB },
++	{  740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB },
++	{  111, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB },
++	{  148, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB },
++	{  185, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB },
++	{  222, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB },
++	{  259, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB },
++	{  296, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB },
++	{  333, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB },
++	{  370, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB },
++	{  407, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB },
++	{  444, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB },
++	{  481, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB },
++	{  528, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB },
++	{  575, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB }
++};
++
++static const struct reg_value gpr13_tx_atten[] = {
++	{  8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 },
++	{  9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 },
++	{ 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 },
++	{ 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 },
++	{ 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 },
++	{ 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 },
++};
++
++static const struct reg_value gpr13_rx_eq[] = {
++	{  500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB },
++	{ 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB },
++	{ 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB },
++	{ 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB },
++	{ 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB },
++	{ 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB },
++	{ 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB },
++	{ 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB },
++};
++
++static const struct reg_property gpr13_props[] = {
++	{
++		.name = "fsl,transmit-level-mV",
++		.values = gpr13_tx_level,
++		.num_values = ARRAY_SIZE(gpr13_tx_level),
++		.def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V,
++	}, {
++		.name = "fsl,transmit-boost-mdB",
++		.values = gpr13_tx_boost,
++		.num_values = ARRAY_SIZE(gpr13_tx_boost),
++		.def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB,
++	}, {
++		.name = "fsl,transmit-atten-16ths",
++		.values = gpr13_tx_atten,
++		.num_values = ARRAY_SIZE(gpr13_tx_atten),
++		.def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16,
++	}, {
++		.name = "fsl,receive-eq-mdB",
++		.values = gpr13_rx_eq,
++		.num_values = ARRAY_SIZE(gpr13_rx_eq),
++		.def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB,
++	}, {
++		.name = "fsl,no-spread-spectrum",
++		.def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN,
++		.set_value = 0,
++	},
++};
++
++static u32 imx_ahci_parse_props(struct device *dev,
++				const struct reg_property *prop, size_t num)
++{
++	struct device_node *np = dev->of_node;
++	u32 reg_value = 0;
++	int i, j;
++
++	for (i = 0; i < num; i++, prop++) {
++		u32 of_val;
++
++		if (prop->num_values == 0) {
++			if (of_property_read_bool(np, prop->name))
++				reg_value |= prop->set_value;
++			else
++				reg_value |= prop->def_value;
++			continue;
++		}
++
++		if (of_property_read_u32(np, prop->name, &of_val)) {
++			dev_info(dev, "%s not specified, using %08x\n",
++				prop->name, prop->def_value);
++			reg_value |= prop->def_value;
++			continue;
++		}
++
++		for (j = 0; j < prop->num_values; j++) {
++			if (prop->values[j].of_value == of_val) {
++				dev_info(dev, "%s value %u, using %08x\n",
++					prop->name, of_val, prop->values[j].reg_value);
++				reg_value |= prop->values[j].reg_value;
++				break;
++			}
++		}
++
++		if (j == prop->num_values) {
++			dev_err(dev, "DT property %s is not a valid value\n",
++				prop->name);
++			reg_value |= prop->def_value;
++		}
++	}
++
++	return reg_value;
++}
++
+ static int imx_ahci_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+@@ -392,6 +549,8 @@ static int imx_ahci_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	if (imxpriv->type == AHCI_IMX6Q) {
++		u32 reg_value;
++
+ 		imxpriv->gpr = syscon_regmap_lookup_by_compatible(
+ 							"fsl,imx6q-iomuxc-gpr");
+ 		if (IS_ERR(imxpriv->gpr)) {
+@@ -399,6 +558,15 @@ static int imx_ahci_probe(struct platform_device *pdev)
+ 				"failed to find fsl,imx6q-iomux-gpr regmap\n");
+ 			return PTR_ERR(imxpriv->gpr);
+ 		}
++
++		reg_value = imx_ahci_parse_props(dev, gpr13_props,
++						 ARRAY_SIZE(gpr13_props));
++
++		imxpriv->phy_params =
++				   IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M |
++				   IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F |
++				   IMX6Q_GPR13_SATA_SPD_MODE_3P0G |
++				   reg_value;
+ 	}
+ 
+ 	hpriv = ahci_platform_get_resources(pdev);
+diff --git a/drivers/cec/Kconfig b/drivers/cec/Kconfig
+new file mode 100644
+index 000000000000..d67cfb83de6a
+--- /dev/null
++++ b/drivers/cec/Kconfig
+@@ -0,0 +1,14 @@
++#
++# Consumer Electroncs Control support
++#
++
++menu "Consumer Electronics Control devices"
++
++config CEC
++	bool
++
++config HDMI_CEC_CORE
++	tristate
++	select CEC
++
++endmenu
+diff --git a/drivers/cec/Makefile b/drivers/cec/Makefile
+new file mode 100644
+index 000000000000..b94278bc8321
+--- /dev/null
++++ b/drivers/cec/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_HDMI_CEC_CORE) += cec-dev.o
+diff --git a/drivers/cec/cec-dev.c b/drivers/cec/cec-dev.c
+new file mode 100644
+index 000000000000..ba58d8217851
+--- /dev/null
++++ b/drivers/cec/cec-dev.c
+@@ -0,0 +1,384 @@
++/*
++ * HDMI Consumer Electronics Control
++ *
++ * This provides the user API for communication with HDMI CEC complaint
++ * devices in kernel drivers, and is based upon the protocol developed
++ * by Freescale for their i.MX SoCs.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/cec-dev.h>
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++struct cec_event {
++	struct cec_user_event usr;
++	struct list_head node;
++};
++
++static struct class *cec_class;
++static int cec_major;
++
++static void cec_dev_send_message(struct cec_dev *cec_dev, u8 *msg,
++	size_t count)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&cec_dev->lock, flags);
++	cec_dev->retries = 5;
++	cec_dev->write_busy = 1;
++	cec_dev->send_message(cec_dev, msg, count);
++	spin_unlock_irqrestore(&cec_dev->lock, flags);
++}
++
++void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len)
++{
++	struct cec_event *event;
++	unsigned long flags;
++
++	event = kzalloc(sizeof(*event), GFP_ATOMIC);
++	if (event) {
++		event->usr.event_type = type;
++		event->usr.msg_len = len;
++		if (msg)
++			memcpy(event->usr.msg, msg, len);
++
++		spin_lock_irqsave(&cec_dev->lock, flags);
++		list_add_tail(&event->node, &cec_dev->events);
++		spin_unlock_irqrestore(&cec_dev->lock, flags);
++		wake_up(&cec_dev->waitq);
++	}
++}
++EXPORT_SYMBOL_GPL(cec_dev_event);
++
++static int cec_dev_lock_write(struct cec_dev *cec_dev, struct file *file)
++	__acquires(cec_dev->mutex)
++{
++	int ret;
++
++	do {
++		if (file->f_flags & O_NONBLOCK) {
++			if (cec_dev->write_busy)
++				return -EAGAIN;
++		} else {
++			ret = wait_event_interruptible(cec_dev->waitq,
++						       !cec_dev->write_busy);
++			if (ret)
++				break;
++		}
++
++		ret = mutex_lock_interruptible(&cec_dev->mutex);
++		if (ret)
++			break;
++
++		if (!cec_dev->write_busy)
++			break;
++
++		mutex_unlock(&cec_dev->mutex);
++	} while (1);
++
++	return ret;
++}
++
++static ssize_t cec_dev_read(struct file *file, char __user *buf,
++	size_t count, loff_t *ppos)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	ssize_t ret;
++
++	if (count > sizeof(struct cec_user_event))
++		count = sizeof(struct cec_user_event);
++
++	if (!access_ok(VERIFY_WRITE, buf, count))
++		return -EFAULT;
++
++	do {
++		struct cec_event *event = NULL;
++		unsigned long flags;
++
++		spin_lock_irqsave(&cec_dev->lock, flags);
++		if (!list_empty(&cec_dev->events)) {
++			event = list_first_entry(&cec_dev->events,
++					struct cec_event, node);
++			list_del(&event->node);
++		}
++		spin_unlock_irqrestore(&cec_dev->lock, flags);
++
++		if (event) {
++			ret = __copy_to_user(buf, &event->usr, count) ?
++				 -EFAULT : count;
++			kfree(event);
++			break;
++		}
++
++		if (file->f_flags & O_NONBLOCK) {
++			ret = -EAGAIN;
++			break;
++		}
++
++		ret = wait_event_interruptible(cec_dev->waitq,
++					       !list_empty(&cec_dev->events));
++		if (ret)
++			break;
++	} while (1);
++
++	return ret;
++}
++
++static ssize_t cec_dev_write(struct file *file, const char __user *buf,
++	size_t count, loff_t *ppos)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	u8 msg[MAX_MESSAGE_LEN];
++	int ret;
++
++	if (count > sizeof(msg))
++		return -E2BIG;
++
++	if (copy_from_user(msg, buf, count))
++		return -EFAULT;
++
++	ret = cec_dev_lock_write(cec_dev, file);
++	if (ret)
++		return ret;
++
++	cec_dev_send_message(cec_dev, msg, count);
++
++	mutex_unlock(&cec_dev->mutex);
++
++	return count;
++}
++
++static long cec_dev_ioctl(struct file *file, u_int cmd, unsigned long arg)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	int ret;
++
++	switch (cmd) {
++	case HDMICEC_IOC_O_SETLOGICALADDRESS:
++	case HDMICEC_IOC_SETLOGICALADDRESS:
++		if (arg > 15) {
++			ret = -EINVAL;
++			break;
++		}
++
++		ret = cec_dev_lock_write(cec_dev, file);
++		if (ret == 0) {
++			unsigned char msg[1];
++
++			cec_dev->addresses = BIT(arg);
++			cec_dev->set_address(cec_dev, cec_dev->addresses);
++
++			/*
++			 * Send a ping message with the source and destination
++			 * set to our address; the result indicates whether
++			 * unit has chosen our address simultaneously.
++			 */
++			msg[0] = arg << 4 | arg;
++			cec_dev_send_message(cec_dev, msg, sizeof(msg));
++			mutex_unlock(&cec_dev->mutex);
++		}
++		break;
++
++	case HDMICEC_IOC_STARTDEVICE:
++		ret = mutex_lock_interruptible(&cec_dev->mutex);
++		if (ret == 0) {
++			cec_dev->addresses = BIT(15);
++			cec_dev->set_address(cec_dev, cec_dev->addresses);
++			mutex_unlock(&cec_dev->mutex);
++		}
++		break;
++
++	case HDMICEC_IOC_STOPDEVICE:
++		ret = 0;
++		break;
++
++	case HDMICEC_IOC_GETPHYADDRESS:
++		ret = put_user(cec_dev->physical, (u16 __user *)arg);
++		ret = -ENOIOCTLCMD;
++		break;
++
++	default:
++		ret = -ENOIOCTLCMD;
++		break;
++	}
++
++	return ret;
++}
++
++static unsigned cec_dev_poll(struct file *file, poll_table *wait)
++{
++	struct cec_dev *cec_dev = file->private_data;
++	unsigned mask = 0;
++
++	poll_wait(file, &cec_dev->waitq, wait);
++
++	if (cec_dev->write_busy == 0)
++		mask |= POLLOUT | POLLWRNORM;
++	if (!list_empty(&cec_dev->events))
++		mask |= POLLIN | POLLRDNORM;
++
++	return mask;
++}
++
++static int cec_dev_release(struct inode *inode, struct file *file)
++{
++	struct cec_dev *cec_dev = file->private_data;
++
++	mutex_lock(&cec_dev->mutex);
++	if (cec_dev->users >= 1)
++		cec_dev->users -= 1;
++	if (cec_dev->users == 0) {
++		/*
++		 * Wait for any write to complete before shutting down.
++		 * A message should complete in a maximum of 2.75ms *
++		 * 160 bits + 4.7ms, or 444.7ms.  Let's call that 500ms.
++		 * If we time out, shutdown anyway.
++		 */
++		wait_event_timeout(cec_dev->waitq, !cec_dev->write_busy,
++				   msecs_to_jiffies(500));
++
++		cec_dev->release(cec_dev);
++
++		while (!list_empty(&cec_dev->events)) {
++			struct cec_event *event;
++
++			event = list_first_entry(&cec_dev->events,
++					struct cec_event, node);
++			list_del(&event->node);
++			kfree(event);
++		}
++	}
++	mutex_unlock(&cec_dev->mutex);
++	return 0;
++}
++
++static int cec_dev_open(struct inode *inode, struct file *file)
++{
++	struct cec_dev *cec_dev = container_of(inode->i_cdev, struct cec_dev,
++					       cdev);
++	int ret = 0;
++
++	nonseekable_open(inode, file);
++
++	file->private_data = cec_dev;
++
++	ret = mutex_lock_interruptible(&cec_dev->mutex);
++	if (ret)
++		return ret;
++
++	if (cec_dev->users++ == 0) {
++		cec_dev->addresses = BIT(15);
++
++		ret = cec_dev->open(cec_dev);
++		if (ret < 0)
++			cec_dev->users = 0;
++	}
++	mutex_unlock(&cec_dev->mutex);
++
++	return ret;
++}
++
++static const struct file_operations hdmi_cec_fops = {
++	.owner = THIS_MODULE,
++	.read = cec_dev_read,
++	.write = cec_dev_write,
++	.open = cec_dev_open,
++	.unlocked_ioctl = cec_dev_ioctl,
++	.release = cec_dev_release,
++	.poll = cec_dev_poll,
++};
++
++void cec_dev_init(struct cec_dev *cec_dev, struct module *module)
++{
++	cec_dev->devn = MKDEV(cec_major, 0);
++
++	INIT_LIST_HEAD(&cec_dev->events);
++	init_waitqueue_head(&cec_dev->waitq);
++	spin_lock_init(&cec_dev->lock);
++	mutex_init(&cec_dev->mutex);
++
++	cec_dev->addresses = BIT(15);
++
++	cdev_init(&cec_dev->cdev, &hdmi_cec_fops);
++	cec_dev->cdev.owner = module;
++}
++EXPORT_SYMBOL_GPL(cec_dev_init);
++
++int cec_dev_add(struct cec_dev *cec_dev, struct device *dev, const char *name)
++{
++	struct device *cd;
++	int ret;
++
++	ret = cdev_add(&cec_dev->cdev, cec_dev->devn, 1);
++	if (ret < 0)
++		goto err_cdev;
++
++	cd = device_create(cec_class, dev, cec_dev->devn, NULL, name);
++	if (IS_ERR(cd)) {
++		ret = PTR_ERR(cd);
++		dev_err(dev, "can't create device: %d\n", ret);
++		goto err_dev;
++	}
++
++	return 0;
++
++ err_dev:
++	cdev_del(&cec_dev->cdev);
++ err_cdev:
++	return ret;
++}
++EXPORT_SYMBOL_GPL(cec_dev_add);
++
++void cec_dev_remove(struct cec_dev *cec_dev)
++{
++	device_destroy(cec_class, cec_dev->devn);
++	cdev_del(&cec_dev->cdev);
++}
++EXPORT_SYMBOL_GPL(cec_dev_remove);
++
++static int cec_init(void)
++{
++	dev_t dev;
++	int ret;
++
++	cec_class = class_create(THIS_MODULE, "hdmi-cec");
++	if (IS_ERR(cec_class)) {
++		ret = PTR_ERR(cec_class);
++		pr_err("cec: can't create cec class: %d\n", ret);
++		goto err_class;
++	}
++
++	ret = alloc_chrdev_region(&dev, 0, 1, "hdmi-cec");
++	if (ret) {
++		pr_err("cec: can't create character devices: %d\n", ret);
++		goto err_chrdev;
++	}
++
++	cec_major = MAJOR(dev);
++
++	return 0;
++
++ err_chrdev:
++	class_destroy(cec_class);
++ err_class:
++	return ret;
++}
++subsys_initcall(cec_init);
++
++static void cec_exit(void)
++{
++	unregister_chrdev_region(MKDEV(cec_major, 0), 1);
++	class_destroy(cec_class);
++}
++module_exit(cec_exit);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Generic HDMI CEC driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
+index df281b54db01..20585cf62091 100644
+--- a/drivers/gpu/drm/drm_crtc_helper.c
++++ b/drivers/gpu/drm/drm_crtc_helper.c
+@@ -140,16 +140,10 @@ drm_encoder_disable(struct drm_encoder *encoder)
+ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
+ {
+ 	struct drm_encoder *encoder;
+-	struct drm_connector *connector;
+ 	struct drm_crtc *crtc;
+ 
+ 	drm_warn_on_modeset_not_all_locked(dev);
+ 
+-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+-		if (!connector->encoder)
+-			continue;
+-	}
+-
+ 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ 		if (!drm_helper_encoder_in_use(encoder)) {
+ 			drm_encoder_disable(encoder);
+diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
+index 7d0aaed1e23a..f5cf1b0f2748 100644
+--- a/drivers/leds/leds-pwm.c
++++ b/drivers/leds/leds-pwm.c
+@@ -69,6 +69,10 @@ static void led_pwm_set(struct led_classdev *led_cdev,
+ 
+ 	duty *= brightness;
+ 	do_div(duty, max);
++
++	if (led_dat->active_low)
++		duty = led_dat->period - duty;
++
+ 	led_dat->duty = duty;
+ 
+ 	if (led_dat->can_sleep)
+@@ -92,55 +96,75 @@ static void led_pwm_cleanup(struct led_pwm_priv *priv)
+ 	}
+ }
+ 
+-static int led_pwm_create_of(struct platform_device *pdev,
+-			     struct led_pwm_priv *priv)
++static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
++		       struct led_pwm *led, struct device_node *child)
+ {
+-	struct device_node *child;
++	struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
+ 	int ret;
+ 
+-	for_each_child_of_node(pdev->dev.of_node, child) {
+-		struct led_pwm_data *led_dat = &priv->leds[priv->num_leds];
++	led_data->active_low = led->active_low;
++	led_data->period = led->pwm_period_ns;
++	led_data->cdev.name = led->name;
++	led_data->cdev.default_trigger = led->default_trigger;
++	led_data->cdev.brightness_set = led_pwm_set;
++	led_data->cdev.brightness = LED_OFF;
++	led_data->cdev.max_brightness = led->max_brightness;
++	led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
++
++	if (child)
++		led_data->pwm = devm_of_pwm_get(dev, child, NULL);
++	else
++		led_data->pwm = devm_pwm_get(dev, led->name);
++	if (IS_ERR(led_data->pwm)) {
++		ret = PTR_ERR(led_data->pwm);
++		dev_err(dev, "unable to request PWM for %s: %d\n",
++			led->name, ret);
++		return ret;
++	}
+ 
+-		led_dat->cdev.name = of_get_property(child, "label",
+-						     NULL) ? : child->name;
++	if (child)
++		led_data->period = pwm_get_period(led_data->pwm);
+ 
+-		led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL);
+-		if (IS_ERR(led_dat->pwm)) {
+-			dev_err(&pdev->dev, "unable to request PWM for %s\n",
+-				led_dat->cdev.name);
+-			ret = PTR_ERR(led_dat->pwm);
+-			goto err;
+-		}
+-		/* Get the period from PWM core when n*/
+-		led_dat->period = pwm_get_period(led_dat->pwm);
++	led_data->can_sleep = pwm_can_sleep(led_data->pwm);
++	if (led_data->can_sleep)
++		INIT_WORK(&led_data->work, led_pwm_work);
+ 
+-		led_dat->cdev.default_trigger = of_get_property(child,
+-						"linux,default-trigger", NULL);
+-		of_property_read_u32(child, "max-brightness",
+-				     &led_dat->cdev.max_brightness);
++	ret = led_classdev_register(dev, &led_data->cdev);
++	if (ret == 0) {
++		priv->num_leds++;
++	} else {
++		dev_err(dev, "failed to register PWM led for %s: %d\n",
++			led->name, ret);
++	}
+ 
+-		led_dat->cdev.brightness_set = led_pwm_set;
+-		led_dat->cdev.brightness = LED_OFF;
+-		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
++	return ret;
++}
+ 
+-		led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
+-		if (led_dat->can_sleep)
+-			INIT_WORK(&led_dat->work, led_pwm_work);
++static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
++{
++	struct device_node *child;
++	struct led_pwm led;
++	int ret = 0;
+ 
+-		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+-		if (ret < 0) {
+-			dev_err(&pdev->dev, "failed to register for %s\n",
+-				led_dat->cdev.name);
++	memset(&led, 0, sizeof(led));
++
++	for_each_child_of_node(dev->of_node, child) {
++		led.name = of_get_property(child, "label", NULL) ? :
++			   child->name;
++
++		led.default_trigger = of_get_property(child,
++						"linux,default-trigger", NULL);
++		led.active_low = of_property_read_bool(child, "active-low");
++		of_property_read_u32(child, "max-brightness",
++				     &led.max_brightness);
++
++		ret = led_pwm_add(dev, priv, &led, child);
++		if (ret) {
+ 			of_node_put(child);
+-			goto err;
++			break;
+ 		}
+-		priv->num_leds++;
+ 	}
+ 
+-	return 0;
+-err:
+-	led_pwm_cleanup(priv);
+-
+ 	return ret;
+ }
+ 
+@@ -166,51 +190,23 @@ static int led_pwm_probe(struct platform_device *pdev)
+ 
+ 	if (pdata) {
+ 		for (i = 0; i < count; i++) {
+-			struct led_pwm *cur_led = &pdata->leds[i];
+-			struct led_pwm_data *led_dat = &priv->leds[i];
+-
+-			led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name);
+-			if (IS_ERR(led_dat->pwm)) {
+-				ret = PTR_ERR(led_dat->pwm);
+-				dev_err(&pdev->dev,
+-					"unable to request PWM for %s\n",
+-					cur_led->name);
+-				goto err;
+-			}
+-
+-			led_dat->cdev.name = cur_led->name;
+-			led_dat->cdev.default_trigger = cur_led->default_trigger;
+-			led_dat->active_low = cur_led->active_low;
+-			led_dat->period = cur_led->pwm_period_ns;
+-			led_dat->cdev.brightness_set = led_pwm_set;
+-			led_dat->cdev.brightness = LED_OFF;
+-			led_dat->cdev.max_brightness = cur_led->max_brightness;
+-			led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+-
+-			led_dat->can_sleep = pwm_can_sleep(led_dat->pwm);
+-			if (led_dat->can_sleep)
+-				INIT_WORK(&led_dat->work, led_pwm_work);
+-
+-			ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
+-			if (ret < 0)
+-				goto err;
++			ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i],
++					  NULL);
++			if (ret)
++				break;
+ 		}
+-		priv->num_leds = count;
+ 	} else {
+-		ret = led_pwm_create_of(pdev, priv);
+-		if (ret)
+-			return ret;
++		ret = led_pwm_create_of(&pdev->dev, priv);
++	}
++
++	if (ret) {
++		led_pwm_cleanup(priv);
++		return ret;
+ 	}
+ 
+ 	platform_set_drvdata(pdev, priv);
+ 
+ 	return 0;
+-
+-err:
+-	priv->num_leds = i;
+-	led_pwm_cleanup(priv);
+-
+-	return ret;
+ }
+ 
+ static int led_pwm_remove(struct platform_device *pdev)
+diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
+index acbc3f2aaaf9..41c4033ec765 100644
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -13,11 +13,13 @@
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
++#include <linux/clk.h>
+ #include <linux/completion.h>
+ #include <linux/device.h>
+ #include <linux/delay.h>
+ #include <linux/pagemap.h>
+ #include <linux/err.h>
++#include <linux/gpio.h>
+ #include <linux/leds.h>
+ #include <linux/scatterlist.h>
+ #include <linux/log2.h>
+@@ -1504,6 +1506,43 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
+ 	mmc_host_clk_release(host);
+ }
+ 
++static void mmc_card_power_up(struct mmc_host *host)
++{
++	int i;
++	struct gpio_desc **gds = host->card_reset_gpios;
++
++	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++		if (gds[i]) {
++			dev_dbg(host->parent, "Asserting reset line %d", i);
++			gpiod_set_value(gds[i], 1);
++		}
++	}
++
++	if (host->card_regulator) {
++		dev_dbg(host->parent, "Enabling external regulator");
++		if (regulator_enable(host->card_regulator))
++			dev_err(host->parent, "Failed to enable external regulator");
++	}
++
++	if (host->card_clk) {
++		dev_dbg(host->parent, "Enabling external clock");
++		clk_prepare_enable(host->card_clk);
++	}
++
++	/* 2ms delay to let clocks and power settle */
++	mmc_delay(20);
++
++	for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++		if (gds[i]) {
++			dev_dbg(host->parent, "Deasserting reset line %d", i);
++			gpiod_set_value(gds[i], 0);
++		}
++	}
++
++	/* 2ms delay to after reset release */
++	mmc_delay(20);
++}
++
+ /*
+  * Apply power to the MMC stack.  This is a two-stage process.
+  * First, we enable power to the card without the clock running.
+@@ -1520,6 +1559,9 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
+ 	if (host->ios.power_mode == MMC_POWER_ON)
+ 		return;
+ 
++	/* Power up the card/module first, if needed */
++	mmc_card_power_up(host);
++
+ 	mmc_host_clk_hold(host);
+ 
+ 	host->ios.vdd = fls(ocr) - 1;
+diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
+index fdea825dbb24..c523f55b317c 100644
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -12,14 +12,18 @@
+  *  MMC host class device management
+  */
+ 
++#include <linux/kernel.h>
++#include <linux/clk.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/idr.h>
+ #include <linux/of.h>
+ #include <linux/of_gpio.h>
+ #include <linux/pagemap.h>
+ #include <linux/export.h>
+ #include <linux/leds.h>
++#include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/suspend.h>
+ 
+@@ -457,6 +461,66 @@ int mmc_of_parse(struct mmc_host *host)
+ 
+ EXPORT_SYMBOL(mmc_of_parse);
+ 
++static int mmc_of_parse_child(struct mmc_host *host)
++{
++	struct device_node *np;
++	struct clk *clk;
++	int i;
++
++	if (!host->parent || !host->parent->of_node)
++		return 0;
++
++	np = host->parent->of_node;
++
++	host->card_regulator = regulator_get(host->parent, "card-external-vcc");
++	if (IS_ERR(host->card_regulator)) {
++		if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER)
++			return PTR_ERR(host->card_regulator);
++		host->card_regulator = NULL;
++	}
++
++	/* Parse card power/reset/clock control */
++	if (of_find_property(np, "card-reset-gpios", NULL)) {
++		struct gpio_desc *gpd;
++		int level = 0;
++
++		/*
++		 * If the regulator is enabled, then we can hold the
++		 * card in reset with an active high resets.  Otherwise,
++		 * hold the resets low.
++		 */
++		if (host->card_regulator && regulator_is_enabled(host->card_regulator))
++			level = 1;
++
++		for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) {
++			gpd = devm_gpiod_get_index(host->parent, "card-reset", i);
++			if (IS_ERR(gpd)) {
++				if (PTR_ERR(gpd) == -EPROBE_DEFER)
++					return PTR_ERR(gpd);
++				break;
++			}
++			gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level);
++			host->card_reset_gpios[i] = gpd;
++		}
++
++		gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios));
++		if (!IS_ERR(gpd)) {
++			dev_warn(host->parent, "More reset gpios than we can handle");
++			gpiod_put(gpd);
++		}
++	}
++
++	clk = of_clk_get_by_name(np, "card_ext_clock");
++	if (IS_ERR(clk)) {
++		if (PTR_ERR(clk) == -EPROBE_DEFER)
++			return PTR_ERR(clk);
++		clk = NULL;
++	}
++	host->card_clk = clk;
++
++	return 0;
++}
++
+ /**
+  *	mmc_alloc_host - initialise the per-host structure.
+  *	@extra: sizeof private data structure
+@@ -536,6 +600,10 @@ int mmc_add_host(struct mmc_host *host)
+ {
+ 	int err;
+ 
++	err = mmc_of_parse_child(host);
++	if (err)
++		return err;
++
+ 	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
+ 		!host->ops->enable_sdio_irq);
+ 
+diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
+index aaa90460ed23..5cc13c8d35bb 100644
+--- a/drivers/mmc/core/sdio_irq.c
++++ b/drivers/mmc/core/sdio_irq.c
+@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
+ 	return ret;
+ }
+ 
++void sdio_run_irqs(struct mmc_host *host)
++{
++	mmc_claim_host(host);
++	host->sdio_irq_pending = true;
++	process_sdio_pending_irqs(host);
++	mmc_release_host(host);
++}
++EXPORT_SYMBOL_GPL(sdio_run_irqs);
++
+ static int sdio_irq_thread(void *_host)
+ {
+ 	struct mmc_host *host = _host;
+@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)
+ 	WARN_ON(!host->claimed);
+ 
+ 	if (!host->sdio_irqs++) {
+-		atomic_set(&host->sdio_irq_thread_abort, 0);
+-		host->sdio_irq_thread =
+-			kthread_run(sdio_irq_thread, host, "ksdioirqd/%s",
+-				mmc_hostname(host));
+-		if (IS_ERR(host->sdio_irq_thread)) {
+-			int err = PTR_ERR(host->sdio_irq_thread);
+-			host->sdio_irqs--;
+-			return err;
++		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
++			atomic_set(&host->sdio_irq_thread_abort, 0);
++			host->sdio_irq_thread =
++				kthread_run(sdio_irq_thread, host,
++					    "ksdioirqd/%s", mmc_hostname(host));
++			if (IS_ERR(host->sdio_irq_thread)) {
++				int err = PTR_ERR(host->sdio_irq_thread);
++				host->sdio_irqs--;
++				return err;
++			}
++		} else {
++			mmc_host_clk_hold(host);
++			host->ops->enable_sdio_irq(host, 1);
++			mmc_host_clk_release(host);
+ 		}
+ 	}
+ 
+@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)
+ 	BUG_ON(host->sdio_irqs < 1);
+ 
+ 	if (!--host->sdio_irqs) {
+-		atomic_set(&host->sdio_irq_thread_abort, 1);
+-		kthread_stop(host->sdio_irq_thread);
++		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
++			atomic_set(&host->sdio_irq_thread_abort, 1);
++			kthread_stop(host->sdio_irq_thread);
++		} else {
++			mmc_host_clk_hold(host);
++			host->ops->enable_sdio_irq(host, 0);
++			mmc_host_clk_release(host);
++		}
+ 	}
+ 
+ 	return 0;
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 8aaf8c1f3f63..d8c1f31ab37f 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -25,8 +25,7 @@ config MMC_PXA
+ 	  If unsure, say N.
+ 
+ config MMC_SDHCI
+-	tristate "Secure Digital Host Controller Interface support"
+-	depends on HAS_DMA
++	tristate
+ 	help
+ 	  This selects the generic Secure Digital Host Controller Interface.
+ 	  It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
+@@ -59,7 +58,8 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+ 
+ config MMC_SDHCI_PCI
+ 	tristate "SDHCI support on PCI bus"
+-	depends on MMC_SDHCI && PCI
++	depends on PCI && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the PCI Secure Digital Host Controller Interface.
+ 	  Most controllers found today are PCI devices.
+@@ -83,7 +83,8 @@ config MMC_RICOH_MMC
+ 
+ config MMC_SDHCI_ACPI
+ 	tristate "SDHCI support for ACPI enumerated SDHCI controllers"
+-	depends on MMC_SDHCI && ACPI
++	depends on ACPI && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects support for ACPI enumerated SDHCI controllers,
+ 	  identified by ACPI Compatibility ID PNP0D40 or specific
+@@ -94,8 +95,8 @@ config MMC_SDHCI_ACPI
+ 	  If unsure, say N.
+ 
+ config MMC_SDHCI_PLTFM
+-	tristate "SDHCI platform and OF driver helper"
+-	depends on MMC_SDHCI
++	tristate
++	select MMC_SDHCI
+ 	help
+ 	  This selects the common helper functions support for Secure Digital
+ 	  Host Controller Interface based platform and OF drivers.
+@@ -106,8 +107,8 @@ config MMC_SDHCI_PLTFM
+ 
+ config MMC_SDHCI_OF_ARASAN
+ 	tristate "SDHCI OF support for the Arasan SDHCI controllers"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on OF
++	depends on OF && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Arasan Secure Digital Host Controller Interface
+ 	  (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
+@@ -118,9 +119,9 @@ config MMC_SDHCI_OF_ARASAN
+ 
+ config MMC_SDHCI_OF_ESDHC
+ 	tristate "SDHCI OF support for the Freescale eSDHC controller"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on PPC_OF
++	depends on PPC_OF && HAS_DMA
+ 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Freescale eSDHC controller support.
+ 
+@@ -130,9 +131,9 @@ config MMC_SDHCI_OF_ESDHC
+ 
+ config MMC_SDHCI_OF_HLWD
+ 	tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+-	depends on MMC_SDHCI_PLTFM
+-	depends on PPC_OF
++	depends on PPC_OF && HAS_DMA
+ 	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  found in the "Hollywood" chipset of the Nintendo Wii video game
+@@ -144,8 +145,8 @@ config MMC_SDHCI_OF_HLWD
+ 
+ config MMC_SDHCI_CNS3XXX
+ 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
+-	depends on ARCH_CNS3XXX
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_CNS3XXX && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the SDHCI support for CNS3xxx System-on-Chip devices.
+ 
+@@ -155,9 +156,9 @@ config MMC_SDHCI_CNS3XXX
+ 
+ config MMC_SDHCI_ESDHC_IMX
+ 	tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
+-	depends on ARCH_MXC
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_MXC && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Freescale eSDHC/uSDHC controller support
+ 	  found on i.MX25, i.MX35 i.MX5x and i.MX6x.
+@@ -168,9 +169,9 @@ config MMC_SDHCI_ESDHC_IMX
+ 
+ config MMC_SDHCI_DOVE
+ 	tristate "SDHCI support on Marvell's Dove SoC"
+-	depends on ARCH_DOVE
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_DOVE && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface in
+ 	  Marvell's Dove SoC.
+@@ -181,9 +182,9 @@ config MMC_SDHCI_DOVE
+ 
+ config MMC_SDHCI_TEGRA
+ 	tristate "SDHCI platform support for the Tegra SD/MMC Controller"
+-	depends on ARCH_TEGRA
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_TEGRA && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Tegra SD/MMC controller. If you have a Tegra
+ 	  platform with SD or MMC devices, say Y or M here.
+@@ -192,7 +193,8 @@ config MMC_SDHCI_TEGRA
+ 
+ config MMC_SDHCI_S3C
+ 	tristate "SDHCI support on Samsung S3C SoC"
+-	depends on MMC_SDHCI && PLAT_SAMSUNG
++	depends on PLAT_SAMSUNG && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  often referrered to as the HSMMC block in some of the Samsung S3C
+@@ -204,8 +206,8 @@ config MMC_SDHCI_S3C
+ 
+ config MMC_SDHCI_SIRF
+ 	tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs"
+-	depends on ARCH_SIRF
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_SIRF && HAS_DMA
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the SDHCI support for SiRF System-on-Chip devices.
+ 
+@@ -215,8 +217,7 @@ config MMC_SDHCI_SIRF
+ 
+ config MMC_SDHCI_PXAV3
+ 	tristate "Marvell MMP2 SD Host Controller support (PXAV3)"
+-	depends on CLKDEV_LOOKUP
+-	select MMC_SDHCI
++	depends on CLKDEV_LOOKUP && HAS_DMA
+ 	select MMC_SDHCI_PLTFM
+ 	default CPU_MMP2
+ 	help
+@@ -228,8 +229,7 @@ config MMC_SDHCI_PXAV3
+ 
+ config MMC_SDHCI_PXAV2
+ 	tristate "Marvell PXA9XX SD Host Controller support (PXAV2)"
+-	depends on CLKDEV_LOOKUP
+-	select MMC_SDHCI
++	depends on CLKDEV_LOOKUP && HAS_DMA
+ 	select MMC_SDHCI_PLTFM
+ 	default CPU_PXA910
+ 	help
+@@ -241,7 +241,8 @@ config MMC_SDHCI_PXAV2
+ 
+ config MMC_SDHCI_SPEAR
+ 	tristate "SDHCI support on ST SPEAr platform"
+-	depends on MMC_SDHCI && PLAT_SPEAR
++	depends on PLAT_SPEAR && HAS_DMA
++	select MMC_SDHCI
+ 	help
+ 	  This selects the Secure Digital Host Controller Interface (SDHCI)
+ 	  often referrered to as the HSMMC block in some of the ST SPEAR range
+@@ -263,7 +264,7 @@ config MMC_SDHCI_S3C_DMA
+ 
+ config MMC_SDHCI_BCM_KONA
+ 	tristate "SDHCI support on Broadcom KONA platform"
+-	depends on ARCH_BCM_MOBILE
++	depends on ARCH_BCM_MOBILE && HAS_DMA
+ 	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the Broadcom Kona Secure Digital Host Controller
+@@ -274,9 +275,9 @@ config MMC_SDHCI_BCM_KONA
+ 
+ config MMC_SDHCI_BCM2835
+ 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
+-	depends on ARCH_BCM2835
+-	depends on MMC_SDHCI_PLTFM
++	depends on ARCH_BCM2835 && HAS_DMA
+ 	select MMC_SDHCI_IO_ACCESSORS
++	select MMC_SDHCI_PLTFM
+ 	help
+ 	  This selects the BCM2835 SD/MMC controller. If you have a BCM2835
+ 	  platform with SD or MMC devices, say Y or M here.
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index cced599d5aeb..a2c12ebb376e 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -2140,6 +2140,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
+ 	if (!mmc)
+ 		return -ENOMEM;
+ 
++	mmc_of_parse(mmc);
++
+ 	slot = mmc_priv(mmc);
+ 	slot->id = id;
+ 	slot->mmc = mmc;
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+index ebb3f392b589..8ce3c28cb76e 100644
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -102,11 +102,19 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
+ }
+ 
+ static const struct sdhci_ops sdhci_acpi_ops_dflt = {
++	.set_clock = sdhci_set_clock,
+ 	.enable_dma = sdhci_acpi_enable_dma,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_ops sdhci_acpi_ops_int = {
++	.set_clock = sdhci_set_clock,
+ 	.enable_dma = sdhci_acpi_enable_dma,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ 	.hw_reset   = sdhci_acpi_int_hw_reset,
+ };
+ 
+diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
+index 6f166e63b817..dd780c315a63 100644
+--- a/drivers/mmc/host/sdhci-bcm-kona.c
++++ b/drivers/mmc/host/sdhci-bcm-kona.c
+@@ -206,9 +206,13 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
+ }
+ 
+ static struct sdhci_ops sdhci_bcm_kona_ops = {
++	.set_clock = sdhci_set_clock,
+ 	.get_max_clock = sdhci_bcm_kona_get_max_clk,
+ 	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
+ 	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ 	.card_event = sdhci_bcm_kona_card_event,
+ };
+ 
+diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
+index f6d8d67c545f..46af9a439d7b 100644
+--- a/drivers/mmc/host/sdhci-bcm2835.c
++++ b/drivers/mmc/host/sdhci-bcm2835.c
+@@ -131,8 +131,12 @@ static const struct sdhci_ops bcm2835_sdhci_ops = {
+ 	.read_l = bcm2835_sdhci_readl,
+ 	.read_w = bcm2835_sdhci_readw,
+ 	.read_b = bcm2835_sdhci_readb,
++	.set_clock = sdhci_set_clock,
+ 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ 	.get_min_clock = bcm2835_sdhci_get_min_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
+diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c
+index f2cc26633cb2..14b74075589a 100644
+--- a/drivers/mmc/host/sdhci-cns3xxx.c
++++ b/drivers/mmc/host/sdhci-cns3xxx.c
+@@ -30,13 +30,12 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	u16 clk;
+ 	unsigned long timeout;
+ 
+-	if (clock == host->clock)
+-		return;
++	host->mmc->actual_clock = 0;
+ 
+ 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+ 
+ 	if (clock == 0)
+-		goto out;
++		return;
+ 
+ 	while (host->max_clk / div > clock) {
+ 		/*
+@@ -75,13 +74,14 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
+ 
+ 	clk |= SDHCI_CLOCK_CARD_EN;
+ 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+-out:
+-	host->clock = clock;
+ }
+ 
+ static const struct sdhci_ops sdhci_cns3xxx_ops = {
+ 	.get_max_clock	= sdhci_cns3xxx_get_max_clk,
+ 	.set_clock	= sdhci_cns3xxx_set_clock,
++	.set_bus_width	= sdhci_set_bus_width,
++	.reset          = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+@@ -90,8 +90,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
+ 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ 		  SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
+ 		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+-		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+-		  SDHCI_QUIRK_NONSTANDARD_CLOCK,
++		  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
+ };
+ 
+ static int sdhci_cns3xxx_probe(struct platform_device *pdev)
+diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
+index 736d7a2eb7ec..0d315f4496c8 100644
+--- a/drivers/mmc/host/sdhci-dove.c
++++ b/drivers/mmc/host/sdhci-dove.c
+@@ -86,6 +86,10 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
+ static const struct sdhci_ops sdhci_dove_ops = {
+ 	.read_w	= sdhci_dove_readw,
+ 	.read_l	= sdhci_dove_readl,
++	.set_clock = sdhci_set_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_pltfm_data sdhci_dove_pdata = {
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index b841bb7cd371..4866d802f9e2 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -160,7 +160,6 @@ struct pltfm_imx_data {
+ 		MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
+ 		WAIT_FOR_INT,        /* sent CMD12, waiting for response INT */
+ 	} multiblock_status;
+-	u32 uhs_mode;
+ 	u32 is_ddr;
+ };
+ 
+@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
+ 		if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
+ 			ret |= SDHCI_CTRL_TUNED_CLK;
+ 
+-		ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
+ 		ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+ 
+ 		return ret;
+@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
+ 		else
+ 			new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
+ 		writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
+-		imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
+ 		if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
+ 			new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ 			if (val & SDHCI_CTRL_TUNED_CLK)
+@@ -600,12 +597,14 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
+ 	u32 temp, val;
+ 
+ 	if (clock == 0) {
++		host->mmc->actual_clock = 0;
++
+ 		if (esdhc_is_usdhc(imx_data)) {
+ 			val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ 			writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
+ 					host->ioaddr + ESDHC_VENDOR_SPEC);
+ 		}
+-		goto out;
++		return;
+ 	}
+ 
+ 	if (esdhc_is_usdhc(imx_data) && !imx_data->is_ddr)
+@@ -645,8 +644,6 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
+ 	}
+ 
+ 	mdelay(1);
+-out:
+-	host->clock = clock;
+ }
+ 
+ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+@@ -668,7 +665,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+ 	return -ENOSYS;
+ }
+ 
+-static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
++static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u32 ctrl;
+ 
+@@ -686,8 +683,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
+ 
+ 	esdhc_clrset_le(host, ESDHC_CTRL_BUSWIDTH_MASK, ctrl,
+ 			SDHCI_HOST_CONTROL);
+-
+-	return 0;
+ }
+ 
+ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
+@@ -697,6 +692,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
+ 	/* FIXME: delay a bit for card to be ready for next tuning due to errors */
+ 	mdelay(1);
+ 
++	/* This is balanced by the runtime put in sdhci_tasklet_finish */
+ 	pm_runtime_get_sync(host->mmc->parent);
+ 	reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ 	reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
+@@ -713,13 +709,12 @@ static void esdhc_request_done(struct mmc_request *mrq)
+ 	complete(&mrq->completion);
+ }
+ 
+-static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
++static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode,
++				 struct scatterlist *sg)
+ {
+ 	struct mmc_command cmd = {0};
+ 	struct mmc_request mrq = {NULL};
+ 	struct mmc_data data = {0};
+-	struct scatterlist sg;
+-	char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
+ 
+ 	cmd.opcode = opcode;
+ 	cmd.arg = 0;
+@@ -728,11 +723,9 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
+ 	data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
+ 	data.blocks = 1;
+ 	data.flags = MMC_DATA_READ;
+-	data.sg = &sg;
++	data.sg = sg;
+ 	data.sg_len = 1;
+ 
+-	sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
+-
+ 	mrq.cmd = &cmd;
+ 	mrq.cmd->mrq = &mrq;
+ 	mrq.data = &data;
+@@ -742,14 +735,12 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
+ 	mrq.done = esdhc_request_done;
+ 	init_completion(&(mrq.completion));
+ 
+-	disable_irq(host->irq);
+-	spin_lock(&host->lock);
++	spin_lock_irq(&host->lock);
+ 	host->mrq = &mrq;
+ 
+ 	sdhci_send_command(host, mrq.cmd);
+ 
+-	spin_unlock(&host->lock);
+-	enable_irq(host->irq);
++	spin_unlock_irq(&host->lock);
+ 
+ 	wait_for_completion(&mrq.completion);
+ 
+@@ -772,13 +763,21 @@ static void esdhc_post_tuning(struct sdhci_host *host)
+ 
+ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
+ {
++	struct scatterlist sg;
++	char *tuning_pattern;
+ 	int min, max, avg, ret;
+ 
++	tuning_pattern = kmalloc(ESDHC_TUNING_BLOCK_PATTERN_LEN, GFP_KERNEL);
++	if (!tuning_pattern)
++		return -ENOMEM;
++
++	sg_init_one(&sg, tuning_pattern, ESDHC_TUNING_BLOCK_PATTERN_LEN);
++
+ 	/* find the mininum delay first which can pass tuning */
+ 	min = ESDHC_TUNE_CTRL_MIN;
+ 	while (min < ESDHC_TUNE_CTRL_MAX) {
+ 		esdhc_prepare_tuning(host, min);
+-		if (!esdhc_send_tuning_cmd(host, opcode))
++		if (!esdhc_send_tuning_cmd(host, opcode, &sg))
+ 			break;
+ 		min += ESDHC_TUNE_CTRL_STEP;
+ 	}
+@@ -787,7 +786,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
+ 	max = min + ESDHC_TUNE_CTRL_STEP;
+ 	while (max < ESDHC_TUNE_CTRL_MAX) {
+ 		esdhc_prepare_tuning(host, max);
+-		if (esdhc_send_tuning_cmd(host, opcode)) {
++		if (esdhc_send_tuning_cmd(host, opcode, &sg)) {
+ 			max -= ESDHC_TUNE_CTRL_STEP;
+ 			break;
+ 		}
+@@ -797,9 +796,11 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
+ 	/* use average delay to get the best timing */
+ 	avg = (min + max) / 2;
+ 	esdhc_prepare_tuning(host, avg);
+-	ret = esdhc_send_tuning_cmd(host, opcode);
++	ret = esdhc_send_tuning_cmd(host, opcode, &sg);
+ 	esdhc_post_tuning(host);
+ 
++	kfree(tuning_pattern);
++
+ 	dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
+ 		ret ? "failed" : "passed", avg, ret);
+ 
+@@ -837,28 +838,20 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
+ 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
+ }
+ 
+-static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
++static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+ {
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ 	struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+ 
+-	switch (uhs) {
++	switch (timing) {
+ 	case MMC_TIMING_UHS_SDR12:
+-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
+-		break;
+ 	case MMC_TIMING_UHS_SDR25:
+-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
+-		break;
+ 	case MMC_TIMING_UHS_SDR50:
+-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
+-		break;
+ 	case MMC_TIMING_UHS_SDR104:
+ 	case MMC_TIMING_MMC_HS200:
+-		imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
+ 		break;
+ 	case MMC_TIMING_UHS_DDR50:
+-		imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
+ 		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
+ 				ESDHC_MIX_CTRL_DDREN,
+ 				host->ioaddr + ESDHC_MIX_CTRL);
+@@ -875,7 +868,15 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+ 		break;
+ 	}
+ 
+-	return esdhc_change_pinstate(host, uhs);
++	esdhc_change_pinstate(host, timing);
++}
++
++static void esdhc_reset(struct sdhci_host *host, u8 mask)
++{
++	sdhci_reset(host, mask);
++
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ }
+ 
+ static struct sdhci_ops sdhci_esdhc_ops = {
+@@ -888,8 +889,9 @@ static struct sdhci_ops sdhci_esdhc_ops = {
+ 	.get_max_clock = esdhc_pltfm_get_max_clock,
+ 	.get_min_clock = esdhc_pltfm_get_min_clock,
+ 	.get_ro = esdhc_pltfm_get_ro,
+-	.platform_bus_width = esdhc_pltfm_bus_width,
++	.set_bus_width = esdhc_pltfm_set_bus_width,
+ 	.set_uhs_signaling = esdhc_set_uhs_signaling,
++	.reset = esdhc_reset,
+ };
+ 
+ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
+@@ -1170,8 +1172,10 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev)
+ 
+ 	ret = sdhci_runtime_suspend_host(host);
+ 
+-	clk_disable_unprepare(imx_data->clk_per);
+-	clk_disable_unprepare(imx_data->clk_ipg);
++	if (!sdhci_sdio_irq_enabled(host)) {
++		clk_disable_unprepare(imx_data->clk_per);
++		clk_disable_unprepare(imx_data->clk_ipg);
++	}
+ 	clk_disable_unprepare(imx_data->clk_ahb);
+ 
+ 	return ret;
+@@ -1183,8 +1187,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ 	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ 
+-	clk_prepare_enable(imx_data->clk_per);
+-	clk_prepare_enable(imx_data->clk_ipg);
++	if (!sdhci_sdio_irq_enabled(host)) {
++		clk_prepare_enable(imx_data->clk_per);
++		clk_prepare_enable(imx_data->clk_ipg);
++	}
+ 	clk_prepare_enable(imx_data->clk_ahb);
+ 
+ 	return sdhci_runtime_resume_host(host);
+diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
+index a7d9f95a7b03..3497cfaf683c 100644
+--- a/drivers/mmc/host/sdhci-esdhc.h
++++ b/drivers/mmc/host/sdhci-esdhc.h
+@@ -20,10 +20,8 @@
+ 
+ #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
+ 				SDHCI_QUIRK_NO_BUSY_IRQ | \
+-				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
+ 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
+-				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
+-				SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
++				SDHCI_QUIRK_PIO_NEEDS_DELAY)
+ 
+ #define ESDHC_SYSTEM_CONTROL	0x2c
+ #define ESDHC_CLOCK_MASK	0x0000fff0
+diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
+index f7c7cf62437d..5bd1092310f2 100644
+--- a/drivers/mmc/host/sdhci-of-arasan.c
++++ b/drivers/mmc/host/sdhci-of-arasan.c
+@@ -52,8 +52,12 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
+ }
+ 
+ static struct sdhci_ops sdhci_arasan_ops = {
++	.set_clock = sdhci_set_clock,
+ 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ 	.get_timeout_clock = sdhci_arasan_get_timeout_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static struct sdhci_pltfm_data sdhci_arasan_pdata = {
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 0b249970b119..605815e52f5f 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -199,13 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
+ 
+ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+ {
+-
+ 	int pre_div = 2;
+ 	int div = 1;
+ 	u32 temp;
+ 
++	host->mmc->actual_clock = 0;
++
+ 	if (clock == 0)
+-		goto out;
++		return;
+ 
+ 	/* Workaround to reduce the clock frequency for p1010 esdhc */
+ 	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
+@@ -238,24 +239,8 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+ 		| (pre_div << ESDHC_PREDIV_SHIFT));
+ 	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ 	mdelay(1);
+-out:
+-	host->clock = clock;
+-}
+-
+-#ifdef CONFIG_PM
+-static u32 esdhc_proctl;
+-static void esdhc_of_suspend(struct sdhci_host *host)
+-{
+-	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
+ }
+ 
+-static void esdhc_of_resume(struct sdhci_host *host)
+-{
+-	esdhc_of_enable_dma(host);
+-	sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+-}
+-#endif
+-
+ static void esdhc_of_platform_init(struct sdhci_host *host)
+ {
+ 	u32 vvn;
+@@ -269,7 +254,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
+ 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+ }
+ 
+-static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
++static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u32 ctrl;
+ 
+@@ -289,8 +274,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
+ 
+ 	clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
+ 			ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
+-
+-	return 0;
+ }
+ 
+ static const struct sdhci_ops sdhci_esdhc_ops = {
+@@ -305,13 +288,46 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
+ 	.get_max_clock = esdhc_of_get_max_clock,
+ 	.get_min_clock = esdhc_of_get_min_clock,
+ 	.platform_init = esdhc_of_platform_init,
+-#ifdef CONFIG_PM
+-	.platform_suspend = esdhc_of_suspend,
+-	.platform_resume = esdhc_of_resume,
+-#endif
+ 	.adma_workaround = esdhci_of_adma_workaround,
+-	.platform_bus_width = esdhc_pltfm_bus_width,
++	.set_bus_width = esdhc_pltfm_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
++};
++
++#ifdef CONFIG_PM
++
++static u32 esdhc_proctl;
++static int esdhc_of_suspend(struct device *dev)
++{
++	struct sdhci_host *host = dev_get_drvdata(dev);
++
++	esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL);
++
++	return sdhci_suspend_host(host);
++}
++
++static void esdhc_of_resume(device *dev)
++{
++	struct sdhci_host *host = dev_get_drvdata(dev);
++	int ret = sdhci_resume_host(host);
++
++	if (ret == 0) {
++		/* Isn't this already done by sdhci_resume_host() ? --rmk */
++		esdhc_of_enable_dma(host);
++		sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
++	}
++
++	return ret;
++}
++
++static const struct dev_pm_ops esdhc_pmops = {
++	.suspend	= esdhci_of_suspend,
++	.resume		= esdhci_of_resume,
+ };
++#define ESDHC_PMOPS (&esdhc_pmops)
++#else
++#define ESDHC_PMOPS NULL
++#endif
+ 
+ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
+ 	/*
+@@ -374,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = {
+ 		.name = "sdhci-esdhc",
+ 		.owner = THIS_MODULE,
+ 		.of_match_table = sdhci_esdhc_of_match,
+-		.pm = SDHCI_PLTFM_PMOPS,
++		.pm = ESDHC_PMOPS,
+ 	},
+ 	.probe = sdhci_esdhc_probe,
+ 	.remove = sdhci_esdhc_remove,
+diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
+index 57c514a81ca5..b341661369a2 100644
+--- a/drivers/mmc/host/sdhci-of-hlwd.c
++++ b/drivers/mmc/host/sdhci-of-hlwd.c
+@@ -58,6 +58,10 @@ static const struct sdhci_ops sdhci_hlwd_ops = {
+ 	.write_l = sdhci_hlwd_writel,
+ 	.write_w = sdhci_hlwd_writew,
+ 	.write_b = sdhci_hlwd_writeb,
++	.set_clock = sdhci_set_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index fdc612120362..52c42fcc284c 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -1031,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
+ 	return 0;
+ }
+ 
+-static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
++static void sdhci_pci_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u8 ctrl;
+ 
+@@ -1052,8 +1052,6 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width)
+ 	}
+ 
+ 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+-
+-	return 0;
+ }
+ 
+ static void sdhci_pci_gpio_hw_reset(struct sdhci_host *host)
+@@ -1080,8 +1078,11 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)
+ }
+ 
+ static const struct sdhci_ops sdhci_pci_ops = {
++	.set_clock	= sdhci_set_clock,
+ 	.enable_dma	= sdhci_pci_enable_dma,
+-	.platform_bus_width	= sdhci_pci_bus_width,
++	.set_bus_width	= sdhci_pci_set_bus_width,
++	.reset		= sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ 	.hw_reset		= sdhci_pci_hw_reset,
+ };
+ 
+diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
+index bef250e95418..7e834fb78f42 100644
+--- a/drivers/mmc/host/sdhci-pltfm.c
++++ b/drivers/mmc/host/sdhci-pltfm.c
+@@ -45,6 +45,10 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)
+ EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);
+ 
+ static const struct sdhci_ops sdhci_pltfm_ops = {
++	.set_clock = sdhci_set_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ #ifdef CONFIG_OF
+diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c
+index d51e061ec576..3c0f3c0a1cc8 100644
+--- a/drivers/mmc/host/sdhci-pxav2.c
++++ b/drivers/mmc/host/sdhci-pxav2.c
+@@ -51,11 +51,13 @@
+ #define MMC_CARD		0x1000
+ #define MMC_WIDTH		0x0100
+ 
+-static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
++static void pxav2_reset(struct sdhci_host *host, u8 mask)
+ {
+ 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ 
++	sdhci_reset(host, mask);
++
+ 	if (mask == SDHCI_RESET_ALL) {
+ 		u16 tmp = 0;
+ 
+@@ -88,7 +90,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask)
+ 	}
+ }
+ 
+-static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
++static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u8 ctrl;
+ 	u16 tmp;
+@@ -107,14 +109,14 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width)
+ 	}
+ 	writew(tmp, host->ioaddr + SD_CE_ATA_2);
+ 	writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
+-
+-	return 0;
+ }
+ 
+ static const struct sdhci_ops pxav2_sdhci_ops = {
++	.set_clock     = sdhci_set_clock,
+ 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+-	.platform_reset_exit = pxav2_set_private_registers,
+-	.platform_bus_width = pxav2_mmc_set_width,
++	.set_bus_width = pxav2_mmc_set_bus_width,
++	.reset         = pxav2_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ #ifdef CONFIG_OF
+diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
+index 2fd73b38c303..f4f128947561 100644
+--- a/drivers/mmc/host/sdhci-pxav3.c
++++ b/drivers/mmc/host/sdhci-pxav3.c
+@@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,
+ 	return 0;
+ }
+ 
+-static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
++static void pxav3_reset(struct sdhci_host *host, u8 mask)
+ {
+ 	struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
+ 	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ 
++	sdhci_reset(host, mask);
++
+ 	if (mask == SDHCI_RESET_ALL) {
+ 		/*
+ 		 * tune timing of read data/command when crc error happen
+@@ -184,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
+ 	pxa->power_mode = power_mode;
+ }
+ 
+-static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
++static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+ {
+ 	u16 ctrl_2;
+ 
+@@ -218,15 +220,16 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+ 	dev_dbg(mmc_dev(host->mmc),
+ 		"%s uhs = %d, ctrl_2 = %04X\n",
+ 		__func__, uhs, ctrl_2);
+-
+-	return 0;
+ }
+ 
+ static const struct sdhci_ops pxav3_sdhci_ops = {
+-	.platform_reset_exit = pxav3_set_private_registers,
++	.set_clock = sdhci_set_clock,
+ 	.set_uhs_signaling = pxav3_set_uhs_signaling,
+ 	.platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+ 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = pxav3_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
+diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
+index d61eb5a70833..76d7c12d8ef9 100644
+--- a/drivers/mmc/host/sdhci-s3c.c
++++ b/drivers/mmc/host/sdhci-s3c.c
+@@ -58,6 +58,8 @@ struct sdhci_s3c {
+ 	struct clk		*clk_io;
+ 	struct clk		*clk_bus[MAX_BUS_CLK];
+ 	unsigned long		clk_rates[MAX_BUS_CLK];
++
++	bool			no_divider;
+ };
+ 
+ /**
+@@ -70,6 +72,7 @@ struct sdhci_s3c {
+  */
+ struct sdhci_s3c_drv_data {
+ 	unsigned int	sdhci_quirks;
++	bool		no_divider;
+ };
+ 
+ static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
+@@ -119,7 +122,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
+ 	 * If controller uses a non-standard clock division, find the best clock
+ 	 * speed possible with selected clock source and skip the division.
+ 	 */
+-	if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
++	if (ourhost->no_divider) {
+ 		rate = clk_round_rate(clksrc, wanted);
+ 		return wanted - rate;
+ 	}
+@@ -161,9 +164,13 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	int src;
+ 	u32 ctrl;
+ 
++	host->mmc->actual_clock = 0;
++
+ 	/* don't bother if the clock is going off. */
+-	if (clock == 0)
++	if (clock == 0) {
++		sdhci_set_clock(host, clock);
+ 		return;
++	}
+ 
+ 	for (src = 0; src < MAX_BUS_CLK; src++) {
+ 		delta = sdhci_s3c_consider_clock(ourhost, src, clock);
+@@ -215,6 +222,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	if (clock < 25 * 1000000)
+ 		ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 | S3C_SDHCI_CTRL3_FCSEL2);
+ 	writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL3);
++
++	sdhci_set_clock(host, clock);
+ }
+ 
+ /**
+@@ -295,10 +304,11 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	unsigned long timeout;
+ 	u16 clk = 0;
+ 
++	host->mmc->actual_clock = 0;
++
+ 	/* If the clock is going off, set to 0 at clock control register */
+ 	if (clock == 0) {
+ 		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+-		host->clock = clock;
+ 		return;
+ 	}
+ 
+@@ -306,8 +316,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
+ 
+ 	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
+ 
+-	host->clock = clock;
+-
+ 	clk = SDHCI_CLOCK_INT_EN;
+ 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ 
+@@ -329,14 +337,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
+ }
+ 
+ /**
+- * sdhci_s3c_platform_bus_width - support 8bit buswidth
++ * sdhci_s3c_set_bus_width - support 8bit buswidth
+  * @host: The SDHCI host being queried
+  * @width: MMC_BUS_WIDTH_ macro for the bus width being requested
+  *
+  * We have 8-bit width support but is not a v3 controller.
+  * So we add platform_bus_width() and support 8bit width.
+  */
+-static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
++static void sdhci_s3c_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u8 ctrl;
+ 
+@@ -358,15 +366,15 @@ static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width)
+ 	}
+ 
+ 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+-
+-	return 0;
+ }
+ 
+ static struct sdhci_ops sdhci_s3c_ops = {
+ 	.get_max_clock		= sdhci_s3c_get_max_clk,
+ 	.set_clock		= sdhci_s3c_set_clock,
+ 	.get_min_clock		= sdhci_s3c_get_min_clock,
+-	.platform_bus_width	= sdhci_s3c_platform_bus_width,
++	.set_bus_width		= sdhci_s3c_set_bus_width,
++	.reset			= sdhci_reset,
++	.set_uhs_signaling	= sdhci_set_uhs_signaling,
+ };
+ 
+ static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
+@@ -606,8 +614,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
+ 	/* Setup quirks for the controller */
+ 	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
+ 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+-	if (drv_data)
++	if (drv_data) {
+ 		host->quirks |= drv_data->sdhci_quirks;
++		sc->no_divider = drv_data->no_divider;
++	}
+ 
+ #ifndef CONFIG_MMC_SDHCI_S3C_DMA
+ 
+@@ -656,7 +666,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)
+ 	 * If controller does not have internal clock divider,
+ 	 * we can use overriding functions instead of default.
+ 	 */
+-	if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
++	if (sc->no_divider) {
+ 		sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
+ 		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
+ 		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
+@@ -797,7 +807,7 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
+ 
+ #if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
+ static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
+-	.sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
++	.no_divider = true,
+ };
+ #define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
+ #else
+diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c
+index 696122c1b468..17004531d089 100644
+--- a/drivers/mmc/host/sdhci-sirf.c
++++ b/drivers/mmc/host/sdhci-sirf.c
+@@ -28,7 +28,11 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)
+ }
+ 
+ static struct sdhci_ops sdhci_sirf_ops = {
++	.set_clock = sdhci_set_clock,
+ 	.get_max_clock	= sdhci_sirf_get_max_clk,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static struct sdhci_pltfm_data sdhci_sirf_pdata = {
+diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c
+index 0316dec3f006..9d535c7336ef 100644
+--- a/drivers/mmc/host/sdhci-spear.c
++++ b/drivers/mmc/host/sdhci-spear.c
+@@ -38,7 +38,10 @@ struct spear_sdhci {
+ 
+ /* sdhci ops */
+ static const struct sdhci_ops sdhci_pltfm_ops = {
+-	/* Nothing to do for now. */
++	.set_clock = sdhci_set_clock,
++	.set_bus_width = sdhci_set_bus_width,
++	.reset = sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ #ifdef CONFIG_OF
+diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
+index a835898a68dd..985247649f46 100644
+--- a/drivers/mmc/host/sdhci-tegra.c
++++ b/drivers/mmc/host/sdhci-tegra.c
+@@ -48,19 +48,6 @@ struct sdhci_tegra {
+ 	int power_gpio;
+ };
+ 
+-static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg)
+-{
+-	u32 val;
+-
+-	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+-		/* Use wp_gpio here instead? */
+-		val = readl(host->ioaddr + reg);
+-		return val | SDHCI_WRITE_PROTECT;
+-	}
+-
+-	return readl(host->ioaddr + reg);
+-}
+-
+ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
+ {
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+@@ -108,12 +95,14 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)
+ 	return mmc_gpio_get_ro(host->mmc);
+ }
+ 
+-static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
++static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
+ {
+ 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ 	struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ 	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
+ 
++	sdhci_reset(host, mask);
++
+ 	if (!(mask & SDHCI_RESET_ALL))
+ 		return;
+ 
+@@ -127,7 +116,7 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask)
+ 	}
+ }
+ 
+-static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
++static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
+ {
+ 	u32 ctrl;
+ 
+@@ -144,16 +133,16 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width)
+ 			ctrl &= ~SDHCI_CTRL_4BITBUS;
+ 	}
+ 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+-	return 0;
+ }
+ 
+ static const struct sdhci_ops tegra_sdhci_ops = {
+ 	.get_ro     = tegra_sdhci_get_ro,
+-	.read_l     = tegra_sdhci_readl,
+ 	.read_w     = tegra_sdhci_readw,
+ 	.write_l    = tegra_sdhci_writel,
+-	.platform_bus_width = tegra_sdhci_buswidth,
+-	.platform_reset_exit = tegra_sdhci_reset_exit,
++	.set_clock  = sdhci_set_clock,
++	.set_bus_width = tegra_sdhci_set_bus_width,
++	.reset      = tegra_sdhci_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
+ };
+ 
+ static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 9a79fc4b60ca..48f4aef034fd 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -44,6 +44,8 @@
+ 
+ #define MAX_TUNING_LOOP 40
+ 
++#define ADMA_SIZE	((128 * 2 + 1) * 4)
++
+ static unsigned int debug_quirks = 0;
+ static unsigned int debug_quirks2;
+ 
+@@ -131,43 +133,26 @@ static void sdhci_dumpregs(struct sdhci_host *host)
+  *                                                                           *
+ \*****************************************************************************/
+ 
+-static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
+-{
+-	u32 ier;
+-
+-	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+-	ier &= ~clear;
+-	ier |= set;
+-	sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+-	sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+-}
+-
+-static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs)
+-{
+-	sdhci_clear_set_irqs(host, 0, irqs);
+-}
+-
+-static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs)
+-{
+-	sdhci_clear_set_irqs(host, irqs, 0);
+-}
+-
+ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
+ {
+-	u32 present, irqs;
++	u32 present;
+ 
+ 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
+ 	    (host->mmc->caps & MMC_CAP_NONREMOVABLE))
+ 		return;
+ 
+-	present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+-			      SDHCI_CARD_PRESENT;
+-	irqs = present ? SDHCI_INT_CARD_REMOVE : SDHCI_INT_CARD_INSERT;
++	if (enable) {
++		present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
++				      SDHCI_CARD_PRESENT;
+ 
+-	if (enable)
+-		sdhci_unmask_irqs(host, irqs);
+-	else
+-		sdhci_mask_irqs(host, irqs);
++		host->ier |= present ? SDHCI_INT_CARD_REMOVE :
++				       SDHCI_INT_CARD_INSERT;
++	} else {
++		host->ier &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
++	}
++
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ }
+ 
+ static void sdhci_enable_card_detection(struct sdhci_host *host)
+@@ -180,22 +165,9 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
+ 	sdhci_set_card_detection(host, false);
+ }
+ 
+-static void sdhci_reset(struct sdhci_host *host, u8 mask)
++void sdhci_reset(struct sdhci_host *host, u8 mask)
+ {
+ 	unsigned long timeout;
+-	u32 uninitialized_var(ier);
+-
+-	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
+-		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
+-			SDHCI_CARD_PRESENT))
+-			return;
+-	}
+-
+-	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+-		ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+-
+-	if (host->ops->platform_reset_enter)
+-		host->ops->platform_reset_enter(host, mask);
+ 
+ 	sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET);
+ 
+@@ -220,16 +192,27 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
+ 		timeout--;
+ 		mdelay(1);
+ 	}
++}
++EXPORT_SYMBOL_GPL(sdhci_reset);
++
++static void sdhci_do_reset(struct sdhci_host *host, u8 mask)
++{
++	if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
++		if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) &
++			SDHCI_CARD_PRESENT))
++			return;
++	}
+ 
+-	if (host->ops->platform_reset_exit)
+-		host->ops->platform_reset_exit(host, mask);
++	host->ops->reset(host, mask);
+ 
+-	if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+-		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
++	if (mask & SDHCI_RESET_ALL) {
++		if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
++			if (host->ops->enable_dma)
++				host->ops->enable_dma(host);
++		}
+ 
+-	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) {
+-		if ((host->ops->enable_dma) && (mask & SDHCI_RESET_ALL))
+-			host->ops->enable_dma(host);
++		/* Resetting the controller clears many */
++		host->preset_enabled = false;
+ 	}
+ }
+ 
+@@ -238,15 +221,18 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
+ static void sdhci_init(struct sdhci_host *host, int soft)
+ {
+ 	if (soft)
+-		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
++		sdhci_do_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
+ 	else
+-		sdhci_reset(host, SDHCI_RESET_ALL);
++		sdhci_do_reset(host, SDHCI_RESET_ALL);
++
++	host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
++		    SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
++		    SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
++		    SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
++		    SDHCI_INT_RESPONSE;
+ 
+-	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
+-		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+-		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
+-		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
+-		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ 
+ 	if (soft) {
+ 		/* force clock reconfiguration */
+@@ -502,11 +488,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
+ 	else
+ 		direction = DMA_TO_DEVICE;
+ 
+-	/*
+-	 * The ADMA descriptor table is mapped further down as we
+-	 * need to fill it with data first.
+-	 */
+-
+ 	host->align_addr = dma_map_single(mmc_dev(host->mmc),
+ 		host->align_buffer, 128 * 4, direction);
+ 	if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
+@@ -567,7 +548,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
+ 		 * If this triggers then we have a calculation bug
+ 		 * somewhere. :/
+ 		 */
+-		WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
++		WARN_ON((desc - host->adma_desc) > ADMA_SIZE);
+ 	}
+ 
+ 	if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) {
+@@ -595,17 +576,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
+ 			host->align_addr, 128 * 4, direction);
+ 	}
+ 
+-	host->adma_addr = dma_map_single(mmc_dev(host->mmc),
+-		host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE);
+-	if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr))
+-		goto unmap_entries;
+-	BUG_ON(host->adma_addr & 0x3);
+-
+ 	return 0;
+ 
+-unmap_entries:
+-	dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+-		data->sg_len, direction);
+ unmap_align:
+ 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
+ 		128 * 4, direction);
+@@ -623,19 +595,25 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
+ 	u8 *align;
+ 	char *buffer;
+ 	unsigned long flags;
++	bool has_unaligned;
+ 
+ 	if (data->flags & MMC_DATA_READ)
+ 		direction = DMA_FROM_DEVICE;
+ 	else
+ 		direction = DMA_TO_DEVICE;
+ 
+-	dma_unmap_single(mmc_dev(host->mmc), host->adma_addr,
+-		(128 * 2 + 1) * 4, DMA_TO_DEVICE);
+-
+ 	dma_unmap_single(mmc_dev(host->mmc), host->align_addr,
+ 		128 * 4, direction);
+ 
+-	if (data->flags & MMC_DATA_READ) {
++	/* Do a quick scan of the SG list for any unaligned mappings */
++	has_unaligned = false;
++	for_each_sg(data->sg, sg, host->sg_count, i)
++		if (sg_dma_address(sg) & 3) {
++			has_unaligned = true;
++			break;
++		}
++
++	if (has_unaligned && data->flags & MMC_DATA_READ) {
+ 		dma_sync_sg_for_cpu(mmc_dev(host->mmc), data->sg,
+ 			data->sg_len, direction);
+ 
+@@ -721,9 +699,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
+ 	u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR;
+ 
+ 	if (host->flags & SDHCI_REQ_USE_DMA)
+-		sdhci_clear_set_irqs(host, pio_irqs, dma_irqs);
++		host->ier = (host->ier & ~pio_irqs) | dma_irqs;
+ 	else
+-		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
++		host->ier = (host->ier & ~dma_irqs) | pio_irqs;
++
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ }
+ 
+ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+@@ -976,8 +957,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
+ 		 * upon error conditions.
+ 		 */
+ 		if (data->error) {
+-			sdhci_reset(host, SDHCI_RESET_CMD);
+-			sdhci_reset(host, SDHCI_RESET_DATA);
++			sdhci_do_reset(host, SDHCI_RESET_CMD);
++			sdhci_do_reset(host, SDHCI_RESET_DATA);
+ 		}
+ 
+ 		sdhci_send_command(host, data->stop);
+@@ -1107,24 +1088,23 @@ static void sdhci_finish_command(struct sdhci_host *host)
+ 
+ static u16 sdhci_get_preset_value(struct sdhci_host *host)
+ {
+-	u16 ctrl, preset = 0;
++	u16 preset = 0;
+ 
+-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+-
+-	switch (ctrl & SDHCI_CTRL_UHS_MASK) {
+-	case SDHCI_CTRL_UHS_SDR12:
++	switch (host->timing) {
++	case MMC_TIMING_UHS_SDR12:
+ 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
+ 		break;
+-	case SDHCI_CTRL_UHS_SDR25:
++	case MMC_TIMING_UHS_SDR25:
+ 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR25);
+ 		break;
+-	case SDHCI_CTRL_UHS_SDR50:
++	case MMC_TIMING_UHS_SDR50:
+ 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR50);
+ 		break;
+-	case SDHCI_CTRL_UHS_SDR104:
++	case MMC_TIMING_UHS_SDR104:
++	case MMC_TIMING_MMC_HS200:
+ 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104);
+ 		break;
+-	case SDHCI_CTRL_UHS_DDR50:
++	case MMC_TIMING_UHS_DDR50:
+ 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_DDR50);
+ 		break;
+ 	default:
+@@ -1136,32 +1116,22 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)
+ 	return preset;
+ }
+ 
+-static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
++void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+ {
+ 	int div = 0; /* Initialized for compiler warning */
+ 	int real_div = div, clk_mul = 1;
+ 	u16 clk = 0;
+ 	unsigned long timeout;
+ 
+-	if (clock && clock == host->clock)
+-		return;
+-
+ 	host->mmc->actual_clock = 0;
+ 
+-	if (host->ops->set_clock) {
+-		host->ops->set_clock(host, clock);
+-		if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK)
+-			return;
+-	}
+-
+ 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+ 
+ 	if (clock == 0)
+-		goto out;
++		return;
+ 
+ 	if (host->version >= SDHCI_SPEC_300) {
+-		if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
+-			SDHCI_CTRL_PRESET_VAL_ENABLE) {
++		if (host->preset_enabled) {
+ 			u16 pre_val;
+ 
+ 			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+@@ -1247,26 +1217,16 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+ 
+ 	clk |= SDHCI_CLOCK_CARD_EN;
+ 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+-
+-out:
+-	host->clock = clock;
+-}
+-
+-static inline void sdhci_update_clock(struct sdhci_host *host)
+-{
+-	unsigned int clock;
+-
+-	clock = host->clock;
+-	host->clock = 0;
+-	sdhci_set_clock(host, clock);
+ }
++EXPORT_SYMBOL_GPL(sdhci_set_clock);
+ 
+-static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
++static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
++			    unsigned short vdd)
+ {
+ 	u8 pwr = 0;
+ 
+-	if (power != (unsigned short)-1) {
+-		switch (1 << power) {
++	if (mode != MMC_POWER_OFF) {
++		switch (1 << vdd) {
+ 		case MMC_VDD_165_195:
+ 			pwr = SDHCI_POWER_180;
+ 			break;
+@@ -1284,7 +1244,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
+ 	}
+ 
+ 	if (host->pwr == pwr)
+-		return -1;
++		return;
+ 
+ 	host->pwr = pwr;
+ 
+@@ -1292,38 +1252,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)
+ 		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+ 		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+ 			sdhci_runtime_pm_bus_off(host);
+-		return 0;
+-	}
+-
+-	/*
+-	 * Spec says that we should clear the power reg before setting
+-	 * a new value. Some controllers don't seem to like this though.
+-	 */
+-	if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+-		sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
++		vdd = 0;
++	} else {
++		/*
++		 * Spec says that we should clear the power reg before setting
++		 * a new value. Some controllers don't seem to like this though.
++		 */
++		if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
++			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+ 
+-	/*
+-	 * At least the Marvell CaFe chip gets confused if we set the voltage
+-	 * and set turn on power at the same time, so set the voltage first.
+-	 */
+-	if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+-		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
++		/*
++		 * At least the Marvell CaFe chip gets confused if we set the
++		 * voltage and set turn on power at the same time, so set the
++		 * voltage first.
++		 */
++		if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
++			sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ 
+-	pwr |= SDHCI_POWER_ON;
++		pwr |= SDHCI_POWER_ON;
+ 
+-	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
++		sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+ 
+-	if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
+-		sdhci_runtime_pm_bus_on(host);
++		if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
++			sdhci_runtime_pm_bus_on(host);
+ 
+-	/*
+-	 * Some controllers need an extra 10ms delay of 10ms before they
+-	 * can apply clock after applying power
+-	 */
+-	if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
+-		mdelay(10);
++		/*
++		 * Some controllers need an extra 10ms delay of 10ms before
++		 * they can apply clock after applying power
++		 */
++		if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
++			mdelay(10);
++	}
+ 
+-	return power;
++	if (host->vmmc) {
++		spin_unlock_irq(&host->lock);
++		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd);
++		spin_lock_irq(&host->lock);
++	}
+ }
+ 
+ /*****************************************************************************\
+@@ -1427,10 +1392,52 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ 	spin_unlock_irqrestore(&host->lock, flags);
+ }
+ 
++void sdhci_set_bus_width(struct sdhci_host *host, int width)
++{
++	u8 ctrl;
++
++	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
++	if (width == MMC_BUS_WIDTH_8) {
++		ctrl &= ~SDHCI_CTRL_4BITBUS;
++		if (host->version >= SDHCI_SPEC_300)
++			ctrl |= SDHCI_CTRL_8BITBUS;
++	} else {
++		if (host->version >= SDHCI_SPEC_300)
++			ctrl &= ~SDHCI_CTRL_8BITBUS;
++		if (width == MMC_BUS_WIDTH_4)
++			ctrl |= SDHCI_CTRL_4BITBUS;
++		else
++			ctrl &= ~SDHCI_CTRL_4BITBUS;
++	}
++	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
++}
++EXPORT_SYMBOL_GPL(sdhci_set_bus_width);
++
++void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
++{
++	u16 ctrl_2;
++
++	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
++	/* Select Bus Speed Mode for host */
++	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
++	if ((timing == MMC_TIMING_MMC_HS200) ||
++	    (timing == MMC_TIMING_UHS_SDR104))
++		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
++	else if (timing == MMC_TIMING_UHS_SDR12)
++		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
++	else if (timing == MMC_TIMING_UHS_SDR25)
++		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
++	else if (timing == MMC_TIMING_UHS_SDR50)
++		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
++	else if (timing == MMC_TIMING_UHS_DDR50)
++		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
++	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
++}
++EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
++
+ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ {
+ 	unsigned long flags;
+-	int vdd_bit = -1;
+ 	u8 ctrl;
+ 
+ 	spin_lock_irqsave(&host->lock, flags);
+@@ -1456,45 +1463,17 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ 		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))
+ 		sdhci_enable_preset_value(host, false);
+ 
+-	sdhci_set_clock(host, ios->clock);
+-
+-	if (ios->power_mode == MMC_POWER_OFF)
+-		vdd_bit = sdhci_set_power(host, -1);
+-	else
+-		vdd_bit = sdhci_set_power(host, ios->vdd);
+-
+-	if (host->vmmc && vdd_bit != -1) {
+-		spin_unlock_irqrestore(&host->lock, flags);
+-		mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
+-		spin_lock_irqsave(&host->lock, flags);
++	if (!ios->clock || ios->clock != host->clock) {
++		host->ops->set_clock(host, ios->clock);
++		host->clock = ios->clock;
+ 	}
+ 
++	sdhci_set_power(host, ios->power_mode, ios->vdd);
++
+ 	if (host->ops->platform_send_init_74_clocks)
+ 		host->ops->platform_send_init_74_clocks(host, ios->power_mode);
+ 
+-	/*
+-	 * If your platform has 8-bit width support but is not a v3 controller,
+-	 * or if it requires special setup code, you should implement that in
+-	 * platform_bus_width().
+-	 */
+-	if (host->ops->platform_bus_width) {
+-		host->ops->platform_bus_width(host, ios->bus_width);
+-	} else {
+-		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+-		if (ios->bus_width == MMC_BUS_WIDTH_8) {
+-			ctrl &= ~SDHCI_CTRL_4BITBUS;
+-			if (host->version >= SDHCI_SPEC_300)
+-				ctrl |= SDHCI_CTRL_8BITBUS;
+-		} else {
+-			if (host->version >= SDHCI_SPEC_300)
+-				ctrl &= ~SDHCI_CTRL_8BITBUS;
+-			if (ios->bus_width == MMC_BUS_WIDTH_4)
+-				ctrl |= SDHCI_CTRL_4BITBUS;
+-			else
+-				ctrl &= ~SDHCI_CTRL_4BITBUS;
+-		}
+-		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+-	}
++	host->ops->set_bus_width(host, ios->bus_width);
+ 
+ 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ 
+@@ -1516,13 +1495,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ 		    (ios->timing == MMC_TIMING_UHS_SDR25))
+ 			ctrl |= SDHCI_CTRL_HISPD;
+ 
+-		ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+-		if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
++		if (!host->preset_enabled) {
+ 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ 			/*
+ 			 * We only need to set Driver Strength if the
+ 			 * preset value enable is not set.
+ 			 */
++			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ 			ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK;
+ 			if (ios->drv_type == MMC_SET_DRIVER_TYPE_A)
+ 				ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A;
+@@ -1546,34 +1525,16 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ 
+ 			/* Re-enable SD Clock */
+-			sdhci_update_clock(host);
++			host->ops->set_clock(host, host->clock);
+ 		}
+ 
+-
+ 		/* Reset SD Clock Enable */
+ 		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ 		clk &= ~SDHCI_CLOCK_CARD_EN;
+ 		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ 
+-		if (host->ops->set_uhs_signaling)
+-			host->ops->set_uhs_signaling(host, ios->timing);
+-		else {
+-			ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+-			/* Select Bus Speed Mode for host */
+-			ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+-			if ((ios->timing == MMC_TIMING_MMC_HS200) ||
+-			    (ios->timing == MMC_TIMING_UHS_SDR104))
+-				ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+-			else if (ios->timing == MMC_TIMING_UHS_SDR12)
+-				ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+-			else if (ios->timing == MMC_TIMING_UHS_SDR25)
+-				ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+-			else if (ios->timing == MMC_TIMING_UHS_SDR50)
+-				ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+-			else if (ios->timing == MMC_TIMING_UHS_DDR50)
+-				ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+-			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+-		}
++		host->ops->set_uhs_signaling(host, ios->timing);
++		host->timing = ios->timing;
+ 
+ 		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
+ 				((ios->timing == MMC_TIMING_UHS_SDR12) ||
+@@ -1590,7 +1551,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ 		}
+ 
+ 		/* Re-enable SD Clock */
+-		sdhci_update_clock(host);
++		host->ops->set_clock(host, host->clock);
+ 	} else
+ 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+ 
+@@ -1600,7 +1561,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
+ 	 * it on each ios seems to solve the problem.
+ 	 */
+ 	if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
+-		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
++		sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ 
+ 	mmiowb();
+ 	spin_unlock_irqrestore(&host->lock, flags);
+@@ -1709,24 +1670,16 @@ static int sdhci_get_ro(struct mmc_host *mmc)
+ 
+ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
+ {
+-	if (host->flags & SDHCI_DEVICE_DEAD)
+-		goto out;
+-
+-	if (enable)
+-		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
+-	else
+-		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
+-
+-	/* SDIO IRQ will be enabled as appropriate in runtime resume */
+-	if (host->runtime_suspended)
+-		goto out;
++	if (!(host->flags & SDHCI_DEVICE_DEAD)) {
++		if (enable)
++			host->ier |= SDHCI_INT_CARD_INT;
++		else
++			host->ier &= ~SDHCI_INT_CARD_INT;
+ 
+-	if (enable)
+-		sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT);
+-	else
+-		sdhci_mask_irqs(host, SDHCI_INT_CARD_INT);
+-out:
+-	mmiowb();
++		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
++		mmiowb();
++	}
+ }
+ 
+ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+@@ -1734,9 +1687,18 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+ 	struct sdhci_host *host = mmc_priv(mmc);
+ 	unsigned long flags;
+ 
++	sdhci_runtime_pm_get(host);
++
+ 	spin_lock_irqsave(&host->lock, flags);
++	if (enable)
++		host->flags |= SDHCI_SDIO_IRQ_ENABLED;
++	else
++		host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
++
+ 	sdhci_enable_sdio_irq_nolock(host, enable);
+ 	spin_unlock_irqrestore(&host->lock, flags);
++
++	sdhci_runtime_pm_put(host);
+ }
+ 
+ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+@@ -1798,9 +1760,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
+ 		ctrl |= SDHCI_CTRL_VDD_180;
+ 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ 
+-		/* Wait for 5ms */
+-		usleep_range(5000, 5500);
+-
+ 		/* 1.8V regulator output should be stable within 5 ms */
+ 		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ 		if (ctrl & SDHCI_CTRL_VDD_180)
+@@ -1855,22 +1814,16 @@ static int sdhci_card_busy(struct mmc_host *mmc)
+ 
+ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ {
+-	struct sdhci_host *host;
++	struct sdhci_host *host = mmc_priv(mmc);
+ 	u16 ctrl;
+-	u32 ier;
+ 	int tuning_loop_counter = MAX_TUNING_LOOP;
+ 	unsigned long timeout;
+ 	int err = 0;
+-	bool requires_tuning_nonuhs = false;
+ 	unsigned long flags;
+ 
+-	host = mmc_priv(mmc);
+-
+ 	sdhci_runtime_pm_get(host);
+ 	spin_lock_irqsave(&host->lock, flags);
+ 
+-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+-
+ 	/*
+ 	 * The Host Controller needs tuning only in case of SDR104 mode
+ 	 * and for SDR50 mode when Use Tuning for SDR50 is set in the
+@@ -1878,15 +1831,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ 	 * If the Host Controller supports the HS200 mode then the
+ 	 * tuning function has to be executed.
+ 	 */
+-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
+-	    (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
+-	     host->flags & SDHCI_SDR104_NEEDS_TUNING))
+-		requires_tuning_nonuhs = true;
+-
+-	if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
+-	    requires_tuning_nonuhs)
+-		ctrl |= SDHCI_CTRL_EXEC_TUNING;
+-	else {
++	switch (host->timing) {
++	case MMC_TIMING_MMC_HS200:
++	case MMC_TIMING_UHS_SDR104:
++		break;
++
++	case MMC_TIMING_UHS_SDR50:
++		if (host->flags & SDHCI_SDR50_NEEDS_TUNING ||
++		    host->flags & SDHCI_SDR104_NEEDS_TUNING)
++			break;
++		/* FALLTHROUGH */
++
++	default:
+ 		spin_unlock_irqrestore(&host->lock, flags);
+ 		sdhci_runtime_pm_put(host);
+ 		return 0;
+@@ -1899,6 +1855,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ 		return err;
+ 	}
+ 
++	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
++	ctrl |= SDHCI_CTRL_EXEC_TUNING;
+ 	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+ 
+ 	/*
+@@ -1911,8 +1869,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ 	 * to make sure we don't hit a controller bug, we _only_
+ 	 * enable Buffer Read Ready interrupt here.
+ 	 */
+-	ier = sdhci_readl(host, SDHCI_INT_ENABLE);
+-	sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL);
++	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
++	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+ 
+ 	/*
+ 	 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
+@@ -2044,7 +2002,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ 	if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
+ 		err = 0;
+ 
+-	sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ 	spin_unlock_irqrestore(&host->lock, flags);
+ 	sdhci_runtime_pm_put(host);
+ 
+@@ -2054,26 +2013,30 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+ 
+ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
+ {
+-	u16 ctrl;
+-
+ 	/* Host Controller v3.00 defines preset value registers */
+ 	if (host->version < SDHCI_SPEC_300)
+ 		return;
+ 
+-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+-
+ 	/*
+ 	 * We only enable or disable Preset Value if they are not already
+ 	 * enabled or disabled respectively. Otherwise, we bail out.
+ 	 */
+-	if (enable && !(ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+-		ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
+-		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+-		host->flags |= SDHCI_PV_ENABLED;
+-	} else if (!enable && (ctrl & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+-		ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
++	if (host->preset_enabled != enable) {
++		u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
++
++		if (enable)
++			ctrl |= SDHCI_CTRL_PRESET_VAL_ENABLE;
++		else
++			ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
++
+ 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+-		host->flags &= ~SDHCI_PV_ENABLED;
++
++		if (enable)
++			host->flags |= SDHCI_PV_ENABLED;
++		else
++			host->flags &= ~SDHCI_PV_ENABLED;
++
++		host->preset_enabled = enable;
+ 	}
+ }
+ 
+@@ -2095,8 +2058,8 @@ static void sdhci_card_event(struct mmc_host *mmc)
+ 		pr_err("%s: Resetting controller.\n",
+ 			mmc_hostname(host->mmc));
+ 
+-		sdhci_reset(host, SDHCI_RESET_CMD);
+-		sdhci_reset(host, SDHCI_RESET_DATA);
++		sdhci_do_reset(host, SDHCI_RESET_CMD);
++		sdhci_do_reset(host, SDHCI_RESET_DATA);
+ 
+ 		host->mrq->cmd->error = -ENOMEDIUM;
+ 		tasklet_schedule(&host->finish_tasklet);
+@@ -2124,15 +2087,6 @@ static const struct mmc_host_ops sdhci_ops = {
+  *                                                                           *
+ \*****************************************************************************/
+ 
+-static void sdhci_tasklet_card(unsigned long param)
+-{
+-	struct sdhci_host *host = (struct sdhci_host*)param;
+-
+-	sdhci_card_event(host->mmc);
+-
+-	mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+-}
+-
+ static void sdhci_tasklet_finish(unsigned long param)
+ {
+ 	struct sdhci_host *host;
+@@ -2169,12 +2123,12 @@ static void sdhci_tasklet_finish(unsigned long param)
+ 		/* Some controllers need this kick or reset won't work here */
+ 		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
+ 			/* This is to force an update */
+-			sdhci_update_clock(host);
++			host->ops->set_clock(host, host->clock);
+ 
+ 		/* Spec says we should do both at the same time, but Ricoh
+ 		   controllers do not like that. */
+-		sdhci_reset(host, SDHCI_RESET_CMD);
+-		sdhci_reset(host, SDHCI_RESET_DATA);
++		sdhci_do_reset(host, SDHCI_RESET_CMD);
++		sdhci_do_reset(host, SDHCI_RESET_DATA);
+ 	}
+ 
+ 	host->mrq = NULL;
+@@ -2424,101 +2378,94 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
+ 
+ static irqreturn_t sdhci_irq(int irq, void *dev_id)
+ {
+-	irqreturn_t result;
++	irqreturn_t result = IRQ_NONE;
+ 	struct sdhci_host *host = dev_id;
+-	u32 intmask, unexpected = 0;
+-	int cardint = 0, max_loops = 16;
++	u32 intmask, mask, unexpected = 0;
++	int max_loops = 16;
+ 
+ 	spin_lock(&host->lock);
+ 
+-	if (host->runtime_suspended) {
++	if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) {
+ 		spin_unlock(&host->lock);
+ 		return IRQ_NONE;
+ 	}
+ 
+ 	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
+-
+ 	if (!intmask || intmask == 0xffffffff) {
+ 		result = IRQ_NONE;
+ 		goto out;
+ 	}
+ 
+-again:
+-	DBG("*** %s got interrupt: 0x%08x\n",
+-		mmc_hostname(host->mmc), intmask);
+-
+-	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+-		u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
+-			      SDHCI_CARD_PRESENT;
+-
+-		/*
+-		 * There is a observation on i.mx esdhc.  INSERT bit will be
+-		 * immediately set again when it gets cleared, if a card is
+-		 * inserted.  We have to mask the irq to prevent interrupt
+-		 * storm which will freeze the system.  And the REMOVE gets
+-		 * the same situation.
+-		 *
+-		 * More testing are needed here to ensure it works for other
+-		 * platforms though.
+-		 */
+-		sdhci_mask_irqs(host, present ? SDHCI_INT_CARD_INSERT :
+-						SDHCI_INT_CARD_REMOVE);
+-		sdhci_unmask_irqs(host, present ? SDHCI_INT_CARD_REMOVE :
+-						  SDHCI_INT_CARD_INSERT);
++	do {
++		/* Clear selected interrupts. */
++		mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++				  SDHCI_INT_BUS_POWER);
++		sdhci_writel(host, mask, SDHCI_INT_STATUS);
+ 
+-		sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
+-			     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
+-		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
+-		tasklet_schedule(&host->card_tasklet);
+-	}
++		DBG("*** %s got interrupt: 0x%08x\n",
++			mmc_hostname(host->mmc), intmask);
+ 
+-	if (intmask & SDHCI_INT_CMD_MASK) {
+-		sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
+-			SDHCI_INT_STATUS);
+-		sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
+-	}
++		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
++			u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
++				      SDHCI_CARD_PRESENT;
+ 
+-	if (intmask & SDHCI_INT_DATA_MASK) {
+-		sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
+-			SDHCI_INT_STATUS);
+-		sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
+-	}
+-
+-	intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
++			/*
++			 * There is a observation on i.mx esdhc.  INSERT
++			 * bit will be immediately set again when it gets
++			 * cleared, if a card is inserted.  We have to mask
++			 * the irq to prevent interrupt storm which will
++			 * freeze the system.  And the REMOVE gets the
++			 * same situation.
++			 *
++			 * More testing are needed here to ensure it works
++			 * for other platforms though.
++			 */
++			host->ier &= ~(SDHCI_INT_CARD_INSERT |
++				       SDHCI_INT_CARD_REMOVE);
++			host->ier |= present ? SDHCI_INT_CARD_REMOVE :
++					       SDHCI_INT_CARD_INSERT;
++			sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++			sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
++
++			sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT |
++				     SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS);
++
++			host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT |
++						       SDHCI_INT_CARD_REMOVE);
++			result = IRQ_WAKE_THREAD;
++		}
+ 
+-	intmask &= ~SDHCI_INT_ERROR;
++		if (intmask & SDHCI_INT_CMD_MASK)
++			sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
+ 
+-	if (intmask & SDHCI_INT_BUS_POWER) {
+-		pr_err("%s: Card is consuming too much power!\n",
+-			mmc_hostname(host->mmc));
+-		sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS);
+-	}
++		if (intmask & SDHCI_INT_DATA_MASK)
++			sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
+ 
+-	intmask &= ~SDHCI_INT_BUS_POWER;
++		if (intmask & SDHCI_INT_BUS_POWER)
++			pr_err("%s: Card is consuming too much power!\n",
++				mmc_hostname(host->mmc));
+ 
+-	if (intmask & SDHCI_INT_CARD_INT)
+-		cardint = 1;
++		if (intmask & SDHCI_INT_CARD_INT) {
++			sdhci_enable_sdio_irq_nolock(host, false);
++			host->thread_isr |= SDHCI_INT_CARD_INT;
++			result = IRQ_WAKE_THREAD;
++		}
+ 
+-	intmask &= ~SDHCI_INT_CARD_INT;
++		intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
++			     SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
++			     SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
++			     SDHCI_INT_CARD_INT);
+ 
+-	if (intmask) {
+-		unexpected |= intmask;
+-		sdhci_writel(host, intmask, SDHCI_INT_STATUS);
+-	}
+-
+-	result = IRQ_HANDLED;
++		if (intmask) {
++			unexpected |= intmask;
++			sdhci_writel(host, intmask, SDHCI_INT_STATUS);
++		}
+ 
+-	intmask = sdhci_readl(host, SDHCI_INT_STATUS);
++		if (result == IRQ_NONE)
++			result = IRQ_HANDLED;
+ 
+-	/*
+-	 * If we know we'll call the driver to signal SDIO IRQ, disregard
+-	 * further indications of Card Interrupt in the status to avoid a
+-	 * needless loop.
+-	 */
+-	if (cardint)
+-		intmask &= ~SDHCI_INT_CARD_INT;
+-	if (intmask && --max_loops)
+-		goto again;
++		intmask = sdhci_readl(host, SDHCI_INT_STATUS);
++	} while (intmask && --max_loops);
+ out:
+ 	spin_unlock(&host->lock);
+ 
+@@ -2527,15 +2474,38 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
+ 			   mmc_hostname(host->mmc), unexpected);
+ 		sdhci_dumpregs(host);
+ 	}
+-	/*
+-	 * We have to delay this as it calls back into the driver.
+-	 */
+-	if (cardint)
+-		mmc_signal_sdio_irq(host->mmc);
+ 
+ 	return result;
+ }
+ 
++static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
++{
++	struct sdhci_host *host = dev_id;
++	unsigned long flags;
++	u32 isr;
++
++	spin_lock_irqsave(&host->lock, flags);
++	isr = host->thread_isr;
++	host->thread_isr = 0;
++	spin_unlock_irqrestore(&host->lock, flags);
++
++	if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
++		sdhci_card_event(host->mmc);
++		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
++	}
++
++	if (isr & SDHCI_INT_CARD_INT) {
++		sdio_run_irqs(host->mmc);
++
++		spin_lock_irqsave(&host->lock, flags);
++		if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
++			sdhci_enable_sdio_irq_nolock(host, true);
++		spin_unlock_irqrestore(&host->lock, flags);
++	}
++
++	return isr ? IRQ_HANDLED : IRQ_NONE;
++}
++
+ /*****************************************************************************\
+  *                                                                           *
+  * Suspend/resume                                                            *
+@@ -2572,9 +2542,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
+ 
+ int sdhci_suspend_host(struct sdhci_host *host)
+ {
+-	if (host->ops->platform_suspend)
+-		host->ops->platform_suspend(host);
+-
+ 	sdhci_disable_card_detection(host);
+ 
+ 	/* Disable tuning since we are suspending */
+@@ -2584,7 +2551,9 @@ int sdhci_suspend_host(struct sdhci_host *host)
+ 	}
+ 
+ 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
+-		sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
++		host->ier = 0;
++		sdhci_writel(host, 0, SDHCI_INT_ENABLE);
++		sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+ 		free_irq(host->irq, host);
+ 	} else {
+ 		sdhci_enable_irq_wakeups(host);
+@@ -2605,8 +2574,9 @@ int sdhci_resume_host(struct sdhci_host *host)
+ 	}
+ 
+ 	if (!device_may_wakeup(mmc_dev(host->mmc))) {
+-		ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+-				  mmc_hostname(host->mmc), host);
++		ret = request_threaded_irq(host->irq, sdhci_irq,
++					   sdhci_thread_irq, IRQF_SHARED,
++					   mmc_hostname(host->mmc), host);
+ 		if (ret)
+ 			return ret;
+ 	} else {
+@@ -2628,9 +2598,6 @@ int sdhci_resume_host(struct sdhci_host *host)
+ 
+ 	sdhci_enable_card_detection(host);
+ 
+-	if (host->ops->platform_resume)
+-		host->ops->platform_resume(host);
+-
+ 	/* Set the re-tuning expiration flag */
+ 	if (host->flags & SDHCI_USING_RETUNING_TIMER)
+ 		host->flags |= SDHCI_NEEDS_RETUNING;
+@@ -2682,10 +2649,12 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
+ 	}
+ 
+ 	spin_lock_irqsave(&host->lock, flags);
+-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
++	host->ier &= SDHCI_INT_CARD_INT;
++	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
++	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ 	spin_unlock_irqrestore(&host->lock, flags);
+ 
+-	synchronize_irq(host->irq);
++	synchronize_hardirq(host->irq);
+ 
+ 	spin_lock_irqsave(&host->lock, flags);
+ 	host->runtime_suspended = true;
+@@ -2729,7 +2698,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
+ 	host->runtime_suspended = false;
+ 
+ 	/* Enable SDIO IRQ */
+-	if ((host->flags & SDHCI_SDIO_IRQ_ENABLED))
++	if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
+ 		sdhci_enable_sdio_irq_nolock(host, true);
+ 
+ 	/* Enable Card Detection */
+@@ -2788,7 +2757,7 @@ int sdhci_add_host(struct sdhci_host *host)
+ 	if (debug_quirks2)
+ 		host->quirks2 = debug_quirks2;
+ 
+-	sdhci_reset(host, SDHCI_RESET_ALL);
++	sdhci_do_reset(host, SDHCI_RESET_ALL);
+ 
+ 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+ 	host->version = (host->version & SDHCI_SPEC_VER_MASK)
+@@ -2848,15 +2817,29 @@ int sdhci_add_host(struct sdhci_host *host)
+ 		 * (128) and potentially one alignment transfer for
+ 		 * each of those entries.
+ 		 */
+-		host->adma_desc = kmalloc((128 * 2 + 1) * 4, GFP_KERNEL);
++		host->adma_desc = dma_alloc_coherent(mmc_dev(host->mmc),
++						     ADMA_SIZE, &host->adma_addr,
++						     GFP_KERNEL);
+ 		host->align_buffer = kmalloc(128 * 4, GFP_KERNEL);
+ 		if (!host->adma_desc || !host->align_buffer) {
+-			kfree(host->adma_desc);
++			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
++					  host->adma_desc, host->adma_addr);
+ 			kfree(host->align_buffer);
+ 			pr_warning("%s: Unable to allocate ADMA "
+ 				"buffers. Falling back to standard DMA.\n",
+ 				mmc_hostname(mmc));
+ 			host->flags &= ~SDHCI_USE_ADMA;
++			host->adma_desc = NULL;
++			host->align_buffer = NULL;
++		} else if (host->adma_addr & 3) {
++			pr_warning("%s: unable to allocate aligned ADMA descriptor\n",
++				   mmc_hostname(mmc));
++			host->flags &= ~SDHCI_USE_ADMA;
++			dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
++					  host->adma_desc, host->adma_addr);
++			kfree(host->align_buffer);
++			host->adma_desc = NULL;
++			host->align_buffer = NULL;
+ 		}
+ 	}
+ 
+@@ -2941,6 +2924,7 @@ int sdhci_add_host(struct sdhci_host *host)
+ 	mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
+ 
+ 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
++	mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
+ 
+ 	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+ 		host->flags |= SDHCI_AUTO_CMD12;
+@@ -3212,8 +3196,6 @@ int sdhci_add_host(struct sdhci_host *host)
+ 	/*
+ 	 * Init tasklets.
+ 	 */
+-	tasklet_init(&host->card_tasklet,
+-		sdhci_tasklet_card, (unsigned long)host);
+ 	tasklet_init(&host->finish_tasklet,
+ 		sdhci_tasklet_finish, (unsigned long)host);
+ 
+@@ -3230,8 +3212,8 @@ int sdhci_add_host(struct sdhci_host *host)
+ 
+ 	sdhci_init(host, 0);
+ 
+-	ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
+-		mmc_hostname(mmc), host);
++	ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
++				   IRQF_SHARED,	mmc_hostname(mmc), host);
+ 	if (ret) {
+ 		pr_err("%s: Failed to request IRQ %d: %d\n",
+ 		       mmc_hostname(mmc), host->irq, ret);
+@@ -3273,12 +3255,12 @@ int sdhci_add_host(struct sdhci_host *host)
+ 
+ #ifdef SDHCI_USE_LEDS_CLASS
+ reset:
+-	sdhci_reset(host, SDHCI_RESET_ALL);
+-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
++	sdhci_do_reset(host, SDHCI_RESET_ALL);
++	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
++	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+ 	free_irq(host->irq, host);
+ #endif
+ untasklet:
+-	tasklet_kill(&host->card_tasklet);
+ 	tasklet_kill(&host->finish_tasklet);
+ 
+ 	return ret;
+@@ -3315,14 +3297,14 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
+ #endif
+ 
+ 	if (!dead)
+-		sdhci_reset(host, SDHCI_RESET_ALL);
++		sdhci_do_reset(host, SDHCI_RESET_ALL);
+ 
+-	sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
++	sdhci_writel(host, 0, SDHCI_INT_ENABLE);
++	sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
+ 	free_irq(host->irq, host);
+ 
+ 	del_timer_sync(&host->timer);
+ 
+-	tasklet_kill(&host->card_tasklet);
+ 	tasklet_kill(&host->finish_tasklet);
+ 
+ 	if (host->vmmc) {
+@@ -3335,7 +3317,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
+ 		regulator_put(host->vqmmc);
+ 	}
+ 
+-	kfree(host->adma_desc);
++	if (host->adma_desc)
++		dma_free_coherent(mmc_dev(host->mmc), ADMA_SIZE,
++				  host->adma_desc, host->adma_addr);
+ 	kfree(host->align_buffer);
+ 
+ 	host->adma_desc = NULL;
+diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
+index 0a3ed01887db..4a5cd5e3fa3e 100644
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -281,18 +281,14 @@ struct sdhci_ops {
+ 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
+ 	unsigned int	(*get_min_clock)(struct sdhci_host *host);
+ 	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
+-	int		(*platform_bus_width)(struct sdhci_host *host,
+-					       int width);
++	void		(*set_bus_width)(struct sdhci_host *host, int width);
+ 	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
+ 					     u8 power_mode);
+ 	unsigned int    (*get_ro)(struct sdhci_host *host);
+-	void	(*platform_reset_enter)(struct sdhci_host *host, u8 mask);
+-	void	(*platform_reset_exit)(struct sdhci_host *host, u8 mask);
++	void		(*reset)(struct sdhci_host *host, u8 mask);
+ 	int	(*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
+-	int	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
++	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
+ 	void	(*hw_reset)(struct sdhci_host *host);
+-	void	(*platform_suspend)(struct sdhci_host *host);
+-	void	(*platform_resume)(struct sdhci_host *host);
+ 	void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
+ 	void	(*platform_init)(struct sdhci_host *host);
+ 	void    (*card_event)(struct sdhci_host *host);
+@@ -397,6 +393,16 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
+ extern void sdhci_send_command(struct sdhci_host *host,
+ 				struct mmc_command *cmd);
+ 
++static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)
++{
++	return !!(host->flags & SDHCI_SDIO_IRQ_ENABLED);
++}
++
++void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
++void sdhci_set_bus_width(struct sdhci_host *host, int width);
++void sdhci_reset(struct sdhci_host *host, u8 mask);
++void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
++
+ #ifdef CONFIG_PM
+ extern int sdhci_suspend_host(struct sdhci_host *host);
+ extern int sdhci_resume_host(struct sdhci_host *host);
+diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
+index 7c397bb81e01..6da2fbbb9bd5 100644
+--- a/drivers/regulator/anatop-regulator.c
++++ b/drivers/regulator/anatop-regulator.c
+@@ -267,6 +267,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
+ 	config.driver_data = sreg;
+ 	config.of_node = pdev->dev.of_node;
+ 	config.regmap = sreg->anatop;
++	config.ena_gpio = -EINVAL;
+ 
+ 	/* Only core regulators have the ramp up delay configuration. */
+ 	if (sreg->control_reg && sreg->delay_bit_width) {
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index 9a09f3cdbabb..19c4077374b6 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -3459,7 +3459,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
+ 
+ 	dev_set_drvdata(&rdev->dev, rdev);
+ 
+-	if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {
++	if (gpio_is_valid(config->ena_gpio)) {
+ 		ret = regulator_ena_gpio_request(rdev, config);
+ 		if (ret != 0) {
+ 			rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
+index 2436db9e2ca3..acc4ea593c95 100644
+--- a/drivers/regulator/dummy.c
++++ b/drivers/regulator/dummy.c
+@@ -48,6 +48,7 @@ static int dummy_regulator_probe(struct platform_device *pdev)
+ 
+ 	config.dev = &pdev->dev;
+ 	config.init_data = &dummy_initdata;
++	config.ena_gpio = -EINVAL;
+ 
+ 	dummy_regulator_rdev = regulator_register(&dummy_desc, &config);
+ 	if (IS_ERR(dummy_regulator_rdev)) {
+diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
+index c61f7e97e4f8..aabf10dc8a50 100644
+--- a/drivers/regulator/fixed.c
++++ b/drivers/regulator/fixed.c
+@@ -161,9 +161,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
+ 		drvdata->desc.n_voltages = 1;
+ 
+ 	drvdata->desc.fixed_uV = config->microvolts;
+-
+-	if (config->gpio >= 0)
+-		cfg.ena_gpio = config->gpio;
++	cfg.ena_gpio = config->gpio;
+ 	cfg.ena_gpio_invert = !config->enable_high;
+ 	if (config->enabled_at_boot) {
+ 		if (config->enable_high)
+diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig
+index c6e8ba7b3e4e..52516a7cf26f 100644
+--- a/drivers/staging/imx-drm/Kconfig
++++ b/drivers/staging/imx-drm/Kconfig
+@@ -35,6 +35,7 @@ config DRM_IMX_TVE
+ config DRM_IMX_LDB
+ 	tristate "Support for LVDS displays"
+ 	depends on DRM_IMX && MFD_SYSCON
++	select DRM_PANEL
+ 	help
+ 	  Choose this to enable the internal LVDS Display Bridge (LDB)
+ 	  found on i.MX53 and i.MX6 processors.
+@@ -60,3 +61,20 @@ config DRM_IMX_HDMI
+ 	depends on DRM_IMX
+ 	help
+ 	  Choose this if you want to use HDMI on i.MX6.
++
++config DRM_DW_HDMI_AUDIO
++	tristate "Synopsis Designware Audio interface"
++	depends on DRM_IMX_HDMI != n
++	help
++	  Support the Audio interface which is part of the Synopsis
++	  Designware HDMI block.  This is used in conjunction with
++	  the i.MX HDMI driver.
++
++config DRM_DW_HDMI_CEC
++	tristate "Synopsis Designware CEC interface"
++	depends on DRM_IMX_HDMI != n
++	select HDMI_CEC_CORE
++	help
++	  Support the CEC interface which is part of the Synposis
++	  Designware HDMI block.  This is used in conjunction with
++	  the i.MX HDMI driver.
+diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
+index 129e3a3f59f1..5eabd5e4e456 100644
+--- a/drivers/staging/imx-drm/Makefile
++++ b/drivers/staging/imx-drm/Makefile
+@@ -3,6 +3,7 @@ imxdrm-objs := imx-drm-core.o
+ 
+ obj-$(CONFIG_DRM_IMX) += imxdrm.o
+ 
++obj-$(CONFIG_DRM_IMX) += drm-ddc-connector.o
+ obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += parallel-display.o
+ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o
+ obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
+@@ -11,3 +12,5 @@ obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
+ imx-ipuv3-crtc-objs  := ipuv3-crtc.o ipuv3-plane.o
+ obj-$(CONFIG_DRM_IMX_IPUV3)	+= imx-ipuv3-crtc.o
+ obj-$(CONFIG_DRM_IMX_HDMI) += imx-hdmi.o
++obj-$(CONFIG_DRM_DW_HDMI_AUDIO) += dw-hdmi-audio.o
++obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o
+diff --git a/drivers/staging/imx-drm/drm-ddc-connector.c b/drivers/staging/imx-drm/drm-ddc-connector.c
+new file mode 100644
+index 000000000000..a36ed4b06ebe
+--- /dev/null
++++ b/drivers/staging/imx-drm/drm-ddc-connector.c
+@@ -0,0 +1,92 @@
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <drm/drmP.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_edid.h>
++
++#include "drm-ddc-connector.h"
++
++static enum drm_connector_status
++drm_ddc_connector_detect(struct drm_connector *connector, bool force)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++
++	return ddc_conn->detect ? ddc_conn->detect(connector, force) :
++		connector_status_connected;
++}
++
++int drm_ddc_connector_get_modes(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++	struct edid *edid;
++	int ret = 0;
++
++	if (!ddc_conn->ddc)
++		return 0;
++
++	edid = drm_get_edid(connector, ddc_conn->ddc);
++	if (edid) {
++		drm_mode_connector_update_edid_property(connector, edid);
++		ret = drm_add_edid_modes(connector, edid);
++		/* Store the ELD */
++		drm_edid_to_eld(connector, edid);
++		kfree(edid);
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_get_modes);
++
++static void drm_ddc_connector_destroy(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++
++	drm_sysfs_connector_remove(connector);
++	drm_connector_cleanup(connector);
++	if (ddc_conn->ddc)
++		i2c_put_adapter(ddc_conn->ddc);
++}
++
++static const struct drm_connector_funcs drm_ddc_connector_funcs = {
++	.dpms = drm_helper_connector_dpms,
++	.fill_modes = drm_helper_probe_single_connector_modes,
++	.detect = drm_ddc_connector_detect,
++	.destroy = drm_ddc_connector_destroy,
++};
++
++int drm_ddc_connector_add(struct drm_device *drm,
++	struct drm_ddc_connector *ddc_conn, int connector_type)
++{
++	drm_connector_init(drm, &ddc_conn->connector, &drm_ddc_connector_funcs,
++			   connector_type);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_add);
++
++struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
++	struct device_node *np, void *private)
++{
++	struct drm_ddc_connector *ddc_conn;
++	struct device_node *ddc_node;
++
++	ddc_conn = devm_kzalloc(drm->dev, sizeof(*ddc_conn), GFP_KERNEL);
++	if (!ddc_conn)
++		return ERR_PTR(-ENOMEM);
++
++	ddc_conn->private = private;
++
++	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
++	if (ddc_node) {
++		ddc_conn->ddc = of_find_i2c_adapter_by_node(ddc_node);
++		of_node_put(ddc_node);
++		if (!ddc_conn->ddc)
++			return ERR_PTR(-EPROBE_DEFER);
++	}
++
++	return ddc_conn;
++}
++EXPORT_SYMBOL_GPL(drm_ddc_connector_create);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Generic DRM DDC connector module");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/staging/imx-drm/drm-ddc-connector.h b/drivers/staging/imx-drm/drm-ddc-connector.h
+new file mode 100644
+index 000000000000..38068e5105d3
+--- /dev/null
++++ b/drivers/staging/imx-drm/drm-ddc-connector.h
+@@ -0,0 +1,26 @@
++#ifndef DRM_DDC_CONNECTOR_H
++#define DRM_DDC_CONNECTOR_H
++
++struct drm_ddc_connector {
++	struct i2c_adapter *ddc;
++	struct drm_connector connector;
++	enum drm_connector_status (*detect)(struct drm_connector *, bool);
++	void *private;
++};
++
++#define to_ddc_conn(c) container_of(c, struct drm_ddc_connector, connector)
++
++int drm_ddc_connector_get_modes(struct drm_connector *connector);
++int drm_ddc_connector_add(struct drm_device *drm,
++	struct drm_ddc_connector *ddc_conn, int connector_type);
++struct drm_ddc_connector *drm_ddc_connector_create(struct drm_device *drm,
++	struct device_node *np, void *private);
++
++static inline void *drm_ddc_private(struct drm_connector *connector)
++{
++	struct drm_ddc_connector *ddc_conn = to_ddc_conn(connector);
++
++	return ddc_conn->private;
++}
++
++#endif
+diff --git a/drivers/staging/imx-drm/dw-hdmi-audio.c b/drivers/staging/imx-drm/dw-hdmi-audio.c
+new file mode 100644
+index 000000000000..e7495265ed84
+--- /dev/null
++++ b/drivers/staging/imx-drm/dw-hdmi-audio.c
+@@ -0,0 +1,652 @@
++/*
++ * DesignWare HDMI audio driver
++ *
++ * 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.
++ *
++ * Written and tested against the (alleged) DW HDMI Tx found in iMX6S.
++ */
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/asoundef.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++
++#include "dw-hdmi-audio.h"
++
++#define DRIVER_NAME "dw-hdmi-audio"
++
++/* Provide some bits rather than bit offsets */
++enum {
++	HDMI_AHB_DMA_CONF0_SW_FIFO_RST = BIT(7),
++	HDMI_AHB_DMA_CONF0_EN_HLOCK = BIT(3),
++	HDMI_AHB_DMA_START_START = BIT(0),
++	HDMI_AHB_DMA_STOP_STOP = BIT(0),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = BIT(5),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = BIT(4),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = BIT(3),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = BIT(2),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL =
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL |
++		HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY,
++	HDMI_IH_AHBDMAAUD_STAT0_ERROR = BIT(5),
++	HDMI_IH_AHBDMAAUD_STAT0_LOST = BIT(4),
++	HDMI_IH_AHBDMAAUD_STAT0_RETRY = BIT(3),
++	HDMI_IH_AHBDMAAUD_STAT0_DONE = BIT(2),
++	HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = BIT(1),
++	HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = BIT(0),
++	HDMI_IH_AHBDMAAUD_STAT0_ALL =
++		HDMI_IH_AHBDMAAUD_STAT0_ERROR |
++		HDMI_IH_AHBDMAAUD_STAT0_LOST |
++		HDMI_IH_AHBDMAAUD_STAT0_RETRY |
++		HDMI_IH_AHBDMAAUD_STAT0_DONE |
++		HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL |
++		HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY,
++	HDMI_AHB_DMA_CONF0_INCR16 = 2 << 1,
++	HDMI_AHB_DMA_CONF0_INCR8 = 1 << 1,
++	HDMI_AHB_DMA_CONF0_INCR4 = 0,
++	HDMI_AHB_DMA_CONF0_BURST_MODE = BIT(0),
++	HDMI_AHB_DMA_MASK_DONE = BIT(7),
++	HDMI_REVISION_ID = 0x0001,
++	HDMI_IH_AHBDMAAUD_STAT0 = 0x0109,
++	HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189,
++	HDMI_AUD_N1 = 0x3200,
++	HDMI_AUD_CTS1 = 0x3203,
++	HDMI_AHB_DMA_CONF0 = 0x3600,
++	HDMI_AHB_DMA_START = 0x3601,
++	HDMI_AHB_DMA_STOP = 0x3602,
++	HDMI_AHB_DMA_THRSLD = 0x3603,
++	HDMI_AHB_DMA_STRADDR0 = 0x3604,
++	HDMI_AHB_DMA_STPADDR0 = 0x3608,
++	HDMI_AHB_DMA_STAT = 0x3612,
++	HDMI_AHB_DMA_STAT_FULL = BIT(1),
++	HDMI_AHB_DMA_MASK = 0x3614,
++	HDMI_AHB_DMA_POL = 0x3615,
++	HDMI_AHB_DMA_CONF1 = 0x3616,
++	HDMI_AHB_DMA_BUFFPOL = 0x361a,
++};
++
++struct snd_dw_hdmi {
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	struct dw_hdmi_audio_data data;
++	struct snd_pcm_substream *substream;
++	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
++	void *buf_src;
++	void *buf_dst;
++	dma_addr_t buf_addr;
++	unsigned buf_offset;
++	unsigned buf_period;
++	unsigned buf_size;
++	unsigned channels;
++	uint8_t revision;
++	uint8_t iec_offset;
++	uint8_t cs[192][8];
++};
++
++static void dw_hdmi_writel(unsigned long val, void __iomem *ptr)
++{
++	writeb_relaxed(val, ptr);
++	writeb_relaxed(val >> 8, ptr + 1);
++	writeb_relaxed(val >> 16, ptr + 2);
++	writeb_relaxed(val >> 24, ptr + 3);
++}
++
++/*
++ * Convert to hardware format: The userspace buffer contains IEC958 samples,
++ * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
++ * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
++ * samples in 23..0.
++ *
++ * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
++ *
++ * Ideally, we could do with having the data properly formatted in userspace.
++ */
++static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
++	size_t offset, size_t bytes)
++{
++	uint32_t *src = dw->buf_src + offset;
++	uint32_t *dst = dw->buf_dst + offset;
++	uint32_t *end = dw->buf_src + offset + bytes;
++
++	do {
++		uint32_t b, sample = *src++;
++
++		b = (sample & 8) << (28 - 3);
++
++		sample >>= 4;
++
++		*dst++ = sample | b;
++	} while (src < end);
++}
++
++static uint32_t parity(uint32_t sample)
++{
++	sample ^= sample >> 16;
++	sample ^= sample >> 8;
++	sample ^= sample >> 4;
++	sample ^= sample >> 2;
++	sample ^= sample >> 1;
++	return (sample & 1) << 27;
++}
++
++static void dw_hdmi_reformat_s24(struct snd_dw_hdmi *dw,
++	size_t offset, size_t bytes)
++{
++	uint32_t *src = dw->buf_src + offset;
++	uint32_t *dst = dw->buf_dst + offset;
++	uint32_t *end = dw->buf_src + offset + bytes;
++
++	do {
++		unsigned i;
++		uint8_t *cs;
++
++		cs = dw->cs[dw->iec_offset++];
++		if (dw->iec_offset >= 192)
++			dw->iec_offset = 0;
++
++		i = dw->channels;
++		do {
++			uint32_t sample = *src++;
++
++			sample &= ~0xff000000;
++			sample |= *cs++ << 24;
++			sample |= parity(sample & ~0xf8000000);
++
++			*dst++ = sample;
++		} while (--i);
++	} while (src < end);
++}
++
++static void dw_hdmi_create_cs(struct snd_dw_hdmi *dw,
++	struct snd_pcm_runtime *runtime)
++{
++	uint8_t cs[4];
++	unsigned ch, i, j;
++
++	cs[0] = IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS_NONE;
++	cs[1] = IEC958_AES1_CON_GENERAL;
++	cs[2] = IEC958_AES2_CON_SOURCE_UNSPEC;
++	cs[3] = IEC958_AES3_CON_CLOCK_1000PPM;
++
++	switch (runtime->rate) {
++	case 32000:
++		cs[3] |= IEC958_AES3_CON_FS_32000;
++		break;
++	case 44100:
++		cs[3] |= IEC958_AES3_CON_FS_44100;
++		break;
++	case 48000:
++		cs[3] |= IEC958_AES3_CON_FS_48000;
++		break;
++	case 88200:
++		cs[3] |= IEC958_AES3_CON_FS_88200;
++		break;
++	case 96000:
++		cs[3] |= IEC958_AES3_CON_FS_96000;
++		break;
++	case 176400:
++		cs[3] |= IEC958_AES3_CON_FS_176400;
++		break;
++	case 192000:
++		cs[3] |= IEC958_AES3_CON_FS_192000;
++		break;
++	}
++
++	memset(dw->cs, 0, sizeof(dw->cs));
++
++	for (ch = 0; ch < 8; ch++) {
++		cs[2] &= ~IEC958_AES2_CON_CHANNEL;
++		cs[2] |= (ch + 1) << 4;
++
++		for (i = 0; i < ARRAY_SIZE(cs); i++) {
++			unsigned c = cs[i];
++
++			for (j = 0; j < 8; j++, c >>= 1)
++				dw->cs[i * 8 + j][ch] = (c & 1) << 2;
++		}
++	}
++	dw->cs[0][0] |= BIT(4);
++}
++
++static void dw_hdmi_start_dma(struct snd_dw_hdmi *dw)
++{
++	void __iomem *base = dw->data.base;
++	unsigned offset = dw->buf_offset;
++	unsigned period = dw->buf_period;
++	u32 start, stop;
++
++	dw->reformat(dw, offset, period);
++
++	/* Clear all irqs before enabling irqs and starting DMA */
++	writeb_relaxed(HDMI_IH_AHBDMAAUD_STAT0_ALL,
++		       base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	start = dw->buf_addr + offset;
++	stop = start + period - 1;
++
++	/* Setup the hardware start/stop addresses */
++	dw_hdmi_writel(start, base + HDMI_AHB_DMA_STRADDR0);
++	dw_hdmi_writel(stop, base + HDMI_AHB_DMA_STPADDR0);
++
++	writeb_relaxed((u8)~HDMI_AHB_DMA_MASK_DONE, base + HDMI_AHB_DMA_MASK);
++	writeb(HDMI_AHB_DMA_START_START, base + HDMI_AHB_DMA_START);
++
++	offset += period;
++	if (offset >= dw->buf_size)
++		offset = 0;
++	dw->buf_offset = offset;
++}
++
++static void dw_hdmi_stop_dma(struct snd_dw_hdmi *dw)
++{
++	dw->substream = NULL;
++
++	/* Disable interrupts before disabling DMA */
++	writeb_relaxed(~0, dw->data.base + HDMI_AHB_DMA_MASK);
++	writeb_relaxed(HDMI_AHB_DMA_STOP_STOP, dw->data.base + HDMI_AHB_DMA_STOP);
++}
++
++static irqreturn_t snd_dw_hdmi_irq(int irq, void *data)
++{
++	struct snd_dw_hdmi *dw = data;
++	struct snd_pcm_substream *substream;
++	unsigned stat;
++
++	stat = readb_relaxed(dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
++	if (!stat)
++		return IRQ_NONE;
++
++	writeb_relaxed(stat, dw->data.base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	substream = dw->substream;
++	if (stat & HDMI_IH_AHBDMAAUD_STAT0_DONE && substream) {
++		snd_pcm_period_elapsed(substream);
++		if (dw->substream)
++			dw_hdmi_start_dma(dw);
++	}
++
++	return IRQ_HANDLED;
++}
++
++static struct snd_pcm_hardware dw_hdmi_hw = {
++	.info = SNDRV_PCM_INFO_INTERLEAVED |
++		SNDRV_PCM_INFO_BLOCK_TRANSFER |
++		SNDRV_PCM_INFO_MMAP |
++		SNDRV_PCM_INFO_MMAP_VALID,
++	.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE |
++		   SNDRV_PCM_FMTBIT_S24_LE,
++	.rates = SNDRV_PCM_RATE_32000 |
++		 SNDRV_PCM_RATE_44100 |
++		 SNDRV_PCM_RATE_48000 |
++		 SNDRV_PCM_RATE_88200 |
++		 SNDRV_PCM_RATE_96000 |
++		 SNDRV_PCM_RATE_176400 |
++		 SNDRV_PCM_RATE_192000,
++	.channels_min = 2,
++	.channels_max = 8,
++	.buffer_bytes_max = 64 * 1024,
++	.period_bytes_min = 256,
++	.period_bytes_max = 8192,	/* ERR004323: must limit to 8k */
++	.periods_min = 2,
++	.periods_max = 16,
++	.fifo_size = 0,
++};
++
++static unsigned rates_mask[] = {
++	SNDRV_PCM_RATE_32000,
++	SNDRV_PCM_RATE_44100,
++	SNDRV_PCM_RATE_48000,
++	SNDRV_PCM_RATE_88200,
++	SNDRV_PCM_RATE_96000,
++	SNDRV_PCM_RATE_176400,
++	SNDRV_PCM_RATE_192000,
++};
++
++static void dw_hdmi_parse_eld(struct snd_dw_hdmi *dw,
++	struct snd_pcm_runtime *runtime)
++{
++	u8 *sad, *eld = dw->data.eld;
++	unsigned eld_ver,  mnl, sad_count, rates, rate_mask, i;
++	unsigned max_channels;
++
++	eld_ver = eld[0] >> 3;
++	if (eld_ver != 2 && eld_ver != 31)
++		return;
++
++	mnl = eld[4] & 0x1f;
++	if (mnl > 16)
++		return;
++
++	sad_count = eld[5] >> 4;
++	sad = eld + 20 + mnl;
++
++	/* Start from the basic audio settings */
++	max_channels = 2;
++	rates = 7;
++	while (sad_count > 0) {
++		switch (sad[0] & 0x78) {
++		case 0x08: /* PCM */
++			max_channels = max(max_channels, (sad[0] & 7) + 1u);
++			rates |= sad[1];
++			break;
++		}
++		sad += 3;
++		sad_count -= 1;
++	}
++
++	for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
++		if (rates & 1 << i)
++			rate_mask |= rates_mask[i];
++
++	runtime->hw.rates &= rate_mask;
++	runtime->hw.channels_max = min(runtime->hw.channels_max, max_channels);
++}
++
++static int dw_hdmi_open(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++	void __iomem *base = dw->data.base;
++	int ret;
++
++	/* Clear FIFO */
++	writeb_relaxed(HDMI_AHB_DMA_CONF0_SW_FIFO_RST,
++		       base + HDMI_AHB_DMA_CONF0);
++
++	/* Configure interrupt polarities */
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_POL);
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_BUFFPOL);
++
++	/* Keep interrupts masked, and clear any pending */
++	writeb_relaxed(~0, base + HDMI_AHB_DMA_MASK);
++	writeb_relaxed(~0, base + HDMI_IH_AHBDMAAUD_STAT0);
++
++	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
++			  "dw-hdmi-audio", dw);
++	if (ret)
++		return ret;
++
++	/* Un-mute done interrupt */
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL &
++		       ~HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE,
++		       base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++
++	runtime->hw = dw_hdmi_hw;
++	dw_hdmi_parse_eld(dw, runtime);
++	snd_pcm_limit_hw_rates(runtime);
++
++	return 0;
++}
++
++static int dw_hdmi_close(struct snd_pcm_substream *substream)
++{
++	struct snd_dw_hdmi *dw = substream->private_data;
++
++	/* Mute all interrupts */
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
++		       dw->data.base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++
++	free_irq(dw->data.irq, dw);
++
++	return 0;
++}
++
++static int dw_hdmi_hw_free(struct snd_pcm_substream *substream)
++{
++	return snd_pcm_lib_free_vmalloc_buffer(substream);
++}
++
++static int dw_hdmi_hw_params(struct snd_pcm_substream *substream,
++	struct snd_pcm_hw_params *params)
++{
++	return snd_pcm_lib_alloc_vmalloc_buffer(substream,
++						params_buffer_bytes(params));
++}
++
++static int dw_hdmi_prepare(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++	uint8_t threshold, conf0, conf1;
++
++	/* Setup as per 3.0.5 FSL 4.1.0 BSP */
++	switch (dw->revision) {
++	case 0x0a:
++		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
++			HDMI_AHB_DMA_CONF0_INCR4;
++		if (runtime->channels == 2)
++			threshold = 126;
++		else
++			threshold = 124;
++		break;
++	case 0x1a:
++		conf0 = HDMI_AHB_DMA_CONF0_BURST_MODE |
++			HDMI_AHB_DMA_CONF0_INCR8;
++		threshold = 128;
++		break;
++	default:
++		/* NOTREACHED */
++		return -EINVAL;
++	}
++
++	dw->data.set_sample_rate(dw->data.hdmi, runtime->rate);
++
++	/* Minimum number of bytes in the fifo. */
++	runtime->hw.fifo_size = threshold * 32;
++
++	conf0 |= HDMI_AHB_DMA_CONF0_EN_HLOCK;
++	conf1 = (1 << runtime->channels) - 1;
++
++	writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD);
++	writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0);
++	writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1);
++
++	switch (runtime->format) {
++	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
++		dw->reformat = dw_hdmi_reformat_iec958;
++		break;
++	case SNDRV_PCM_FORMAT_S24_LE:
++		dw_hdmi_create_cs(dw, runtime);
++		dw->reformat = dw_hdmi_reformat_s24;
++		break;
++	}
++	dw->iec_offset = 0;
++	dw->channels = runtime->channels;
++	dw->buf_src  = runtime->dma_area;
++	dw->buf_dst  = substream->dma_buffer.area;
++	dw->buf_addr = substream->dma_buffer.addr;
++	dw->buf_period = snd_pcm_lib_period_bytes(substream);
++	dw->buf_size = snd_pcm_lib_buffer_bytes(substream);
++
++	return 0;
++}
++
++static int dw_hdmi_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++	struct snd_dw_hdmi *dw = substream->private_data;
++	void __iomem *base = dw->data.base;
++	unsigned n[3], cts[3];
++	int ret = 0, i;
++	bool err005174;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++		err005174 = dw->revision == 0x0a;
++		if (err005174) {
++			for (i = 2; i >= 1; i--) {
++				n[i] = readb_relaxed(base + HDMI_AUD_N1 + i);
++				cts[i] = readb_relaxed(base + HDMI_AUD_CTS1 + i);
++				writeb_relaxed(0, base + HDMI_AUD_N1 + i);
++				writeb_relaxed(0, base + HDMI_AUD_CTS1 + i);
++			}
++		}
++
++		dw->buf_offset = 0;
++		dw->substream = substream;
++		dw_hdmi_start_dma(dw);
++
++		if (err005174) {
++			for (i = 2; i >= 1; i--)
++				writeb_relaxed(cts[i], base + HDMI_AUD_CTS1 + i);
++			for (i = 2; i >= 1; i--)
++				writeb_relaxed(n[i], base + HDMI_AUD_N1 + i);
++		}
++
++		substream->runtime->delay = substream->runtime->period_size;
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++		dw_hdmi_stop_dma(dw);
++		break;
++
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++static snd_pcm_uframes_t dw_hdmi_pointer(struct snd_pcm_substream *substream)
++{
++	struct snd_pcm_runtime *runtime = substream->runtime;
++	struct snd_dw_hdmi *dw = substream->private_data;
++
++	return bytes_to_frames(runtime, dw->buf_offset);
++}
++
++static struct snd_pcm_ops snd_dw_hdmi_ops = {
++	.open = dw_hdmi_open,
++	.close = dw_hdmi_close,
++	.ioctl = snd_pcm_lib_ioctl,
++	.hw_params = dw_hdmi_hw_params,
++	.hw_free = dw_hdmi_hw_free,
++	.prepare = dw_hdmi_prepare,
++	.trigger = dw_hdmi_trigger,
++	.pointer = dw_hdmi_pointer,
++	.page = snd_pcm_lib_get_vmalloc_page,
++};
++
++static int snd_dw_hdmi_probe(struct platform_device *pdev)
++{
++	const struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
++	struct device *dev = pdev->dev.parent;
++	struct snd_dw_hdmi *dw;
++	struct snd_card *card;
++	struct snd_pcm *pcm;
++	unsigned revision;
++	int ret;
++
++	writeb_relaxed(HDMI_IH_MUTE_AHBDMAAUD_STAT0_ALL,
++		       data->base + HDMI_IH_MUTE_AHBDMAAUD_STAT0);
++	revision = readb_relaxed(data->base + HDMI_REVISION_ID);
++	if (revision != 0x0a && revision != 0x1a) {
++		dev_err(dev, "dw-hdmi-audio: unknown revision 0x%02x\n",
++			revision);
++		return -ENXIO;
++	}
++
++	ret = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
++			      THIS_MODULE, sizeof(struct snd_dw_hdmi), &card);
++	if (ret < 0)
++		return ret;
++
++	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
++	strlcpy(card->shortname, "DW-HDMI", sizeof(card->shortname));
++	snprintf(card->longname, sizeof(card->longname),
++		 "%s rev 0x%02x, irq %d", card->shortname, revision,
++		 data->irq);
++
++	dw = card->private_data;
++	dw->card = card;
++	dw->data = *data;
++	dw->revision = revision;
++
++	ret = snd_pcm_new(card, "DW HDMI", 0, 1, 0, &pcm);
++	if (ret < 0)
++		goto err;
++
++	dw->pcm = pcm;
++	pcm->private_data = dw;
++	strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
++	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dw_hdmi_ops);
++
++	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++			dev, 64 * 1024, 64 * 1024);
++
++	ret = snd_card_register(card);
++	if (ret < 0)
++		goto err;
++
++	platform_set_drvdata(pdev, dw);
++
++	return 0;
++
++err:
++	snd_card_free(card);
++	return ret;
++}
++
++static int snd_dw_hdmi_remove(struct platform_device *pdev)
++{
++	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
++
++	snd_card_free(dw->card);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int snd_dw_hdmi_suspend(struct device *dev)
++{
++	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
++
++	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D3cold);
++	snd_pcm_suspend_all(dw->pcm);
++
++	return 0;
++}
++
++static int snd_dw_hdmi_resume(struct device *dev)
++{
++	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
++
++	snd_power_change_state(dw->card, SNDRV_CTL_POWER_D0);
++
++	return 0;
++}
++
++static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
++			 snd_dw_hdmi_resume);
++#define PM_OPS &snd_dw_hdmi_pm
++#else
++#define PM_OPS NULL
++#endif
++
++static struct platform_driver snd_dw_hdmi_driver = {
++	.probe	= snd_dw_hdmi_probe,
++	.remove	= snd_dw_hdmi_remove,
++	.driver	= {
++		.name = "dw-hdmi-audio",
++		.owner = THIS_MODULE,
++		.pm = PM_OPS,
++	},
++};
++
++module_platform_driver(snd_dw_hdmi_driver);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/staging/imx-drm/dw-hdmi-audio.h b/drivers/staging/imx-drm/dw-hdmi-audio.h
+new file mode 100644
+index 000000000000..2d91d709381d
+--- /dev/null
++++ b/drivers/staging/imx-drm/dw-hdmi-audio.h
+@@ -0,0 +1,15 @@
++#ifndef DW_HDMI_AUDIO_H
++#define DW_HDMI_AUDIO_H
++
++struct imx_hdmi;
++
++struct dw_hdmi_audio_data {
++	phys_addr_t phys;
++	void __iomem *base;
++	int irq;
++	struct imx_hdmi *hdmi;
++	u8 *eld;
++	void (*set_sample_rate)(struct imx_hdmi *, unsigned);
++};
++
++#endif
+diff --git a/drivers/staging/imx-drm/dw-hdmi-cec.c b/drivers/staging/imx-drm/dw-hdmi-cec.c
+new file mode 100644
+index 000000000000..c94b75aa037b
+--- /dev/null
++++ b/drivers/staging/imx-drm/dw-hdmi-cec.c
+@@ -0,0 +1,205 @@
++/* http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c?h=imx_3.0.35_4.1.0 */
++#include <linux/cec-dev.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++#include "imx-hdmi.h"
++#include "dw-hdmi-cec.h"
++
++#define DEV_NAME "mxc_hdmi_cec"
++
++enum {
++	CEC_STAT_DONE		= BIT(0),
++	CEC_STAT_EOM		= BIT(1),
++	CEC_STAT_NACK		= BIT(2),
++	CEC_STAT_ARBLOST	= BIT(3),
++	CEC_STAT_ERROR_INIT	= BIT(4),
++	CEC_STAT_ERROR_FOLL	= BIT(5),
++	CEC_STAT_WAKEUP		= BIT(6),
++
++	CEC_CTRL_START		= BIT(0),
++	CEC_CTRL_NORMAL		= 1 << 1,
++};
++
++struct dw_hdmi_cec {
++	struct cec_dev cec;
++
++	struct device *dev;
++	void __iomem *base;
++	const struct dw_hdmi_cec_ops *ops;
++	void *ops_data;
++	int irq;
++};
++
++static void dw_hdmi_set_address(struct cec_dev *cec_dev, unsigned addresses)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++
++	writeb(addresses & 255, cec->base + HDMI_CEC_ADDR_L);
++	writeb(addresses >> 8, cec->base + HDMI_CEC_ADDR_H);
++}
++
++static void dw_hdmi_send_message(struct cec_dev *cec_dev, u8 *msg,
++	size_t count)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++	unsigned i;
++
++	for (i = 0; i < count; i++)
++		writeb(msg[i], cec->base + HDMI_CEC_TX_DATA0 + i);
++
++	writeb(count, cec->base + HDMI_CEC_TX_CNT);
++	writeb(CEC_CTRL_NORMAL | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
++}
++
++static irqreturn_t dw_hdmi_cec_irq(int irq, void *data)
++{
++	struct dw_hdmi_cec *cec = data;
++	struct cec_dev *cec_dev = &cec->cec;
++	unsigned stat = readb(cec->base + HDMI_IH_CEC_STAT0);
++
++	if (stat == 0)
++		return IRQ_NONE;
++
++	writeb(stat, cec->base + HDMI_IH_CEC_STAT0);
++
++	if (stat & CEC_STAT_ERROR_INIT) {
++		if (cec->cec.retries) {
++			unsigned v = readb(cec->base + HDMI_CEC_CTRL);
++			writeb(v | CEC_CTRL_START, cec->base + HDMI_CEC_CTRL);
++			cec->cec.retries -= 1;
++		} else {
++			cec->cec.write_busy = 0;
++			cec_dev_event(cec_dev, MESSAGE_TYPE_SEND_ERROR, NULL, 0);
++		}
++	} else if (stat & (CEC_STAT_DONE | CEC_STAT_NACK))
++		cec_dev_send_complete(cec_dev, stat & CEC_STAT_DONE);
++
++	if (stat & CEC_STAT_EOM) {
++		unsigned len, i;
++		u8 msg[MAX_MESSAGE_LEN];
++
++		len = readb(cec->base + HDMI_CEC_RX_CNT);
++		if (len > sizeof(msg))
++			len = sizeof(msg);
++
++		for (i = 0; i < len; i++)
++			msg[i] = readb(cec->base + HDMI_CEC_RX_DATA0 + i);
++
++		writeb(0, cec->base + HDMI_CEC_LOCK);
++
++		cec_dev_receive(cec_dev, msg, len);
++	}
++
++	return IRQ_HANDLED;
++}
++EXPORT_SYMBOL(dw_hdmi_cec_irq);
++
++static void dw_hdmi_cec_release(struct cec_dev *cec_dev)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++
++	writeb(~0, cec->base + HDMI_CEC_MASK);
++	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_POLARITY);
++
++	free_irq(cec->irq, cec);
++
++	cec->ops->disable(cec->ops_data);
++}
++
++static int dw_hdmi_cec_open(struct cec_dev *cec_dev)
++{
++	struct dw_hdmi_cec *cec = container_of(cec_dev, struct dw_hdmi_cec, cec);
++	unsigned irqs;
++	int ret;
++
++	writeb(0, cec->base + HDMI_CEC_CTRL);
++	writeb(~0, cec->base + HDMI_IH_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_LOCK);
++
++	ret = request_irq(cec->irq, dw_hdmi_cec_irq, IRQF_SHARED,
++			  DEV_NAME, cec);
++	if (ret < 0)
++		return ret;
++
++	dw_hdmi_set_address(cec_dev, cec_dev->addresses);
++
++	cec->ops->enable(cec->ops_data);
++
++	irqs = CEC_STAT_ERROR_INIT | CEC_STAT_NACK | CEC_STAT_EOM |
++	       CEC_STAT_DONE;
++	writeb(irqs, cec->base + HDMI_CEC_POLARITY);
++	writeb(~irqs, cec->base + HDMI_CEC_MASK);
++	writeb(~irqs, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++
++	return 0;
++}
++
++static int dw_hdmi_cec_probe(struct platform_device *pdev)
++{
++	struct dw_hdmi_cec_data *data = dev_get_platdata(&pdev->dev);
++	struct dw_hdmi_cec *cec;
++
++	if (!data)
++		return -ENXIO;
++
++	cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL);
++	if (!cec)
++		return -ENOMEM;
++
++	cec->dev = &pdev->dev;
++	cec->base = data->base;
++	cec->irq = data->irq;
++	cec->ops = data->ops;
++	cec->ops_data = data->ops_data;
++	cec->cec.open = dw_hdmi_cec_open;
++	cec->cec.release = dw_hdmi_cec_release;
++	cec->cec.send_message = dw_hdmi_send_message;
++	cec->cec.set_address = dw_hdmi_set_address;
++
++	cec_dev_init(&cec->cec, THIS_MODULE);
++
++	/* FIXME: soft-reset the CEC interface */
++
++	dw_hdmi_set_address(&cec->cec, cec->cec.addresses);
++	writeb(0, cec->base + HDMI_CEC_TX_CNT);
++	writeb(~0, cec->base + HDMI_CEC_MASK);
++	writeb(~0, cec->base + HDMI_IH_MUTE_CEC_STAT0);
++	writeb(0, cec->base + HDMI_CEC_POLARITY);
++
++	/*
++	 * Our device is just a convenience - we want to link to the real
++	 * hardware device here, so that userspace can see the association
++	 * between the HDMI hardware and its associated CEC chardev.
++	 */
++	return cec_dev_add(&cec->cec, cec->dev->parent, DEV_NAME);
++}
++
++static int dw_hdmi_cec_remove(struct platform_device *pdev)
++{
++	struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
++
++	cec_dev_remove(&cec->cec);
++
++	return 0;
++}
++
++static struct platform_driver dw_hdmi_cec_driver = {
++	.probe	= dw_hdmi_cec_probe,
++	.remove	= dw_hdmi_cec_remove,
++	.driver = {
++		.name = "dw-hdmi-cec",
++		.owner = THIS_MODULE,
++	},
++};
++module_platform_driver(dw_hdmi_cec_driver);
++
++MODULE_AUTHOR("Russell King <rmk+kernel@arm.linux.org.uk>");
++MODULE_DESCRIPTION("Synopsis Designware HDMI CEC driver for i.MX");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec");
+diff --git a/drivers/staging/imx-drm/dw-hdmi-cec.h b/drivers/staging/imx-drm/dw-hdmi-cec.h
+new file mode 100644
+index 000000000000..5ff40cc237a8
+--- /dev/null
++++ b/drivers/staging/imx-drm/dw-hdmi-cec.h
+@@ -0,0 +1,16 @@
++#ifndef DW_HDMI_CEC_H
++#define DW_HDMI_CEC_H
++
++struct dw_hdmi_cec_ops {
++	void (*enable)(void *);
++	void (*disable)(void *);
++};
++
++struct dw_hdmi_cec_data {
++	void __iomem *base;
++	int irq;
++	const struct dw_hdmi_cec_ops *ops;
++	void *ops_data;
++};
++
++#endif
+diff --git a/drivers/staging/imx-drm/imx-hdmi.c b/drivers/staging/imx-drm/imx-hdmi.c
+index d47dedd2cdb4..627b4b608794 100644
+--- a/drivers/staging/imx-drm/imx-hdmi.c
++++ b/drivers/staging/imx-drm/imx-hdmi.c
+@@ -28,6 +28,9 @@
+ #include <drm/drm_edid.h>
+ #include <drm/drm_encoder_slave.h>
+ 
++#include "drm-ddc-connector.h"
++#include "dw-hdmi-audio.h"
++#include "dw-hdmi-cec.h"
+ #include "ipu-v3/imx-ipu-v3.h"
+ #include "imx-hdmi.h"
+ #include "imx-drm.h"
+@@ -112,27 +115,27 @@ struct hdmi_data_info {
+ };
+ 
+ struct imx_hdmi {
+-	struct drm_connector connector;
++	struct drm_ddc_connector *ddc_conn;
+ 	struct drm_encoder encoder;
+ 
++	struct platform_device *audio;
++	struct platform_device *cec;
+ 	enum imx_hdmi_devtype dev_type;
+ 	struct device *dev;
+ 	struct clk *isfr_clk;
+ 	struct clk *iahb_clk;
+ 
+-	enum drm_connector_status connector_status;
+-
+ 	struct hdmi_data_info hdmi_data;
+ 	int vic;
+ 
+ 	u8 edid[HDMI_EDID_LEN];
++	u8 mc_clkdis;
+ 	bool cable_plugin;
+ 
+ 	bool phy_enabled;
+ 	struct drm_display_mode previous_mode;
+ 
+ 	struct regmap *regmap;
+-	struct i2c_adapter *ddc;
+ 	void __iomem *regs;
+ 
+ 	unsigned int sample_rate;
+@@ -362,6 +365,12 @@ static void hdmi_clk_regenerator_update_pixel_clock(struct imx_hdmi *hdmi)
+ 	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
+ }
+ 
++static void imx_hdmi_set_sample_rate(struct imx_hdmi *hdmi, unsigned rate)
++{
++	hdmi->sample_rate = rate;
++	hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock);
++}
++
+ /*
+  * this submodule is responsible for the video data synchronization.
+  * for example, for RGB 4:4:4 input, the data map is defined as
+@@ -1148,8 +1157,6 @@ static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi)
+ /* HDMI Initialization Step B.4 */
+ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
+ {
+-	u8 clkdis;
+-
+ 	/* control period minimum duration */
+ 	hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
+ 	hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
+@@ -1161,23 +1168,28 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
+ 	hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
+ 
+ 	/* Enable pixel clock and tmds data path */
+-	clkdis = 0x7F;
+-	clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+-	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
++	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
++			   HDMI_MC_CLKDIS_CSCCLK_DISABLE |
++			   HDMI_MC_CLKDIS_AUDCLK_DISABLE |
++			   HDMI_MC_CLKDIS_PREPCLK_DISABLE |
++			   HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ 
+-	clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+-	hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ 
+ 	/* Enable csc path */
+ 	if (is_color_space_conversion(hdmi)) {
+-		clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+-		hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
++		hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
++		hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ 	}
+ }
+ 
+ static void hdmi_enable_audio_clk(struct imx_hdmi *hdmi)
+ {
+-	hdmi_modb(hdmi, 0, HDMI_MC_CLKDIS_AUDCLK_DISABLE, HDMI_MC_CLKDIS);
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
+ }
+ 
+ /* Workaround to clear the overflow condition */
+@@ -1380,41 +1392,16 @@ static void imx_hdmi_poweroff(struct imx_hdmi *hdmi)
+ static enum drm_connector_status imx_hdmi_connector_detect(struct drm_connector
+ 							*connector, bool force)
+ {
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
+-	return hdmi->connector_status;
+-}
+-
+-static int imx_hdmi_connector_get_modes(struct drm_connector *connector)
+-{
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
+-	struct edid *edid;
+-	int ret;
+-
+-	if (!hdmi->ddc)
+-		return 0;
+-
+-	edid = drm_get_edid(connector, hdmi->ddc);
+-	if (edid) {
+-		dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
+-			edid->width_cm, edid->height_cm);
+-
+-		drm_mode_connector_update_edid_property(connector, edid);
+-		ret = drm_add_edid_modes(connector, edid);
+-		kfree(edid);
+-	} else {
+-		dev_dbg(hdmi->dev, "failed to get edid\n");
+-	}
++	struct imx_hdmi *hdmi = drm_ddc_private(connector);
+ 
+-	return 0;
++	return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
++		connector_status_connected : connector_status_disconnected;
+ }
+ 
+ static struct drm_encoder *imx_hdmi_connector_best_encoder(struct drm_connector
+ 							   *connector)
+ {
+-	struct imx_hdmi *hdmi = container_of(connector, struct imx_hdmi,
+-					     connector);
++	struct imx_hdmi *hdmi = drm_ddc_private(connector);
+ 
+ 	return &hdmi->encoder;
+ }
+@@ -1483,15 +1470,8 @@ static struct drm_encoder_helper_funcs imx_hdmi_encoder_helper_funcs = {
+ 	.disable = imx_hdmi_encoder_disable,
+ };
+ 
+-static struct drm_connector_funcs imx_hdmi_connector_funcs = {
+-	.dpms = drm_helper_connector_dpms,
+-	.fill_modes = drm_helper_probe_single_connector_modes,
+-	.detect = imx_hdmi_connector_detect,
+-	.destroy = imx_drm_connector_destroy,
+-};
+-
+ static struct drm_connector_helper_funcs imx_hdmi_connector_helper_funcs = {
+-	.get_modes = imx_hdmi_connector_get_modes,
++	.get_modes = drm_ddc_connector_get_modes,
+ 	.mode_valid = imx_drm_connector_mode_valid,
+ 	.best_encoder = imx_hdmi_connector_best_encoder,
+ };
+@@ -1524,7 +1504,6 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
+ 
+ 			hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0);
+ 
+-			hdmi->connector_status = connector_status_connected;
+ 			imx_hdmi_poweron(hdmi);
+ 		} else {
+ 			dev_dbg(hdmi->dev, "EVENT=plugout\n");
+@@ -1532,10 +1511,9 @@ static irqreturn_t imx_hdmi_irq(int irq, void *dev_id)
+ 			hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD,
+ 				HDMI_PHY_POL0);
+ 
+-			hdmi->connector_status = connector_status_disconnected;
+ 			imx_hdmi_poweroff(hdmi);
+ 		}
+-		drm_helper_hpd_irq_event(hdmi->connector.dev);
++		drm_helper_hpd_irq_event(hdmi->ddc_conn->connector.dev);
+ 	}
+ 
+ 	hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
+@@ -1553,24 +1531,42 @@ static int imx_hdmi_register(struct drm_device *drm, struct imx_hdmi *hdmi)
+ 	if (ret)
+ 		return ret;
+ 
+-	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
++	hdmi->ddc_conn->connector.polled = DRM_CONNECTOR_POLL_HPD;
+ 
+ 	drm_encoder_helper_add(&hdmi->encoder, &imx_hdmi_encoder_helper_funcs);
+ 	drm_encoder_init(drm, &hdmi->encoder, &imx_hdmi_encoder_funcs,
+ 			 DRM_MODE_ENCODER_TMDS);
+ 
+-	drm_connector_helper_add(&hdmi->connector,
++	drm_connector_helper_add(&hdmi->ddc_conn->connector,
+ 			&imx_hdmi_connector_helper_funcs);
+-	drm_connector_init(drm, &hdmi->connector, &imx_hdmi_connector_funcs,
+-			   DRM_MODE_CONNECTOR_HDMIA);
+-
+-	hdmi->connector.encoder = &hdmi->encoder;
++	drm_ddc_connector_add(drm, hdmi->ddc_conn, DRM_MODE_CONNECTOR_HDMIA);
+ 
+-	drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
++	drm_mode_connector_attach_encoder(&hdmi->ddc_conn->connector, &hdmi->encoder);
+ 
+ 	return 0;
+ }
+ 
++static void imx_hdmi_cec_enable(void *data)
++{
++	struct imx_hdmi *hdmi = data;
++
++	hdmi->mc_clkdis &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
++}
++
++static void imx_hdmi_cec_disable(void *data)
++{
++	struct imx_hdmi *hdmi = data;
++
++	hdmi->mc_clkdis |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
++	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
++}
++
++static const struct dw_hdmi_cec_ops imx_hdmi_cec_ops = {
++	.enable = imx_hdmi_cec_enable,
++	.disable = imx_hdmi_cec_disable,
++};
++
+ static struct platform_device_id imx_hdmi_devtype[] = {
+ 	{
+ 		.name = "imx6q-hdmi",
+@@ -1592,11 +1588,13 @@ MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids);
+ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
+ {
+ 	struct platform_device *pdev = to_platform_device(dev);
++	struct platform_device_info pdevinfo;
+ 	const struct of_device_id *of_id =
+ 				of_match_device(imx_hdmi_dt_ids, dev);
+ 	struct drm_device *drm = data;
+ 	struct device_node *np = dev->of_node;
+-	struct device_node *ddc_node;
++	struct dw_hdmi_audio_data audio;
++	struct dw_hdmi_cec_data cec;
+ 	struct imx_hdmi *hdmi;
+ 	struct resource *iores;
+ 	int ret, irq;
+@@ -1605,27 +1603,22 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
+ 	if (!hdmi)
+ 		return -ENOMEM;
+ 
++	hdmi->ddc_conn = drm_ddc_connector_create(drm, np, hdmi);
++	if (IS_ERR(hdmi->ddc_conn))
++		return PTR_ERR(hdmi->ddc_conn);
++
++	hdmi->ddc_conn->detect = imx_hdmi_connector_detect;
++
+ 	hdmi->dev = dev;
+-	hdmi->connector_status = connector_status_disconnected;
+ 	hdmi->sample_rate = 48000;
+ 	hdmi->ratio = 100;
++	hdmi->mc_clkdis = 0x7f;
+ 
+ 	if (of_id) {
+ 		const struct platform_device_id *device_id = of_id->data;
+ 		hdmi->dev_type = device_id->driver_data;
+ 	}
+ 
+-	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+-	if (ddc_node) {
+-		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+-		if (!hdmi->ddc)
+-			dev_dbg(hdmi->dev, "failed to read ddc node\n");
+-
+-		of_node_put(ddc_node);
+-	} else {
+-		dev_dbg(hdmi->dev, "no ddc property found\n");
+-	}
+-
+ 	irq = platform_get_irq(pdev, 0);
+ 	if (irq < 0)
+ 		return -EINVAL;
+@@ -1711,6 +1704,35 @@ static int imx_hdmi_bind(struct device *dev, struct device *master, void *data)
+ 	/* Unmute interrupts */
+ 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+ 
++	memset(&pdevinfo, 0, sizeof(pdevinfo));
++	pdevinfo.parent = dev;
++	pdevinfo.id = PLATFORM_DEVID_AUTO;
++
++	audio.phys = iores->start;
++	audio.base = hdmi->regs;
++	audio.irq = irq;
++	audio.hdmi = hdmi;
++	audio.eld = hdmi->ddc_conn->connector.eld;
++	audio.set_sample_rate = imx_hdmi_set_sample_rate;
++
++	pdevinfo.name = "dw-hdmi-audio";
++	pdevinfo.data = &audio;
++	pdevinfo.size_data = sizeof(audio);
++	pdevinfo.dma_mask = DMA_BIT_MASK(32);
++	hdmi->audio = platform_device_register_full(&pdevinfo);
++
++	cec.base = hdmi->regs;
++	cec.irq = irq;
++	cec.ops = &imx_hdmi_cec_ops;
++	cec.ops_data = hdmi;
++
++	pdevinfo.name = "dw-hdmi-cec";
++	pdevinfo.data = &cec;
++	pdevinfo.size_data = sizeof(cec);
++	pdevinfo.dma_mask = 0;
++
++	hdmi->cec = platform_device_register_full(&pdevinfo);
++
+ 	dev_set_drvdata(dev, hdmi);
+ 
+ 	return 0;
+@@ -1728,15 +1750,19 @@ static void imx_hdmi_unbind(struct device *dev, struct device *master,
+ {
+ 	struct imx_hdmi *hdmi = dev_get_drvdata(dev);
+ 
++	if (!IS_ERR(hdmi->audio))
++		platform_device_unregister(hdmi->audio);
++	if (!IS_ERR(hdmi->cec))
++		platform_device_unregister(hdmi->cec);
++
+ 	/* Disable all interrupts */
+ 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+ 
+-	hdmi->connector.funcs->destroy(&hdmi->connector);
++	hdmi->ddc_conn->connector.funcs->destroy(&hdmi->ddc_conn->connector);
+ 	hdmi->encoder.funcs->destroy(&hdmi->encoder);
+ 
+ 	clk_disable_unprepare(hdmi->iahb_clk);
+ 	clk_disable_unprepare(hdmi->isfr_clk);
+-	i2c_put_adapter(hdmi->ddc);
+ }
+ 
+ static const struct component_ops hdmi_ops = {
+diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
+index fe4c1ef4e7a5..3a3bacec2e11 100644
+--- a/drivers/staging/imx-drm/imx-ldb.c
++++ b/drivers/staging/imx-drm/imx-ldb.c
+@@ -24,6 +24,7 @@
+ #include <drm/drmP.h>
+ #include <drm/drm_fb_helper.h>
+ #include <drm/drm_crtc_helper.h>
++#include <drm/drm_panel.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+ #include <linux/of_address.h>
+@@ -60,6 +61,7 @@ struct imx_ldb_channel {
+ 	struct imx_ldb *ldb;
+ 	struct drm_connector connector;
+ 	struct drm_encoder encoder;
++	struct drm_panel *panel;
+ 	struct device_node *child;
+ 	int chno;
+ 	void *edid;
+@@ -96,6 +98,13 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
+ 	struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
+ 	int num_modes = 0;
+ 
++	if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
++	    imx_ldb_ch->panel->funcs->get_modes) {
++		num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
++		if (num_modes > 0)
++			return num_modes;
++	}
++
+ 	if (imx_ldb_ch->edid) {
+ 		drm_mode_connector_update_edid_property(connector,
+ 							imx_ldb_ch->edid);
+@@ -243,6 +252,8 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
+ 	}
+ 
+ 	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
++
++	drm_panel_enable(imx_ldb_ch->panel);
+ }
+ 
+ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
+@@ -294,6 +305,8 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
+ 		 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
+ 		return;
+ 
++	drm_panel_disable(imx_ldb_ch->panel);
++
+ 	if (imx_ldb_ch == &ldb->channel[0])
+ 		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
+ 	else if (imx_ldb_ch == &ldb->channel[1])
+@@ -379,6 +392,9 @@ static int imx_ldb_register(struct drm_device *drm,
+ 	drm_connector_init(drm, &imx_ldb_ch->connector,
+ 			   &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
+ 
++	if (imx_ldb_ch->panel)
++		drm_panel_attach(imx_ldb_ch->panel, &imx_ldb_ch->connector);
++
+ 	drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
+ 			&imx_ldb_ch->encoder);
+ 
+@@ -493,6 +509,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
+ 
+ 	for_each_child_of_node(np, child) {
+ 		struct imx_ldb_channel *channel;
++		struct device_node *panel_node;
+ 
+ 		ret = of_property_read_u32(child, "reg", &i);
+ 		if (ret || i < 0 || i > 1)
+@@ -556,6 +573,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
+ 			return -EINVAL;
+ 		}
+ 
++		panel_node = of_parse_phandle(child, "fsl,panel", 0);
++		if (panel_node)
++			channel->panel = of_drm_find_panel(panel_node);
++
+ 		ret = imx_ldb_register(drm, channel);
+ 		if (ret)
+ 			return ret;
+diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
+index a23f4f773146..6eafba5072ad 100644
+--- a/drivers/staging/imx-drm/imx-tve.c
++++ b/drivers/staging/imx-drm/imx-tve.c
+@@ -22,7 +22,6 @@
+ #include <linux/clk-provider.h>
+ #include <linux/component.h>
+ #include <linux/module.h>
+-#include <linux/i2c.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/spinlock.h>
+@@ -31,6 +30,7 @@
+ #include <drm/drm_fb_helper.h>
+ #include <drm/drm_crtc_helper.h>
+ 
++#include "drm-ddc-connector.h"
+ #include "ipu-v3/imx-ipu-v3.h"
+ #include "imx-drm.h"
+ 
+@@ -111,7 +111,7 @@ enum {
+ };
+ 
+ struct imx_tve {
+-	struct drm_connector connector;
++	struct drm_ddc_connector *ddc_conn;
+ 	struct drm_encoder encoder;
+ 	struct device *dev;
+ 	spinlock_t lock;	/* register lock */
+@@ -120,7 +120,6 @@ struct imx_tve {
+ 
+ 	struct regmap *regmap;
+ 	struct regulator *dac_reg;
+-	struct i2c_adapter *ddc;
+ 	struct clk *clk;
+ 	struct clk *di_sel_clk;
+ 	struct clk_hw clk_hw_di;
+@@ -219,35 +218,10 @@ static int tve_setup_vga(struct imx_tve *tve)
+ 	return 0;
+ }
+ 
+-static enum drm_connector_status imx_tve_connector_detect(
+-				struct drm_connector *connector, bool force)
+-{
+-	return connector_status_connected;
+-}
+-
+-static int imx_tve_connector_get_modes(struct drm_connector *connector)
+-{
+-	struct imx_tve *tve = con_to_tve(connector);
+-	struct edid *edid;
+-	int ret = 0;
+-
+-	if (!tve->ddc)
+-		return 0;
+-
+-	edid = drm_get_edid(connector, tve->ddc);
+-	if (edid) {
+-		drm_mode_connector_update_edid_property(connector, edid);
+-		ret = drm_add_edid_modes(connector, edid);
+-		kfree(edid);
+-	}
+-
+-	return ret;
+-}
+-
+ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
+ 					struct drm_display_mode *mode)
+ {
+-	struct imx_tve *tve = con_to_tve(connector);
++	struct imx_tve *tve = to_ddc_conn(connector)->private;
+ 	unsigned long rate;
+ 	int ret;
+ 
+@@ -274,7 +248,7 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
+ static struct drm_encoder *imx_tve_connector_best_encoder(
+ 		struct drm_connector *connector)
+ {
+-	struct imx_tve *tve = con_to_tve(connector);
++	struct imx_tve *tve = drm_ddc_private(connector);
+ 
+ 	return &tve->encoder;
+ }
+@@ -362,15 +336,8 @@ static void imx_tve_encoder_disable(struct drm_encoder *encoder)
+ 	tve_disable(tve);
+ }
+ 
+-static struct drm_connector_funcs imx_tve_connector_funcs = {
+-	.dpms = drm_helper_connector_dpms,
+-	.fill_modes = drm_helper_probe_single_connector_modes,
+-	.detect = imx_tve_connector_detect,
+-	.destroy = imx_drm_connector_destroy,
+-};
+-
+ static struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
+-	.get_modes = imx_tve_connector_get_modes,
++	.get_modes = drm_ddc_connector_get_modes,
+ 	.best_encoder = imx_tve_connector_best_encoder,
+ 	.mode_valid = imx_tve_connector_mode_valid,
+ };
+@@ -513,12 +480,11 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
+ 	drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs,
+ 			 encoder_type);
+ 
+-	drm_connector_helper_add(&tve->connector,
++	drm_connector_helper_add(&tve->ddc_conn->connector,
+ 			&imx_tve_connector_helper_funcs);
+-	drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs,
+-			   DRM_MODE_CONNECTOR_VGA);
++	drm_ddc_connector_add(drm, tve->ddc_conn, DRM_MODE_CONNECTOR_VGA);
+ 
+-	drm_mode_connector_attach_encoder(&tve->connector, &tve->encoder);
++	drm_mode_connector_attach_encoder(&tve->ddc_conn->connector, &tve->encoder);
+ 
+ 	return 0;
+ }
+@@ -567,7 +533,6 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
+ 	struct platform_device *pdev = to_platform_device(dev);
+ 	struct drm_device *drm = data;
+ 	struct device_node *np = dev->of_node;
+-	struct device_node *ddc_node;
+ 	struct imx_tve *tve;
+ 	struct resource *res;
+ 	void __iomem *base;
+@@ -579,15 +544,13 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
+ 	if (!tve)
+ 		return -ENOMEM;
+ 
++	tve->ddc_conn = drm_ddc_connector_create(drm, np, tve);
++	if (IS_ERR(tve->ddc_conn))
++		return PTR_ERR(tve->ddc_conn);
++
+ 	tve->dev = dev;
+ 	spin_lock_init(&tve->lock);
+ 
+-	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+-	if (ddc_node) {
+-		tve->ddc = of_find_i2c_adapter_by_node(ddc_node);
+-		of_node_put(ddc_node);
+-	}
+-
+ 	tve->mode = of_get_tve_mode(np);
+ 	if (tve->mode != TVE_MODE_VGA) {
+ 		dev_err(dev, "only VGA mode supported, currently\n");
+@@ -694,7 +657,7 @@ static void imx_tve_unbind(struct device *dev, struct device *master,
+ {
+ 	struct imx_tve *tve = dev_get_drvdata(dev);
+ 
+-	tve->connector.funcs->destroy(&tve->connector);
++	tve->ddc_conn->connector.funcs->destroy(&tve->ddc_conn->connector);
+ 	tve->encoder.funcs->destroy(&tve->encoder);
+ 
+ 	if (!IS_ERR(tve->dac_reg))
+diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+index c4d14ead5837..c2c6fab05eaa 100644
+--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
++++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+@@ -76,6 +76,7 @@ enum ipu_channel_irq {
+ 	IPU_IRQ_EOS = 192,
+ };
+ 
++int ipu_map_irq(struct ipu_soc *ipu, int irq);
+ int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+ 		enum ipu_channel_irq irq);
+ 
+@@ -114,8 +115,10 @@ struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
+ void ipu_dc_put(struct ipu_dc *dc);
+ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+ 		u32 pixel_fmt, u32 width);
++void ipu_dc_enable(struct ipu_soc *ipu);
+ void ipu_dc_enable_channel(struct ipu_dc *dc);
+ void ipu_dc_disable_channel(struct ipu_dc *dc);
++void ipu_dc_disable(struct ipu_soc *ipu);
+ 
+ /*
+  * IPU Display Interface (di) functions
+@@ -152,8 +155,10 @@ void ipu_dmfc_put(struct dmfc_channel *dmfc);
+ 
+ struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
+ void ipu_dp_put(struct ipu_dp *);
++int ipu_dp_enable(struct ipu_soc *ipu);
+ int ipu_dp_enable_channel(struct ipu_dp *dp);
+ void ipu_dp_disable_channel(struct ipu_dp *dp);
++void ipu_dp_disable(struct ipu_soc *ipu);
+ int ipu_dp_setup_channel(struct ipu_dp *dp,
+ 		enum ipu_color_space in, enum ipu_color_space out);
+ int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+index ca85d3d70ae3..8fb4c207f3f1 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+@@ -697,6 +697,12 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
+ }
+ EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
+ 
++bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno)
++{
++	return (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(chno)) & idma_mask(chno));
++}
++EXPORT_SYMBOL_GPL(ipu_idmac_channel_busy);
++
+ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
+ {
+ 	struct ipu_soc *ipu = channel->ipu;
+@@ -714,6 +720,22 @@ int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
+ }
+ EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
+ 
++int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms)
++{
++	unsigned long timeout;
++
++	timeout = jiffies + msecs_to_jiffies(ms);
++	ipu_cm_write(ipu, BIT(irq % 32), IPU_INT_STAT(irq / 32));
++	while (!(ipu_cm_read(ipu, IPU_INT_STAT(irq / 32) & BIT(irq % 32)))) {
++		if (time_after(jiffies, timeout))
++			return -ETIMEDOUT;
++		cpu_relax();
++	}
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(ipu_wait_interrupt);
++
+ int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
+ {
+ 	struct ipu_soc *ipu = channel->ipu;
+@@ -933,15 +955,22 @@ static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
+ 	chained_irq_exit(chip, desc);
+ }
+ 
+-int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+-		enum ipu_channel_irq irq_type)
++int ipu_map_irq(struct ipu_soc *ipu, int irq)
+ {
+-	int irq = irq_linear_revmap(ipu->domain, irq_type + channel->num);
++	int virq;
+ 
+-	if (!irq)
+-		irq = irq_create_mapping(ipu->domain, irq_type + channel->num);
++	virq = irq_linear_revmap(ipu->domain, irq);
++	if (!virq)
++		virq = irq_create_mapping(ipu->domain, irq);
+ 
+-	return irq;
++	return virq;
++}
++EXPORT_SYMBOL_GPL(ipu_map_irq);
++
++int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
++		enum ipu_channel_irq irq_type)
++{
++	return ipu_map_irq(ipu, irq_type + channel->num);
+ }
+ EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
+ 
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+index d5de8bb5c803..97cf6fad2427 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+@@ -18,6 +18,7 @@
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/delay.h>
++#include <linux/interrupt.h>
+ #include <linux/io.h>
+ 
+ #include "../imx-drm.h"
+@@ -92,6 +93,7 @@ enum ipu_dc_map {
+ 	IPU_DC_MAP_GBR24, /* TVEv2 */
+ 	IPU_DC_MAP_BGR666,
+ 	IPU_DC_MAP_BGR24,
++	IPU_DC_MAP_RGB666,
+ };
+ 
+ struct ipu_dc {
+@@ -110,6 +112,9 @@ struct ipu_dc_priv {
+ 	struct device		*dev;
+ 	struct ipu_dc		channels[IPU_DC_NUM_CHANNELS];
+ 	struct mutex		mutex;
++	struct completion	comp;
++	int			dc_irq;
++	int			dp_irq;
+ };
+ 
+ static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
+@@ -155,6 +160,8 @@ static int ipu_pixfmt_to_map(u32 fmt)
+ 		return IPU_DC_MAP_BGR666;
+ 	case V4L2_PIX_FMT_BGR24:
+ 		return IPU_DC_MAP_BGR24;
++	case V4L2_PIX_FMT_RGB666:
++		return IPU_DC_MAP_RGB666;
+ 	default:
+ 		return -EINVAL;
+ 	}
+@@ -220,12 +227,16 @@ int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+ 	writel(0x0, dc->base + DC_WR_CH_ADDR);
+ 	writel(width, priv->dc_reg + DC_DISP_CONF2(dc->di));
+ 
+-	ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
+-
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
+ 
++void ipu_dc_enable(struct ipu_soc *ipu)
++{
++	ipu_module_enable(ipu, IPU_CONF_DC_EN);
++}
++EXPORT_SYMBOL_GPL(ipu_dc_enable);
++
+ void ipu_dc_enable_channel(struct ipu_dc *dc)
+ {
+ 	int di;
+@@ -239,41 +250,55 @@ void ipu_dc_enable_channel(struct ipu_dc *dc)
+ }
+ EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
+ 
++static irqreturn_t dc_irq_handler(int irq, void *dev_id)
++{
++	struct ipu_dc *dc = dev_id;
++	u32 reg;
++
++	reg = readl(dc->base + DC_WR_CH_CONF);
++	reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
++	writel(reg, dc->base + DC_WR_CH_CONF);
++
++	/* The Freescale BSP kernel clears DIx_COUNTER_RELEASE here */
++
++	complete(&dc->priv->comp);
++	return IRQ_HANDLED;
++}
++
+ void ipu_dc_disable_channel(struct ipu_dc *dc)
+ {
+ 	struct ipu_dc_priv *priv = dc->priv;
++	int irq, ret;
+ 	u32 val;
+-	int irq = 0, timeout = 50;
+ 
++	/* TODO: Handle MEM_FG_SYNC differently from MEM_BG_SYNC */
+ 	if (dc->chno == 1)
+-		irq = IPU_IRQ_DC_FC_1;
++		irq = priv->dc_irq;
+ 	else if (dc->chno == 5)
+-		irq = IPU_IRQ_DP_SF_END;
++		irq = priv->dp_irq;
+ 	else
+ 		return;
+ 
+-	/* should wait for the interrupt here */
+-	mdelay(50);
++	init_completion(&priv->comp);
++	enable_irq(irq);
++	ret = wait_for_completion_timeout(&priv->comp, msecs_to_jiffies(50));
++	disable_irq(irq);
++	if (ret <= 0) {
++		dev_warn(priv->dev, "DC stop timeout after 50 ms\n");
+ 
+-	if (dc->di == 0)
+-		val = 0x00000002;
+-	else
+-		val = 0x00000020;
+-
+-	/* Wait for DC triple buffer to empty */
+-	while ((readl(priv->dc_reg + DC_STAT) & val) != val) {
+-		usleep_range(2000, 20000);
+-		timeout -= 2;
+-		if (timeout <= 0)
+-			break;
++		val = readl(dc->base + DC_WR_CH_CONF);
++		val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
++		writel(val, dc->base + DC_WR_CH_CONF);
+ 	}
+-
+-	val = readl(dc->base + DC_WR_CH_CONF);
+-	val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+-	writel(val, dc->base + DC_WR_CH_CONF);
+ }
+ EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
+ 
++void ipu_dc_disable(struct ipu_soc *ipu)
++{
++	ipu_module_disable(ipu, IPU_CONF_DC_EN);
++}
++EXPORT_SYMBOL_GPL(ipu_dc_disable);
++
+ static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
+ 		int byte_num, int offset, int mask)
+ {
+@@ -340,7 +365,7 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
+ 	struct ipu_dc_priv *priv;
+ 	static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
+ 		0x78, 0, 0x94, 0xb4};
+-	int i;
++	int i, ret;
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv)
+@@ -361,6 +386,23 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
+ 		priv->channels[i].base = priv->dc_reg + channel_offsets[i];
+ 	}
+ 
++	priv->dc_irq = ipu_map_irq(ipu, IPU_IRQ_DC_FC_1);
++	if (!priv->dc_irq)
++		return -EINVAL;
++	ret = devm_request_irq(dev, priv->dc_irq, dc_irq_handler, 0, NULL,
++			       &priv->channels[1]);
++	if (ret < 0)
++		return ret;
++	disable_irq(priv->dc_irq);
++	priv->dp_irq = ipu_map_irq(ipu, IPU_IRQ_DP_SF_END);
++	if (!priv->dp_irq)
++		return -EINVAL;
++	ret = devm_request_irq(dev, priv->dp_irq, dc_irq_handler, 0, NULL,
++			       &priv->channels[5]);
++	if (ret < 0)
++		return ret;
++	disable_irq(priv->dp_irq);
++
+ 	writel(DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
+ 			DC_WR_CH_CONF_PROG_DI_ID,
+ 			priv->channels[1].base + DC_WR_CH_CONF);
+@@ -404,6 +446,12 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev,
+ 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
+ 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
+ 
++	/* rgb666 */
++	ipu_dc_map_clear(priv, IPU_DC_MAP_RGB666);
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 0, 5, 0xfc); /* blue */
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 1, 11, 0xfc); /* green */
++	ipu_dc_map_config(priv, IPU_DC_MAP_RGB666, 2, 17, 0xfc); /* red */
++
+ 	return 0;
+ }
+ 
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-di.c b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+index 82a9ebad697c..849b3e120ef0 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-di.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-di.c
+@@ -595,7 +595,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
+ 		}
+ 	}
+ 
+-	if (!sig->clk_pol)
++	if (sig->clk_pol)
+ 		di_gen |= DI_GEN_POLARITY_DISP_CLK;
+ 
+ 	ipu_di_write(di, di_gen, DI_GENERAL);
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+index 45213017fa4b..59f182b28fc1 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+@@ -28,7 +28,12 @@
+ #define DMFC_GENERAL1		0x0014
+ #define DMFC_GENERAL2		0x0018
+ #define DMFC_IC_CTRL		0x001c
+-#define DMFC_STAT		0x0020
++#define DMFC_WR_CHAN_ALT	0x0020
++#define DMFC_WR_CHAN_DEF_ALT	0x0024
++#define DMFC_DP_CHAN_ALT	0x0028
++#define DMFC_DP_CHAN_DEF_ALT	0x002c
++#define DMFC_GENERAL1_ALT	0x0030
++#define DMFC_STAT		0x0034
+ 
+ #define DMFC_WR_CHAN_1_28		0
+ #define DMFC_WR_CHAN_2_41		8
+@@ -133,6 +138,20 @@ int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
+ }
+ EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
+ 
++static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
++{
++	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
++
++	while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
++		if (time_after(jiffies, timeout)) {
++			dev_warn(priv->dev,
++				 "Timeout waiting for DMFC FIFOs to clear\n");
++			break;
++		}
++		cpu_relax();
++	}
++}
++
+ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
+ {
+ 	struct ipu_dmfc_priv *priv = dmfc->priv;
+@@ -141,8 +160,10 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
+ 
+ 	priv->use_count--;
+ 
+-	if (!priv->use_count)
++	if (!priv->use_count) {
++		ipu_dmfc_wait_fifos(priv);
+ 		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
++	}
+ 
+ 	if (priv->use_count < 0)
+ 		priv->use_count = 0;
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+index 58f87c8d7c07..d90f82a87d19 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+@@ -215,10 +215,9 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
+ }
+ EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
+ 
+-int ipu_dp_enable_channel(struct ipu_dp *dp)
++int ipu_dp_enable(struct ipu_soc *ipu)
+ {
+-	struct ipu_flow *flow = to_flow(dp);
+-	struct ipu_dp_priv *priv = flow->priv;
++	struct ipu_dp_priv *priv = ipu->dp_priv;
+ 
+ 	mutex_lock(&priv->mutex);
+ 
+@@ -227,15 +226,28 @@ int ipu_dp_enable_channel(struct ipu_dp *dp)
+ 
+ 	priv->use_count++;
+ 
+-	if (dp->foreground) {
+-		u32 reg;
++	mutex_unlock(&priv->mutex);
+ 
+-		reg = readl(flow->base + DP_COM_CONF);
+-		reg |= DP_COM_CONF_FG_EN;
+-		writel(reg, flow->base + DP_COM_CONF);
++	return 0;
++}
++EXPORT_SYMBOL_GPL(ipu_dp_enable);
+ 
+-		ipu_srm_dp_sync_update(priv->ipu);
+-	}
++int ipu_dp_enable_channel(struct ipu_dp *dp)
++{
++	struct ipu_flow *flow = to_flow(dp);
++	struct ipu_dp_priv *priv = flow->priv;
++	u32 reg;
++
++	if (!dp->foreground)
++		return 0;
++
++	mutex_lock(&priv->mutex);
++
++	reg = readl(flow->base + DP_COM_CONF);
++	reg |= DP_COM_CONF_FG_EN;
++	writel(reg, flow->base + DP_COM_CONF);
++
++	ipu_srm_dp_sync_update(priv->ipu);
+ 
+ 	mutex_unlock(&priv->mutex);
+ 
+@@ -247,25 +259,38 @@ void ipu_dp_disable_channel(struct ipu_dp *dp)
+ {
+ 	struct ipu_flow *flow = to_flow(dp);
+ 	struct ipu_dp_priv *priv = flow->priv;
++	u32 reg, csc;
++
++	if (!dp->foreground)
++		return;
+ 
+ 	mutex_lock(&priv->mutex);
+ 
+-	priv->use_count--;
++	reg = readl(flow->base + DP_COM_CONF);
++	csc = reg & DP_COM_CONF_CSC_DEF_MASK;
++	if (csc == DP_COM_CONF_CSC_DEF_FG)
++		reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+ 
+-	if (dp->foreground) {
+-		u32 reg, csc;
++	reg &= ~DP_COM_CONF_FG_EN;
++	writel(reg, flow->base + DP_COM_CONF);
+ 
+-		reg = readl(flow->base + DP_COM_CONF);
+-		csc = reg & DP_COM_CONF_CSC_DEF_MASK;
+-		if (csc == DP_COM_CONF_CSC_DEF_FG)
+-			reg &= ~DP_COM_CONF_CSC_DEF_MASK;
++	writel(0, flow->base + DP_FG_POS);
++	ipu_srm_dp_sync_update(priv->ipu);
+ 
+-		reg &= ~DP_COM_CONF_FG_EN;
+-		writel(reg, flow->base + DP_COM_CONF);
++	if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC))
++		ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50);
+ 
+-		writel(0, flow->base + DP_FG_POS);
+-		ipu_srm_dp_sync_update(priv->ipu);
+-	}
++	mutex_unlock(&priv->mutex);
++}
++EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
++
++void ipu_dp_disable(struct ipu_soc *ipu)
++{
++	struct ipu_dp_priv *priv = ipu->dp_priv;
++
++	mutex_lock(&priv->mutex);
++
++	priv->use_count--;
+ 
+ 	if (!priv->use_count)
+ 		ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
+@@ -275,7 +300,7 @@ void ipu_dp_disable_channel(struct ipu_dp *dp)
+ 
+ 	mutex_unlock(&priv->mutex);
+ }
+-EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
++EXPORT_SYMBOL_GPL(ipu_dp_disable);
+ 
+ struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
+ {
+diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
+index 4df00501adc2..bfc1b3366488 100644
+--- a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
++++ b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h
+@@ -185,6 +185,9 @@ void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
+ int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
+ int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
+ 
++bool ipu_idmac_channel_busy(struct ipu_soc *ipu, unsigned int chno);
++int ipu_wait_interrupt(struct ipu_soc *ipu, int irq, int ms);
++
+ int ipu_di_init(struct ipu_soc *ipu, struct device *dev, int id,
+ 		unsigned long base, u32 module, struct clk *ipu_clk);
+ void ipu_di_exit(struct ipu_soc *ipu, int id);
+diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
+index c48f640db006..47bec5e17358 100644
+--- a/drivers/staging/imx-drm/ipuv3-crtc.c
++++ b/drivers/staging/imx-drm/ipuv3-crtc.c
+@@ -60,24 +60,32 @@ struct ipu_crtc {
+ 
+ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
+ {
++	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
++
+ 	if (ipu_crtc->enabled)
+ 		return;
+ 
+-	ipu_di_enable(ipu_crtc->di);
+-	ipu_dc_enable_channel(ipu_crtc->dc);
++	ipu_dc_enable(ipu);
+ 	ipu_plane_enable(ipu_crtc->plane[0]);
++	/* Start DC channel and DI after IDMAC */
++	ipu_dc_enable_channel(ipu_crtc->dc);
++	ipu_di_enable(ipu_crtc->di);
+ 
+ 	ipu_crtc->enabled = 1;
+ }
+ 
+ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
+ {
++	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
++
+ 	if (!ipu_crtc->enabled)
+ 		return;
+ 
+-	ipu_plane_disable(ipu_crtc->plane[0]);
++	/* Stop DC channel and DI before IDMAC */
+ 	ipu_dc_disable_channel(ipu_crtc->dc);
+ 	ipu_di_disable(ipu_crtc->di);
++	ipu_plane_disable(ipu_crtc->plane[0]);
++	ipu_dc_disable(ipu);
+ 
+ 	ipu_crtc->enabled = 0;
+ }
+@@ -158,7 +166,7 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
+ 		sig_cfg.Vsync_pol = 1;
+ 
+ 	sig_cfg.enable_pol = 1;
+-	sig_cfg.clk_pol = 1;
++	sig_cfg.clk_pol = 0;
+ 	sig_cfg.width = mode->hdisplay;
+ 	sig_cfg.height = mode->vdisplay;
+ 	sig_cfg.pixel_fmt = out_pixel_fmt;
+diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
+index 27a8d735dae0..5697e59ddf1d 100644
+--- a/drivers/staging/imx-drm/ipuv3-plane.c
++++ b/drivers/staging/imx-drm/ipuv3-plane.c
+@@ -239,6 +239,8 @@ int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+ 
+ void ipu_plane_enable(struct ipu_plane *ipu_plane)
+ {
++	if (ipu_plane->dp)
++		ipu_dp_enable(ipu_plane->ipu);
+ 	ipu_dmfc_enable_channel(ipu_plane->dmfc);
+ 	ipu_idmac_enable_channel(ipu_plane->ipu_ch);
+ 	if (ipu_plane->dp)
+@@ -257,6 +259,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
+ 		ipu_dp_disable_channel(ipu_plane->dp);
+ 	ipu_idmac_disable_channel(ipu_plane->ipu_ch);
+ 	ipu_dmfc_disable_channel(ipu_plane->dmfc);
++	if (ipu_plane->dp)
++		ipu_dp_disable(ipu_plane->ipu);
+ }
+ 
+ static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
+diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
+index c60b6c645f42..01b7ce50fc30 100644
+--- a/drivers/staging/imx-drm/parallel-display.c
++++ b/drivers/staging/imx-drm/parallel-display.c
+@@ -219,6 +219,8 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
+ 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
+ 		else if (!strcmp(fmt, "bgr666"))
+ 			imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
++		else if (!strcmp(fmt, "rgb666"))
++			imxpd->interface_pix_fmt = V4L2_PIX_FMT_RGB666;
+ 	}
+ 
+ 	panel_node = of_parse_phandle(np, "fsl,panel", 0);
+diff --git a/include/linux/cec-dev.h b/include/linux/cec-dev.h
+new file mode 100644
+index 000000000000..76a7d7f6a72d
+--- /dev/null
++++ b/include/linux/cec-dev.h
+@@ -0,0 +1,69 @@
++#ifndef _LINUX_CEC_DEV_H
++#define _LINUX_CEC_DEV_H
++
++#include <linux/cdev.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
++
++#include <uapi/linux/cec-dev.h>
++
++struct device;
++
++struct cec_dev {
++	struct cdev cdev;
++	dev_t devn;
++
++	struct mutex mutex;
++	unsigned users;
++
++	spinlock_t lock;
++	wait_queue_head_t waitq;
++	struct list_head events;
++	u8 write_busy;
++
++	u8 retries;
++	u16 addresses;
++	u16 physical;
++
++	int (*open)(struct cec_dev *);
++	void (*release)(struct cec_dev *);
++	void (*send_message)(struct cec_dev *, u8 *, size_t);
++	void (*set_address)(struct cec_dev *, unsigned);
++};
++
++void cec_dev_event(struct cec_dev *cec_dev, int type, u8 *msg, size_t len);
++
++static inline void cec_dev_receive(struct cec_dev *cec_dev, u8 *msg,
++	unsigned len)
++{
++	cec_dev_event(cec_dev, MESSAGE_TYPE_RECEIVE_SUCCESS, msg, len);
++}
++
++static inline void cec_dev_send_complete(struct cec_dev *cec_dev, int ack)
++{
++	cec_dev->retries = 0;
++	cec_dev->write_busy = 0;
++
++	cec_dev_event(cec_dev, ack ? MESSAGE_TYPE_SEND_SUCCESS :
++		      MESSAGE_TYPE_NOACK, NULL, 0);
++}
++
++static inline void cec_dev_disconnect(struct cec_dev *cec_dev)
++{
++	cec_dev->physical = 0;
++	cec_dev_event(cec_dev, MESSAGE_TYPE_DISCONNECTED, NULL, 0);
++}
++
++static inline void cec_dev_connect(struct cec_dev *cec_dev, u32 phys)
++{
++	cec_dev->physical = phys;
++	cec_dev_event(cec_dev, MESSAGE_TYPE_CONNECTED, NULL, 0);
++}
++
++void cec_dev_init(struct cec_dev *cec_dev, struct module *);
++int cec_dev_add(struct cec_dev *cec_dev, struct device *, const char *name);
++void cec_dev_remove(struct cec_dev *cec_dev);
++
++#endif
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+index cb61ea4d6945..2fdfe30295d5 100644
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -278,6 +278,7 @@ struct mmc_host {
+ #define MMC_CAP2_PACKED_CMD	(MMC_CAP2_PACKED_RD | \
+ 				 MMC_CAP2_PACKED_WR)
+ #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)	/* Don't power up before scan */
++#define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 15)
+ 
+ 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
+ 
+@@ -293,6 +294,11 @@ struct mmc_host {
+ 	unsigned long           clkgate_delay;
+ #endif
+ 
++	/* card specific properties to deal with power and reset */
++	struct regulator	*card_regulator; /* External VCC needed by the card */
++	struct gpio_desc	*card_reset_gpios[2]; /* External resets, active low */
++	struct clk		*card_clk;	/* External clock needed by the card */
++
+ 	/* host specific block data */
+ 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
+ 	unsigned short		max_segs;	/* see blk_queue_max_segments */
+@@ -391,6 +397,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
+ 	wake_up_process(host->sdio_irq_thread);
+ }
+ 
++void sdio_run_irqs(struct mmc_host *host);
++
+ #ifdef CONFIG_REGULATOR
+ int mmc_regulator_get_ocrmask(struct regulator *supply);
+ int mmc_regulator_set_ocr(struct mmc_host *mmc,
+diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
+index 7be12b883485..08abe9941884 100644
+--- a/include/linux/mmc/sdhci.h
++++ b/include/linux/mmc/sdhci.h
+@@ -57,12 +57,8 @@ struct sdhci_host {
+ #define SDHCI_QUIRK_BROKEN_CARD_DETECTION		(1<<15)
+ /* Controller reports inverted write-protect state */
+ #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT		(1<<16)
+-/* Controller has nonstandard clock management */
+-#define SDHCI_QUIRK_NONSTANDARD_CLOCK			(1<<17)
+ /* Controller does not like fast PIO transfers */
+ #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)
+-/* Controller losing signal/interrupt enable states after reset */
+-#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET		(1<<19)
+ /* Controller has to be forced to use block size of 2048 bytes */
+ #define SDHCI_QUIRK_FORCE_BLK_SZ_2048			(1<<20)
+ /* Controller cannot do multi-block transfers */
+@@ -147,6 +143,7 @@ struct sdhci_host {
+ 
+ 	bool runtime_suspended;	/* Host is runtime suspended */
+ 	bool bus_on;		/* Bus power prevents runtime suspend */
++	bool preset_enabled;	/* Preset is enabled */
+ 
+ 	struct mmc_request *mrq;	/* Current request */
+ 	struct mmc_command *cmd;	/* Current command */
+@@ -164,8 +161,7 @@ struct sdhci_host {
+ 	dma_addr_t adma_addr;	/* Mapped ADMA descr. table */
+ 	dma_addr_t align_addr;	/* Mapped bounce buffer */
+ 
+-	struct tasklet_struct card_tasklet;	/* Tasklet structures */
+-	struct tasklet_struct finish_tasklet;
++	struct tasklet_struct finish_tasklet;	/* Tasklet structures */
+ 
+ 	struct timer_list timer;	/* Timer for timeouts */
+ 
+@@ -177,6 +173,13 @@ struct sdhci_host {
+ 	unsigned int            ocr_avail_mmc;
+ 	u32 ocr_mask;		/* available voltages */
+ 
++	unsigned		timing;		/* Current timing */
++
++	u32			thread_isr;
++
++	/* cached registers */
++	u32			ier;
++
+ 	wait_queue_head_t	buf_ready_int;	/* Waitqueue for Buffer Read Ready interrupt */
+ 	unsigned int		tuning_done;	/* Condition flag set when CMD19 succeeds */
+ 
+diff --git a/include/uapi/linux/cec-dev.h b/include/uapi/linux/cec-dev.h
+new file mode 100644
+index 000000000000..fb7a41704c77
+--- /dev/null
++++ b/include/uapi/linux/cec-dev.h
+@@ -0,0 +1,34 @@
++#ifndef _UAPI_LINUX_CEC_DEV_H
++#define _UAPI_LINUX_CEC_DEV_H
++
++#include <linux/ioctl.h>
++#include <linux/types.h>
++
++#define MAX_MESSAGE_LEN 16
++
++enum {
++	HDMICEC_IOC_MAGIC = 'H',
++	/* This is wrong: we pass the argument as a number, not a pointer */
++	HDMICEC_IOC_O_SETLOGICALADDRESS	= _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char),
++	HDMICEC_IOC_SETLOGICALADDRESS	= _IO(HDMICEC_IOC_MAGIC, 1),
++	HDMICEC_IOC_STARTDEVICE		= _IO(HDMICEC_IOC_MAGIC, 2),
++	HDMICEC_IOC_STOPDEVICE		= _IO(HDMICEC_IOC_MAGIC, 3),
++	HDMICEC_IOC_GETPHYADDRESS	= _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4]),
++};
++
++enum {
++	MESSAGE_TYPE_RECEIVE_SUCCESS = 1,
++	MESSAGE_TYPE_NOACK,
++	MESSAGE_TYPE_DISCONNECTED,
++	MESSAGE_TYPE_CONNECTED,
++	MESSAGE_TYPE_SEND_SUCCESS,
++	MESSAGE_TYPE_SEND_ERROR,
++};
++
++struct cec_user_event {
++	__u32 event_type;
++	__u32 msg_len;
++	__u8 msg[MAX_MESSAGE_LEN];
++};
++
++#endif
+diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
+index ea468ee8fe21..d5d818a86676 100644
+--- a/include/uapi/linux/videodev2.h
++++ b/include/uapi/linux/videodev2.h
+@@ -299,6 +299,7 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
+ #define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
+ #define V4L2_PIX_FMT_BGR666  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6	  */
++#define V4L2_PIX_FMT_RGB666  v4l2_fourcc('R', 'G', 'B', 'H') /* 18  RGB-6-6-6	  */
+ #define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
+ #define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
+ #define V4L2_PIX_FMT_BGR32   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
+diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
+index 2585ae44e634..a86d84854c7f 100644
+--- a/sound/soc/fsl/imx-pcm-dma.c
++++ b/sound/soc/fsl/imx-pcm-dma.c
+@@ -44,7 +44,7 @@ static const struct snd_pcm_hardware imx_pcm_hardware = {
+ 	.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
+ 	.period_bytes_min = 128,
+ 	.period_bytes_max = 65535, /* Limited by SDMA engine */
+-	.periods_min = 2,
++	.periods_min = 4,
+ 	.periods_max = 255,
+ 	.fifo_size = 0,
+ };

+ 0 - 0
target/arm/cubox-i/patches/3.15-rc7/sdma-firmware-cubox-i.patch → target/arm/cubox-i/patches/3.15/sdma-firmware-cubox-i.patch


+ 2 - 2
target/config/Config.in.kernelversion.choice

@@ -6,8 +6,8 @@ prompt "Kernel Version"
 depends on !ADK_CHOOSE_TARGET_ARCH && !ADK_CHOOSE_TARGET_SYSTEM && ADK_TARGET_KERNEL_CUSTOMISING
 default ADK_KERNEL_VERSION_3_14_5
 
-config ADK_KERNEL_VERSION_3_15_RC7
-	prompt "3.15-rc7"
+config ADK_KERNEL_VERSION_3_15_0
+	prompt "3.15"
 	boolean
 	select ADK_KERNEL_VERSION_3_15
 

+ 1 - 1
target/config/Config.in.kernelversion.default

@@ -18,7 +18,7 @@ config ADK_KERNEL_VERSION_3_4
 
 config ADK_KERNEL_VERSION
 	string
-	default "3.15-rc7" if ADK_KERNEL_VERSION_3_15_RC7
+	default "3.15" if ADK_KERNEL_VERSION_3_15
 	default "3.14.5" if ADK_KERNEL_VERSION_3_14_5
 	default "3.12.20" if ADK_KERNEL_VERSION_3_12_20
 	default "3.10.40" if ADK_KERNEL_VERSION_3_10_40

+ 0 - 0
target/linux/patches/3.15-rc7/bsd-compatibility.patch → target/linux/patches/3.15-rc8/bsd-compatibility.patch


+ 0 - 0
target/linux/patches/3.15-rc7/cleankernel.patch → target/linux/patches/3.15-rc8/cleankernel.patch


+ 0 - 0
target/linux/patches/3.15-rc7/defaults.patch → target/linux/patches/3.15-rc8/defaults.patch


+ 0 - 0
target/linux/patches/3.15-rc7/disable-netfilter.patch → target/linux/patches/3.15-rc8/disable-netfilter.patch


+ 0 - 0
target/linux/patches/3.15-rc7/export-symbol-for-exmap.patch → target/linux/patches/3.15-rc8/export-symbol-for-exmap.patch


+ 0 - 0
target/linux/patches/3.15-rc7/gemalto.patch → target/linux/patches/3.15-rc8/gemalto.patch


+ 0 - 0
target/linux/patches/3.15-rc7/initramfs-nosizelimit.patch → target/linux/patches/3.15-rc8/initramfs-nosizelimit.patch


+ 0 - 0
target/linux/patches/3.15-rc7/lemote-rfkill.patch → target/linux/patches/3.15-rc8/lemote-rfkill.patch


+ 0 - 0
target/linux/patches/3.15-rc7/microblaze-axi.patch → target/linux/patches/3.15-rc8/microblaze-axi.patch


+ 0 - 0
target/linux/patches/3.15-rc7/microblaze-ethernet.patch → target/linux/patches/3.15-rc8/microblaze-ethernet.patch


+ 0 - 0
target/linux/patches/3.15-rc7/mkpiggy.patch → target/linux/patches/3.15-rc8/mkpiggy.patch


+ 0 - 0
target/linux/patches/3.15-rc7/mtd-rootfs.patch → target/linux/patches/3.15-rc8/mtd-rootfs.patch


+ 0 - 0
target/linux/patches/3.15-rc7/nfsv3-tcp.patch → target/linux/patches/3.15-rc8/nfsv3-tcp.patch


+ 0 - 0
target/linux/patches/3.15-rc7/non-static.patch → target/linux/patches/3.15-rc8/non-static.patch


+ 0 - 0
target/linux/patches/3.15-rc7/patch-yaffs2 → target/linux/patches/3.15-rc8/patch-yaffs2


+ 0 - 0
target/linux/patches/3.15-rc7/ppc64-missing-zlib.patch → target/linux/patches/3.15-rc8/ppc64-missing-zlib.patch


+ 0 - 0
target/linux/patches/3.15-rc7/relocs.patch → target/linux/patches/3.15-rc8/relocs.patch


+ 0 - 0
target/linux/patches/3.15-rc7/sgidefs.patch → target/linux/patches/3.15-rc8/sgidefs.patch


+ 0 - 0
target/linux/patches/3.15-rc7/sortext.patch → target/linux/patches/3.15-rc8/sortext.patch


+ 0 - 0
target/linux/patches/3.15-rc7/startup.patch → target/linux/patches/3.15-rc8/startup.patch


+ 0 - 0
target/linux/patches/3.15-rc7/tcp-fastopen.patch → target/linux/patches/3.15-rc8/tcp-fastopen.patch


+ 0 - 0
target/linux/patches/3.15-rc7/uuid.patch → target/linux/patches/3.15-rc8/uuid.patch


+ 0 - 0
target/linux/patches/3.15-rc7/wlan-cf.patch → target/linux/patches/3.15-rc8/wlan-cf.patch


+ 0 - 0
target/linux/patches/3.15-rc7/xargs.patch → target/linux/patches/3.15-rc8/xargs.patch


+ 0 - 11
target/mips/mikrotik-rb532/patches/3.15-rc7/rb532-pci.patch

@@ -1,11 +0,0 @@
-diff -Nur linux-3.15-rc5.orig/arch/mips/pci/pci-rc32434.c linux-3.15-rc5/arch/mips/pci/pci-rc32434.c
---- linux-3.15-rc5.orig/arch/mips/pci/pci-rc32434.c	2014-05-09 22:10:52.000000000 +0200
-+++ linux-3.15-rc5/arch/mips/pci/pci-rc32434.c	2014-05-16 10:38:10.000000000 +0200
-@@ -53,7 +53,6 @@
- 	.start = 0x50000000,
- 	.end = 0x5FFFFFFF,
- 	.flags = IORESOURCE_MEM,
--	.parent = &rc32434_res_pci_mem1,
- 	.sibling = NULL,
- 	.child = &rc32434_res_pci_mem2
- };

+ 0 - 0
target/mips/mikrotik-rb532/patches/3.15-rc7/rb532-serial.patch → target/mips/mikrotik-rb532/patches/3.15-rc8/rb532-serial.patch