From 229b4a4437da2ea83d68f4ebd1d81a10c2a7e616 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 8 Jul 2014 12:29:18 +0200 Subject: remove rmk.patch, need refresh later --- target/arm/cubox-i/patches/3.15.4/rmk.patch | 6640 --------------------------- 1 file changed, 6640 deletions(-) delete mode 100644 target/arm/cubox-i/patches/3.15.4/rmk.patch (limited to 'target/arm') diff --git a/target/arm/cubox-i/patches/3.15.4/rmk.patch b/target/arm/cubox-i/patches/3.15.4/rmk.patch deleted file mode 100644 index 7ccbf3b4a..000000000 --- a/target/arm/cubox-i/patches/3.15.4/rmk.patch +++ /dev/null @@ -1,6640 +0,0 @@ - .../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 V4L2_COLORSPACE_SRGB. - - - -+ -+ V4L2_PIX_FMT_RGB666 -+ 'RGBH' -+ -+ r5 -+ r4 -+ r3 -+ r2 -+ r1 -+ r0 -+ g5 -+ g4 -+ -+ g3 -+ g2 -+ g1 -+ g0 -+ b5 -+ b4 -+ b3 -+ b2 -+ -+ b1 -+ b0 -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - V4L2_PIX_FMT_BGR24 - 'BGR3' -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 = ; - }; -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 = ; -+ }; -+ - pinctrl_cubox_i_spdif: cubox-i-spdif { - fsl,pins = ; - }; -@@ -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 = <®_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 -+/ { -+ 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 = ; - }; -+ -+ 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 = <®_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 = <®_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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 "); -+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 - #include - #include -+#include - #include - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -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 -+#include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include - -@@ -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 -+#include -+#include -+#include -+#include -+ -+#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 "); -+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 -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#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 "); -+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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 "); -+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 - #include - -+#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 - #include - #include -+#include - #include - #include - #include -@@ -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 - #include - #include --#include - #include - #include - #include -@@ -31,6 +30,7 @@ - #include - #include - -+#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 - #include - #include -+#include - #include - - #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 -+#include -+#include -+#include -+#include -+ -+#include -+ -+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 -+#include -+ -+#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, - }; -- cgit v1.2.3