Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 4/4] ARM: sunxi: enable battery on reference design tablets
From: Icenowy Zheng @ 2016-10-09  6:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161009062714.5085-1-icenowy@aosc.xyz>

Since battery is one part of the reference design of Allwinner tablets,
enable the battery node of reference design tablets.

Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
---
Changes since v1:
- Applied to reference design tablet, not Q8 only now.
- Add support for sun5i reference design tablet.

 arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi | 4 ++++
 arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
index 20cc940..9e17b46 100644
--- a/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
+++ b/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
@@ -92,6 +92,10 @@
 
 #include "axp209.dtsi"
 
+&battery {
+	status = "okay";
+};
+
 &lradc {
 	vref-supply = <&reg_ldo2>;
 };
diff --git a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
index 9d90361..74517ab 100644
--- a/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
+++ b/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
@@ -112,6 +112,10 @@
 
 #include "axp22x.dtsi"
 
+&battery {
+	status = "okay";
+};
+
 &reg_aldo1 {
 	regulator-always-on;
 	regulator-min-microvolt = <3000000>;
-- 
2.10.0

^ permalink raw reply related

* [PATCH V2 1/5] powerpc/mpc85xx: Update TMU device tree node for T1040/T1042
From: Jia Hongtao @ 2016-10-09  6:47 UTC (permalink / raw)
  To: linux-arm-kernel

From: Hongtao Jia <hongtao.jia@nxp.com>

SoC compatible string and endianness property are added according to the
new bindings.

Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Changes for V2:
* Rebase on latest linux-next tree (next-20161006).

 arch/powerpc/boot/dts/fsl/t1040si-post.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
index 44e399b..145c7f4 100644
--- a/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
@@ -526,7 +526,7 @@
 
 				       0x00030000 0x00000012
 				       0x00030001 0x0000001d>;
-		#thermal-sensor-cells = <0>;
+		#thermal-sensor-cells = <1>;
 	};
 
 	thermal-zones {
@@ -534,7 +534,7 @@
 			polling-delay-passive = <1000>;
 			polling-delay = <5000>;
 
-			thermal-sensors = <&tmu>;
+			thermal-sensors = <&tmu 2>;
 
 			trips {
 				cpu_alert: cpu-alert {
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH V2 2/5] powerpc/mpc85xx: Update TMU device tree node for T1023/T1024
From: Jia Hongtao @ 2016-10-09  6:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475995626-14049-1-git-send-email-hongtao.jia@nxp.com>

From: Hongtao Jia <hongtao.jia@nxp.com>

SoC compatible string and endianness property are added according to the
new bindings.

Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Changes for V2:
* Rebase on latest linux-next tree (next-20161006).

 arch/powerpc/boot/dts/fsl/t1023si-post.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
index 6e0b489..bce762a 100644
--- a/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
@@ -321,7 +321,7 @@
 				       0x00030001 0x0000000d
 				       0x00030002 0x00000019
 				       0x00030003 0x00000024>;
-		#thermal-sensor-cells = <0>;
+		#thermal-sensor-cells = <1>;
 	};
 
 	thermal-zones {
@@ -329,7 +329,7 @@
 			polling-delay-passive = <1000>;
 			polling-delay = <5000>;
 
-			thermal-sensors = <&tmu>;
+			thermal-sensors = <&tmu 0>;
 
 			trips {
 				cpu_alert: cpu-alert {
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH V2 3/5] arm:dt:ls1021a: Add TMU device tree support for LS1021A
From: Jia Hongtao @ 2016-10-09  6:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475995626-14049-1-git-send-email-hongtao.jia@nxp.com>

From: Hongtao Jia <hongtao.jia@nxp.com>

Also add nodes and properties for thermal management support.

Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Changes for V2:
* Rebase on latest linux-next tree (next-20161006).

 arch/arm/boot/dts/ls1021a.dtsi | 84 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 368e219..282d854 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -47,6 +47,7 @@
 
 #include "skeleton64.dtsi"
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "fsl,ls1021a";
@@ -70,14 +71,15 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu at f00 {
+		cpu0: cpu at f00 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <0xf00>;
 			clocks = <&cluster1_clk>;
+			#cooling-cells = <2>;
 		};
 
-		cpu at f01 {
+		cpu1: cpu at f01 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <0xf01>;
@@ -251,6 +253,84 @@
 			};
 		};
 
+		tmu: tmu at 1f00000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f00000 0x0 0x10000>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x30061>;
+			fsl,tmu-calibration = <0x00000000 0x0000000f
+					       0x00000001 0x00000017
+					       0x00000002 0x0000001e
+					       0x00000003 0x00000026
+					       0x00000004 0x0000002e
+					       0x00000005 0x00000035
+					       0x00000006 0x0000003d
+					       0x00000007 0x00000044
+					       0x00000008 0x0000004c
+					       0x00000009 0x00000053
+					       0x0000000a 0x0000005b
+					       0x0000000b 0x00000064
+
+					       0x00010000 0x00000011
+					       0x00010001 0x0000001c
+					       0x00010002 0x00000024
+					       0x00010003 0x0000002b
+					       0x00010004 0x00000034
+					       0x00010005 0x00000039
+					       0x00010006 0x00000042
+					       0x00010007 0x0000004c
+					       0x00010008 0x00000051
+					       0x00010009 0x0000005a
+					       0x0001000a 0x00000063
+
+					       0x00020000 0x00000013
+					       0x00020001 0x00000019
+					       0x00020002 0x00000024
+					       0x00020003 0x0000002c
+					       0x00020004 0x00000035
+					       0x00020005 0x0000003d
+					       0x00020006 0x00000046
+					       0x00020007 0x00000050
+					       0x00020008 0x00000059
+
+					       0x00030000 0x00000002
+					       0x00030001 0x0000000d
+					       0x00030002 0x00000019
+					       0x00030003 0x00000024>;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 0>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <95000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		dspi0: dspi at 2100000 {
 			compatible = "fsl,ls1021a-v1.0-dspi";
 			#address-cells = <1>;
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH V2 4/5] arm64:dt:ls1043a: Add TMU device tree support for LS1043A
From: Jia Hongtao @ 2016-10-09  6:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475995626-14049-1-git-send-email-hongtao.jia@nxp.com>

From: Hongtao Jia <hongtao.jia@nxp.com>

Also add nodes and properties for thermal management support.

Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Changes for V2:
* Rebase on latest linux-next tree (next-20161006).

 arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts |  2 +-
 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi    | 78 +++++++++++++++++++++++
 3 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
index dd9e919..0989d63 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
@@ -45,7 +45,7 @@
  */
 
 /dts-v1/;
-/include/ "fsl-ls1043a.dtsi"
+#include "fsl-ls1043a.dtsi"
 
 / {
 	model = "LS1043A QDS Board";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
index d2313e0..c37110b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
@@ -45,7 +45,7 @@
  */
 
 /dts-v1/;
-/include/ "fsl-ls1043a.dtsi"
+#include "fsl-ls1043a.dtsi"
 
 / {
 	model = "LS1043A RDB Board";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 220ac70..41e5dc1 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -44,6 +44,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/thermal/thermal.h>
+
 / {
 	compatible = "fsl,ls1043a";
 	interrupt-parent = <&gic>;
@@ -66,6 +68,7 @@
 			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 			next-level-cache = <&l2>;
+			#cooling-cells = <2>;
 		};
 
 		cpu1: cpu at 1 {
@@ -254,6 +257,81 @@
 			big-endian;
 		};
 
+		tmu: tmu at 1f00000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f00000 0x0 0x10000>;
+			interrupts = <0 33 0x4>;
+			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+			fsl,tmu-calibration = <0x00000000 0x00000026
+					       0x00000001 0x0000002d
+					       0x00000002 0x00000032
+					       0x00000003 0x00000039
+					       0x00000004 0x0000003f
+					       0x00000005 0x00000046
+					       0x00000006 0x0000004d
+					       0x00000007 0x00000054
+					       0x00000008 0x0000005a
+					       0x00000009 0x00000061
+					       0x0000000a 0x0000006a
+					       0x0000000b 0x00000071
+
+					       0x00010000 0x00000025
+					       0x00010001 0x0000002c
+					       0x00010002 0x00000035
+					       0x00010003 0x0000003d
+					       0x00010004 0x00000045
+					       0x00010005 0x0000004e
+					       0x00010006 0x00000057
+					       0x00010007 0x00000061
+					       0x00010008 0x0000006b
+					       0x00010009 0x00000076
+
+					       0x00020000 0x00000029
+					       0x00020001 0x00000033
+					       0x00020002 0x0000003d
+					       0x00020003 0x00000049
+					       0x00020004 0x00000056
+					       0x00020005 0x00000061
+					       0x00020006 0x0000006d
+
+					       0x00030000 0x00000021
+					       0x00030001 0x0000002a
+					       0x00030002 0x0000003c
+					       0x00030003 0x0000004e>;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 3>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <95000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		dspi0: dspi at 2100000 {
 			compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi";
 			#address-cells = <1>;
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH V2 5/5] arm64:dt:ls2080a: Add TMU device tree support for LS2080A
From: Jia Hongtao @ 2016-10-09  6:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475995626-14049-1-git-send-email-hongtao.jia@nxp.com>

From: Hongtao Jia <hongtao.jia@nxp.com>

Also add nodes and properties for thermal management support.

Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
---
Changes for V2:
* Rebase on latest linux-next tree (next-20161006).

 arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts  |   2 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts  |   2 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts |   2 +-
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi     | 116 +++++++++++++++++++--
 4 files changed, 111 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
index b0dd010..8bc1f8f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a QDS Board";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
index ad0ebb8..265e0a8 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a RDB Board";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
index 505d038..290604b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a software Simulator model";
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 337da90..723185e 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -44,6 +44,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/thermal/thermal.h>
+
 / {
 	compatible = "fsl,ls2080a";
 	interrupt-parent = <&gic>;
@@ -62,15 +64,16 @@
 		 */
 
 		/* We have 4 clusters having 2 Cortex-A57 cores each */
-		cpu at 0 {
+		cpu0: cpu at 0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 			next-level-cache = <&cluster0_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu at 1 {
+		cpu1: cpu at 1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x1>;
@@ -78,15 +81,16 @@
 			next-level-cache = <&cluster0_l2>;
 		};
 
-		cpu at 100 {
+		cpu2: cpu at 100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x100>;
 			clocks = <&clockgen 1 1>;
 			next-level-cache = <&cluster1_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu at 101 {
+		cpu3: cpu at 101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x101>;
@@ -94,15 +98,16 @@
 			next-level-cache = <&cluster1_l2>;
 		};
 
-		cpu at 200 {
+		cpu4: cpu at 200 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x200>;
 			clocks = <&clockgen 1 2>;
 			next-level-cache = <&cluster2_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu at 201 {
+		cpu5: cpu at 201 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x201>;
@@ -110,15 +115,16 @@
 			next-level-cache = <&cluster2_l2>;
 		};
 
-		cpu at 300 {
+		cpu6: cpu at 300 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x300>;
 			clocks = <&clockgen 1 3>;
 			next-level-cache = <&cluster3_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu at 301 {
+		cpu7: cpu at 301 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x301>;
@@ -215,6 +221,100 @@
 			clocks = <&sysclk>;
 		};
 
+		tmu: tmu at 1f80000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f80000 0x0 0x10000>;
+			interrupts = <0 23 0x4>;
+			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+			fsl,tmu-calibration = <0x00000000 0x00000026
+					       0x00000001 0x0000002d
+					       0x00000002 0x00000032
+					       0x00000003 0x00000039
+					       0x00000004 0x0000003f
+					       0x00000005 0x00000046
+					       0x00000006 0x0000004d
+					       0x00000007 0x00000054
+					       0x00000008 0x0000005a
+					       0x00000009 0x00000061
+					       0x0000000a 0x0000006a
+					       0x0000000b 0x00000071
+
+					       0x00010000 0x00000025
+					       0x00010001 0x0000002c
+					       0x00010002 0x00000035
+					       0x00010003 0x0000003d
+					       0x00010004 0x00000045
+					       0x00010005 0x0000004e
+					       0x00010006 0x00000057
+					       0x00010007 0x00000061
+					       0x00010008 0x0000006b
+					       0x00010009 0x00000076
+
+					       0x00020000 0x00000029
+					       0x00020001 0x00000033
+					       0x00020002 0x0000003d
+					       0x00020003 0x00000049
+					       0x00020004 0x00000056
+					       0x00020005 0x00000061
+					       0x00020006 0x0000006d
+
+					       0x00030000 0x00000021
+					       0x00030001 0x0000002a
+					       0x00030002 0x0000003c
+					       0x00030003 0x0000004e>;
+			little-endian;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 4>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <75000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map1 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu2 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map2 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu4 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map3 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu6 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		serial0: serial at 21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x0 0x21c0500 0x0 0x100>;
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [RESEND PATCH v6, 3/5] usb: xhci-mtk: make IPPC register optional
From: Chunfeng Yun @ 2016-10-09  6:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474437277-27201-4-git-send-email-chunfeng.yun@mediatek.com>

On Wed, 2016-09-21 at 13:54 +0800, Chunfeng Yun wrote:
> Make IPPC register optional to support host side of dual-role mode,
> due to it is moved into common glue layer for simplification.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
>  drivers/usb/host/xhci-mtk.c |   36 +++++++++++++++++++++++++++++-------
>  1 file changed, 29 insertions(+), 7 deletions(-)

Hi Mathias,

    Would you please take a little time out of your busy schedule and
help review this patch?

    Thank you very much.

^ permalink raw reply

* [PATCH v3 00/17] pinctrl: exynos/samsung: Add header with values used for configuration
From: Tomasz Figa @ 2016-10-09  7:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1472987060-28293-1-git-send-email-krzk@kernel.org>

Hi Krzysztof,

2016-09-04 20:04 GMT+09:00 Krzysztof Kozlowski <krzk@kernel.org>:
>
> Hi,
>
> Changes since v2
> ================
> 1. Combine separate patchsets into one. Previously I sent separately the fixes
>    and changes for S3C platforms.
> 2. Fix issues pointed during review.
> 3. Add review tags.
>
> Changes since v1
> ================
> 1. Follow Arnd's suggestion about moving the macros to common place.
> 2. Subjects: replace "GPIO" with "pinctrl".
> 3. There were some major changes here so I did not add Javier's
>    reviewed-by and tested-by tags.
>
> Merging
> =======
> Patches #1 and #2 should probably go through pinctrl tree. In that case I would
> appreciate a stable branch/tag so DTS could base on top of it.
>
> Goal
> ====
> Increase readability:
>         uart0_data: uart0-data {
>                 samsung,pins = "gpa0-0", "gpa0-1";
> -               samsung,pin-function = <2>;
> -               samsung,pin-pud = <0>;
> -               samsung,pin-drv = <0>;
> +               samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
> +               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
> +               samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;

I like the idea, thanks for cleaning this up. However I'd like to
bikeshed the prefix a bit. Since the properties are already prefixed
by "samsung,", I think it would make much more sense to also prefix
the generic values with "SAMSUNG_". Of course for soc/family-specific
values, the soc/family name prefix sounds right.

Similarly for rest of the value names, such as SAMSUNG_PIN_PUD instead
of SAMSUNG_PIN_PULL, which obviously sounds more like correct English,
however hurts the consistency and could confuse the people writing new
dts files.

Best regards,
Tomasz

^ permalink raw reply

* [PATCH V2 1/7] dt-bindings: Update QorIQ TMU thermal bindings
From: Troy Jia @ 2016-10-09  7:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474253068.23153.2.camel@intel.com>

> -----Original Message-----
> From: Zhang Rui [mailto:rui.zhang at intel.com]
> Sent: Monday, September 19, 2016 10:44 AM
> To: Leo Li <pku.leo@gmail.com>; Rob Herring <robh@kernel.org>
> Cc: Troy Jia <hongtao.jia@nxp.com>; devicetree at vger.kernel.org; linux-
> pm at vger.kernel.org; linuxppc-dev <linuxppc-dev@lists.ozlabs.org>; lkml <linux-
> kernel at vger.kernel.org>; Scott Wood <scott.wood@nxp.com>; Eduardo Valentin
> <edubezval@gmail.com>; Kumar Gala <galak@codeaurora.org>; Shawn Guo
> <shawnguo@kernel.org>; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH V2 1/7] dt-bindings: Update QorIQ TMU thermal bindings
> 
> On ?, 2016-09-14 at 11:40 -0500, Leo Li wrote:
> > On Wed, Jun 8, 2016 at 2:52 PM, Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Tue, Jun 07, 2016 at 11:27:34AM +0800, Jia Hongtao wrote:
> > > >
> > > > For different types of SoC the sensor id and endianness may vary.
> > > > "#thermal-sensor-cells" is used to provide sensor id information.
> > > > "little-endian" property is to tell the endianness of TMU.
> > > >
> > > > Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
> > > > ---
> > > > Changes for V2:
> > > > * Remove formatting chnages.
> > > >
> > > > ?Documentation/devicetree/bindings/thermal/qoriq-thermal.txt | 7
> > > > +++++++
> > > > ?1 file changed, 7 insertions(+)
> > > Acked-by: Rob Herring <robh@kernel.org>
> > Hi Zhang Rui,
> >
> > Since you have applied the driver patch, can you also apply the
> > binding patch???The binding is supposed to go with the driver.
> >
> 
> Do you mean I should take both patch 1/7 and 7/7? I can not see the other patches
> in this patch set.

Yes, please take 7/7 as well.
I also reworked the device tree patches and you can find them here:
https://patchwork.kernel.org/patch/9368377/
https://patchwork.kernel.org/patch/9368381/
https://patchwork.kernel.org/patch/9368383/
https://patchwork.kernel.org/patch/9368379/
https://patchwork.kernel.org/patch/9368385/

-Hongtao.

> 
> thanks,
> rui

^ permalink raw reply

* [PATCH v2 1/2] dt-bindings: add bindings doc for ZTE VOU display controller
From: Shawn Guo @ 2016-10-09  7:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161003174429.GA26054@rob-hp-laptop>

On Mon, Oct 03, 2016 at 12:44:29PM -0500, Rob Herring wrote:
> > +Example:
> > +
> > +vou: vou at 1440000 {
> > +	compatible = "zte,zx296718-vou";
> > +	#address-cells = <1>;
> > +	#size-cells = <1>;
> > +	reg = <0x1440000 0x10000>;
> > +	ranges;
> 
> You still have overlapping addresses. Explicitly list the sub ranges in 
> reg here used by the VOU driver if the driver usage doesn't overlap. If 
> there is overlap (2 drivers accessing the same range), then you need 
> some APIs between the components (or possibly regmap).

The driver matching "zte,zx296718-vou" doesn't map or access the any
'reg' address.  The 'reg' property here is more like a hint telling
that the VOU block covers the address space of all child devices.

I will simply drop the 'reg' property here.

> Also, don't do an empty ranges here. Fill it in so the child nodes are 
> just offsets of 0x1440000

Okay.  I thought that empty 'ranges' is fine as long as parent and child
address spaces are identical (1:1 mapping).

So with your suggestion, I made the changes below.  Let me know if this
is still not what you are asking for.

Shawn

-----8<-----------------

diff --git a/Documentation/devicetree/bindings/display/zte,vou.txt b/Documentation/devicetree/bindings/display/zte,vou.txt
index d03ba4c4810c..6bb4ab2517ef 100644
--- a/Documentation/devicetree/bindings/display/zte,vou.txt
+++ b/Documentation/devicetree/bindings/display/zte,vou.txt
@@ -56,14 +56,13 @@ vou: vou@1440000 {
        compatible = "zte,zx296718-vou";
        #address-cells = <1>;
        #size-cells = <1>;
-       reg = <0x1440000 0x10000>;
-       ranges;
+       ranges = <0 0x1440000 0x10000>;
 
-       dpc: dpc at 1440000 {
+       dpc: dpc at 0 {
                compatible = "zte,zx296718-dpc";
-               reg = <0x1440000 0x1000>, <0x1441000 0x1000>,
-                     <0x1445000 0x1000>, <0x1446000 0x1000>,
-                     <0x144a000 0x1000>;
+               reg = <0x0000 0x1000>, <0x1000 0x1000>,
+                     <0x5000 0x1000>, <0x6000 0x1000>,
+                     <0xa000 0x1000>;
                reg-names = "osd", "timing_ctrl",
                            "dtrc", "vou_ctrl",
                            "otfppu";
@@ -74,9 +73,9 @@ vou: vou at 1440000 {
                              "main_wclk", "aux_wclk";
        };
 
-       hdmi: hdmi at 144c000 {
+       hdmi: hdmi at c000 {
                compatible = "zte,zx296718-hdmi";
-               reg = <0x144c000 0x4000>;
+               reg = <0xc000 0x4000>;
                interrupts = <GIC_SPI 82 IRQ_TYPE_EDGE_RISING>;

^ permalink raw reply related

* [PATCH v3 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Jonathan Cameron @ 2016-10-09  8:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161005090443.24576-3-mugunthanvnm@ti.com>

On 05/10/16 10:04, Mugunthan V N wrote:
> This patch adds the required pieces to ti_am335x_adc driver for
> DMA support
> 
> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Hi,

Just the one question inline.  I'll also need an Ack from Lee as
this touches code in mfd (as does the previous patch).
We have obviously missed this merge window, so no particular rush.

Otherwise, looking very nice indeed.  Got to get my BBB out and play
with this now ;)

Jonathan
> ---
>  drivers/iio/adc/ti_am335x_adc.c      | 148 ++++++++++++++++++++++++++++++++++-
>  include/linux/mfd/ti_am335x_tscadc.h |   7 ++
>  2 files changed, 152 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index c3cfacca..ad9dec3 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -30,10 +30,28 @@
>  #include <linux/iio/buffer.h>
>  #include <linux/iio/kfifo_buf.h>
>  
> +#include <linux/dmaengine.h>
> +#include <linux/dma-mapping.h>
> +
> +#define DMA_BUFFER_SIZE		SZ_2K
> +
> +struct tiadc_dma {
> +	struct dma_slave_config	conf;
> +	struct dma_chan		*chan;
> +	dma_addr_t		addr;
> +	dma_cookie_t		cookie;
> +	u8			*buf;
> +	int			current_period;
> +	int			period_size;
> +	u8			fifo_thresh;
> +};
> +
>  struct tiadc_device {
>  	struct ti_tscadc_dev *mfd_tscadc;
> +	struct tiadc_dma dma;
>  	struct mutex fifo1_lock; /* to protect fifo access */
>  	int channels;
> +	int total_ch_enabled;
>  	u8 channel_line[8];
>  	u8 channel_step[8];
>  	int buffer_en_ch_steps;
> @@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
>  	return IRQ_HANDLED;
>  }
>  
> +static void tiadc_dma_rx_complete(void *param)
> +{
> +	struct iio_dev *indio_dev = param;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct tiadc_dma *dma = &adc_dev->dma;
> +	u8 *data;
> +	int i;
> +
> +	data = dma->buf + dma->current_period * dma->period_size;
> +	dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
> +
> +	for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) {
> +		iio_push_to_buffers(indio_dev, data);
> +		data += indio_dev->scan_bytes;
> +	}
Hmm. Another case for the mooted iio_push_to_buffers_multi. Guess
we should move on with that one ;)
> +}
> +
> +static int tiadc_start_dma(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct tiadc_dma *dma = &adc_dev->dma;
> +	struct dma_async_tx_descriptor *desc;
> +
> +	dma->current_period = 0; /* We start to fill period 0 */
> +	/*
> +	 * Make the fifo thresh as the multiple of total number of
> +	 * channels enabled, so make sure that cyclic DMA period
> +	 * length is also a multiple of total number of channels
> +	 * enabled. This ensures that no invalid data is reported
> +	 * to the stack via iio_push_to_buffers().
> +	 */
> +	dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
> +				     adc_dev->total_ch_enabled) - 1;
> +	/* Make sure that period length is multiple of fifo thresh level */
> +	dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
> +				    (dma->fifo_thresh + 1) * sizeof(u16));
> +
> +	dma->conf.src_maxburst = dma->fifo_thresh + 1;
> +	dmaengine_slave_config(dma->chan, &dma->conf);
> +
> +	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
> +					 dma->period_size * 2,
> +					 dma->period_size, DMA_DEV_TO_MEM,
> +					 DMA_PREP_INTERRUPT);
> +	if (!desc)
> +		return -EBUSY;
> +
> +	desc->callback = tiadc_dma_rx_complete;
> +	desc->callback_param = indio_dev;
> +
> +	dma->cookie = dmaengine_submit(desc);
> +
> +	dma_async_issue_pending(dma->chan);
> +
> +	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
> +	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
> +	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
> +
> +	return 0;
> +}
> +
>  static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>  {
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> @@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
>  static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>  {
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct tiadc_dma *dma = &adc_dev->dma;
> +	unsigned int irq_enable;
>  	unsigned int enb = 0;
>  	u8 bit;
>  
>  	tiadc_step_config(indio_dev);
> -	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
> +	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
>  		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
> +		adc_dev->total_ch_enabled++;
> +	}
>  	adc_dev->buffer_en_ch_steps = enb;
>  
> +	if (dma->chan)
> +		tiadc_start_dma(indio_dev);
> +
>  	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
>  
>  	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
>  				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
> -	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
> -				| IRQENB_FIFO1OVRRUN);
> +
> +	irq_enable = IRQENB_FIFO1OVRRUN;
> +	if (!dma->chan)
> +		irq_enable |= IRQENB_FIFO1THRES;
This changes the non dma behaviour as we no longer set IRQENB_FIFO1THRES.
Why?  Was it wrong before?
> +	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
>  
>  	return 0;
>  }
> @@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>  static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
>  {
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct tiadc_dma *dma = &adc_dev->dma;
>  	int fifo1count, i, read;
>  
>  	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
>  				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
>  	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
>  	adc_dev->buffer_en_ch_steps = 0;
> +	adc_dev->total_ch_enabled = 0;
> +	if (dma->chan) {
> +		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
> +		dmaengine_terminate_async(dma->chan);
> +	}
>  
>  	/* Flush FIFO of leftover data in the time it takes to disable adc */
>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> @@ -430,6 +525,41 @@ static const struct iio_info tiadc_info = {
>  	.driver_module = THIS_MODULE,
>  };
>  
> +static int tiadc_request_dma(struct platform_device *pdev,
> +			     struct tiadc_device *adc_dev)
> +{
> +	struct tiadc_dma	*dma = &adc_dev->dma;
> +	dma_cap_mask_t		mask;
> +
> +	/* Default slave configuration parameters */
> +	dma->conf.direction = DMA_DEV_TO_MEM;
> +	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
> +
> +	dma_cap_zero(mask);
> +	dma_cap_set(DMA_CYCLIC, mask);
> +
> +	/* Get a channel for RX */
> +	dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
> +	if (IS_ERR(dma->chan)) {
> +		int ret = PTR_ERR(dma->chan);
> +
> +		dma->chan = NULL;
> +		return ret;
> +	}
> +
> +	/* RX buffer */
> +	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
> +				      &dma->addr, GFP_KERNEL);
> +	if (!dma->buf)
> +		goto err;
> +
> +	return 0;
> +err:
> +	dma_release_channel(dma->chan);
> +	return -ENOMEM;
> +}
> +
>  static int tiadc_parse_dt(struct platform_device *pdev,
>  			  struct tiadc_device *adc_dev)
>  {
> @@ -512,8 +642,14 @@ static int tiadc_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, indio_dev);
>  
> +	err = tiadc_request_dma(pdev, adc_dev);
> +	if (err && err == -EPROBE_DEFER)
> +		goto err_dma;
> +
>  	return 0;
>  
> +err_dma:
> +	iio_device_unregister(indio_dev);
>  err_buffer_unregister:
>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>  err_free_channels:
> @@ -525,8 +661,14 @@ static int tiadc_remove(struct platform_device *pdev)
>  {
>  	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct tiadc_dma *dma = &adc_dev->dma;
>  	u32 step_en;
>  
> +	if (dma->chan) {
> +		dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
> +				  dma->buf, dma->addr);
> +		dma_release_channel(dma->chan);
> +	}
>  	iio_device_unregister(indio_dev);
>  	tiadc_iio_buffered_hardware_remove(indio_dev);
>  	tiadc_channels_remove(indio_dev);
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index e45a208..b9a53e0 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -23,6 +23,8 @@
>  #define REG_IRQENABLE		0x02C
>  #define REG_IRQCLR		0x030
>  #define REG_IRQWAKEUP		0x034
> +#define REG_DMAENABLE_SET	0x038
> +#define REG_DMAENABLE_CLEAR	0x03c
>  #define REG_CTRL		0x040
>  #define REG_ADCFSM		0x044
>  #define REG_CLKDIV		0x04C
> @@ -36,6 +38,7 @@
>  #define REG_FIFO0THR		0xE8
>  #define REG_FIFO1CNT		0xF0
>  #define REG_FIFO1THR		0xF4
> +#define REG_DMA1REQ		0xF8
>  #define REG_FIFO0		0x100
>  #define REG_FIFO1		0x200
>  
> @@ -126,6 +129,10 @@
>  #define FIFOREAD_DATA_MASK (0xfff << 0)
>  #define FIFOREAD_CHNLID_MASK (0xf << 16)
>  
> +/* DMA ENABLE/CLEAR Register */
> +#define DMA_FIFO0		BIT(0)
> +#define DMA_FIFO1		BIT(1)
> +
>  /* Sequencer Status */
>  #define SEQ_STATUS BIT(5)
>  #define CHARGE_STEP		0x11
> 

^ permalink raw reply

* [PATCH v3 3/4] ARM: dts: am33xx: add DMA properties for tscadc
From: Jonathan Cameron @ 2016-10-09  8:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161005090443.24576-4-mugunthanvnm@ti.com>

On 05/10/16 10:04, Mugunthan V N wrote:
> Add DMA properties for tscadc
> 
> Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Do the binding docs need updating to reflect this?  I can't immediately
find the relevant doc to check!

Jonathan
> ---
>  arch/arm/boot/dts/am33xx.dtsi | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
> index 98748c6..6d607b8 100644
> --- a/arch/arm/boot/dts/am33xx.dtsi
> +++ b/arch/arm/boot/dts/am33xx.dtsi
> @@ -917,6 +917,8 @@
>  			interrupts = <16>;
>  			ti,hwmods = "adc_tsc";
>  			status = "disabled";
> +			dmas = <&edma 53 0>, <&edma 57 0>;
> +			dma-names = "fifo0", "fifo1";
>  
>  			tsc {
>  				compatible = "ti,am3359-tsc";
> 

^ permalink raw reply

* [PATCH] ahci: qoriq: added ls1046a platform support
From: yuantian.tang at nxp.com @ 2016-10-09  8:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Tang Yuantian <Yuantian.Tang@nxp.com>

Ls1046a is a new introduced soc which supports ATA3.0.

Signed-off-by: Tang Yuantian <yuantian.tang@nxp.com>
---
 drivers/ata/ahci_qoriq.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index 1eba8df..9884c8c 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -46,11 +46,13 @@
 #define LS1021A_AXICC_ADDR	0xC0
 
 #define SATA_ECC_DISABLE	0x00020000
+#define LS1046A_SATA_ECC_DIS	0x80000000
 
 enum ahci_qoriq_type {
 	AHCI_LS1021A,
 	AHCI_LS1043A,
 	AHCI_LS2080A,
+	AHCI_LS1046A,
 };
 
 struct ahci_qoriq_priv {
@@ -63,6 +65,7 @@ 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,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
+	{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
@@ -175,6 +178,13 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
 		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
 		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
 		break;
+
+	case AHCI_LS1046A:
+		writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr);
+		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+		break;
 	}
 
 	return 0;
@@ -204,9 +214,9 @@ static int ahci_qoriq_probe(struct platform_device *pdev)
 
 	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");
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"sata-ecc");
+	if (res) {
 		qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
 		if (IS_ERR(qoriq_priv->ecc_addr))
 			return PTR_ERR(qoriq_priv->ecc_addr);
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH 5/9] mtd: nand: Expose data interface for ONFI mode 0
From: Boris Brezillon @ 2016-10-09 11:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161009051248.GC10199@brian-ubuntu>

Hi Brian,

On Sat, 8 Oct 2016 22:12:48 -0700
Brian Norris <computersforpeace@gmail.com> wrote:

> On Thu, Sep 15, 2016 at 02:56:25PM +0200, Boris Brezillon wrote:
> > On Thu, 15 Sep 2016 10:32:49 +0200
> > Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >   
> > > The nand layer will need ONFI mode 0 to use it as timing mode
> > > before and right after reset.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > ---
> > >  drivers/mtd/nand/nand_timings.c | 11 +++++++++++
> > >  include/linux/mtd/nand.h        |  2 ++
> > >  2 files changed, 13 insertions(+)
> > > 
> > > diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
> > > index 608d098..9cdbc16 100644
> > > --- a/drivers/mtd/nand/nand_timings.c
> > > +++ b/drivers/mtd/nand/nand_timings.c
> > > @@ -297,3 +297,14 @@ int onfi_init_data_interface(struct nand_chip *chip,
> > >  
> > >  	return 0;
> > >  }
> > > +
> > > +/**
> > > + * nand_get_default_data_interface - [NAND Interface] Retrieve NAND
> > > + * data interface for mode 0. This is used as default timing after
> > > + * reset.
> > > + */
> > > +const struct nand_data_interface *nand_get_default_data_interface(void)
> > > +{
> > > +	return &onfi_sdr_timings[0];
> > > +}
> > > +EXPORT_SYMBOL(nand_get_default_data_interface);  
> > 
> > You export nand_get_default_data_interface() here, but you don't export
> > onfi_init_data_interface().
> > None of these functions should be called from NAND controller drivers,
> > so they don't need to be exported. ITOH, the prototypes are public
> > (defined in nand.h), so nothing prevents a driver from calling these
> > functions.  
> 
> A bit late, but we can still change things for the next cycle of
> course...
> 
> > I don't know what's the best solution here:
> > 1/ Export both nand_get_default_data_interface() and
> >    onfi_init_data_interface()  
> 
> I don't really like this one. We shouldn't export them if we don't want
> people to use them in modules. And I'm sure the various compile-test
> builders out there would complain eventually if someone did.

Yes, I had the feeling it was the wrong choice, but it was also the
less invasive one ;-).

> 
> > 2/ Do not export them, but keep their prototypes in nand.h with a
> >    comment saying that they should not be directly called by NAND
> >    controller drivers  
> 
> Could be OK.

I don't like that one. It just bloats nand.h with things that are not
supposed to be exported to NAND controller drivers, which just adds
more confusion (the NAND framework is already hard to
follow/understand, let's try not to make it worse).

> 
> > 3/ Removing the prototypes from nand.h and defining them in nand_base.c
> >    (or in a private header).  
> 
> I like this one. Why not add a drivers/mtd/nand/nand.h that's intended
> for the nand.{o,ko} module only?

I like this one too. I'll try to come up with something (maybe with a
different name, like core.h, to prevent developers from including this
file in their NAND controller drivers).

Thanks,

Boris

^ permalink raw reply

* [PATCH] mm/vmalloc: reduce the number of lazy_max_pages to reduce latency
From: Chris Wilson @ 2016-10-09 12:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAD=GYpYKL9=uY=Fks2xO6oK3bJ772yo4EiJ1tJkVU9PheSD+Cw@mail.gmail.com>

On Sat, Oct 08, 2016 at 08:43:51PM -0700, Joel Fernandes wrote:
> On Thu, Sep 29, 2016 at 1:18 AM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > On Thu, Sep 29, 2016 at 03:34:11PM +0800, Jisheng Zhang wrote:
> >> On Marvell berlin arm64 platforms, I see the preemptoff tracer report
> >> a max 26543 us latency at __purge_vmap_area_lazy, this latency is an
> >> awfully bad for STB. And the ftrace log also shows __free_vmap_area
> >> contributes most latency now. I noticed that Joel mentioned the same
> >> issue[1] on x86 platform and gave two solutions, but it seems no patch
> >> is sent out for this purpose.
> >>
> >> This patch adopts Joel's first solution, but I use 16MB per core
> >> rather than 8MB per core for the number of lazy_max_pages. After this
> >> patch, the preemptoff tracer reports a max 6455us latency, reduced to
> >> 1/4 of original result.
> >
> > My understanding is that
> >
> > diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> > index 91f44e78c516..3f7c6d6969ac 100644
> > --- a/mm/vmalloc.c
> > +++ b/mm/vmalloc.c
> > @@ -626,7 +626,6 @@ void set_iounmap_nonlazy(void)
> >  static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
> >                                         int sync, int force_flush)
> >  {
> > -       static DEFINE_SPINLOCK(purge_lock);
> >         struct llist_node *valist;
> >         struct vmap_area *va;
> >         struct vmap_area *n_va;
> > @@ -637,12 +636,6 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
> >          * should not expect such behaviour. This just simplifies locking for
> >          * the case that isn't actually used at the moment anyway.
> >          */
> > -       if (!sync && !force_flush) {
> > -               if (!spin_trylock(&purge_lock))
> > -                       return;
> > -       } else
> > -               spin_lock(&purge_lock);
> > -
> >         if (sync)
> >                 purge_fragmented_blocks_allcpus();
> >
> > @@ -667,7 +660,6 @@ static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
> >                         __free_vmap_area(va);
> >                 spin_unlock(&vmap_area_lock);
> >         }
> > -       spin_unlock(&purge_lock);
> >  }
> >
> [..]
> > should now be safe. That should significantly reduce the preempt-disabled
> > section, I think.
> 
> I believe that the purge_lock is supposed to prevent concurrent purges
> from happening.
> 
> For the case where if you have another concurrent overflow happen in
> alloc_vmap_area() between the spin_unlock and purge :
> 
> spin_unlock(&vmap_area_lock);
> if (!purged)
>    purge_vmap_area_lazy();
> 
> Then the 2 purges would happen at the same time and could subtract
> vmap_lazy_nr twice.

That itself is not the problem, as each instance of
__purge_vmap_area_lazy() operates on its own freelist, and so there will
be no double accounting.

However, removing the lock removes the serialisation which does mean
that alloc_vmap_area() will not block on another thread conducting the
purge, and so it will try to reallocate before that is complete and the
free area made available. It also means that we are doing the
atomic_sub(vmap_lazy_nr) too early.

That supports making the outer lock a mutex as you suggested. But I think
cond_resched_lock() is better for the vmap_area_lock (just because it
turns out to be an expensive loop and we may want the reschedule).
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply

* [PATCH 7/10] mmc: sdhci-xenon: Add support to PHYs of Marvell Xenon SDHC
From: Shawn Lin @ 2016-10-09 13:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ac786510-74b2-f14c-b2a7-9c65fb07e40f@marvell.com>

? 2016/10/8 17:28, Ziji Hu ??:
> Hi Shawn,
>
> On 2016/10/8 10:44, Shawn Lin wrote:
>> ? 2016/10/7 23:22, Gregory CLEMENT ??:
>>> From: Ziji Hu <huziji@marvell.com>
>>>
>>> Marvell Xenon eMMC/SD/SDIO Host Controller contains PHY.
>>> Three types of PHYs are supported.
>>>
>>> Add support to multiple types of PHYs init and configuration.
>>> Add register definitions of PHYs.
>>>
>>> Signed-off-by: Hu Ziji <huziji@marvell.com>
>>> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>>> ---
>>>  MAINTAINERS                        |    1 +-
>>>  drivers/mmc/host/Makefile          |    2 +-
>>>  drivers/mmc/host/sdhci-xenon-phy.c | 1141 +++++++++++++++++++++++++++++-
>>>  drivers/mmc/host/sdhci-xenon-phy.h |  157 ++++-
>>>  drivers/mmc/host/sdhci-xenon.c     |    4 +-
>>>  drivers/mmc/host/sdhci-xenon.h     |   17 +-
>>>  6 files changed, 1321 insertions(+), 1 deletion(-)
>>>  create mode 100644 drivers/mmc/host/sdhci-xenon-phy.c
>>>  create mode 100644 drivers/mmc/host/sdhci-xenon-phy.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 859420e5dfd3..b5673c2ee5f2 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -7583,6 +7583,7 @@ M:    Ziji Hu <huziji@marvell.com>
>>>  L:    linux-mmc at vger.kernel.org
>>>  S:    Supported
>>>  F:    drivers/mmc/host/sdhci-xenon.*
>>> +F:    drivers/mmc/host/sdhci-xenon-phy.*
>>
>> drivers/mmc/host/sdhci-xenon* shoube enough
>>
>>>  F:    Documentation/devicetree/bindings/mmc/marvell,sdhci-xenon.txt
>>>
>>>  MATROX FRAMEBUFFER DRIVER
>>> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
>>> index 75eaf743486c..4f2854556ff7 100644
>>> --- a/drivers/mmc/host/Makefile
>>> +++ b/drivers/mmc/host/Makefile
>>> @@ -82,4 +82,4 @@ ifeq ($(CONFIG_CB710_DEBUG),y)
>>>  endif
>>>
>>>  obj-$(CONFIG_MMC_SDHCI_XENON)    += sdhci-xenon-driver.o
>>> -sdhci-xenon-driver-y        += sdhci-xenon.o
>>> +sdhci-xenon-driver-y        += sdhci-xenon.o sdhci-xenon-phy.o
>>> diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c
>>> new file mode 100644
>>> index 000000000000..4eb8fea1bec9
>>> --- /dev/null
>>> +++ b/drivers/mmc/host/sdhci-xenon-phy.c
>>
>> Well, it's legit to use phy API and move your phy
>> operations to PHY subsystem. :)
>>
>
>     Actually we tried to put the PHY code into Linux PHY framework.
>     But it cannot fit in Linux common PHY framework.
>

Indeed, it seems you need much intercation between the phy and host,
but the phy APIs are not so rich. :)

>     Our Xenon SDHC PHY register is a part of Xenon SDHC register set.
>     Besides, during MMC initialization, MMC sequence has to call several PHY functions to complete timing setting.
>     In those PHY setting functions, they have to access SDHC register and know current MMC setting, such as bus width, clock frequency and speed mode.
>     As a result, we have to implement PHY under MMC directory.
>
>     Thank you.
>
> Best regards,
> Hu Ziji
>
>>> @@ -0,0 +1,1141 @@
>>> +/*
>>> + * PHY support for Xenon SDHC
>>> + *
>>> + * Copyright (C) 2016 Marvell, All Rights Reserved.
>>> + *
>>> + * Author:    Hu Ziji <huziji@marvell.com>
>>> + * Date:    2016-8-24
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License as
>>> + * published by the Free Software Foundation version 2.
>>> + */
>>> +
>>> +#include <linux/slab.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/mmc/host.h>
>>> +#include <linux/mmc/mmc.h>
>>> +#include <linux/mmc/card.h>
>>> +#include <linux/mmc/sdio.h>
>>> +
>>> +#include "sdhci.h"
>>> +#include "sdhci-pltfm.h"
>>> +#include "sdhci-xenon.h"
>>> +
>>> +static const char * const phy_types[] = {
>>> +    "sdh phy",
>>> +    "emmc 5.0 phy",
>>> +    "emmc 5.1 phy"
>>> +};
>>> +
>>> +enum phy_type_enum {
>>> +    SDH_PHY,
>>> +    EMMC_5_0_PHY,
>>> +    EMMC_5_1_PHY,
>>> +    NR_PHY_TYPES
>>> +};
>>> +
>>> +struct soc_pad_ctrl_table {
>>> +    const char *soc;
>>> +    void (*set_soc_pad)(struct sdhci_host *host,
>>> +                unsigned char signal_voltage);
>>> +};
>>> +
>>> +struct soc_pad_ctrl {
>>> +    /* Register address of SOC PHY PAD ctrl */
>>> +    void __iomem    *reg;
>>> +    /* SOC PHY PAD ctrl type */
>>> +    enum soc_pad_ctrl_type pad_type;
>>> +    /* SOC specific operation to set SOC PHY PAD */
>>> +    void (*set_soc_pad)(struct sdhci_host *host,
>>> +                unsigned char signal_voltage);
>>> +};
>>> +
>>> +static struct xenon_emmc_phy_regs  xenon_emmc_5_0_phy_regs = {
>>> +    .timing_adj    = EMMC_5_0_PHY_TIMING_ADJUST,
>>> +    .func_ctrl    = EMMC_5_0_PHY_FUNC_CONTROL,
>>> +    .pad_ctrl    = EMMC_5_0_PHY_PAD_CONTROL,
>>> +    .pad_ctrl2    = EMMC_5_0_PHY_PAD_CONTROL2,
>>> +    .dll_ctrl    = EMMC_5_0_PHY_DLL_CONTROL,
>>> +    .logic_timing_adj = EMMC_5_0_PHY_LOGIC_TIMING_ADJUST,
>>> +    .delay_mask    = EMMC_5_0_PHY_FIXED_DELAY_MASK,
>>> +    .dll_update    = DLL_UPDATE_STROBE_5_0,
>>> +};
>>> +
>>> +static struct xenon_emmc_phy_regs  xenon_emmc_5_1_phy_regs = {
>>> +    .timing_adj    = EMMC_PHY_TIMING_ADJUST,
>>> +    .func_ctrl    = EMMC_PHY_FUNC_CONTROL,
>>> +    .pad_ctrl    = EMMC_PHY_PAD_CONTROL,
>>> +    .pad_ctrl2    = EMMC_PHY_PAD_CONTROL2,
>>> +    .dll_ctrl    = EMMC_PHY_DLL_CONTROL,
>>> +    .logic_timing_adj = EMMC_PHY_LOGIC_TIMING_ADJUST,
>>> +    .delay_mask    = EMMC_PHY_FIXED_DELAY_MASK,
>>> +    .dll_update    = DLL_UPDATE,
>>> +};
>>> +
>>> +static int xenon_delay_adj_test(struct mmc_card *card);
>>> +
>>> +/*
>>> + * eMMC PHY configuration and operations
>>> + */
>>> +struct emmc_phy_params {
>>> +    bool    slow_mode;
>>> +
>>> +    u8    znr;
>>> +    u8    zpr;
>>> +
>>> +    /* Nr of consecutive Sampling Points of a Valid Sampling Window */
>>> +    u8    nr_tun_times;
>>> +    /* Divider for calculating Tuning Step */
>>> +    u8    tun_step_divider;
>>> +
>>> +    struct soc_pad_ctrl pad_ctrl;
>>> +};
>>> +
>>> +static void xenon_emmc_phy_strobe_delay_adj(struct sdhci_host *host,
>>> +                        struct mmc_card *card);
>>> +static int xenon_emmc_phy_fix_sampl_delay_adj(struct sdhci_host *host,
>>> +                          struct mmc_card *card);
>>> +static void xenon_emmc_phy_set(struct sdhci_host *host,
>>> +                   unsigned char timing);
>>> +static void xenon_emmc_set_soc_pad(struct sdhci_host *host,
>>> +                   unsigned char signal_voltage);
>>> +
>>> +static const struct xenon_phy_ops emmc_phy_ops = {
>>> +    .strobe_delay_adj = xenon_emmc_phy_strobe_delay_adj,
>>> +    .fix_sampl_delay_adj = xenon_emmc_phy_fix_sampl_delay_adj,
>>> +    .phy_set = xenon_emmc_phy_set,
>>> +    .set_soc_pad = xenon_emmc_set_soc_pad,
>>> +};
>>> +
>>> +static int alloc_emmc_phy(struct sdhci_xenon_priv *priv)
>>> +{
>>> +    struct emmc_phy_params *params;
>>> +
>>> +    params = kzalloc(sizeof(*params), GFP_KERNEL);
>>> +    if (!params)
>>> +        return -ENOMEM;
>>> +
>>> +    priv->phy_params = params;
>>> +    priv->phy_ops = &emmc_phy_ops;
>>> +    if (priv->phy_type == EMMC_5_0_PHY)
>>> +        priv->emmc_phy_regs = &xenon_emmc_5_0_phy_regs;
>>> +    else
>>> +        priv->emmc_phy_regs = &xenon_emmc_5_1_phy_regs;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int xenon_emmc_phy_init(struct sdhci_host *host)
>>> +{
>>> +    u32 reg;
>>> +    u32 wait, clock;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
>>> +
>>> +    reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +    reg |= PHY_INITIALIZAION;
>>> +    sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +
>>> +    /* Add duration of FC_SYNC_RST */
>>> +    wait = ((reg >> FC_SYNC_RST_DURATION_SHIFT) &
>>> +            FC_SYNC_RST_DURATION_MASK);
>>> +    /* Add interval between FC_SYNC_EN and FC_SYNC_RST */
>>> +    wait += ((reg >> FC_SYNC_RST_EN_DURATION_SHIFT) &
>>> +            FC_SYNC_RST_EN_DURATION_MASK);
>>> +    /* Add duration of asserting FC_SYNC_EN */
>>> +    wait += ((reg >> FC_SYNC_EN_DURATION_SHIFT) &
>>> +            FC_SYNC_EN_DURATION_MASK);
>>> +    /* Add duration of waiting for PHY */
>>> +    wait += ((reg >> WAIT_CYCLE_BEFORE_USING_SHIFT) &
>>> +            WAIT_CYCLE_BEFORE_USING_MASK);
>>> +    /* 4 addtional bus clock and 4 AXI bus clock are required */
>>> +    wait += 8;
>>> +    wait <<= 20;
>>> +
>>> +    clock = host->clock;
>>> +    if (!clock)
>>> +        /* Use the possibly slowest bus frequency value */
>>> +        clock = LOWEST_SDCLK_FREQ;
>>> +    /* get the wait time */
>>> +    wait /= clock;
>>> +    wait++;
>>> +    /* wait for host eMMC PHY init completes */
>>> +    udelay(wait);
>>> +
>>> +    reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +    reg &= PHY_INITIALIZAION;
>>> +    if (reg) {
>>> +        dev_err(mmc_dev(host->mmc), "eMMC PHY init cannot complete after %d us\n",
>>> +            wait);
>>> +        return -ETIMEDOUT;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +#define ARMADA_3700_SOC_PAD_1_8V    0x1
>>> +#define ARMADA_3700_SOC_PAD_3_3V    0x0
>>> +
>>> +static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host,
>>> +                        unsigned char signal_voltage)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct emmc_phy_params *params = priv->phy_params;
>>> +
>>> +    if (params->pad_ctrl.pad_type == SOC_PAD_FIXED_1_8V) {
>>> +        writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg);
>>> +    } else if (params->pad_ctrl.pad_type == SOC_PAD_SD) {
>>> +        if (signal_voltage == MMC_SIGNAL_VOLTAGE_180)
>>> +            writel(ARMADA_3700_SOC_PAD_1_8V, params->pad_ctrl.reg);
>>> +        else if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
>>> +            writel(ARMADA_3700_SOC_PAD_3_3V, params->pad_ctrl.reg);
>>> +    }
>>> +}
>>> +
>>> +static void xenon_emmc_set_soc_pad(struct sdhci_host *host,
>>> +                   unsigned char signal_voltage)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct emmc_phy_params *params = priv->phy_params;
>>> +
>>> +    if (!params->pad_ctrl.reg)
>>> +        return;
>>> +
>>> +    if (params->pad_ctrl.set_soc_pad)
>>> +        params->pad_ctrl.set_soc_pad(host, signal_voltage);
>>> +}
>>> +
>>> +static int emmc_phy_set_fix_sampl_delay(struct sdhci_host *host,
>>> +                    unsigned int delay,
>>> +                    bool invert,
>>> +                    bool delay_90_degree)
>>> +{
>>> +    u32 reg;
>>> +    unsigned long flags;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
>>> +    int ret = 0;
>>> +
>>> +    spin_lock_irqsave(&host->lock, flags);
>>> +
>>> +    /* Setup Sampling fix delay */
>>> +    reg = sdhci_readl(host, SDHC_SLOT_OP_STATUS_CTRL);
>>> +    reg &= ~phy_regs->delay_mask;
>>> +    reg |= delay & phy_regs->delay_mask;
>>> +    sdhci_writel(host, reg, SDHC_SLOT_OP_STATUS_CTRL);
>>> +
>>> +    if (priv->phy_type == EMMC_5_0_PHY) {
>>> +        /* set 90 degree phase if necessary */
>>> +        reg &= ~DELAY_90_DEGREE_MASK_EMMC5;
>>> +        reg |= (delay_90_degree << DELAY_90_DEGREE_SHIFT_EMMC5);
>>> +        sdhci_writel(host, reg, SDHC_SLOT_OP_STATUS_CTRL);
>>> +    }
>>> +
>>> +    /* Disable SDCLK */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
>>> +    sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    udelay(200);
>>> +
>>> +    if (priv->phy_type == EMMC_5_1_PHY) {
>>> +        /* set 90 degree phase if necessary */
>>> +        reg = sdhci_readl(host, EMMC_PHY_FUNC_CONTROL);
>>> +        reg &= ~ASYNC_DDRMODE_MASK;
>>> +        reg |= (delay_90_degree << ASYNC_DDRMODE_SHIFT);
>>> +        sdhci_writel(host, reg, EMMC_PHY_FUNC_CONTROL);
>>> +    }
>>> +
>>> +    /* Setup Inversion of Sampling edge */
>>> +    reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +    reg &= ~SAMPL_INV_QSP_PHASE_SELECT;
>>> +    reg |= (invert << SAMPL_INV_QSP_PHASE_SELECT_SHIFT);
>>> +    sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +
>>> +    /* Enable SD internal clock */
>>> +    ret = enable_xenon_internal_clk(host);
>>> +    if (ret)
>>> +        goto out;
>>> +
>>> +    /* Enable SDCLK */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg |= SDHCI_CLOCK_CARD_EN;
>>> +    sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    udelay(200);
>>> +
>>> +    /*
>>> +     * Has to re-initialize eMMC PHY here to active PHY
>>> +     * because later get status cmd will be issued.
>>> +     */
>>> +    ret = xenon_emmc_phy_init(host);
>>> +
>>> +out:
>>> +    spin_unlock_irqrestore(&host->lock, flags);
>>> +    return ret;
>>> +}
>>> +
>>> +static int emmc_phy_do_fix_sampl_delay(struct sdhci_host *host,
>>> +                       struct mmc_card *card,
>>> +                       unsigned int delay,
>>> +                       bool invert, bool quarter)
>>> +{
>>> +    int ret;
>>> +
>>> +    emmc_phy_set_fix_sampl_delay(host, delay, invert, quarter);
>>> +
>>> +    ret = xenon_delay_adj_test(card);
>>> +    if (ret) {
>>> +        dev_dbg(mmc_dev(host->mmc),
>>> +            "fail when sampling fix delay = %d, phase = %d degree\n",
>>> +            delay, invert * 180 + quarter * 90);
>>> +        return -1;
>>> +    }
>>> +    return 0;
>>> +}
>>> +
>>> +static int xenon_emmc_phy_fix_sampl_delay_adj(struct sdhci_host *host,
>>> +                          struct mmc_card *card)
>>> +{
>>> +    enum sampl_fix_delay_phase phase;
>>> +    int idx, nr_pair;
>>> +    int ret;
>>> +    unsigned int delay;
>>> +    unsigned int min_delay, max_delay;
>>> +    bool invert, quarter;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
>>> +    u32 coarse_step, fine_step;
>>> +    const enum sampl_fix_delay_phase delay_edge[] = {
>>> +        PHASE_0_DEGREE,
>>> +        PHASE_180_DEGREE,
>>> +        PHASE_90_DEGREE,
>>> +        PHASE_270_DEGREE
>>> +    };
>>> +
>>> +    coarse_step = phy_regs->delay_mask >> 1;
>>> +    fine_step = coarse_step >> 2;
>>> +
>>> +    nr_pair = ARRAY_SIZE(delay_edge);
>>> +
>>> +    for (idx = 0; idx < nr_pair; idx++) {
>>> +        phase = delay_edge[idx];
>>> +        invert = (phase & 0x2) ? true : false;
>>> +        quarter = (phase & 0x1) ? true : false;
>>> +
>>> +        /* increase delay value to get fix delay */
>>> +        for (min_delay = 0;
>>> +             min_delay <= phy_regs->delay_mask;
>>> +             min_delay += coarse_step) {
>>> +            ret = emmc_phy_do_fix_sampl_delay(host, card, min_delay,
>>> +                              invert, quarter);
>>> +            if (!ret)
>>> +                break;
>>> +        }
>>> +
>>> +        if (ret) {
>>> +            dev_dbg(mmc_dev(host->mmc),
>>> +                "Fail to set Sampling Fixed Delay with phase = %d degree\n",
>>> +                phase * 90);
>>> +            continue;
>>> +        }
>>> +
>>> +        for (max_delay = min_delay + fine_step;
>>> +             max_delay < phy_regs->delay_mask;
>>> +             max_delay += fine_step) {
>>> +            ret = emmc_phy_do_fix_sampl_delay(host, card, max_delay,
>>> +                              invert, quarter);
>>> +            if (ret) {
>>> +                max_delay -= fine_step;
>>> +                break;
>>> +            }
>>> +        }
>>> +
>>> +        if (!ret) {
>>> +            ret = emmc_phy_do_fix_sampl_delay(host, card,
>>> +                              phy_regs->delay_mask,
>>> +                              invert, quarter);
>>> +            if (!ret)
>>> +                max_delay = phy_regs->delay_mask;
>>> +        }
>>> +
>>> +        /*
>>> +         * Sampling Fixed Delay line window should be large enough,
>>> +         * thus the sampling point (the middle of the window)
>>> +         * can work when environment varies.
>>> +         * However, there is no clear conclusion how large the window
>>> +         * should be.
>>> +         */
>>> +        if ((max_delay - min_delay) <=
>>> +            EMMC_PHY_FIXED_DELAY_WINDOW_MIN) {
>>> +            dev_info(mmc_dev(host->mmc),
>>> +                 "The window size %d with phase = %d degree is too small\n",
>>> +                 max_delay - min_delay, phase * 90);
>>> +            continue;
>>> +        }
>>> +
>>> +        delay = (min_delay + max_delay) / 2;
>>> +        emmc_phy_set_fix_sampl_delay(host, delay, invert, quarter);
>>> +        dev_dbg(mmc_dev(host->mmc),
>>> +            "sampling fix delay = %d with phase = %d degree\n",
>>> +            delay, phase * 90);
>>> +        return 0;
>>> +    }
>>> +
>>> +    return -EIO;
>>> +}
>>> +
>>> +static int xenon_emmc_phy_enable_dll(struct sdhci_host *host)
>>> +{
>>> +    u32 reg;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
>>> +    u8 timeout;
>>> +
>>> +    if (WARN_ON(host->clock <= MMC_HIGH_52_MAX_DTR))
>>> +        return -EINVAL;
>>> +
>>> +    reg = sdhci_readl(host, phy_regs->dll_ctrl);
>>> +    if (reg & DLL_ENABLE)
>>> +        return 0;
>>> +
>>> +    /* Enable DLL */
>>> +    reg = sdhci_readl(host, phy_regs->dll_ctrl);
>>> +    reg |= (DLL_ENABLE | DLL_FAST_LOCK);
>>> +
>>> +    /*
>>> +     * Set Phase as 90 degree, which is most common value.
>>> +     * Might set another value if necessary.
>>> +     * The granularity is 1 degree.
>>> +     */
>>> +    reg &= ~((DLL_PHASE_MASK << DLL_PHSEL0_SHIFT) |
>>> +            (DLL_PHASE_MASK << DLL_PHSEL1_SHIFT));
>>> +    reg |= ((DLL_PHASE_90_DEGREE << DLL_PHSEL0_SHIFT) |
>>> +            (DLL_PHASE_90_DEGREE << DLL_PHSEL1_SHIFT));
>>> +
>>> +    reg &= ~DLL_BYPASS_EN;
>>> +    reg |= phy_regs->dll_update;
>>> +    if (priv->phy_type == EMMC_5_1_PHY)
>>> +        reg &= ~DLL_REFCLK_SEL;
>>> +    sdhci_writel(host, reg, phy_regs->dll_ctrl);
>>> +
>>> +    /* Wait max 32 ms */
>>> +    timeout = 32;
>>> +    while (!(sdhci_readw(host, SDHC_SLOT_EXT_PRESENT_STATE) & LOCK_STATE)) {
>>> +        if (!timeout) {
>>> +            dev_err(mmc_dev(host->mmc), "Wait for DLL Lock time-out\n");
>>> +            return -ETIMEDOUT;
>>> +        }
>>> +        timeout--;
>>> +        mdelay(1);
>>> +    }
>>> +    return 0;
>>> +}
>>> +
>>> +static int __emmc_phy_config_tuning(struct sdhci_host *host)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct emmc_phy_params *params = priv->phy_params;
>>> +    u32 reg, tuning_step;
>>> +    int ret;
>>> +    unsigned long flags;
>>> +
>>> +    if (WARN_ON(host->clock <= MMC_HIGH_52_MAX_DTR))
>>> +        return -EINVAL;
>>> +
>>> +    spin_lock_irqsave(&host->lock, flags);
>>> +
>>> +    ret = xenon_emmc_phy_enable_dll(host);
>>> +    if (ret) {
>>> +        spin_unlock_irqrestore(&host->lock, flags);
>>> +        return ret;
>>> +    }
>>> +
>>> +    reg = sdhci_readl(host, SDHC_SLOT_DLL_CUR_DLY_VAL);
>>> +    tuning_step = reg / params->tun_step_divider;
>>> +    if (unlikely(tuning_step > TUNING_STEP_MASK)) {
>>> +        dev_warn(mmc_dev(host->mmc),
>>> +             "HS200 TUNING_STEP %d is larger than MAX value\n",
>>> +             tuning_step);
>>> +        tuning_step = TUNING_STEP_MASK;
>>> +    }
>>> +
>>> +    reg = sdhci_readl(host, SDHC_SLOT_OP_STATUS_CTRL);
>>> +    reg &= ~(TUN_CONSECUTIVE_TIMES_MASK << TUN_CONSECUTIVE_TIMES_SHIFT);
>>> +    reg |= (params->nr_tun_times << TUN_CONSECUTIVE_TIMES_SHIFT);
>>> +    reg &= ~(TUNING_STEP_MASK << TUNING_STEP_SHIFT);
>>> +    reg |= (tuning_step << TUNING_STEP_SHIFT);
>>> +    sdhci_writel(host, reg, SDHC_SLOT_OP_STATUS_CTRL);
>>> +
>>> +    spin_unlock_irqrestore(&host->lock, flags);
>>> +    return 0;
>>> +}
>>> +
>>> +static int xenon_emmc_phy_config_tuning(struct sdhci_host *host)
>>> +{
>>> +    return __emmc_phy_config_tuning(host);
>>> +}
>>> +
>>> +static void xenon_emmc_phy_strobe_delay_adj(struct sdhci_host *host,
>>> +                        struct mmc_card *card)
>>> +{
>>> +    u32 reg;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    unsigned long flags;
>>> +
>>> +    if (host->clock <= MMC_HIGH_52_MAX_DTR)
>>> +        return;
>>> +
>>> +    dev_dbg(mmc_dev(host->mmc), "starts HS400 strobe delay adjustment\n");
>>> +
>>> +    spin_lock_irqsave(&host->lock, flags);
>>> +
>>> +    xenon_emmc_phy_enable_dll(host);
>>> +
>>> +    /* Enable SDHC Data Strobe */
>>> +    reg = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL);
>>> +    reg |= ENABLE_DATA_STROBE;
>>> +    sdhci_writel(host, reg, SDHC_SLOT_EMMC_CTRL);
>>> +
>>> +    /* Set Data Strobe Pull down */
>>> +    if (priv->phy_type == EMMC_5_0_PHY) {
>>> +        reg = sdhci_readl(host, EMMC_5_0_PHY_PAD_CONTROL);
>>> +        reg |= EMMC5_FC_QSP_PD;
>>> +        reg &= ~EMMC5_FC_QSP_PU;
>>> +        sdhci_writel(host, reg, EMMC_5_0_PHY_PAD_CONTROL);
>>> +    } else {
>>> +        reg = sdhci_readl(host, EMMC_PHY_PAD_CONTROL1);
>>> +        reg |= EMMC5_1_FC_QSP_PD;
>>> +        reg &= ~EMMC5_1_FC_QSP_PU;
>>> +        sdhci_writel(host, reg, EMMC_PHY_PAD_CONTROL1);
>>> +    }
>>> +    spin_unlock_irqrestore(&host->lock, flags);
>>> +}
>>> +
>>> +#define LOGIC_TIMING_VALUE    0x00AA8977
>>> +
>>> +static void xenon_emmc_phy_set(struct sdhci_host *host,
>>> +                   unsigned char timing)
>>> +{
>>> +    u32 reg;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    struct emmc_phy_params *params = priv->phy_params;
>>> +    struct xenon_emmc_phy_regs *phy_regs = priv->emmc_phy_regs;
>>> +    struct mmc_card *card = priv->card_candidate;
>>> +    unsigned long flags;
>>> +
>>> +    dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting starts\n");
>>> +
>>> +    spin_lock_irqsave(&host->lock, flags);
>>> +
>>> +    /* Setup pad, set bit[28] and bits[26:24] */
>>> +    reg = sdhci_readl(host, phy_regs->pad_ctrl);
>>> +    reg |= (FC_DQ_RECEN | FC_CMD_RECEN | FC_QSP_RECEN | OEN_QSN);
>>> +    /*
>>> +     * All FC_XX_RECEIVCE should be set as CMOS Type
>>> +     */
>>> +    reg |= FC_ALL_CMOS_RECEIVER;
>>> +    sdhci_writel(host, reg, phy_regs->pad_ctrl);
>>> +
>>> +    /* Set CMD and DQ Pull Up */
>>> +    if (priv->phy_type == EMMC_5_0_PHY) {
>>> +        reg = sdhci_readl(host, EMMC_5_0_PHY_PAD_CONTROL);
>>> +        reg |= (EMMC5_FC_CMD_PU | EMMC5_FC_DQ_PU);
>>> +        reg &= ~(EMMC5_FC_CMD_PD | EMMC5_FC_DQ_PD);
>>> +        sdhci_writel(host, reg, EMMC_5_0_PHY_PAD_CONTROL);
>>> +    } else {
>>> +        reg = sdhci_readl(host, EMMC_PHY_PAD_CONTROL1);
>>> +        reg |= (EMMC5_1_FC_CMD_PU | EMMC5_1_FC_DQ_PU);
>>> +        reg &= ~(EMMC5_1_FC_CMD_PD | EMMC5_1_FC_DQ_PD);
>>> +        sdhci_writel(host, reg, EMMC_PHY_PAD_CONTROL1);
>>> +    }
>>> +
>>> +    if ((timing == MMC_TIMING_LEGACY) || !card)
>>> +        goto phy_init;
>>> +
>>> +    /*
>>> +     * FIXME: should depends on the specific board timing.
>>> +     */
>>> +    if ((timing == MMC_TIMING_MMC_HS400) ||
>>> +        (timing == MMC_TIMING_MMC_HS200) ||
>>> +        (timing == MMC_TIMING_UHS_SDR50) ||
>>> +        (timing == MMC_TIMING_UHS_SDR104) ||
>>> +        (timing == MMC_TIMING_UHS_DDR50) ||
>>> +        (timing == MMC_TIMING_UHS_SDR25) ||
>>> +        (timing == MMC_TIMING_MMC_DDR52)) {
>>> +        reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +        reg &= ~OUTPUT_QSN_PHASE_SELECT;
>>> +        sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +    }
>>> +
>>> +    /*
>>> +     * If SDIO card, set SDIO Mode
>>> +     * Otherwise, clear SDIO Mode and Slow Mode
>>> +     */
>>> +    if (mmc_card_sdio(card)) {
>>> +        reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +        reg |= TIMING_ADJUST_SDIO_MODE;
>>> +
>>> +        if ((timing == MMC_TIMING_UHS_SDR25) ||
>>> +            (timing == MMC_TIMING_UHS_SDR12) ||
>>> +            (timing == MMC_TIMING_SD_HS) ||
>>> +            (timing == MMC_TIMING_LEGACY))
>>> +            reg |= TIMING_ADJUST_SLOW_MODE;
>>> +
>>> +        sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +    } else {
>>> +        reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +        reg &= ~(TIMING_ADJUST_SDIO_MODE | TIMING_ADJUST_SLOW_MODE);
>>> +        sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +    }
>>> +
>>> +    if (((timing == MMC_TIMING_UHS_SDR50) ||
>>> +         (timing == MMC_TIMING_UHS_SDR25) ||
>>> +         (timing == MMC_TIMING_UHS_SDR12) ||
>>> +         (timing == MMC_TIMING_SD_HS) ||
>>> +         (timing == MMC_TIMING_MMC_HS) ||
>>> +         (timing == MMC_TIMING_LEGACY)) && params->slow_mode) {
>>> +        reg = sdhci_readl(host, phy_regs->timing_adj);
>>> +        reg |= TIMING_ADJUST_SLOW_MODE;
>>> +        sdhci_writel(host, reg, phy_regs->timing_adj);
>>> +    }
>>> +
>>> +    /*
>>> +     * Set preferred ZNR and ZPR value
>>> +     * The ZNR and ZPR value vary between different boards.
>>> +     * Define them both in sdhci-xenon-emmc-phy.h.
>>> +     */
>>> +    reg = sdhci_readl(host, phy_regs->pad_ctrl2);
>>> +    reg &= ~((ZNR_MASK << ZNR_SHIFT) | ZPR_MASK);
>>> +    reg |= ((params->znr << ZNR_SHIFT) | params->zpr);
>>> +    sdhci_writel(host, reg, phy_regs->pad_ctrl2);
>>> +
>>> +    /*
>>> +     * When setting EMMC_PHY_FUNC_CONTROL register,
>>> +     * SD clock should be disabled
>>> +     */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg &= ~SDHCI_CLOCK_CARD_EN;
>>> +    sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    if ((timing == MMC_TIMING_UHS_DDR50) ||
>>> +        (timing == MMC_TIMING_MMC_HS400) ||
>>> +        (timing == MMC_TIMING_MMC_DDR52)) {
>>> +        reg = sdhci_readl(host, phy_regs->func_ctrl);
>>> +        reg |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
>>> +        sdhci_writel(host, reg, phy_regs->func_ctrl);
>>> +    }
>>> +
>>> +    if (timing == MMC_TIMING_MMC_HS400) {
>>> +        reg = sdhci_readl(host, phy_regs->func_ctrl);
>>> +        reg &= ~DQ_ASYNC_MODE;
>>> +        sdhci_writel(host, reg, phy_regs->func_ctrl);
>>> +    }
>>> +
>>> +    /* Enable bus clock */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg |= SDHCI_CLOCK_CARD_EN;
>>> +    sdhci_writew(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    if (timing == MMC_TIMING_MMC_HS400)
>>> +        /* Hardware team recommend a value for HS400 */
>>> +        sdhci_writel(host, LOGIC_TIMING_VALUE,
>>> +                 phy_regs->logic_timing_adj);
>>> +
>>> +phy_init:
>>> +    xenon_emmc_phy_init(host);
>>> +
>>> +    spin_unlock_irqrestore(&host->lock, flags);
>>> +
>>> +    dev_dbg(mmc_dev(host->mmc), "eMMC PHY setting completes\n");
>>> +}
>>> +
>>> +static int get_dt_pad_ctrl_data(struct sdhci_host *host,
>>> +                struct device_node *np,
>>> +                struct emmc_phy_params *params)
>>> +{
>>> +    int ret = 0;
>>> +    const char *name;
>>> +    struct resource iomem;
>>> +
>>> +    if (of_device_is_compatible(np, "marvell,armada-3700-sdhci"))
>>> +        params->pad_ctrl.set_soc_pad = armada_3700_soc_pad_voltage_set;
>>> +    else
>>> +        return 0;
>>> +
>>> +    if (of_address_to_resource(np, 1, &iomem)) {
>>> +        dev_err(mmc_dev(host->mmc), "Unable to find SOC PAD ctrl register address for %s\n",
>>> +            np->name);
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    params->pad_ctrl.reg = devm_ioremap_resource(mmc_dev(host->mmc),
>>> +                             &iomem);
>>> +    if (IS_ERR(params->pad_ctrl.reg)) {
>>> +        dev_err(mmc_dev(host->mmc), "Unable to get SOC PHY PAD ctrl regiser for %s\n",
>>> +            np->name);
>>> +        return PTR_ERR(params->pad_ctrl.reg);
>>> +    }
>>> +
>>> +    ret = of_property_read_string(np, "xenon,pad-type", &name);
>>> +    if (ret) {
>>> +        dev_err(mmc_dev(host->mmc), "Unable to determine SOC PHY PAD ctrl type\n");
>>> +        return ret;
>>> +    }
>>> +    if (!strcmp(name, "sd")) {
>>> +        params->pad_ctrl.pad_type = SOC_PAD_SD;
>>> +    } else if (!strcmp(name, "fixed-1-8v")) {
>>> +        params->pad_ctrl.pad_type = SOC_PAD_FIXED_1_8V;
>>> +    } else {
>>> +        dev_err(mmc_dev(host->mmc), "Unsupported SOC PHY PAD ctrl type %s\n",
>>> +            name);
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static int emmc_phy_parse_param_dt(struct sdhci_host *host,
>>> +                   struct device_node *np,
>>> +                   struct emmc_phy_params *params)
>>> +{
>>> +    u32 value;
>>> +
>>> +    if (of_property_read_bool(np, "xenon,phy-slow-mode"))
>>> +        params->slow_mode = true;
>>> +    else
>>> +        params->slow_mode = false;
>>> +
>>> +    if (!of_property_read_u32(np, "xenon,phy-znr", &value))
>>> +        params->znr = value & ZNR_MASK;
>>> +    else
>>> +        params->znr = ZNR_DEF_VALUE;
>>> +
>>> +    if (!of_property_read_u32(np, "xenon,phy-zpr", &value))
>>> +        params->zpr = value & ZPR_MASK;
>>> +    else
>>> +        params->zpr = ZPR_DEF_VALUE;
>>> +
>>> +    if (!of_property_read_u32(np, "xenon,phy-nr-tun-times", &value))
>>> +        params->nr_tun_times = value & TUN_CONSECUTIVE_TIMES_MASK;
>>> +    else
>>> +        params->nr_tun_times = TUN_CONSECUTIVE_TIMES;
>>> +
>>> +    if (!of_property_read_u32(np, "xenon,phy-tun-step-divider", &value))
>>> +        params->tun_step_divider = value & 0xFF;
>>> +    else
>>> +        params->tun_step_divider = TUNING_STEP_DIVIDER;
>>> +
>>> +    return get_dt_pad_ctrl_data(host, np, params);
>>> +}
>>> +
>>> +/*
>>> + * SDH PHY configuration and operations
>>> + */
>>> +static int xenon_sdh_phy_set_fix_sampl_delay(struct sdhci_host *host,
>>> +                         unsigned int delay, bool invert)
>>> +{
>>> +    u32 reg;
>>> +    unsigned long flags;
>>> +    int ret;
>>> +
>>> +    if (invert)
>>> +        invert = 0x1;
>>> +    else
>>> +        invert = 0x0;
>>> +
>>> +    spin_lock_irqsave(&host->lock, flags);
>>> +
>>> +    /* Disable SDCLK */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
>>> +    sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    udelay(200);
>>> +
>>> +    /* Setup Sampling fix delay */
>>> +    reg = sdhci_readl(host, SDHC_SLOT_OP_STATUS_CTRL);
>>> +    reg &= ~(SDH_PHY_FIXED_DELAY_MASK |
>>> +            (0x1 << FORCE_SEL_INVERSE_CLK_SHIFT));
>>> +    reg |= ((delay & SDH_PHY_FIXED_DELAY_MASK) |
>>> +            (invert << FORCE_SEL_INVERSE_CLK_SHIFT));
>>> +    sdhci_writel(host, reg, SDHC_SLOT_OP_STATUS_CTRL);
>>> +
>>> +    /* Enable SD internal clock */
>>> +    ret = enable_xenon_internal_clk(host);
>>> +
>>> +    /* Enable SDCLK */
>>> +    reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
>>> +    reg |= SDHCI_CLOCK_CARD_EN;
>>> +    sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
>>> +
>>> +    udelay(200);
>>> +
>>> +    spin_unlock_irqrestore(&host->lock, flags);
>>> +    return ret;
>>> +}
>>> +
>>> +static int sdh_phy_do_fix_sampl_delay(struct sdhci_host *host,
>>> +                      struct mmc_card *card,
>>> +                      unsigned int delay, bool invert)
>>> +{
>>> +    int ret;
>>> +
>>> +    xenon_sdh_phy_set_fix_sampl_delay(host, delay, invert);
>>> +
>>> +    ret = xenon_delay_adj_test(card);
>>> +    if (ret) {
>>> +        dev_dbg(mmc_dev(host->mmc),
>>> +            "fail when sampling fix delay = %d, phase = %d degree\n",
>>> +            delay, invert * 180);
>>> +        return -1;
>>> +    }
>>> +    return 0;
>>> +}
>>> +
>>> +#define SDH_PHY_COARSE_FIX_DELAY    (SDH_PHY_FIXED_DELAY_MASK / 2)
>>> +#define SDH_PHY_FINE_FIX_DELAY        (SDH_PHY_COARSE_FIX_DELAY / 4)
>>> +
>>> +static int xenon_sdh_phy_fix_sampl_delay_adj(struct sdhci_host *host,
>>> +                         struct mmc_card *card)
>>> +{
>>> +    u32 reg;
>>> +    bool dll_enable = false;
>>> +    unsigned int min_delay, max_delay, delay;
>>> +    const bool sampl_edge[] = {
>>> +        false,
>>> +        true,
>>> +    };
>>> +    int i, nr;
>>> +    int ret;
>>> +
>>> +    if (host->clock > HIGH_SPEED_MAX_DTR) {
>>> +        /* Enable DLL when SDCLK is higher than 50MHz */
>>> +        reg = sdhci_readl(host, SDH_PHY_SLOT_DLL_CTRL);
>>> +        if (!(reg & SDH_PHY_ENABLE_DLL)) {
>>> +            reg |= (SDH_PHY_ENABLE_DLL | SDH_PHY_FAST_LOCK_EN);
>>> +            sdhci_writel(host, reg, SDH_PHY_SLOT_DLL_CTRL);
>>> +            mdelay(1);
>>> +
>>> +            reg = sdhci_readl(host, SDH_PHY_SLOT_DLL_PHASE_SEL);
>>> +            reg |= SDH_PHY_DLL_UPDATE_TUNING;
>>> +            sdhci_writel(host, reg, SDH_PHY_SLOT_DLL_PHASE_SEL);
>>> +        }
>>> +        dll_enable = true;
>>> +    }
>>> +
>>> +    nr = dll_enable ? ARRAY_SIZE(sampl_edge) : 1;
>>> +    for (i = 0; i < nr; i++) {
>>> +        for (min_delay = 0; min_delay <= SDH_PHY_FIXED_DELAY_MASK;
>>> +                min_delay += SDH_PHY_COARSE_FIX_DELAY) {
>>> +            ret = sdh_phy_do_fix_sampl_delay(host, card, min_delay,
>>> +                             sampl_edge[i]);
>>> +            if (!ret)
>>> +                break;
>>> +        }
>>> +
>>> +        if (ret) {
>>> +            dev_dbg(mmc_dev(host->mmc),
>>> +                "Fail to set Fixed Sampling Delay with %s edge\n",
>>> +                sampl_edge[i] ? "negative" : "positive");
>>> +            continue;
>>> +        }
>>> +
>>> +        for (max_delay = min_delay + SDH_PHY_FINE_FIX_DELAY;
>>> +                max_delay < SDH_PHY_FIXED_DELAY_MASK;
>>> +                max_delay += SDH_PHY_FINE_FIX_DELAY) {
>>> +            ret = sdh_phy_do_fix_sampl_delay(host, card, max_delay,
>>> +                             sampl_edge[i]);
>>> +            if (ret) {
>>> +                max_delay -= SDH_PHY_FINE_FIX_DELAY;
>>> +                break;
>>> +            }
>>> +        }
>>> +
>>> +        if (!ret) {
>>> +            delay = SDH_PHY_FIXED_DELAY_MASK;
>>> +            ret = sdh_phy_do_fix_sampl_delay(host, card, delay,
>>> +                             sampl_edge[i]);
>>> +            if (!ret)
>>> +                max_delay = SDH_PHY_FIXED_DELAY_MASK;
>>> +        }
>>> +
>>> +        if ((max_delay - min_delay) <= SDH_PHY_FIXED_DELAY_WINDOW_MIN) {
>>> +            dev_info(mmc_dev(host->mmc),
>>> +                 "The window size %d with %s edge is too small\n",
>>> +                 max_delay - min_delay,
>>> +                 sampl_edge[i] ? "negative" : "positive");
>>> +            continue;
>>> +        }
>>> +
>>> +        delay = (min_delay + max_delay) / 2;
>>> +        xenon_sdh_phy_set_fix_sampl_delay(host, delay, sampl_edge[i]);
>>> +        dev_dbg(mmc_dev(host->mmc), "sampling fix delay = %d with %s edge\n",
>>> +            delay, sampl_edge[i] ? "negative" : "positive");
>>> +        return 0;
>>> +    }
>>> +    return -EIO;
>>> +}
>>> +
>>> +static const struct xenon_phy_ops sdh_phy_ops = {
>>> +    .fix_sampl_delay_adj = xenon_sdh_phy_fix_sampl_delay_adj,
>>> +};
>>> +
>>> +static int alloc_sdh_phy(struct sdhci_xenon_priv *priv)
>>> +{
>>> +    priv->phy_params = NULL;
>>> +    priv->phy_ops = &sdh_phy_ops;
>>> +    return 0;
>>> +}
>>> +
>>> +/*
>>> + * Common functions for all PHYs
>>> + */
>>> +void xenon_soc_pad_ctrl(struct sdhci_host *host,
>>> +            unsigned char signal_voltage)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> +    if (priv->phy_ops->set_soc_pad)
>>> +        priv->phy_ops->set_soc_pad(host, signal_voltage);
>>> +}
>>> +
>>> +static int __xenon_emmc_delay_adj_test(struct mmc_card *card)
>>> +{
>>> +    int err;
>>> +    u8 *ext_csd = NULL;
>>> +
>>> +    err = mmc_get_ext_csd(card, &ext_csd);
>>> +    kfree(ext_csd);
>>> +
>>> +    return err;
>>> +}
>>> +
>>> +static int __xenon_sdio_delay_adj_test(struct mmc_card *card)
>>> +{
>>> +    struct mmc_command cmd = {0};
>>> +    int err;
>>> +
>>> +    cmd.opcode = SD_IO_RW_DIRECT;
>>> +    cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
>>> +
>>> +    err = mmc_wait_for_cmd(card->host, &cmd, 0);
>>> +    if (err)
>>> +        return err;
>>> +
>>> +    if (cmd.resp[0] & R5_ERROR)
>>> +        return -EIO;
>>> +    if (cmd.resp[0] & R5_FUNCTION_NUMBER)
>>> +        return -EINVAL;
>>> +    if (cmd.resp[0] & R5_OUT_OF_RANGE)
>>> +        return -ERANGE;
>>> +    return 0;
>>> +}
>>> +
>>> +static int __xenon_sd_delay_adj_test(struct mmc_card *card)
>>> +{
>>> +    struct mmc_command cmd = {0};
>>> +    int err;
>>> +
>>> +    cmd.opcode = MMC_SEND_STATUS;
>>> +    cmd.arg = card->rca << 16;
>>> +    cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
>>> +
>>> +    err = mmc_wait_for_cmd(card->host, &cmd, 0);
>>> +    return err;
>>> +}
>>> +
>>> +static int xenon_delay_adj_test(struct mmc_card *card)
>>> +{
>>> +    WARN_ON(!card);
>>> +    WARN_ON(!card->host);
>>> +
>>> +    if (mmc_card_mmc(card))
>>> +        return __xenon_emmc_delay_adj_test(card);
>>> +    else if (mmc_card_sd(card))
>>> +        return __xenon_sd_delay_adj_test(card);
>>> +    else if (mmc_card_sdio(card))
>>> +        return __xenon_sdio_delay_adj_test(card);
>>> +    else
>>> +        return -EINVAL;
>>> +}
>>> +
>>> +static void xenon_phy_set(struct sdhci_host *host, unsigned char timing)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> +    if (priv->phy_ops->phy_set)
>>> +        priv->phy_ops->phy_set(host, timing);
>>> +}
>>> +
>>> +static void xenon_hs400_strobe_delay_adj(struct sdhci_host *host,
>>> +                     struct mmc_card *card)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> +    if (WARN_ON(!mmc_card_hs400(card)))
>>> +        return;
>>> +
>>> +    /* Enable the DLL to automatically adjust HS400 strobe delay.
>>> +     */
>>> +    if (priv->phy_ops->strobe_delay_adj)
>>> +        priv->phy_ops->strobe_delay_adj(host, card);
>>> +}
>>> +
>>> +static int xenon_fix_sampl_delay_adj(struct sdhci_host *host,
>>> +                     struct mmc_card *card)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> +    if (priv->phy_ops->fix_sampl_delay_adj)
>>> +        return priv->phy_ops->fix_sampl_delay_adj(host, card);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +/*
>>> + * xenon_delay_adj should not be called inside IRQ context,
>>> + * either Hard IRQ or Softirq.
>>> + */
>>> +static int xenon_hs_delay_adj(struct sdhci_host *host,
>>> +                  struct mmc_card *card)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    int ret = 0;
>>> +
>>> +    if (WARN_ON(host->clock <= DEFAULT_SDCLK_FREQ))
>>> +        return -EINVAL;
>>> +
>>> +    if (mmc_card_hs400(card)) {
>>> +        xenon_hs400_strobe_delay_adj(host, card);
>>> +        return 0;
>>> +    }
>>> +
>>> +    if (((priv->phy_type == EMMC_5_1_PHY) ||
>>> +         (priv->phy_type == EMMC_5_0_PHY)) &&
>>> +         (mmc_card_hs200(card) ||
>>> +         (host->timing == MMC_TIMING_UHS_SDR104))) {
>>> +        ret = xenon_emmc_phy_config_tuning(host);
>>> +        if (!ret)
>>> +            return 0;
>>> +    }
>>> +
>>> +    ret = xenon_fix_sampl_delay_adj(host, card);
>>> +    if (ret)
>>> +        dev_err(mmc_dev(host->mmc), "fails sampling fixed delay adjustment\n");
>>> +    return ret;
>>> +}
>>> +
>>> +int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios)
>>> +{
>>> +    struct mmc_host *mmc = host->mmc;
>>> +    struct mmc_card *card;
>>> +    int ret = 0;
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +
>>> +    if (!host->clock) {
>>> +        priv->clock = 0;
>>> +        return 0;
>>> +    }
>>> +
>>> +    /*
>>> +     * The timing, frequency or bus width is changed,
>>> +     * better to set eMMC PHY based on current setting
>>> +     * and adjust Xenon SDHC delay.
>>> +     */
>>> +    if ((host->clock == priv->clock) &&
>>> +        (ios->bus_width == priv->bus_width) &&
>>> +        (ios->timing == priv->timing))
>>> +        return 0;
>>> +
>>> +    xenon_phy_set(host, ios->timing);
>>> +
>>> +    /* Update the record */
>>> +    priv->bus_width = ios->bus_width;
>>> +    /* Temp stage from HS200 to HS400 */
>>> +    if (((priv->timing == MMC_TIMING_MMC_HS200) &&
>>> +         (ios->timing == MMC_TIMING_MMC_HS)) ||
>>> +        ((ios->timing == MMC_TIMING_MMC_HS) &&
>>> +         (priv->clock > host->clock))) {
>>> +        priv->timing = ios->timing;
>>> +        priv->clock = host->clock;
>>> +        return 0;
>>> +    }
>>> +    priv->timing = ios->timing;
>>> +    priv->clock = host->clock;
>>> +
>>> +    /* Legacy mode is a special case */
>>> +    if (ios->timing == MMC_TIMING_LEGACY)
>>> +        return 0;
>>> +
>>> +    card = priv->card_candidate;
>>> +    if (unlikely(!card)) {
>>> +        dev_warn(mmc_dev(mmc), "card is not present\n");
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    if (host->clock > DEFAULT_SDCLK_FREQ)
>>> +        ret = xenon_hs_delay_adj(host, card);
>>> +    return ret;
>>> +}
>>> +
>>> +static int add_xenon_phy(struct device_node *np, struct sdhci_host *host,
>>> +             const char *phy_name)
>>> +{
>>> +    struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>>> +    struct sdhci_xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
>>> +    int i, ret;
>>> +
>>> +    for (i = 0; i < NR_PHY_TYPES; i++) {
>>> +        if (!strcmp(phy_name, phy_types[i])) {
>>> +            priv->phy_type = i;
>>> +            break;
>>> +        }
>>> +    }
>>> +    if (i == NR_PHY_TYPES) {
>>> +        dev_err(mmc_dev(host->mmc),
>>> +            "Unable to determine PHY name %s. Use default eMMC 5.1 PHY\n",
>>> +            phy_name);
>>> +        priv->phy_type = EMMC_5_1_PHY;
>>> +    }
>>> +
>>> +    if (priv->phy_type == SDH_PHY) {
>>> +        return alloc_sdh_phy(priv);
>>> +    } else if ((priv->phy_type == EMMC_5_0_PHY) ||
>>> +            (priv->phy_type == EMMC_5_1_PHY)) {
>>> +        ret = alloc_emmc_phy(priv);
>>> +        if (ret)
>>> +            return ret;
>>> +        return emmc_phy_parse_param_dt(host, np, priv->phy_params);
>>> +    }
>>> +
>>> +    return -EINVAL;
>>> +}
>>> +
>>> +int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host)
>>> +{
>>> +    const char *phy_type = NULL;
>>> +
>>> +    if (!of_property_read_string(np, "xenon,phy-type", &phy_type))
>>> +        return add_xenon_phy(np, host, phy_type);
>>> +
>>> +    dev_err(mmc_dev(host->mmc), "Fail to get Xenon PHY type. Use default eMMC 5.1 PHY\n");
>>> +    return add_xenon_phy(np, host, "emmc 5.1 phy");
>>> +}
>>> diff --git a/drivers/mmc/host/sdhci-xenon-phy.h b/drivers/mmc/host/sdhci-xenon-phy.h
>>> new file mode 100644
>>> index 000000000000..4373c71d3b7b
>>> --- /dev/null
>>> +++ b/drivers/mmc/host/sdhci-xenon-phy.h
>>> @@ -0,0 +1,157 @@
>>> +/* linux/drivers/mmc/host/sdhci-xenon-phy.h
>>> + *
>>> + * Author:    Hu Ziji <huziji@marvell.com>
>>> + * Date:    2016-8-24
>>> + *
>>> + *  Copyright (C) 2016 Marvell, All Rights Reserved.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or (at
>>> + * your option) any later version.
>>> + */
>>> +#ifndef SDHCI_XENON_PHY_H_
>>> +#define SDHCI_XENON_PHY_H_
>>> +
>>> +#include <linux/types.h>
>>> +#include "sdhci.h"
>>> +
>>> +/* Register base for eMMC PHY 5.0 Version */
>>> +#define EMMC_5_0_PHY_REG_BASE            0x0160
>>> +/* Register base for eMMC PHY 5.1 Version */
>>> +#define EMMC_PHY_REG_BASE            0x0170
>>> +
>>> +#define EMMC_PHY_TIMING_ADJUST            EMMC_PHY_REG_BASE
>>> +#define EMMC_5_0_PHY_TIMING_ADJUST        EMMC_5_0_PHY_REG_BASE
>>> +#define TIMING_ADJUST_SLOW_MODE            BIT(29)
>>> +#define TIMING_ADJUST_SDIO_MODE            BIT(28)
>>> +#define OUTPUT_QSN_PHASE_SELECT            BIT(17)
>>> +#define SAMPL_INV_QSP_PHASE_SELECT        BIT(18)
>>> +#define SAMPL_INV_QSP_PHASE_SELECT_SHIFT    18
>>> +#define PHY_INITIALIZAION            BIT(31)
>>> +#define WAIT_CYCLE_BEFORE_USING_MASK        0xF
>>> +#define WAIT_CYCLE_BEFORE_USING_SHIFT        12
>>> +#define FC_SYNC_EN_DURATION_MASK        0xF
>>> +#define FC_SYNC_EN_DURATION_SHIFT        8
>>> +#define FC_SYNC_RST_EN_DURATION_MASK        0xF
>>> +#define FC_SYNC_RST_EN_DURATION_SHIFT        4
>>> +#define FC_SYNC_RST_DURATION_MASK        0xF
>>> +#define FC_SYNC_RST_DURATION_SHIFT        0
>>> +
>>> +#define EMMC_PHY_FUNC_CONTROL            (EMMC_PHY_REG_BASE + 0x4)
>>> +#define EMMC_5_0_PHY_FUNC_CONTROL        (EMMC_5_0_PHY_REG_BASE + 0x4)
>>> +#define ASYNC_DDRMODE_MASK            BIT(23)
>>> +#define ASYNC_DDRMODE_SHIFT            23
>>> +#define CMD_DDR_MODE                BIT(16)
>>> +#define DQ_DDR_MODE_SHIFT            8
>>> +#define DQ_DDR_MODE_MASK            0xFF
>>> +#define DQ_ASYNC_MODE                BIT(4)
>>> +
>>> +#define EMMC_PHY_PAD_CONTROL            (EMMC_PHY_REG_BASE + 0x8)
>>> +#define EMMC_5_0_PHY_PAD_CONTROL        (EMMC_5_0_PHY_REG_BASE + 0x8)
>>> +#define REC_EN_SHIFT                24
>>> +#define REC_EN_MASK                0xF
>>> +#define FC_DQ_RECEN                BIT(24)
>>> +#define FC_CMD_RECEN                BIT(25)
>>> +#define FC_QSP_RECEN                BIT(26)
>>> +#define FC_QSN_RECEN                BIT(27)
>>> +#define OEN_QSN                    BIT(28)
>>> +#define AUTO_RECEN_CTRL                BIT(30)
>>> +#define FC_ALL_CMOS_RECEIVER            0xF000
>>> +
>>> +#define EMMC5_FC_QSP_PD                BIT(18)
>>> +#define EMMC5_FC_QSP_PU                BIT(22)
>>> +#define EMMC5_FC_CMD_PD                BIT(17)
>>> +#define EMMC5_FC_CMD_PU                BIT(21)
>>> +#define EMMC5_FC_DQ_PD                BIT(16)
>>> +#define EMMC5_FC_DQ_PU                BIT(20)
>>> +
>>> +#define EMMC_PHY_PAD_CONTROL1            (EMMC_PHY_REG_BASE + 0xC)
>>> +#define EMMC5_1_FC_QSP_PD            BIT(9)
>>> +#define EMMC5_1_FC_QSP_PU            BIT(25)
>>> +#define EMMC5_1_FC_CMD_PD            BIT(8)
>>> +#define EMMC5_1_FC_CMD_PU            BIT(24)
>>> +#define EMMC5_1_FC_DQ_PD            0xFF
>>> +#define EMMC5_1_FC_DQ_PU            (0xFF << 16)
>>> +
>>> +#define EMMC_PHY_PAD_CONTROL2            (EMMC_PHY_REG_BASE + 0x10)
>>> +#define EMMC_5_0_PHY_PAD_CONTROL2        (EMMC_5_0_PHY_REG_BASE + 0xC)
>>> +#define ZNR_MASK                0x1F
>>> +#define ZNR_SHIFT                8
>>> +#define ZPR_MASK                0x1F
>>> +/* Perferred ZNR and ZPR value vary between different boards.
>>> + * The specific ZNR and ZPR value should be defined here
>>> + * according to board actual timing.
>>> + */
>>> +#define ZNR_DEF_VALUE                0xF
>>> +#define ZPR_DEF_VALUE                0xF
>>> +
>>> +#define EMMC_PHY_DLL_CONTROL            (EMMC_PHY_REG_BASE + 0x14)
>>> +#define EMMC_5_0_PHY_DLL_CONTROL        (EMMC_5_0_PHY_REG_BASE + 0x10)
>>> +#define DLL_ENABLE                BIT(31)
>>> +#define DLL_UPDATE_STROBE_5_0            BIT(30)
>>> +#define DLL_REFCLK_SEL                BIT(30)
>>> +#define DLL_UPDATE                BIT(23)
>>> +#define DLL_PHSEL1_SHIFT            24
>>> +#define DLL_PHSEL0_SHIFT            16
>>> +#define DLL_PHASE_MASK                0x3F
>>> +#define DLL_PHASE_90_DEGREE            0x1F
>>> +#define DLL_FAST_LOCK                BIT(5)
>>> +#define DLL_GAIN2X                BIT(3)
>>> +#define DLL_BYPASS_EN                BIT(0)
>>> +
>>> +#define EMMC_5_0_PHY_LOGIC_TIMING_ADJUST    (EMMC_5_0_PHY_REG_BASE + 0x14)
>>> +#define EMMC_PHY_LOGIC_TIMING_ADJUST        (EMMC_PHY_REG_BASE + 0x18)
>>> +
>>> +enum sampl_fix_delay_phase {
>>> +    PHASE_0_DEGREE = 0x0,
>>> +    PHASE_90_DEGREE = 0x1,
>>> +    PHASE_180_DEGREE = 0x2,
>>> +    PHASE_270_DEGREE = 0x3,
>>> +};
>>> +
>>> +#define SDH_PHY_SLOT_DLL_CTRL            (0x0138)
>>> +#define SDH_PHY_ENABLE_DLL            BIT(1)
>>> +#define SDH_PHY_FAST_LOCK_EN            BIT(5)
>>> +
>>> +#define SDH_PHY_SLOT_DLL_PHASE_SEL        (0x013C)
>>> +#define SDH_PHY_DLL_UPDATE_TUNING        BIT(15)
>>> +
>>> +enum soc_pad_ctrl_type {
>>> +    SOC_PAD_SD,
>>> +    SOC_PAD_FIXED_1_8V,
>>> +};
>>> +
>>> +/*
>>> + * List offset of PHY registers and some special register values
>>> + * in eMMC PHY 5.0 or eMMC PHY 5.1
>>> + */
>>> +struct xenon_emmc_phy_regs {
>>> +    /* Offset of Timing Adjust register */
>>> +    u16 timing_adj;
>>> +    /* Offset of Func Control register */
>>> +    u16 func_ctrl;
>>> +    /* Offset of Pad Control register */
>>> +    u16 pad_ctrl;
>>> +    /* Offset of Pad Control register */
>>> +    u16 pad_ctrl2;
>>> +    /* Offset of DLL Control register */
>>> +    u16 dll_ctrl;
>>> +    /* Offset of Logic Timing Adjust register */
>>> +    u16 logic_timing_adj;
>>> +    /* Max value of eMMC Fixed Sampling Delay */
>>> +    u32 delay_mask;
>>> +    /* DLL Update Enable bit */
>>> +    u32 dll_update;
>>> +};
>>> +
>>> +struct xenon_phy_ops {
>>> +    void (*strobe_delay_adj)(struct sdhci_host *host,
>>> +                 struct mmc_card *card);
>>> +    int (*fix_sampl_delay_adj)(struct sdhci_host *host,
>>> +                   struct mmc_card *card);
>>> +    void (*phy_set)(struct sdhci_host *host, unsigned char timing);
>>> +    void (*set_soc_pad)(struct sdhci_host *host,
>>> +                unsigned char signal_voltage);
>>> +};
>>> +#endif
>>> diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
>>> index 03ba183494d3..4d7d871544fc 100644
>>> --- a/drivers/mmc/host/sdhci-xenon.c
>>> +++ b/drivers/mmc/host/sdhci-xenon.c
>>> @@ -224,6 +224,7 @@ static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>      spin_unlock_irqrestore(&host->lock, flags);
>>>
>>>      sdhci_set_ios(mmc, ios);
>>> +    xenon_phy_adj(host, ios);
>>>
>>>      if (host->clock > DEFAULT_SDCLK_FREQ) {
>>>          spin_lock_irqsave(&host->lock, flags);
>>> @@ -309,6 +310,8 @@ static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
>>>       */
>>>      enable_xenon_internal_clk(host);
>>>
>>> +    xenon_soc_pad_ctrl(host, ios->signal_voltage);
>>> +
>>>      if (priv->card_candidate) {
>>>          if (mmc_card_mmc(priv->card_candidate))
>>>              return xenon_emmc_signal_voltage_switch(mmc, ios);
>>> @@ -453,6 +456,7 @@ static int xenon_probe_dt(struct platform_device *pdev)
>>>          sdhci_writel(host, reg, SDHC_SYS_EXT_OP_CTRL);
>>>      }
>>>
>>> +    err = xenon_phy_parse_dt(np, host);
>>>      return err;
>>>  }
>>>
>>> diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h
>>> index c2370493fbe8..06e5261a563c 100644
>>> --- a/drivers/mmc/host/sdhci-xenon.h
>>> +++ b/drivers/mmc/host/sdhci-xenon.h
>>> @@ -15,6 +15,7 @@
>>>  #include <linux/mmc/card.h>
>>>  #include <linux/of.h>
>>>  #include "sdhci.h"
>>> +#include "sdhci-xenon-phy.h"
>>>
>>>  /* Register Offset of SD Host Controller SOCP self-defined register */
>>>  #define SDHC_SYS_CFG_INFO            0x0104
>>> @@ -76,6 +77,7 @@
>>>  #define MMC_TIMING_FAKE                0xFF
>>>
>>>  #define DEFAULT_SDCLK_FREQ            (400000)
>>> +#define LOWEST_SDCLK_FREQ            (100000)
>>>
>>>  /* Xenon specific Mode Select value */
>>>  #define XENON_SDHCI_CTRL_HS200            0x5
>>> @@ -97,6 +99,15 @@ struct sdhci_xenon_priv {
>>>      /* Slot idx */
>>>      u8        slot_idx;
>>>
>>> +    int        phy_type;
>>> +    /*
>>> +     * Contains board-specific PHY parameters
>>> +     * passed from device tree.
>>> +     */
>>> +    void        *phy_params;
>>> +    const struct xenon_phy_ops *phy_ops;
>>> +    struct xenon_emmc_phy_regs *emmc_phy_regs;
>>> +
>>>      /*
>>>       * When initializing card, Xenon has to determine card type and
>>>       * adjust Sampling Fixed delay.
>>> @@ -131,4 +142,10 @@ static inline int enable_xenon_internal_clk(struct sdhci_host *host)
>>>
>>>      return 0;
>>>  }
>>> +
>>> +int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
>>> +int xenon_phy_parse_dt(struct device_node *np,
>>> +               struct sdhci_host *host);
>>> +void xenon_soc_pad_ctrl(struct sdhci_host *host,
>>> +            unsigned char signal_voltage);
>>>  #endif
>>>
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Best Regards
Shawn Lin

^ permalink raw reply

* [PATCH v3 2/2] ARM: dts: rockchip: Add rk3066 MK808 board
From: Shawn Lin @ 2016-10-09 13:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <876234f84363b4a83c566137866cd823528ed07a.1475957884.git.paweljarosz3691@gmail.com>

? 2016/10/9 4:22, Pawe? Jarosz ??:
> MK808 is a tv stick which has rockchip rk3066 CPU inside, two usb ports
> - host and otg, micro sd card slot and onboard wifi RK901.
>
> Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>

It looks okay to me, so feel free to add

Reviewed-by: Shawn Lin <shawn.lin@rock-chip.com>

> ---
>
> Changes in v2:
> - included Heiko sugestion.
>
> Changes in v3:
> - added regulators for mmc0 and mmc1
> - added proper pincontrol for mmc1
> - removed regulator-always-on flag from vcc_io
>
>  Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
>  arch/arm/boot/dts/Makefile                         |   1 +
>  arch/arm/boot/dts/rk3066a-mk808.dts                | 196 +++++++++++++++++++++
>  3 files changed, 201 insertions(+)
>  create mode 100644 arch/arm/boot/dts/rk3066a-mk808.dts
>
> diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
> index 55f388f..c09595b 100644
> --- a/Documentation/devicetree/bindings/arm/rockchip.txt
> +++ b/Documentation/devicetree/bindings/arm/rockchip.txt
> @@ -17,6 +17,10 @@ Rockchip platforms device tree bindings
>      Required root node properties:
>        - compatible = "chipspark,rayeager-px2", "rockchip,rk3066a";
>
> +- Rikomagic MK808 v1 board:
> +    Required root node properties:
> +      - compatible = "rikomagic,mk808", "rockchip,rk3066a";
> +
>  - Radxa Rock board:
>      Required root node properties:
>        - compatible = "radxa,rock", "rockchip,rk3188";
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index befcd26..f19cc1d 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -639,6 +639,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
>  	rk3036-kylin.dtb \
>  	rk3066a-bqcurie2.dtb \
>  	rk3066a-marsboard.dtb \
> +	rk3066a-mk808.dtb \
>  	rk3066a-rayeager.dtb \
>  	rk3188-radxarock.dtb \
>  	rk3228-evb.dtb \
> diff --git a/arch/arm/boot/dts/rk3066a-mk808.dts b/arch/arm/boot/dts/rk3066a-mk808.dts
> new file mode 100644
> index 0000000..0123fa4
> --- /dev/null
> +++ b/arch/arm/boot/dts/rk3066a-mk808.dts
> @@ -0,0 +1,196 @@
> +/*
> + * Copyright (c) 2016 Pawe? Jarosz <paweljarosz3691@gmail.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL 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 file 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 file 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 "rk3066a.dtsi"
> +
> +/ {
> +	model = "Rikomagic MK808";
> +	compatible = "rikomagic,mk808", "rockchip,rk3066a";
> +
> +	chosen {
> +		stdout-path = "serial2:115200n8";
> +	};
> +
> +	memory at 60000000 {
> +		device_type = "memory";
> +		reg = <0x60000000 0x40000000>;
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +
> +		blue {
> +			label = "mk808:blue:power";
> +			gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
> +			default-state = "off";
> +			linux,default-trigger = "default-on";
> +		};
> +	};
> +
> +	vcc_io: vcc-io {
> +		compatible = "regulator-fixed";
> +		regulator-name = "vcc_io";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +	};
> +
> +	vcc_host: usb-host-regulator {
> +		compatible = "regulator-fixed";
> +		enable-active-high;
> +		gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>;
> +		pinctrl-0 = <&host_drv>;
> +		pinctrl-names = "default";
> +		regulator-always-on;
> +		regulator-name = "host-pwr";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +		startup-delay-us = <100000>;
> +		vin-supply = <&vcc_io>;
> +	};
> +
> +	vcc_otg: usb-otg-regulator {
> +		compatible = "regulator-fixed";
> +		enable-active-high;
> +		gpio = <&gpio0 5 GPIO_ACTIVE_HIGH>;
> +		pinctrl-0 = <&otg_drv>;
> +		pinctrl-names = "default";
> +		regulator-always-on;
> +		regulator-name = "vcc_otg";
> +		regulator-min-microvolt = <5000000>;
> +		regulator-max-microvolt = <5000000>;
> +		startup-delay-us = <100000>;
> +		vin-supply = <&vcc_io>;
> +	};
> +
> +	vcc_sd: sdmmc-regulator {
> +		compatible = "regulator-fixed";
> +		gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
> +		pinctrl-0 = <&sdmmc_pwr>;
> +		pinctrl-names = "default";
> +		regulator-name = "vcc_sd";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <100000>;
> +		vin-supply = <&vcc_io>;
> +	};
> +
> +	vcc_wifi: sdio-regulator {
> +		compatible = "regulator-fixed";
> +		enable-active-high;
> +		gpio = <&gpio3 24 GPIO_ACTIVE_HIGH>;
> +		pinctrl-0 = <&wifi_pwr>;
> +		pinctrl-names = "default";
> +		regulator-name = "vcc_wifi";
> +		regulator-min-microvolt = <3300000>;
> +		regulator-max-microvolt = <3300000>;
> +		startup-delay-us = <100000>;
> +		vin-supply = <&vcc_io>;
> +	};
> +};
> +
> +&mmc0 {
> +	bus-width = <4>;
> +	cap-mmc-highspeed;
> +	cap-sd-highspeed;
> +	num-slots = <1>;
> +	status = "okay";
> +	vmmc-supply = <&vcc_sd>;
> +};
> +
> +&mmc1 {
> +	bus-width = <4>;
> +	disable-wp;
> +	non-removable;
> +	num-slots = <1>;
> +	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +	vmmc-supply = <&vcc_wifi>;
> +};
> +
> +&pinctrl {
> +	usb-host {
> +		host_drv: host-drv {
> +			rockchip,pins = <RK_GPIO0 6 RK_FUNC_GPIO &pcfg_pull_default>;
> +		};
> +	};
> +
> +	usb-otg {
> +		otg_drv: otg-drv {
> +			rockchip,pins = <RK_GPIO0 5 RK_FUNC_GPIO &pcfg_pull_default>;
> +		};
> +	};
> +
> +	sdmmc {
> +		sdmmc_pwr: sdmmc-pwr {
> +			rockchip,pins = <RK_GPIO3 7 RK_FUNC_GPIO &pcfg_pull_default>;
> +		};
> +	};
> +
> +	sdio {
> +		wifi_pwr: wifi-pwr {
> +			rockchip,pins = <RK_GPIO3 24 RK_FUNC_GPIO &pcfg_pull_none>;
> +		};
> +	};
> +};
> +
> +&uart2 {
> +	status = "okay";
> +};
> +
> +&usb_host {
> +	status = "okay";
> +};
> +
> +&usb_otg {
> +	status = "okay";
> +};
> +
> +&usbphy {
> +	status = "okay";
> +};
> +
> +&wdt {
> +	status = "okay";
> +};
> +
>


-- 
Best Regards
Shawn Lin

^ permalink raw reply

* [PATCH 1/2] host: ehci-exynos: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
From: Anand Moon @ 2016-10-09 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

Move the ehci-exynos system PM callbacks within #ifdef CONFIG_PM_SLEEP
as to avoid them being build when not used. This also allows us to use the
SET_SYSTEM_SLEEP_PM_OPS macro which simplifies the code.

Signed-off-by: Anand Moon <linux.amoon@gmail.com>
---
 drivers/usb/host/ehci-exynos.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 42e5b66..1899900 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -251,7 +251,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int exynos_ehci_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -292,15 +292,13 @@ static int exynos_ehci_resume(struct device *dev)
 	ehci_resume(hcd, false);
 	return 0;
 }
-#else
-#define exynos_ehci_suspend	NULL
-#define exynos_ehci_resume	NULL
-#endif
 
 static const struct dev_pm_ops exynos_ehci_pm_ops = {
-	.suspend	= exynos_ehci_suspend,
-	.resume		= exynos_ehci_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_ehci_suspend, exynos_ehci_resume)
 };
+#endif /* CONFIG_PM_SLEEP */
+
+#define DEV_PM_OPS IS_ENABLED(CONFIG_PM_SLEEP) ? &exynos_ehci_pm_ops : NULL
 
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_ehci_match[] = {
@@ -317,7 +315,7 @@ static struct platform_driver exynos_ehci_driver = {
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver = {
 		.name	= "exynos-ehci",
-		.pm	= &exynos_ehci_pm_ops,
+		.pm	= DEV_PM_OPS,
 		.of_match_table = of_match_ptr(exynos_ehci_match),
 	}
 };
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/2] host: ohci-exynos: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
From: Anand Moon @ 2016-10-09 14:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476023655-3232-1-git-send-email-linux.amoon@gmail.com>

Move the ohci-exynos system PM callbacks within #ifdef CONFIG_PM_SLEEP
as to avoid them being build when not used. This also allows us to use the
SET_SYSTEM_SLEEP_PM_OPS macro which simplifies the code.

Signed-off-by: Anand Moon <linux.amoon@gmail.com>
---
 drivers/usb/host/ohci-exynos.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 2cd105b..1764baa 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -219,7 +219,7 @@ static void exynos_ohci_shutdown(struct platform_device *pdev)
 		hcd->driver->shutdown(hcd);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int exynos_ohci_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -256,18 +256,16 @@ static int exynos_ohci_resume(struct device *dev)
 
 	return 0;
 }
