From c900ee654e74c0b15a72e94b791c9f6ebe09d59b Mon Sep 17 00:00:00 2001
From: Lijun Pan <Lijun.Pan@freescale.com>
Date: Wed, 24 Feb 2016 13:04:31 -0600
Subject: [PATCH] NXP Layerscape: initial support patch

This patch provides NXP (Freescale) Layerscape SoC support for
the following drivers:
QORIQ-CLOCK
POWER RESET
SATA
USB
I2C
eSDHC/eMMC

Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
---
 SOURCES/NXP-Layerscape-support.patch | 7640 ++++++++++++++++++++++++++++++++++
 SOURCES/config-centos-sig            |   12 +
 SPECS/kernel-aarch64.spec            |    5 +
 3 files changed, 7657 insertions(+)
 create mode 100644 SOURCES/NXP-Layerscape-support.patch

diff --git a/SOURCES/NXP-Layerscape-support.patch b/SOURCES/NXP-Layerscape-support.patch
new file mode 100644
index 0000000..ffd62a3
--- /dev/null
+++ b/SOURCES/NXP-Layerscape-support.patch
@@ -0,0 +1,7640 @@
+From ddb8e078147f556b039b4b25e04d89529de8a0c4 Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Wed, 18 Nov 2015 22:53:54 -0600
+Subject: [PATCH 01/66] arm64: Use generic Layerscape SoC family naming
+
+Freescale will be a spinning-out a set of ARMv8 based SoCs which
+will be based on a similar overall SoC architecture. So, this patch
+converts the existing infrastructure in the arm64/dts, arm64/Kconfig
+and arm64/configs to use the generic convention ARCH_LAYERSCAPE
+in place of the more specific FSL_LS2085A, to save code duplication
+later-on.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ Documentation/devicetree/bindings/arm/fsl.txt |    4 ++--
+ arch/arm64/Kconfig                            |    6 +++---
+ arch/arm64/boot/dts/freescale/Makefile        |    2 +-
+ arch/arm64/configs/defconfig                  |    2 +-
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
+index 2a3ba73..744b4de 100644
+--- a/Documentation/devicetree/bindings/arm/fsl.txt
++++ b/Documentation/devicetree/bindings/arm/fsl.txt
+@@ -128,8 +128,8 @@ Example:
+ 		reg = <0x0 0x1ee0000 0x0 0x10000>;
+ 	};
+ 
+-Freescale LS2085A SoC Device Tree Bindings
+-------------------------------------------
++Freescale ARMv8 based Layerscape SoC family Device Tree Bindings
++----------------------------------------------------------------
+ 
+ LS2085A ARMv8 based Simulator model
+ Required root node properties:
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 318175f..0e33750 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -179,10 +179,10 @@ config ARCH_EXYNOS7
+ 	help
+ 	  This enables support for Samsung Exynos7 SoC family
+ 
+-config ARCH_FSL_LS2085A
+-	bool "Freescale LS2085A SOC"
++config ARCH_LAYERSCAPE
++	bool "ARMv8 based Freescale Layerscape SoC family"
+ 	help
+-	  This enables support for Freescale LS2085A SOC.
++	  This enables support for the Freescale Layerscape SoC family.
+ 
+ config ARCH_HISI
+ 	bool "Hisilicon SoC Family"
+diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
+index 4f2de3e7..fc6fca3c 100644
+--- a/arch/arm64/boot/dts/freescale/Makefile
++++ b/arch/arm64/boot/dts/freescale/Makefile
+@@ -1,4 +1,4 @@
+-dtb-$(CONFIG_ARCH_FSL_LS2085A) += fsl-ls2085a-simu.dtb
++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2085a-simu.dtb
+  
+ always		:= $(dtb-y)
+ subdir-y	:= $(dts-dirs)
+diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
+index 4e17e7e..fa6aa9f 100644
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -32,7 +32,7 @@ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_IOSCHED_DEADLINE is not set
+ CONFIG_ARCH_EXYNOS7=y
+-CONFIG_ARCH_FSL_LS2085A=y
++CONFIG_ARCH_LAYERSCAPE=y
+ CONFIG_ARCH_HISI=y
+ CONFIG_ARCH_MEDIATEK=y
+ CONFIG_ARCH_SEATTLE=y
+-- 
+1.7.9.5
+
+
+From 0e34e1f88e93ec00907a8eb684795f5795b079b7 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:51 +0530
+Subject: [PATCH 02/66] arm64: Rename FSL LS2085A SoC support code to LS2080A
+
+Freescale is renaming the LS2085A SoC to LS2080A. This patch
+addresses the same.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ Documentation/devicetree/bindings/arm/fsl.txt      |    4 ++--
+ arch/arm64/boot/dts/freescale/Makefile             |    2 +-
+ .../{fsl-ls2085a-simu.dts => fsl-ls2080a-simu.dts} |   10 +++++-----
+ .../{fsl-ls2085a.dtsi => fsl-ls2080a.dtsi}         |    6 +++---
+ 4 files changed, 11 insertions(+), 11 deletions(-)
+ rename arch/arm64/boot/dts/freescale/{fsl-ls2085a-simu.dts => fsl-ls2080a-simu.dts} (90%)
+ rename arch/arm64/boot/dts/freescale/{fsl-ls2085a.dtsi => fsl-ls2080a.dtsi} (97%)
+
+diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
+index 744b4de..53f229a 100644
+--- a/Documentation/devicetree/bindings/arm/fsl.txt
++++ b/Documentation/devicetree/bindings/arm/fsl.txt
+@@ -131,7 +131,7 @@ Example:
+ Freescale ARMv8 based Layerscape SoC family Device Tree Bindings
+ ----------------------------------------------------------------
+ 
+-LS2085A ARMv8 based Simulator model
++LS2080A ARMv8 based Simulator model
+ Required root node properties:
+-    - compatible = "fsl,ls2085a-simu", "fsl,ls2085a";
++    - compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
+ 
+diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
+index fc6fca3c..932001a 100644
+--- a/arch/arm64/boot/dts/freescale/Makefile
++++ b/arch/arm64/boot/dts/freescale/Makefile
+@@ -1,4 +1,4 @@
+-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2085a-simu.dtb
++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
+  
+ always		:= $(dtb-y)
+ subdir-y	:= $(dts-dirs)
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2085a-simu.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+similarity index 90%
+rename from arch/arm64/boot/dts/freescale/fsl-ls2085a-simu.dts
+rename to arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+index 82e2a6f..33d6d0c 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2085a-simu.dts
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+@@ -1,7 +1,7 @@
+ /*
+- * Device Tree file for Freescale LS2085a software Simulator model
++ * Device Tree file for Freescale LS2080a software Simulator model
+  *
+- * Copyright (C) 2014, Freescale Semiconductor
++ * Copyright (C) 2014-2015, Freescale Semiconductor
+  *
+  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
+  *
+@@ -51,11 +51,11 @@
+ 
+ /dts-v1/;
+ 
+-/include/ "fsl-ls2085a.dtsi"
++/include/ "fsl-ls2080a.dtsi"
+ 
+ / {
+-	model = "Freescale Layerscape 2085a software Simulator model";
+-	compatible = "fsl,ls2085a-simu", "fsl,ls2085a";
++	model = "Freescale Layerscape 2080a software Simulator model";
++	compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
+ 
+ 	ethernet@2210000 {
+ 		compatible = "smsc,lan91c111";
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2085a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+similarity index 97%
+rename from arch/arm64/boot/dts/freescale/fsl-ls2085a.dtsi
+rename to arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index e281ceb..9597edf 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2085a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -1,7 +1,7 @@
+ /*
+- * Device Tree Include file for Freescale Layerscape-2085A family SoC.
++ * Device Tree Include file for Freescale Layerscape-2080A family SoC.
+  *
+- * Copyright (C) 2014, Freescale Semiconductor
++ * Copyright (C) 2014-2015, Freescale Semiconductor
+  *
+  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
+  *
+@@ -50,7 +50,7 @@
+  */
+ 
+ / {
+-	compatible = "fsl,ls2085a";
++	compatible = "fsl,ls2080a";
+ 	interrupt-parent = <&gic>;
+ 	#address-cells = <2>;
+ 	#size-cells = <2>;
+-- 
+1.7.9.5
+
+
+From 44809e377108b7b9d172fc05e0715ae831598365 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:52 +0530
+Subject: [PATCH 03/66] Documentation: DT: Add entry for FSL LS2080A QDS and
+ RDB boards
+
+This patch adds a devicetree binding documentation for Freescale's
+LS2080A QDS and RDB boards.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ Documentation/devicetree/bindings/arm/fsl.txt |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt
+index 53f229a..34c88b0 100644
+--- a/Documentation/devicetree/bindings/arm/fsl.txt
++++ b/Documentation/devicetree/bindings/arm/fsl.txt
+@@ -135,3 +135,11 @@ LS2080A ARMv8 based Simulator model
+ Required root node properties:
+     - compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
+ 
++LS2080A ARMv8 based QDS Board
++Required root node properties:
++    - compatible = "fsl,ls2080a-qds", "fsl,ls2080a";
++
++LS2080A ARMv8 based RDB Board
++Required root node properties:
++    - compatible = "fsl,ls2080a-rdb", "fsl,ls2080a";
++
+-- 
+1.7.9.5
+
+
+From f073c9ecf72ed1332d1186b8189c2516ef5a7313 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:53 +0530
+Subject: [PATCH 04/66] Documentation/dts: Move FSL board-specific bindings
+ out of /powerpc
+
+Since the same board components can be used across ARM and PPC board families,
+this patch moves the FSL board-specific bindings out of bindings/powerpci.
+
+While at it, this patch also adds the bindings for QIXIS FPGA controller
+found on FSL LS2080A boards. These boards have an on-board FPGA/CPLD
+connected to the IFC controller.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Jaiprakash Singh <b44839@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ .../{powerpc/fsl/board.txt => board/fsl-board.txt} |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+ rename Documentation/devicetree/bindings/{powerpc/fsl/board.txt => board/fsl-board.txt} (90%)
+
+diff --git a/Documentation/devicetree/bindings/powerpc/fsl/board.txt b/Documentation/devicetree/bindings/board/fsl-board.txt
+similarity index 90%
+rename from Documentation/devicetree/bindings/powerpc/fsl/board.txt
+rename to Documentation/devicetree/bindings/board/fsl-board.txt
+index cff38bd..fb7b03e 100644
+--- a/Documentation/devicetree/bindings/powerpc/fsl/board.txt
++++ b/Documentation/devicetree/bindings/board/fsl-board.txt
+@@ -21,11 +21,14 @@ Example:
+ 
+ This is the memory-mapped registers for on board FPGA.
+ 
+-Required properities:
++Required properties:
+ - compatible: should be a board-specific string followed by a string
+   indicating the type of FPGA.  Example:
+-	"fsl,<board>-fpga", "fsl,fpga-pixis"
++	"fsl,<board>-fpga", "fsl,fpga-pixis", or
++	"fsl,<board>-fpga", "fsl,fpga-qixis"
+ - reg: should contain the address and the length of the FPGA register set.
++
++Optional properties:
+ - interrupt-parent: should specify phandle for the interrupt controller.
+ - interrupts: should specify event (wakeup) IRQ.
+ 
+@@ -38,6 +41,13 @@ Example (P1022DS):
+ 		 interrupts = <8 8 0 0>;
+ 	 };
+ 
++Example (LS2080A-RDB):
++
++        cpld@3,0 {
++                compatible = "fsl,ls2080ardb-fpga", "fsl,fpga-qixis";
++                reg = <0x3 0 0x10000>;
++        };
++
+ * Freescale BCSR GPIO banks
+ 
+ Some BCSR registers act as simple GPIO controllers, each such
+-- 
+1.7.9.5
+
+
+From 43746209bd4adca49c595a30213b50382471dc5e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Thu, 16 Jul 2015 21:08:24 +0200
+Subject: [PATCH 05/66] dt-bindings: gpio: document bindings supported by
+ gpio-mpc8xxx.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ .../devicetree/bindings/gpio/gpio-mpc8xxx.txt      |   22 ++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+
+diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+new file mode 100644
+index 0000000..805ddcd
+--- /dev/null
++++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+@@ -0,0 +1,22 @@
++* Freescale MPC512x/MPC8xxx GPIO controller
++
++Required properties:
++- compatible : Should be "fsl,<soc>-gpio"
++  The following <soc>s are known to be supported:
++    mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq
++- reg : Address and length of the register set for the device
++- interrupts : Should be the port interrupt shared by all 32 pins.
++- #gpio-cells : Should be two.  The first cell is the pin number and
++  the second cell is used to specify the gpio polarity:
++      0 = active high
++      1 = active low
++
++Example:
++
++gpio0: gpio@1100 {
++	compatible = "fsl,mpc5125-gpio";
++	#gpio-cells = <2>;
++	reg = <0x1100 0x080>;
++	interrupts = <78 0x8>;
++	status = "okay";
++};
+-- 
+1.7.9.5
+
+
+From a96e77cda386bf7cf1c85980e4b5499e0223c105 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:55 +0530
+Subject: [PATCH 06/66] doc/bindings: Update GPIO devicetree binding
+ documentation for LS2080A
+
+Update the FSL, GPIO binding documentation to add support
+for GPIO controller found on Freescale's LS2080A platform.
+
+Signed-off-by: Liu Gang <Gang.Liu@freescale.com>
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ .../devicetree/bindings/gpio/gpio-mpc8xxx.txt      |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+index 805ddcd..f2455c5 100644
+--- a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
++++ b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
+@@ -1,9 +1,9 @@
+-* Freescale MPC512x/MPC8xxx GPIO controller
++* Freescale MPC512x/MPC8xxx/Layerscape GPIO controller
+ 
+ Required properties:
+ - compatible : Should be "fsl,<soc>-gpio"
+   The following <soc>s are known to be supported:
+-    mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq
++    mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq.
+ - reg : Address and length of the register set for the device
+ - interrupts : Should be the port interrupt shared by all 32 pins.
+ - #gpio-cells : Should be two.  The first cell is the pin number and
+-- 
+1.7.9.5
+
+
+From 3315a6864a74d72983e37c081db0cecf625eb6f2 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:56 +0530
+Subject: [PATCH 07/66] doc: DTS: Update DWC3 binding to provide reference to
+ generic bindings
+
+Since the Synopsys DWC3 controller driver inherits the generic bindings
+defined in 'usb/generic.txt', this patch tries to capture the same in
+the DWC3 binging documentation to avoid any confusion in usage of properties
+like 'dr_mode' for certain SoCs like FSL LS2080A.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ Documentation/devicetree/bindings/usb/dwc3.txt |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
+index 0815eac..9f64f69 100644
+--- a/Documentation/devicetree/bindings/usb/dwc3.txt
++++ b/Documentation/devicetree/bindings/usb/dwc3.txt
+@@ -1,6 +1,7 @@
+ synopsys DWC3 CORE
+ 
+-DWC3- USB3 CONTROLLER
++DWC3- USB3 CONTROLLER. Complies to the generic USB binding properties
++      as described in 'usb/generic.txt'
+ 
+ Required properties:
+  - compatible: must be "snps,dwc3"
+-- 
+1.7.9.5
+
+
+From 01ab58618d696b345075b376469b4b20eadfbc83 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:57 +0530
+Subject: [PATCH 08/66] dts/ls2080a: Update DTSI to add support of various
+ peripherals
+
+This patch updates the LS2080a DTSI (DTS Include) file to add
+support for the following peripherals:
+	- USB 3.0 Host
+	- PMU
+	- CCN-504
+	- SATA
+	- SPI
+	- PCIe
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Jaiprakash Singh <b44839@freescale.com>
+Signed-off-by: Alison Wang <alison.wang@freescale.com>
+Signed-off-by: Liu Gang <Gang.Liu@freescale.com>
+Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
+Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |  393 ++++++++++++++++++++++--
+ 1 file changed, 375 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index 9597edf..e52536e 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -71,48 +71,56 @@
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x0>;
++			clocks = <&clockgen 1 0>;
+ 		};
+ 
+ 		cpu@1 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x1>;
++			clocks = <&clockgen 1 0>;
+ 		};
+ 
+ 		cpu@100 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x100>;
++			clocks = <&clockgen 1 1>;
+ 		};
+ 
+ 		cpu@101 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x101>;
++			clocks = <&clockgen 1 1>;
+ 		};
+ 
+ 		cpu@200 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x200>;
++			clocks = <&clockgen 1 2>;
+ 		};
+ 
+ 		cpu@201 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x201>;
++			clocks = <&clockgen 1 2>;
+ 		};
+ 
+ 		cpu@300 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x300>;
++			clocks = <&clockgen 1 3>;
+ 		};
+ 
+ 		cpu@301 {
+ 			device_type = "cpu";
+ 			compatible = "arm,cortex-a57";
+ 			reg = <0x0 0x301>;
++			clocks = <&clockgen 1 3>;
+ 		};
+ 	};
+ 
+@@ -122,13 +130,32 @@
+ 		      /* DRAM space - 1, size : 2 GB DRAM */
+ 	};
+ 
++	sysclk: sysclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++		clock-output-names = "sysclk";
++	};
++
+ 	gic: interrupt-controller@6000000 {
+ 		compatible = "arm,gic-v3";
+ 		reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
+-		      <0x0 0x06100000 0 0x100000>; /* GICR (RD_base + SGI_base) */
++			<0x0 0x06100000 0 0x100000>, /* GICR (RD_base + SGI_base) */
++			<0x0 0x0c0c0000 0 0x2000>, /* GICC */
++			<0x0 0x0c0d0000 0 0x1000>, /* GICH */
++			<0x0 0x0c0e0000 0 0x20000>; /* GICV */
+ 		#interrupt-cells = <3>;
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
+ 		interrupt-controller;
+ 		interrupts = <1 9 0x4>;
++
++		its: gic-its@6020000 {
++			compatible = "arm,gic-v3-its";
++			msi-controller;
++			reg = <0x0 0x6020000 0 0x20000>;
++		};
+ 	};
+ 
+ 	timer {
+@@ -139,25 +166,355 @@
+ 			     <1 10 0x8>; /* Hypervisor PPI, active-low */
+ 	};
+ 
+-	serial0: serial@21c0500 {
+-		device_type = "serial";
+-		compatible = "fsl,ns16550", "ns16550a";
+-		reg = <0x0 0x21c0500 0x0 0x100>;
+-		clock-frequency = <0>;	/* Updated by bootloader */
+-		interrupts = <0 32 0x1>; /* edge triggered */
++	pmu {
++		compatible = "arm,armv8-pmuv3";
++		interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
+ 	};
+ 
+-	serial1: serial@21c0600 {
+-		device_type = "serial";
+-		compatible = "fsl,ns16550", "ns16550a";
+-		reg = <0x0 0x21c0600 0x0 0x100>;
+-		clock-frequency = <0>; 	/* Updated by bootloader */
+-		interrupts = <0 32 0x1>; /* edge triggered */
+-	};
++	soc {
++		compatible = "simple-bus";
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
++
++		clockgen: clocking@1300000 {
++			compatible = "fsl,ls2080a-clockgen";
++			reg = <0 0x1300000 0 0xa0000>;
++			#clock-cells = <2>;
++			clocks = <&sysclk>;
++		};
++
++		serial0: serial@21c0500 {
++			compatible = "fsl,ns16550", "ns16550a";
++			reg = <0x0 0x21c0500 0x0 0x100>;
++			clocks = <&clockgen 4 3>;
++			interrupts = <0 32 0x4>; /* Level high type */
++		};
++
++		serial1: serial@21c0600 {
++			compatible = "fsl,ns16550", "ns16550a";
++			reg = <0x0 0x21c0600 0x0 0x100>;
++			clocks = <&clockgen 4 3>;
++			interrupts = <0 32 0x4>; /* Level high type */
++		};
++
++		fsl_mc: fsl-mc@80c000000 {
++			compatible = "fsl,qoriq-mc";
++			reg = <0x00000008 0x0c000000 0 0x40>,	 /* MC portal base */
++			      <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
++		};
+ 
+-	fsl_mc: fsl-mc@80c000000 {
+-		compatible = "fsl,qoriq-mc";
+-		reg = <0x00000008 0x0c000000 0 0x40>,	 /* MC portal base */
+-		      <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
++		smmu: iommu@5000000 {
++			compatible = "arm,mmu-500";
++			reg = <0 0x5000000 0 0x800000>;
++			#global-interrupts = <12>;
++			interrupts = <0 13 4>, /* global secure fault */
++				     <0 14 4>, /* combined secure interrupt */
++				     <0 15 4>, /* global non-secure fault */
++				     <0 16 4>, /* combined non-secure interrupt */
++				/* performance counter interrupts 0-7 */
++				     <0 211 4>, <0 212 4>,
++				     <0 213 4>, <0 214 4>,
++				     <0 215 4>, <0 216 4>,
++				     <0 217 4>, <0 218 4>,
++				/* per context interrupt, 64 interrupts */
++				     <0 146 4>, <0 147 4>,
++				     <0 148 4>, <0 149 4>,
++				     <0 150 4>, <0 151 4>,
++				     <0 152 4>, <0 153 4>,
++				     <0 154 4>, <0 155 4>,
++				     <0 156 4>, <0 157 4>,
++				     <0 158 4>, <0 159 4>,
++				     <0 160 4>, <0 161 4>,
++				     <0 162 4>, <0 163 4>,
++				     <0 164 4>, <0 165 4>,
++				     <0 166 4>, <0 167 4>,
++				     <0 168 4>, <0 169 4>,
++				     <0 170 4>, <0 171 4>,
++				     <0 172 4>, <0 173 4>,
++				     <0 174 4>, <0 175 4>,
++				     <0 176 4>, <0 177 4>,
++				     <0 178 4>, <0 179 4>,
++				     <0 180 4>, <0 181 4>,
++				     <0 182 4>, <0 183 4>,
++				     <0 184 4>, <0 185 4>,
++				     <0 186 4>, <0 187 4>,
++				     <0 188 4>, <0 189 4>,
++				     <0 190 4>, <0 191 4>,
++				     <0 192 4>, <0 193 4>,
++				     <0 194 4>, <0 195 4>,
++				     <0 196 4>, <0 197 4>,
++				     <0 198 4>, <0 199 4>,
++				     <0 200 4>, <0 201 4>,
++				     <0 202 4>, <0 203 4>,
++				     <0 204 4>, <0 205 4>,
++				     <0 206 4>, <0 207 4>,
++				     <0 208 4>, <0 209 4>;
++			mmu-masters = <&fsl_mc 0x300 0>;
++		};
++
++		dspi: dspi@2100000 {
++			status = "disabled";
++			compatible = "fsl,vf610-dspi";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x2100000 0x0 0x10000>;
++			interrupts = <0 26 0x4>; /* Level high type */
++			clocks = <&clockgen 4 3>;
++			clock-names = "dspi";
++			spi-num-chipselects = <5>;
++			bus-num = <0>;
++		};
++
++		esdhc: esdhc@2140000 {
++			status = "disabled";
++			compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
++			reg = <0x0 0x2140000 0x0 0x10000>;
++			interrupts = <0 28 0x4>; /* Level high type */
++			clock-frequency = <0>;	/* Updated by bootloader */
++			voltage-ranges = <1800 1800 3300 3300>;
++			sdhci,auto-cmd12;
++			bus-width = <4>;
++		};
++
++		gpio0: gpio@2300000 {
++			compatible = "fsl,qoriq-gpio";
++			reg = <0x0 0x2300000 0x0 0x10000>;
++			interrupts = <0 36 0x4>; /* Level high type */
++			gpio-controller;
++			#gpio-cells = <2>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++		};
++
++		gpio1: gpio@2310000 {
++			compatible = "fsl,qoriq-gpio";
++			reg = <0x0 0x2310000 0x0 0x10000>;
++			interrupts = <0 36 0x4>; /* Level high type */
++			gpio-controller;
++			#gpio-cells = <2>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++		};
++
++		gpio2: gpio@2320000 {
++			compatible = "fsl,qoriq-gpio";
++			reg = <0x0 0x2320000 0x0 0x10000>;
++			interrupts = <0 37 0x4>; /* Level high type */
++			gpio-controller;
++			#gpio-cells = <2>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++		};
++
++		gpio3: gpio@2330000 {
++			compatible = "fsl,qoriq-gpio";
++			reg = <0x0 0x2330000 0x0 0x10000>;
++			interrupts = <0 37 0x4>; /* Level high type */
++			gpio-controller;
++			#gpio-cells = <2>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++		};
++
++		i2c0: i2c@2000000 {
++			status = "disabled";
++			compatible = "fsl,vf610-i2c";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x2000000 0x0 0x10000>;
++			interrupts = <0 34 0x4>; /* Level high type */
++			clock-names = "i2c";
++			clocks = <&clockgen 4 3>;
++		};
++
++		i2c1: i2c@2010000 {
++			status = "disabled";
++			compatible = "fsl,vf610-i2c";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x2010000 0x0 0x10000>;
++			interrupts = <0 34 0x4>; /* Level high type */
++			clock-names = "i2c";
++			clocks = <&clockgen 4 3>;
++		};
++
++		i2c2: i2c@2020000 {
++			status = "disabled";
++			compatible = "fsl,vf610-i2c";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x2020000 0x0 0x10000>;
++			interrupts = <0 35 0x4>; /* Level high type */
++			clock-names = "i2c";
++			clocks = <&clockgen 4 3>;
++		};
++
++		i2c3: i2c@2030000 {
++			status = "disabled";
++			compatible = "fsl,vf610-i2c";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x2030000 0x0 0x10000>;
++			interrupts = <0 35 0x4>; /* Level high type */
++			clock-names = "i2c";
++			clocks = <&clockgen 4 3>;
++		};
++
++		ifc: ifc@2240000 {
++			compatible = "fsl,ifc", "simple-bus";
++			reg = <0x0 0x2240000 0x0 0x20000>;
++			interrupts = <0 21 0x4>; /* Level high type */
++			little-endian;
++			#address-cells = <2>;
++			#size-cells = <1>;
++
++			ranges = <0 0 0x5 0x80000000 0x08000000
++				  2 0 0x5 0x30000000 0x00010000
++				  3 0 0x5 0x20000000 0x00010000>;
++		};
++
++		qspi: quadspi@20c0000 {
++			status = "disabled";
++			compatible = "fsl,vf610-qspi";
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x0 0x20c0000 0x0 0x10000>,
++			      <0x0 0x20000000 0x0 0x10000000>;
++			reg-names = "QuadSPI", "QuadSPI-memory";
++			interrupts = <0 25 0x4>; /* Level high type */
++			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
++			clock-names = "qspi_en", "qspi";
++		};
++
++		pcie@3400000 {
++			compatible = "fsl,ls2080a-pcie", "snps,dw-pcie";
++			reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
++			       0x10 0x00000000 0x0 0x00002000>; /* configuration space */
++			reg-names = "regs", "config";
++			interrupts = <0 108 0x4>; /* Level high type */
++			interrupt-names = "intr";
++			#address-cells = <3>;
++			#size-cells = <2>;
++			device_type = "pci";
++			num-lanes = <4>;
++			bus-range = <0x0 0xff>;
++			ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000   /* downstream I/O */
++				  0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
++			msi-parent = <&its>;
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 7>;
++			interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>,
++					<0000 0 0 2 &gic 0 0 0 110 4>,
++					<0000 0 0 3 &gic 0 0 0 111 4>,
++					<0000 0 0 4 &gic 0 0 0 112 4>;
++		};
++
++		pcie@3500000 {
++			compatible = "fsl,ls2080a-pcie", "snps,dw-pcie";
++			reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
++			       0x12 0x00000000 0x0 0x00002000>; /* configuration space */
++			reg-names = "regs", "config";
++			interrupts = <0 113 0x4>; /* Level high type */
++			interrupt-names = "intr";
++			#address-cells = <3>;
++			#size-cells = <2>;
++			device_type = "pci";
++			num-lanes = <4>;
++			bus-range = <0x0 0xff>;
++			ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000   /* downstream I/O */
++				  0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
++			msi-parent = <&its>;
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 7>;
++			interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>,
++					<0000 0 0 2 &gic 0 0 0 115 4>,
++					<0000 0 0 3 &gic 0 0 0 116 4>,
++					<0000 0 0 4 &gic 0 0 0 117 4>;
++		};
++
++		pcie@3600000 {
++			compatible = "fsl,ls2080a-pcie", "snps,dw-pcie";
++			reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
++			       0x14 0x00000000 0x0 0x00002000>; /* configuration space */
++			reg-names = "regs", "config";
++			interrupts = <0 118 0x4>; /* Level high type */
++			interrupt-names = "intr";
++			#address-cells = <3>;
++			#size-cells = <2>;
++			device_type = "pci";
++			num-lanes = <8>;
++			bus-range = <0x0 0xff>;
++			ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000   /* downstream I/O */
++				  0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
++			msi-parent = <&its>;
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 7>;
++			interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>,
++					<0000 0 0 2 &gic 0 0 0 120 4>,
++					<0000 0 0 3 &gic 0 0 0 121 4>,
++					<0000 0 0 4 &gic 0 0 0 122 4>;
++		};
++
++		pcie@3700000 {
++			compatible = "fsl,ls2080a-pcie", "snps,dw-pcie";
++			reg = <0x00 0x03700000 0x0 0x00100000   /* controller registers */
++			       0x16 0x00000000 0x0 0x00002000>; /* configuration space */
++			reg-names = "regs", "config";
++			interrupts = <0 123 0x4>; /* Level high type */
++			interrupt-names = "intr";
++			#address-cells = <3>;
++			#size-cells = <2>;
++			device_type = "pci";
++			num-lanes = <4>;
++			bus-range = <0x0 0xff>;
++			ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000   /* downstream I/O */
++				  0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
++			msi-parent = <&its>;
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 7>;
++			interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>,
++					<0000 0 0 2 &gic 0 0 0 125 4>,
++					<0000 0 0 3 &gic 0 0 0 126 4>,
++					<0000 0 0 4 &gic 0 0 0 127 4>;
++		};
++
++		sata0: sata@3200000 {
++			status = "disabled";
++			compatible = "fsl,ls2080a-ahci";
++			reg = <0x0 0x3200000 0x0 0x10000>;
++			interrupts = <0 133 0x4>; /* Level high type */
++			clocks = <&clockgen 4 3>;
++		};
++
++		sata1: sata@3210000 {
++			status = "disabled";
++			compatible = "fsl,ls2080a-ahci";
++			reg = <0x0 0x3210000 0x0 0x10000>;
++			interrupts = <0 136 0x4>; /* Level high type */
++			clocks = <&clockgen 4 3>;
++		};
++
++		usb0: usb3@3100000 {
++			status = "disabled";
++			compatible = "snps,dwc3";
++			reg = <0x0 0x3100000 0x0 0x10000>;
++			interrupts = <0 80 0x4>; /* Level high type */
++			dr_mode = "host";
++		};
++
++		usb1: usb3@3110000 {
++			status = "disabled";
++			compatible = "snps,dwc3";
++			reg = <0x0 0x3110000 0x0 0x10000>;
++			interrupts = <0 81 0x4>; /* Level high type */
++			dr_mode = "host";
++		};
++
++		ccn@4000000 {
++			compatible = "arm,ccn-504";
++			reg = <0x0 0x04000000 0x0 0x01000000>;
++			interrupts = <0 12 4>;
++		};
+ 	};
+ };
+-- 
+1.7.9.5
+
+
+From 74088343e67c0a9611b98fc6a1e641d720dc81f2 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:59 +0530
+Subject: [PATCH 09/66] dts/ls2080a: Remove text about writing to Free
+ Software Foundation
+
+Checkpatch complains about the text suggesting writing to
+Free Software Foundation for GPLv2 license copy.
+
+This patch removes the same from the .dtsi and .dts
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts |    5 -----
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     |    5 -----
+ 2 files changed, 10 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+index 33d6d0c..6d363d5 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+@@ -20,11 +20,6 @@
+  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *     GNU General Public License for more details.
+  *
+- *     You should have received a copy of the GNU General Public
+- *     License along with this library; if not, write to the Free
+- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+- *     MA 02110-1301 USA
+- *
+  * Or, alternatively,
+  *
+  *  b) Permission is hereby granted, free of charge, to any person
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index e52536e..e81cd48 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -20,11 +20,6 @@
+  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *     GNU General Public License for more details.
+  *
+- *     You should have received a copy of the GNU General Public
+- *     License along with this library; if not, write to the Free
+- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+- *     MA 02110-1301 USA
+- *
+  * Or, alternatively,
+  *
+  *  b) Permission is hereby granted, free of charge, to any person
+-- 
+1.7.9.5
+
+
+From f375a36f06aeee8301b648eb434a222c374eeda2 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:01:58 +0530
+Subject: [PATCH 10/66] dts/ls2080a: Update Simulator DTS to add support of
+ various peripherals
+
+This patch updates the LS2080a simulator DTS to add support of various
+peripherals which are supported on the simulator platform and explicitly
+disables those which are yet not supported on the platform.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+index 6d363d5..505d038 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+@@ -52,9 +52,19 @@
+ 	model = "Freescale Layerscape 2080a software Simulator model";
+ 	compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
+ 
++	aliases {
++		serial0 = &serial0;
++		serial1 = &serial1;
++	};
++
+ 	ethernet@2210000 {
+ 		compatible = "smsc,lan91c111";
+ 		reg = <0x0 0x2210000 0x0 0x100>;
+ 		interrupts = <0 58 0x1>;
+ 	};
+ };
++
++&ifc {
++	status = "okay";
++};
++
+-- 
+1.7.9.5
+
+
+From 6bb2ea47640b37cdf10336e3326829f3933f01b3 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:02:00 +0530
+Subject: [PATCH 11/66] dts/ls2080a: Add DTS support for LS2080a QDS & RDB
+ boards
+
+This patch adds the LS2080a DTS files for QDS and RDB boards
+which support the LS2080a SoC.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts |  204 +++++++++++++++++++++
+ arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts |  166 +++++++++++++++++
+ 2 files changed, 370 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+ create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+new file mode 100644
+index 0000000..4cb996d
+--- /dev/null
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+@@ -0,0 +1,204 @@
++/*
++ * Device Tree file for Freescale LS2080a QDS Board.
++ *
++ * Copyright (C) 2015, Freescale Semiconductor
++ *
++ * Bhupesh Sharma <bhupesh.sharma@freescale.com>
++ *
++ * This file is dual-licensed: you can use it either under the terms
++ * of the GPLv2 or the X11 license, at your option. Note that this dual
++ * licensing only applies to this file, and not this project as a
++ * whole.
++ *
++ *  a) This library is free software; you can redistribute it and/or
++ *     modify it under the terms of the GNU General Public License as
++ *     published by the Free Software Foundation; either version 2 of the
++ *     License, or (at your option) any later version.
++ *
++ *     This library is distributed in the hope that it will be useful,
++ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *     GNU General Public License for more details.
++ *
++ * Or, alternatively,
++ *
++ *  b) Permission is hereby granted, free of charge, to any person
++ *     obtaining a copy of this software and associated documentation
++ *     files (the "Software"), to deal in the Software without
++ *     restriction, including without limitation the rights to use,
++ *     copy, modify, merge, publish, distribute, sublicense, and/or
++ *     sell copies of the Software, and to permit persons to whom the
++ *     Software is furnished to do so, subject to the following
++ *     conditions:
++ *
++ *     The above copyright notice and this permission notice shall be
++ *     included in all copies or substantial portions of the Software.
++ *
++ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
++ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ *     OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++/dts-v1/;
++
++/include/ "fsl-ls2080a.dtsi"
++
++/ {
++	model = "Freescale Layerscape 2080a QDS Board";
++	compatible = "fsl,ls2080a-qds", "fsl,ls2080a";
++
++	aliases {
++		serial0 = &serial0;
++		serial1 = &serial1;
++	};
++
++};
++
++&esdhc {
++	status = "okay";
++};
++
++&ifc {
++	status = "okay";
++	#address-cells = <2>;
++	#size-cells = <1>;
++	ranges = <0x0 0x0 0x5 0x80000000 0x08000000
++		  0x2 0x0 0x5 0x30000000 0x00010000
++		  0x3 0x0 0x5 0x20000000 0x00010000>;
++
++	nor@0,0 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "cfi-flash";
++		reg = <0x0 0x0 0x8000000>;
++		bank-width = <2>;
++		device-width = <1>;
++	};
++
++	nand@2,0 {
++	     compatible = "fsl,ifc-nand";
++	     reg = <0x2 0x0 0x10000>;
++	};
++
++	cpld@3,0 {
++	     reg = <0x3 0x0 0x10000>;
++	     compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
++	};
++};
++
++&i2c0 {
++	status = "okay";
++	pca9547@77 {
++		compatible = "nxp,pca9547";
++		reg = <0x77>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++		i2c@0 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x00>;
++			rtc@68 {
++				compatible = "dallas,ds3232";
++				reg = <0x68>;
++			};
++		};
++
++		i2c@2 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x02>;
++
++			ina220@40 {
++				compatible = "ti,ina220";
++				reg = <0x40>;
++				shunt-resistor = <500>;
++			};
++
++			ina220@41 {
++				compatible = "ti,ina220";
++				reg = <0x41>;
++				shunt-resistor = <1000>;
++			};
++		};
++
++		i2c@3 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x3>;
++
++			adt7481@4c {
++				compatible = "adi,adt7461";
++				reg = <0x4c>;
++			};
++		};
++	};
++};
++
++&i2c1 {
++	status = "disabled";
++};
++
++&i2c2 {
++	status = "disabled";
++};
++
++&i2c3 {
++	status = "disabled";
++};
++
++&dspi {
++	status = "okay";
++	dflash0: n25q128a {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "st,m25p80";
++		spi-max-frequency = <3000000>;
++		reg = <0>;
++	};
++	dflash1: sst25wf040b {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "st,m25p80";
++		spi-max-frequency = <3000000>;
++		reg = <1>;
++	};
++	dflash2: en25s64 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "st,m25p80";
++		spi-max-frequency = <3000000>;
++		reg = <2>;
++	};
++};
++
++&qspi {
++	status = "okay";
++	qflash0: s25fl008k {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "st,m25p80";
++		spi-max-frequency = <20000000>;
++		reg = <0>;
++	};
++};
++
++&sata0 {
++	status = "okay";
++};
++
++&sata1 {
++	status = "okay";
++};
++
++&usb0 {
++	status = "okay";
++};
++
++&usb1 {
++	status = "okay";
++};
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+new file mode 100644
+index 0000000..e127f0b
+--- /dev/null
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+@@ -0,0 +1,166 @@
++/*
++ * Device Tree file for Freescale LS2080a RDB Board.
++ *
++ * Copyright (C) 2015, Freescale Semiconductor
++ *
++ * Bhupesh Sharma <bhupesh.sharma@freescale.com>
++ *
++ * This file is dual-licensed: you can use it either under the terms
++ * of the GPLv2 or the X11 license, at your option. Note that this dual
++ * licensing only applies to this file, and not this project as a
++ * whole.
++ *
++ *  a) This library is free software; you can redistribute it and/or
++ *     modify it under the terms of the GNU General Public License as
++ *     published by the Free Software Foundation; either version 2 of the
++ *     License, or (at your option) any later version.
++ *
++ *     This library is distributed in the hope that it will be useful,
++ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *     GNU General Public License for more details.
++ *
++ * Or, alternatively,
++ *
++ *  b) Permission is hereby granted, free of charge, to any person
++ *     obtaining a copy of this software and associated documentation
++ *     files (the "Software"), to deal in the Software without
++ *     restriction, including without limitation the rights to use,
++ *     copy, modify, merge, publish, distribute, sublicense, and/or
++ *     sell copies of the Software, and to permit persons to whom the
++ *     Software is furnished to do so, subject to the following
++ *     conditions:
++ *
++ *     The above copyright notice and this permission notice shall be
++ *     included in all copies or substantial portions of the Software.
++ *
++ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
++ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ *     OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++/dts-v1/;
++
++/include/ "fsl-ls2080a.dtsi"
++
++/ {
++	model = "Freescale Layerscape 2080a RDB Board";
++	compatible = "fsl,ls2080a-rdb", "fsl,ls2080a";
++
++	aliases {
++		serial0 = &serial0;
++		serial1 = &serial1;
++	};
++};
++
++&esdhc {
++	status = "okay";
++};
++
++&ifc {
++	status = "okay";
++	#address-cells = <2>;
++	#size-cells = <1>;
++	ranges = <0x0 0x0 0x5 0x80000000 0x08000000
++		  0x2 0x0 0x5 0x30000000 0x00010000
++		  0x3 0x0 0x5 0x20000000 0x00010000>;
++
++	nor@0,0 {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "cfi-flash";
++		reg = <0x0 0x0 0x8000000>;
++		bank-width = <2>;
++		device-width = <1>;
++	};
++
++	nand@2,0 {
++	     compatible = "fsl,ifc-nand";
++	     reg = <0x2 0x0 0x10000>;
++	};
++
++	cpld@3,0 {
++	     reg = <0x3 0x0 0x10000>;
++	     compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
++	};
++
++};
++
++&i2c0 {
++	status = "okay";
++	pca9547@75 {
++		compatible = "nxp,pca9547";
++		reg = <0x75>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++		status = "disabled";
++		i2c@1 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x01>;
++			rtc@68 {
++				compatible = "dallas,ds3232";
++				reg = <0x68>;
++			};
++		};
++
++		i2c@3 {
++			#address-cells = <1>;
++			#size-cells = <0>;
++			reg = <0x3>;
++
++			adt7481@4c {
++				compatible = "adi,adt7461";
++				reg = <0x4c>;
++			};
++		};
++	};
++};
++
++&i2c1 {
++	status = "disabled";
++};
++
++&i2c2 {
++	status = "disabled";
++};
++
++&i2c3 {
++	status = "disabled";
++};
++
++&dspi {
++	status = "okay";
++	dflash0: n25q512a {
++		#address-cells = <1>;
++		#size-cells = <1>;
++		compatible = "st,m25p80";
++		spi-max-frequency = <3000000>;
++		reg = <0>;
++	};
++};
++
++&qspi {
++	status = "disabled";
++};
++
++&sata0 {
++	status = "okay";
++};
++
++&sata1 {
++	status = "okay";
++};
++
++&usb0 {
++	status = "okay";
++};
++
++&usb1 {
++	status = "okay";
++};
+-- 
+1.7.9.5
+
+
+From 55e88df470daf9752de9e6f8eb4de7cc4ccee718 Mon Sep 17 00:00:00 2001
+From: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Date: Sat, 24 Oct 2015 01:02:01 +0530
+Subject: [PATCH 12/66] dts/Makefile: Add build support for LS2080a QDS & RDB
+ board DTS
+
+This patch adds build support for LS2080a QDS & RDB board DTS files
+in the arm64 DTS Makefile.
+
+Signed-off-by: Bhupesh Sharma <bhupesh.sharma@freescale.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/boot/dts/freescale/Makefile |    2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
+index 932001a..c4957a4 100644
+--- a/arch/arm64/boot/dts/freescale/Makefile
++++ b/arch/arm64/boot/dts/freescale/Makefile
+@@ -1,3 +1,5 @@
++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
+ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
+  
+ always		:= $(dtb-y)
+-- 
+1.7.9.5
+
+
+From 4319e317b54786993652517f10f90884cb154150 Mon Sep 17 00:00:00 2001
+From: Scott Wood <scottwood@freescale.com>
+Date: Sat, 19 Sep 2015 23:29:53 -0500
+Subject: [PATCH 13/66] powerpc/fsl: Move fsl_guts.h out of arch/powerpc
+
+Freescale's Layerscape ARM chips use the same structure.
+
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+---
+ arch/powerpc/platforms/85xx/mpc85xx_mds.c          |    2 +-
+ arch/powerpc/platforms/85xx/mpc85xx_rdb.c          |    2 +-
+ arch/powerpc/platforms/85xx/p1022_ds.c             |    2 +-
+ arch/powerpc/platforms/85xx/p1022_rdk.c            |    2 +-
+ arch/powerpc/platforms/85xx/smp.c                  |    2 +-
+ arch/powerpc/platforms/85xx/twr_p102x.c            |    2 +-
+ arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |    2 +-
+ drivers/iommu/fsl_pamu.c                           |    2 +-
+ .../asm/fsl_guts.h => include/linux/fsl/guts.h     |    8 ++++----
+ sound/soc/fsl/mpc8610_hpcd.c                       |    2 +-
+ sound/soc/fsl/p1022_ds.c                           |    2 +-
+ sound/soc/fsl/p1022_rdk.c                          |    2 +-
+ 12 files changed, 15 insertions(+), 15 deletions(-)
+ rename arch/powerpc/include/asm/fsl_guts.h => include/linux/fsl/guts.h (98%)
+
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+index a392e94..f0be439 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+@@ -34,6 +34,7 @@
+ #include <linux/of_device.h>
+ #include <linux/phy.h>
+ #include <linux/memblock.h>
++#include <linux/fsl/guts.h>
+ 
+ #include <linux/atomic.h>
+ #include <asm/time.h>
+@@ -51,7 +52,6 @@
+ #include <asm/qe_ic.h>
+ #include <asm/mpic.h>
+ #include <asm/swiotlb.h>
+-#include <asm/fsl_guts.h>
+ #include "smp.h"
+ 
+ #include "mpc85xx.h"
+diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+index e358bed..50dcc00 100644
+--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
++++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+@@ -17,6 +17,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
+ #include <linux/of_platform.h>
++#include <linux/fsl/guts.h>
+ 
+ #include <asm/time.h>
+ #include <asm/machdep.h>
+@@ -27,7 +28,6 @@
+ #include <asm/mpic.h>
+ #include <asm/qe.h>
+ #include <asm/qe_ic.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include <sysdev/fsl_soc.h>
+ #include <sysdev/fsl_pci.h>
+diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
+index 6ac986d3..371df82 100644
+--- a/arch/powerpc/platforms/85xx/p1022_ds.c
++++ b/arch/powerpc/platforms/85xx/p1022_ds.c
+@@ -16,6 +16,7 @@
+  * kind, whether express or implied.
+  */
+ 
++#include <linux/fsl/guts.h>
+ #include <linux/pci.h>
+ #include <linux/of_platform.h>
+ #include <asm/div64.h>
+@@ -25,7 +26,6 @@
+ #include <sysdev/fsl_soc.h>
+ #include <sysdev/fsl_pci.h>
+ #include <asm/udbg.h>
+-#include <asm/fsl_guts.h>
+ #include <asm/fsl_lbc.h>
+ #include "smp.h"
+ 
+diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
+index 680232d..5087bec 100644
+--- a/arch/powerpc/platforms/85xx/p1022_rdk.c
++++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
+@@ -12,6 +12,7 @@
+  * kind, whether express or implied.
+  */
+ 
++#include <linux/fsl/guts.h>
+ #include <linux/pci.h>
+ #include <linux/of_platform.h>
+ #include <asm/div64.h>
+@@ -21,7 +22,6 @@
+ #include <sysdev/fsl_soc.h>
+ #include <sysdev/fsl_pci.h>
+ #include <asm/udbg.h>
+-#include <asm/fsl_guts.h>
+ #include "smp.h"
+ 
+ #include "mpc85xx.h"
+diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
+index b8b8216..6ac7786 100644
+--- a/arch/powerpc/platforms/85xx/smp.c
++++ b/arch/powerpc/platforms/85xx/smp.c
+@@ -19,6 +19,7 @@
+ #include <linux/kexec.h>
+ #include <linux/highmem.h>
+ #include <linux/cpu.h>
++#include <linux/fsl/guts.h>
+ 
+ #include <asm/machdep.h>
+ #include <asm/pgtable.h>
+@@ -26,7 +27,6 @@
+ #include <asm/mpic.h>
+ #include <asm/cacheflush.h>
+ #include <asm/dbell.h>
+-#include <asm/fsl_guts.h>
+ #include <asm/code-patching.h>
+ #include <asm/cputhreads.h>
+ 
+diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c
+index 30e002f..892e613 100644
+--- a/arch/powerpc/platforms/85xx/twr_p102x.c
++++ b/arch/powerpc/platforms/85xx/twr_p102x.c
+@@ -15,6 +15,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
++#include <linux/fsl/guts.h>
+ #include <linux/pci.h>
+ #include <linux/of_platform.h>
+ 
+@@ -23,7 +24,6 @@
+ #include <asm/mpic.h>
+ #include <asm/qe.h>
+ #include <asm/qe_ic.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include <sysdev/fsl_soc.h>
+ #include <sysdev/fsl_pci.h>
+diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+index 55413a5..437a9c3 100644
+--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
++++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+@@ -24,6 +24,7 @@
+ #include <linux/delay.h>
+ #include <linux/seq_file.h>
+ #include <linux/of.h>
++#include <linux/fsl/guts.h>
+ 
+ #include <asm/time.h>
+ #include <asm/machdep.h>
+@@ -38,7 +39,6 @@
+ #include <sysdev/fsl_pci.h>
+ #include <sysdev/fsl_soc.h>
+ #include <sysdev/simple_gpio.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include "mpc86xx.h"
+ 
+diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
+index abeedc9..24705c2 100644
+--- a/drivers/iommu/fsl_pamu.c
++++ b/drivers/iommu/fsl_pamu.c
+@@ -20,11 +20,11 @@
+ 
+ #include "fsl_pamu.h"
+ 
++#include <linux/fsl/guts.h>
+ #include <linux/interrupt.h>
+ #include <linux/genalloc.h>
+ 
+ #include <asm/mpc85xx.h>
+-#include <asm/fsl_guts.h>
+ 
+ /* define indexes for each operation mapping scenario */
+ #define OMI_QMAN        0x00
+diff --git a/arch/powerpc/include/asm/fsl_guts.h b/include/linux/fsl/guts.h
+similarity index 98%
+rename from arch/powerpc/include/asm/fsl_guts.h
+rename to include/linux/fsl/guts.h
+index 43b6bb1..84d971f 100644
+--- a/arch/powerpc/include/asm/fsl_guts.h
++++ b/include/linux/fsl/guts.h
+@@ -12,9 +12,10 @@
+  * option) any later version.
+  */
+ 
+-#ifndef __ASM_POWERPC_FSL_GUTS_H__
+-#define __ASM_POWERPC_FSL_GUTS_H__
+-#ifdef __KERNEL__
++#ifndef __FSL_GUTS_H__
++#define __FSL_GUTS_H__
++
++#include <linux/types.h>
+ 
+ /**
+  * Global Utility Registers.
+@@ -189,4 +190,3 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+ #endif
+ 
+ #endif
+-#endif
+diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
+index 9621b91..6f236f1 100644
+--- a/sound/soc/fsl/mpc8610_hpcd.c
++++ b/sound/soc/fsl/mpc8610_hpcd.c
+@@ -12,11 +12,11 @@
+ 
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
++#include <linux/fsl/guts.h>
+ #include <linux/of_address.h>
+ #include <linux/of_device.h>
+ #include <linux/slab.h>
+ #include <sound/soc.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include "fsl_dma.h"
+ #include "fsl_ssi.h"
+diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
+index 71c1a7d..747aab0 100644
+--- a/sound/soc/fsl/p1022_ds.c
++++ b/sound/soc/fsl/p1022_ds.c
+@@ -11,12 +11,12 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/fsl/guts.h>
+ #include <linux/interrupt.h>
+ #include <linux/of_address.h>
+ #include <linux/of_device.h>
+ #include <linux/slab.h>
+ #include <sound/soc.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include "fsl_dma.h"
+ #include "fsl_ssi.h"
+diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
+index ee29048..1dd49e5 100644
+--- a/sound/soc/fsl/p1022_rdk.c
++++ b/sound/soc/fsl/p1022_rdk.c
+@@ -18,12 +18,12 @@
+  */
+ 
+ #include <linux/module.h>
++#include <linux/fsl/guts.h>
+ #include <linux/interrupt.h>
+ #include <linux/of_address.h>
+ #include <linux/of_device.h>
+ #include <linux/slab.h>
+ #include <sound/soc.h>
+-#include <asm/fsl_guts.h>
+ 
+ #include "fsl_dma.h"
+ #include "fsl_ssi.h"
+-- 
+1.7.9.5
+
+
+From 62e5d73821fa2e5676bc92ac1c3448ae4fb02ca1 Mon Sep 17 00:00:00 2001
+From: Scott Wood <scottwood@freescale.com>
+Date: Sat, 19 Sep 2015 23:29:54 -0500
+Subject: [PATCH 14/66] clk: qoriq: Move chip-specific knowledge into driver
+
+The device tree should describe the chips (or chip-like subblocks) in
+the system, but it generally does not describe individual registers --
+it should identify, rather than describe, a programming interface.
+
+This has not been the case with the QorIQ clockgen nodes.  The
+knowledge of what each bit setting of CLKCnCSR means is encoded in
+three places (binding, pll node, and mux node), and the last also needs
+to know which options are valid on a particular chip.  All three of
+these locations are considered stable ABI, making it difficult to fix
+mistakes (of which I have found several), much less refactor the
+abstraction to be able to address problems, limitations, or new chips.
+
+Under the current binding, a pll clock specifier of 2 means that the
+PLL is divided by 4 -- and the driver implements this, unless there
+happen to be four clock-output-names rather than 3, in which case it
+interprets it as PLL divided by 3.  This does not appear in the binding
+documentation at all.  That hack is now considered stable ABI.
+
+The current device tree nodes contain errors, such as saying that
+T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options.
+The current binding also ignores some restrictions on clock selection,
+such as p5020's requirement that if a core uses the "wrong" PLL, that
+PLL must be clocked lower than the "correct" PLL and be at most 80% of
+the rated CPU frequency.
+
+Possibly because of the lack of the ability to express such nuance in
+the binding, some valid options are omitted from the device trees, such
+as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from
+PLL1 (again, only if they are at most 80% of rated CPU frequency).
+This omission, combined with excessive caution in the cpufreq driver
+(addressed in a subsequent patch), means that currently on a 1500 MHz
+p4080 with typical PLL configuration, cpufreq can lower the frequency
+to 1200 MHz on half the CPUs and do nothing on the others.  With this
+patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a
+rev3 p4080 half can be lowered to 750 MHz and the other half to 600
+MHz.
+
+The current binding only deals with CPU clocks.  To describe FMan in
+the device tree, we need to describe its clock.  Some chips have
+additional muxes that work like the CPU muxes, but are not described in
+the device tree.  Others require inspecting the Reset Control Word to
+determine which PLL is used.  Rather than continue to extend this mess,
+replace it.  Have the driver bind to the chip-specific clockgen
+compatible, and keep the detailed description of quirky chip variations
+in the driver, where it can be easily fixed, refactored, and extended.
+
+Older device trees will continue to work (including a workaround for
+old ls1021a device trees that are missing compatible and reg in the
+clockgen node, which even the old binding required).  The pll/mux
+details in old device trees will be ignored, but "clocks" properties
+pointing at the old nodes will still work, and be directed at the
+corresponding new clock.
+
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+Acked-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ .../devicetree/bindings/clock/qoriq-clock.txt      |   61 +-
+ drivers/clk/clk-qoriq.c                            | 1261 ++++++++++++++++----
+ 2 files changed, 1090 insertions(+), 232 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+index df4a259..16a3ec4 100644
+--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt
++++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt
+@@ -1,6 +1,6 @@
+ * Clock Block on Freescale QorIQ Platforms
+ 
+-Freescale qoriq chips take primary clocking input from the external
++Freescale QorIQ chips take primary clocking input from the external
+ SYSCLK signal. The SYSCLK input (frequency) is multiplied using
+ multiple phase locked loops (PLL) to create a variety of frequencies
+ which can then be passed to a variety of internal logic, including
+@@ -13,14 +13,16 @@ which the chip complies.
+ Chassis Version		Example Chips
+ ---------------		-------------
+ 1.0			p4080, p5020, p5040
+-2.0			t4240, b4860, t1040
++2.0			t4240, b4860
+ 
+ 1. Clock Block Binding
+ 
+ Required properties:
+-- compatible: Should contain a specific clock block compatible string
+-	and a single chassis clock compatible string.
+-	Clock block strings include, but not limited to, one of the:
++- compatible: Should contain a chip-specific clock block compatible
++	string and (if applicable) may contain a chassis-version clock
++	compatible string.
++
++	Chip-specific strings are of the form "fsl,<chip>-clockgen", such as:
+ 	* "fsl,p2041-clockgen"
+ 	* "fsl,p3041-clockgen"
+ 	* "fsl,p4080-clockgen"
+@@ -30,15 +32,14 @@ Required properties:
+ 	* "fsl,b4420-clockgen"
+ 	* "fsl,b4860-clockgen"
+ 	* "fsl,ls1021a-clockgen"
+-	Chassis clock strings include:
++	Chassis-version clock strings include:
+ 	* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
+ 	* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
+ - reg: Describes the address of the device's resources within the
+ 	address space defined by its parent bus, and resource zero
+ 	represents the clock register set
+-- clock-frequency: Input system clock frequency
+ 
+-Recommended properties:
++Optional properties:
+ - ranges: Allows valid translation between child's address space and
+ 	parent's. Must be present if the device has sub-nodes.
+ - #address-cells: Specifies the number of cells used to represent
+@@ -47,8 +48,46 @@ Recommended properties:
+ - #size-cells: Specifies the number of cells used to represent
+ 	the size of an address. Must be present if the device has
+ 	sub-nodes and set to 1 if present
++- clock-frequency: Input system clock frequency (SYSCLK)
++- clocks: If clock-frequency is not specified, sysclk may be provided
++	as an input clock.  Either clock-frequency or clocks must be
++	provided.
++
++2. Clock Provider
++
++The clockgen node should act as a clock provider, though in older device
++trees the children of the clockgen node are the clock providers.
++
++When the clockgen node is a clock provider, #clock-cells = <2>.
++The first cell of the clock specifier is the clock type, and the
++second cell is the clock index for the specified type.
++
++	Type#	Name		Index Cell
++	0	sysclk		must be 0
++	1	cmux		index (n in CLKCnCSR)
++	2	hwaccel		index (n in CLKCGnHWACSR)
++	3	fman		0 for fm1, 1 for fm2
++	4	platform pll	0=pll, 1=pll/2, 2=pll/3, 3=pll/4
++
++3. Example
++
++	clockgen: global-utilities@e1000 {
++		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
++		clock-frequency = <133333333>;
++		reg = <0xe1000 0x1000>;
++		#clock-cells = <2>;
++	};
++
++	fman@400000 {
++		...
++		clocks = <&clockgen 3 0>;
++		...
++	};
++}
++4. Legacy Child Nodes
+ 
+-2. Clock Provider/Consumer Binding
++NOTE: These nodes are deprecated.  Kernels should continue to support
++device trees with these nodes, but new device trees should not use them.
+ 
+ Most of the bindings are from the common clock binding[1].
+  [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+@@ -82,7 +121,7 @@ Recommended properties:
+ - reg: Should be the offset and length of clock block base address.
+ 	The length should be 4.
+ 
+-Example for clock block and clock provider:
++Legacy Example:
+ / {
+ 	clockgen: global-utilities@e1000 {
+ 		compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+@@ -142,7 +181,7 @@ Example for clock block and clock provider:
+ 	};
+ };
+ 
+-Example for clock consumer:
++Example for legacy clock consumer:
+ 
+ / {
+ 	cpu0: PowerPC,e5500@0 {
+diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
+index cda90a9..06281a3 100644
+--- a/drivers/clk/clk-qoriq.c
++++ b/drivers/clk/clk-qoriq.c
+@@ -10,7 +10,9 @@
+ 
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+ 
++#include <linux/clk.h>
+ #include <linux/clk-provider.h>
++#include <linux/fsl/guts.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+@@ -19,213 +21,934 @@
+ #include <linux/of.h>
+ #include <linux/slab.h>
+ 
+-struct cmux_clk {
++#define PLL_DIV1	0
++#define PLL_DIV2	1
++#define PLL_DIV3	2
++#define PLL_DIV4	3
++
++#define PLATFORM_PLL	0
++#define CGA_PLL1	1
++#define CGA_PLL2	2
++#define CGA_PLL3	3
++#define CGA_PLL4	4	/* only on clockgen-1.0, which lacks CGB */
++#define CGB_PLL1	4
++#define CGB_PLL2	5
++
++struct clockgen_pll_div {
++	struct clk *clk;
++	char name[32];
++};
++
++struct clockgen_pll {
++	struct clockgen_pll_div div[4];
++};
++
++#define CLKSEL_VALID	1
++#define CLKSEL_80PCT	2	/* Only allowed if PLL <= 80% of max cpu freq */
++
++struct clockgen_sourceinfo {
++	u32 flags;	/* CLKSEL_xxx */
++	int pll;	/* CGx_PLLn */
++	int div;	/* PLL_DIVn */
++};
++
++#define NUM_MUX_PARENTS	16
++
++struct clockgen_muxinfo {
++	struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS];
++};
++
++#define NUM_HWACCEL	5
++#define NUM_CMUX	8
++
++struct clockgen;
++
++/*
++ * cmux freq must be >= platform pll.
++ * If not set, cmux freq must be >= platform pll/2
++ */
++#define CG_CMUX_GE_PLAT		1
++#define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
++
++struct clockgen_chipinfo {
++	const char *compat, *guts_compat;
++	const struct clockgen_muxinfo *cmux_groups[2];
++	const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL];
++	void (*init_periph)(struct clockgen *cg);
++	int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */
++	u32 pll_mask;	/* 1 << n bit set if PLL n is valid */
++	u32 flags;	/* CG_xxx */
++};
++
++struct clockgen {
++	struct device_node *node;
++	void __iomem *regs;
++	struct clockgen_chipinfo info; /* mutable copy */
++	struct clk *sysclk;
++	struct clockgen_pll pll[6];
++	struct clk *cmux[NUM_CMUX];
++	struct clk *hwaccel[NUM_HWACCEL];
++	struct clk *fman[2];
++	struct ccsr_guts __iomem *guts;
++};
++
++static struct clockgen clockgen;
++
++static const struct clockgen_muxinfo p2041_cmux_grp1 = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++	}
++};
++
++static const struct clockgen_muxinfo p2041_cmux_grp2 = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++	}
++};
++
++static const struct clockgen_muxinfo p5020_cmux_grp1 = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
++	}
++};
++
++static const struct clockgen_muxinfo p5020_cmux_grp2 = {
++	{
++		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++	}
++};
++
++static const struct clockgen_muxinfo p5040_cmux_grp1 = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 },
++	}
++};
++
++static const struct clockgen_muxinfo p5040_cmux_grp2 = {
++	{
++		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++	}
++};
++
++static const struct clockgen_muxinfo p4080_cmux_grp1 = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		[8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 },
++	}
++};
++
++static const struct clockgen_muxinfo p4080_cmux_grp2 = {
++	{
++		[0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 },
++		[8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
++		[9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
++		[12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 },
++		[13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 },
++	}
++};
++
++static const struct clockgen_muxinfo t1023_cmux = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++	}
++};
++
++static const struct clockgen_muxinfo t1040_cmux = {
++	{
++		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		[1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++	}
++};
++
++
++static const struct clockgen_muxinfo clockgen2_cmux_cga = {
++	{
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
++		{},
++		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL3, PLL_DIV4 },
++	},
++};
++
++static const struct clockgen_muxinfo clockgen2_cmux_cga12 = {
++	{
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
++	},
++};
++
++static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
++	{
++		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
++		{},
++		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV1 },
++		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
++	},
++};
++
++static const struct clockgen_muxinfo t1023_hwa1 = {
++	{
++		{},
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++	},
++};
++
++static const struct clockgen_muxinfo t1023_hwa2 = {
++	{
++		[6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++	},
++};
++
++static const struct clockgen_muxinfo t2080_hwa1 = {
++	{
++		{},
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
++		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++	},
++};
++
++static const struct clockgen_muxinfo t2080_hwa2 = {
++	{
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
++		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++	},
++};
++
++static const struct clockgen_muxinfo t4240_hwa1 = {
++	{
++		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++	},
++};
++
++static const struct clockgen_muxinfo t4240_hwa4 = {
++	{
++		[2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
++		[3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
++		[4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 },
++		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
++		[6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
++	},
++};
++
++static const struct clockgen_muxinfo t4240_hwa5 = {
++	{
++		[2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 },
++		[3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 },
++		[4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 },
++		[5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
++		[6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 },
++		[7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 },
++	},
++};
++
++#define RCWSR7_FM1_CLK_SEL	0x40000000
++#define RCWSR7_FM2_CLK_SEL	0x20000000
++#define RCWSR7_HWA_ASYNC_DIV	0x04000000
++
++static void __init p2041_init_periph(struct clockgen *cg)
++{
++	u32 reg;
++
++	reg = ioread32be(&cg->guts->rcwsr[7]);
++
++	if (reg & RCWSR7_FM1_CLK_SEL)
++		cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk;
++	else
++		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++}
++
++static void __init p4080_init_periph(struct clockgen *cg)
++{
++	u32 reg;
++
++	reg = ioread32be(&cg->guts->rcwsr[7]);
++
++	if (reg & RCWSR7_FM1_CLK_SEL)
++		cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
++	else
++		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++
++	if (reg & RCWSR7_FM2_CLK_SEL)
++		cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk;
++	else
++		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++}
++
++static void __init p5020_init_periph(struct clockgen *cg)
++{
++	u32 reg;
++	int div = PLL_DIV2;
++
++	reg = ioread32be(&cg->guts->rcwsr[7]);
++	if (reg & RCWSR7_HWA_ASYNC_DIV)
++		div = PLL_DIV4;
++
++	if (reg & RCWSR7_FM1_CLK_SEL)
++		cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk;
++	else
++		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++}
++
++static void __init p5040_init_periph(struct clockgen *cg)
++{
++	u32 reg;
++	int div = PLL_DIV2;
++
++	reg = ioread32be(&cg->guts->rcwsr[7]);
++	if (reg & RCWSR7_HWA_ASYNC_DIV)
++		div = PLL_DIV4;
++
++	if (reg & RCWSR7_FM1_CLK_SEL)
++		cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk;
++	else
++		cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++
++	if (reg & RCWSR7_FM2_CLK_SEL)
++		cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk;
++	else
++		cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk;
++}
++
++static void __init t1023_init_periph(struct clockgen *cg)
++{
++	cg->fman[0] = cg->hwaccel[1];
++}
++
++static void __init t1040_init_periph(struct clockgen *cg)
++{
++	cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk;
++}
++
++static void __init t2080_init_periph(struct clockgen *cg)
++{
++	cg->fman[0] = cg->hwaccel[0];
++}
++
++static void __init t4240_init_periph(struct clockgen *cg)
++{
++	cg->fman[0] = cg->hwaccel[3];
++	cg->fman[1] = cg->hwaccel[4];
++}
++
++static const struct clockgen_chipinfo chipinfo[] = {
++	{
++		.compat = "fsl,b4420-clockgen",
++		.guts_compat = "fsl,b4860-device-config",
++		.init_periph = t2080_init_periph,
++		.cmux_groups = {
++			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
++		},
++		.hwaccel = {
++			&t2080_hwa1
++		},
++		.cmux_to_group = {
++			0, 1, 1, 1, -1
++		},
++		.pll_mask = 0x3f,
++		.flags = CG_PLL_8BIT,
++	},
++	{
++		.compat = "fsl,b4860-clockgen",
++		.guts_compat = "fsl,b4860-device-config",
++		.init_periph = t2080_init_periph,
++		.cmux_groups = {
++			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
++		},
++		.hwaccel = {
++			&t2080_hwa1
++		},
++		.cmux_to_group = {
++			0, 1, 1, 1, -1
++		},
++		.pll_mask = 0x3f,
++		.flags = CG_PLL_8BIT,
++	},
++	{
++		.compat = "fsl,ls1021a-clockgen",
++		.cmux_groups = {
++			&t1023_cmux
++		},
++		.cmux_to_group = {
++			0, -1
++		},
++		.pll_mask = 0x03,
++	},
++	{
++		.compat = "fsl,p2041-clockgen",
++		.guts_compat = "fsl,qoriq-device-config-1.0",
++		.init_periph = p2041_init_periph,
++		.cmux_groups = {
++			&p2041_cmux_grp1, &p2041_cmux_grp2
++		},
++		.cmux_to_group = {
++			0, 0, 1, 1, -1
++		},
++		.pll_mask = 0x07,
++	},
++	{
++		.compat = "fsl,p3041-clockgen",
++		.guts_compat = "fsl,qoriq-device-config-1.0",
++		.init_periph = p2041_init_periph,
++		.cmux_groups = {
++			&p2041_cmux_grp1, &p2041_cmux_grp2
++		},
++		.cmux_to_group = {
++			0, 0, 1, 1, -1
++		},
++		.pll_mask = 0x07,
++	},
++	{
++		.compat = "fsl,p4080-clockgen",
++		.guts_compat = "fsl,qoriq-device-config-1.0",
++		.init_periph = p4080_init_periph,
++		.cmux_groups = {
++			&p4080_cmux_grp1, &p4080_cmux_grp2
++		},
++		.cmux_to_group = {
++			0, 0, 0, 0, 1, 1, 1, 1
++		},
++		.pll_mask = 0x1f,
++	},
++	{
++		.compat = "fsl,p5020-clockgen",
++		.guts_compat = "fsl,qoriq-device-config-1.0",
++		.init_periph = p5020_init_periph,
++		.cmux_groups = {
++			&p2041_cmux_grp1, &p2041_cmux_grp2
++		},
++		.cmux_to_group = {
++			0, 1, -1
++		},
++		.pll_mask = 0x07,
++	},
++	{
++		.compat = "fsl,p5040-clockgen",
++		.guts_compat = "fsl,p5040-device-config",
++		.init_periph = p5040_init_periph,
++		.cmux_groups = {
++			&p5040_cmux_grp1, &p5040_cmux_grp2
++		},
++		.cmux_to_group = {
++			0, 0, 1, 1, -1
++		},
++		.pll_mask = 0x0f,
++	},
++	{
++		.compat = "fsl,t1023-clockgen",
++		.guts_compat = "fsl,t1023-device-config",
++		.init_periph = t1023_init_periph,
++		.cmux_groups = {
++			&t1023_cmux
++		},
++		.hwaccel = {
++			&t1023_hwa1, &t1023_hwa2
++		},
++		.cmux_to_group = {
++			0, 0, -1
++		},
++		.pll_mask = 0x03,
++		.flags = CG_PLL_8BIT,
++	},
++	{
++		.compat = "fsl,t1040-clockgen",
++		.guts_compat = "fsl,t1040-device-config",
++		.init_periph = t1040_init_periph,
++		.cmux_groups = {
++			&t1040_cmux
++		},
++		.cmux_to_group = {
++			0, 0, 0, 0, -1
++		},
++		.pll_mask = 0x07,
++		.flags = CG_PLL_8BIT,
++	},
++	{
++		.compat = "fsl,t2080-clockgen",
++		.guts_compat = "fsl,t2080-device-config",
++		.init_periph = t2080_init_periph,
++		.cmux_groups = {
++			&clockgen2_cmux_cga12
++		},
++		.hwaccel = {
++			&t2080_hwa1, &t2080_hwa2
++		},
++		.cmux_to_group = {
++			0, -1
++		},
++		.pll_mask = 0x07,
++		.flags = CG_PLL_8BIT,
++	},
++	{
++		.compat = "fsl,t4240-clockgen",
++		.guts_compat = "fsl,t4240-device-config",
++		.init_periph = t4240_init_periph,
++		.cmux_groups = {
++			&clockgen2_cmux_cga, &clockgen2_cmux_cgb
++		},
++		.hwaccel = {
++			&t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5
++		},
++		.cmux_to_group = {
++			0, 0, 1, -1
++		},
++		.pll_mask = 0x3f,
++		.flags = CG_PLL_8BIT,
++	},
++	{},
++};
++
++struct mux_hwclock {
+ 	struct clk_hw hw;
+-	void __iomem *reg;
+-	unsigned int clk_per_pll;
+-	u32 flags;
++	struct clockgen *cg;
++	const struct clockgen_muxinfo *info;
++	u32 __iomem *reg;
++	u8 parent_to_clksel[NUM_MUX_PARENTS];
++	s8 clksel_to_parent[NUM_MUX_PARENTS];
++	int num_parents;
+ };
+ 
+-#define PLL_KILL			BIT(31)
++#define to_mux_hwclock(p)	container_of(p, struct mux_hwclock, hw)
++#define CLKSEL_MASK		0x78000000
+ #define	CLKSEL_SHIFT		27
+-#define CLKSEL_ADJUST		BIT(0)
+-#define to_cmux_clk(p)		container_of(p, struct cmux_clk, hw)
+ 
+-static int cmux_set_parent(struct clk_hw *hw, u8 idx)
++static int mux_set_parent(struct clk_hw *hw, u8 idx)
+ {
+-	struct cmux_clk *clk = to_cmux_clk(hw);
++	struct mux_hwclock *hwc = to_mux_hwclock(hw);
+ 	u32 clksel;
+ 
+-	clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll;
+-	if (clk->flags & CLKSEL_ADJUST)
+-		clksel += 8;
+-	clksel = (clksel & 0xf) << CLKSEL_SHIFT;
+-	iowrite32be(clksel, clk->reg);
++	if (idx >= hwc->num_parents)
++		return -EINVAL;
++
++	clksel = hwc->parent_to_clksel[idx];
++	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
+ 
+ 	return 0;
+ }
+ 
+-static u8 cmux_get_parent(struct clk_hw *hw)
++static u8 mux_get_parent(struct clk_hw *hw)
+ {
+-	struct cmux_clk *clk = to_cmux_clk(hw);
++	struct mux_hwclock *hwc = to_mux_hwclock(hw);
+ 	u32 clksel;
++	s8 ret;
+ 
+-	clksel = ioread32be(clk->reg);
+-	clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
+-	if (clk->flags & CLKSEL_ADJUST)
+-		clksel -= 8;
+-	clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4;
++	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+ 
+-	return clksel;
++	ret = hwc->clksel_to_parent[clksel];
++	if (ret < 0) {
++		pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg);
++		return 0;
++	}
++
++	return ret;
+ }
+ 
+ static const struct clk_ops cmux_ops = {
+-	.get_parent = cmux_get_parent,
+-	.set_parent = cmux_set_parent,
++	.get_parent = mux_get_parent,
++	.set_parent = mux_set_parent,
+ };
+ 
+-static void __init core_mux_init(struct device_node *np)
++/*
++ * Don't allow setting for now, as the clock options haven't been
++ * sanitized for additional restrictions.
++ */
++static const struct clk_ops hwaccel_ops = {
++	.get_parent = mux_get_parent,
++};
++
++static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg,
++						  struct mux_hwclock *hwc,
++						  int idx)
+ {
+-	struct clk *clk;
+-	struct clk_init_data init;
+-	struct cmux_clk *cmux_clk;
+-	struct device_node *node;
+-	int rc, count, i;
+-	u32	offset;
+-	const char *clk_name;
+-	const char **parent_names;
+-	struct of_phandle_args clkspec;
++	int pll, div;
+ 
+-	rc = of_property_read_u32(np, "reg", &offset);
+-	if (rc) {
+-		pr_err("%s: could not get reg property\n", np->name);
+-		return;
+-	}
++	if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID))
++		return NULL;
+ 
+-	/* get the input clock source count */
+-	count = of_property_count_strings(np, "clock-names");
+-	if (count < 0) {
+-		pr_err("%s: get clock count error\n", np->name);
+-		return;
+-	}
+-	parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL);
+-	if (!parent_names)
+-		return;
++	pll = hwc->info->clksel[idx].pll;
++	div = hwc->info->clksel[idx].div;
+ 
+-	for (i = 0; i < count; i++)
+-		parent_names[i] = of_clk_get_parent_name(np, i);
++	return &cg->pll[pll].div[div];
++}
+ 
+-	cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL);
+-	if (!cmux_clk)
+-		goto err_name;
++static struct clk * __init create_mux_common(struct clockgen *cg,
++					     struct mux_hwclock *hwc,
++					     const struct clk_ops *ops,
++					     unsigned long min_rate,
++					     unsigned long pct80_rate,
++					     const char *fmt, int idx)
++{
++	struct clk_init_data init = {};
++	struct clk *clk;
++	const struct clockgen_pll_div *div;
++	const char *parent_names[NUM_MUX_PARENTS];
++	char name[32];
++	int i, j;
+ 
+-	cmux_clk->reg = of_iomap(np, 0);
+-	if (!cmux_clk->reg) {
+-		pr_err("%s: could not map register\n", __func__);
+-		goto err_clk;
+-	}
++	snprintf(name, sizeof(name), fmt, idx);
+ 
+-	rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0,
+-					&clkspec);
+-	if (rc) {
+-		pr_err("%s: parse clock node error\n", __func__);
+-		goto err_clk;
+-	}
++	for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) {
++		unsigned long rate;
+ 
+-	cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np,
+-			"clock-output-names");
+-	of_node_put(clkspec.np);
++		hwc->clksel_to_parent[i] = -1;
+ 
+-	node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
+-	if (node && (offset >= 0x80))
+-		cmux_clk->flags = CLKSEL_ADJUST;
++		div = get_pll_div(cg, hwc, i);
++		if (!div)
++			continue;
+ 
+-	rc = of_property_read_string_index(np, "clock-output-names",
+-					   0, &clk_name);
+-	if (rc) {
+-		pr_err("%s: read clock names error\n", np->name);
+-		goto err_clk;
++		rate = clk_get_rate(div->clk);
++
++		if (hwc->info->clksel[i].flags & CLKSEL_80PCT &&
++		    rate > pct80_rate)
++			continue;
++		if (rate < min_rate)
++			continue;
++
++		parent_names[j] = div->name;
++		hwc->parent_to_clksel[j] = i;
++		hwc->clksel_to_parent[i] = j;
++		j++;
+ 	}
+ 
+-	init.name = clk_name;
+-	init.ops = &cmux_ops;
++	init.name = name;
++	init.ops = ops;
+ 	init.parent_names = parent_names;
+-	init.num_parents = count;
++	init.num_parents = hwc->num_parents = j;
+ 	init.flags = 0;
+-	cmux_clk->hw.init = &init;
++	hwc->hw.init = &init;
++	hwc->cg = cg;
+ 
+-	clk = clk_register(NULL, &cmux_clk->hw);
++	clk = clk_register(NULL, &hwc->hw);
+ 	if (IS_ERR(clk)) {
+-		pr_err("%s: could not register clock\n", clk_name);
+-		goto err_clk;
++		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
++		       PTR_ERR(clk));
++		kfree(hwc);
++		return NULL;
++	}
++
++	return clk;
++}
++
++static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
++{
++	struct mux_hwclock *hwc;
++	const struct clockgen_pll_div *div;
++	unsigned long plat_rate, min_rate;
++	u64 pct80_rate;
++	u32 clksel;
++
++	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
++	if (!hwc)
++		return NULL;
++
++	hwc->reg = cg->regs + 0x20 * idx;
++	hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]];
++
++	/*
++	 * Find the rate for the default clksel, and treat it as the
++	 * maximum rated core frequency.  If this is an incorrect
++	 * assumption, certain clock options (possibly including the
++	 * default clksel) may be inappropriately excluded on certain
++	 * chips.
++	 */
++	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
++	div = get_pll_div(cg, hwc, clksel);
++	if (!div)
++		return NULL;
++
++	pct80_rate = clk_get_rate(div->clk);
++	pct80_rate *= 8;
++	do_div(pct80_rate, 10);
++
++	plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk);
++
++	if (cg->info.flags & CG_CMUX_GE_PLAT)
++		min_rate = plat_rate;
++	else
++		min_rate = plat_rate / 2;
++
++	return create_mux_common(cg, hwc, &cmux_ops, min_rate,
++				 pct80_rate, "cg-cmux%d", idx);
++}
++
++static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx)
++{
++	struct mux_hwclock *hwc;
++
++	hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
++	if (!hwc)
++		return NULL;
++
++	hwc->reg = cg->regs + 0x20 * idx + 0x10;
++	hwc->info = cg->info.hwaccel[idx];
++
++	return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0,
++				 "cg-hwaccel%d", idx);
++}
++
++static void __init create_muxes(struct clockgen *cg)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) {
++		if (cg->info.cmux_to_group[i] < 0)
++			break;
++		if (cg->info.cmux_to_group[i] >=
++		    ARRAY_SIZE(cg->info.cmux_groups)) {
++			WARN_ON_ONCE(1);
++			continue;
++		}
++
++		cg->cmux[i] = create_one_cmux(cg, i);
+ 	}
+ 
++	for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) {
++		if (!cg->info.hwaccel[i])
++			continue;
++
++		cg->hwaccel[i] = create_one_hwaccel(cg, i);
++	}
++}
++
++static void __init clockgen_init(struct device_node *np);
++
++/* Legacy nodes may get probed before the parent clockgen node */
++static void __init legacy_init_clockgen(struct device_node *np)
++{
++	if (!clockgen.node)
++		clockgen_init(of_get_parent(np));
++}
++
++/* Legacy node */
++static void __init core_mux_init(struct device_node *np)
++{
++	struct clk *clk;
++	struct resource res;
++	int idx, rc;
++
++	legacy_init_clockgen(np);
++
++	if (of_address_to_resource(np, 0, &res))
++		return;
++
++	idx = (res.start & 0xf0) >> 5;
++	clk = clockgen.cmux[idx];
++
+ 	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ 	if (rc) {
+-		pr_err("Could not register clock provider for node:%s\n",
+-		       np->name);
+-		goto err_clk;
++		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
++		       __func__, np->name, rc);
++		return;
+ 	}
+-	goto err_name;
++}
+ 
+-err_clk:
+-	kfree(cmux_clk);
+-err_name:
+-	/* free *_names because they are reallocated when registered */
+-	kfree(parent_names);
++static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
++{
++	u32 rate;
++
++	if (of_property_read_u32(node, "clock-frequency", &rate))
++		return ERR_PTR(-ENODEV);
++
++	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+ }
+ 
+-static void __init core_pll_init(struct device_node *np)
++static struct clk *sysclk_from_parent(const char *name)
++{
++	struct clk *clk;
++	const char *parent_name;
++
++	clk = of_clk_get(clockgen.node, 0);
++	if (IS_ERR(clk))
++		return clk;
++
++	/* Register the input clock under the desired name. */
++	parent_name = __clk_get_name(clk);
++	clk = clk_register_fixed_factor(NULL, name, parent_name,
++					0, 1, 1);
++	if (IS_ERR(clk))
++		pr_err("%s: Couldn't register %s: %ld\n", __func__, name,
++		       PTR_ERR(clk));
++
++	return clk;
++}
++
++static struct clk * __init create_sysclk(const char *name)
++{
++	struct device_node *sysclk;
++	struct clk *clk;
++
++	clk = sysclk_from_fixed(clockgen.node, name);
++	if (!IS_ERR(clk))
++		return clk;
++
++	clk = sysclk_from_parent(name);
++	if (!IS_ERR(clk))
++		return clk;
++
++	sysclk = of_get_child_by_name(clockgen.node, "sysclk");
++	if (sysclk) {
++		clk = sysclk_from_fixed(sysclk, name);
++		if (!IS_ERR(clk))
++			return clk;
++	}
++
++	pr_err("%s: No input clock\n", __func__);
++	return NULL;
++}
++
++/* Legacy node */
++static void __init sysclk_init(struct device_node *node)
++{
++	struct clk *clk;
++
++	legacy_init_clockgen(node);
++
++	clk = clockgen.sysclk;
++	if (clk)
++		of_clk_add_provider(node, of_clk_src_simple_get, clk);
++}
++
++#define PLL_KILL BIT(31)
++
++static void __init create_one_pll(struct clockgen *cg, int idx)
+ {
++	u32 __iomem *reg;
+ 	u32 mult;
+-	int i, rc, count;
+-	const char *clk_name, *parent_name;
+-	struct clk_onecell_data *onecell_data;
+-	struct clk      **subclks;
+-	void __iomem *base;
++	struct clockgen_pll *pll = &cg->pll[idx];
++	int i;
+ 
+-	base = of_iomap(np, 0);
+-	if (!base) {
+-		pr_err("iomap error\n");
++	if (!(cg->info.pll_mask & (1 << idx)))
+ 		return;
+-	}
+ 
+-	/* get the multiple of PLL */
+-	mult = ioread32be(base);
++	if (idx == PLATFORM_PLL)
++		reg = cg->regs + 0xc00;
++	else
++		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
+ 
+-	/* check if this PLL is disabled */
++	/* Get the multiple of PLL */
++	mult = ioread32be(reg);
++
++	/* Check if this PLL is disabled */
+ 	if (mult & PLL_KILL) {
+-		pr_debug("PLL:%s is disabled\n", np->name);
+-		goto err_map;
++		pr_debug("%s(): pll %p disabled\n", __func__, reg);
++		return;
+ 	}
+-	mult = (mult >> 1) & 0x3f;
+ 
+-	parent_name = of_clk_get_parent_name(np, 0);
+-	if (!parent_name) {
+-		pr_err("PLL: %s must have a parent\n", np->name);
+-		goto err_map;
++	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
++		mult = (mult & GENMASK(8, 1)) >> 1;
++	else
++		mult = (mult & GENMASK(6, 1)) >> 1;
++
++	for (i = 0; i < ARRAY_SIZE(pll->div); i++) {
++		struct clk *clk;
++
++		snprintf(pll->div[i].name, sizeof(pll->div[i].name),
++			 "cg-pll%d-div%d", idx, i + 1);
++
++		clk = clk_register_fixed_factor(NULL,
++				pll->div[i].name, "cg-sysclk", 0, mult, i + 1);
++		if (IS_ERR(clk)) {
++			pr_err("%s: %s: register failed %ld\n",
++			       __func__, pll->div[i].name, PTR_ERR(clk));
++			continue;
++		}
++
++		pll->div[i].clk = clk;
+ 	}
++}
++
++static void __init create_plls(struct clockgen *cg)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(cg->pll); i++)
++		create_one_pll(cg, i);
++}
+ 
++static void __init legacy_pll_init(struct device_node *np, int idx)
++{
++	struct clockgen_pll *pll;
++	struct clk_onecell_data *onecell_data;
++	struct clk **subclks;
++	int count, rc;
++
++	legacy_init_clockgen(np);
++
++	pll = &clockgen.pll[idx];
+ 	count = of_property_count_strings(np, "clock-output-names");
+-	if (count < 0 || count > 4) {
+-		pr_err("%s: clock is not supported\n", np->name);
+-		goto err_map;
+-	}
+ 
+-	subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
++	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
++	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
+ 	if (!subclks)
+-		goto err_map;
++		return;
+ 
+ 	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
+ 	if (!onecell_data)
+ 		goto err_clks;
+ 
+-	for (i = 0; i < count; i++) {
+-		rc = of_property_read_string_index(np, "clock-output-names",
+-						   i, &clk_name);
+-		if (rc) {
+-			pr_err("%s: could not get clock names\n", np->name);
+-			goto err_cell;
+-		}
+-
+-		/*
+-		 * when count == 4, there are 4 output clocks:
+-		 * /1, /2, /3, /4 respectively
+-		 * when count < 4, there are at least 2 output clocks:
+-		 * /1, /2, (/4, if count == 3) respectively.
+-		 */
+-		if (count == 4)
+-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+-					parent_name, 0, mult, 1 + i);
+-		else
+-
+-			subclks[i] = clk_register_fixed_factor(NULL, clk_name,
+-					parent_name, 0, mult, 1 << i);
+-
+-		if (IS_ERR(subclks[i])) {
+-			pr_err("%s: could not register clock\n", clk_name);
+-			goto err_cell;
+-		}
++	if (count <= 3) {
++		subclks[0] = pll->div[0].clk;
++		subclks[1] = pll->div[1].clk;
++		subclks[2] = pll->div[3].clk;
++	} else {
++		subclks[0] = pll->div[0].clk;
++		subclks[1] = pll->div[1].clk;
++		subclks[2] = pll->div[2].clk;
++		subclks[3] = pll->div[3].clk;
+ 	}
+ 
+ 	onecell_data->clks = subclks;
+@@ -233,125 +956,221 @@ static void __init core_pll_init(struct device_node *np)
+ 
+ 	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
+ 	if (rc) {
+-		pr_err("Could not register clk provider for node:%s\n",
+-		       np->name);
++		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
++		       __func__, np->name, rc);
+ 		goto err_cell;
+ 	}
+ 
+-	iounmap(base);
+ 	return;
+ err_cell:
+ 	kfree(onecell_data);
+ err_clks:
+ 	kfree(subclks);
+-err_map:
+-	iounmap(base);
+ }
+ 
+-static void __init sysclk_init(struct device_node *node)
++/* Legacy node */
++static void __init pltfrm_pll_init(struct device_node *np)
+ {
+-	struct clk *clk;
+-	const char *clk_name = node->name;
+-	struct device_node *np = of_get_parent(node);
+-	u32 rate;
++	legacy_pll_init(np, PLATFORM_PLL);
++}
+ 
+-	if (!np) {
+-		pr_err("could not get parent node\n");
++/* Legacy node */
++static void __init core_pll_init(struct device_node *np)
++{
++	struct resource res;
++	int idx;
++
++	if (of_address_to_resource(np, 0, &res))
+ 		return;
++
++	if ((res.start & 0xfff) == 0xc00) {
++		/*
++		 * ls1021a devtree labels the platform PLL
++		 * with the core PLL compatible
++		 */
++		pltfrm_pll_init(np);
++	} else {
++		idx = (res.start & 0xf0) >> 5;
++		legacy_pll_init(np, CGA_PLL1 + idx);
+ 	}
++}
+ 
+-	if (of_property_read_u32(np, "clock-frequency", &rate)) {
+-		of_node_put(node);
+-		return;
++static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct clockgen *cg = data;
++	struct clk *clk;
++	struct clockgen_pll *pll;
++	u32 type, idx;
++
++	if (clkspec->args_count < 2) {
++		pr_err("%s: insufficient phandle args\n", __func__);
++		return ERR_PTR(-EINVAL);
+ 	}
+ 
+-	of_property_read_string(np, "clock-output-names", &clk_name);
++	type = clkspec->args[0];
++	idx = clkspec->args[1];
+ 
+-	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
+-	if (!IS_ERR(clk))
+-		of_clk_add_provider(np, of_clk_src_simple_get, clk);
++	switch (type) {
++	case 0:
++		if (idx != 0)
++			goto bad_args;
++		clk = cg->sysclk;
++		break;
++	case 1:
++		if (idx >= ARRAY_SIZE(cg->cmux))
++			goto bad_args;
++		clk = cg->cmux[idx];
++		break;
++	case 2:
++		if (idx >= ARRAY_SIZE(cg->hwaccel))
++			goto bad_args;
++		clk = cg->hwaccel[idx];
++		break;
++	case 3:
++		if (idx >= ARRAY_SIZE(cg->fman))
++			goto bad_args;
++		clk = cg->fman[idx];
++		break;
++	case 4:
++		pll = &cg->pll[PLATFORM_PLL];
++		if (idx >= ARRAY_SIZE(pll->div))
++			goto bad_args;
++		clk = pll->div[idx].clk;
++		break;
++	default:
++		goto bad_args;
++	}
++
++	if (!clk)
++		return ERR_PTR(-ENOENT);
++	return clk;
++
++bad_args:
++	pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx);
++	return ERR_PTR(-EINVAL);
+ }
+ 
+-static void __init pltfrm_pll_init(struct device_node *np)
++#ifdef CONFIG_PPC
++#include <asm/mpc85xx.h>
++
++static const u32 a4510_svrs[] __initconst = {
++	(SVR_P2040 << 8) | 0x10,	/* P2040 1.0 */
++	(SVR_P2040 << 8) | 0x11,	/* P2040 1.1 */
++	(SVR_P2041 << 8) | 0x10,	/* P2041 1.0 */
++	(SVR_P2041 << 8) | 0x11,	/* P2041 1.1 */
++	(SVR_P3041 << 8) | 0x10,	/* P3041 1.0 */
++	(SVR_P3041 << 8) | 0x11,	/* P3041 1.1 */
++	(SVR_P4040 << 8) | 0x20,	/* P4040 2.0 */
++	(SVR_P4080 << 8) | 0x20,	/* P4080 2.0 */
++	(SVR_P5010 << 8) | 0x10,	/* P5010 1.0 */
++	(SVR_P5010 << 8) | 0x20,	/* P5010 2.0 */
++	(SVR_P5020 << 8) | 0x10,	/* P5020 1.0 */
++	(SVR_P5021 << 8) | 0x10,	/* P5021 1.0 */
++	(SVR_P5040 << 8) | 0x10,	/* P5040 1.0 */
++};
++
++#define SVR_SECURITY	0x80000	/* The Security (E) bit */
++
++static bool __init has_erratum_a4510(void)
+ {
+-	void __iomem *base;
+-	uint32_t mult;
+-	const char *parent_name, *clk_name;
+-	int i, _errno;
+-	struct clk_onecell_data *cod;
+-
+-	base = of_iomap(np, 0);
+-	if (!base) {
+-		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
+-		return;
++	u32 svr = mfspr(SPRN_SVR);
++	int i;
++
++	svr &= ~SVR_SECURITY;
++
++	for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) {
++		if (svr == a4510_svrs[i])
++			return true;
+ 	}
+ 
+-	/* Get the multiple of PLL */
+-	mult = ioread32be(base);
++	return false;
++}
++#else
++static bool __init has_erratum_a4510(void)
++{
++	return false;
++}
++#endif
+ 
+-	iounmap(base);
++static void __init clockgen_init(struct device_node *np)
++{
++	int i, ret;
++	bool is_old_ls1021a = false;
+ 
+-	/* Check if this PLL is disabled */
+-	if (mult & PLL_KILL) {
+-		pr_debug("%s(): %s: Disabled\n", __func__, np->name);
++	/* May have already been called by a legacy probe */
++	if (clockgen.node)
+ 		return;
+-	}
+-	mult = (mult & GENMASK(6, 1)) >> 1;
+ 
+-	parent_name = of_clk_get_parent_name(np, 0);
+-	if (!parent_name) {
+-		pr_err("%s(): %s: of_clk_get_parent_name() failed\n",
+-		       __func__, np->name);
++	clockgen.node = np;
++	clockgen.regs = of_iomap(np, 0);
++	if (!clockgen.regs &&
++	    of_device_is_compatible(of_root, "fsl,ls1021a")) {
++		/* Compatibility hack for old, broken device trees */
++		clockgen.regs = ioremap(0x1ee1000, 0x1000);
++		is_old_ls1021a = true;
++	}
++	if (!clockgen.regs) {
++		pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
+ 		return;
+ 	}
+ 
+-	i = of_property_count_strings(np, "clock-output-names");
+-	if (i < 0) {
+-		pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n",
+-		       __func__, np->name, i);
+-		return;
++	for (i = 0; i < ARRAY_SIZE(chipinfo); i++) {
++		if (of_device_is_compatible(np, chipinfo[i].compat))
++			break;
++		if (is_old_ls1021a &&
++		    !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen"))
++			break;
+ 	}
+ 
+-	cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL);
+-	if (!cod)
+-		return;
+-	cod->clks = (struct clk **)(cod + 1);
+-	cod->clk_num = i;
+-
+-	for (i = 0; i < cod->clk_num; i++) {
+-		_errno = of_property_read_string_index(np, "clock-output-names",
+-						       i, &clk_name);
+-		if (_errno < 0) {
+-			pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n",
+-			       __func__, np->name, _errno);
+-			goto return_clk_unregister;
+-		}
++	if (i == ARRAY_SIZE(chipinfo)) {
++		pr_err("%s: unknown clockgen node %s\n", __func__,
++		       np->full_name);
++		goto err;
++	}
++	clockgen.info = chipinfo[i];
++
++	if (clockgen.info.guts_compat) {
++		struct device_node *guts;
+ 
+-		cod->clks[i] = clk_register_fixed_factor(NULL, clk_name,
+-					       parent_name, 0, mult, 1 + i);
+-		if (IS_ERR(cod->clks[i])) {
+-			pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n",
+-			       __func__, np->name,
+-			       clk_name, PTR_ERR(cod->clks[i]));
+-			goto return_clk_unregister;
++		guts = of_find_compatible_node(NULL, NULL,
++					       clockgen.info.guts_compat);
++		if (guts) {
++			clockgen.guts = of_iomap(guts, 0);
++			if (!clockgen.guts) {
++				pr_err("%s: Couldn't map %s regs\n", __func__,
++				       guts->full_name);
++			}
+ 		}
++
+ 	}
+ 
+-	_errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod);
+-	if (_errno < 0) {
+-		pr_err("%s(): %s: of_clk_add_provider() = %d\n",
+-		       __func__, np->name, _errno);
+-		goto return_clk_unregister;
++	if (has_erratum_a4510())
++		clockgen.info.flags |= CG_CMUX_GE_PLAT;
++
++	clockgen.sysclk = create_sysclk("cg-sysclk");
++	create_plls(&clockgen);
++	create_muxes(&clockgen);
++
++	if (clockgen.info.init_periph)
++		clockgen.info.init_periph(&clockgen);
++
++	ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
++	if (ret) {
++		pr_err("%s: Couldn't register clk provider for node %s: %d\n",
++		       __func__, np->name, ret);
+ 	}
+ 
+ 	return;
+-
+-return_clk_unregister:
+-	while (--i >= 0)
+-		clk_unregister(cod->clks[i]);
+-	kfree(cod);
++err:
++	iounmap(clockgen.regs);
++	clockgen.regs = NULL;
+ }
+ 
++CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
++CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
++CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
++
++/* Legacy nodes */
+ CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
+ CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init);
+ CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init);
+-- 
+1.7.9.5
+
+
+From 78928e732bdd8aec43f25c78e29f677730d13232 Mon Sep 17 00:00:00 2001
+From: Scott Wood <scottwood@freescale.com>
+Date: Sat, 19 Sep 2015 23:29:55 -0500
+Subject: [PATCH 15/66] clk: qoriq: Add ls2080a support.
+
+LS2080A is the first implementation of the chassis 3 clockgen, which
+has a different register layout than previous chips.  It is also little
+endian, unlike previous chips.
+
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+Acked-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/Kconfig     |    2 +-
+ drivers/clk/clk-qoriq.c |   77 +++++++++++++++++++++++++++++++++++++++++------
+ 2 files changed, 69 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
+index 42f7120..9f1970c 100644
+--- a/drivers/clk/Kconfig
++++ b/drivers/clk/Kconfig
+@@ -121,7 +121,7 @@ config COMMON_CLK_AXI_CLKGEN
+ 
+ config CLK_QORIQ
+ 	bool "Clock driver for Freescale QorIQ platforms"
+-	depends on (PPC_E500MC || ARM) && OF
++	depends on (PPC_E500MC || ARM || ARM64) && OF
+ 	---help---
+ 	  This adds the clock driver support for Freescale QorIQ platforms
+ 	  using common clock framework.
+diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
+index 06281a3..8f9c93b 100644
+--- a/drivers/clk/clk-qoriq.c
++++ b/drivers/clk/clk-qoriq.c
+@@ -68,7 +68,10 @@ struct clockgen;
+  * If not set, cmux freq must be >= platform pll/2
+  */
+ #define CG_CMUX_GE_PLAT		1
++
+ #define CG_PLL_8BIT		2	/* PLLCnGSR[CFG] is 8 bits, not 6 */
++#define CG_VER3			4	/* version 3 cg: reg layout different */
++#define CG_LITTLE_ENDIAN	8
+ 
+ struct clockgen_chipinfo {
+ 	const char *compat, *guts_compat;
+@@ -94,6 +97,26 @@ struct clockgen {
+ 
+ static struct clockgen clockgen;
+ 
++static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg)
++{
++	if (cg->info.flags & CG_LITTLE_ENDIAN)
++		iowrite32(val, reg);
++	else
++		iowrite32be(val, reg);
++}
++
++static u32 cg_in(struct clockgen *cg, u32 __iomem *reg)
++{
++	u32 val;
++
++	if (cg->info.flags & CG_LITTLE_ENDIAN)
++		val = ioread32(reg);
++	else
++		val = ioread32be(reg);
++
++	return val;
++}
++
+ static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+ 	{
+ 		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+@@ -429,6 +452,17 @@ static const struct clockgen_chipinfo chipinfo[] = {
+ 		.pll_mask = 0x03,
+ 	},
+ 	{
++		.compat = "fsl,ls2080a-clockgen",
++		.cmux_groups = {
++			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
++		},
++		.cmux_to_group = {
++			0, 0, 1, 1, -1
++		},
++		.pll_mask = 0x37,
++		.flags = CG_VER3 | CG_LITTLE_ENDIAN,
++	},
++	{
+ 		.compat = "fsl,p2041-clockgen",
+ 		.guts_compat = "fsl,qoriq-device-config-1.0",
+ 		.init_periph = p2041_init_periph,
+@@ -575,7 +609,7 @@ static int mux_set_parent(struct clk_hw *hw, u8 idx)
+ 		return -EINVAL;
+ 
+ 	clksel = hwc->parent_to_clksel[idx];
+-	iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
++	cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg);
+ 
+ 	return 0;
+ }
+@@ -586,7 +620,7 @@ static u8 mux_get_parent(struct clk_hw *hw)
+ 	u32 clksel;
+ 	s8 ret;
+ 
+-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
++	clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+ 
+ 	ret = hwc->clksel_to_parent[clksel];
+ 	if (ret < 0) {
+@@ -705,7 +739,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
+ 	 * default clksel) may be inappropriately excluded on certain
+ 	 * chips.
+ 	 */
+-	clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
++	clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
+ 	div = get_pll_div(cg, hwc, clksel);
+ 	if (!div)
+ 		return NULL;
+@@ -874,13 +908,36 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
+ 	if (!(cg->info.pll_mask & (1 << idx)))
+ 		return;
+ 
+-	if (idx == PLATFORM_PLL)
+-		reg = cg->regs + 0xc00;
+-	else
+-		reg = cg->regs + 0x800 + 0x20 * (idx - 1);
++	if (cg->info.flags & CG_VER3) {
++		switch (idx) {
++		case PLATFORM_PLL:
++			reg = cg->regs + 0x60080;
++			break;
++		case CGA_PLL1:
++			reg = cg->regs + 0x80;
++			break;
++		case CGA_PLL2:
++			reg = cg->regs + 0xa0;
++			break;
++		case CGB_PLL1:
++			reg = cg->regs + 0x10080;
++			break;
++		case CGB_PLL2:
++			reg = cg->regs + 0x100a0;
++			break;
++		default:
++			WARN_ONCE(1, "index %d\n", idx);
++			return;
++		}
++	} else {
++		if (idx == PLATFORM_PLL)
++			reg = cg->regs + 0xc00;
++		else
++			reg = cg->regs + 0x800 + 0x20 * (idx - 1);
++	}
+ 
+ 	/* Get the multiple of PLL */
+-	mult = ioread32be(reg);
++	mult = cg_in(cg, reg);
+ 
+ 	/* Check if this PLL is disabled */
+ 	if (mult & PLL_KILL) {
+@@ -888,7 +945,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
+ 		return;
+ 	}
+ 
+-	if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)
++	if ((cg->info.flags & CG_VER3) ||
++	    ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL))
+ 		mult = (mult & GENMASK(8, 1)) >> 1;
+ 	else
+ 		mult = (mult & GENMASK(6, 1)) >> 1;
+@@ -1169,6 +1227,7 @@ err:
+ CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
++CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
+ 
+ /* Legacy nodes */
+ CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init);
+-- 
+1.7.9.5
+
+
+From 44ed2523c30406ac7e47522f2f47db1271cc7447 Mon Sep 17 00:00:00 2001
+From: Scott Wood <scottwood@freescale.com>
+Date: Thu, 22 Oct 2015 23:21:46 -0500
+Subject: [PATCH 16/66] clk: qoriq: Fix wrong data in p2041_cmux_grp2
+
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+---
+ drivers/clk/clk-qoriq.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
+index 8f9c93b..07985a5 100644
+--- a/drivers/clk/clk-qoriq.c
++++ b/drivers/clk/clk-qoriq.c
+@@ -128,8 +128,8 @@ static const struct clockgen_muxinfo p2041_cmux_grp1 = {
+ static const struct clockgen_muxinfo p2041_cmux_grp2 = {
+ 	{
+ 		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+-		[4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+-		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		[5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ 	}
+ };
+ 
+-- 
+1.7.9.5
+
+
+From f958ffccdb65510943a8ba7250f218fad2dad02d Mon Sep 17 00:00:00 2001
+From: Hou Zhiqiang <B48286@freescale.com>
+Date: Fri, 23 Oct 2015 16:01:21 +0800
+Subject: [PATCH 17/66] clk: qoriq: Add ls1043a support.
+
+Signed-off-by: Hou Zhiqiang <B48286@freescale.com>
+Acked-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Scott Wood <scottwood@freescale.com>
+---
+ drivers/clk/clk-qoriq.c |   38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
+index 07985a5..1ab0fb8 100644
+--- a/drivers/clk/clk-qoriq.c
++++ b/drivers/clk/clk-qoriq.c
+@@ -244,6 +244,28 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
+ 	},
+ };
+ 
++static const struct clockgen_muxinfo ls1043a_hwa1 = {
++	{
++		{},
++		{},
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
++		{},
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++	},
++};
++
++static const struct clockgen_muxinfo ls1043a_hwa2 = {
++	{
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
++		{},
++		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
++	},
++};
++
+ static const struct clockgen_muxinfo t1023_hwa1 = {
+ 	{
+ 		{},
+@@ -452,6 +474,21 @@ static const struct clockgen_chipinfo chipinfo[] = {
+ 		.pll_mask = 0x03,
+ 	},
+ 	{
++		.compat = "fsl,ls1043a-clockgen",
++		.init_periph = t2080_init_periph,
++		.cmux_groups = {
++			&t1040_cmux
++		},
++		.hwaccel = {
++			&ls1043a_hwa1, &ls1043a_hwa2
++		},
++		.cmux_to_group = {
++			0, -1
++		},
++		.pll_mask = 0x07,
++		.flags = CG_PLL_8BIT,
++	},
++	{
+ 		.compat = "fsl,ls2080a-clockgen",
+ 		.cmux_groups = {
+ 			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
+@@ -1227,6 +1264,7 @@ err:
+ CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
++CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
+ CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
+ 
+ /* Legacy nodes */
+-- 
+1.7.9.5
+
+
+From 4354e44116626cddeb606f5151cbcc114610a09c Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Mon, 7 Sep 2015 16:23:14 +0800
+Subject: [PATCH 18/66] Revert "ahci: added support for Freescale AHCI sata"
+
+This reverts commit 5163fb62541e
+("ahci: added support for Freescale AHCI sata")
+
+The reverted patch added Freescale QorIQ AHCI sata support to
+ahci_platform driver though, but it left SoC specific settings to uboot.
+It leads to QorIQ sata heavily depending on uboot. In order to removing
+the dependency we first revert the old patch and then will add a new driver
+for QorIQ SATA.
+Since there are no LS* platforms that have been upstreamed, So
+the revert would not break anything exists.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ .../devicetree/bindings/ata/ahci-platform.txt      |    2 --
+ drivers/ata/ahci_platform.c                        |    1 -
+ 2 files changed, 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+index a232181..c2340ee 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
+@@ -16,8 +16,6 @@ Required properties:
+   - "snps,dwc-ahci"
+   - "snps,exynos5440-ahci"
+   - "snps,spear-ahci"
+-  - "fsl,qoriq-ahci" : for qoriq series socs which include ls1021, ls2085, etc.
+-  - "fsl,<chip>-ahci" : chip could be ls1021, ls2085 etc.
+   - "generic-ahci"
+ - interrupts        : <interrupt mapping for SATA IRQ>
+ - reg               : <registers mapping>
+diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
+index 1befb11..04975b8 100644
+--- a/drivers/ata/ahci_platform.c
++++ b/drivers/ata/ahci_platform.c
+@@ -76,7 +76,6 @@ static const struct of_device_id ahci_of_match[] = {
+ 	{ .compatible = "ibm,476gtr-ahci", },
+ 	{ .compatible = "snps,dwc-ahci", },
+ 	{ .compatible = "hisilicon,hisi-ahci", },
+-	{ .compatible = "fsl,qoriq-ahci", },
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(of, ahci_of_match);
+-- 
+1.7.9.5
+
+
+From 7a07069e9a4a5960a2dbae6f6720148a14791d19 Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Mon, 7 Sep 2015 16:23:15 +0800
+Subject: [PATCH 19/66] devicetree:bindings: add devicetree bindings for
+ Freescale AHCI
+
+adds bindings for Freescale QorIQ AHCI SATA controller.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ .../devicetree/bindings/ata/ahci-fsl-qoriq.txt     |   21 ++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+new file mode 100644
+index 0000000..b614e3b
+--- /dev/null
++++ b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+@@ -0,0 +1,21 @@
++Binding for Freescale QorIQ AHCI SATA Controller
++
++Required properties:
++  - reg: Physical base address and size of the controller's register area.
++  - compatible: Compatibility string. Must be 'fsl,<chip>-ahci', where
++    chip could be ls1021a, ls2085a, ls1043a etc.
++  - clocks: Input clock specifier. Refer to common clock bindings.
++  - interrupts: Interrupt specifier. Refer to interrupt binding.
++
++Optional properties:
++  - dma-coherent: Enable ACHI coherency DMA operation.
++  - reg-names: register area names when there are more then 1 regster area.
++
++Examples:
++	sata@3200000 {
++		compatible = "fsl,ls1021a-ahci";
++		reg = <0x0 0x3200000 0x0 0x10000>;
++		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
++		clocks = <&platform_clk 1>;
++		dma-coherent;
++	};
+-- 
+1.7.9.5
+
+
+From 05816af311558b592b8cc711cd54996da14191ba Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Mon, 7 Sep 2015 16:23:16 +0800
+Subject: [PATCH 20/66] ahci: added a new driver for supporting Freescale AHCI
+ sata
+
+Currently Freescale QorIQ series SATA is supported by ahci_platform
+driver. Some SoC specific settings have been put in uboot. So whether
+SATA works or not heavily depends on uboot.
+This patch will add a new driver to support QorIQ sata which removes
+the dependency on any other boot loader.
+Freescale QorIQ series sata, like ls1021a ls2085a ls1043a, is
+compatible with serial ATA 3.0 and AHCI 1.3 specification.
+
+Signed-off-by: Yuantian Tang <Yuantian.Tang@freescale.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ drivers/ata/Kconfig      |    9 ++
+ drivers/ata/Makefile     |    1 +
+ drivers/ata/ahci_qoriq.c |  272 ++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 282 insertions(+)
+ create mode 100644 drivers/ata/ahci_qoriq.c
+
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index 15e40ee..6aaa3f8 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -175,6 +175,15 @@ config AHCI_XGENE
+ 	help
+ 	 This option enables support for APM X-Gene SoC SATA host controller.
+ 
++config AHCI_QORIQ
++	tristate "Freescale QorIQ AHCI SATA support"
++	depends on OF
++	help
++	  This option enables support for the Freescale QorIQ AHCI SoC's
++	  onboard AHCI SATA.
++
++	  If unsure, say N.
++
+ config SATA_FSL
+ 	tristate "Freescale 3.0Gbps SATA support"
+ 	depends on FSL_SOC
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index af70919..af45eff 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -19,6 +19,7 @@ obj-$(CONFIG_AHCI_SUNXI)	+= ahci_sunxi.o libahci.o libahci_platform.o
+ obj-$(CONFIG_AHCI_ST)		+= ahci_st.o libahci.o libahci_platform.o
+ obj-$(CONFIG_AHCI_TEGRA)	+= ahci_tegra.o libahci.o libahci_platform.o
+ obj-$(CONFIG_AHCI_XGENE)	+= ahci_xgene.o libahci.o libahci_platform.o
++obj-$(CONFIG_AHCI_QORIQ)	+= ahci_qoriq.o libahci.o libahci_platform.o
+ 
+ # SFF w/ custom DMA
+ obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+new file mode 100644
+index 0000000..e5e4988
+--- /dev/null
++++ b/drivers/ata/ahci_qoriq.c
+@@ -0,0 +1,272 @@
++/*
++ * Freescale QorIQ AHCI SATA platform driver
++ *
++ * Copyright 2015 Freescale, Inc.
++ *   Tang Yuantian <Yuantian.Tang@freescale.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/pm.h>
++#include <linux/ahci_platform.h>
++#include <linux/device.h>
++#include <linux/of_address.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/libata.h>
++#include "ahci.h"
++
++#define DRV_NAME "ahci-qoriq"
++
++/* port register definition */
++#define PORT_PHY1	0xA8
++#define PORT_PHY2	0xAC
++#define PORT_PHY3	0xB0
++#define PORT_PHY4	0xB4
++#define PORT_PHY5	0xB8
++#define PORT_TRANS	0xC8
++
++/* port register default value */
++#define AHCI_PORT_PHY_1_CFG	0xa003fffe
++#define AHCI_PORT_PHY_2_CFG	0x28183411
++#define AHCI_PORT_PHY_3_CFG	0x0e081004
++#define AHCI_PORT_PHY_4_CFG	0x00480811
++#define AHCI_PORT_PHY_5_CFG	0x192c96a4
++#define AHCI_PORT_TRANS_CFG	0x08000025
++
++#define SATA_ECC_DISABLE	0x00020000
++
++enum ahci_qoriq_type {
++	AHCI_LS1021A,
++	AHCI_LS1043A,
++	AHCI_LS2085A,
++};
++
++struct ahci_qoriq_priv {
++	struct ccsr_ahci *reg_base;
++	enum ahci_qoriq_type type;
++	void __iomem *ecc_addr;
++};
++
++static const struct of_device_id ahci_qoriq_of_match[] = {
++	{ .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
++	{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
++	{ .compatible = "fsl,ls2085a-ahci", .data = (void *)AHCI_LS2085A},
++	{},
++};
++MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
++
++static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
++			  unsigned long deadline)
++{
++	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
++	void __iomem *port_mmio = ahci_port_base(link->ap);
++	u32 px_cmd, px_is, px_val;
++	struct ata_port *ap = link->ap;
++	struct ahci_port_priv *pp = ap->private_data;
++	struct ahci_host_priv *hpriv = ap->host->private_data;
++	struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data;
++	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
++	struct ata_taskfile tf;
++	bool online;
++	int rc;
++
++	DPRINTK("ENTER\n");
++
++	ahci_stop_engine(ap);
++
++	/*
++	 * There is a errata on ls1021a Rev1.0 and Rev2.0 which is:
++	 * A-009042: The device detection initialization sequence
++	 * mistakenly resets some registers.
++	 *
++	 * Workaround for this is:
++	 * The software should read and store PxCMD and PxIS values
++	 * before issuing the device detection initialization sequence.
++	 * After the sequence is complete, software should restore the
++	 * PxCMD and PxIS with the stored values.
++	 */
++	if (qoriq_priv->type == AHCI_LS1021A) {
++		px_cmd = readl(port_mmio + PORT_CMD);
++		px_is = readl(port_mmio + PORT_IRQ_STAT);
++	}
++
++	/* clear D2H reception area to properly wait for D2H FIS */
++	ata_tf_init(link->device, &tf);
++	tf.command = ATA_BUSY;
++	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
++
++	rc = sata_link_hardreset(link, timing, deadline, &online,
++				 ahci_check_ready);
++
++	/* restore the PxCMD and PxIS on ls1021 */
++	if (qoriq_priv->type == AHCI_LS1021A) {
++		px_val = readl(port_mmio + PORT_CMD);
++		if (px_val != px_cmd)
++			writel(px_cmd, port_mmio + PORT_CMD);
++
++		px_val = readl(port_mmio + PORT_IRQ_STAT);
++		if (px_val != px_is)
++			writel(px_is, port_mmio + PORT_IRQ_STAT);
++	}
++
++	hpriv->start_engine(ap);
++
++	if (online)
++		*class = ahci_dev_classify(ap);
++
++	DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
++	return rc;
++}
++
++static struct ata_port_operations ahci_qoriq_ops = {
++	.inherits	= &ahci_ops,
++	.hardreset	= ahci_qoriq_hardreset,
++};
++
++static const struct ata_port_info ahci_qoriq_port_info = {
++	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
++	.pio_mask	= ATA_PIO4,
++	.udma_mask	= ATA_UDMA6,
++	.port_ops	= &ahci_qoriq_ops,
++};
++
++static struct scsi_host_template ahci_qoriq_sht = {
++	AHCI_SHT(DRV_NAME),
++};
++
++static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
++{
++	struct ahci_qoriq_priv *qpriv = hpriv->plat_data;
++	void __iomem *reg_base = hpriv->mmio;
++
++	switch (qpriv->type) {
++	case AHCI_LS1021A:
++		writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
++		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
++		writel(AHCI_PORT_PHY_2_CFG, reg_base + PORT_PHY2);
++		writel(AHCI_PORT_PHY_3_CFG, reg_base + PORT_PHY3);
++		writel(AHCI_PORT_PHY_4_CFG, reg_base + PORT_PHY4);
++		writel(AHCI_PORT_PHY_5_CFG, reg_base + PORT_PHY5);
++		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
++		break;
++
++	case AHCI_LS1043A:
++	case AHCI_LS2085A:
++		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
++		break;
++	}
++
++	return 0;
++}
++
++static int ahci_qoriq_probe(struct platform_device *pdev)
++{
++	struct device_node *np = pdev->dev.of_node;
++	struct device *dev = &pdev->dev;
++	struct ahci_host_priv *hpriv;
++	struct ahci_qoriq_priv *qoriq_priv;
++	const struct of_device_id *of_id;
++	struct resource *res;
++	int rc;
++
++	hpriv = ahci_platform_get_resources(pdev);
++	if (IS_ERR(hpriv))
++		return PTR_ERR(hpriv);
++
++	of_id = of_match_node(ahci_qoriq_of_match, np);
++	if (!of_id)
++		return -ENODEV;
++
++	qoriq_priv = devm_kzalloc(dev, sizeof(*qoriq_priv), GFP_KERNEL);
++	if (!qoriq_priv)
++		return -ENOMEM;
++
++	qoriq_priv->type = (enum ahci_qoriq_type)of_id->data;
++
++	if (qoriq_priv->type == AHCI_LS1021A) {
++		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++				"sata-ecc");
++		qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
++		if (IS_ERR(qoriq_priv->ecc_addr))
++			return PTR_ERR(qoriq_priv->ecc_addr);
++	}
++
++	rc = ahci_platform_enable_resources(hpriv);
++	if (rc)
++		return rc;
++
++	hpriv->plat_data = qoriq_priv;
++	rc = ahci_qoriq_phy_init(hpriv);
++	if (rc)
++		goto disable_resources;
++
++	rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info,
++				     &ahci_qoriq_sht);
++	if (rc)
++		goto disable_resources;
++
++	return 0;
++
++disable_resources:
++	ahci_platform_disable_resources(hpriv);
++
++	return rc;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int ahci_qoriq_resume(struct device *dev)
++{
++	struct ata_host *host = dev_get_drvdata(dev);
++	struct ahci_host_priv *hpriv = host->private_data;
++	int rc;
++
++	rc = ahci_platform_enable_resources(hpriv);
++	if (rc)
++		return rc;
++
++	rc = ahci_qoriq_phy_init(hpriv);
++	if (rc)
++		goto disable_resources;
++
++	rc = ahci_platform_resume_host(dev);
++	if (rc)
++		goto disable_resources;
++
++	/* We resumed so update PM runtime state */
++	pm_runtime_disable(dev);
++	pm_runtime_set_active(dev);
++	pm_runtime_enable(dev);
++
++	return 0;
++
++disable_resources:
++	ahci_platform_disable_resources(hpriv);
++
++	return rc;
++}
++#endif
++
++static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend,
++			 ahci_qoriq_resume);
++
++static struct platform_driver ahci_qoriq_driver = {
++	.probe = ahci_qoriq_probe,
++	.remove = ata_platform_remove_one,
++	.driver = {
++		.name = DRV_NAME,
++		.of_match_table = ahci_qoriq_of_match,
++		.pm = &ahci_qoriq_pm_ops,
++	},
++};
++module_platform_driver(ahci_qoriq_driver);
++
++MODULE_DESCRIPTION("Freescale QorIQ AHCI SATA platform driver");
++MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
++MODULE_LICENSE("GPL");
+-- 
+1.7.9.5
+
+
+From 6d0feff9d583b6720d3c4b8d47e3b61ccb04ce4a Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Wed, 14 Oct 2015 16:46:52 +0800
+Subject: [PATCH 21/66] ahci: qoriq: Fix a compiling warning
+
+kbuild test robot reports the warnings:
+drivers/ata/ahci_qoriq.c: In function 'ahci_qoriq_hardreset':
+>> include/asm-generic/io.h:163:2: warning: 'px_is' may be used
+>> uninitialized in this function [-Wuninitialized]
+drivers/ata/ahci_qoriq.c:70:14: note: 'px_is' was declared here
+>> include/asm-generic/io.h:163:2: warning: 'px_cmd' may be used
+>> uninitialized in this function [-Wuninitialized]
+drivers/ata/ahci_qoriq.c:70:6: note: 'px_cmd' was declared here
+
+This patch fixed it by introducing a local variable.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ drivers/ata/ahci_qoriq.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index e5e4988..58c1a94 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -76,6 +76,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
+ 	struct ata_taskfile tf;
+ 	bool online;
+ 	int rc;
++	bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A);
+ 
+ 	DPRINTK("ENTER\n");
+ 
+@@ -92,7 +93,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
+ 	 * After the sequence is complete, software should restore the
+ 	 * PxCMD and PxIS with the stored values.
+ 	 */
+-	if (qoriq_priv->type == AHCI_LS1021A) {
++	if (ls1021a_workaround) {
+ 		px_cmd = readl(port_mmio + PORT_CMD);
+ 		px_is = readl(port_mmio + PORT_IRQ_STAT);
+ 	}
+@@ -106,7 +107,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
+ 				 ahci_check_ready);
+ 
+ 	/* restore the PxCMD and PxIS on ls1021 */
+-	if (qoriq_priv->type == AHCI_LS1021A) {
++	if (ls1021a_workaround) {
+ 		px_val = readl(port_mmio + PORT_CMD);
+ 		if (px_val != px_cmd)
+ 			writel(px_cmd, port_mmio + PORT_CMD);
+-- 
+1.7.9.5
+
+
+From 25f36fe44c1836ce12aa276d7ff12fe71683277e Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Thu, 29 Oct 2015 14:22:15 +0800
+Subject: [PATCH 22/66] ahci: qoriq: Rename LS2085A SoC support code to
+ LS2080A
+
+Freescale is renaming the LS2085A SoC to LS2080A.
+This patch addresses the same.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ .../devicetree/bindings/ata/ahci-fsl-qoriq.txt     |    2 +-
+ drivers/ata/ahci_qoriq.c                           |    6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+index b614e3b..3aafe27 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+@@ -3,7 +3,7 @@ Binding for Freescale QorIQ AHCI SATA Controller
+ Required properties:
+   - reg: Physical base address and size of the controller's register area.
+   - compatible: Compatibility string. Must be 'fsl,<chip>-ahci', where
+-    chip could be ls1021a, ls2085a, ls1043a etc.
++    chip could be ls1021a, ls2080a, ls1043a etc.
+   - clocks: Input clock specifier. Refer to common clock bindings.
+   - interrupts: Interrupt specifier. Refer to interrupt binding.
+ 
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index 58c1a94..b9b691e 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -45,7 +45,7 @@
+ enum ahci_qoriq_type {
+ 	AHCI_LS1021A,
+ 	AHCI_LS1043A,
+-	AHCI_LS2085A,
++	AHCI_LS2080A,
+ };
+ 
+ struct ahci_qoriq_priv {
+@@ -57,7 +57,7 @@ struct ahci_qoriq_priv {
+ static const struct of_device_id ahci_qoriq_of_match[] = {
+ 	{ .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
+ 	{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
+-	{ .compatible = "fsl,ls2085a-ahci", .data = (void *)AHCI_LS2085A},
++	{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
+ 	{},
+ };
+ MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
+@@ -159,7 +159,7 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
+ 		break;
+ 
+ 	case AHCI_LS1043A:
+-	case AHCI_LS2085A:
++	case AHCI_LS2080A:
+ 		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ 		break;
+ 	}
+-- 
+1.7.9.5
+
+
+From 695549df8ca210fef5771d4b487a8bce04329100 Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Thu, 29 Oct 2015 14:22:16 +0800
+Subject: [PATCH 23/66] ahci: qoriq: Disable NCQ on ls2080a SoC
+
+NCQ feature can't be used due to the erratum A-008473.
+This patch disables NCQ as a workaround.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ drivers/ata/ahci_qoriq.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
+index b9b691e..d0f9de9 100644
+--- a/drivers/ata/ahci_qoriq.c
++++ b/drivers/ata/ahci_qoriq.c
+@@ -131,7 +131,7 @@ static struct ata_port_operations ahci_qoriq_ops = {
+ 	.hardreset	= ahci_qoriq_hardreset,
+ };
+ 
+-static const struct ata_port_info ahci_qoriq_port_info = {
++static struct ata_port_info ahci_qoriq_port_info = {
+ 	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+ 	.pio_mask	= ATA_PIO4,
+ 	.udma_mask	= ATA_UDMA6,
+@@ -208,6 +208,12 @@ static int ahci_qoriq_probe(struct platform_device *pdev)
+ 	if (rc)
+ 		goto disable_resources;
+ 
++	/* Workaround for ls2080a */
++	if (qoriq_priv->type == AHCI_LS2080A) {
++		hpriv->flags |= AHCI_HFLAG_NO_NCQ;
++		ahci_qoriq_port_info.flags &= ~ATA_FLAG_NCQ;
++	}
++
+ 	rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info,
+ 				     &ahci_qoriq_sht);
+ 	if (rc)
+-- 
+1.7.9.5
+
+
+From 7a3f7f310e0748947c5a95b461809a7699831fa8 Mon Sep 17 00:00:00 2001
+From: Tang Yuantian <Yuantian.Tang@freescale.com>
+Date: Thu, 29 Oct 2015 14:22:17 +0800
+Subject: [PATCH 24/66] devicetree: bindings: Fixed a few typos
+
+There is a few typos in Freescale QorIQ AHCI bindings, This
+patch fixes them.
+
+Signed-off-by: Tang Yuantian <Yuantian.Tang@freescale.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+---
+ .../devicetree/bindings/ata/ahci-fsl-qoriq.txt     |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+index 3aafe27..032a760 100644
+--- a/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
++++ b/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
+@@ -8,8 +8,8 @@ Required properties:
+   - interrupts: Interrupt specifier. Refer to interrupt binding.
+ 
+ Optional properties:
+-  - dma-coherent: Enable ACHI coherency DMA operation.
+-  - reg-names: register area names when there are more then 1 regster area.
++  - dma-coherent: Enable AHCI coherent DMA operation.
++  - reg-names: register area names when there are more than 1 register area.
+ 
+ Examples:
+ 	sata@3200000 {
+-- 
+1.7.9.5
+
+
+From 65f77e76129c69ca38526c97a910304f5155d7c7 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Mon, 15 Jun 2015 15:46:37 +0530
+Subject: [PATCH 25/66] drivers:usb:fsl: Replace macros with enumerated type
+
+Replace macros with enumerated type to represent usb ip
+controller version
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/fsl-mph-dr-of.c |    8 ++++----
+ include/linux/fsl_devices.h      |   16 ++++++++++------
+ 2 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 5e0d600..2195956 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -119,9 +119,9 @@ error:
+ 
+ static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+ 
+-static int usb_get_ver_info(struct device_node *np)
++static enum fsl_usb2_controller_ver usb_get_ver_info(struct device_node *np)
+ {
+-	int ver = -1;
++	enum fsl_usb2_controller_ver ver = FSL_USB_VER_NONE;
+ 
+ 	/*
+ 	 * returns 1 for usb controller version 1.6
+@@ -142,7 +142,7 @@ static int usb_get_ver_info(struct device_node *np)
+ 		else /* for previous controller versions */
+ 			ver = FSL_USB_VER_OLD;
+ 
+-		if (ver > -1)
++		if (ver > FSL_USB_VER_NONE)
+ 			return ver;
+ 	}
+ 
+@@ -215,7 +215,7 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ 	pdata->controller_ver = usb_get_ver_info(np);
+ 
+ 	if (pdata->have_sysif_regs) {
+-		if (pdata->controller_ver < 0) {
++		if (pdata->controller_ver == FSL_USB_VER_NONE) {
+ 			dev_warn(&ofdev->dev, "Could not get controller version\n");
+ 			return -ENODEV;
+ 		}
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index 2a2f56b..0d4855cd 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -20,11 +20,6 @@
+ #define FSL_UTMI_PHY_DLY	10	/*As per P1010RM, delay for UTMI
+ 				PHY CLK to become stable - 10ms*/
+ #define FSL_USB_PHY_CLK_TIMEOUT	10000	/* uSec */
+-#define FSL_USB_VER_OLD		0
+-#define FSL_USB_VER_1_6		1
+-#define FSL_USB_VER_2_2		2
+-#define FSL_USB_VER_2_4		3
+-#define FSL_USB_VER_2_5		4
+ 
+ #include <linux/types.h>
+ 
+@@ -52,6 +47,15 @@
+  *
+  */
+ 
++enum fsl_usb2_controller_ver {
++	FSL_USB_VER_NONE = -1,
++	FSL_USB_VER_OLD = 0,
++	FSL_USB_VER_1_6 = 1,
++	FSL_USB_VER_2_2 = 2,
++	FSL_USB_VER_2_4 = 3,
++	FSL_USB_VER_2_5 = 4,
++};
++
+ enum fsl_usb2_operating_modes {
+ 	FSL_USB2_MPH_HOST,
+ 	FSL_USB2_DR_HOST,
+@@ -72,7 +76,7 @@ struct platform_device;
+ 
+ struct fsl_usb2_platform_data {
+ 	/* board specific information */
+-	int				controller_ver;
++	enum fsl_usb2_controller_ver	controller_ver;
+ 	enum fsl_usb2_operating_modes	operating_mode;
+ 	enum fsl_usb2_phy_modes		phy_mode;
+ 	unsigned int			port_enables;
+-- 
+1.7.9.5
+
+
+From ab35506e5d9e09845c9e90ca76d112664ad08102 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Mon, 15 Jun 2015 15:47:29 +0530
+Subject: [PATCH 26/66] drivers: usb :fsl: Implement Workaround for USB
+ Erratum A007792
+
+USB controller version-2.5 requires to enable internal UTMI
+phy and program PTS field in PORTSC register before asserting
+controller reset. This is must for successful resetting of the
+controller and subsequent enumeration of usb devices
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Suresh Gupta <suresh.gupta@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-fsl.c      |    9 +++++++++
+ drivers/usb/host/fsl-mph-dr-of.c |    6 ++++++
+ include/linux/fsl_devices.h      |    1 +
+ 3 files changed, 16 insertions(+)
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 5352e74..716aa8b 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -129,6 +129,15 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
+ 	if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
+ 		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+ 
++	/*
++	 * Enable UTMI phy and program PTS field in UTMI mode before asserting
++	 * controller reset for USB Controller version 2.5
++	 */
++	if (pdata->has_fsl_erratum_a007792) {
++		writel_be(CTRL_UTMI_PHY_EN, hcd->regs + FSL_SOC_USB_CTRL);
++		writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
++	}
++
+ 	/* Don't need to set host mode here. It will be done by tdi_reset() */
+ 
+ 	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 2195956..17e1e6b 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -214,6 +214,12 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ 	pdata->phy_mode = determine_usb_phy(prop);
+ 	pdata->controller_ver = usb_get_ver_info(np);
+ 
++	/* Activate Erratum by reading property in device tree */
++	if (of_get_property(np, "fsl,usb-erratum-a007792", NULL))
++		pdata->has_fsl_erratum_a007792 = 1;
++	else
++		pdata->has_fsl_erratum_a007792 = 0;
++
+ 	if (pdata->have_sysif_regs) {
+ 		if (pdata->controller_ver == FSL_USB_VER_NONE) {
+ 			dev_warn(&ofdev->dev, "Could not get controller version\n");
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index 0d4855cd..bdb40f6 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -97,6 +97,7 @@ struct fsl_usb2_platform_data {
+ 
+ 	unsigned	suspended:1;
+ 	unsigned	already_suspended:1;
++	unsigned        has_fsl_erratum_a007792:1;
+ 
+ 	/* register save area for suspend/resume */
+ 	u32		pm_command;
+-- 
+1.7.9.5
+
+
+From 066595fe42986c567abe1d283048046c75d69051 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Mon, 15 Jun 2015 15:48:22 +0530
+Subject: [PATCH 27/66] drivers:usb:fsl: Introduce FSL_USB2_PHY_UTMI_DUAL
+ macro
+
+Introduce FSL_USB2_PHY_UTMI_DUAL macro for setting phy mode
+in SOCs such has T4240, T1040, T2080 which have utmi dual-phy
+
+Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-fsl.c      |    1 +
+ drivers/usb/host/fsl-mph-dr-of.c |    2 ++
+ include/linux/fsl_devices.h      |    1 +
+ 3 files changed, 4 insertions(+)
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 716aa8b..b04c9db 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -213,6 +213,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
+ 		portsc |= PORT_PTS_PTW;
+ 		/* fall through */
+ 	case FSL_USB2_PHY_UTMI:
++	case FSL_USB2_PHY_UTMI_DUAL:
+ 		if (pdata->have_sysif_regs && pdata->controller_ver) {
+ 			/* controller version 1.6 or above */
+ 			setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 17e1e6b..631fc50 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -69,6 +69,8 @@ static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
+ 		return FSL_USB2_PHY_UTMI;
+ 	if (!strcasecmp(phy_type, "utmi_wide"))
+ 		return FSL_USB2_PHY_UTMI_WIDE;
++	if (!strcasecmp(phy_type, "utmi_dual"))
++		return FSL_USB2_PHY_UTMI_DUAL;
+ 	if (!strcasecmp(phy_type, "serial"))
+ 		return FSL_USB2_PHY_SERIAL;
+ 
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index bdb40f6..070d9ae 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -69,6 +69,7 @@ enum fsl_usb2_phy_modes {
+ 	FSL_USB2_PHY_UTMI,
+ 	FSL_USB2_PHY_UTMI_WIDE,
+ 	FSL_USB2_PHY_SERIAL,
++	FSL_USB2_PHY_UTMI_DUAL,
+ };
+ 
+ struct clk;
+-- 
+1.7.9.5
+
+
+From ac9caf983cb5d959584b69b20eb08546399fe9e4 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Tue, 14 Jul 2015 17:28:10 +0530
+Subject: [PATCH 28/66] drivers: usb: fsl: Modify phy clk valid bit checking
+
+Phy_clk_valid bit is checked only when the boolean
+property phy-clk-valid in present in usb node device tree.
+This property is added to the usb node via device tree fixup.
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-fsl.c      |   16 ++++++++--------
+ drivers/usb/host/fsl-mph-dr-of.c |    9 +++++++++
+ include/linux/fsl_devices.h      |    1 +
+ 3 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index b04c9db..05ebe3d 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -230,14 +230,14 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
+ 		break;
+ 	}
+ 
+-	if (pdata->have_sysif_regs &&
+-	    pdata->controller_ver > FSL_USB_VER_1_6 &&
+-	    (phy_mode == FSL_USB2_PHY_ULPI)) {
+-		/* check PHY_CLK_VALID to get phy clk valid */
+-		if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
+-				PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
+-				in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
+-			dev_warn(hcd->self.controller, "USB PHY clock invalid\n");
++	/*
++	 * check PHY_CLK_VALID to determine phy clock presence before writing
++	 * to portsc
++	 */
++	if (pdata->check_phy_clk_valid) {
++		if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) {
++			dev_warn(hcd->self.controller,
++				 "USB PHY clock invalid\n");
+ 			return -EINVAL;
+ 		}
+ 	}
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 631fc50..9f73141 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -222,6 +222,15 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ 	else
+ 		pdata->has_fsl_erratum_a007792 = 0;
+ 
++	/*
++	 * Determine whether phy_clk_valid needs to be checked
++	 * by reading property in device tree
++	 */
++	if (of_get_property(np, "phy-clk-valid", NULL))
++		pdata->check_phy_clk_valid = 1;
++	else
++		pdata->check_phy_clk_valid = 0;
++
+ 	if (pdata->have_sysif_regs) {
+ 		if (pdata->controller_ver == FSL_USB_VER_NONE) {
+ 			dev_warn(&ofdev->dev, "Could not get controller version\n");
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index 070d9ae..cebdbbb 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -99,6 +99,7 @@ struct fsl_usb2_platform_data {
+ 	unsigned	suspended:1;
+ 	unsigned	already_suspended:1;
+ 	unsigned        has_fsl_erratum_a007792:1;
++	unsigned        check_phy_clk_valid:1;
+ 
+ 	/* register save area for suspend/resume */
+ 	u32		pm_command;
+-- 
+1.7.9.5
+
+
+From 9b43cd830dbf169da55a450f576a02e919d7487d Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Tue, 14 Jul 2015 17:28:47 +0530
+Subject: [PATCH 29/66] drivers: usb: fsl: Define usb control register mask
+ for w1c bits
+
+Define and use CONTROL_REGISTER_W1C_MASK to make sure that
+w1c bits of usb control register do not get reset while
+writing any other bit
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-fsl.c |   25 ++++++++++++++++---------
+ drivers/usb/host/ehci-fsl.h |    1 +
+ 2 files changed, 17 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 05ebe3d..202dafb 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -127,14 +127,16 @@ static int fsl_ehci_drv_probe(struct platform_device *pdev)
+ 
+ 	/* Enable USB controller, 83xx or 8536 */
+ 	if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
+-		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
++		clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
++				CONTROL_REGISTER_W1C_MASK, 0x4);
+ 
+ 	/*
+ 	 * Enable UTMI phy and program PTS field in UTMI mode before asserting
+ 	 * controller reset for USB Controller version 2.5
+ 	 */
+ 	if (pdata->has_fsl_erratum_a007792) {
+-		writel_be(CTRL_UTMI_PHY_EN, hcd->regs + FSL_SOC_USB_CTRL);
++		clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
++				CONTROL_REGISTER_W1C_MASK, CTRL_UTMI_PHY_EN);
+ 		writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
+ 	}
+ 
+@@ -200,9 +202,11 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
+ 	case FSL_USB2_PHY_ULPI:
+ 		if (pdata->have_sysif_regs && pdata->controller_ver) {
+ 			/* controller version 1.6 or above */
+-			clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
+-			setbits32(non_ehci + FSL_SOC_USB_CTRL,
+-				ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
++			clrbits32(non_ehci + FSL_SOC_USB_CTRL,
++				  CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
++			clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
++					CONTROL_REGISTER_W1C_MASK,
++					ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
+ 		}
+ 		portsc |= PORT_PTS_ULPI;
+ 		break;
+@@ -216,14 +220,16 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
+ 	case FSL_USB2_PHY_UTMI_DUAL:
+ 		if (pdata->have_sysif_regs && pdata->controller_ver) {
+ 			/* controller version 1.6 or above */
+-			setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
++			clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
++					CONTROL_REGISTER_W1C_MASK, UTMI_PHY_EN);
+ 			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
+ 						become stable - 10ms*/
+ 		}
+ 		/* enable UTMI PHY */
+ 		if (pdata->have_sysif_regs)
+-			setbits32(non_ehci + FSL_SOC_USB_CTRL,
+-				  CTRL_UTMI_PHY_EN);
++			clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
++					CONTROL_REGISTER_W1C_MASK,
++					CTRL_UTMI_PHY_EN);
+ 		portsc |= PORT_PTS_UTMI;
+ 		break;
+ 	case FSL_USB2_PHY_NONE:
+@@ -245,7 +251,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
+ 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
+ 
+ 	if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
+-		setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
++		clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
++				CONTROL_REGISTER_W1C_MASK, USB_CTRL_USB_EN);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
+index dbd292e..1a8a60a 100644
+--- a/drivers/usb/host/ehci-fsl.h
++++ b/drivers/usb/host/ehci-fsl.h
+@@ -52,6 +52,7 @@
+ #define SNOOP_SIZE_2GB		0x1e
+ 
+ /* control Register Bit Masks */
++#define CONTROL_REGISTER_W1C_MASK       0x00020000  /* W1C: PHY_CLK_VALID */
+ #define ULPI_INT_EN             (1<<0)
+ #define WU_INT_EN               (1<<1)
+ #define USB_CTRL_USB_EN         (1<<2)
+-- 
+1.7.9.5
+
+
+From c1537d0aacb9e523fad68ea72263fb26fbebfb56 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Thu, 6 Aug 2015 14:51:27 +0530
+Subject: [PATCH 30/66] drivers: usb: fsl: Workaround for USB erratum-A005275
+
+Incoming packets in high speed are randomly corrupted by h/w
+resulting in multiple errors. This workaround makes FS as
+default mode in all affected socs by disabling HS chirp
+signalling.This errata does not affect FS and LS mode.
+
+Forces all HS devices to connect in FS mode for all socs
+affected by this erratum:
+P3041 and P2041 rev 1.0 and 1.1
+P5020 and P5010 rev 1.0 and 2.0
+P5040, P1010 and T4240 rev 1.0
+
+Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ehci-fsl.c      |    4 ++++
+ drivers/usb/host/ehci-hub.c      |    7 +++++++
+ drivers/usb/host/ehci.h          |   12 ++++++++++++
+ drivers/usb/host/fsl-mph-dr-of.c |    4 ++++
+ include/linux/fsl_devices.h      |    1 +
+ 5 files changed, 28 insertions(+)
+
+diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
+index 202dafb..3b6eb21 100644
+--- a/drivers/usb/host/ehci-fsl.c
++++ b/drivers/usb/host/ehci-fsl.c
+@@ -278,6 +278,10 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
+ 		out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
+ 	}
+ 
++	/* Deal with USB erratum A-005275 */
++	if (pdata->has_fsl_erratum_a005275 == 1)
++		ehci->has_fsl_hs_errata = 1;
++
+ 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+ 			(pdata->operating_mode == FSL_USB2_DR_OTG))
+ 		if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index 22abb68..086a711 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -1221,6 +1221,13 @@ int ehci_hub_control(
+ 				 */
+ 				ehci->reset_done [wIndex] = jiffies
+ 						+ msecs_to_jiffies (50);
++
++				/*
++				 * Force full-speed connect for FSL high-speed
++				 * erratum; disable HS Chirp by setting PFSC bit
++				 */
++				if (ehci_has_fsl_hs_errata(ehci))
++					temp |= (1 << PORTSC_FSL_PFSC);
+ 			}
+ 			ehci_writel(ehci, temp, status_reg);
+ 			break;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index f700157..46f62e4 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -215,6 +215,7 @@ struct ehci_hcd {			/* one per controller */
+ 	/* SILICON QUIRKS */
+ 	unsigned		no_selective_suspend:1;
+ 	unsigned		has_fsl_port_bug:1; /* FreeScale */
++	unsigned		has_fsl_hs_errata:1;	/* Freescale HS quirk */
+ 	unsigned		big_endian_mmio:1;
+ 	unsigned		big_endian_desc:1;
+ 	unsigned		big_endian_capbase:1;
+@@ -686,6 +687,17 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+ #define	ehci_has_fsl_portno_bug(e)		(0)
+ #endif
+ 
++#define PORTSC_FSL_PFSC	24	/* Port Force Full-Speed Connect */
++
++#if defined(CONFIG_PPC_85xx)
++/* Some Freescale processors have an erratum (USB A-005275) in which
++ * incoming packets get corrupted in HS mode
++ */
++#define ehci_has_fsl_hs_errata(e)	((e)->has_fsl_hs_errata)
++#else
++#define ehci_has_fsl_hs_errata(e)	(0)
++#endif
++
+ /*
+  * While most USB host controllers implement their registers in
+  * little-endian format, a minority (celleb companion chip) implement
+diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
+index 9f73141..534c4c5 100644
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -221,6 +221,10 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
+ 		pdata->has_fsl_erratum_a007792 = 1;
+ 	else
+ 		pdata->has_fsl_erratum_a007792 = 0;
++	if (of_get_property(np, "fsl,usb-erratum-a005275", NULL))
++		pdata->has_fsl_erratum_a005275 = 1;
++	else
++		pdata->has_fsl_erratum_a005275 = 0;
+ 
+ 	/*
+ 	 * Determine whether phy_clk_valid needs to be checked
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index cebdbbb..f291291 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -99,6 +99,7 @@ struct fsl_usb2_platform_data {
+ 	unsigned	suspended:1;
+ 	unsigned	already_suspended:1;
+ 	unsigned        has_fsl_erratum_a007792:1;
++	unsigned        has_fsl_erratum_a005275:1;
+ 	unsigned        check_phy_clk_valid:1;
+ 
+ 	/* register save area for suspend/resume */
+-- 
+1.7.9.5
+
+
+From 04cbb46efabda9785fc92b687ee96c5c170c69fd Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Fri, 4 Sep 2015 10:14:54 +0530
+Subject: [PATCH 31/66] Documentation: dt: dwc3: Add
+ snps,quirk-frame-length-adjustment property
+
+Add snps,quirk-frame-length-adjustment property which provides value
+for post silicon frame length adjustment
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+---
+ Documentation/devicetree/bindings/usb/dwc3.txt |    3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
+index 9f64f69..6bacd1b 100644
+--- a/Documentation/devicetree/bindings/usb/dwc3.txt
++++ b/Documentation/devicetree/bindings/usb/dwc3.txt
+@@ -41,6 +41,9 @@ Optional properties:
+  - snps,hird-threshold: HIRD threshold
+  - snps,hsphy_interface: High-Speed PHY interface selection between "utmi" for
+    UTMI+ and "ulpi" for ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3.
++ - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
++	register for post-silicon frame length adjustment when the
++	fladj_30mhz_sdbnd signal is invalid or incorrect.
+ 
+ This is usually a subnode to DWC3 glue to which it is connected.
+ 
+-- 
+1.7.9.5
+
+
+From 634b115caf3ce99dc05397507ab81710677ee310 Mon Sep 17 00:00:00 2001
+From: Nikhil Badola <nikhil.badola@freescale.com>
+Date: Fri, 4 Sep 2015 10:15:58 +0530
+Subject: [PATCH 32/66] usb: dwc3: Add frame length adjustment quirk
+
+Add adjust_frame_length_quirk for writing to fladj register
+which adjusts (micro)frame length to value provided by
+"snps,quirk-frame-length-adjustment" property thus avoiding
+USB 2.0 devices to time-out over a longer run
+
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: Felipe Balbi <balbi@ti.com>
+---
+ drivers/usb/dwc3/core.c          |   34 ++++++++++++++++++++++++++++++++++
+ drivers/usb/dwc3/core.h          |    5 +++++
+ drivers/usb/dwc3/platform_data.h |    2 ++
+ 3 files changed, 41 insertions(+)
+
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index ff5773c..c9b8479 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -143,6 +143,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc)
+ 	return 0;
+ }
+ 
++/*
++ * dwc3_frame_length_adjustment - Adjusts frame length if required
++ * @dwc3: Pointer to our controller context structure
++ * @fladj: Value of GFLADJ_30MHZ to adjust frame length
++ */
++static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
++{
++	u32 reg;
++	u32 dft;
++
++	if (dwc->revision < DWC3_REVISION_250A)
++		return;
++
++	if (fladj == 0)
++		return;
++
++	reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
++	dft = reg & DWC3_GFLADJ_30MHZ_MASK;
++	if (!dev_WARN_ONCE(dwc->dev, dft == fladj,
++	    "request value same as default, ignoring\n")) {
++		reg &= ~DWC3_GFLADJ_30MHZ_MASK;
++		reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
++		dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
++	}
++}
++
+ /**
+  * dwc3_free_one_event_buffer - Frees one event buffer
+  * @dwc: Pointer to our controller context structure
+@@ -781,6 +807,7 @@ static int dwc3_probe(struct platform_device *pdev)
+ 	u8			lpm_nyet_threshold;
+ 	u8			tx_de_emphasis;
+ 	u8			hird_threshold;
++	u32			fladj = 0;
+ 
+ 	int			ret;
+ 
+@@ -888,6 +915,9 @@ static int dwc3_probe(struct platform_device *pdev)
+ 				&tx_de_emphasis);
+ 		of_property_read_string(node, "snps,hsphy_interface",
+ 					&dwc->hsphy_interface);
++		of_property_read_u32(node,
++				     "snps,quirk-frame-length-adjustment",
++				     &fladj);
+ 	} else if (pdata) {
+ 		dwc->maximum_speed = pdata->maximum_speed;
+ 		dwc->has_lpm_erratum = pdata->has_lpm_erratum;
+@@ -917,6 +947,7 @@ static int dwc3_probe(struct platform_device *pdev)
+ 			tx_de_emphasis = pdata->tx_de_emphasis;
+ 
+ 		dwc->hsphy_interface = pdata->hsphy_interface;
++		fladj = pdata->fladj_value;
+ 	}
+ 
+ 	/* default to superspeed if no maximum_speed passed */
+@@ -973,6 +1004,9 @@ static int dwc3_probe(struct platform_device *pdev)
+ 		goto err1;
+ 	}
+ 
++	/* Adjust Frame Length */
++	dwc3_frame_length_adjustment(dwc, fladj);
++
+ 	usb_phy_set_suspend(dwc->usb2_phy, 0);
+ 	usb_phy_set_suspend(dwc->usb3_phy, 0);
+ 	ret = phy_power_on(dwc->usb2_generic_phy);
+diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
+index 0447788..9188745 100644
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -124,6 +124,7 @@
+ #define DWC3_GEVNTCOUNT(n)	(0xc40c + (n * 0x10))
+ 
+ #define DWC3_GHWPARAMS8		0xc600
++#define DWC3_GFLADJ		0xc630
+ 
+ /* Device Registers */
+ #define DWC3_DCFG		0xc700
+@@ -234,6 +235,10 @@
+ /* Global HWPARAMS6 Register */
+ #define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
+ 
++/* Global Frame Length Adjustment Register */
++#define DWC3_GFLADJ_30MHZ_SDBND_SEL		(1 << 7)
++#define DWC3_GFLADJ_30MHZ_MASK			0x3f
++
+ /* Device Configuration Register */
+ #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
+ #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
+diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h
+index d3614ec..400b197 100644
+--- a/drivers/usb/dwc3/platform_data.h
++++ b/drivers/usb/dwc3/platform_data.h
+@@ -46,5 +46,7 @@ struct dwc3_platform_data {
+ 	unsigned tx_de_emphasis_quirk:1;
+ 	unsigned tx_de_emphasis:2;
+ 
++	u32 fladj_value;
++
+ 	const char *hsphy_interface;
+ };
+-- 
+1.7.9.5
+
+
+From 8c94e158a6c56fd743b0bc1c90b2b80f10fcb913 Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Thu, 4 Feb 2016 16:00:32 -0600
+Subject: [PATCH 33/66] arm64: dts: ls2080a: Add quirk for Erratum A009116
+
+Add "snps,quirk-frame-length-adjustment" property to
+USB3 node for erratum A009116. This property provides
+value of GFLADJ_30MHZ for post silicon frame length
+adjustment.
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |    2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index e81cd48..1554da4 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -496,6 +496,7 @@
+ 			reg = <0x0 0x3100000 0x0 0x10000>;
+ 			interrupts = <0 80 0x4>; /* Level high type */
+ 			dr_mode = "host";
++			snps,quirk-frame-length-adjustment = <0x20>;
+ 		};
+ 
+ 		usb1: usb3@3110000 {
+@@ -504,6 +505,7 @@
+ 			reg = <0x0 0x3110000 0x0 0x10000>;
+ 			interrupts = <0 81 0x4>; /* Level high type */
+ 			dr_mode = "host";
++			snps,quirk-frame-length-adjustment = <0x20>;
+ 		};
+ 
+ 		ccn@4000000 {
+-- 
+1.7.9.5
+
+
+From 9dd2d93bede314bfdd641194c9b779c2617d8605 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Date: Fri, 10 Jul 2015 14:52:31 +0900
+Subject: [PATCH 34/66] i2c: Drop owner assignment from i2c_driver
+
+i2c_driver does not need to set an owner because i2c_register_driver()
+will set it.
+
+Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/i2c-slave-eeprom.c      |    1 -
+ drivers/i2c/muxes/i2c-mux-pca9541.c |    1 -
+ drivers/i2c/muxes/i2c-mux-pca954x.c |    1 -
+ 3 files changed, 3 deletions(-)
+
+diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c
+index 1da4496..b2039f9 100644
+--- a/drivers/i2c/i2c-slave-eeprom.c
++++ b/drivers/i2c/i2c-slave-eeprom.c
+@@ -157,7 +157,6 @@ MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id);
+ static struct i2c_driver i2c_slave_eeprom_driver = {
+ 	.driver = {
+ 		.name = "i2c-slave-eeprom",
+-		.owner = THIS_MODULE,
+ 	},
+ 	.probe = i2c_slave_eeprom_probe,
+ 	.remove = i2c_slave_eeprom_remove,
+diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
+index 0c8d4d2..d0ba424 100644
+--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
++++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
+@@ -386,7 +386,6 @@ static int pca9541_remove(struct i2c_client *client)
+ static struct i2c_driver pca9541_driver = {
+ 	.driver = {
+ 		   .name = "pca9541",
+-		   .owner = THIS_MODULE,
+ 		   },
+ 	.probe = pca9541_probe,
+ 	.remove = pca9541_remove,
+diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
+index ea4aa9d..acfcef3 100644
+--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
++++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
+@@ -300,7 +300,6 @@ static struct i2c_driver pca954x_driver = {
+ 	.driver		= {
+ 		.name	= "pca954x",
+ 		.pm	= &pca954x_pm,
+-		.owner	= THIS_MODULE,
+ 	},
+ 	.probe		= pca954x_probe,
+ 	.remove		= pca954x_remove,
+-- 
+1.7.9.5
+
+
+From efe0dd9bbf708db85bb8dfca3f266838fbc30820 Mon Sep 17 00:00:00 2001
+From: Shaohui Xie <Shaohui.Xie@freescale.com>
+Date: Fri, 23 Oct 2015 16:01:17 +0800
+Subject: [PATCH 35/66] i2c: imx: add support for Freescale Layerscape
+ platforms
+
+Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
+Signed-off-by: Hou Zhiqiang <B48286@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/Kconfig |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 577d58d..b7f02c8 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -575,10 +575,10 @@ config I2C_IMG
+ 
+ config I2C_IMX
+ 	tristate "IMX I2C interface"
+-	depends on ARCH_MXC
++	depends on ARCH_MXC || ARCH_LAYERSCAPE
+ 	help
+ 	  Say Y here if you want to use the IIC bus controller on
+-	  the Freescale i.MX/MXC processors.
++	  the Freescale i.MX/MXC or Layerscape processors.
+ 
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-imx.
+-- 
+1.7.9.5
+
+
+From 8b825fee6379edbe2f59f3fbf9e22691cdd96c4b Mon Sep 17 00:00:00 2001
+From: Gao Pan <b54642@freescale.com>
+Date: Fri, 23 Oct 2015 20:28:54 +0800
+Subject: [PATCH 36/66] i2c: imx: implement bus recovery
+
+Implement bus recovery methods for i2c-imx so we can recover from
+situations where SCL/SDA are stuck low.
+
+Once i2c bus SCL/SDA are stuck low during transfer, config the i2c
+pinctrl to gpio mode by calling pinctrl sleep set function, and then
+use GPIO to emulate the i2c protocol to send nine dummy clock to recover
+i2c device. After recovery, set i2c pinctrl to default group setting.
+
+Signed-off-by: Fugang Duan <B38611@freescale.com>
+Signed-off-by: Gao Pan <b54642@freescale.com>
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ Documentation/devicetree/bindings/i2c/i2c-imx.txt |    9 +++
+ drivers/i2c/busses/i2c-imx.c                      |   71 +++++++++++++++++++++
+ 2 files changed, 80 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.txt b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
+index ce4311d..eab5836 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-imx.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-imx.txt
+@@ -14,6 +14,10 @@ Optional properties:
+   The absence of the propoerty indicates the default frequency 100 kHz.
+ - dmas: A list of two dma specifiers, one for each entry in dma-names.
+ - dma-names: should contain "tx" and "rx".
++- scl-gpios: specify the gpio related to SCL pin
++- sda-gpios: specify the gpio related to SDA pin
++- pinctrl: add extra pinctrl to configure i2c pins to gpio function for i2c
++  bus recovery, call it "gpio" state
+ 
+ Examples:
+ 
+@@ -37,4 +41,9 @@ i2c0: i2c@40066000 { /* i2c0 on vf610 */
+ 	dmas = <&edma0 0 50>,
+ 		<&edma0 0 51>;
+ 	dma-names = "rx","tx";
++	pinctrl-names = "default", "gpio";
++	pinctrl-0 = <&pinctrl_i2c1>;
++	pinctrl-1 = <&pinctrl_i2c1_gpio>;
++	scl-gpios = <&gpio5 26 GPIO_ACTIVE_HIGH>;
++	sda-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;
+ };
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 785aa67..8d46e74 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -49,6 +49,7 @@
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_dma.h>
++#include <linux/of_gpio.h>
+ #include <linux/platform_data/i2c-imx.h>
+ #include <linux/platform_device.h>
+ #include <linux/sched.h>
+@@ -207,6 +208,11 @@ struct imx_i2c_struct {
+ 	unsigned int		cur_clk;
+ 	unsigned int		bitrate;
+ 	const struct imx_i2c_hwdata	*hwdata;
++	struct i2c_bus_recovery_info rinfo;
++
++	struct pinctrl *pinctrl;
++	struct pinctrl_state *pinctrl_pins_default;
++	struct pinctrl_state *pinctrl_pins_gpio;
+ 
+ 	struct imx_i2c_dma	*dma;
+ };
+@@ -896,6 +902,13 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
+ 
+ 	/* Start I2C transfer */
+ 	result = i2c_imx_start(i2c_imx);
++	if (result) {
++		if (i2c_imx->adapter.bus_recovery_info) {
++			i2c_recover_bus(&i2c_imx->adapter);
++			result = i2c_imx_start(i2c_imx);
++		}
++	}
++
+ 	if (result)
+ 		goto fail0;
+ 
+@@ -956,6 +969,55 @@ fail0:
+ 	return (result < 0) ? result : num;
+ }
+ 
++static void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
++{
++	struct imx_i2c_struct *i2c_imx;
++
++	i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
++
++	pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
++}
++
++static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
++{
++	struct imx_i2c_struct *i2c_imx;
++
++	i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
++
++	pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
++}
++
++static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
++		struct platform_device *pdev)
++{
++	struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo;
++
++	i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
++			PINCTRL_STATE_DEFAULT);
++	i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
++			"gpio");
++	rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
++			"sda-gpios", 0, NULL);
++	rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
++			"scl-gpios", 0, NULL);
++
++	if (!gpio_is_valid(rinfo->sda_gpio) ||
++	    !gpio_is_valid(rinfo->scl_gpio) ||
++	    IS_ERR(i2c_imx->pinctrl_pins_default) ||
++	    IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
++		dev_dbg(&pdev->dev, "recovery information incomplete\n");
++		return;
++	}
++
++	dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
++			rinfo->sda_gpio, rinfo->scl_gpio);
++
++	rinfo->prepare_recovery = i2c_imx_prepare_recovery;
++	rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
++	rinfo->recover_bus = i2c_generic_gpio_recovery;
++	i2c_imx->adapter.bus_recovery_info = rinfo;
++}
++
+ static u32 i2c_imx_func(struct i2c_adapter *adapter)
+ {
+ 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
+@@ -1023,6 +1085,13 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 		dev_err(&pdev->dev, "can't enable I2C clock\n");
+ 		return ret;
+ 	}
++
++	i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
++	if (IS_ERR(i2c_imx->pinctrl)) {
++		ret = PTR_ERR(i2c_imx->pinctrl);
++		goto clk_disable;
++	}
++
+ 	/* Request IRQ */
+ 	ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
+ 				pdev->name, i2c_imx);
+@@ -1056,6 +1125,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 		goto clk_disable;
+ 	}
+ 
++	i2c_imx_init_recovery_info(i2c_imx, pdev);
++
+ 	/* Set up platform driver data */
+ 	platform_set_drvdata(pdev, i2c_imx);
+ 	clk_disable_unprepare(i2c_imx->clk);
+-- 
+1.7.9.5
+
+
+From ee13bb0ace8af13b6eb80168ac27c76dfe51bae1 Mon Sep 17 00:00:00 2001
+From: Fabio Estevam <fabio.estevam@freescale.com>
+Date: Thu, 22 Oct 2015 14:41:20 -0200
+Subject: [PATCH 37/66] i2c: imx: Use -ENXIO as error in the NACK case
+
+According to Documentation/i2c/fault-codes the response to a bus NACK
+should be -ENXIO, so fix the error code.
+
+Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 8d46e74..1e4d99d 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -467,7 +467,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
+ {
+ 	if (imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR) & I2SR_RXAK) {
+ 		dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__);
+-		return -EIO;  /* No ACK */
++		return -ENXIO;  /* No ACK */
+ 	}
+ 
+ 	dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__);
+-- 
+1.7.9.5
+
+
+From fe5c3ee455f9b190449e5d3567517af2c9a2e6ed Mon Sep 17 00:00:00 2001
+From: Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
+Date: Tue, 17 Nov 2015 17:53:18 +0800
+Subject: [PATCH 38/66] i2c: imx: fix a compiling error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+drivers/i2c/busses/i2c-imx.c:978:2: error: implicit declaration of
+function ‘pinctrl_select_state’ [-Werror=implicit-function-declaration]
+  pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
+  ^
+
+Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 1e4d99d..9bb0b05 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -50,6 +50,7 @@
+ #include <linux/of_device.h>
+ #include <linux/of_dma.h>
+ #include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
+ #include <linux/platform_data/i2c-imx.h>
+ #include <linux/platform_device.h>
+ #include <linux/sched.h>
+-- 
+1.7.9.5
+
+
+From 51e1a2b5af47496064f4cc6dbdd0ca9915e6356d Mon Sep 17 00:00:00 2001
+From: Gao Pan <b54642@freescale.com>
+Date: Wed, 9 Dec 2015 11:08:22 +0800
+Subject: [PATCH 39/66] i2c: imx: init bus recovery info before adding i2c
+ adapter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+During driver probe, i2c_imx_init_recovery_info() must come before
+i2c_add_numbered_adapter(), because the get/set_scl() functions
+are assigned in i2c_register_adapter() under the conditon that bus
+recover_info are initialized. Otherwise, get/set_scl() function
+pointers never get assigned.
+
+In such case, when i2c_generic_gpio_recovery() is used for bus recovery,
+there will be kernel crash because bri->set_scl is NULL.
+
+The solution to this bug is moving i2c_imx_init_recovery_info() before
+i2c_register_adapter().
+
+Signed-off-by: Gao Pan <b54642@freescale.com>
+Signed-off-by: Fugang Duan <B38611@freescale.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Cc: stable@kernel.org
+---
+ drivers/i2c/busses/i2c-imx.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 9bb0b05..d4d8536 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -1119,6 +1119,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 			i2c_imx, IMX_I2C_I2CR);
+ 	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+ 
++	i2c_imx_init_recovery_info(i2c_imx, pdev);
++
+ 	/* Add I2C adapter */
+ 	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
+ 	if (ret < 0) {
+@@ -1126,8 +1128,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 		goto clk_disable;
+ 	}
+ 
+-	i2c_imx_init_recovery_info(i2c_imx, pdev);
+-
+ 	/* Set up platform driver data */
+ 	platform_set_drvdata(pdev, i2c_imx);
+ 	clk_disable_unprepare(i2c_imx->clk);
+-- 
+1.7.9.5
+
+
+From 0cef55a2bca8a9af56037b9ff0aa8eb74c195716 Mon Sep 17 00:00:00 2001
+From: Gao Pan <b54642@freescale.com>
+Date: Fri, 11 Dec 2015 10:24:09 +0800
+Subject: [PATCH 40/66] i2c: imx: add runtime pm support to improve the
+ performance
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In our former i2c driver, i2c clk is enabled and disabled in
+xfer function, which contributes to power saving. However,
+the clk enable process brings a busy wait delay until the core
+is stable. As a result, the performance is sacrificed.
+
+To weigh the power consumption and i2c bus performance, runtime
+pm is the good solution for it. The clk is enabled when a i2c
+transfer starts, and disabled after a specifically defined delay.
+
+If CONFIG_PM is disabled the net result of this patch is that the
+clock is never disabled.
+
+Without the patch the test case (many eeprom reads) executes with approx:
+real 1m7.735s
+user 0m0.488s
+sys 0m20.040s
+
+With the patch the same test case (many eeprom reads) executes with approx:
+real 0m54.241s
+user 0m0.440s
+sys 0m5.920s
+
+Signed-off-by: Fugang Duan <B38611@freescale.com>
+Signed-off-by: Gao Pan <b54642@freescale.com>
+Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+[wsa: sorted includes]
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |   90 ++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 78 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index d4d8536..3ffdcf4 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -53,6 +53,7 @@
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/platform_data/i2c-imx.h>
+ #include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ 
+@@ -120,6 +121,8 @@
+ #define I2CR_IEN_OPCODE_0	0x0
+ #define I2CR_IEN_OPCODE_1	I2CR_IEN
+ 
++#define I2C_PM_TIMEOUT		10 /* ms */
++
+ /** Variables ******************************************************************
+ *******************************************************************************/
+ 
+@@ -527,9 +530,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+ 
+ 	i2c_imx_set_clk(i2c_imx);
+ 
+-	result = clk_prepare_enable(i2c_imx->clk);
+-	if (result)
+-		return result;
+ 	imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
+ 	/* Enable I2C controller */
+ 	imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
+@@ -582,7 +582,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
+ 	/* Disable I2C controller */
+ 	temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+ 	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+-	clk_disable_unprepare(i2c_imx->clk);
+ }
+ 
+ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
+@@ -901,6 +900,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
+ 
+ 	dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ 
++	result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
++	if (result < 0)
++		goto out;
++
+ 	/* Start I2C transfer */
+ 	result = i2c_imx_start(i2c_imx);
+ 	if (result) {
+@@ -964,6 +967,10 @@ fail0:
+ 	/* Stop I2C transfer */
+ 	i2c_imx_stop(i2c_imx);
+ 
++	pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
++	pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
++
++out:
+ 	dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
+ 		(result < 0) ? "error" : "success msg",
+ 			(result < 0) ? result : num);
+@@ -1083,7 +1090,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 
+ 	ret = clk_prepare_enable(i2c_imx->clk);
+ 	if (ret) {
+-		dev_err(&pdev->dev, "can't enable I2C clock\n");
++		dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
+ 		return ret;
+ 	}
+ 
+@@ -1107,6 +1114,18 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 	/* Set up adapter data */
+ 	i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
+ 
++	/* Set up platform driver data */
++	platform_set_drvdata(pdev, i2c_imx);
++
++	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
++	pm_runtime_use_autosuspend(&pdev->dev);
++	pm_runtime_set_active(&pdev->dev);
++	pm_runtime_enable(&pdev->dev);
++
++	ret = pm_runtime_get_sync(&pdev->dev);
++	if (ret < 0)
++		goto rpm_disable;
++
+ 	/* Set up clock divider */
+ 	i2c_imx->bitrate = IMX_I2C_BIT_RATE;
+ 	ret = of_property_read_u32(pdev->dev.of_node,
+@@ -1125,12 +1144,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 	ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
+ 	if (ret < 0) {
+ 		dev_err(&pdev->dev, "registration failed\n");
+-		goto clk_disable;
++		goto rpm_disable;
+ 	}
+ 
+-	/* Set up platform driver data */
+-	platform_set_drvdata(pdev, i2c_imx);
+-	clk_disable_unprepare(i2c_imx->clk);
++	pm_runtime_mark_last_busy(&pdev->dev);
++	pm_runtime_put_autosuspend(&pdev->dev);
+ 
+ 	dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
+ 	dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
+@@ -1143,6 +1161,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 
+ 	return 0;   /* Return OK */
+ 
++rpm_disable:
++	pm_runtime_put_noidle(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
++	pm_runtime_set_suspended(&pdev->dev);
++	pm_runtime_dont_use_autosuspend(&pdev->dev);
++
+ clk_disable:
+ 	clk_disable_unprepare(i2c_imx->clk);
+ 	return ret;
+@@ -1151,6 +1175,11 @@ clk_disable:
+ static int i2c_imx_remove(struct platform_device *pdev)
+ {
+ 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
++	int ret;
++
++	ret = pm_runtime_get_sync(&pdev->dev);
++	if (ret < 0)
++		return ret;
+ 
+ 	/* remove adapter */
+ 	dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
+@@ -1165,17 +1194,54 @@ static int i2c_imx_remove(struct platform_device *pdev)
+ 	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
+ 	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
+ 
++	clk_disable_unprepare(i2c_imx->clk);
++
++	pm_runtime_put_noidle(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
++
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int i2c_imx_runtime_suspend(struct device *dev)
++{
++	struct imx_i2c_struct *i2c_imx  = dev_get_drvdata(dev);
++
++	clk_disable_unprepare(i2c_imx->clk);
++
+ 	return 0;
+ }
+ 
++static int i2c_imx_runtime_resume(struct device *dev)
++{
++	struct imx_i2c_struct *i2c_imx  = dev_get_drvdata(dev);
++	int ret;
++
++	ret = clk_prepare_enable(i2c_imx->clk);
++	if (ret)
++		dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
++
++	return ret;
++}
++
++static const struct dev_pm_ops i2c_imx_pm_ops = {
++	SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
++			   i2c_imx_runtime_resume, NULL)
++};
++#define I2C_IMX_PM_OPS (&i2c_imx_pm_ops)
++#else
++#define I2C_IMX_PM_OPS NULL
++#endif /* CONFIG_PM */
++
+ static struct platform_driver i2c_imx_driver = {
+ 	.probe = i2c_imx_probe,
+ 	.remove = i2c_imx_remove,
+-	.driver	= {
+-		.name	= DRIVER_NAME,
++	.driver = {
++		.name = DRIVER_NAME,
++		.pm = I2C_IMX_PM_OPS,
+ 		.of_match_table = i2c_imx_dt_ids,
+ 	},
+-	.id_table	= imx_i2c_devtype,
++	.id_table = imx_i2c_devtype,
+ };
+ 
+ static int __init i2c_adap_imx_init(void)
+-- 
+1.7.9.5
+
+
+From 22a73944115439888eb7cb9f77e5470e499a1da3 Mon Sep 17 00:00:00 2001
+From: Fabio Estevam <fabio.estevam@freescale.com>
+Date: Sun, 1 Nov 2015 14:22:51 -0200
+Subject: [PATCH 41/66] i2c: imx: Improve message log when DMA is not used
+
+When DMA cannot be used, it is better to state that the I2C controller
+will operate in PIO mode.
+
+Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 3ffdcf4..8f62e1f 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -349,7 +349,7 @@ fail_tx:
+ 	dma_release_channel(dma->chan_tx);
+ fail_al:
+ 	devm_kfree(dev, dma);
+-	dev_info(dev, "can't use DMA\n");
++	dev_info(dev, "can't use DMA, using PIO instead.\n");
+ }
+ 
+ static void i2c_imx_dma_callback(void *arg)
+-- 
+1.7.9.5
+
+
+From dc09794be16109deab319ac3596cbb5bc5ef283c Mon Sep 17 00:00:00 2001
+From: Gao Pan <b54642@freescale.com>
+Date: Mon, 2 Nov 2015 17:05:30 +0800
+Subject: [PATCH 42/66] i2c: imx: improve code readability
+
+Replace of_get_named_gpio_flags with of_get_named_gpio because
+the latter has less parameters, which improves code readability.
+
+Signed-off-by: Fugang Duan <B38611@freescale.com>
+Signed-off-by: Gao Pan <b54642@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 8f62e1f..dcea8d2 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -1004,10 +1004,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
+ 			PINCTRL_STATE_DEFAULT);
+ 	i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
+ 			"gpio");
+-	rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+-			"sda-gpios", 0, NULL);
+-	rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+-			"scl-gpios", 0, NULL);
++	rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0);
++	rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0);
+ 
+ 	if (!gpio_is_valid(rinfo->sda_gpio) ||
+ 	    !gpio_is_valid(rinfo->scl_gpio) ||
+-- 
+1.7.9.5
+
+
+From 0ec66079d6765fce59666e6ca004d1b9e2d830b7 Mon Sep 17 00:00:00 2001
+From: Gao Pan <pandy.gao@nxp.com>
+Date: Fri, 8 Jan 2016 13:33:15 +0800
+Subject: [PATCH 43/66] i2c: imx: fix i2c resource leak with dma transfer
+
+In i2c_imx_dma_xfer(), when dmaengine_submit() returns error,
+the context goto label err_submit and then return. However, the
+memory allocated for txdesc has not been freed yet, which
+leads to resource leak.
+
+Signed-off-by: Gao Pan <b54642@freescale.com>
+Signed-off-by: Fugang Duan <B38611@freescale.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-imx.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index dcea8d2..73f42b8 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -396,6 +396,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
+ 	return 0;
+ 
+ err_submit:
++	dmaengine_terminate_all(dma->chan_using);
+ err_desc:
+ 	dma_unmap_single(chan_dev, dma->dma_buf,
+ 			dma->dma_len, dma->dma_data_dir);
+-- 
+1.7.9.5
+
+
+From 26bb58e938cdee6bc2d23fbd4c10ab3f24fe13c8 Mon Sep 17 00:00:00 2001
+From: Ying Zhang <b40530@freescale.com>
+Date: Mon, 11 Jan 2016 17:23:34 +0800
+Subject: [PATCH 44/66] =?UTF-8?q?drivers:=20i2c:=20I2C=20device=20on=20bus=20?=
+ =?UTF-8?q?1=20can=E2=80=99t=20claim=20irq?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+I2C device on bus 1 can’t claim irq on LS2085
+
+===================================
+imx-i2c 2010000.i2c: can’t claim irq 14
+imx-i2c: probe of 2010000.i2c failed with error -16
+====================================
+
+Because I2C1&2, 3&4 share interrupts but the flag is not set
+when requesting IRQ.
+
+Signed-off-by: Ying Zhang <b40530@freescale.com>
+---
+ drivers/i2c/busses/i2c-imx.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index 73f42b8..140fd23 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -1100,7 +1100,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	/* Request IRQ */
+-	ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
++	ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED,
+ 				pdev->name, i2c_imx);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
+-- 
+1.7.9.5
+
+
+From 22f079bd1b8b2156ca3ec76fe49c51eac82a1c11 Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Mon, 14 Sep 2015 16:06:03 +0100
+Subject: [PATCH 45/66] KVM: arm64: add workaround for Cortex-A57 erratum
+ #852523
+
+When restoring the system register state for an AArch32 guest at EL2,
+writes to DACR32_EL2 may not be correctly synchronised by Cortex-A57,
+which can lead to the guest effectively running with junk in the DACR
+and running into unexpected domain faults.
+
+This patch works around the issue by re-ordering our restoration of the
+AArch32 register aliases so that they happen before the AArch64 system
+registers. Ensuring that the registers are restored in this order
+guarantees that they will be correctly synchronised by the core.
+
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+(cherry picked from commit 43297dda0a51e4ffed0888ce727c218cfb7474b6)
+---
+ arch/arm64/kvm/hyp.S |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
+index 17a8fb1..7bd37d0 100644
+--- a/arch/arm64/kvm/hyp.S
++++ b/arch/arm64/kvm/hyp.S
+@@ -943,13 +943,15 @@ ENTRY(__kvm_vcpu_run)
+ 	// Guest context
+ 	add	x2, x0, #VCPU_CONTEXT
+ 
++	// We must restore the 32-bit state before the sysregs, thanks
++	// to Cortex-A57 erratum #852523.
++	restore_guest_32bit_state
+ 	bl __restore_sysregs
+ 	bl __restore_fpsimd
+ 
+ 	skip_debug_state x3, 1f
+ 	bl	__restore_debug
+ 1:
+-	restore_guest_32bit_state
+ 	restore_guest_regs
+ 
+ 	// That's it, no more messing around.
+-- 
+1.7.9.5
+
+
+From 7b24625e62070e10c719eac18cb9fcbdb5791055 Mon Sep 17 00:00:00 2001
+From: Daniel Thompson <daniel.thompson@linaro.org>
+Date: Wed, 22 Jul 2015 12:21:01 +0100
+Subject: [PATCH 46/66] arm64: alternative: Provide if/else/endif assembler
+ macros
+
+The existing alternative_insn macro has some limitations that make it
+hard to work with. In particular the fact it takes instructions from it
+own macro arguments means it doesn't play very nicely with C pre-processor
+macros because the macro arguments look like a string to the C
+pre-processor. Workarounds are (probably) possible but things start to
+look ugly.
+
+Introduce an alternative set of macros that allows instructions to be
+presented to the assembler as normal and switch everything over to the
+new macros.
+
+Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+---
+ arch/arm64/include/asm/alternative.h |   41 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
+index c385a0c..e86681ad 100644
+--- a/arch/arm64/include/asm/alternative.h
++++ b/arch/arm64/include/asm/alternative.h
+@@ -77,6 +77,47 @@ void free_alternatives_memory(void);
+ 	.org	. - (662b-661b) + (664b-663b)
+ .endm
+ 
++/*
++ * Begin an alternative code sequence.
++ *
++ * The code that follows this macro will be assembled and linked as
++ * normal. There are no restrictions on this code.
++ */
++.macro alternative_if_not cap
++	.pushsection .altinstructions, "a"
++	altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
++	.popsection
++661:
++.endm
++
++/*
++ * Provide the alternative code sequence.
++ *
++ * The code that follows this macro is assembled into a special
++ * section to be used for dynamic patching. Code that follows this
++ * macro must:
++ *
++ * 1. Be exactly the same length (in bytes) as the default code
++ *    sequence.
++ *
++ * 2. Not contain a branch target that is used outside of the
++ *    alternative sequence it is defined in (branches into an
++ *    alternative sequence are not fixed up).
++ */
++.macro alternative_else
++662:	.pushsection .altinstr_replacement, "ax"
++663:
++.endm
++
++/*
++ * Complete an alternative code sequence.
++ */
++.macro alternative_endif
++664:	.popsection
++	.org	. - (664b-663b) + (662b-661b)
++	.org	. - (662b-661b) + (664b-663b)
++.endm
++
+ #endif  /*  __ASSEMBLY__  */
+ 
+ #endif /* __ASM_ALTERNATIVE_H */
+-- 
+1.7.9.5
+
+
+From b37bf6ca75095d9aa40308b75b17bb12d7c4391c Mon Sep 17 00:00:00 2001
+From: Lijun Pan <Lijun.Pan@freescale.com>
+Date: Wed, 24 Feb 2016 11:56:12 -0600
+Subject: [PATCH 47/66] arm64: defconfig: change back to 4.2 kernel default
+
+In order to let rpmbuild run successfully, revert all
+the changes on arch/arm64/configs/defconfig.
+
+Signed-off-by: Lijun Pan <Lijun.Pan@freescale.com>
+---
+ arch/arm64/configs/defconfig |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
+index fa6aa9f..4e17e7e 100644
+--- a/arch/arm64/configs/defconfig
++++ b/arch/arm64/configs/defconfig
+@@ -32,7 +32,7 @@ CONFIG_MODULE_UNLOAD=y
+ # CONFIG_BLK_DEV_BSG is not set
+ # CONFIG_IOSCHED_DEADLINE is not set
+ CONFIG_ARCH_EXYNOS7=y
+-CONFIG_ARCH_LAYERSCAPE=y
++CONFIG_ARCH_FSL_LS2085A=y
+ CONFIG_ARCH_HISI=y
+ CONFIG_ARCH_MEDIATEK=y
+ CONFIG_ARCH_SEATTLE=y
+-- 
+1.7.9.5
+
+
+From 50adaf15e5a547a281bc7807d17f2df75a347181 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@freescale.com>
+Date: Fri, 10 Jul 2015 11:42:37 +0800
+Subject: [PATCH 48/66] mmc: sdhci-esdhc: add default quirk
+ SDHCI_QUIRK_NO_HISPD_BIT
+
+eSDHC supports high speed mode, but has no enabling bit for it.
+Add this quirk to avoid writing to eSDHC_PROCTL[DTW] by mistake.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc.h |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
+index a870c42..163ac99 100644
+--- a/drivers/mmc/host/sdhci-esdhc.h
++++ b/drivers/mmc/host/sdhci-esdhc.h
+@@ -21,7 +21,8 @@
+ #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
+ 				SDHCI_QUIRK_NO_BUSY_IRQ | \
+ 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
+-				SDHCI_QUIRK_PIO_NEEDS_DELAY)
++				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
++				SDHCI_QUIRK_NO_HISPD_BIT)
+ 
+ #define ESDHC_SYSTEM_CONTROL	0x2c
+ #define ESDHC_CLOCK_MASK	0x0000fff0
+-- 
+1.7.9.5
+
+
+From 09d78117636d17cd33b82a583b971584c19d807e Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@freescale.com>
+Date: Fri, 10 Jul 2015 11:44:03 +0800
+Subject: [PATCH 49/66] mmc: block: add fixup of broken CMD23 for Sandisk card
+
+Some Sandisk cards(such as "SDMB-32" and "SDM032" cards)
+can't support CMD23, and would generate CMD timeout. So add
+FIX-UP for these two types Sandisk cards.
+
+Error log:
+mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900
+mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900
+mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900
+end_request: I/O error, dev mmcblk0, sector 0
+Buffer I/O error on device mmcblk0, logical block 0
+mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/card/block.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
+index a1b820f..ea0ff37 100644
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -2408,6 +2408,10 @@ static const struct mmc_fixup blk_fixups[] =
+ 	 *
+ 	 * N.B. This doesn't affect SD cards.
+ 	 */
++	MMC_FIXUP("SDMB-32", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
++		  MMC_QUIRK_BLK_NO_CMD23),
++	MMC_FIXUP("SDM032", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
++		  MMC_QUIRK_BLK_NO_CMD23),
+ 	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+ 		  MMC_QUIRK_BLK_NO_CMD23),
+ 	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+-- 
+1.7.9.5
+
+
+From 219bfc50ae5a0ada48e2ae4fbb8e998e67aa84e9 Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 25 Aug 2015 10:02:11 +0800
+Subject: [PATCH 50/66] mmc: sdhci: fix dma memory leak in sdhci_pre_req()
+
+Currently one mrq->data maybe execute dma_map_sg() twice
+when mmc subsystem prepare over one new request, and the
+following log show up:
+	sdhci[sdhci_pre_dma_transfer] invalid cookie: 24, next-cookie 25
+
+In this condition, mrq->date map a dma-memory(1) in sdhci_pre_req
+for the first time, and map another dma-memory(2) in sdhci_prepare_data
+for the second time. But driver only unmap the dma-memory(2), and
+dma-memory(1) never unmapped, which cause the dma memory leak issue.
+
+This patch use another method to map the dma memory for the mrq->data
+which can fix this dma memory leak issue.
+
+Fixes: 348487cb28e6 ("mmc: sdhci: use pipeline mmc requests to improve performance")
+Reported-and-tested-by: Jiri Slaby <jslaby@suse.cz>
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci.c |   67 +++++++++++++++++-----------------------------
+ drivers/mmc/host/sdhci.h |    8 +++---
+ 2 files changed, 29 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 1dbe932..ea10ebc 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -54,8 +54,7 @@ static void sdhci_finish_command(struct sdhci_host *);
+ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
+ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
+ static int sdhci_pre_dma_transfer(struct sdhci_host *host,
+-					struct mmc_data *data,
+-					struct sdhci_host_next *next);
++					struct mmc_data *data);
+ static int sdhci_do_get_cd(struct sdhci_host *host);
+ 
+ #ifdef CONFIG_PM
+@@ -496,7 +495,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
+ 		goto fail;
+ 	BUG_ON(host->align_addr & host->align_mask);
+ 
+-	host->sg_count = sdhci_pre_dma_transfer(host, data, NULL);
++	host->sg_count = sdhci_pre_dma_transfer(host, data);
+ 	if (host->sg_count < 0)
+ 		goto unmap_align;
+ 
+@@ -635,9 +634,11 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
+ 		}
+ 	}
+ 
+-	if (!data->host_cookie)
++	if (data->host_cookie == COOKIE_MAPPED) {
+ 		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+ 			data->sg_len, direction);
++		data->host_cookie = COOKIE_UNMAPPED;
++	}
+ }
+ 
+ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+@@ -833,7 +834,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+ 		} else {
+ 			int sg_cnt;
+ 
+-			sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
++			sg_cnt = sdhci_pre_dma_transfer(host, data);
+ 			if (sg_cnt <= 0) {
+ 				/*
+ 				 * This only happens when someone fed
+@@ -949,11 +950,13 @@ static void sdhci_finish_data(struct sdhci_host *host)
+ 		if (host->flags & SDHCI_USE_ADMA)
+ 			sdhci_adma_table_post(host, data);
+ 		else {
+-			if (!data->host_cookie)
++			if (data->host_cookie == COOKIE_MAPPED) {
+ 				dma_unmap_sg(mmc_dev(host->mmc),
+ 					data->sg, data->sg_len,
+ 					(data->flags & MMC_DATA_READ) ?
+ 					DMA_FROM_DEVICE : DMA_TO_DEVICE);
++				data->host_cookie = COOKIE_UNMAPPED;
++			}
+ 		}
+ 	}
+ 
+@@ -2097,49 +2100,36 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ 	struct mmc_data *data = mrq->data;
+ 
+ 	if (host->flags & SDHCI_REQ_USE_DMA) {
+-		if (data->host_cookie)
++		if (data->host_cookie == COOKIE_GIVEN ||
++				data->host_cookie == COOKIE_MAPPED)
+ 			dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+ 					 data->flags & MMC_DATA_WRITE ?
+ 					 DMA_TO_DEVICE : DMA_FROM_DEVICE);
+-		mrq->data->host_cookie = 0;
++		data->host_cookie = COOKIE_UNMAPPED;
+ 	}
+ }
+ 
+ static int sdhci_pre_dma_transfer(struct sdhci_host *host,
+-				       struct mmc_data *data,
+-				       struct sdhci_host_next *next)
++				       struct mmc_data *data)
+ {
+ 	int sg_count;
+ 
+-	if (!next && data->host_cookie &&
+-	    data->host_cookie != host->next_data.cookie) {
+-		pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n",
+-			__func__, data->host_cookie, host->next_data.cookie);
+-		data->host_cookie = 0;
++	if (data->host_cookie == COOKIE_MAPPED) {
++		data->host_cookie = COOKIE_GIVEN;
++		return data->sg_count;
+ 	}
+ 
+-	/* Check if next job is already prepared */
+-	if (next ||
+-	    (!next && data->host_cookie != host->next_data.cookie)) {
+-		sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg,
+-				     data->sg_len,
+-				     data->flags & MMC_DATA_WRITE ?
+-				     DMA_TO_DEVICE : DMA_FROM_DEVICE);
+-
+-	} else {
+-		sg_count = host->next_data.sg_count;
+-		host->next_data.sg_count = 0;
+-	}
++	WARN_ON(data->host_cookie == COOKIE_GIVEN);
+ 
++	sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++				data->flags & MMC_DATA_WRITE ?
++				DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ 
+ 	if (sg_count == 0)
+-		return -EINVAL;
++		return -ENOSPC;
+ 
+-	if (next) {
+-		next->sg_count = sg_count;
+-		data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
+-	} else
+-		host->sg_count = sg_count;
++	data->sg_count = sg_count;
++	data->host_cookie = COOKIE_MAPPED;
+ 
+ 	return sg_count;
+ }
+@@ -2149,16 +2139,10 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+ {
+ 	struct sdhci_host *host = mmc_priv(mmc);
+ 
+-	if (mrq->data->host_cookie) {
+-		mrq->data->host_cookie = 0;
+-		return;
+-	}
++	mrq->data->host_cookie = COOKIE_UNMAPPED;
+ 
+ 	if (host->flags & SDHCI_REQ_USE_DMA)
+-		if (sdhci_pre_dma_transfer(host,
+-					mrq->data,
+-					&host->next_data) < 0)
+-			mrq->data->host_cookie = 0;
++		sdhci_pre_dma_transfer(host, mrq->data);
+ }
+ 
+ static void sdhci_card_event(struct mmc_host *mmc)
+@@ -3030,7 +3014,6 @@ int sdhci_add_host(struct sdhci_host *host)
+ 		host->max_clk = host->ops->get_max_clock(host);
+ 	}
+ 
+-	host->next_data.cookie = 1;
+ 	/*
+ 	 * In case of Host Controller v3.00, find out whether clock
+ 	 * multiplier is supported.
+diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
+index 5521d29..a9512a4 100644
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc {
+  */
+ #define SDHCI_MAX_SEGS		128
+ 
+-struct sdhci_host_next {
+-	unsigned int	sg_count;
+-	s32		cookie;
++enum sdhci_cookie {
++	COOKIE_UNMAPPED,
++	COOKIE_MAPPED,
++	COOKIE_GIVEN,
+ };
+ 
+ struct sdhci_host {
+@@ -503,7 +504,6 @@ struct sdhci_host {
+ 	unsigned int		tuning_mode;	/* Re-tuning mode supported by host */
+ #define SDHCI_TUNING_MODE_1	0
+ 
+-	struct sdhci_host_next	next_data;
+ 	unsigned long private[0] ____cacheline_aligned;
+ };
+ 
+-- 
+1.7.9.5
+
+
+From 45a04a9e5e88becab80896bdf4870f1bef688116 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@freescale.com>
+Date: Tue, 11 Aug 2015 10:53:34 +0800
+Subject: [PATCH 51/66] mmc: sdhci-of-esdhc: add workaround for pre divider
+ initial value
+
+For eSDHC(version < 2.3), the pre divider only could divide base clock
+by 2 at least. Add workaround for this to avoid unexpected issue.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Acked-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
+Fixes: bd455029d01c ("mmc: sdhci-of-esdhc: Pre divider starts at 1")
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 797be75..653f335 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -208,6 +208,12 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	if (clock == 0)
+ 		return;
+ 
++	/* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
++	temp = esdhc_readw(host, SDHCI_HOST_VERSION);
++	temp = (temp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
++	if (temp < VENDOR_V_23)
++		pre_div = 2;
++
+ 	/* Workaround to reduce the clock frequency for p1010 esdhc */
+ 	if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
+ 		if (clock > 20000000)
+-- 
+1.7.9.5
+
+
+From 1cc0ae43f75d95bc5b01e4e5f781cafacd1546d9 Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 11 Aug 2015 19:38:26 +0800
+Subject: [PATCH 52/66] mmc: sdhci-esdhc-imx: add imx7d support and support
+ HS400
+
+The imx7d usdhc is derived from imx6sx, the difference is that
+imx7d support HS400.
+
+So introduce a new compatible string for imx7d and add HS400
+support for imx7d usdhc.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Acked-by: Dong Aisheng <aisheng.dong@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c |   86 ++++++++++++++++++++++++++++++++++--
+ 1 file changed, 83 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index c6b9f64..b8b7e88 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -44,6 +44,7 @@
+ #define  ESDHC_MIX_CTRL_EXE_TUNE	(1 << 22)
+ #define  ESDHC_MIX_CTRL_SMPCLK_SEL	(1 << 23)
+ #define  ESDHC_MIX_CTRL_FBCLK_SEL	(1 << 25)
++#define  ESDHC_MIX_CTRL_HS400_EN	(1 << 26)
+ /* Bits 3 and 6 are not SDHCI standard definitions */
+ #define  ESDHC_MIX_CTRL_SDHCI_MASK	0xb7
+ /* Tuning bits */
+@@ -60,6 +61,16 @@
+ #define  ESDHC_TUNE_CTRL_MIN		0
+ #define  ESDHC_TUNE_CTRL_MAX		((1 << 7) - 1)
+ 
++/* strobe dll register */
++#define ESDHC_STROBE_DLL_CTRL		0x70
++#define ESDHC_STROBE_DLL_CTRL_ENABLE	(1 << 0)
++#define ESDHC_STROBE_DLL_CTRL_RESET	(1 << 1)
++#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT	3
++
++#define ESDHC_STROBE_DLL_STATUS		0x74
++#define ESDHC_STROBE_DLL_STS_REF_LOCK	(1 << 1)
++#define ESDHC_STROBE_DLL_STS_SLV_LOCK	0x1
++
+ #define ESDHC_TUNING_CTRL		0xcc
+ #define ESDHC_STD_TUNING_EN		(1 << 24)
+ /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
+@@ -120,6 +131,11 @@
+ #define ESDHC_FLAG_ERR004536		BIT(7)
+ /* The IP supports HS200 mode */
+ #define ESDHC_FLAG_HS200		BIT(8)
++/* The IP supports HS400 mode */
++#define ESDHC_FLAG_HS400		BIT(9)
++
++/* A higher clock ferquency than this rate requires strobell dll control */
++#define ESDHC_STROBE_DLL_CLK_FREQ	100000000
+ 
+ struct esdhc_soc_data {
+ 	u32 flags;
+@@ -156,6 +172,12 @@ static struct esdhc_soc_data usdhc_imx6sx_data = {
+ 			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
+ };
+ 
++static struct esdhc_soc_data usdhc_imx7d_data = {
++	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
++			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
++			| ESDHC_FLAG_HS400,
++};
++
+ struct pltfm_imx_data {
+ 	u32 scratchpad;
+ 	struct pinctrl *pinctrl;
+@@ -199,6 +221,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
+ 	{ .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
+ 	{ .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
+ 	{ .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
++	{ .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
+ 	{ /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
+@@ -274,6 +297,9 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+ 				val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
+ 					| SDHCI_SUPPORT_SDR50
+ 					| SDHCI_USE_SDR50_TUNING;
++
++			if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
++				val |= SDHCI_SUPPORT_HS400;
+ 		}
+ 	}
+ 
+@@ -774,6 +800,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
+ 		break;
+ 	case MMC_TIMING_UHS_SDR104:
+ 	case MMC_TIMING_MMC_HS200:
++	case MMC_TIMING_MMC_HS400:
+ 		pinctrl = imx_data->pins_200mhz;
+ 		break;
+ 	default:
+@@ -784,24 +811,68 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
+ 	return pinctrl_select_state(imx_data->pinctrl, pinctrl);
+ }
+ 
++/*
++ * For HS400 eMMC, there is a data_strobe line, this signal is generated
++ * by the device and used for data output and CRC status response output
++ * in HS400 mode. The frequency of this signal follows the frequency of
++ * CLK generated by host. Host receive the data which is aligned to the
++ * edge of data_strobe line. Due to the time delay between CLK line and
++ * data_strobe line, if the delay time is larger than one clock cycle,
++ * then CLK and data_strobe line will misaligned, read error shows up.
++ * So when the CLK is higher than 100MHz, each clock cycle is short enough,
++ * host should config the delay target.
++ */
++static void esdhc_set_strobe_dll(struct sdhci_host *host)
++{
++	u32 v;
++
++	if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
++		/* force a reset on strobe dll */
++		writel(ESDHC_STROBE_DLL_CTRL_RESET,
++			host->ioaddr + ESDHC_STROBE_DLL_CTRL);
++		/*
++		 * enable strobe dll ctrl and adjust the delay target
++		 * for the uSDHC loopback read clock
++		 */
++		v = ESDHC_STROBE_DLL_CTRL_ENABLE |
++			(7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
++		writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
++		/* wait 1us to make sure strobe dll status register stable */
++		udelay(1);
++		v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
++		if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
++			dev_warn(mmc_dev(host->mmc),
++				"warning! HS400 strobe DLL status REF not lock!\n");
++		if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
++			dev_warn(mmc_dev(host->mmc),
++				"warning! HS400 strobe DLL status SLV not lock!\n");
++	}
++}
++
+ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+ {
++	u32 m;
+ 	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;
+ 
++	/* disable ddr mode and disable HS400 mode */
++	m = readl(host->ioaddr + ESDHC_MIX_CTRL);
++	m &= ~(ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN);
++	imx_data->is_ddr = 0;
++
+ 	switch (timing) {
+ 	case MMC_TIMING_UHS_SDR12:
+ 	case MMC_TIMING_UHS_SDR25:
+ 	case MMC_TIMING_UHS_SDR50:
+ 	case MMC_TIMING_UHS_SDR104:
+ 	case MMC_TIMING_MMC_HS200:
++		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
+ 		break;
+ 	case MMC_TIMING_UHS_DDR50:
+ 	case MMC_TIMING_MMC_DDR52:
+-		writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
+-				ESDHC_MIX_CTRL_DDREN,
+-				host->ioaddr + ESDHC_MIX_CTRL);
++		m |= ESDHC_MIX_CTRL_DDREN;
++		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
+ 		imx_data->is_ddr = 1;
+ 		if (boarddata->delay_line) {
+ 			u32 v;
+@@ -813,6 +884,12 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+ 			writel(v, host->ioaddr + ESDHC_DLL_CTRL);
+ 		}
+ 		break;
++	case MMC_TIMING_MMC_HS400:
++		m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
++		writel(m, host->ioaddr + ESDHC_MIX_CTRL);
++		imx_data->is_ddr = 1;
++		esdhc_set_strobe_dll(host);
++		break;
+ 	}
+ 
+ 	esdhc_change_pinstate(host, timing);
+@@ -1100,6 +1177,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
+ 	if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
+ 		host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
+ 
++	if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
++		host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
++
+ 	if (of_id)
+ 		err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
+ 	else
+-- 
+1.7.9.5
+
+
+From 00ca424a957114180d3266c663ad411a8cd5e48d Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 11 Aug 2015 19:38:27 +0800
+Subject: [PATCH 53/66] mmc: sdhci-esdhc-imx: add tuning-step setting support
+
+tuning-step is the delay cell steps in tuning procedure. The default value
+of tuning-step is 1. Some boards or cards need another value to pass the
+tuning procedure. For example, imx7d-sdb board need the tuning-step value
+as 2, otherwise it can't pass the tuning procedure.
+
+So this patch add the tuning-step setting in driver, so that user can set
+the tuning-step value in dts.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Acked-by: Dong Aisheng <aisheng.dong@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c          |    9 +++++++++
+ include/linux/platform_data/mmc-esdhc-imx.h |    1 +
+ 2 files changed, 10 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index b8b7e88..298551d 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -75,6 +75,7 @@
+ #define ESDHC_STD_TUNING_EN		(1 << 24)
+ /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
+ #define ESDHC_TUNING_START_TAP		0x1
++#define ESDHC_TUNING_STEP_SHIFT		16
+ 
+ /* pinctrl state */
+ #define ESDHC_PINCTRL_STATE_100MHZ	"state_100mhz"
+@@ -474,6 +475,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
+ 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
+ 			u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
+ 			u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
++			u32 tuning_ctrl;
+ 			if (val & SDHCI_CTRL_TUNED_CLK) {
+ 				v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
+ 			} else {
+@@ -484,6 +486,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
+ 			if (val & SDHCI_CTRL_EXEC_TUNING) {
+ 				v |= ESDHC_MIX_CTRL_EXE_TUNE;
+ 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
++				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
++				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
++				if (imx_data->boarddata.tuning_step)
++					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
++					writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
+ 			} else {
+ 				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+ 			}
+@@ -963,6 +970,8 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
+ 	if (gpio_is_valid(boarddata->wp_gpio))
+ 		boarddata->wp_type = ESDHC_WP_GPIO;
+ 
++	of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
++
+ 	if (of_find_property(np, "no-1-8-v", NULL))
+ 		boarddata->support_vsel = false;
+ 	else
+diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
+index e1571ef..95ccab3 100644
+--- a/include/linux/platform_data/mmc-esdhc-imx.h
++++ b/include/linux/platform_data/mmc-esdhc-imx.h
+@@ -45,5 +45,6 @@ struct esdhc_platform_data {
+ 	int max_bus_width;
+ 	bool support_vsel;
+ 	unsigned int delay_line;
++	unsigned int tuning_step;       /* The delay cell steps in tuning procedure */
+ };
+ #endif /* __ASM_ARCH_IMX_ESDHC_H */
+-- 
+1.7.9.5
+
+
+From cc569b4ce119f6864b360b6f1b144a69597ffeaf Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 11 Aug 2015 19:38:30 +0800
+Subject: [PATCH 54/66] mmc: sdhci-esdhc-imx: set back the burst_length_enable
+ bit to 1
+
+Currently we find that if a usdhc is choosed to boot system, then ROM
+code will set the burst length enable bit of this usdhc as 0.
+
+This will make performance drop a lot if this usdhc's burst length is
+configed. So this patch set back the burst_length_enable bit as 1,
+which is the default value, and means burst length is enabled for INCR.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Acked-by: Dong Aisheng <aisheng.dong@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index 298551d..ac8ec01 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -32,6 +32,7 @@
+ #include "sdhci-esdhc.h"
+ 
+ #define	ESDHC_CTRL_D3CD			0x08
++#define ESDHC_BURST_LEN_EN_INCR		(1 << 27)
+ /* VENDOR SPEC register */
+ #define ESDHC_VENDOR_SPEC		0xc0
+ #define  ESDHC_VENDOR_SPEC_SDIO_QUIRK	(1 << 1)
+@@ -1163,6 +1164,21 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
+ 		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+ 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
+ 
++		/*
++		 * ROM code will change the bit burst_length_enable setting
++		 * to zero if this usdhc is choosed to boot system. Change
++		 * it back here, otherwise it will impact the performance a
++		 * lot. This bit is used to enable/disable the burst length
++		 * for the external AHB2AXI bridge, it's usefully especially
++		 * for INCR transfer because without burst length indicator,
++		 * the AHB2AXI bridge does not know the burst length in
++		 * advance. And without burst length indicator, AHB INCR
++		 * transfer can only be converted to singles on the AXI side.
++		 */
++		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
++			| ESDHC_BURST_LEN_EN_INCR,
++			host->ioaddr + SDHCI_HOST_CONTROL);
++
+ 		if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
+ 			host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
+ 
+-- 
+1.7.9.5
+
+
+From 2de848aadb51b03188fd68c273bc4a0e08195e7c Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 11 Aug 2015 19:38:31 +0800
+Subject: [PATCH 55/66] mmc: sdhci-esdhc-imx: change default watermark level
+ and burst length
+
+By default, for all imx SoC types, the watermark level is 16, and the
+burst length is 8. But if the SDIO/SD/MMC I/O speed is fast enough,
+this default watermark level and burst length will be the performance
+bottleneck.
+
+For example, i.MX7D support eMMC HS400 mode, this mode can run in 8 bit,
+200MHZ DDR mode. So the I/O speed improve a lot compare to SD3.0.
+The default burst length is 8, if we don't change this value, in
+HS400 mode, when we do eMMC read operation, we can find that the
+clock signal will stop for a period of time. This means the speed
+of data moving on AHB bus is slower than I/O speed. So we should
+improve the speed of data moving on AHB bus.
+
+This patch set the default burst length as 16, and set the default
+watermark level as 64. The test result is the clock signal has
+no stop during the eMMC HS400 operation.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Acked-by: Dong Aisheng <aisheng.dong@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index ac8ec01..886d230 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -1160,7 +1160,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
+ 	 * to something insane.  Change it back here.
+ 	 */
+ 	if (esdhc_is_usdhc(imx_data)) {
+-		writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
++		writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
++
+ 		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+ 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
+ 
+-- 
+1.7.9.5
+
+
+From a293877d6b40d35624e533d42ca537d04569f4eb Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 15 Sep 2015 18:32:58 +0800
+Subject: [PATCH 56/66] mmc: sdhci: call sdhci_init() before request irq
+
+sdhci_init() will clear all irqs and set the needed irqs. So
+logically sdhci_init() should be called before request irq.
+
+If not, some irqs may be triggled and handled wrongly. Take
+the following into consideration, after request irq, if
+SDIO card interrupt enabled, a sd card in the sd slot will
+trigger a mass of interrupt(SDHCI_INT_CARD_INT), because at
+this time, the vmmc-regulator still not restore, no voltage
+supply for the sd card, so the pin of data0~data3 change and
+keep low, interrupt(SDHCI_INT_CARD_INT) will rise up ceaselessly.
+Due to we already reguest irq, system will be busy in handling
+this endless irq, can't response to other event.
+
+So we should call sdhci_init() before request irq in sd resume.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci.c |   22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index ea10ebc..faab934 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2693,17 +2693,6 @@ int sdhci_resume_host(struct sdhci_host *host)
+ 			host->ops->enable_dma(host);
+ 	}
+ 
+-	if (!device_may_wakeup(mmc_dev(host->mmc))) {
+-		ret = request_threaded_irq(host->irq, sdhci_irq,
+-					   sdhci_thread_irq, IRQF_SHARED,
+-					   mmc_hostname(host->mmc), host);
+-		if (ret)
+-			return ret;
+-	} else {
+-		sdhci_disable_irq_wakeups(host);
+-		disable_irq_wake(host->irq);
+-	}
+-
+ 	if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) &&
+ 	    (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) {
+ 		/* Card keeps power but host controller does not */
+@@ -2716,6 +2705,17 @@ int sdhci_resume_host(struct sdhci_host *host)
+ 		mmiowb();
+ 	}
+ 
++	if (!device_may_wakeup(mmc_dev(host->mmc))) {
++		ret = request_threaded_irq(host->irq, sdhci_irq,
++					   sdhci_thread_irq, IRQF_SHARED,
++					   mmc_hostname(host->mmc), host);
++		if (ret)
++			return ret;
++	} else {
++		sdhci_disable_irq_wakeups(host);
++		disable_irq_wake(host->irq);
++	}
++
+ 	sdhci_enable_card_detection(host);
+ 
+ 	return ret;
+-- 
+1.7.9.5
+
+
+From e2ef5eb6b3c7b0ef014571ad93d6d4084d09e3bd Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@freescale.com>
+Date: Wed, 16 Sep 2015 14:36:10 +0800
+Subject: [PATCH 57/66] mmc: sdhci-pltfm: enable interrupt mode to detect card
+ for ls1021a
+
+Enable interrupt mode to detect card instead of polling mode for
+ls1021a by removing the quirk SDHCI_QUIRK_BROKEN_CARD_DETECTION.
+This could improve data transferring performance and avoid the call
+trace caused by polling card status sometime.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 653f335..2a54dbe 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -371,7 +371,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ 	    of_device_is_compatible(np, "fsl,p5020-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p1020-esdhc") ||
+-	    of_device_is_compatible(np, "fsl,t1040-esdhc"))
++	    of_device_is_compatible(np, "fsl,t1040-esdhc") ||
++	    of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
+ 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ 
+ 	if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
+-- 
+1.7.9.5
+
+
+From bad219a04683bbce2fc552175041a1ebb8da9caa Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Thu, 8 Oct 2015 18:36:36 +0800
+Subject: [PATCH 58/66] mmc: sdhci-of-esdhc: support both BE and LE host
+ controller
+
+To support little endian eSDHC controller, we redefine both BE and
+LE IO accessors. In the new accessors, use ioread*/iowrite* instead
+of in_be32/out_be32 and will select accessors according to endian
+mode in probe function.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc.h    |    2 +
+ drivers/mmc/host/sdhci-of-esdhc.c |  451 ++++++++++++++++++++++++++++---------
+ 2 files changed, 341 insertions(+), 112 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
+index 163ac99..de132e2 100644
+--- a/drivers/mmc/host/sdhci-esdhc.h
++++ b/drivers/mmc/host/sdhci-esdhc.h
+@@ -24,6 +24,8 @@
+ 				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
+ 				SDHCI_QUIRK_NO_HISPD_BIT)
+ 
++#define ESDHC_PROCTL		0x28
++
+ #define ESDHC_SYSTEM_CONTROL	0x2c
+ #define ESDHC_CLOCK_MASK	0x0000fff0
+ #define ESDHC_PREDIV_SHIFT	8
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 2a54dbe..910838f 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -24,122 +24,318 @@
+ 
+ #define VENDOR_V_22	0x12
+ #define VENDOR_V_23	0x13
+-static u32 esdhc_readl(struct sdhci_host *host, int reg)
++
++struct sdhci_esdhc {
++	u8 vendor_ver;
++	u8 spec_ver;
++};
++
++/**
++ * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register
++ *		       to make it compatible with SD spec.
++ *
++ * @host: pointer to sdhci_host
++ * @spec_reg: SD spec register address
++ * @value: 32bit eSDHC register value on spec_reg address
++ *
++ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
++ * registers are 32 bits. There are differences in register size, register
++ * address, register function, bit position and function between eSDHC spec
++ * and SD spec.
++ *
++ * Return a fixed up register value
++ */
++static u32 esdhc_readl_fixup(struct sdhci_host *host,
++				     int spec_reg, u32 value)
+ {
++	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++	struct sdhci_esdhc *esdhc = pltfm_host->priv;
+ 	u32 ret;
+ 
+-	ret = in_be32(host->ioaddr + reg);
+ 	/*
+ 	 * The bit of ADMA flag in eSDHC is not compatible with standard
+ 	 * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is
+ 	 * supported by eSDHC.
+ 	 * And for many FSL eSDHC controller, the reset value of field
+-	 * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA,
++	 * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA,
+ 	 * only these vendor version is greater than 2.2/0x12 support ADMA.
+-	 * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the
+-	 * the verdor version number, oxFE is SDHCI_HOST_VERSION.
+ 	 */
+-	if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) {
+-		u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+-		tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+-		if (tmp > VENDOR_V_22)
+-			ret |= SDHCI_CAN_DO_ADMA2;
++	if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) {
++		if (esdhc->vendor_ver > VENDOR_V_22) {
++			ret = value | SDHCI_CAN_DO_ADMA2;
++			return ret;
++		}
+ 	}
+-
++	ret = value;
+ 	return ret;
+ }
+ 
+-static u16 esdhc_readw(struct sdhci_host *host, int reg)
++static u16 esdhc_readw_fixup(struct sdhci_host *host,
++				     int spec_reg, u32 value)
+ {
+ 	u16 ret;
+-	int base = reg & ~0x3;
+-	int shift = (reg & 0x2) * 8;
++	int shift = (spec_reg & 0x2) * 8;
+ 
+-	if (unlikely(reg == SDHCI_HOST_VERSION))
+-		ret = in_be32(host->ioaddr + base) & 0xffff;
++	if (spec_reg == SDHCI_HOST_VERSION)
++		ret = value & 0xffff;
+ 	else
+-		ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
++		ret = (value >> shift) & 0xffff;
+ 	return ret;
+ }
+ 
+-static u8 esdhc_readb(struct sdhci_host *host, int reg)
++static u8 esdhc_readb_fixup(struct sdhci_host *host,
++				     int spec_reg, u32 value)
+ {
+-	int base = reg & ~0x3;
+-	int shift = (reg & 0x3) * 8;
+-	u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff;
++	u8 ret;
++	u8 dma_bits;
++	int shift = (spec_reg & 0x3) * 8;
++
++	ret = (value >> shift) & 0xff;
+ 
+ 	/*
+ 	 * "DMA select" locates at offset 0x28 in SD specification, but on
+ 	 * P5020 or P3041, it locates at 0x29.
+ 	 */
+-	if (reg == SDHCI_HOST_CONTROL) {
+-		u32 dma_bits;
+-
+-		dma_bits = in_be32(host->ioaddr + reg);
++	if (spec_reg == SDHCI_HOST_CONTROL) {
+ 		/* DMA select is 22,23 bits in Protocol Control Register */
+-		dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK;
+-
++		dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK;
+ 		/* fixup the result */
+ 		ret &= ~SDHCI_CTRL_DMA_MASK;
+ 		ret |= dma_bits;
+ 	}
+-
+ 	return ret;
+ }
+ 
+-static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
++/**
++ * esdhc_write*_fixup - Fixup the SD spec register value so that it could be
++ *			written into eSDHC register.
++ *
++ * @host: pointer to sdhci_host
++ * @spec_reg: SD spec register address
++ * @value: 8/16/32bit SD spec register value that would be written
++ * @old_value: 32bit eSDHC register value on spec_reg address
++ *
++ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC
++ * registers are 32 bits. There are differences in register size, register
++ * address, register function, bit position and function between eSDHC spec
++ * and SD spec.
++ *
++ * Return a fixed up register value
++ */
++static u32 esdhc_writel_fixup(struct sdhci_host *host,
++				     int spec_reg, u32 value, u32 old_value)
+ {
++	u32 ret;
++
+ 	/*
+-	 * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+-	 * when SYSCTL[RSTD]) is set for some special operations.
+-	 * No any impact other operation.
++	 * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
++	 * when SYSCTL[RSTD] is set for some special operations.
++	 * No any impact on other operation.
+ 	 */
+-	if (reg == SDHCI_INT_ENABLE)
+-		val |= SDHCI_INT_BLK_GAP;
+-	sdhci_be32bs_writel(host, val, reg);
++	if (spec_reg == SDHCI_INT_ENABLE)
++		ret = value | SDHCI_INT_BLK_GAP;
++	else
++		ret = value;
++
++	return ret;
+ }
+ 
+-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
++static u32 esdhc_writew_fixup(struct sdhci_host *host,
++				     int spec_reg, u16 value, u32 old_value)
+ {
+-	if (reg == SDHCI_BLOCK_SIZE) {
++	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++	int shift = (spec_reg & 0x2) * 8;
++	u32 ret;
++
++	switch (spec_reg) {
++	case SDHCI_TRANSFER_MODE:
++		/*
++		 * Postpone this write, we must do it together with a
++		 * command write that is down below. Return old value.
++		 */
++		pltfm_host->xfer_mode_shadow = value;
++		return old_value;
++	case SDHCI_COMMAND:
++		ret = (value << 16) | pltfm_host->xfer_mode_shadow;
++		return ret;
++	}
++
++	ret = old_value & (~(0xffff << shift));
++	ret |= (value << shift);
++
++	if (spec_reg == SDHCI_BLOCK_SIZE) {
+ 		/*
+ 		 * Two last DMA bits are reserved, and first one is used for
+ 		 * non-standard blksz of 4096 bytes that we don't support
+ 		 * yet. So clear the DMA boundary bits.
+ 		 */
+-		val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
++		ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0));
+ 	}
+-	sdhci_be32bs_writew(host, val, reg);
++	return ret;
+ }
+ 
+-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
++static u32 esdhc_writeb_fixup(struct sdhci_host *host,
++				     int spec_reg, u8 value, u32 old_value)
+ {
++	u32 ret;
++	u32 dma_bits;
++	u8 tmp;
++	int shift = (spec_reg & 0x3) * 8;
++
+ 	/*
+ 	 * "DMA select" location is offset 0x28 in SD specification, but on
+ 	 * P5020 or P3041, it's located at 0x29.
+ 	 */
+-	if (reg == SDHCI_HOST_CONTROL) {
+-		u32 dma_bits;
+-
++	if (spec_reg == SDHCI_HOST_CONTROL) {
+ 		/*
+ 		 * If host control register is not standard, exit
+ 		 * this function
+ 		 */
+ 		if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL)
+-			return;
++			return old_value;
+ 
+ 		/* DMA select is 22,23 bits in Protocol Control Register */
+-		dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5;
+-		clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5,
+-			dma_bits);
+-		val &= ~SDHCI_CTRL_DMA_MASK;
+-		val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK;
++		dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5;
++		ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits;
++		tmp = (value & (~SDHCI_CTRL_DMA_MASK)) |
++		      (old_value & SDHCI_CTRL_DMA_MASK);
++		ret = (ret & (~0xff)) | tmp;
++
++		/* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */
++		ret &= ~ESDHC_HOST_CONTROL_RES;
++		return ret;
+ 	}
+ 
+-	/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
+-	if (reg == SDHCI_HOST_CONTROL)
+-		val &= ~ESDHC_HOST_CONTROL_RES;
+-	sdhci_be32bs_writeb(host, val, reg);
++	ret = (old_value & (~(0xff << shift))) | (value << shift);
++	return ret;
++}
++
++static u32 esdhc_be_readl(struct sdhci_host *host, int reg)
++{
++	u32 ret;
++	u32 value;
++
++	value = ioread32be(host->ioaddr + reg);
++	ret = esdhc_readl_fixup(host, reg, value);
++
++	return ret;
++}
++
++static u32 esdhc_le_readl(struct sdhci_host *host, int reg)
++{
++	u32 ret;
++	u32 value;
++
++	value = ioread32(host->ioaddr + reg);
++	ret = esdhc_readl_fixup(host, reg, value);
++
++	return ret;
++}
++
++static u16 esdhc_be_readw(struct sdhci_host *host, int reg)
++{
++	u16 ret;
++	u32 value;
++	int base = reg & ~0x3;
++
++	value = ioread32be(host->ioaddr + base);
++	ret = esdhc_readw_fixup(host, reg, value);
++	return ret;
++}
++
++static u16 esdhc_le_readw(struct sdhci_host *host, int reg)
++{
++	u16 ret;
++	u32 value;
++	int base = reg & ~0x3;
++
++	value = ioread32(host->ioaddr + base);
++	ret = esdhc_readw_fixup(host, reg, value);
++	return ret;
++}
++
++static u8 esdhc_be_readb(struct sdhci_host *host, int reg)
++{
++	u8 ret;
++	u32 value;
++	int base = reg & ~0x3;
++
++	value = ioread32be(host->ioaddr + base);
++	ret = esdhc_readb_fixup(host, reg, value);
++	return ret;
++}
++
++static u8 esdhc_le_readb(struct sdhci_host *host, int reg)
++{
++	u8 ret;
++	u32 value;
++	int base = reg & ~0x3;
++
++	value = ioread32(host->ioaddr + base);
++	ret = esdhc_readb_fixup(host, reg, value);
++	return ret;
++}
++
++static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg)
++{
++	u32 value;
++
++	value = esdhc_writel_fixup(host, reg, val, 0);
++	iowrite32be(value, host->ioaddr + reg);
++}
++
++static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg)
++{
++	u32 value;
++
++	value = esdhc_writel_fixup(host, reg, val, 0);
++	iowrite32(value, host->ioaddr + reg);
++}
++
++static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg)
++{
++	int base = reg & ~0x3;
++	u32 value;
++	u32 ret;
++
++	value = ioread32be(host->ioaddr + base);
++	ret = esdhc_writew_fixup(host, reg, val, value);
++	if (reg != SDHCI_TRANSFER_MODE)
++		iowrite32be(ret, host->ioaddr + base);
++}
++
++static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg)
++{
++	int base = reg & ~0x3;
++	u32 value;
++	u32 ret;
++
++	value = ioread32(host->ioaddr + base);
++	ret = esdhc_writew_fixup(host, reg, val, value);
++	if (reg != SDHCI_TRANSFER_MODE)
++		iowrite32(ret, host->ioaddr + base);
++}
++
++static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg)
++{
++	int base = reg & ~0x3;
++	u32 value;
++	u32 ret;
++
++	value = ioread32be(host->ioaddr + base);
++	ret = esdhc_writeb_fixup(host, reg, val, value);
++	iowrite32be(ret, host->ioaddr + base);
++}
++
++static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg)
++{
++	int base = reg & ~0x3;
++	u32 value;
++	u32 ret;
++
++	value = ioread32(host->ioaddr + base);
++	ret = esdhc_writeb_fixup(host, reg, val, value);
++	iowrite32(ret, host->ioaddr + base);
+ }
+ 
+ /*
+@@ -149,19 +345,17 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+  * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+  * and re-issue the entire read transaction from beginning.
+  */
+-static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
++static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+ {
+-	u32 tmp;
++	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++	struct sdhci_esdhc *esdhc = pltfm_host->priv;
+ 	bool applicable;
+ 	dma_addr_t dmastart;
+ 	dma_addr_t dmanow;
+ 
+-	tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+-	tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+-
+ 	applicable = (intmask & SDHCI_INT_DATA_END) &&
+-		(intmask & SDHCI_INT_BLK_GAP) &&
+-		(tmp == VENDOR_V_23);
++		     (intmask & SDHCI_INT_BLK_GAP) &&
++		     (esdhc->vendor_ver == VENDOR_V_23);
+ 	if (!applicable)
+ 		return;
+ 
+@@ -179,7 +373,11 @@ static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+ 
+ static int esdhc_of_enable_dma(struct sdhci_host *host)
+ {
+-	setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
++	u32 value;
++
++	value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
++	value |= ESDHC_DMA_SNOOP;
++	sdhci_writel(host, value, ESDHC_DMA_SYSCTL);
+ 	return 0;
+ }
+ 
+@@ -199,6 +397,8 @@ 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)
+ {
++	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++	struct sdhci_esdhc *esdhc = pltfm_host->priv;
+ 	int pre_div = 1;
+ 	int div = 1;
+ 	u32 temp;
+@@ -209,9 +409,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+ 		return;
+ 
+ 	/* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */
+-	temp = esdhc_readw(host, SDHCI_HOST_VERSION);
+-	temp = (temp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+-	if (temp < VENDOR_V_23)
++	if (esdhc->vendor_ver < VENDOR_V_23)
+ 		pre_div = 2;
+ 
+ 	/* Workaround to reduce the clock frequency for p1010 esdhc */
+@@ -247,39 +445,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
+ 	mdelay(1);
+ }
+ 
+-static void esdhc_of_platform_init(struct sdhci_host *host)
+-{
+-	u32 vvn;
+-
+-	vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+-	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+-	if (vvn == VENDOR_V_22)
+-		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+-
+-	if (vvn > VENDOR_V_22)
+-		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+-}
+-
+ static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
+ {
+ 	u32 ctrl;
+ 
++	ctrl = sdhci_readl(host, ESDHC_PROCTL);
++	ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK);
+ 	switch (width) {
+ 	case MMC_BUS_WIDTH_8:
+-		ctrl = ESDHC_CTRL_8BITBUS;
++		ctrl |= ESDHC_CTRL_8BITBUS;
+ 		break;
+ 
+ 	case MMC_BUS_WIDTH_4:
+-		ctrl = ESDHC_CTRL_4BITBUS;
++		ctrl |= ESDHC_CTRL_4BITBUS;
+ 		break;
+ 
+ 	default:
+-		ctrl = 0;
+ 		break;
+ 	}
+ 
+-	clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL,
+-			ESDHC_CTRL_BUSWIDTH_MASK, ctrl);
++	sdhci_writel(host, ctrl, ESDHC_PROCTL);
+ }
+ 
+ static void esdhc_reset(struct sdhci_host *host, u8 mask)
+@@ -290,32 +475,13 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
+ 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ }
+ 
+-static const struct sdhci_ops sdhci_esdhc_ops = {
+-	.read_l = esdhc_readl,
+-	.read_w = esdhc_readw,
+-	.read_b = esdhc_readb,
+-	.write_l = esdhc_writel,
+-	.write_w = esdhc_writew,
+-	.write_b = esdhc_writeb,
+-	.set_clock = esdhc_of_set_clock,
+-	.enable_dma = esdhc_of_enable_dma,
+-	.get_max_clock = esdhc_of_get_max_clock,
+-	.get_min_clock = esdhc_of_get_min_clock,
+-	.platform_init = esdhc_of_platform_init,
+-	.adma_workaround = esdhci_of_adma_workaround,
+-	.set_bus_width = esdhc_pltfm_set_bus_width,
+-	.reset = esdhc_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);
++	esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+ 
+ 	return sdhci_suspend_host(host);
+ }
+@@ -328,9 +494,8 @@ static int esdhc_of_resume(struct device *dev)
+ 	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);
++		sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
+ 	}
+-
+ 	return ret;
+ }
+ 
+@@ -343,30 +508,92 @@ static const struct dev_pm_ops esdhc_pmops = {
+ #define ESDHC_PMOPS NULL
+ #endif
+ 
+-static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
+-	/*
+-	 * card detection could be handled via GPIO
+-	 * eSDHC cannot support End Attribute in NOP ADMA descriptor
+-	 */
++static const struct sdhci_ops sdhci_esdhc_be_ops = {
++	.read_l = esdhc_be_readl,
++	.read_w = esdhc_be_readw,
++	.read_b = esdhc_be_readb,
++	.write_l = esdhc_be_writel,
++	.write_w = esdhc_be_writew,
++	.write_b = esdhc_be_writeb,
++	.set_clock = esdhc_of_set_clock,
++	.enable_dma = esdhc_of_enable_dma,
++	.get_max_clock = esdhc_of_get_max_clock,
++	.get_min_clock = esdhc_of_get_min_clock,
++	.adma_workaround = esdhc_of_adma_workaround,
++	.set_bus_width = esdhc_pltfm_set_bus_width,
++	.reset = esdhc_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
++};
++
++static const struct sdhci_ops sdhci_esdhc_le_ops = {
++	.read_l = esdhc_le_readl,
++	.read_w = esdhc_le_readw,
++	.read_b = esdhc_le_readb,
++	.write_l = esdhc_le_writel,
++	.write_w = esdhc_le_writew,
++	.write_b = esdhc_le_writeb,
++	.set_clock = esdhc_of_set_clock,
++	.enable_dma = esdhc_of_enable_dma,
++	.get_max_clock = esdhc_of_get_max_clock,
++	.get_min_clock = esdhc_of_get_min_clock,
++	.adma_workaround = esdhc_of_adma_workaround,
++	.set_bus_width = esdhc_pltfm_set_bus_width,
++	.reset = esdhc_reset,
++	.set_uhs_signaling = sdhci_set_uhs_signaling,
++};
++
++static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = {
++	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
++		| SDHCI_QUIRK_NO_CARD_NO_RESET
++		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
++	.ops = &sdhci_esdhc_be_ops,
++};
++
++static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = {
+ 	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+ 		| SDHCI_QUIRK_NO_CARD_NO_RESET
+ 		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+-	.ops = &sdhci_esdhc_ops,
++	.ops = &sdhci_esdhc_le_ops,
+ };
+ 
++static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
++{
++	struct sdhci_pltfm_host *pltfm_host;
++	struct sdhci_esdhc *esdhc;
++	u16 host_ver;
++
++	pltfm_host = sdhci_priv(host);
++	esdhc = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_esdhc),
++			     GFP_KERNEL);
++
++	host_ver = sdhci_readw(host, SDHCI_HOST_VERSION);
++	esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
++			     SDHCI_VENDOR_VER_SHIFT;
++	esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
++
++	pltfm_host->priv = esdhc;
++}
++
+ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host;
+ 	struct device_node *np;
+ 	int ret;
+ 
+-	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0);
++	np = pdev->dev.of_node;
++
++	if (of_get_property(np, "little-endian", NULL))
++		host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 0);
++	else
++		host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 0);
++
+ 	if (IS_ERR(host))
+ 		return PTR_ERR(host);
+ 
++	esdhc_init(pdev, host);
++
+ 	sdhci_get_of_property(pdev);
+ 
+-	np = pdev->dev.of_node;
+ 	if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p5020-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+-- 
+1.7.9.5
+
+
+From 7b2732d4ee834c53f302b89188e8e01887ecb41b Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Thu, 8 Oct 2015 18:36:47 +0800
+Subject: [PATCH 59/66] mmc: kconfig: reconfigure MMC_SDHCI_OF_ESDHC option
+
+Freescale eSDHC driver now supports both little-endian and
+big-endian mode eSDHC IPs for ARM and PPC. So, MMC_SDHCI_OF_ESDHC
+option needs to be reconfigured.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/Kconfig |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 6a0f9c7..122f108 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -67,7 +67,7 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+ 	  has the effect of scrambling the addresses and formats of data
+ 	  accessed in sizes other than the datum size.
+ 
+-	  This is the case for the Freescale eSDHC and Nintendo Wii SDHCI.
++	  This is the case for the Nintendo Wii SDHCI.
+ 
+ config MMC_SDHCI_PCI
+ 	tristate "SDHCI support on PCI bus"
+@@ -132,8 +132,8 @@ 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
+-	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
++	depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
++	select MMC_SDHCI_IO_ACCESSORS
+ 	help
+ 	  This selects the Freescale eSDHC controller support.
+ 
+-- 
+1.7.9.5
+
+
+From ea2ef8962e89d08e2893227084ed656f916d0d20 Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Thu, 8 Oct 2015 18:36:57 +0800
+Subject: [PATCH 60/66] mmc: sdhci-of-esdhc: add quirk
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL for ls1021a
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 910838f..7b9282b 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -602,6 +602,9 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ 	    of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
+ 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ 
++	if (of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
++		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
++
+ 	if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
+ 		/*
+ 		 * Freescale messed up with P2020 as it has a non-standard
+-- 
+1.7.9.5
+
+
+From 4ac97b96d59352fbc013eff1e223ab23e4fe445c Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Fri, 16 Oct 2015 15:44:03 +0800
+Subject: [PATCH 61/66] mmc: sdhci-of-esdhc: avoid writing power control
+ register
+
+The eSDHC doesn't have a standard power control register, so when
+writing this register in stack we should do nothing to avoid
+incorrect operation.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 7b9282b..90e94a0 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -183,6 +183,12 @@ static u32 esdhc_writeb_fixup(struct sdhci_host *host,
+ 	int shift = (spec_reg & 0x3) * 8;
+ 
+ 	/*
++	 * eSDHC doesn't have a standard power control register, so we do
++	 * nothing here to avoid incorrect operation.
++	 */
++	if (spec_reg == SDHCI_POWER_CONTROL)
++		return old_value;
++	/*
+ 	 * "DMA select" location is offset 0x28 in SD specification, but on
+ 	 * P5020 or P3041, it's located at 0x29.
+ 	 */
+-- 
+1.7.9.5
+
+
+From 04dd6def04872de44db776c1bfd63c0b8dde5da4 Mon Sep 17 00:00:00 2001
+From: Haibo Chen <haibo.chen@freescale.com>
+Date: Tue, 10 Nov 2015 17:43:30 +0800
+Subject: [PATCH 62/66] mmc: sdhci-esdhc-imx: correct the tuning-step setting
+
+Here we use '|=' to set the tuning-step, but before that, we should
+clear the tuning-step, otherwise we could got the wrong setting.
+
+Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
+Acked-by: Dong Aisheng <aisheng.dong@freescale.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index 886d230..9456d8c 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -76,6 +76,7 @@
+ #define ESDHC_STD_TUNING_EN		(1 << 24)
+ /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
+ #define ESDHC_TUNING_START_TAP		0x1
++#define ESDHC_TUNING_STEP_MASK		0x00070000
+ #define ESDHC_TUNING_STEP_SHIFT		16
+ 
+ /* pinctrl state */
+@@ -489,9 +490,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
+ 				m |= ESDHC_MIX_CTRL_FBCLK_SEL;
+ 				tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+ 				tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
+-				if (imx_data->boarddata.tuning_step)
++				if (imx_data->boarddata.tuning_step) {
++					tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
+ 					tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
+-					writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
++				}
++				writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
+ 			} else {
+ 				v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+ 			}
+-- 
+1.7.9.5
+
+
+From 3f449f2691edd7525ba48fe0684b1d195baee7d2 Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Wed, 25 Nov 2015 10:05:37 +0800
+Subject: [PATCH 63/66] mmc: sdhci-of-esdhc: add/remove some quirks according
+ to vendor version
+
+A previous patch had removed esdhc_of_platform_init() by mistake.
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+	u32 vvn;
+
+	vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+	vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+	if (vvn == VENDOR_V_22)
+		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+	if (vvn > VENDOR_V_22)
+		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+}
+
+This patch is used to fix it by add/remove some quirks according to
+verdor version in probe.
+
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Fixes: f4932cfd22f1 ("mmc: sdhci-of-esdhc: support both BE and LE host controller")
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 90e94a0..83b1226 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -584,6 +584,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ {
+ 	struct sdhci_host *host;
+ 	struct device_node *np;
++	struct sdhci_pltfm_host *pltfm_host;
++	struct sdhci_esdhc *esdhc;
+ 	int ret;
+ 
+ 	np = pdev->dev.of_node;
+@@ -600,6 +602,14 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ 
+ 	sdhci_get_of_property(pdev);
+ 
++	pltfm_host = sdhci_priv(host);
++	esdhc = pltfm_host->priv;
++	if (esdhc->vendor_ver == VENDOR_V_22)
++		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
++
++	if (esdhc->vendor_ver > VENDOR_V_22)
++		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
++
+ 	if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p5020-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+-- 
+1.7.9.5
+
+
+From 8f605373c5316cc5a60cf2549b33e6447ee097b0 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Tue, 26 Jan 2016 10:34:17 +0800
+Subject: [PATCH 64/66] mmc: sdhci-of-esdhc: enable IRQ detecting mode for LS
+ platforms
+
+Enable IRQ detecting mode for Layerscape platforms(LS1043A/LS2080A/LS2085A)
+
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ drivers/mmc/host/sdhci-of-esdhc.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
+index 83b1226..43f61ee 100644
+--- a/drivers/mmc/host/sdhci-of-esdhc.c
++++ b/drivers/mmc/host/sdhci-of-esdhc.c
+@@ -615,7 +615,10 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
+ 	    of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,p1020-esdhc") ||
+ 	    of_device_is_compatible(np, "fsl,t1040-esdhc") ||
+-	    of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
++	    of_device_is_compatible(np, "fsl,ls1021a-esdhc") ||
++	    of_device_is_compatible(np, "fsl,ls2080a-esdhc") ||
++	    of_device_is_compatible(np, "fsl,ls2085a-esdhc") ||
++	    of_device_is_compatible(np, "fsl,ls1043a-esdhc"))
+ 		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ 
+ 	if (of_device_is_compatible(np, "fsl,ls1021a-esdhc"))
+-- 
+1.7.9.5
+
+
+From acafcfa12579a1aa365a4ce48eaa63ffb347d133 Mon Sep 17 00:00:00 2001
+From: yangbo lu <yangbo.lu@freescale.com>
+Date: Fri, 4 Dec 2015 16:55:03 -0600
+Subject: [PATCH 65/66] ARM64: dts: ls2080a: fix eSDHC endianness
+
+Add the "little-endian" property to fix the issue that eSDHC
+is not working and dumping out "mmc0: Controller never released
+inhibit bit(s)." error messages constantly.
+
+Fixes: 5461597f6ce0 ("dts/ls2080a: Update DTSI to add support of various peripherals")
+Signed-off-by: Yangbo Lu <yangbo.lu@freescale.com>
+Signed-off-by: Li Yang <leoli@freescale.com>
+Signed-off-by: Kevin Hilman <khilman@linaro.org>
+(cherry picked from commit 2dd2e4d1eaadfc39eae0399c5be1a122a73ed13b)
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |    1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index 1554da4..4b54d31 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -269,6 +269,7 @@
+ 			clock-frequency = <0>;	/* Updated by bootloader */
+ 			voltage-ranges = <1800 1800 3300 3300>;
+ 			sdhci,auto-cmd12;
++			little-endian;
+ 			bus-width = <4>;
+ 		};
+ 
+-- 
+1.7.9.5
+
+
+From 34f9869aab654532e30c0d42ccdd825123c5a4e1 Mon Sep 17 00:00:00 2001
+From: "J. German Rivera" <German.Rivera@freescale.com>
+Date: Fri, 4 Dec 2015 16:56:04 -0600
+Subject: [PATCH 66/66] arm64: dts: Added syscon-reboot node for FSL's LS2080A
+ SoC
+
+Added sys-reboot node to the FSL's LS2080A SoC DT to leverage
+the ARM-generic reboot mechanism for this SoC. This mechanism
+is enabled through CONFIG_POWER_RESET_SYSCON.
+
+Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
+Signed-off-by: Li Yang <leoli@freescale.com>
+Signed-off-by: Olof Johansson <olof@lixom.net>
+(cherry picked from commit c7a5675f525c668ec4dabd06705d5243f0d9da90)
+---
+ arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+index 4b54d31..c6979de 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+@@ -153,6 +153,18 @@
+ 		};
+ 	};
+ 
++	rstcr: syscon@1e60000 {
++		compatible = "fsl,ls2080a-rstcr", "syscon";
++		reg = <0x0 0x1e60000 0x0 0x4>;
++	};
++
++	reboot {
++		compatible ="syscon-reboot";
++		regmap = <&rstcr>;
++		offset = <0x0>;
++		mask = <0x2>;
++	};
++
+ 	timer {
+ 		compatible = "arm,armv8-timer";
+ 		interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */
+-- 
+1.7.9.5
+
diff --git a/SOURCES/config-centos-sig b/SOURCES/config-centos-sig
index 7837a37..8daf0fe 100644
--- a/SOURCES/config-centos-sig
+++ b/SOURCES/config-centos-sig
@@ -15,3 +15,15 @@ CONFIG_SCSI_MPT2SAS_LOGGING=y
 CONFIG_SCSI_MPT3SAS=m
 CONFIG_SCSI_MPT3SAS_MAX_SGE=128
 CONFIG_SCSI_MPT3SAS_LOGGING=y
+
+# NXP Specific Configurations
+# LAYERSCPAE
+CONFIG_ARCH_LAYERSCAPE=y
+# clock
+CONFIG_CLK_QORIQ=y
+# sata
+CONFIG_AHCI_QORIQ=m
+# i2c
+CONFIG_I2C_IMX=m
+# mmc esdhc
+CONFIG_MMC_SDHCI_OF_ESDHC=m
diff --git a/SPECS/kernel-aarch64.spec b/SPECS/kernel-aarch64.spec
index 046f4f7..f6c8bde 100644
--- a/SPECS/kernel-aarch64.spec
+++ b/SPECS/kernel-aarch64.spec
@@ -341,6 +341,9 @@ Patch1012: 0012-drivers-net-xgene-classifier-rss-support.patch
 # Security patches outside redhat
 Patch2000: KEYS-Fix-keyring-ref-leak-in-join_session_keyring.patch
 
+# NXP Patches
+Patch3001: NXP-Layerscape-support.patch
+
 # empty final patch to facilitate testing of kernel patches
 Patch999999: linux-kernel-test.patch
 
@@ -687,6 +690,8 @@ git am %{PATCH1012}
 
 git am %{PATCH2000}
 
+# Apply NXP patches
+git am %{PATCH3001}
 
 # Any further pre-build tree manipulations happen here.
 
-- 
1.7.9.5