-#else
-#define exynos_ohci_suspend	NULL
-#define exynos_ohci_resume	NULL
-#endif
 
-static const struct ohci_driver_overrides exynos_overrides __initconst = {
-	.extra_priv_size =	sizeof(struct exynos_ohci_hcd),
+static const struct dev_pm_ops exynos_ohci_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_ohci_suspend, exynos_ohci_resume)
 };
+#endif /* CONFIG_PM_SLEEP */
 
-static const struct dev_pm_ops exynos_ohci_pm_ops = {
-	.suspend	= exynos_ohci_suspend,
-	.resume		= exynos_ohci_resume,
+#define DEV_PM_OPS IS_ENABLED(CONFIG_PM_SLEEP) ? &exynos_ohci_pm_ops : NULL
+
+static const struct ohci_driver_overrides exynos_overrides __initconst = {
+	.extra_priv_size =	sizeof(struct exynos_ohci_hcd),
 };
 
 #ifdef CONFIG_OF
@@ -285,7 +283,7 @@ static struct platform_driver exynos_ohci_driver = {
 	.shutdown	= exynos_ohci_shutdown,
 	.driver = {
 		.name	= "exynos-ohci",
-		.pm	= &exynos_ohci_pm_ops,
+		.pm	= DEV_PM_OPS,
 		.of_match_table	= of_match_ptr(exynos_ohci_match),
 	}
 };
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/2] host: ehci-exynos: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
From: Krzysztof Kozlowski @ 2016-10-09 16:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476023655-3232-1-git-send-email-linux.amoon@gmail.com>

On Sun, Oct 09, 2016 at 02:34:14PM +0000, Anand Moon wrote:
> Move the ehci-exynos system PM callbacks within #ifdef CONFIG_PM_SLEEP
> as to avoid them being build when not used. This also allows us to use the
> SET_SYSTEM_SLEEP_PM_OPS macro which simplifies the code.
> 
> Signed-off-by: Anand Moon <linux.amoon@gmail.com>
> ---
>  drivers/usb/host/ehci-exynos.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
> index 42e5b66..1899900 100644
> --- a/drivers/usb/host/ehci-exynos.c
> +++ b/drivers/usb/host/ehci-exynos.c
> @@ -251,7 +251,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> -#ifdef CONFIG_PM
> +#ifdef CONFIG_PM_SLEEP

Does not look like an equivalent change. How will it behave in a config
with !SUSPEND && !HIBERNATE && PM?

Best regards,
Krzysztof

>  static int exynos_ehci_suspend(struct device *dev)
>  {
>  	struct usb_hcd *hcd = dev_get_drvdata(dev);
> @@ -292,15 +292,13 @@ static int exynos_ehci_resume(struct device *dev)
>  	ehci_resume(hcd, false);
>  	return 0;
>  }
> -#else
> -#define exynos_ehci_suspend	NULL
> -#define exynos_ehci_resume	NULL
> -#endif
>  
>  static const struct dev_pm_ops exynos_ehci_pm_ops = {
> -	.suspend	= exynos_ehci_suspend,
> -	.resume		= exynos_ehci_resume,
> +	SET_SYSTEM_SLEEP_PM_OPS(exynos_ehci_suspend, exynos_ehci_resume)
>  };
> +#endif /* CONFIG_PM_SLEEP */
> +
> +#define DEV_PM_OPS IS_ENABLED(CONFIG_PM_SLEEP) ? &exynos_ehci_pm_ops : NULL
>  
>  #ifdef CONFIG_OF
>  static const struct of_device_id exynos_ehci_match[] = {
> @@ -317,7 +315,7 @@ static struct platform_driver exynos_ehci_driver = {
>  	.shutdown	= usb_hcd_platform_shutdown,
>  	.driver = {
>  		.name	= "exynos-ehci",
> -		.pm	= &exynos_ehci_pm_ops,
> +		.pm	= DEV_PM_OPS,
>  		.of_match_table = of_match_ptr(exynos_ehci_match),
>  	}
>  };
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v3 00/17] pinctrl: exynos/samsung: Add header with values used for configuration
From: Krzysztof Kozlowski @ 2016-10-09 16:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CA+Ln22Eotn=dLyA8KYT_6Fnwvp1sTSxzP8DepAFB2P8EUMME6Q@mail.gmail.com>

On Sun, Oct 09, 2016 at 04:04:11PM +0900, Tomasz Figa wrote:
> Hi Krzysztof,
> 
> 2016-09-04 20:04 GMT+09:00 Krzysztof Kozlowski <krzk@kernel.org>:
> >
> > Hi,
> >
> > Changes since v2
> > ================
> > 1. Combine separate patchsets into one. Previously I sent separately the fixes
> >    and changes for S3C platforms.
> > 2. Fix issues pointed during review.
> > 3. Add review tags.
> >
> > Changes since v1
> > ================
> > 1. Follow Arnd's suggestion about moving the macros to common place.
> > 2. Subjects: replace "GPIO" with "pinctrl".
> > 3. There were some major changes here so I did not add Javier's
> >    reviewed-by and tested-by tags.
> >
> > Merging
> > =======
> > Patches #1 and #2 should probably go through pinctrl tree. In that case I would
> > appreciate a stable branch/tag so DTS could base on top of it.
> >
> > Goal
> > ====
> > Increase readability:
> >         uart0_data: uart0-data {
> >                 samsung,pins = "gpa0-0", "gpa0-1";
> > -               samsung,pin-function = <2>;
> > -               samsung,pin-pud = <0>;
> > -               samsung,pin-drv = <0>;
> > +               samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
> > +               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
> > +               samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
> 
> I like the idea, thanks for cleaning this up. However I'd like to
> bikeshed the prefix a bit. Since the properties are already prefixed
> by "samsung,", I think it would make much more sense to also prefix
> the generic values with "SAMSUNG_". Of course for soc/family-specific
> values, the soc/family name prefix sounds right.

I am lost. Sorry, I don't get what kind of final prefixes you would like
to have.

SAMSUNG_EXYNOS4_PIN_DRV_LV1
SAMSUNG_EXYNOS5260_PIN_DRV_LV1
?

> Similarly for rest of the value names, such as SAMSUNG_PIN_PUD instead
> of SAMSUNG_PIN_PULL, which obviously sounds more like correct English,
> however hurts the consistency and could confuse the people writing new
> dts files.

SAMSUNG_S3C64XX_PIN_PUD_NONE
SAMSUNG_EXYNOS_PIN_PUD_NONE

?

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH 1/2] host: ehci-exynos: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
From: Anand Moon @ 2016-10-09 17:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161009163446.GA9672@kozik-lap>

Hi Krzysztof,

On 9 October 2016 at 22:04, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> On Sun, Oct 09, 2016 at 02:34:14PM +0000, Anand Moon wrote:
>> Move the ehci-exynos system PM callbacks within #ifdef CONFIG_PM_SLEEP
>> as to avoid them being build when not used. This also allows us to use the
>> SET_SYSTEM_SLEEP_PM_OPS macro which simplifies the code.
>>
>> Signed-off-by: Anand Moon <linux.amoon@gmail.com>
>> ---
>>  drivers/usb/host/ehci-exynos.c | 14 ++++++--------
>>  1 file changed, 6 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
>> index 42e5b66..1899900 100644
>> --- a/drivers/usb/host/ehci-exynos.c
>> +++ b/drivers/usb/host/ehci-exynos.c
>> @@ -251,7 +251,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
>>       return 0;
>>  }
>>
>> -#ifdef CONFIG_PM
>> +#ifdef CONFIG_PM_SLEEP
>
> Does not look like an equivalent change. How will it behave in a config
> with !SUSPEND && !HIBERNATE && PM?
>

[snip]

I just wanted to update suspend and resume callback to use
SET_SYSTEM_SLEEP_PM_OPS
as they are define under CONFIG_PM_SLEEP so I update above to avoid
compilation warning/error.

http://lxr.free-electrons.com/source/include/linux/pm.h#L321

-Best Regards
Anand Moon

^ permalink raw reply

* [PATCH 1/2] host: ehci-exynos: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
From: Krzysztof Kozlowski @ 2016-10-09 17:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANAwSgSr6-0x47=0P_NCiGCv=FSZR9dNT89JpY=9R_32U8HywQ@mail.gmail.com>

On Sun, Oct 09, 2016 at 10:45:40PM +0530, Anand Moon wrote:
> Hi Krzysztof,
> 
> On 9 October 2016 at 22:04, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> > On Sun, Oct 09, 2016 at 02:34:14PM +0000, Anand Moon wrote:
> >> Move the ehci-exynos system PM callbacks within #ifdef CONFIG_PM_SLEEP
> >> as to avoid them being build when not used. This also allows us to use the
> >> SET_SYSTEM_SLEEP_PM_OPS macro which simplifies the code.
> >>
> >> Signed-off-by: Anand Moon <linux.amoon@gmail.com>
> >> ---
> >>  drivers/usb/host/ehci-exynos.c | 14 ++++++--------
> >>  1 file changed, 6 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
> >> index 42e5b66..1899900 100644
> >> --- a/drivers/usb/host/ehci-exynos.c
> >> +++ b/drivers/usb/host/ehci-exynos.c
> >> @@ -251,7 +251,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
> >>       return 0;
> >>  }
> >>
> >> -#ifdef CONFIG_PM
> >> +#ifdef CONFIG_PM_SLEEP
> >
> > Does not look like an equivalent change. How will it behave in a config
> > with !SUSPEND && !HIBERNATE && PM?
> >
> 
> [snip]
> 
> I just wanted to update suspend and resume callback to use
> SET_SYSTEM_SLEEP_PM_OPS
> as they are define under CONFIG_PM_SLEEP so I update above to avoid
> compilation warning/error.

First of all you did not answer to my question, so let me rephrase into
two:
1. Is the code equivalent?
2. What will be the output with !SUSPEND && !HIBERNATE && PM?

You didn't mention compilation warning/error in message commit so I do
not know what you are thinking about...

Best regards,
Krzysztof

^ permalink raw reply

* [PATCH 0/6] crypto: arm64 - big endian fixes
From: Ard Biesheuvel @ 2016-10-09 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

As it turns out, none of the accelerated crypto routines under arch/arm64/crypto
currently work, or have ever worked correctly when built for big endian. So this
series fixes all of them.

Each of these patches carries a fixes tag, and could be backported to stable.
However, for patches #1 and #5, the fixes tag denotes the oldest commit that the
fix is compatible with, not the patch that introduced the algorithm. This is due
to the fact that the key schedules are incompatible between generic AES and the
arm64 Crypto Extensions implementation (but only when building for big endian)
This is not a problem in practice, but it does mean that the AES-CCM and AES in
EBC/CBC/CTR/XTS mode implementations before v3.19 require a different fix, i.e.,
one that is compatible with the generic AES key schedule generation code (which
it currently no longer uses)

In any case, please apply with cc to stable.

Ard Biesheuvel (6):
  crypto: arm64/aes-ce - fix for big endian
  crypto: arm64/ghash-ce - fix for big endian
  crypto: arm64/sha1-ce - fix for big endian
  crypto: arm64/sha2-ce - fix for big endian
  crypto: arm64/aes-ccm-ce: fix for big endian
  crypto: arm64/aes-neon - fix for big endian

 arch/arm64/crypto/aes-ce-ccm-core.S | 53 ++++++++++----------
 arch/arm64/crypto/aes-ce-cipher.c   | 25 +++++----
 arch/arm64/crypto/aes-neon.S        | 25 +++++----
 arch/arm64/crypto/ghash-ce-core.S   |  6 +--
 arch/arm64/crypto/sha1-ce-core.S    |  4 +-
 arch/arm64/crypto/sha2-ce-core.S    |  4 +-
 6 files changed, 64 insertions(+), 53 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/6] crypto: arm64/aes-ce - fix for big endian
From: Ard Biesheuvel @ 2016-10-09 17:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476034945-9186-1-git-send-email-ard.biesheuvel@linaro.org>

The core AES cipher implementation that uses ARMv8 Crypto Extensions
instructions erroneously loads the round keys as 64-bit quantities,
which causes the algorithm to fail when built for big endian. In
addition, the key schedule generation routine fails to take endianness
into account as well, when loading the combining the input key with
the round constants. So fix both issues.

Fixes: 12ac3efe74f8 ("arm64/crypto: use crypto instructions to generate AES key schedule")
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/crypto/aes-ce-cipher.c | 25 ++++++++++++--------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/crypto/aes-ce-cipher.c b/arch/arm64/crypto/aes-ce-cipher.c
index f7bd9bf0bbb3..50d9fe11d0c8 100644
--- a/arch/arm64/crypto/aes-ce-cipher.c
+++ b/arch/arm64/crypto/aes-ce-cipher.c
@@ -47,24 +47,24 @@ static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aese	v0.16b, v2.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aese	v0.16b, v3.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aese	v0.16b, v1.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aese	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -92,24 +92,24 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aesd	v0.16b, v2.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aesd	v0.16b, v3.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aesd	v0.16b, v1.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aesd	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -173,7 +173,12 @@ int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
 		u32 *rki = ctx->key_enc + (i * kwords);
 		u32 *rko = rki + kwords;
 
+#ifndef CONFIG_CPU_BIG_ENDIAN
 		rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
+#else
+		rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^
+			 rki[0];
+#endif
 		rko[1] = rko[0] ^ rki[1];
 		rko[2] = rko[1] ^ rki[2];
 		rko[3] = rko[2] ^ rki[3];
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox