Merge "usb: f_gsi: Honor RNDIS host IN aggregation size"
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index d11af52..ac9489f 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -54,6 +54,7 @@
| ARM | Cortex-A57 | #852523 | N/A |
| ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 |
| ARM | Cortex-A72 | #853709 | N/A |
+| ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 |
| ARM | MMU-500 | #841119,#826419 | N/A |
| | | | |
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index d150116..1b8b7cf 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -175,6 +175,9 @@
- VR device:
compatible = "qcom,qvr"
+- SVR device:
+ compatible = "qcom,svr"
+
- HDK device:
compatible = "qcom,hdk"
@@ -295,6 +298,7 @@
compatible = "qcom,sda845-mtp"
compatible = "qcom,sda845-qrd"
compatible = "qcom,sda845-hdk"
+compatible = "qcom,sda845-svr"
compatible = "qcom,sdm670-rumi"
compatible = "qcom,sdm670-cdp"
compatible = "qcom,sdm670-mtp"
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
index a89b834..0f40cbce 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
@@ -66,6 +66,10 @@
- qcom,dsi-display: Specifies dsi display is present
- qcom,hdmi-display: Specifies hdmi is present
- qcom,dp-display: Specified dp is present
+- ports: This video port is used when external bridge is present. The connection is modelled
+ using the OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+ Video port 0 is for the bridge output. The remote endpoint phandle should be
+ mipi_dsi_device device node.
- qcom,<type>-supply-entries: A node that lists the elements of the supply used by the
a particular "type" of DSI module. The module "types"
can be "core", "ctrl", and "phy". Within the same type,
diff --git a/Documentation/devicetree/bindings/gpu/adreno-iommu.txt b/Documentation/devicetree/bindings/gpu/adreno-iommu.txt
index b399145..c679fe6 100644
--- a/Documentation/devicetree/bindings/gpu/adreno-iommu.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno-iommu.txt
@@ -42,6 +42,7 @@
currently supported names are:
- gfx3d_user : Used for the 'normal' GPU address space.
- gfx3d_secure : Used for the content protection address space.
+ - gfx3d_secure_alt : Used for the content protection address space for alternative SID.
Each sub node has the following required properties:
- compatible : "qcom,smmu-kgsl-cb"
@@ -83,4 +84,9 @@
compatible = "qcom,smmu-kgsl-cb";
iommus = <&kgsl_smmu 2>;
};
+
+ gfx3d_secure_alt: gfx3d_secure_alt {
+ compatible = "qcom,smmu-kgsl-cb";
+ iommus = <&kgsl_smmu 2>, <&kgsl_smmu 1>;
+ };
};
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 42153e1..375e929 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -207,6 +207,9 @@
- qcom,gpu-quirk-limit-uche-gbif-rw:
Limit number of read and write transactions from UCHE block to
GBIF to avoid possible deadlock between GBIF, SMMU and MEMNOC.
+- qcom,gpu-quirk-mmu-secure-cb-alt:
+ Select alternate secure context bank to generate SID1 for
+ secure playback.
KGSL Memory Pools:
- qcom,gpu-mempools: Container for sets of GPU mempools.Multiple sets
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8e17f80..65c3cb8 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -114,12 +114,6 @@
SOC. If this property is not specified, then auto recharge will
be based off battery voltage.
-- qcom,micro-usb
- Usage: optional
- Value type: <empty>
- Definition: Boolean flag which indicates that the platform only support
- micro usb port.
-
- qcom,suspend-input-on-debug-batt
Usage: optional
Value type: <empty>
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
index 67ffaed..6ff6e9b 100644
--- a/Documentation/devicetree/bindings/thermal/tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -19,6 +19,7 @@
should be "qcom,sdm630-tsens" for 630 TSENS driver.
should be "qcom,sdm845-tsens" for SDM845 TSENS driver.
should be "qcom,tsens24xx" for 2.4 TSENS controller.
+ should be "qcom,msm8937-tsens" for 8937 TSENS driver.
The compatible property is used to identify the respective controller to use
for the corresponding SoC.
- reg : offset and length of the TSENS registers with associated property in reg-names
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index c51581d..8f6af4c 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -1,7 +1,9 @@
dtb-$(CONFIG_ARCH_SDXPOORWILLS) += sdxpoorwills-rumi.dtb \
sdxpoorwills-cdp.dtb \
- sdxpoorwills-mtp.dtb
+ sdxpoorwills-mtp.dtb \
+ sdxpoorwills-pcie-ep-cdp.dtb \
+ sdxpoorwills-pcie-ep-mtp.dtb
targets += dtbs
targets += $(addprefix ../, $(dtb-y))
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
index 261829f..38137a2 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
@@ -12,10 +12,7 @@
/dts-v1/;
-
-#include "sdxpoorwills.dtsi"
-#include "sdxpoorwills-pinctrl.dtsi"
-#include "sdxpoorwills-cdp-audio-overlay.dtsi"
+#include "sdxpoorwills-cdp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDXPOORWILLS CDP";
@@ -23,132 +20,3 @@
"qcom,sdxpoorwills", "qcom,cdp";
qcom,board-id = <1 0x0>, <1 0x100>, <1 0x2>, <1 0x102>;
};
-
-&serial_uart {
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_console_active>;
- status = "ok";
-};
-
-&qnand_1 {
- status = "ok";
-};
-
-&sdhc_1 {
- vdd-supply = <&vreg_sd_mmc>;
-
- vdd-io-supply = <&pmxpoorwills_l7>;
- qcom,vdd-io-voltage-level = <1800000 2950000>;
- qcom,vdd-io-current-level = <200 10000>;
-
- pinctrl-names = "active", "sleep";
- pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_cd_on>;
- pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_cd_off>;
-
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
- 200000000>;
- qcom,devfreq,freq-table = <50000000 200000000>;
-
- cd-gpios = <&tlmm 93 0x1>;
-
- status = "ok";
-};
-
-&pmxpoorwills_vadc {
- chan@83 {
- label = "vph_pwr";
- reg = <0x83>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@4c {
- label = "xo_therm";
- reg = <0x4c>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <4>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4d {
- label = "pa_therm1";
- reg = <0x4d>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4e {
- label = "pa_therm2";
- reg = <0x4e>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4f {
- label = "mdm_case_therm";
- reg = <0x4f>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@52 {
- label = "ambient_therm";
- reg = <0x52>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-};
-
-&i2c_3 {
- status = "okay";
- #include "smb138x.dtsi"
-};
-
-&smb138x {
- pinctrl-names = "default";
- pinctrl-0 = <&smb_int_default>;
- interrupt-parent = <&tlmm>;
- interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
-
- smb1381_charger: qcom,smb1381-charger@1000 {
- compatible = "qcom,smb138x-charger";
- qcom,use-extcon;
- };
-};
-
-&smb138x_vbus {
- status = "okay";
-};
-
-&usb {
- status = "okay";
- extcon = <&smb1381_charger>;
-};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
new file mode 100644
index 0000000..b5944d1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
@@ -0,0 +1,144 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+#include "sdxpoorwills.dtsi"
+#include "sdxpoorwills-pinctrl.dtsi"
+#include "sdxpoorwills-cdp-audio-overlay.dtsi"
+
+&serial_uart {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_console_active>;
+ status = "ok";
+};
+
+&qnand_1 {
+ status = "ok";
+};
+
+&sdhc_1 {
+ vdd-supply = <&vreg_sd_mmc>;
+
+ vdd-io-supply = <&pmxpoorwills_l7>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 10000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_cd_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_cd_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ cd-gpios = <&tlmm 93 0x1>;
+
+ status = "ok";
+};
+
+&pmxpoorwills_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "pa_therm1";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4e {
+ label = "pa_therm2";
+ reg = <0x4e>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "mdm_case_therm";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@52 {
+ label = "ambient_therm";
+ reg = <0x52>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
+
+&i2c_3 {
+ status = "okay";
+ #include "smb138x.dtsi"
+};
+
+&smb138x {
+ pinctrl-names = "default";
+ pinctrl-0 = <&smb_int_default>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+ smb1381_charger: qcom,smb1381-charger@1000 {
+ compatible = "qcom,smb138x-charger";
+ qcom,use-extcon;
+ };
+};
+
+&smb138x_vbus {
+ status = "okay";
+};
+
+&usb {
+ status = "okay";
+ extcon = <&smb1381_charger>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
index cba6262..a0bcdc9 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
@@ -12,10 +12,7 @@
/dts-v1/;
-
-#include "sdxpoorwills.dtsi"
-#include "sdxpoorwills-pinctrl.dtsi"
-#include "sdxpoorwills-mtp-audio-overlay.dtsi"
+#include "sdxpoorwills-mtp.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDXPOORWILLS MTP";
@@ -23,132 +20,3 @@
"qcom,sdxpoorwills", "qcom,mtp";
qcom,board-id = <8 0x0>, <8 0x100>, <8 0x2>, <8 0x102>;
};
-
-&serial_uart {
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_console_active>;
- status = "ok";
-};
-
-&qnand_1 {
- status = "ok";
-};
-
-&sdhc_1 {
- vdd-supply = <&vreg_sd_mmc>;
-
- vdd-io-supply = <&pmxpoorwills_l7>;
- qcom,vdd-io-voltage-level = <1800000 2950000>;
- qcom,vdd-io-current-level = <200 10000>;
-
- pinctrl-names = "active", "sleep";
- pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_cd_on>;
- pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_cd_off>;
-
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
- 200000000>;
- qcom,devfreq,freq-table = <50000000 200000000>;
-
- cd-gpios = <&tlmm 93 0x1>;
-
- status = "ok";
-};
-
-&pmxpoorwills_vadc {
- chan@83 {
- label = "vph_pwr";
- reg = <0x83>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <1>;
- qcom,calibration-type = "absolute";
- qcom,scale-function = <0>;
- qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- };
-
- chan@4c {
- label = "xo_therm";
- reg = <0x4c>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <4>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4d {
- label = "pa_therm1";
- reg = <0x4d>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4e {
- label = "pa_therm2";
- reg = <0x4e>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@4f {
- label = "mdm_case_therm";
- reg = <0x4f>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-
- chan@52 {
- label = "ambient_therm";
- reg = <0x52>;
- qcom,decimation = <2>;
- qcom,pre-div-channel-scaling = <0>;
- qcom,calibration-type = "ratiometric";
- qcom,scale-function = <2>;
- qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
- };
-};
-
-&i2c_3 {
- status = "okay";
- #include "smb138x.dtsi"
-};
-
-&smb138x {
- pinctrl-names = "default";
- pinctrl-0 = <&smb_int_default>;
- interrupt-parent = <&tlmm>;
- interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
-
- smb1381_charger: qcom,smb1381-charger@1000 {
- compatible = "qcom,smb138x-charger";
- qcom,use-extcon;
- };
-};
-
-&smb138x_vbus {
- status = "okay";
-};
-
-&usb {
- status = "okay";
- extcon = <&smb1381_charger>;
-};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
new file mode 100644
index 0000000..63cc3a4
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
@@ -0,0 +1,144 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+#include "sdxpoorwills.dtsi"
+#include "sdxpoorwills-pinctrl.dtsi"
+#include "sdxpoorwills-mtp-audio-overlay.dtsi"
+
+&serial_uart {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_console_active>;
+ status = "ok";
+};
+
+&qnand_1 {
+ status = "ok";
+};
+
+&sdhc_1 {
+ vdd-supply = <&vreg_sd_mmc>;
+
+ vdd-io-supply = <&pmxpoorwills_l7>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 10000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_cd_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_cd_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ cd-gpios = <&tlmm 93 0x1>;
+
+ status = "ok";
+};
+
+&pmxpoorwills_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "pa_therm1";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4e {
+ label = "pa_therm2";
+ reg = <0x4e>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "mdm_case_therm";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@52 {
+ label = "ambient_therm";
+ reg = <0x52>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
+
+&i2c_3 {
+ status = "okay";
+ #include "smb138x.dtsi"
+};
+
+&smb138x {
+ pinctrl-names = "default";
+ pinctrl-0 = <&smb_int_default>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <42 IRQ_TYPE_LEVEL_LOW>;
+
+ smb1381_charger: qcom,smb1381-charger@1000 {
+ compatible = "qcom,smb138x-charger";
+ qcom,use-extcon;
+ };
+};
+
+&smb138x_vbus {
+ status = "okay";
+};
+
+&usb {
+ status = "okay";
+ extcon = <&smb1381_charger>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
new file mode 100644
index 0000000..8339f9a
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS PCIE-EP CDP";
+ compatible = "qcom,sdxpoorwills-cdp",
+ "qcom,sdxpoorwills", "qcom,cdp";
+ qcom,board-id = <1 0x1>, <1 0x101>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
new file mode 100644
index 0000000..2240133
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS PCIE-EP MTP";
+ compatible = "qcom,sdxpoorwills-mtp",
+ "qcom,sdxpoorwills", "qcom,mtp";
+ qcom,board-id = <8 0x1>, <8 0x101>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index b64570b..d684fb2 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -742,8 +742,6 @@
qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
qcom,modem-cfg-emb-pipe-flt;
qcom,use-ipa-pm;
- qcom,arm-smmu;
- qcom,smmu-fast-map;
qcom,bandwidth-vote-for-ipa;
qcom,msm-bus,name = "ipa";
qcom,msm-bus,num-cases = <5>;
@@ -882,30 +880,6 @@
compatible = "qcom,smp2pgpio-map-ipa-1-in";
gpios = <&smp2pgpio_ipa_1_in 0 0>;
};
-
- ipa_smmu_ap: ipa_smmu_ap {
- compatible = "qcom,ipa-smmu-ap-cb";
- iommus = <&apps_smmu 0x5E0 0x0>;
- qcom,iova-mapping = <0x20000000 0x40000000>;
- qcom,additional-mapping =
- /* modem tables in IMEM */
- <0x14686000 0x14686000 0x3000>;
- qcom,ipa-q6-smem-size = <16384>;
- };
-
- ipa_smmu_wlan: ipa_smmu_wlan {
- compatible = "qcom,ipa-smmu-wlan-cb";
- iommus = <&apps_smmu 0x5E1 0x0>;
- qcom,additional-mapping =
- /* ipa-uc ram */
- <0x1E60000 0x1E60000 0xA000>;
- };
-
- ipa_smmu_uc: ipa_smmu_uc {
- compatible = "qcom,ipa-smmu-uc-cb";
- iommus = <&apps_smmu 0x5E2 0x0>;
- qcom,iova-mapping = <0x40000000 0x20000000>;
- };
};
qmp_aop: qcom,qmp-aop@c300000 {
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 98c0aa6..d1dc88e 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -302,6 +302,7 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8953=y
+CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
@@ -351,6 +352,7 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
CONFIG_HID_APPLE=y
@@ -358,7 +360,33 @@
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
@@ -367,6 +395,21 @@
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RMNET_BAM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_PARANOID_SD_INIT=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 38e79f5..2029932 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -312,6 +312,7 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
CONFIG_PINCTRL_MSM8953=y
+CONFIG_PINCTRL_MSM8937=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
@@ -362,6 +363,7 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
CONFIG_HID_APPLE=y
@@ -369,7 +371,33 @@
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_GADGET=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
@@ -378,6 +406,21 @@
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RMNET_BAM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_RING_BUFFER=y
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 32a80d6..cf5311f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -432,6 +432,20 @@
If unsure, say Y.
+config ARM64_ERRATUM_1024718
+ bool "Cortex-A55: 1024718: Update of DBM/AP bits without break before make might result in incorrect update"
+ default y
+ help
+ This option adds work around for Arm Cortex-A55 Erratum 1024718.
+
+ Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect
+ update of the hardware dirty bit when the DBM/AP bits are updated
+ without a break-before-make. The work around is to disable the usage
+ of hardware DBM locally on the affected cores. CPUs not affected by
+ erratum will continue to use the feature.
+
+ If unsure, say Y.
+
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 961921b..7e5cdf2 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -34,12 +34,14 @@
sda845-v2-mtp-overlay.dtbo \
sda845-v2-qrd-overlay.dtbo \
sda845-v2-hdk-overlay.dtbo \
+ sda845-v2-svr-overlay.dtbo \
sda845-v2-4k-panel-mtp-overlay.dtbo \
sda845-v2-4k-panel-cdp-overlay.dtbo \
sda845-v2-4k-panel-qrd-overlay.dtbo \
sda845-v2.1-cdp-overlay.dtbo \
sda845-v2.1-mtp-overlay.dtbo \
sda845-v2.1-qrd-overlay.dtbo \
+ sda845-v2.1-svr-overlay.dtbo \
sda845-v2.1-4k-panel-cdp-overlay.dtbo \
sda845-v2.1-4k-panel-mtp-overlay.dtbo \
sda845-v2.1-4k-panel-qrd-overlay.dtbo \
@@ -77,12 +79,14 @@
sda845-v2-mtp-overlay.dtbo-base := sda845-v2.dtb
sda845-v2-qrd-overlay.dtbo-base := sda845-v2.dtb
sda845-v2-hdk-overlay.dtbo-base := sda845-v2.dtb
+sda845-v2-svr-overlay.dtbo-base := sda845-v2.dtb
sda845-v2-4k-panel-mtp-overlay.dtbo-base := sda845-v2.dtb
sda845-v2-4k-panel-cdp-overlay.dtbo-base := sda845-v2.dtb
sda845-v2-4k-panel-qrd-overlay.dtbo-base := sda845-v2.dtb
sda845-v2.1-cdp-overlay.dtbo-base := sda845-v2.1.dtb
sda845-v2.1-mtp-overlay.dtbo-base := sda845-v2.1.dtb
sda845-v2.1-qrd-overlay.dtbo-base := sda845-v2.1.dtb
+sda845-v2.1-svr-overlay.dtbo-base := sda845-v2.1.dtb
sda845-v2.1-4k-panel-cdp-overlay.dtbo-base := sda845-v2.1.dtb
sda845-v2.1-4k-panel-mtp-overlay.dtbo-base := sda845-v2.1.dtb
sda845-v2.1-4k-panel-qrd-overlay.dtbo-base := sda845-v2.1.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8053.dts b/arch/arm64/boot/dts/qcom/apq8053.dts
index bf9e2f2..6bb67c3 100644
--- a/arch/arm64/boot/dts/qcom/apq8053.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "apq8053.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
/ {
model = "Qualcomm Technologies, Inc. APQ8053 + PMI8950 SOC";
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi
new file mode 100644
index 0000000..77f2a1d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi
@@ -0,0 +1,133 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+&mdss_mdp {
+ dsi_hx8399c_truly_vid: qcom,mdss_dsi_hx8399c_truly_video{
+ qcom,mdss-dsi-panel-name =
+ "hx8399c video mode dsi truly panel";
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <2160>;
+ qcom,mdss-dsi-h-front-porch = <24>;
+ qcom,mdss-dsi-h-back-porch = <24>;
+ qcom,mdss-dsi-h-pulse-width = <16>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <40>;
+ qcom,mdss-dsi-v-front-porch = <36>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 39 01 00 00 00 00 04
+ b9 ff 83 99
+ 39 01 00 00 00 00 02
+ d2 88
+ 39 01 00 00 00 00 10
+ b1 02 04 74 94 01 32 33
+ 11 11 e6 5d 56 73 02 02
+ 39 01 00 00 00 00 10
+ b2 00 80 80 cc 05 07 5a
+ 11 10 10 00 1e 70 03 D4
+ 39 01 00 00 00 00 2d
+ b4 00 ff 59 59 0c ac 00
+ 00 0c 00 07 0a 00 28 07
+ 08 0c 21 03 00 00 00 ae
+ 87 59 59 0c ac 00 00 0c
+ 00 07 0a 00 28 07 08 0c
+ 01 00 00 ae 01
+ 39 01 00 00 05 00 22
+ d3 00 00 01 01 00 00 10
+ 10 00 00 03 00 03 00 08
+ 78 08 78 00 00 00 00 00
+ 24 02 05 05 03 00 00 00
+ 05 40
+ 39 01 00 00 05 00 21
+ d5 20 20 19 19 18 18 02
+ 03 00 01 24 24 18 18 18
+ 18 24 24 00 00 00 00 00
+ 00 00 00 2f 2f 30 30 31
+ 31
+ 39 01 00 00 05 00 21
+ d6 24 24 18 18 19 19 01
+ 00 03 02 24 24 18 18 18
+ 18 20 20 40 40 40 40 40
+ 40 40 40 2f 2f 30 30 31
+ 31
+ 39 01 00 00 00 00 02
+ bd 00
+ 39 01 00 00 00 00 11
+ d8 aa aa aa aa aa aa aa
+ aa aa ba aa aa aa ba aa
+ aa
+ 39 01 00 00 00 00 02
+ bd 01
+ 39 01 00 00 00 00 11
+ d8 82 ea aa aa 82 ea aa
+ aa 82 ea aa aa 82 ea aa
+ aa
+ 39 01 00 00 00 00 02
+ bd 02
+ 39 01 00 00 00 00 09
+ d8 ff ff c0 3f ff ff c0
+ 3f
+ 39 01 00 00 00 00 02
+ bd 00
+ 39 01 00 00 05 00 37
+ e0 08 2a 39 35 74 7c 87
+ 7f 84 8a 8e 91 93 96 9b
+ 9c 9e a5 a6 ae a1 af b2
+ 5c 58 63 74 08 2a 39 35
+ 74 7c 87 7f 84 8a 8e 91
+ 93 96 9b 9c 9e a5 a6 ae
+ a1 af b2 5c 58 63 74
+ 39 01 00 00 00 00 03
+ b6 7e 7e
+ 39 01 00 00 00 00 02
+ cc 08
+ 39 01 00 00 00 00 06
+ c7 00 08 00 01 08
+ 39 01 00 00 00 00 03
+ c0 25 5a
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 14 00 02 29 00];
+ qcom,mdss-dsi-off-command = [
+ 05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-t-clk-post = <0x0e>;
+ qcom,mdss-dsi-t-clk-pre = <0x31>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-test-dualmipi-oled-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-test-dualmipi-oled-cmd.dtsi
new file mode 100644
index 0000000..3a5d272
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-test-dualmipi-oled-cmd.dtsi
@@ -0,0 +1,50 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+&mdss_mdp {
+ dsi_dual_test_cmd: qcom,mdss_dsi_test_oled_cmd {
+ qcom,mdss-dsi-panel-name =
+ "Dual test cmd mode DSI amoled non-DSC panel";
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,adjust-timer-wakeup-ms = <1>;
+ qcom,mdss-dsi-reset-sequence = <1 2>, <0 2>, <1 2>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-wr-mem-start = <0x2c>;
+ qcom,mdss-dsi-wr-mem-continue = <0x3c>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-hfp-power-mode;
+ qcom,mdss-dsi-hbp-power-mode;
+ qcom,mdss-dsi-hsa-power-mode;
+ qcom,mdss-dsi-display-timings {
+ timing@0{
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-demo-3600mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-demo-3600mah.dtsi
new file mode 100644
index 0000000..5c379d9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-demo-3600mah.dtsi
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+qcom,fg-gen3-batterydata-demo-3600mah {
+ qcom,faschg-current-ma = <5000>;
+ qcom,max-voltage-uv = <4350000>;
+ qcom,nom-batt-capacity-mah = <3600>;
+ qcom,batt-id-kohm = <100>;
+ qcom,battery-beta = <3435>;
+ qcom,battery-type = "fg-gen3-batterydata-demo-3600mah";
+ qcom,checksum = <0xA401>;
+ qcom,gui-version = "PMI8998GUI - 2.0.0.54";
+ qcom,fg-profile-data = [
+ B2 1F 79 05
+ 86 0A 36 06
+ 8D 1D 6F F4
+ 39 12 9A 14
+ DC 18 91 22
+ 26 3C EB 4B
+ 5D 00 00 00
+ 11 00 00 00
+ 00 00 78 BC
+ 26 CD 48 C2
+ 1E 00 08 00
+ 78 C5 64 E5
+ 95 FC 1D F3
+ E1 F5 ED 0B
+ 33 FD 8C 2B
+ 1E 06 09 20
+ 27 00 14 00
+ D8 1F 77 05
+ 8B 0A 57 FC
+ 59 1D 8B 00
+ 33 03 78 0C
+ 0F 19 ED 22
+ 6B 45 21 53
+ 5A 00 00 00
+ 0E 00 00 00
+ 00 00 F7 07
+ 55 C2 AA AA
+ 1A 00 00 00
+ B1 EA 64 E5
+ 7C 06 93 F2
+ 71 FD 9E 03
+ 80 0A 7A 22
+ CF 33 CC FF
+ 07 10 00 00
+ 6F 0E 99 45
+ 1A 00 40 00
+ 13 01 0A FA
+ FF 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ ];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
index d0eff96..3da16e4 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
@@ -33,11 +33,11 @@
};
};
-&pmi8950_fg {
+&qpnp_fg {
qcom,battery-data = <&mtp_batterydata>;
};
-&pmi8950_charger {
+&qpnp_smbcharger {
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
qcom,chg-led-support;
diff --git a/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
new file mode 100644
index 0000000..d5537e9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
@@ -0,0 +1,229 @@
+/* Copyright (c) 2015, 2018 The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+&soc {
+ qcom,smp2p-modem@0xb011008 {
+ compatible = "qcom,smp2p";
+ reg = <0xb011008 0x4>;
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-wcnss@0xb011008 {
+ compatible = "qcom,smp2p";
+ reg = <0xb011008 0x4>;
+ qcom,remote-pid = <4>;
+ qcom,irq-bitmask = <0x40000>;
+ interrupts = <0 143 1>;
+ };
+
+ qcom,smp2p-adsp@0xb011008 {
+ compatible = "qcom,smp2p";
+ reg = <0xb011008 0x4>;
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 291 1>;
+ };
+
+ smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+ gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+ gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+ gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+ gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ /* ssr - inbound entry from mss. */
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to mss */
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - inbound entry from lpass. */
+ smp2pgpio_ssr_smp2p_2_in: qcom,smp2pgpio-ssr-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to lpass */
+ smp2pgpio_ssr_smp2p_2_out: qcom,smp2pgpio-ssr-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - inbound entry from wcnss. */
+ smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to wcnss */
+ smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 285727d..baa6ad5 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -121,6 +121,7 @@
#include "msm8937-pinctrl.dtsi"
#include "msm8937-cpu.dtsi"
#include "msm8937-ion.dtsi"
+#include "msm8937-smp2p.dtsi"
&soc {
#address-cells = <1>;
@@ -234,6 +235,174 @@
qcom,pipe-attr-ee;
};
+ thermal_zones: thermal-zones {
+ aoss0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 0>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-core-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 1>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdss-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 2>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 3>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpuss-0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 4>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1_cpu1-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 5>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1_cpu2-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 6>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1_cpu3-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 7>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc1_cpu4-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 8>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ apc0_cpu0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 9>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 10>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+ };
+
+ tsens0: tsens@4a8000 {
+ compatible = "qcom,msm8937-tsens";
+ reg = <0x4a8000 0x1000>,
+ <0x4a9000 0x1000>,
+ <0xa4000 0x1000>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ interrupt-names = "tsens-upper-lower";
+ #thermal-sensor-cells = <1>;
+ };
+
slim_msm: slim@c140000{
cell-index = <1>;
compatible = "qcom,slim-ngd";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index cb59ac3..28a6b74 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -23,6 +23,7 @@
#include "dsi-panel-truly-wuxga-video.dtsi"
#include "dsi-panel-lt8912-480p-video.dtsi"
#include "dsi-panel-lt8912-1080p-video.dtsi"
+#include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -86,6 +87,27 @@
24 1b 08 09 05 03 04 a0];
};
+&dsi_hx8399c_truly_vid {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1c 08 09 05 03 04 a0];
+ qcom,esd-check-enabled;
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-status-read-length = <4>;
+ qcom,mdss-dsi-panel-max-error-count = <3>;
+ qcom,mdss-dsi-min-refresh-rate = <55>;
+ qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,mdss-dsi-pan-fps-update =
+ "dfps_immediate_porch_mode_vfp";
+};
+
&dsi_adv7533_1080p {
qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0
24 1f 08 09 05 03 04 a0
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
index 49956df..c6ae512 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
@@ -20,3 +20,21 @@
model = "MTP";
qcom,board-id = <8 0>;
};
+
+/{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&mtp_batterydata>;
+ qcom,chg-led-sw-controls;
+ qcom,chg-led-support;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
index b53f7b8..97c6db3 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. 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 version 2 and
@@ -33,16 +33,12 @@
};
};
-&pmi8950_fg {
+&qpnp_fg {
qcom,battery-data = <&mtp_batterydata>;
};
-&pmi8950_charger {
+&qpnp_smbcharger {
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
qcom,chg-led-support;
};
-
-&usb3 {
- extcon = <&pmi8950_charger>;
-};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dts b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dts
index a9f64a4..5ec92ae 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "msm8953.dtsi"
+#include "pmi8937.dtsi"
+#include "msm8953-pmi8937.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8937 SOC";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
index a208e1a..80050c4 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
@@ -24,10 +24,10 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
- extcon = <&pmi8937_charger>;
+ extcon = <&qpnp_smbcharger>;
};
-&pmi8937_charger {
+&qpnp_smbcharger {
qcom,external-typec;
qcom,typec-psy-name = "typec";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dts b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dts
index e9c80a0d..ba5c3c7 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "msm8953.dtsi"
+#include "pmi8940.dtsi"
+#include "msm8953-pmi8940.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8940 SOC";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
index 28fc0d7..c36dd1b 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
@@ -24,7 +24,7 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
- extcon = <&pmi8940_charger>;
+ extcon = <&qpnp_smbcharger>;
};
&labibb {
@@ -36,7 +36,7 @@
qcom,qpnp-ibb-discharge-resistor = <32>;
};
-&pmi8940_charger {
+&qpnp_smbcharger {
qcom,external-typec;
qcom,typec-psy-name = "typec";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
index 139ef1e..d81a0a5 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
@@ -29,10 +29,10 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
- extcon = <&pmi8950_charger>;
+ extcon = <&qpnp_smbcharger>;
};
-&pmi8950_charger {
+&qpnp_smbcharger {
qcom,external-typec;
qcom,typec-psy-name = "typec";
};
@@ -46,23 +46,3 @@
lab-supply = <&lab_regulator>;
ibb-supply = <&ibb_regulator>;
};
-
-&dsi_panel_pwr_supply {
- qcom,panel-supply-entry@2 {
- reg = <2>;
- qcom,supply-name = "lab";
- qcom,supply-min-voltage = <4600000>;
- qcom,supply-max-voltage = <6000000>;
- qcom,supply-enable-load = <100000>;
- qcom,supply-disable-load = <100>;
- };
- qcom,panel-supply-entry@3 {
- reg = <3>;
- qcom,supply-name = "ibb";
- qcom,supply-min-voltage = <4600000>;
- qcom,supply-max-voltage = <6000000>;
- qcom,supply-enable-load = <100000>;
- qcom,supply-disable-load = <100>;
- qcom,supply-post-on-sleep = <10>;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-smp2p.dtsi b/arch/arm64/boot/dts/qcom/msm8953-smp2p.dtsi
new file mode 100644
index 0000000..e82e2c8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8953-smp2p.dtsi
@@ -0,0 +1,227 @@
+/* Copyright (c) 2015-2016, 2018 The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+&soc {
+ qcom,smp2p-modem@0x0b011008 {
+ compatible = "qcom,smp2p";
+ reg = <0x0b011008 0x4>;
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-wcnss@0x0b011008 {
+ compatible = "qcom,smp2p";
+ reg = <0x0b011008 0x4>;
+ qcom,remote-pid = <4>;
+ qcom,irq-bitmask = <0x40000>;
+ interrupts = <0 143 1>;
+ };
+
+ qcom,smp2p-adsp@0x0b011008 {
+ compatible = "qcom,smp2p";
+ reg = <0x0b011008 0x4>;
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 291 1>;
+ };
+
+ smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+ gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+ gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+ gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+ gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ /* ssr - inbound entry from mss. */
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to mss */
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - inbound entry from lpass. */
+ smp2pgpio_ssr_smp2p_2_in: qcom,smp2pgpio-ssr-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to lpass */
+ smp2pgpio_ssr_smp2p_2_out: qcom,smp2pgpio-ssr-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dts b/arch/arm64/boot/dts/qcom/msm8953.dts
index ddf2218..2f6cbc4 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "msm8953.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
/ {
model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 SOC";
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 71cba8a..23ab67d 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -168,6 +168,7 @@
#include "msm8953-gpu.dtsi"
#include "msm8953-mdss.dtsi"
#include "msm8953-mdss-pll.dtsi"
+#include "msm8953-smp2p.dtsi"
&soc {
#address-cells = <1>;
@@ -1161,6 +1162,11 @@
reg = <0x94c 200>;
};
+
+ diag_dload@c8 {
+ compatible = "qcom,msm-imem-diag-dload";
+ reg = <0xc8 200>;
+ };
};
qcom,memshare {
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index e5963ef..3561656 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -214,6 +214,151 @@
#gpio-cells = <2>;
qcom,gpios-disallowed = <1>;
};
+
+ pmi632_charger: qcom,qpnp-smb5 {
+ compatible = "qcom,qpnp-smb5";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,pmic-revid = <&pmi632_revid>;
+ dpdm-supply = <&qusb_phy>;
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts =
+ <0x2 0x10 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x2 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x3 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x4 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x5 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x10 0x6 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x10 0x7 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-names = "chgr-error",
+ "chg-state-change",
+ "step-chg-state-change",
+ "step-chg-soc-update-fail",
+ "step-chg-soc-update-req",
+ "fg-fvcal-qualified",
+ "vph-alarm",
+ "vph-drop-prechg";
+ };
+
+ qcom,dcdc@1100 {
+ reg = <0x1100 0x100>;
+ interrupts =
+ <0x2 0x11 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x11 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x11 0x2 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x11 0x3 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x11 0x4 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x11 0x5 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x11 0x6 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x11 0x7 IRQ_TYPE_EDGE_BOTH>;
+
+ interrupt-names = "otg-fail",
+ "otg-oc-disable-sw",
+ "otg-oc-hiccup",
+ "bsm-active",
+ "high-duty-cycle",
+ "input-current-limiting",
+ "concurrent-mode-disable",
+ "switcher-power-ok";
+ };
+
+ qcom,batif@1200 {
+ reg = <0x1200 0x100>;
+ interrupts =
+ <0x2 0x12 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x12 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x12 0x2 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x12 0x3 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x12 0x4 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x12 0x5 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x12 0x6 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x12 0x7 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-names = "bat-temp",
+ "all-chnl-conv-done",
+ "bat-ov",
+ "bat-low",
+ "bat-therm-or-id-missing",
+ "bat-terminal-missing",
+ "buck-oc",
+ "vph-ov";
+ };
+
+ qcom,usb@1300 {
+ reg = <0x1300 0x100>;
+ interrupts =
+ <0x2 0x13 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x13 0x4 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x13 0x5 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x13 0x7 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "usbin-collapse",
+ "usbin-vashdn",
+ "usbin-uv",
+ "usbin-ov",
+ "usbin-plugin",
+ "usbin-revi-change",
+ "usbin-src-change",
+ "usbin-icl-change";
+ };
+
+ qcom,typec@1500 {
+ reg = <0x1500 0x100>;
+ interrupts =
+ <0x2 0x15 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x15 0x1 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x15 0x2 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x3 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x15 0x4 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x15 0x6 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x15 0x7 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "typec-or-rid-detect-change",
+ "typec-vpd-detect",
+ "typec-cc-state-change",
+ "typec-vconn-oc",
+ "typec-vbus-change",
+ "typec-attach-detach",
+ "typec-legacy-cable-detect",
+ "typec-try-snk-src-detect";
+ };
+
+ qcom,misc@1600 {
+ reg = <0x1600 0x100>;
+ interrupts =
+ <0x2 0x16 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x16 0x2 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x16 0x3 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x16 0x4 IRQ_TYPE_LEVEL_HIGH>,
+ <0x2 0x16 0x5 IRQ_TYPE_EDGE_RISING>,
+ <0x2 0x16 0x6 IRQ_TYPE_EDGE_FALLING>,
+ <0x2 0x16 0x7 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "wdog-snarl",
+ "wdog-bark",
+ "aicl-fail",
+ "aicl-done",
+ "smb-en",
+ "imp-trigger",
+ "temp-change",
+ "temp-change-smb";
+ };
+
+ smb5_vbus: qcom,smb5-vbus {
+ regulator-name = "smb5-vbus";
+ };
+ };
};
pmi632_3: qcom,pmi632@3 {
diff --git a/arch/arm64/boot/dts/qcom/pmi8937.dtsi b/arch/arm64/boot/dts/qcom/pmi8937.dtsi
index a7aa08a..c72225d 100644
--- a/arch/arm64/boot/dts/qcom/pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8937.dtsi
@@ -153,7 +153,7 @@
#gpio-cells = <2>;
};
- pmi8937_charger: qcom,qpnp-smbcharger {
+ qpnp_smbcharger: qcom,qpnp-smbcharger {
compatible = "qcom,qpnp-smbcharger";
#address-cells = <1>;
#size-cells = <1>;
@@ -268,7 +268,7 @@
};
};
- pmi8937_fg: qcom,fg {
+ qpnp_fg: qcom,fg {
compatible = "qcom,qpnp-fg";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/pmi8940.dtsi b/arch/arm64/boot/dts/qcom/pmi8940.dtsi
index c6d5c87..d83145c 100644
--- a/arch/arm64/boot/dts/qcom/pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8940.dtsi
@@ -152,7 +152,7 @@
#gpio-cells = <2>;
};
- pmi8940_charger: qcom,qpnp-smbcharger {
+ qpnp_smbcharger: qcom,qpnp-smbcharger {
compatible = "qcom,qpnp-smbcharger";
#address-cells = <1>;
#size-cells = <1>;
@@ -264,7 +264,7 @@
};
};
- pmi8940_fg: qcom,fg {
+ qpnp_fg: qcom,fg {
compatible = "qcom,qpnp-fg";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
index 4e82cfe..e3388c1 100644
--- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -168,7 +168,7 @@
#gpio-cells = <2>;
};
- pmi8950_charger: qcom,qpnp-smbcharger {
+ qpnp_smbcharger: qcom,qpnp-smbcharger {
compatible = "qcom,qpnp-smbcharger";
#address-cells = <1>;
#size-cells = <1>;
@@ -284,7 +284,7 @@
};
};
- pmi8950_fg: qcom,fg {
+ qpnp_fg: qcom,fg {
compatible = "qcom,qpnp-fg";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
index 01471b6..1429880 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
@@ -32,3 +32,47 @@
<0x0001001b 0x0102001a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&cam_cci {
+ /delete-node/ qcom,cam-sensor@1;
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <90>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
index ea10fa0..6c6012e 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
@@ -26,3 +26,47 @@
<0x0001001b 0x0102001a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&cam_cci {
+ /delete-node/ qcom,cam-sensor@1;
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <90>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-svr-pinctrl-overlay.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr-pinctrl-overlay.dtsi
new file mode 100644
index 0000000..c76ef2b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-svr-pinctrl-overlay.dtsi
@@ -0,0 +1,97 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+&cam_sensor_mclk0_active{
+ /* MCLK0 */
+ mux {
+ pins = "gpio13";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio13";
+ bias-disable; /* No PULL */
+ drive-strength = <8>; /* 2 MA */
+ };
+};
+
+&cam_sensor_mclk0_suspend {
+ /* MCLK0 */
+ mux {
+ pins = "gpio13";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio13";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <8>; /* 2 MA */
+ };
+};
+
+&cam_sensor_rear_active {
+ /* RESET, AVDD LDO */
+ mux {
+ pins = "gpio8","gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio8","gpio79";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+&cam_sensor_rear_suspend {
+ /* RESET, AVDD LDO */
+ mux {
+ pins = "gpio8","gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio8","gpio79";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+};
+
+&cam_sensor_front_active{
+ /* RESET AVDD_LDO*/
+ mux {
+ pins = "gpio26", "gpio8";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio26", "gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+&cam_sensor_front_suspend{
+ /* RESET */
+ mux {
+ pins = "gpio26", "gpio8";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio26", "gpio8";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ output-low;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
new file mode 100644
index 0000000..fa82be2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
@@ -0,0 +1,548 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+#include "sdm845-pmic-overlay.dtsi"
+#include "sdm845-pinctrl-overlay.dtsi"
+#include "sda845-svr-pinctrl-overlay.dtsi"
+#include "sdm845-camera-sensor-svr.dtsi"
+#include "smb1355.dtsi"
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
+
+&vendor {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pm8998_s3>;
+ qca,bt-vdd-xtal-supply = <&pm8998_s5>;
+ qca,bt-vdd-core-supply = <&pm8998_l7>;
+ qca,bt-vdd-pa-supply = <&pm8998_l17>;
+ qca,bt-vdd-ldo-supply = <&pm8998_l25>;
+
+ qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+ qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+ qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+ };
+
+ svr_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "fg-gen3-batterydata-demo-3600mah.dtsi"
+ };
+};
+
+&pmi8998_pdphy {
+ vbus-supply = <&smb2_vbus>;
+};
+
+&qupv3_se6_4uart {
+ status = "ok";
+};
+
+&pmi8998_fg {
+ qcom,battery-data = <&svr_batterydata>;
+ qcom,fg-bmd-en-delay-ms = <300>;
+};
+
+&pmi8998_charger {
+ qcom,battery-data = <&svr_batterydata>;
+ qcom,sw-jeita-enable;
+};
+
+&qupv3_se10_i2c {
+ status = "ok";
+};
+
+&smb1355_charger_0 {
+ status = "ok";
+ qcom,disable-ctm;
+};
+
+&smb1355_charger_1 {
+ status = "ok";
+ qcom,disable-ctm;
+};
+
+&soc {
+ qcom,qbt1000 {
+ status = "disabled";
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ label = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_vol_up_default
+ &key_home_default
+ &key_cam_focus_default>;
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pm8998_gpios 6 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+
+ home {
+ label = "home"; /* BACK Key*/
+ gpios = <&pm8998_gpios 5 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <158>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ key_cam_focus {
+ label = "Confirm"; /* Confirm Key*/
+ gpios = <&pm8998_gpios 8 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <28>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ linux,can-disable;
+ };
+ };
+
+ dsi_panel_pwr_supply_amoled: dsi_panel_pwr_supply_amoled {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,panel-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "vddio";
+ qcom,supply-min-voltage = <1880000>;
+ qcom,supply-max-voltage = <1880000>;
+ qcom,supply-enable-load = <62000>;
+ qcom,supply-disable-load = <80>;
+ qcom,supply-post-on-sleep = <20>;
+ };
+
+ qcom,panel-supply-entry@1 {
+ reg = <1>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-post-on-sleep = <20>;
+ };
+ qcom,panel-supply-entry@3 {
+ reg = <3>;
+ qcom,supply-name = "oled-vdda";
+ qcom,supply-min-voltage = <3312000>;
+ qcom,supply-max-voltage = <3312000>;
+ qcom,supply-enable-load = <857000>;
+ qcom,supply-disable-load = <0>;
+ qcom,supply-post-on-sleep = <0>;
+ };
+ };
+};
+
+&sde_rscc {
+ status = "disabled";
+};
+
+&mdss_dsi0 {
+ oled-vdda-supply = <&pm8998_l22>;
+};
+
+&mdss_dsi1 {
+ oled-vdda-supply = <&pm8998_l22>;
+};
+
+&pmi8998_wled {
+ status = "ok";
+ qcom,disp-type-amoled;
+ qcom,avdd-target-voltage-mv = <7600>;
+};
+
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "amoled";
+ qcom,swire-control;
+};
+
+&ibb_regulator {
+ status = "ok";
+ qcom,qpnp-ibb-init-amoled-voltage = <4600000>;
+ qcom,qpnp-ibb-discharge-resistor = <300>;
+};
+
+&lab_regulator {
+ status = "ok";
+ qcom,qpnp-lab-init-amoled-voltage = <4600000>;
+};
+
+&mdss_mdp {
+ connectors = <&sde_wb &sde_dp>;
+};
+
+&dsi_dual_test_cmd {
+ qcom,mdss-dsi-t-clk-post = <0x0e>;
+ qcom,mdss-dsi-t-clk-pre = <0x35>;
+ qcom,mdss-dsi-display-timings {
+ timing@0{
+ qcom,mdss-dsi-panel-phy-timings =
+ [00 24 09 09 26 24 09 09 06 03 04 00];
+ qcom,display-topology = <2 0 2>,
+ <2 0 2>;
+ qcom,default-topology-index = <0>;
+ };
+ };
+};
+
+&dsi_dual_test_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_amoled>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_dual_test_cmd_display {
+ qcom,dsi-display-active;
+};
+
+&snd_934x {
+ qcom,msm-mbhc-hphl-swh = <0>;
+};
+
+&pmi8998_haptics {
+ qcom,vmax-mv = <2400>;
+ qcom,lra-auto-mode;
+ status = "okay";
+};
+
+&qupv3_se9_2uart {
+ status = "ok";
+};
+
+&mdss_mdp {
+ #cooling-cells = <2>;
+};
+
+&ufsphy_mem {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm8998_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm8998_l26>; /* 1.2v */
+ vdda-phy-max-microamp = <62900>;
+ vdda-pll-max-microamp = <18300>;
+
+ status = "ok";
+};
+
+&ufshc_mem {
+ vdd-hba-supply = <&ufs_phy_gdsc>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pm8998_l20>;
+ vcc-voltage-level = <2950000 2960000>;
+ vccq2-supply = <&pm8998_s4>;
+ vcc-max-microamp = <600000>;
+ vccq2-max-microamp = <600000>;
+
+ qcom,vddp-ref-clk-supply = <&pm8998_l2>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm8998_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm8998_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep", "ds_400KHz",
+ "ds_50MHz", "ds_100MHz", "ds_200MHz";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &storage_cd>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &storage_cd>;
+ pinctrl-2 = <&sdc2_clk_ds_400KHz
+ &sdc2_cmd_ds_400KHz &sdc2_data_ds_400KHz>;
+ pinctrl-3 = <&sdc2_clk_ds_50MHz
+ &sdc2_cmd_ds_50MHz &sdc2_data_ds_50MHz>;
+ pinctrl-4 = <&sdc2_clk_ds_100MHz
+ &sdc2_cmd_ds_100MHz &sdc2_data_ds_100MHz>;
+ pinctrl-5 = <&sdc2_clk_ds_200MHz
+ &sdc2_cmd_ds_200MHz &sdc2_data_ds_200MHz>;
+
+ cd-gpios = <&tlmm 126 GPIO_ACTIVE_LOW>;
+
+ status = "ok";
+};
+
+&pmi8998_switch1 {
+ pinctrl-names = "led_enable", "led_disable";
+ pinctrl-0 = <&flash_led3_front_en>;
+ pinctrl-1 = <&flash_led3_front_dis>;
+};
+
+&pmi8998_switch2 {
+ pinctrl-names = "led_enable", "led_disable";
+ pinctrl-0 = <&flash_led3_iris_en>;
+ pinctrl-1 = <&flash_led3_iris_dis>;
+};
+
+&vendor {
+ extcon_usb1: extcon_usb1 {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&pmi8998_gpios 8 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb2_vbus_det_default>;
+ };
+};
+
+&qupv3_se9_2uart {
+ status = "ok";
+};
+
+&qupv3_se8_spi {
+ status = "ok";
+};
+
+&qupv3_se10_i2c {
+ status = "ok";
+};
+
+&qupv3_se6_4uart {
+ status = "ok";
+};
+
+&usb1 {
+ status = "okay";
+ extcon = <&extcon_usb1>;
+};
+
+&qusb_phy1 {
+ status = "okay";
+};
+
+&ext_5v_boost {
+ status = "ok";
+};
+
+&usb_qmp_phy {
+ status = "okay";
+};
+
+&pm8998_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4f {
+ label = "pa_therm1";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
+
+&pm8998_adc_tm {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
+ };
+
+ chan@4f {
+ label = "pa_therm1";
+ reg = <0x4f>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x78>;
+ qcom,thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x80>;
+ qcom,thermal-node;
+ };
+};
+
+&thermal_zones {
+ xo-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_adc_tm 0x4c>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ msm-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_adc_tm 0x4d>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pa-therm1-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_adc_tm 0x4f>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ quiet-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_adc_tm 0x51>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+};
+
+&wil6210 {
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-svr-overlay.dts b/arch/arm64/boot/dts/qcom/sda845-v2-svr-overlay.dts
new file mode 100644
index 0000000..1c6db6f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-svr-overlay.dts
@@ -0,0 +1,31 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+#include "sda845-svr.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDA845 V2 SVR";
+ compatible = "qcom,sda845-svr", "qcom,sda845", "qcom,svr";
+ qcom,msm-id = <341 0x20000>;
+ qcom,board-id = <8 2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-svr.dts b/arch/arm64/boot/dts/qcom/sda845-v2-svr.dts
new file mode 100644
index 0000000..1d7bf7d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-svr.dts
@@ -0,0 +1,25 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+
+/dts-v1/;
+
+#include "sda845-v2.dtsi"
+#include "sdm845-sde-display.dtsi"
+#include "sda845-svr.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDA845 V2 SVR";
+ compatible = "qcom,sda845-svr", "qcom,sda845", "qcom,svr";
+ qcom,msm-id = <341 0x20000>;
+ qcom,board-id = <8 2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2.1-svr-overlay.dts b/arch/arm64/boot/dts/qcom/sda845-v2.1-svr-overlay.dts
new file mode 100644
index 0000000..b4326a9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2.1-svr-overlay.dts
@@ -0,0 +1,32 @@
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm845-sde-display.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+#include "sda845-svr.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sda845 v2.1 SVR";
+ compatible = "qcom,sda845-svr", "qcom,sda845", "qcom,svr";
+ qcom,msm-id = <341 0x20001>;
+ qcom,board-id = <8 2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
index 040b4ba..5744390 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
@@ -24,3 +24,21 @@
qcom,board-id = <8 0>;
qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
};
+
+/{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&mtp_batterydata>;
+ qcom,chg-led-sw-controls;
+ qcom,chg-led-support;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi8937.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi8937.dts
index 700e950..eb6a692 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi8937.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi8937.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "sdm450.dtsi"
+#include "pmi8937.dtsi"
+#include "msm8953-pmi8937.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI8937 SOC";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi8940.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi8940.dts
index f50d177..cfdd4e9 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi8940.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi8940.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "sdm450.dtsi"
+#include "pmi8940.dtsi"
+#include "msm8953-pmi8940.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI8940 SOC";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index 5226e74..9e2981a 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -12,6 +12,7 @@
*/
#include "msm8953-qrd.dtsi"
+#include "msm8953-mdss-panels.dtsi"
&qusb_phy {
qcom,qusb-phy-init-seq = <0x78 0x80
@@ -31,3 +32,78 @@
status = "disabled";
};
+&tlmm {
+ pmx_mdss {
+ mdss_dsi_active: mdss_dsi_active {
+ mux {
+ pins = "gpio61";
+ };
+ config {
+ pins = "gpio61";
+ };
+ };
+ mdss_dsi_suspend: mdss_dsi_suspend {
+ mux {
+ pins = "gpio61";
+ };
+ config {
+ pins = "gpio61";
+ };
+ };
+ };
+};
+
+&dsi_panel_pwr_supply {
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@3 {
+ reg = <3>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-post-on-sleep = <10>;
+ };
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
+ /delete-property/ vdd-supply;
+
+ qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
+ qcom,platform-bklight-en-gpio = <&pm8953_gpios 4 0>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 24 0>;
+ qcom,platform-reset-gpio = <&tlmm 61 0>;
+};
+
+&mdss_dsi1 {
+ status = "disabled";
+};
+
+&dsi_hx8399c_truly_vid {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450.dts b/arch/arm64/boot/dts/qcom/sdm450.dts
index b829b81..6cdf897 100644
--- a/arch/arm64/boot/dts/qcom/sdm450.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "sdm450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
/ {
model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 SOC";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
index 88aad0c..9acef75 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
@@ -146,6 +146,7 @@
qcom,chipid = <0x06010500>;
qcom,gpu-quirk-hfi-use-reg;
qcom,gpu-quirk-limit-uche-gbif-rw;
+ qcom,gpu-quirk-mmu-secure-cb-alt;
};
qcom,soc-hw-revision-1 {
@@ -506,6 +507,11 @@
gfx3d_secure: gfx3d_secure {
compatible = "qcom,smmu-kgsl-cb";
+ iommus = <&kgsl_smmu 2>;
+ };
+
+ gfx3d_secure_alt: gfx3d_secure_alt {
+ compatible = "qcom,smmu-kgsl-cb";
iommus = <&kgsl_smmu 2>, <&kgsl_smmu 1>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
index 007f937..a3f7b8e 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
@@ -831,7 +831,7 @@
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode = "reg_read";
qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
- qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
qcom,mdss-dsi-panel-status-value = <0x9c>;
qcom,mdss-dsi-panel-on-check-value = <0x9c>;
qcom,mdss-dsi-panel-status-read-length = <1>;
@@ -849,6 +849,18 @@
&dsi_hx8399_truly_cmd {
qcom,mdss-dsi-t-clk-post = <0x0E>;
qcom,mdss-dsi-t-clk-pre = <0x30>;
+ qcom,mdss-dsi-min-refresh-rate = <55>;
+ qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,mdss-dsi-pan-fps-update =
+ "dfps_immediate_porch_mode_vfp";
+ qcom,esd-check-enabled;
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
+ qcom,mdss-dsi-panel-status-read-length = <4>;
qcom,mdss-dsi-display-timings {
timing@0 {
qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 22 08
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi
new file mode 100644
index 0000000..d387f93
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-svr.dtsi
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ */
+
+&soc {
+ led_flash_rear: qcom,camera-flash@0 {
+ cell-index = <0>;
+ reg = <0x00 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+ torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+ switch-source = <&pmi8998_switch0>;
+ status = "ok";
+ };
+
+ led_flash_rear_aux: qcom,camera-flash@1 {
+ cell-index = <1>;
+ reg = <0x01 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+ torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+ switch-source = <&pmi8998_switch0>;
+ status = "ok";
+ };
+
+ led_flash_front: qcom,camera-flash@2 {
+ cell-index = <2>;
+ reg = <0x02 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pmi8998_flash2>;
+ torch-source = <&pmi8998_torch2>;
+ switch-source = <&pmi8998_switch1>;
+ status = "ok";
+ };
+
+ led_flash_iris: qcom,camera-flash@3 {
+ cell-index = <3>;
+ reg = <0x03 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pmi8998_flash2>;
+ torch-source = <&pmi8998_torch2>;
+ switch-source = <&pmi8998_switch2>;
+ status = "ok";
+ };
+
+ actuator_regulator: gpio-regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0x00 0x00>;
+ regulator-name = "actuator_regulator";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <100>;
+ enable-active-high;
+ gpio = <&tlmm 27 0>;
+ vin-supply = <&pmi8998_bob>;
+ };
+
+ camera_rear_ldo: gpio-regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <0x01 0x00>;
+ regulator-name = "camera_rear_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <135>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 12 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_rear_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+
+ camera_ldo: gpio-regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <0x02 0x00>;
+ regulator-name = "camera_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 9 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+};
+
+&cam_cci {
+ qcom,cam-res-mgr {
+ compatible = "qcom,cam-res-mgr";
+ status = "ok";
+ shared-gpios = <9>;
+ pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend";
+ pinctrl-0 = <&cam_res_mgr_active>;
+ pinctrl-1 = <&cam_res_mgr_suspend>;
+ };
+
+ actuator_rear: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ actuator_rear_aux: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ actuator_front: qcom,actuator@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,actuator";
+ cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ ois_rear: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ status = "ok";
+ };
+
+ eeprom_rear: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1050000 0 2800000>;
+ rgltr-max-voltage = <0 3600000 1050000 0 2800000>;
+ rgltr-load-current = <0 80000 105000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 80 0>,
+ <&tlmm 79 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-req-tbl-num = <0 1 2>;
+ gpio-req-tbl-flags = <1 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VANA0";
+ sensor-position = <0>;
+ sensor-mode = <0>;
+ cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ eeprom_rear_aux: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1050000 0 3312000 0 2800000>;
+ rgltr-max-voltage = <1050000 0 3600000 0 2800000>;
+ rgltr-load-current = <105000 0 80000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-req-tbl-num = <0 1 2>;
+ gpio-req-tbl-flags = <1 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ sensor-position = <0>;
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ eeprom_front: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1050000 0 2800000>;
+ rgltr-max-voltage = <0 3600000 1050000 0 2800000>;
+ rgltr-load-current = <0 80000 105000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 8 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-req-tbl-num = <0 1 2>;
+ gpio-req-tbl-flags = <1 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VANA2";
+ sensor-position = <1>;
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@0 {
+ cell-index = <0>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x0>;
+ csiphy-sd-index = <0>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ led-flash-src = <&led_flash_rear>;
+ actuator-src = <&actuator_rear>;
+ ois-src = <&ois_rear>;
+ eeprom-src = <&eeprom_rear>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&pm8998_l9>;
+ cam_vio-supply = <&pm8998_l8>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1704000 1200000>;
+ rgltr-max-voltage = <0 3600000 2928000 1248000>;
+ rgltr-load-current = <0 80000 105000 1200000>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 8 0>,
+ <&tlmm 115 0>,
+ <&tlmm 95 0 >,
+ <&tlmm 97 0>;
+ gpio-reset = <1>;
+ gpio-vio = <2>;
+ gpio-vana = <3>;
+ gpio-vdig = <4>;
+ gpio-req-tbl-num = <0 1 2 3 4>;
+ gpio-req-tbl-flags = <1 0 0 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VIO",
+ "CAM_VANA",
+ "CAM_VDIG";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ actuator-src = <&actuator_rear_aux>;
+ led-flash-src = <&led_flash_rear_aux>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1050000 0 3312000 0>;
+ rgltr-max-voltage = <1050000 0 3600000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-req-tbl-num = <0 1 2>;
+ gpio-req-tbl-flags = <1 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "disabled";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@2 {
+ cell-index = <2>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x02>;
+ csiphy-sd-index = <2>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <0>;
+ eeprom-src = <&eeprom_front>;
+ actuator-src = <&actuator_front>;
+ led-flash-src = <&led_flash_front>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&pm8998_lvs1>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1800000 0>;
+ rgltr-max-voltage = <0 3600000 1800000 0>;
+ rgltr-load-current = <0 80000 105000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 26 0>,
+ <&tlmm 132 0>,
+ <&tlmm 133 0>,
+ <&tlmm 90 0>,
+ <&tlmm 40 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-vdig = <3>;
+ gpio-vio = <4>;
+ gpio-standby = <5>;
+ gpio-req-tbl-num = <0 1 2 3 4 5>;
+ gpio-req-tbl-flags = <1 0 0 0 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET2",
+ "CAM_VANA2",
+ "CAM_VDIG2",
+ "CAM_VIO2",
+ "CAM_STANDBY2";
+ sensor-mode = <0>;
+ cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@3 {
+ cell-index = <3>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x03>;
+ csiphy-sd-index = <3>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <0>;
+ led-flash-src = <&led_flash_iris>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1050000 0>;
+ rgltr-max-voltage = <0 3600000 1050000 0>;
+ rgltr-load-current = <0 80000 105000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk3_active
+ &cam_sensor_iris_active>;
+ pinctrl-1 = <&cam_sensor_mclk3_suspend
+ &cam_sensor_iris_suspend>;
+ gpios = <&tlmm 16 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ gpio-reset = <1>;
+ gpio-vana = <2>;
+ gpio-req-tbl-num = <0 1 2>;
+ gpio-req-tbl-flags = <1 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK3",
+ "CAM_RESET3",
+ "CAM_VANA1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK3_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
index 1c7269a..d6be6d4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -72,6 +72,13 @@
ibb-supply = <&lcdb_ncp_vreg>;
};
+&dsi_dual_test_cmd_display {
+ /delete-property/ vddio-supply;
+ /delete-property/ lab-supply;
+ /delete-property/ ibb-supply;
+ /delete-property/ oled-vdda-supply;
+};
+
&sde_dp {
status = "disabled";
/delete-property/ vdda-1p2-supply;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index dd4e0b1..8b67649 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -28,6 +28,7 @@
#include "dsi-panel-nt35597-dualmipi-wqxga-video.dtsi"
#include "dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi"
#include "dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi"
+#include "dsi-panel-test-dualmipi-oled-cmd.dtsi"
#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
&soc {
@@ -476,6 +477,31 @@
ibb-supply = <&ibb_regulator>;
};
+ dsi_dual_test_cmd_display: qcom,dsi-display@17 {
+ compatible = "qcom,dsi-display";
+ label = "dsi_dual_test_cmd";
+ qcom,display-type = "primary";
+
+ qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+ qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+ clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+ <&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+ clock-names = "src_byte_clk", "src_pixel_clk";
+
+ pinctrl-names = "panel_active", "panel_suspend";
+ pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+ pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+
+ qcom,dsi-panel = <&dsi_dual_test_cmd>;
+ vddio-supply = <&pm8998_l14>;
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+ oled-vdda-supply = <&pm8998_l22>;
+ };
+
sde_wb: qcom,wb-display@0 {
compatible = "qcom,wb-display";
cell-index = <0>;
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f651cc0..4f4f1ae 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -324,6 +324,7 @@
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
CONFIG_QPNP_TYPEC=y
CONFIG_MSM_APM=y
@@ -358,8 +359,8 @@
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
@@ -435,6 +436,7 @@
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index e0e3cdc..50f3754 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -334,6 +334,7 @@
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
CONFIG_QPNP_TYPEC=y
CONFIG_MSM_APM=y
@@ -368,8 +369,8 @@
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
@@ -446,6 +447,7 @@
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 46d0448..88a4d1e 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -25,6 +25,7 @@
#include <asm/asm-offsets.h>
#include <asm/cpufeature.h>
+#include <asm/cputype.h>
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
#include <asm/ptrace.h>
@@ -452,4 +453,43 @@
mrs \rd, sp_el0
.endm
+/*
+ * Check the MIDR_EL1 of the current CPU for a given model and a range of
+ * variant/revision. See asm/cputype.h for the macros used below.
+ *
+ * model: MIDR_CPU_MODEL of CPU
+ * rv_min: Minimum of MIDR_CPU_VAR_REV()
+ * rv_max: Maximum of MIDR_CPU_VAR_REV()
+ * res: Result register.
+ * tmp1, tmp2, tmp3: Temporary registers
+ *
+ * Corrupts: res, tmp1, tmp2, tmp3
+ * Returns: 0, if the CPU id doesn't match. Non-zero otherwise
+ */
+ .macro cpu_midr_match model, rv_min, rv_max, res, tmp1, tmp2, tmp3
+ mrs \res, midr_el1
+ mov_q \tmp1, (MIDR_REVISION_MASK | MIDR_VARIANT_MASK)
+ mov_q \tmp2, MIDR_CPU_MODEL_MASK
+ and \tmp3, \res, \tmp2 // Extract model
+ and \tmp1, \res, \tmp1 // rev & variant
+ mov_q \tmp2, \model
+ cmp \tmp3, \tmp2
+ cset \res, eq
+ cbz \res, .Ldone\@ // Model matches ?
+
+ .if (\rv_min != 0) // Skip min check if rv_min == 0
+ mov_q \tmp3, \rv_min
+ cmp \tmp1, \tmp3
+ cset \res, ge
+ .endif // \rv_min != 0
+ /* Skip rv_max check if rv_min == rv_max && rv_min != 0 */
+ .if ((\rv_min != \rv_max) || \rv_min == 0)
+ mov_q \tmp2, \rv_max
+ cmp \tmp1, \tmp2
+ cset \tmp2, le
+ and \res, \res, \tmp2
+ .endif
+.Ldone\@:
+ .endm
+
#endif /* __ASM_ASSEMBLER_H */
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index ddbf3b1..c088c4f 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -56,6 +56,9 @@
(0xf << MIDR_ARCHITECTURE_SHIFT) | \
((partnum) << MIDR_PARTNUM_SHIFT))
+#define MIDR_CPU_VAR_REV(var, rev) \
+ (((var) << MIDR_VARIANT_SHIFT) | (rev))
+
#define MIDR_CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
MIDR_ARCHITECTURE_MASK)
@@ -79,7 +82,9 @@
#define ARM_CPU_PART_CORTEX_A53 0xD03
#define ARM_CPU_PART_CORTEX_A73 0xD09
#define ARM_CPU_PART_CORTEX_A75 0xD0A
+#define ARM_CPU_PART_KRYO3S 0x803
#define ARM_CPU_PART_KRYO3G 0x802
+#define ARM_CPU_PART_CORTEX_A55 0xD05
#define APM_CPU_PART_POTENZA 0x000
@@ -93,7 +98,9 @@
#define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
#define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75)
+#define MIDR_KRYO3S MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, ARM_CPU_PART_KRYO3S)
#define MIDR_KRYO3G MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, ARM_CPU_PART_KRYO3G)
+#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 653359b..c7b3ba68 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -180,8 +180,9 @@
/* Cortex-A57 r0p0 - r1p2 */
.desc = "ARM erratum 832075",
.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
- MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
- (1 << MIDR_VARIANT_SHIFT) | 2),
+ MIDR_RANGE(MIDR_CORTEX_A57,
+ MIDR_CPU_VAR_REV(0, 0),
+ MIDR_CPU_VAR_REV(1, 2)),
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_834220
@@ -189,8 +190,9 @@
/* Cortex-A57 r0p0 - r1p2 */
.desc = "ARM erratum 834220",
.capability = ARM64_WORKAROUND_834220,
- MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
- (1 << MIDR_VARIANT_SHIFT) | 2),
+ MIDR_RANGE(MIDR_CORTEX_A57,
+ MIDR_CPU_VAR_REV(0, 0),
+ MIDR_CPU_VAR_REV(1, 2)),
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_845719
@@ -214,8 +216,9 @@
/* Cavium ThunderX, T88 pass 1.x - 2.1 */
.desc = "Cavium erratum 27456",
.capability = ARM64_WORKAROUND_CAVIUM_27456,
- MIDR_RANGE(MIDR_THUNDERX, 0x00,
- (1 << MIDR_VARIANT_SHIFT) | 1),
+ MIDR_RANGE(MIDR_THUNDERX,
+ MIDR_CPU_VAR_REV(0, 0),
+ MIDR_CPU_VAR_REV(1, 1)),
},
{
/* Cavium ThunderX, T81 pass 1.0 */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 80ff3df5..5cf4c64 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -722,13 +722,11 @@
static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused)
{
u32 midr = read_cpuid_id();
- u32 rv_min, rv_max;
/* Cavium ThunderX pass 1.x and 2.x */
- rv_min = 0;
- rv_max = (1 << MIDR_VARIANT_SHIFT) | MIDR_REVISION_MASK;
-
- return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, rv_min, rv_max);
+ return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX,
+ MIDR_CPU_VAR_REV(0, 0),
+ MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK));
}
static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused)
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 28bedd7..2e69a14 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -293,6 +293,12 @@
cbz x9, 2f
cmp x9, #2
b.lt 1f
+#ifdef CONFIG_ARM64_ERRATUM_1024718
+ /* Disable hardware DBM on Kryo3S */
+ cpu_midr_match MIDR_KRYO3S, MIDR_CPU_VAR_REV(7, 12), \
+ MIDR_CPU_VAR_REV(7, 13), x1, x2, x3, x4
+ cbnz x1, 1f
+#endif
orr x10, x10, #TCR_HD // hardware Dirty flag update
1: orr x10, x10, #TCR_HA // hardware Access flag update
2:
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 0ee052b..70e8414 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -149,6 +149,32 @@
EXPORT_SYMBOL(drm_bridge_detach);
/**
+ * drm_bridge_connector_init - call bridge's connector_init callback to allow
+ * the bridge to update connector's behavior.
+ * @bridge: bridge control structure
+ * @connector: connector control structure
+ *
+ * Calls ->connector_init() &drm_bridge_funcs op for the bridge.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+int drm_bridge_connector_init(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ int ret = 0;
+
+ if (!bridge || !connector)
+ return -EINVAL;
+
+ if (bridge->funcs->connector_init)
+ ret = bridge->funcs->connector_init(bridge, connector);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_bridge_connector_init);
+
+/**
* DOC: bridge callbacks
*
* The &drm_bridge_funcs ops are populated by the bridge driver. The DRM
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
index 1fd10d9..fa80317 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -239,8 +239,7 @@
*
* return: error code in case of failure or 0 for success.
*/
-int dsi_display_clk_ctrl(void *handle,
- enum dsi_clk_type clk_type, enum dsi_clk_state clk_state);
+int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state);
/**
* dsi_clk_set_link_frequencies() - set frequencies for link clks
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
index 38eba8d..bff8627 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -1071,8 +1071,7 @@
DEFINE_MUTEX(dsi_mngr_clk_mutex);
-int dsi_display_clk_ctrl(void *handle,
- enum dsi_clk_type clk_type, enum dsi_clk_state clk_state)
+int dsi_display_clk_ctrl(void *handle, u32 clk_type, u32 clk_state)
{
int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 6fb7105..0113c83 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -401,6 +401,21 @@
return rc;
}
+bool dsi_ctrl_validate_host_state(struct dsi_ctrl *dsi_ctrl)
+{
+ struct dsi_ctrl_state_info *state = &dsi_ctrl->current_state;
+
+ if (!state) {
+ pr_err("Invalid host state for DSI controller\n");
+ return -EINVAL;
+ }
+
+ if (!state->host_initialized)
+ return true;
+
+ return false;
+}
+
static void dsi_ctrl_update_state(struct dsi_ctrl *dsi_ctrl,
enum dsi_ctrl_driver_ops op,
u32 op_state)
@@ -1072,10 +1087,10 @@
cmdbuf = (u8 *)(dsi_ctrl->vaddr);
+ msm_gem_sync(dsi_ctrl->tx_cmd_buf);
for (cnt = 0; cnt < length; cnt++)
cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt];
- msm_gem_sync(dsi_ctrl->tx_cmd_buf);
dsi_ctrl->cmd_len += length;
if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) {
@@ -3294,6 +3309,25 @@
return misr;
}
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl)
+{
+ if (!dsi_ctrl || !dsi_ctrl->hw.ops.error_intr_ctrl
+ || !dsi_ctrl->hw.ops.clear_error_status) {
+ pr_err("Invalid params\n");
+ return;
+ }
+
+ /*
+ * Mask DSI error status interrupts and clear error status
+ * register
+ */
+ mutex_lock(&dsi_ctrl->ctrl_lock);
+ dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false);
+ dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
+ DSI_ERROR_INTERRUPT_COUNT);
+ mutex_unlock(&dsi_ctrl->ctrl_lock);
+}
+
/**
* dsi_ctrl_irq_update() - Put a irq vote to process DSI error
* interrupts at any time.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 537bdc3..9636dbe 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -549,6 +549,16 @@
enum dsi_engine_state state);
/**
+ * dsi_ctrl_validate_host_state() - validate DSI ctrl host state
+ * @dsi_ctrl: DSI Controller handle.
+ *
+ * Validate DSI cotroller host state
+ *
+ * Return: boolean indicating whether host is not initalized.
+ */
+bool dsi_ctrl_validate_host_state(struct dsi_ctrl *dsi_ctrl);
+
+/**
* dsi_ctrl_set_vid_engine_state() - set video engine state
* @dsi_ctrl: DSI Controller handle.
* @state: Engine state.
@@ -713,6 +723,13 @@
void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable);
/**
+ * dsi_ctrl_mask_error_status_interrupts() - API to mask dsi ctrl error status
+ * interrupts
+ * @dsi_ctrl: DSI controller handle.
+ */
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl);
+
+/**
* dsi_ctrl_irq_update() - Put a irq vote to process DSI error
* interrupts at any time.
* @dsi_ctrl: DSI controller handle.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c8edb09..fd18905 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/err.h>
#include "msm_drv.h"
@@ -51,6 +52,40 @@
static struct dsi_display *main_display;
+static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display)
+{
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ if (!display)
+ return;
+
+ for (i = 0; (i < display->ctrl_count) &&
+ (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+ ctrl = &display->ctrl[i];
+ if (!ctrl)
+ continue;
+ dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl);
+ }
+}
+
+static void dsi_display_ctrl_irq_update(struct dsi_display *display, bool en)
+{
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ if (!display)
+ return;
+
+ for (i = 0; (i < display->ctrl_count) &&
+ (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+ ctrl = &display->ctrl[i];
+ if (!ctrl)
+ continue;
+ dsi_ctrl_irq_update(ctrl->ctrl, en);
+ }
+}
+
void dsi_rect_intersect(const struct dsi_rect *r1,
const struct dsi_rect *r2,
struct dsi_rect *result)
@@ -88,8 +123,11 @@
panel = dsi_display->panel;
- if (!dsi_panel_initialized(panel))
- return -EINVAL;
+ mutex_lock(&panel->panel_lock);
+ if (!dsi_panel_initialized(panel)) {
+ rc = -EINVAL;
+ goto error;
+ }
panel->bl_config.bl_level = bl_lvl;
@@ -124,6 +162,7 @@
}
error:
+ mutex_unlock(&panel->panel_lock);
return rc;
}
@@ -390,9 +429,17 @@
struct dsi_cmd_desc *cmds;
u32 flags = 0;
- if (!panel)
+ if (!panel || !ctrl || !ctrl->ctrl)
return -EINVAL;
+ /*
+ * When DSI controller is not in initialized state, we do not want to
+ * report a false ESD failure and hence we defer until next read
+ * happen.
+ */
+ if (dsi_ctrl_validate_host_state(ctrl->ctrl))
+ return 1;
+
/* acquire panel_lock to make sure no commands are in progress */
dsi_panel_acquire_panel_lock(panel);
@@ -497,6 +544,11 @@
}
}
exit:
+ if (rc <= 0) {
+ dsi_display_ctrl_irq_update(display, false);
+ dsi_display_mask_ctrl_error_interrupts(display);
+ }
+
dsi_display_cmd_engine_disable(display);
done:
return rc;
@@ -865,6 +917,62 @@
return rc;
}
+static ssize_t debugfs_esd_trigger_check(struct file *file,
+ const char __user *user_buf,
+ size_t user_len,
+ loff_t *ppos)
+{
+ struct dsi_display *display = file->private_data;
+ char *buf;
+ int rc = 0;
+ u32 esd_trigger;
+
+ if (!display)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ if (user_len > sizeof(u32))
+ return -EINVAL;
+
+ buf = kzalloc(user_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, user_buf, user_len)) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ buf[user_len] = '\0'; /* terminate the string */
+
+ if (kstrtouint(buf, 10, &esd_trigger)) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (esd_trigger != 1) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ display->esd_trigger = esd_trigger;
+
+ if (display->esd_trigger) {
+ rc = dsi_panel_trigger_esd_attack(display->panel);
+ if (rc) {
+ pr_err("Failed to trigger ESD attack\n");
+ return rc;
+ }
+ }
+
+ rc = user_len;
+error:
+ kfree(buf);
+ return rc;
+}
+
static ssize_t debugfs_misr_read(struct file *file,
char __user *user_buf,
size_t user_len,
@@ -941,6 +1049,11 @@
.write = debugfs_misr_setup,
};
+static const struct file_operations esd_trigger_fops = {
+ .open = simple_open,
+ .write = debugfs_esd_trigger_check,
+};
+
static int dsi_display_debugfs_init(struct dsi_display *display)
{
int rc = 0;
@@ -968,6 +1081,18 @@
goto error_remove_dir;
}
+ dump_file = debugfs_create_file("esd_trigger",
+ 0644,
+ dir,
+ display,
+ &esd_trigger_fops);
+ if (IS_ERR_OR_NULL(dump_file)) {
+ rc = PTR_ERR(dump_file);
+ pr_err("[%s] debugfs for esd trigger file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
misr_data = debugfs_create_file("misr_data",
0600,
dir,
@@ -2162,15 +2287,111 @@
return rc;
}
+/* initialize dsi_panel using ext bridge's setting */
+static int dsi_display_populate_ext_bridge_config(struct dsi_display *display,
+ struct mipi_dsi_device *dsi)
+{
+ struct dsi_panel *panel = display->panel;
+
+ if (!panel) {
+ pr_err("Invalid param\n");
+ return -EINVAL;
+ }
+
+ pr_debug("DSI[%s]: channel=%d, lanes=%d, format=%d, mode_flags=%lx\n",
+ dsi->name, dsi->channel, dsi->lanes,
+ dsi->format, dsi->mode_flags);
+
+ panel->host_config.data_lanes = 0;
+ if (dsi->lanes > 0)
+ panel->host_config.data_lanes |= DSI_DATA_LANE_0;
+ if (dsi->lanes > 1)
+ panel->host_config.data_lanes |= DSI_DATA_LANE_1;
+ if (dsi->lanes > 2)
+ panel->host_config.data_lanes |= DSI_DATA_LANE_2;
+ if (dsi->lanes > 3)
+ panel->host_config.data_lanes |= DSI_DATA_LANE_3;
+
+ switch (dsi->format) {
+ case MIPI_DSI_FMT_RGB888:
+ panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB888;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+ panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB666_LOOSE;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+ panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB666;
+ break;
+ case MIPI_DSI_FMT_RGB565:
+ default:
+ panel->host_config.dst_format = DSI_PIXEL_FORMAT_RGB565;
+ break;
+ }
+
+ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ panel->panel_mode = DSI_OP_VIDEO_MODE;
+
+ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ panel->video_config.traffic_mode =
+ DSI_VIDEO_TRAFFIC_BURST_MODE;
+ else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+ panel->video_config.traffic_mode =
+ DSI_VIDEO_TRAFFIC_SYNC_PULSES;
+ else
+ panel->video_config.traffic_mode =
+ DSI_VIDEO_TRAFFIC_SYNC_START_EVENTS;
+
+ panel->video_config.hsa_lp11_en =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSA;
+ panel->video_config.hbp_lp11_en =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HBP;
+ panel->video_config.hfp_lp11_en =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HFP;
+ panel->video_config.pulse_mode_hsa_he =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE;
+ panel->video_config.bllp_lp11_en =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BLLP;
+ panel->video_config.eof_bllp_lp11_en =
+ dsi->mode_flags & MIPI_DSI_MODE_VIDEO_EOF_BLLP;
+ } else {
+ panel->panel_mode = DSI_OP_CMD_MODE;
+ pr_err("command mode not supported by ext bridge\n");
+ return -ENOTSUPP;
+ }
+
+ /* TODO: add calc for these 2 values */
+ panel->host_config.t_clk_post = 0x03;
+ panel->host_config.t_clk_pre = 0x24;
+
+ panel->bl_config.type = DSI_BACKLIGHT_UNKNOWN;
+
+ return 0;
+}
+
static int dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi)
{
- return 0;
+ struct dsi_display *display = to_dsi_display(host);
+ int ret = 0;
+
+ if (!host || !dsi) {
+ pr_err("Invalid param\n");
+ return -EINVAL;
+ }
+
+ pr_debug("host attach\n");
+
+ if (dsi_display_has_ext_bridge(display))
+ ret = dsi_display_populate_ext_bridge_config(display, dsi);
+
+ return ret;
}
+
static int dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi)
{
+ pr_debug("host detach\n");
return 0;
}
@@ -2468,23 +2689,6 @@
}
}
-static void dsi_display_ctrl_irq_update(struct dsi_display *display, bool en)
-{
- int i;
- struct dsi_display_ctrl *ctrl;
-
- if (!display)
- return;
-
- for (i = 0; (i < display->ctrl_count) &&
- (i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
- ctrl = &display->ctrl[i];
- if (!ctrl)
- continue;
- dsi_ctrl_irq_update(ctrl->ctrl, en);
- }
-}
-
int dsi_pre_clkoff_cb(void *priv,
enum dsi_clk_type clk,
enum dsi_clk_state new_state)
@@ -2847,11 +3051,31 @@
of_node = of_parse_phandle(display->pdev->dev.of_node,
"qcom,dsi-panel", 0);
if (!of_node) {
- pr_err("No Panel device present\n");
- rc = -ENODEV;
- goto error;
+ struct device_node *endpoint;
+
+ endpoint = of_graph_get_next_endpoint(
+ display->pdev->dev.of_node, NULL);
+ if (!endpoint) {
+ pr_err("no endpoint for ext bridge\n");
+ rc = -ENODEV;
+ goto error;
+ }
+
+ of_node = of_graph_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
+ if (!of_node) {
+ pr_err("no valid ext bridge\n");
+ rc = -ENODEV;
+ goto error;
+ }
+ of_node_put(of_node);
+
+ display->panel_of = of_node;
+ /* TODO: split support */
+ display->type = DSI_DISPLAY_EXT_BRIDGE;
} else {
display->panel_of = of_node;
+ display->type = DSI_DISPLAY_SINGLE;
}
error:
@@ -2863,6 +3087,8 @@
int rc = 0;
int i;
struct dsi_display_ctrl *ctrl;
+ enum dsi_panel_type panel_type =
+ dsi_display_has_ext_bridge(display) ? EXT_BRIDGE : DSI_PANEL;
for (i = 0; i < display->ctrl_count; i++) {
ctrl = &display->ctrl[i];
@@ -2885,7 +3111,8 @@
}
display->panel = dsi_panel_get(&display->pdev->dev, display->panel_of,
- display->cmdline_topology);
+ display->cmdline_topology, panel_type);
+
if (IS_ERR_OR_NULL(display->panel)) {
rc = PTR_ERR(display->panel);
pr_err("failed to get panel, rc=%d\n", rc);
@@ -3300,9 +3527,9 @@
struct dsi_display_mode_priv_info *priv_info;
priv_info = mode->priv_info;
- if (!priv_info) {
+ if (!dsi_display_has_ext_bridge(display) && !priv_info) {
pr_err("[%s] failed to get private info of the display mode",
- display->name);
+ display->name);
return -EINVAL;
}
@@ -3339,7 +3566,8 @@
}
}
- if (priv_info->phy_timing_len) {
+ /* ext bridge calculates these timing params by phy driver */
+ if (priv_info && priv_info->phy_timing_len) {
for (i = 0; i < display->ctrl_count; i++) {
ctrl = &display->ctrl[i];
rc = dsi_phy_set_timing_params(ctrl->phy,
@@ -3424,6 +3652,12 @@
{
int rc = 0;
+ /* Continuous splash not supported by external bridge */
+ if (dsi_display_has_ext_bridge(display)) {
+ display->is_cont_splash_enabled = false;
+ return 0;
+ }
+
/* Vote for gdsc required to read register address space */
display->cont_splash_client = sde_power_client_create(display->phandle,
@@ -3436,7 +3670,9 @@
return -EINVAL;
}
- /* Verify whether continuous splash is enabled or not */
+ /*
+ * Verify whether continuous splash is enabled or not.
+ */
display->is_cont_splash_enabled =
dsi_display_get_cont_splash_status(display);
if (!display->is_cont_splash_enabled) {
@@ -4029,7 +4265,7 @@
}
if (display->bridge) {
- pr_err("display is already initialize\n");
+ pr_err("display is already initialized\n");
goto error;
}
@@ -4048,6 +4284,56 @@
return rc;
}
+int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
+ struct drm_encoder *enc, struct drm_connector *connector)
+{
+ int rc = 0;
+ struct drm_bridge *ext_bridge;
+ struct msm_drm_private *priv = NULL;
+
+ if (!display || !display->drm_dev || !enc) {
+ pr_err("invalid param(s)\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&display->display_lock);
+ priv = display->drm_dev->dev_private;
+
+ if (!priv) {
+ pr_err("Private data is not present\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (!display->bridge) {
+ pr_err("dsi bridge is not initialize\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ ext_bridge = of_drm_find_bridge(display->panel_of);
+ if (!ext_bridge) {
+ pr_err("ext brige not found\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ /* update connector ops in ext bridge */
+ drm_bridge_connector_init(ext_bridge, connector);
+
+ /* insert ext bridge to the bridge chain */
+ display->bridge->base.next = ext_bridge;
+ ext_bridge->encoder = enc;
+ priv->bridges[priv->num_bridges++] = ext_bridge;
+
+ drm_bridge_attach(display->drm_dev, ext_bridge);
+
+error:
+ mutex_unlock(&display->display_lock);
+ return rc;
+
+}
+
int dsi_display_drm_bridge_deinit(struct dsi_display *display)
{
int rc = 0;
@@ -4127,6 +4413,44 @@
return rc;
}
+int dsi_display_ext_bridge_get_info(struct msm_display_info *info, void *disp)
+{
+ struct dsi_display *display;
+ int i;
+
+ if (!info || !disp) {
+ pr_err("invalid params\n");
+ return -EINVAL;
+ }
+
+ display = disp;
+ if (!display->panel) {
+ pr_err("invalid display panel\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&display->display_lock);
+
+ memset(info, 0, sizeof(struct msm_display_info));
+
+ info->intf_type = DRM_MODE_CONNECTOR_DSI;
+ info->num_of_h_tiles = display->ctrl_count;
+ for (i = 0; i < info->num_of_h_tiles; i++)
+ info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index;
+
+ /*
+ * TODO: these info need come from ext bridge.
+ * using drm_connector->status, connector->polled.
+ */
+ info->is_connected = true;
+ info->is_primary = true;
+ info->capabilities |= (MSM_DISPLAY_CAP_VID_MODE |
+ MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_HOT_PLUG);
+
+ mutex_unlock(&display->display_lock);
+ return 0;
+}
+
static int dsi_display_get_mode_count_no_lock(struct dsi_display *display,
u32 *count)
{
@@ -4851,12 +5175,15 @@
mode = display->panel->cur_mode;
if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
+ if (display->is_cont_splash_enabled) {
+ pr_err("DMS is not supposed to be set on first frame\n");
+ return -EINVAL;
+ }
/* update dsi ctrl for new mode */
rc = dsi_display_pre_switch(display);
if (rc)
pr_err("[%s] panel pre-prepare-res-switch failed, rc=%d\n",
- display->name, rc);
-
+ display->name, rc);
goto error;
}
@@ -4990,6 +5317,9 @@
struct dsi_rect req_roi = { 0 };
int rc = 0;
+ if (dsi_display_has_ext_bridge(display))
+ return 0;
+
cur_mode = display->panel->cur_mode;
if (!cur_mode)
return 0;
@@ -5043,6 +5373,9 @@
if (!display || !rois || !display->panel)
return -EINVAL;
+ if (dsi_display_has_ext_bridge(display))
+ return 0;
+
cur_mode = display->panel->cur_mode;
if (!cur_mode)
return 0;
@@ -5197,7 +5530,7 @@
}
}
- if (mode->priv_info->dsc_enabled) {
+ if (mode->priv_info && mode->priv_info->dsc_enabled) {
mode->priv_info->dsc.pic_width *= display->ctrl_count;
rc = dsi_panel_update_pps(display->panel);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 4cfd4a9..53004e4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation.All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation.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 version 2 and
@@ -160,6 +160,7 @@
* @root: Debugfs root directory
* @misr_enable Frame MISR enable/disable
* @misr_frame_count Number of frames to accumulate the MISR value
+ * @esd_trigger field indicating ESD trigger through debugfs
*/
struct dsi_display {
struct platform_device *pdev;
@@ -218,6 +219,7 @@
bool misr_enable;
u32 misr_frame_count;
+ u32 esd_trigger;
/* multiple dsi error handlers */
struct workqueue_struct *err_workq;
struct work_struct fifo_underflow_work;
@@ -225,6 +227,18 @@
struct work_struct lp_rx_timeout_work;
};
+/**
+ * dsi_display_has_ext_bridge() - check whether display has ext bridge
+ * connected.
+ *
+ * Return: True - ext bridge, False - no ext bridge.
+ */
+static inline bool dsi_display_has_ext_bridge(const struct dsi_display *display)
+{
+ return display->type == DSI_DISPLAY_EXT_BRIDGE ||
+ display->type == DSI_DISPLAY_SPLIT_EXT_BRIDGE;
+}
+
int dsi_display_dev_probe(struct platform_device *pdev);
int dsi_display_dev_remove(struct platform_device *pdev);
@@ -288,6 +302,19 @@
int dsi_display_drm_bridge_deinit(struct dsi_display *display);
/**
+ * dsi_display_drm_ext_bridge_init() - initializes DRM bridge for ext bridge
+ * @display: Handle to the display.
+ * @enc: Pointer to the encoder object which is connected to the
+ * display.
+ * @connector: Pointer to the connector object which is connected to
+ * the display.
+ *
+ * Return: error code.
+ */
+int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
+ struct drm_encoder *enc, struct drm_connector *connector);
+
+/**
* dsi_display_get_info() - returns the display properties
* @info: Pointer to the structure where info is stored.
* @disp: Handle to the display.
@@ -297,6 +324,15 @@
int dsi_display_get_info(struct msm_display_info *info, void *disp);
/**
+ * dsi_display_ext_bridge_get_info() - returns the ext bridge's display info
+ * @info: Pointer to the structure where info is stored.
+ * @disp: Handle to the display.
+ *
+ * Return: error code.
+ */
+int dsi_display_ext_bridge_get_info(struct msm_display_info *info, void *disp);
+
+/**
* dsi_display_get_mode_count() - get number of modes supported by the display
* @display: Handle to display.
* @count: Number of modes supported
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index a1e4685..5b47865 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -63,6 +63,11 @@
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_DMS;
if (msm_is_mode_seamless_vrr(drm_mode))
dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
+
+ dsi_mode->timing.h_sync_polarity =
+ !!(drm_mode->flags & DRM_MODE_FLAG_PHSYNC);
+ dsi_mode->timing.v_sync_polarity =
+ !!(drm_mode->flags & DRM_MODE_FLAG_PVSYNC);
}
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
@@ -101,6 +106,11 @@
if (dsi_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR)
drm_mode->private_flags |= MSM_MODE_FLAG_SEAMLESS_VRR;
+ if (dsi_mode->timing.h_sync_polarity)
+ drm_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ if (dsi_mode->timing.v_sync_polarity)
+ drm_mode->flags |= DRM_MODE_FLAG_PVSYNC;
+
drm_mode_set_name(drm_mode);
}
@@ -288,17 +298,23 @@
convert_to_dsi_mode(mode, &dsi_mode);
- /*
- * retrieve dsi mode from dsi driver's cache since not safe to take
- * the drm mode config mutex in all paths
- */
- rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode);
- if (rc)
- return rc;
+ /* external bridge doesn't use priv_info and dsi_mode_flags */
+ if (!dsi_display_has_ext_bridge(display)) {
+ /*
+ * retrieve dsi mode from dsi driver's cache since not safe to
+ * take the drm mode config mutex in all paths
+ */
+ rc = dsi_display_find_mode(display, &dsi_mode, &panel_dsi_mode);
+ if (rc)
+ return rc;
- /* propagate the private info to the adjusted_mode derived dsi mode */
- dsi_mode.priv_info = panel_dsi_mode->priv_info;
- dsi_mode.dsi_mode_flags = panel_dsi_mode->dsi_mode_flags;
+ /*
+ * propagate the private info to the adjusted_mode derived dsi
+ * mode
+ */
+ dsi_mode.priv_info = panel_dsi_mode->priv_info;
+ dsi_mode.dsi_mode_flags = panel_dsi_mode->dsi_mode_flags;
+ }
rc = dsi_display_validate_mode(c_bridge->display, &dsi_mode,
DSI_VALIDATE_FLAG_ALLOW_ADJUST);
@@ -377,6 +393,35 @@
return 0;
}
+int dsi_conn_ext_bridge_get_mode_info(const struct drm_display_mode *drm_mode,
+ struct msm_mode_info *mode_info,
+ u32 max_mixer_width, void *display)
+{
+ struct msm_display_topology *topology;
+ struct dsi_display_mode dsi_mode;
+ struct dsi_mode_info *timing;
+
+ if (!drm_mode || !mode_info)
+ return -EINVAL;
+
+ convert_to_dsi_mode(drm_mode, &dsi_mode);
+
+ memset(mode_info, 0, sizeof(*mode_info));
+
+ timing = &dsi_mode.timing;
+ mode_info->frame_rate = dsi_mode.timing.refresh_rate;
+ mode_info->vtotal = DSI_V_TOTAL(timing);
+
+ topology = &mode_info->topology;
+ topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ? 2 : 1;
+ topology->num_enc = 0;
+ topology->num_intf = topology->num_lm;
+
+ mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
+
+ return 0;
+}
+
static const struct drm_bridge_funcs dsi_bridge_ops = {
.attach = dsi_bridge_attach,
.mode_fixup = dsi_bridge_mode_fixup,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
index ec58479..2bad8c0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -86,6 +86,18 @@
void *display);
/**
+ * dsi_conn_ext_bridge_get_mode_info - retrieve information on the mode selected
+ * @drm_mode: Display mode set for the display
+ * @mode_info: Out parameter. information of the mode.
+ * @max_mixer_width: max width supported by HW layer mixer
+ * @display: Pointer to private display structure
+ * Returns: Zero on success
+ */
+int dsi_conn_ext_bridge_get_mode_info(const struct drm_display_mode *drm_mode,
+ struct msm_mode_info *mode_info, u32 max_mixer_width,
+ void *display);
+
+/**
* dsi_conn_mode_valid - callback to determine if specified mode is valid
* @connector: Pointer to drm connector structure
* @mode: Pointer to drm mode structure
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index eaeeb52..d8b90e3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -32,6 +32,7 @@
#define MAX_TOPOLOGY 5
#define DSI_PANEL_DEFAULT_LABEL "Default dsi panel"
+#define EXT_BRIDGE_DEFAULT_LABEL "Default ext bridge"
#define DEFAULT_MDP_TRANSFER_TIME 14000
@@ -321,6 +322,30 @@
return rc;
}
+int dsi_panel_trigger_esd_attack(struct dsi_panel *panel)
+{
+ struct dsi_panel_reset_config *r_config;
+
+ if (!panel) {
+ pr_err("Invalid panel param\n");
+ return -EINVAL;
+ }
+
+ r_config = &panel->reset_config;
+ if (!r_config) {
+ pr_err("Invalid panel reset configuration\n");
+ return -EINVAL;
+ }
+
+ if (gpio_is_valid(r_config->reset_gpio)) {
+ gpio_set_value(r_config->reset_gpio, 0);
+ pr_info("GPIO pulled low to simulate ESD\n");
+ return 0;
+ }
+ pr_err("failed to pull down gpio\n");
+ return -EINVAL;
+}
+
static int dsi_panel_reset(struct dsi_panel *panel)
{
int rc = 0;
@@ -480,6 +505,9 @@
if (!panel || !panel->cur_mode)
return -EINVAL;
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mode = panel->cur_mode;
cmds = mode->priv_info->cmd_sets[type].cmds;
@@ -610,13 +638,10 @@
dsi = &panel->mipi_device;
- mutex_lock(&panel->panel_lock);
-
rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl);
if (rc < 0)
pr_err("failed to update dcs backlight:%d\n", bl_lvl);
- mutex_unlock(&panel->panel_lock);
return rc;
}
@@ -625,13 +650,16 @@
int rc = 0;
struct dsi_backlight_config *bl = &panel->bl_config;
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
pr_debug("backlight type:%d lvl:%d\n", bl->type, bl_lvl);
switch (bl->type) {
case DSI_BACKLIGHT_WLED:
led_trigger_event(bl->wled, bl_lvl);
break;
case DSI_BACKLIGHT_DCS:
- dsi_panel_update_backlight(panel, bl_lvl);
+ rc = dsi_panel_update_backlight(panel, bl_lvl);
break;
default:
pr_err("Backlight type(%d) not supported\n", bl->type);
@@ -2713,7 +2741,8 @@
struct dsi_panel *dsi_panel_get(struct device *parent,
struct device_node *of_node,
- int topology_override)
+ int topology_override,
+ enum dsi_panel_type type)
{
struct dsi_panel *panel;
int rc = 0;
@@ -2722,68 +2751,85 @@
if (!panel)
return ERR_PTR(-ENOMEM);
- panel->name = of_get_property(of_node, "qcom,mdss-dsi-panel-name",
- NULL);
- if (!panel->name)
- panel->name = DSI_PANEL_DEFAULT_LABEL;
+ if (type == DSI_PANEL) {
+ panel->name = of_get_property(of_node,
+ "qcom,mdss-dsi-panel-name", NULL);
+ if (!panel->name)
+ panel->name = DSI_PANEL_DEFAULT_LABEL;
- rc = dsi_panel_parse_host_config(panel, of_node);
- if (rc) {
- pr_err("failed to parse host configuration, rc=%d\n", rc);
+ rc = dsi_panel_parse_host_config(panel, of_node);
+ if (rc) {
+ pr_err("failed to parse host configuration, rc=%d\n",
+ rc);
+ goto error;
+ }
+
+ rc = dsi_panel_parse_panel_mode(panel, of_node);
+ if (rc) {
+ pr_err("failed to parse panel mode configuration, rc=%d\n",
+ rc);
+ goto error;
+ }
+
+ rc = dsi_panel_parse_dfps_caps(&panel->dfps_caps,
+ of_node, panel->name);
+ if (rc)
+ pr_err("failed to parse dfps configuration, rc=%d\n",
+ rc);
+
+ rc = dsi_panel_parse_phy_props(&panel->phy_props,
+ of_node, panel->name);
+ if (rc) {
+ pr_err("failed to parse panel physical dimension, rc=%d\n",
+ rc);
+ goto error;
+ }
+
+ rc = dsi_panel_parse_power_cfg(parent, panel, of_node);
+ if (rc)
+ pr_err("failed to parse power config, rc=%d\n", rc);
+
+ rc = dsi_panel_parse_gpios(panel, of_node);
+ if (rc)
+ pr_err("failed to parse panel gpios, rc=%d\n", rc);
+
+ rc = dsi_panel_parse_bl_config(panel, of_node);
+ if (rc)
+ pr_err("failed to parse backlight config, rc=%d\n", rc);
+
+
+ rc = dsi_panel_parse_misc_features(panel, of_node);
+ if (rc)
+ pr_err("failed to parse misc features, rc=%d\n", rc);
+
+ rc = dsi_panel_parse_hdr_config(panel, of_node);
+ if (rc)
+ pr_err("failed to parse hdr config, rc=%d\n", rc);
+
+ rc = dsi_panel_get_mode_count(panel, of_node);
+ if (rc) {
+ pr_err("failed to get mode count, rc=%d\n", rc);
+ goto error;
+ }
+
+ rc = dsi_panel_parse_dms_info(panel, of_node);
+ if (rc)
+ pr_debug("failed to get dms info, rc=%d\n", rc);
+
+ rc = dsi_panel_parse_esd_config(panel, of_node);
+ if (rc)
+ pr_debug("failed to parse esd config, rc=%d\n", rc);
+
+ panel->type = DSI_PANEL;
+ } else if (type == EXT_BRIDGE) {
+ panel->name = EXT_BRIDGE_DEFAULT_LABEL;
+ panel->type = EXT_BRIDGE;
+ } else {
+ pr_err("invalid panel type\n");
+ rc = -ENOTSUPP;
goto error;
}
- rc = dsi_panel_parse_panel_mode(panel, of_node);
- if (rc) {
- pr_err("failed to parse panel mode configuration, rc=%d\n", rc);
- goto error;
- }
-
- rc = dsi_panel_parse_dfps_caps(&panel->dfps_caps, of_node, panel->name);
- if (rc)
- pr_err("failed to parse dfps configuration, rc=%d\n", rc);
-
- rc = dsi_panel_parse_phy_props(&panel->phy_props, of_node, panel->name);
- if (rc) {
- pr_err("failed to parse panel physical dimension, rc=%d\n", rc);
- goto error;
- }
-
- rc = dsi_panel_parse_power_cfg(parent, panel, of_node);
- if (rc)
- pr_err("failed to parse power config, rc=%d\n", rc);
-
- rc = dsi_panel_parse_gpios(panel, of_node);
- if (rc)
- pr_err("failed to parse panel gpios, rc=%d\n", rc);
-
- rc = dsi_panel_parse_bl_config(panel, of_node);
- if (rc)
- pr_err("failed to parse backlight config, rc=%d\n", rc);
-
-
- rc = dsi_panel_parse_misc_features(panel, of_node);
- if (rc)
- pr_err("failed to parse misc features, rc=%d\n", rc);
-
- rc = dsi_panel_parse_hdr_config(panel, of_node);
- if (rc)
- pr_err("failed to parse hdr config, rc=%d\n", rc);
-
- rc = dsi_panel_get_mode_count(panel, of_node);
- if (rc) {
- pr_err("failed to get mode count, rc=%d\n", rc);
- goto error;
- }
-
- rc = dsi_panel_parse_dms_info(panel, of_node);
- if (rc)
- pr_debug("failed to get dms info, rc=%d\n", rc);
-
- rc = dsi_panel_parse_esd_config(panel, of_node);
- if (rc)
- pr_debug("failed to parse esd config, rc=%d\n", rc);
-
panel->panel_of_node = of_node;
drm_panel_init(&panel->drm_panel);
mutex_init(&panel->panel_lock);
@@ -2797,7 +2843,8 @@
void dsi_panel_put(struct dsi_panel *panel)
{
/* free resources allocated for ESD check */
- dsi_panel_esd_config_deinit(&panel->esd_config);
+ if (panel->type == DSI_PANEL)
+ dsi_panel_esd_config_deinit(&panel->esd_config);
kfree(panel);
}
@@ -2813,6 +2860,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
dev = &panel->mipi_device;
@@ -2877,6 +2927,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_bl_unregister(panel);
@@ -3005,6 +3058,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
mode->priv_info = kzalloc(sizeof(*mode->priv_info), GFP_KERNEL);
@@ -3112,10 +3168,12 @@
memcpy(&config->video_timing, &mode->timing,
sizeof(config->video_timing));
- config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled;
- config->video_timing.dsc = &mode->priv_info->dsc;
- config->bit_clk_rate_hz = mode->priv_info->clk_rate_hz;
+ if (mode->priv_info) {
+ config->video_timing.dsc_enabled = mode->priv_info->dsc_enabled;
+ config->video_timing.dsc = &mode->priv_info->dsc;
+ config->bit_clk_rate_hz = mode->priv_info->clk_rate_hz;
+ }
config->esc_clk_rate_hz = 19200000;
mutex_unlock(&panel->panel_lock);
return rc;
@@ -3130,6 +3188,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
/* If LP11_INIT is set, panel will be powered up during prepare() */
@@ -3158,6 +3219,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
priv_info = panel->cur_mode->priv_info;
@@ -3193,6 +3257,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP1);
if (rc)
@@ -3211,6 +3278,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP2);
if (rc)
@@ -3229,6 +3299,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP);
if (rc)
@@ -3247,6 +3320,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
if (panel->lp11_init) {
@@ -3357,6 +3433,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
priv_info = panel->cur_mode->priv_info;
set = &priv_info->cmd_sets[DSI_CMD_SET_ROI];
@@ -3392,6 +3471,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_TIMING_SWITCH);
@@ -3412,6 +3494,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_TIMING_SWITCH);
@@ -3432,6 +3517,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ON);
@@ -3453,6 +3541,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_ON);
@@ -3475,6 +3566,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_PRE_OFF);
@@ -3498,6 +3592,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
@@ -3522,6 +3619,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_POST_OFF);
@@ -3553,6 +3653,9 @@
return -EINVAL;
}
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
mutex_lock(&panel->panel_lock);
if (!panel->lp11_init) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index 06199f4..3b226b0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. 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 version 2 and
@@ -140,8 +140,15 @@
u32 groups;
};
+enum dsi_panel_type {
+ DSI_PANEL = 0,
+ EXT_BRIDGE,
+ DSI_PANEL_TYPE_MAX,
+};
+
struct dsi_panel {
const char *name;
+ enum dsi_panel_type type;
struct device_node *panel_of_node;
struct mipi_dsi_device mipi_device;
@@ -204,7 +211,10 @@
struct dsi_panel *dsi_panel_get(struct device *parent,
struct device_node *of_node,
- int topology_override);
+ int topology_override,
+ enum dsi_panel_type type);
+
+int dsi_panel_trigger_esd_attack(struct dsi_panel *panel);
void dsi_panel_put(struct dsi_panel *panel);
@@ -269,4 +279,10 @@
void dsi_dsc_pclk_param_calc(struct msm_display_dsc_info *dsc, int intf_width);
+struct dsi_panel *dsi_panel_ext_bridge_get(struct device *parent,
+ struct device_node *of_node,
+ int topology_override);
+
+void dsi_panel_ext_bridge_put(struct dsi_panel *panel);
+
#endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 655390b..21b67d9 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -68,6 +68,7 @@
struct sde_connector *c_conn;
int bl_lvl;
struct drm_event event;
+ int rc = 0;
brightness = bd->props.brightness;
@@ -93,10 +94,10 @@
event.length = sizeof(u32);
msm_mode_object_event_notify(&c_conn->base.base,
c_conn->base.dev, &event, (u8 *)&brightness);
- c_conn->ops.set_backlight(c_conn->display, bl_lvl);
+ rc = c_conn->ops.set_backlight(c_conn->display, bl_lvl);
}
- return 0;
+ return rc;
}
static int sde_backlight_device_get_brightness(struct backlight_device *bd)
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 1ee75c4..8d2f115 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -4581,10 +4581,13 @@
{
struct drm_encoder *encoder;
struct sde_crtc_state *cstate;
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_smmu_state_data *smmu_state;
uint32_t secure;
uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0;
int encoder_cnt = 0, i;
int rc;
+ bool is_video_mode = false;
if (!crtc || !state) {
SDE_ERROR("invalid arguments\n");
@@ -4642,6 +4645,37 @@
}
}
+
+ drm_for_each_encoder(encoder, crtc->dev) {
+ if (encoder->crtc != crtc)
+ continue;
+
+ is_video_mode |= sde_encoder_check_mode(encoder,
+ MSM_DISPLAY_CAP_VID_MODE);
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ smmu_state = &sde_crtc->smmu_state;
+ /*
+ * In video mode check for null commit before transition
+ * from secure to non secure and vice versa
+ */
+ if (is_video_mode && smmu_state &&
+ state->plane_mask && crtc->state->plane_mask &&
+ ((fb_sec_dir && ((smmu_state->state == ATTACHED) &&
+ (secure == SDE_DRM_SEC_ONLY))) ||
+ (fb_ns && ((smmu_state->state == DETACHED) ||
+ (smmu_state->state == DETACH_ALL_REQ))))) {
+
+ SDE_EVT32(DRMID(&sde_crtc->base), fb_ns, fb_sec_dir,
+ smmu_state->state, crtc->state->plane_mask,
+ crtc->state->plane_mask);
+ SDE_DEBUG("crtc %d, Invalid secure transition %x\n",
+ crtc->base.id, smmu_state->state);
+ return -EINVAL;
+
+ }
+
SDE_DEBUG("crtc:%d Secure validation successful\n", crtc->base.id);
return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
index 6ccf957..02d593b 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018, The Linux Foundation. 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 version 2 and
@@ -474,6 +474,7 @@
struct sde_hw_blk_reg_map hw;
memset(&hw, 0, sizeof(hw));
+ msm_gem_sync(cfg->dma_buf->buf);
cmd1 = (cfg->op == REG_DMA_READ) ?
(dspp_read_sel[cfg->block_select] << 30) : 0;
cmd1 |= (cfg->last_command) ? BIT(24) : 0;
@@ -481,7 +482,6 @@
cmd1 |= (cfg->op == REG_DMA_WRITE) ? (BIT(22)) : 0;
cmd1 |= (SIZE_DWORD(cfg->dma_buf->index) & MAX_DWORDS_SZ);
- msm_gem_sync(cfg->dma_buf->buf);
SET_UP_REG_DMA_REG(hw, reg_dma);
SDE_REG_WRITE(&hw, REG_DMA_OP_MODE_OFF, BIT(0));
SDE_REG_WRITE(&hw, reg_dma_clear_status_off,
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 5d3835c..5895a4d 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -952,6 +952,17 @@
.config_hdr = dp_connector_config_hdr,
.cmd_transfer = NULL,
};
+ static const struct sde_connector_ops ext_bridge_ops = {
+ .set_info_blob = dsi_conn_set_info_blob,
+ .mode_valid = dsi_conn_mode_valid,
+ .get_info = dsi_display_ext_bridge_get_info,
+ .soft_reset = dsi_display_soft_reset,
+ .clk_ctrl = dsi_display_clk_ctrl,
+ .get_mode_info = dsi_conn_ext_bridge_get_mode_info,
+ .get_dst_format = dsi_display_get_dst_format,
+ .enable_event = dsi_conn_enable_event,
+ .cmd_transfer = NULL,
+ };
struct msm_display_info info;
struct drm_encoder *encoder;
void *display, *connector;
@@ -976,39 +987,95 @@
display = sde_kms->dsi_displays[i];
encoder = NULL;
- memset(&info, 0x0, sizeof(info));
- rc = dsi_display_get_info(&info, display);
- if (rc) {
- SDE_ERROR("dsi get_info %d failed\n", i);
- continue;
- }
+ if (!dsi_display_has_ext_bridge(display)) {
+ memset(&info, 0x0, sizeof(info));
+ rc = dsi_display_get_info(&info, display);
+ if (rc) {
+ SDE_ERROR("dsi get_info %d failed\n", i);
+ continue;
+ }
- encoder = sde_encoder_init(dev, &info);
- if (IS_ERR_OR_NULL(encoder)) {
- SDE_ERROR("encoder init failed for dsi %d\n", i);
- continue;
- }
+ encoder = sde_encoder_init(dev, &info);
+ if (IS_ERR_OR_NULL(encoder)) {
+ SDE_ERROR("encoder init failed for dsi %d\n",
+ i);
+ continue;
+ }
- rc = dsi_display_drm_bridge_init(display, encoder);
- if (rc) {
- SDE_ERROR("dsi bridge %d init failed, %d\n", i, rc);
- sde_encoder_destroy(encoder);
- continue;
- }
+ rc = dsi_display_drm_bridge_init(display, encoder);
+ if (rc) {
+ SDE_ERROR("dsi bridge %d init failed, %d\n",
+ i, rc);
+ sde_encoder_destroy(encoder);
+ continue;
+ }
- connector = sde_connector_init(dev,
- encoder,
- 0,
- display,
- &dsi_ops,
- DRM_CONNECTOR_POLL_HPD,
- DRM_MODE_CONNECTOR_DSI);
- if (connector) {
- priv->encoders[priv->num_encoders++] = encoder;
+ connector = sde_connector_init(dev,
+ encoder,
+ NULL,
+ display,
+ &dsi_ops,
+ DRM_CONNECTOR_POLL_HPD,
+ DRM_MODE_CONNECTOR_DSI);
+ if (connector) {
+ priv->encoders[priv->num_encoders++] = encoder;
+ } else {
+ SDE_ERROR("dsi %d connector init failed\n", i);
+ dsi_display_drm_bridge_deinit(display);
+ sde_encoder_destroy(encoder);
+ }
} else {
- SDE_ERROR("dsi %d connector init failed\n", i);
- dsi_display_drm_bridge_deinit(display);
- sde_encoder_destroy(encoder);
+ memset(&info, 0x0, sizeof(info));
+ rc = dsi_display_ext_bridge_get_info(&info, display);
+ if (rc) {
+ SDE_ERROR("ext get_info %d failed\n", i);
+ continue;
+ }
+
+ encoder = sde_encoder_init(dev, &info);
+ if (IS_ERR_OR_NULL(encoder)) {
+ SDE_ERROR("encoder init failed for ext %d\n",
+ i);
+ continue;
+ }
+
+ rc = dsi_display_drm_bridge_init(display, encoder);
+ if (rc) {
+ SDE_ERROR("dsi bridge %d init failed for ext\n",
+ i);
+ sde_encoder_destroy(encoder);
+ continue;
+ }
+
+ connector = sde_connector_init(dev,
+ encoder,
+ NULL,
+ display,
+ &ext_bridge_ops,
+ DRM_CONNECTOR_POLL_HPD,
+ DRM_MODE_CONNECTOR_DSI);
+ if (connector) {
+ priv->encoders[priv->num_encoders++] = encoder;
+ } else {
+ SDE_ERROR("connector init %d failed for ext\n",
+ i);
+ dsi_display_drm_bridge_deinit(display);
+ sde_encoder_destroy(encoder);
+ continue;
+ }
+
+ rc = dsi_display_drm_ext_bridge_init(display,
+ encoder, connector);
+ if (rc) {
+ struct drm_connector *conn = connector;
+
+ SDE_ERROR("ext bridge %d init failed, %d\n",
+ i, rc);
+ conn->funcs->destroy(connector);
+ dsi_display_drm_bridge_deinit(display);
+ sde_encoder_destroy(encoder);
+ continue;
+ }
}
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 406743f..ab9f203 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -744,6 +744,7 @@
{ ADRENO_QUIRK_SECVID_SET_ONCE, "qcom,gpu-quirk-secvid-set-once" },
{ ADRENO_QUIRK_LIMIT_UCHE_GBIF_RW,
"qcom,gpu-quirk-limit-uche-gbif-rw" },
+ { ADRENO_QUIRK_MMU_SECURE_CB_ALT, "qcom,gpu-quirk-mmu-secure-cb-alt" },
};
static struct device_node *
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index a506f47..8785d62 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -150,6 +150,8 @@
* between GBIF, SMMU and MEMNOC.
*/
#define ADRENO_QUIRK_LIMIT_UCHE_GBIF_RW BIT(8)
+/* Select alternate secure context bank for mmu */
+#define ADRENO_QUIRK_MMU_SECURE_CB_ALT BIT(9)
/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE 0
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5168d9e..a8075fe 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2018, The Linux Foundation. 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 version 2 and
@@ -261,7 +261,8 @@
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
- int i, status;
+ int i;
+ int status = -ENOMEM;
if (!adreno_is_a3xx(adreno_dev)) {
status = kgsl_allocate_global(device, &device->scratch,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 60c56a06..c4296c8 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -2527,6 +2527,7 @@
} kgsl_iommu_cbs[] = {
{ KGSL_IOMMU_CONTEXT_USER, "gfx3d_user", },
{ KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure" },
+ { KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure_alt" },
};
static int _kgsl_iommu_cb_probe(struct kgsl_device *device,
@@ -2534,12 +2535,20 @@
{
struct platform_device *pdev = of_find_device_by_node(node);
struct kgsl_iommu_context *ctx = NULL;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int i;
for (i = 0; i < ARRAY_SIZE(kgsl_iommu_cbs); i++) {
if (!strcmp(node->name, kgsl_iommu_cbs[i].name)) {
int id = kgsl_iommu_cbs[i].id;
+ if (ADRENO_QUIRK(adreno_dev,
+ ADRENO_QUIRK_MMU_SECURE_CB_ALT)) {
+ if (!strcmp(node->name, "gfx3d_secure"))
+ continue;
+ } else if (!strcmp(node->name, "gfx3d_secure_alt"))
+ continue;
+
ctx = &iommu->ctx[id];
ctx->id = id;
ctx->cb_num = -1;
@@ -2550,8 +2559,8 @@
}
if (ctx == NULL) {
- KGSL_CORE_ERR("dt: Unknown context label %s\n", node->name);
- return -EINVAL;
+ KGSL_CORE_ERR("dt: Unused context label %s\n", node->name);
+ return 0;
}
if (ctx->id == KGSL_IOMMU_CONTEXT_SECURE)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 85df514..868be8b 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -4396,8 +4396,12 @@
smmu->arch_ops = data->arch_ops;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res)
- smmu->phys_addr = res->start;
+ if (res == NULL) {
+ dev_err(dev, "no MEM resource info\n");
+ return -EINVAL;
+ }
+
+ smmu->phys_addr = res->start;
smmu->base = devm_ioremap_resource(dev, res);
if (IS_ERR(smmu->base))
return PTR_ERR(smmu->base);
diff --git a/drivers/leds/leds-qpnp-haptics.c b/drivers/leds/leds-qpnp-haptics.c
index fad36ea..764657a 100644
--- a/drivers/leds/leds-qpnp-haptics.c
+++ b/drivers/leds/leds-qpnp-haptics.c
@@ -482,7 +482,8 @@
{
int rc = 0;
u32 delay_us = HAPTICS_BACK_EMF_DELAY_US;
- u8 val, auto_res_mode_qwd;
+ u8 val;
+ bool auto_res_mode_qwd;
if (chip->act_type != HAP_LRA)
return 0;
@@ -496,7 +497,7 @@
/*
* Do not enable auto resonance if auto mode is enabled and auto
- * resonance mode is QWD, meaning short pattern.
+ * resonance mode is QWD, meaning long pattern.
*/
if (chip->lra_auto_mode && auto_res_mode_qwd && enable) {
pr_debug("auto_mode enabled, not enabling auto_res\n");
@@ -1232,7 +1233,7 @@
ares_cfg.lra_qwd_drive_duration = 0;
ares_cfg.calibrate_at_eop = 0;
} else {
- ares_cfg.auto_res_mode = HAP_AUTO_RES_QWD;
+ ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD_EOP;
ares_cfg.lra_qwd_drive_duration = -EINVAL;
ares_cfg.calibrate_at_eop = -EINVAL;
}
@@ -1242,16 +1243,13 @@
if (rc < 0)
return rc;
- rc = qpnp_haptics_brake_config(chip, brake_pat);
- if (rc < 0)
- return rc;
-
/* enable play_irq for buffer mode */
if (chip->play_irq >= 0 && !chip->play_irq_en) {
enable_irq(chip->play_irq);
chip->play_irq_en = true;
}
+ brake_pat[0] = BRAKE_VMAX;
chip->play_mode = HAP_BUFFER;
chip->wave_shape = HAP_WAVE_SQUARE;
} else {
@@ -1264,7 +1262,7 @@
ares_cfg.lra_qwd_drive_duration = 0;
ares_cfg.calibrate_at_eop = 1;
} else {
- ares_cfg.auto_res_mode = HAP_AUTO_RES_ZXD_EOP;
+ ares_cfg.auto_res_mode = HAP_AUTO_RES_QWD;
ares_cfg.lra_res_cal_period = HAP_RES_CAL_PERIOD_MAX;
ares_cfg.lra_qwd_drive_duration = -EINVAL;
ares_cfg.calibrate_at_eop = -EINVAL;
@@ -1275,11 +1273,6 @@
if (rc < 0)
return rc;
- brake_pat[0] = 0x3;
- rc = qpnp_haptics_brake_config(chip, brake_pat);
- if (rc < 0)
- return rc;
-
/* enable play_irq for direct mode */
if (chip->play_irq >= 0 && chip->play_irq_en) {
disable_irq(chip->play_irq);
@@ -1303,6 +1296,10 @@
return rc;
}
+ rc = qpnp_haptics_brake_config(chip, brake_pat);
+ if (rc < 0)
+ return rc;
+
rc = qpnp_haptics_masked_write_reg(chip, HAP_CFG2_REG(chip),
HAP_LRA_RES_TYPE_MASK, chip->wave_shape);
if (rc < 0)
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
index df50ca5..82e3b40 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
@@ -22,11 +22,16 @@
#include "venus_boot.h"
#include "soc/qcom/secure_buffer.h"
#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
enum clock_properties {
CLOCK_PROP_HAS_SCALING = 1 << 0,
};
+struct regulator *gdsc_venus;
+struct regulator *gdsc_venus_core0;
+
static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
{
return NULL;
@@ -59,6 +64,118 @@
return 0;
}
+static int venus_regulator_setup(struct msm_vidc_platform_resources *res)
+{
+ const char *reg_name = "venus";
+ const char *reg_name_core0 = "venus-core0";
+ int rc = 0;
+
+ gdsc_venus = devm_regulator_get(&res->pdev->dev, reg_name);
+ if (IS_ERR(gdsc_venus))
+ dprintk(VIDC_ERR, "Failed to get Venus GDSC\n");
+
+ rc = regulator_enable(gdsc_venus);
+ if (rc)
+ dprintk(VIDC_ERR, "Venus GDSC enable failed\n");
+
+ gdsc_venus_core0 = devm_regulator_get(&res->pdev->dev, reg_name_core0);
+ if (IS_ERR(gdsc_venus_core0))
+ dprintk(VIDC_ERR, "Failed to get Venus-Core0 GDSC\n");
+
+ rc = regulator_enable(gdsc_venus_core0);
+ if (rc)
+ dprintk(VIDC_ERR, "Venus-Core0 GDSC enable failed\n");
+
+ dprintk(VIDC_DBG, "Vensu, Venus-Core0 GDSC's are enabled\n");
+ return rc;
+}
+
+
+static int venus_clock_setup(struct msm_vidc_platform_resources *res,
+ unsigned long rate)
+{
+ int i, rc = 0;
+ struct clock_info *cl;
+ struct clk *clk = NULL;
+
+ dprintk(VIDC_DBG, " %s In\n", __func__);
+ for (i = 0; i < res->clock_set.count; i++) {
+ cl = &res->clock_set.clock_tbl[i];
+ if (!cl->has_scaling)
+ continue;
+
+ clk = clk_get(&res->pdev->dev, cl->name);
+ rc = clk_set_rate(clk, clk_round_rate(clk, rate));
+
+ if (rc)
+ dprintk(VIDC_ERR,
+ "%s: Failed to set clock rate %s: %d\n",
+ __func__, cl->name, rc);
+
+ dprintk(VIDC_DBG, "%s clock set clock rate to %lu\n",
+ cl->name, rate);
+ }
+
+ dprintk(VIDC_DBG, " %s exit\n", __func__);
+ return rc;
+}
+
+static int venus_clock_prepare_enable(struct msm_vidc_platform_resources *res)
+{
+ int i, rc = 0;
+ struct clock_info *cl;
+ struct clk *clk = NULL;
+
+ dprintk(VIDC_DBG, " %s In\n", __func__);
+ for (i = 0; i < res->clock_set.count; i++) {
+ cl = &res->clock_set.clock_tbl[i];
+ clk = clk_get(&res->pdev->dev, cl->name);
+ rc = clk_prepare_enable(clk);
+
+ if (rc) {
+ dprintk(VIDC_ERR, "failed to enable %s clock\n",
+ cl->name);
+ for (i--; i >= 0; i--) {
+ cl = &res->clock_set.clock_tbl[i];
+ clk = clk_get(&res->pdev->dev, cl->name);
+ clk_disable_unprepare(clk);
+ dprintk(VIDC_ERR, "clock %s unprepared\n",
+ cl->name);
+ }
+ return rc;
+ }
+ dprintk(VIDC_DBG, " Clock : %s enabled\n", cl->name);
+ }
+
+ dprintk(VIDC_DBG, " %s exit\n", __func__);
+ return rc;
+}
+
+static void venus_clk_disable_unprepare(struct msm_vidc_platform_resources *res)
+{
+ int i;
+ struct clock_info *cl;
+ struct clk *clk = NULL;
+
+ for (i = 0; i < res->clock_set.count; i++) {
+ cl = &res->clock_set.clock_tbl[i];
+ clk = clk_get(&res->pdev->dev, cl->name);
+ dprintk(VIDC_DBG, "clock %s unprepared\n", cl->name);
+ clk_disable_unprepare(clk);
+ }
+
+ if (gdsc_venus) {
+ regulator_disable(gdsc_venus);
+ dprintk(VIDC_DBG, "Venus Regulator disabled\n");
+ gdsc_venus = NULL;
+ }
+ if (gdsc_venus_core0) {
+ regulator_disable(gdsc_venus_core0);
+ dprintk(VIDC_DBG, "Venus-Core0 Regulator disabled\n");
+ gdsc_venus_core0 = NULL;
+ }
+}
+
static inline enum imem_type read_imem_type(struct platform_device *pdev)
{
bool is_compatible(char *compat)
@@ -843,6 +960,8 @@
bus->dev = dev;
dprintk(VIDC_DBG, "Found bus %s [%d->%d] with governor %s\n",
bus->name, bus->master, bus->slave, bus->governor);
+
+ venus_clk_disable_unprepare(res);
err_bus:
return rc;
}
@@ -1232,6 +1351,12 @@
of_property_read_u32(pdev->dev.of_node,
"qcom,max-secure-instances",
&res->max_secure_inst_count);
+
+ venus_regulator_setup(res);
+ venus_clock_setup(res, 0);
+ venus_clock_prepare_enable(res);
+ venus_clock_setup(res, 1);
+
return rc;
err_setup_legacy_cb:
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index eab93cc..a86d9f1 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. 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 version 2 and
@@ -2216,13 +2216,24 @@
}
*data->hdcp_ctx = handle;
- /* Cache the client ctx to be used later
- * HDCP driver probe happens earlier than
+
+ /* Cache the client ctx to be used later if
+ * Misc HDCP driver probe happens later than
* SDE driver probe hence caching it to
* be used later.
*/
-
drv_client_handle = handle;
+
+ /* if misc HDCP driver probe happens earlier
+ * than SDE driver probe store the client
+ * handle to be used to sysfs notifications.
+ */
+
+ if (hdcp_drv_mgr && !hdcp_drv_mgr->handle) {
+ if (drv_client_handle)
+ hdcp_drv_mgr->handle = drv_client_handle;
+ }
+
handle->thread = kthread_run(kthread_worker_fn,
&handle->worker, "hdcp_tz_lib");
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 5ed9b72..0abc7a3 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1916,7 +1916,11 @@
err = PTR_ERR(buf);
}
} else {
- val = *buf;
+ /*
+ * 30 bits from bit offset 0 would be read.
+ * We're interested in bits 28:29
+ */
+ val = (*buf >> 28) & 0x3;
kfree(buf);
}
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 93692fa..6adb44c 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -324,6 +324,8 @@
POWER_SUPPLY_ATTR(parallel_fcc_max),
POWER_SUPPLY_ATTR(min_icl),
POWER_SUPPLY_ATTR(moisture_detected),
+ POWER_SUPPLY_ATTR(batt_full_current),
+ POWER_SUPPLY_ATTR(recharge_soc),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index d1031ba..b07efdf 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -28,7 +28,67 @@
#include "smb5-reg.h"
#include "smb5-lib.h"
-static struct smb_params smb5_params = {
+static struct smb_params smb5_pmi632_params = {
+ .fcc = {
+ .name = "fast charge current",
+ .reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .fv = {
+ .name = "float voltage",
+ .reg = CHGR_FLOAT_VOLTAGE_CFG_REG,
+ .min_u = 3600000,
+ .max_u = 4800000,
+ .step_u = 10000,
+ },
+ .usb_icl = {
+ .name = "usb input current limit",
+ .reg = USBIN_CURRENT_LIMIT_CFG_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .icl_stat = {
+ .name = "input current limit status",
+ .reg = AICL_ICL_STATUS_REG,
+ .min_u = 0,
+ .max_u = 3000000,
+ .step_u = 50000,
+ },
+ .otg_cl = {
+ .name = "usb otg current limit",
+ .reg = DCDC_OTG_CURRENT_LIMIT_CFG_REG,
+ .min_u = 500000,
+ .max_u = 1000000,
+ .step_u = 250000,
+ },
+ .jeita_cc_comp_hot = {
+ .name = "jeita fcc reduction",
+ .reg = JEITA_CCCOMP_CFG_HOT_REG,
+ .min_u = 0,
+ .max_u = 1575000,
+ .step_u = 25000,
+ },
+ .jeita_cc_comp_cold = {
+ .name = "jeita fcc reduction",
+ .reg = JEITA_CCCOMP_CFG_COLD_REG,
+ .min_u = 0,
+ .max_u = 1575000,
+ .step_u = 25000,
+ },
+ .freq_switcher = {
+ .name = "switching frequency",
+ .reg = DCDC_FSW_SEL_REG,
+ .min_u = 600,
+ .max_u = 1200,
+ .step_u = 400,
+ .set_proc = smblib_set_chg_freq,
+ },
+};
+
+static struct smb_params smb5_pmi855_params = {
.fcc = {
.name = "fast charge current",
.reg = CHGR_FAST_CHARGE_CURRENT_CFG_REG,
@@ -119,6 +179,64 @@
weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600
);
+#define PMI632_MAX_ICL_UA 3000000
+static int smb5_chg_config_init(struct smb5 *chip)
+{
+ struct smb_charger *chg = &chip->chg;
+ struct pmic_revid_data *pmic_rev_id;
+ struct device_node *revid_dev_node;
+ int rc = 0;
+
+ revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
+ "qcom,pmic-revid", 0);
+ if (!revid_dev_node) {
+ pr_err("Missing qcom,pmic-revid property\n");
+ return -EINVAL;
+ }
+
+ pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR_OR_NULL(pmic_rev_id)) {
+ /*
+ * the revid peripheral must be registered, any failure
+ * here only indicates that the rev-id module has not
+ * probed yet.
+ */
+ rc = -EPROBE_DEFER;
+ goto out;
+ }
+
+ switch (pmic_rev_id->pmic_subtype) {
+ case PM855B_SUBTYPE:
+ chip->chg.smb_version = PM855B_SUBTYPE;
+ chg->param = smb5_pmi855_params;
+ chg->name = "pm855b_charger";
+ break;
+ case PMI632_SUBTYPE:
+ chip->chg.smb_version = PMI632_SUBTYPE;
+ chg->param = smb5_pmi632_params;
+ chg->use_extcon = true;
+ chg->name = "pmi632_charger";
+ chg->hw_max_icl_ua =
+ (chip->dt.usb_icl_ua > 0) ? chip->dt.usb_icl_ua
+ : PMI632_MAX_ICL_UA;
+ chg->chg_freq.freq_5V = 600;
+ chg->chg_freq.freq_6V_8V = 800;
+ chg->chg_freq.freq_9V = 1050;
+ chg->chg_freq.freq_removal = 1050;
+ chg->chg_freq.freq_below_otg_threshold = 800;
+ chg->chg_freq.freq_above_otg_threshold = 800;
+ break;
+ default:
+ pr_err("PMIC subtype %d not supported\n",
+ pmic_rev_id->pmic_subtype);
+ rc = -EINVAL;
+ }
+
+out:
+ of_node_put(revid_dev_node);
+ return rc;
+}
+
#define MICRO_1P5A 1500000
#define MICRO_P1A 100000
#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
@@ -213,8 +331,6 @@
chip->dt.auto_recharge_soc = of_property_read_bool(node,
"qcom,auto-recharge-soc");
- chg->micro_usb_mode = of_property_read_bool(node, "qcom,micro-usb");
-
chg->dcp_icl_ua = chip->dt.usb_icl_ua;
chg->suspend_input_on_debug_batt = of_property_read_bool(node,
@@ -253,6 +369,8 @@
POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONNECTOR_TYPE,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
};
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -272,12 +390,13 @@
if (!val->intval)
break;
- if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
- chg->micro_usb_mode) &&
- chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
+ (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
+ && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
val->intval = 0;
else
val->intval = 1;
+
if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
val->intval = 0;
break;
@@ -297,19 +416,19 @@
val->intval = chg->real_charger_type;
break;
case POWER_SUPPLY_PROP_TYPEC_MODE:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = POWER_SUPPLY_TYPEC_NONE;
else
val->intval = chg->typec_mode;
break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
else
rc = smblib_get_prop_typec_power_role(chg, val);
break;
case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
val->intval = 0;
else
rc = smblib_get_prop_typec_cc_orientation(chg, val);
@@ -354,6 +473,9 @@
val->intval = get_client_vote(chg->usb_icl_votable,
USB_PSY_VOTER);
break;
+ case POWER_SUPPLY_PROP_CONNECTOR_TYPE:
+ val->intval = chg->connector_type;
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -496,9 +618,9 @@
if (!val->intval)
break;
- if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ||
- chg->micro_usb_mode) &&
- chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) ||
+ (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
+ && (chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
val->intval = 1;
else
val->intval = 0;
@@ -1093,7 +1215,7 @@
struct regulator_config cfg = {};
int rc = 0;
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
return 0;
chg->vconn_vreg = devm_kzalloc(chg->dev, sizeof(*chg->vconn_vreg),
@@ -1139,7 +1261,6 @@
}
rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
- MICRO_USB_STATE_CHANGE_INT_EN_BIT |
TYPEC_WATER_DETECTION_INT_EN_BIT);
if (rc < 0) {
dev_err(chg->dev,
@@ -1172,14 +1293,23 @@
return rc;
}
+ rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
+ MICRO_USB_STATE_CHANGE_INT_EN_BIT,
+ MICRO_USB_STATE_CHANGE_INT_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure Type-C interrupts rc=%d\n", rc);
+ return rc;
+ }
+
return rc;
}
static int smb5_init_hw(struct smb5 *chip)
{
struct smb_charger *chg = &chip->chg;
- int rc;
- u8 val;
+ int rc, type = 0;
+ u8 val = 0;
if (chip->dt.no_battery)
chg->fake_capacity = 50;
@@ -1194,8 +1324,50 @@
smblib_get_charge_param(chg, &chg->param.usb_icl,
&chg->default_icl_ua);
- if (chip->dt.usb_icl_ua < 0)
- chip->dt.usb_icl_ua = chg->default_icl_ua;
+
+ /* Use SW based VBUS control, disable HW autonomous mode */
+ /* TODO: auth can be enabled through vote based on APSD flow */
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT,
+ HVDCP_AUTH_ALG_EN_CFG_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure HVDCP rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * PMI632 can have the connector type defined by a dedicated register
+ * TYPEC_MICRO_USB_MODE_REG or by a common TYPEC_U_USB_CFG_REG.
+ */
+ if (chg->smb_version == PMI632_SUBTYPE) {
+ rc = smblib_read(chg, TYPEC_MICRO_USB_MODE_REG, &val);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't read USB mode rc=%d\n", rc);
+ return rc;
+ }
+ type = !!(val & MICRO_USB_MODE_ONLY_BIT);
+ }
+
+ /*
+ * If TYPEC_MICRO_USB_MODE_REG is not set and for all non-PMI632
+ * check the connector type using TYPEC_U_USB_CFG_REG.
+ */
+ if (!type) {
+ rc = smblib_read(chg, TYPEC_U_USB_CFG_REG, &val);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't read U_USB config rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ type = !!(val & EN_MICRO_USB_MODE_BIT);
+ }
+
+ chg->connector_type = type ? POWER_SUPPLY_CONNECTOR_MICRO_USB
+ : POWER_SUPPLY_CONNECTOR_TYPEC;
+ pr_debug("Connector type=%s\n", type ? "Micro USB" : "TypeC");
+
+ smblib_rerun_apsd_if_required(chg);
/* vote 0mA on usb_icl for non battery platforms */
vote(chg->usb_icl_votable,
@@ -1207,15 +1379,21 @@
vote(chg->fv_votable, HW_LIMIT_VOTER,
chip->dt.batt_profile_fv_uv > 0, chip->dt.batt_profile_fv_uv);
vote(chg->fcc_votable,
- BATT_PROFILE_VOTER, true, chg->batt_profile_fcc_ua);
+ BATT_PROFILE_VOTER, chg->batt_profile_fcc_ua > 0,
+ chg->batt_profile_fcc_ua);
vote(chg->fv_votable,
- BATT_PROFILE_VOTER, true, chg->batt_profile_fv_uv);
+ BATT_PROFILE_VOTER, chg->batt_profile_fv_uv > 0,
+ chg->batt_profile_fv_uv);
vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
true, 0);
vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
true, 0);
vote(chg->pd_disallowed_votable_indirect, MICRO_USB_VOTER,
- chg->micro_usb_mode, 0);
+ chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB, 0);
+
+ /* Some h/w limit maximum supported ICL */
+ vote(chg->usb_icl_votable, HW_LIMIT_VOTER,
+ chg->hw_max_icl_ua > 0, chg->hw_max_icl_ua);
/*
* AICL configuration:
@@ -1235,7 +1413,7 @@
return rc;
}
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
rc = smb5_configure_micro_usb(chg);
else
rc = smb5_configure_typec(chg);
@@ -1384,8 +1562,8 @@
pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
rc = smblib_set_prop_typec_power_role(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't configure power role for DRP rc=%d\n", rc);
+ dev_err(chg->dev, "Couldn't configure DRP role rc=%d\n",
+ rc);
return rc;
}
@@ -1405,6 +1583,7 @@
if (chg->bms_psy)
smblib_suspend_on_debug_battery(chg);
+
usb_plugin_irq_handler(0, &irq_data);
typec_state_change_irq_handler(0, &irq_data);
usb_source_change_irq_handler(0, &irq_data);
@@ -1412,6 +1591,7 @@
icl_change_irq_handler(0, &irq_data);
batt_temp_changed_irq_handler(0, &irq_data);
wdog_bark_irq_handler(0, &irq_data);
+ typec_or_rid_detection_change_irq_handler(0, &irq_data);
return 0;
}
@@ -1586,7 +1766,7 @@
/* TYPEC IRQs */
[TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
.name = "typec-or-rid-detect-change",
- .handler = default_irq_handler,
+ .handler = typec_or_rid_detection_change_irq_handler,
},
[TYPEC_VPD_DETECT_IRQ] = {
.name = "typec-vpd-detect",
@@ -1880,13 +2060,12 @@
chg = &chip->chg;
chg->dev = &pdev->dev;
- chg->param = smb5_params;
chg->debug_mask = &__debug_mask;
chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
chg->mode = PARALLEL_MASTER;
chg->irq_info = smb5_irqs;
chg->die_health = -EINVAL;
- chg->name = "pm855b_charger";
+ chg->otg_present = false;
chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
if (!chg->regmap) {
@@ -1897,13 +2076,20 @@
rc = smb5_parse_dt(chip);
if (rc < 0) {
pr_err("Couldn't parse device tree rc=%d\n", rc);
- goto cleanup;
+ return rc;
+ }
+
+ rc = smb5_chg_config_init(chip);
+ if (rc < 0) {
+ if (rc != -EPROBE_DEFER)
+ pr_err("Couldn't setup chg_config rc=%d\n", rc);
+ return rc;
}
rc = smblib_init(chg);
if (rc < 0) {
pr_err("Smblib_init failed rc=%d\n", rc);
- goto cleanup;
+ return rc;
}
/* set driver data before resources request it */
@@ -1945,10 +2131,12 @@
goto cleanup;
}
- rc = smb5_init_dc_psy(chip);
- if (rc < 0) {
- pr_err("Couldn't initialize dc psy rc=%d\n", rc);
- goto cleanup;
+ if (chg->smb_version == PM855B_SUBTYPE) {
+ rc = smb5_init_dc_psy(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize dc psy rc=%d\n", rc);
+ goto cleanup;
+ }
}
rc = smb5_init_usb_psy(chip);
@@ -1991,7 +2179,7 @@
rc = smb5_post_init(chip);
if (rc < 0) {
pr_err("Failed in post init rc=%d\n", rc);
- goto cleanup;
+ goto free_irq;
}
smb5_create_debugfs(chip);
@@ -1999,7 +2187,7 @@
rc = smb5_show_charger_status(chip);
if (rc < 0) {
pr_err("Failed in getting charger status rc=%d\n", rc);
- goto cleanup;
+ goto free_irq;
}
device_init_wakeup(chg->dev, true);
@@ -2008,8 +2196,9 @@
return rc;
-cleanup:
+free_irq:
smb5_free_interrupts(chg);
+cleanup:
smblib_deinit(chg);
platform_set_drvdata(pdev, NULL);
@@ -2036,7 +2225,7 @@
smb5_disable_interrupts(chg);
/* configure power role for UFP */
- if (!chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC)
smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
TYPEC_POWER_ROLE_CMD_MASK, EN_SNK_ONLY_BIT);
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index ff7da6c..dbadd95 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -107,19 +107,6 @@
return 0;
}
-int smblib_icl_override(struct smb_charger *chg, bool override)
-{
- int rc;
-
- rc = smblib_masked_write(chg, USBIN_LOAD_CFG_REG,
- ICL_OVERRIDE_AFTER_APSD_BIT,
- override ? ICL_OVERRIDE_AFTER_APSD_BIT : 0);
- if (rc < 0)
- smblib_err(chg, "Couldn't override ICL rc=%d\n", rc);
-
- return rc;
-}
-
int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override)
{
int rc = 0;
@@ -137,6 +124,39 @@
return rc;
}
+static void smblib_notify_extcon_props(struct smb_charger *chg, int id)
+{
+ union extcon_property_value val;
+ union power_supply_propval prop_val;
+
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_TYPEC) {
+ smblib_get_prop_typec_cc_orientation(chg, &prop_val);
+ val.intval = ((prop_val.intval == 2) ? 1 : 0);
+ extcon_set_property(chg->extcon, id,
+ EXTCON_PROP_USB_TYPEC_POLARITY, val);
+ }
+
+ val.intval = true;
+ extcon_set_property(chg->extcon, id,
+ EXTCON_PROP_USB_SS, val);
+}
+
+static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg, EXTCON_USB);
+
+ extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
+}
+
+static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg, EXTCON_USB_HOST);
+
+ extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);
+}
+
/********************
* REGISTER GETTERS *
********************/
@@ -281,6 +301,48 @@
/********************
* REGISTER SETTERS *
********************/
+static const struct buck_boost_freq chg_freq_list[] = {
+ [0] = {
+ .freq_khz = 2400,
+ .val = 7,
+ },
+ [1] = {
+ .freq_khz = 2100,
+ .val = 8,
+ },
+ [2] = {
+ .freq_khz = 1600,
+ .val = 11,
+ },
+ [3] = {
+ .freq_khz = 1200,
+ .val = 15,
+ },
+};
+
+int smblib_set_chg_freq(struct smb_chg_param *param,
+ int val_u, u8 *val_raw)
+{
+ u8 i;
+
+ if (val_u > param->max_u || val_u < param->min_u)
+ return -EINVAL;
+
+ /* Charger FSW is the configured freqency / 2 */
+ val_u *= 2;
+ for (i = 0; i < ARRAY_SIZE(chg_freq_list); i++) {
+ if (chg_freq_list[i].freq_khz == val_u)
+ break;
+ }
+ if (i == ARRAY_SIZE(chg_freq_list)) {
+ pr_err("Invalid frequency %d Hz\n", val_u / 2);
+ return -EINVAL;
+ }
+
+ *val_raw = chg_freq_list[i].val;
+
+ return 0;
+}
int smblib_set_opt_switcher_freq(struct smb_charger *chg, int fsw_khz)
{
@@ -316,11 +378,15 @@
if (rc < 0)
return -EINVAL;
} else {
- if (val_u > param->max_u || val_u < param->min_u) {
- smblib_err(chg, "%s: %d is out of range [%d, %d]\n",
+ if (val_u > param->max_u || val_u < param->min_u)
+ smblib_dbg(chg, PR_MISC,
+ "%s: %d is out of range [%d, %d]\n",
param->name, val_u, param->min_u, param->max_u);
- return -EINVAL;
- }
+
+ if (val_u > param->max_u)
+ val_u = param->max_u;
+ if (val_u < param->min_u)
+ val_u = param->min_u;
val_raw = (val_u - param->min_u) / param->step_u;
}
@@ -771,69 +837,46 @@
int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
{
int rc = 0;
- bool override;
+ bool hc_mode = false;
/* suspend and return if 25mA or less is requested */
if (icl_ua <= USBIN_25MA)
return smblib_set_usb_suspend(chg, true);
if (icl_ua == INT_MAX)
- goto override_suspend_config;
+ goto set_mode;
/* configure current */
- if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+ if (((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT)
+ || (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB))
&& (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)) {
rc = set_sdp_current(chg, icl_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set SDP ICL rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
} else {
set_sdp_current(chg, 100000);
rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
if (rc < 0) {
smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
+ hc_mode = true;
}
-override_suspend_config:
- /* determine if override needs to be enforced */
- override = true;
- if (icl_ua == INT_MAX) {
- /* remove override if no voters - hw defaults is desired */
- override = false;
- } else if (chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
- if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB)
- /* For std cable with type = SDP never override */
- override = false;
- else if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_CDP
- && icl_ua == 1500000)
- /*
- * For std cable with type = CDP override only if
- * current is not 1500mA
- */
- override = false;
- }
-
- /* enforce override */
+set_mode:
rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USBIN_MODE_CHG_BIT, override ? USBIN_MODE_CHG_BIT : 0);
-
- rc = smblib_icl_override(chg, override);
- if (rc < 0) {
- smblib_err(chg, "Couldn't set ICL override rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
- }
+ USBIN_MODE_CHG_BIT, hc_mode ? USBIN_MODE_CHG_BIT : 0);
/* unsuspend after configuring current and override */
rc = smblib_set_usb_suspend(chg, false);
if (rc < 0) {
smblib_err(chg, "Couldn't resume input rc=%d\n", rc);
- goto enable_icl_changed_interrupt;
+ goto out;
}
-enable_icl_changed_interrupt:
+out:
return rc;
}
@@ -844,7 +887,7 @@
bool override;
if ((chg->typec_mode == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
- || chg->micro_usb_mode)
+ || chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
&& (chg->usb_psy->desc->type == POWER_SUPPLY_TYPE_USB)) {
rc = get_sdp_current(chg, icl_ua);
if (rc < 0) {
@@ -881,6 +924,9 @@
{
struct smb_charger *chg = data;
+ if (chg->smb_version == PMI632_SUBTYPE)
+ return 0;
+
/* resume input if suspend is invalid */
if (suspend < 0)
suspend = 0;
@@ -1523,6 +1569,18 @@
return rc;
}
+static int smblib_force_vbus_voltage(struct smb_charger *chg, u8 val)
+{
+ int rc;
+
+ rc = smblib_masked_write(chg, CMD_HVDCP_2_REG, val, val);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't write to CMD_HVDCP_2_REG rc=%d\n",
+ rc);
+
+ return rc;
+}
+
int smblib_dp_dm(struct smb_charger *chg, int val)
{
int target_icl_ua, rc = 0;
@@ -1573,6 +1631,21 @@
smblib_dbg(chg, PR_PARALLEL, "ICL DOWN ICL=%d reduction=%d\n",
target_icl_ua, chg->usb_icl_delta_ua);
break;
+ case POWER_SUPPLY_DP_DM_FORCE_5V:
+ rc = smblib_force_vbus_voltage(chg, FORCE_5V_BIT);
+ if (rc < 0)
+ pr_err("Failed to force 5V\n");
+ break;
+ case POWER_SUPPLY_DP_DM_FORCE_9V:
+ rc = smblib_force_vbus_voltage(chg, FORCE_9V_BIT);
+ if (rc < 0)
+ pr_err("Failed to force 9V\n");
+ break;
+ case POWER_SUPPLY_DP_DM_FORCE_12V:
+ rc = smblib_force_vbus_voltage(chg, FORCE_12V_BIT);
+ if (rc < 0)
+ pr_err("Failed to force 12V\n");
+ break;
case POWER_SUPPLY_DP_DM_ICL_UP:
default:
break;
@@ -1699,8 +1772,13 @@
{
switch (chg->real_charger_type) {
case POWER_SUPPLY_TYPE_USB_HVDCP:
+ case POWER_SUPPLY_TYPE_USB_HVDCP_3:
case POWER_SUPPLY_TYPE_USB_PD:
- val->intval = MICRO_12V;
+ if (chg->smb_version == PMI632_SUBTYPE)
+ val->intval = MICRO_9V;
+ else
+ val->intval = MICRO_12V;
+ break;
default:
val->intval = MICRO_5V;
break;
@@ -2053,7 +2131,7 @@
}
int smblib_set_prop_boost_current(struct smb_charger *chg,
- const union power_supply_propval *val)
+ const union power_supply_propval *val)
{
int rc = 0;
@@ -2076,6 +2154,9 @@
int rc = 0;
u8 power_role;
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ return 0;
+
switch (val->intval) {
case POWER_SUPPLY_TYPEC_PR_NONE:
power_role = TYPEC_DISABLE_CMD_BIT;
@@ -2513,7 +2594,7 @@
} else {
chg->typec_present = 0;
smblib_update_usb_type(chg);
- extcon_set_state_sync(chg->extcon, EXTCON_USB, false);
+ smblib_notify_device_mode(chg, false);
smblib_uusb_removal(chg);
}
}
@@ -2601,7 +2682,7 @@
smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
}
- if (chg->micro_usb_mode)
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
smblib_micro_usb_plugin(chg, vbus_rising);
power_supply_changed(chg->usb_psy);
@@ -2763,37 +2844,6 @@
rising ? "rising" : "falling");
}
-static void smblib_notify_extcon_props(struct smb_charger *chg, int id)
-{
- union extcon_property_value val;
- union power_supply_propval prop_val;
-
- smblib_get_prop_typec_cc_orientation(chg, &prop_val);
- val.intval = ((prop_val.intval == 2) ? 1 : 0);
- extcon_set_property(chg->extcon, id,
- EXTCON_PROP_USB_TYPEC_POLARITY, val);
-
- val.intval = true;
- extcon_set_property(chg->extcon, id,
- EXTCON_PROP_USB_SS, val);
-}
-
-static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
-{
- if (enable)
- smblib_notify_extcon_props(chg, EXTCON_USB);
-
- extcon_set_state_sync(chg->extcon, EXTCON_USB, enable);
-}
-
-static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
-{
- if (enable)
- smblib_notify_extcon_props(chg, EXTCON_USB_HOST);
-
- extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, enable);
-}
-
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
const struct apsd_result *apsd_result;
@@ -2806,13 +2856,11 @@
switch (apsd_result->bit) {
case SDP_CHARGER_BIT:
case CDP_CHARGER_BIT:
- if (chg->micro_usb_mode)
- extcon_set_state_sync(chg->extcon, EXTCON_USB,
- true);
/* if not DCP then no hvdcp timeout happens. Enable pd here */
vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
false, 0);
- if (chg->use_extcon)
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ || chg->use_extcon)
smblib_notify_device_mode(chg, true);
break;
case OCP_CHARGER_BIT:
@@ -2845,8 +2893,9 @@
}
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
- if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
- && !chg->uusb_apsd_rerun_done) {
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ && (stat & APSD_DTC_STATUS_DONE_BIT)
+ && !chg->uusb_apsd_rerun_done) {
/*
* Force re-run APSD to handle slow insertion related
* charger-mis-detection.
@@ -3146,12 +3195,12 @@
power_supply_changed(chg->usb_psy);
}
-irqreturn_t typec_state_change_irq_handler(int irq, void *data)
+irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
- if (chg->micro_usb_mode) {
+ if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
cancel_delayed_work_sync(&chg->uusb_otg_work);
vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
@@ -3160,7 +3209,16 @@
return IRQ_HANDLED;
}
- if (chg->pr_swap_in_progress) {
+ return IRQ_HANDLED;
+}
+
+irqreturn_t typec_state_change_irq_handler(int irq, void *data)
+{
+ struct smb_irq_data *irq_data = data;
+ struct smb_charger *chg = irq_data->parent_data;
+
+ if ((chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
+ || chg->pr_swap_in_progress) {
smblib_dbg(chg, PR_INTERRUPT,
"Ignoring since pr_swap_in_progress\n");
return IRQ_HANDLED;
@@ -3335,10 +3393,20 @@
smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
goto out;
}
+ otg = !!(stat & U_USB_GROUND_NOVBUS_BIT);
+ if (chg->otg_present != otg)
+ smblib_notify_usb_host(chg, otg);
+ chg->otg_present = otg;
+ if (!otg)
+ chg->boost_current_ua = 0;
- otg = !!(stat & (U_USB_GROUND_NOVBUS_BIT | U_USB_GROUND_BIT));
- extcon_set_state_sync(chg->extcon, EXTCON_USB_HOST, otg);
- smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
+ rc = smblib_set_charge_param(chg, &chg->param.freq_switcher,
+ otg ? chg->chg_freq.freq_below_otg_threshold
+ : chg->chg_freq.freq_removal);
+ if (rc < 0)
+ dev_err(chg->dev, "Error in setting freq_boost rc=%d\n", rc);
+
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_U_USB_STATUS = 0x%02x OTG=%d\n",
stat, otg);
power_supply_changed(chg->usb_psy);
@@ -3559,13 +3627,6 @@
return rc;
}
- rc = smblib_register_notifier(chg);
- if (rc < 0) {
- smblib_err(chg,
- "Couldn't register notifier rc=%d\n", rc);
- return rc;
- }
-
chg->bms_psy = power_supply_get_by_name("bms");
chg->pl.psy = power_supply_get_by_name("parallel");
if (chg->pl.psy) {
@@ -3576,6 +3637,12 @@
return rc;
}
}
+ rc = smblib_register_notifier(chg);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't register notifier rc=%d\n", rc);
+ return rc;
+ }
break;
case PARALLEL_SLAVE:
break;
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 8633ba0..fa7381c 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -196,6 +196,11 @@
u8 *val_raw);
};
+struct buck_boost_freq {
+ int freq_khz;
+ u8 val;
+};
+
struct smb_chg_freq {
unsigned int freq_5V;
unsigned int freq_6V_8V;
@@ -311,7 +316,7 @@
bool sw_jeita_enabled;
bool is_hdc;
bool chg_done;
- bool micro_usb_mode;
+ int connector_type;
bool otg_en;
bool suspend_input_on_debug_batt;
int otg_attempts;
@@ -329,6 +334,7 @@
u8 float_cfg;
bool use_extcon;
bool otg_present;
+ int hw_max_icl_ua;
/* workaround flag */
u32 wa_flags;
@@ -369,6 +375,8 @@
int val_u, u8 *val_raw);
int smblib_set_chg_freq(struct smb_chg_param *param,
int val_u, u8 *val_raw);
+int smblib_set_prop_boost_current(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);
@@ -390,6 +398,7 @@
irqreturn_t high_duty_cycle_irq_handler(int irq, void *data);
irqreturn_t switcher_power_ok_irq_handler(int irq, void *data);
irqreturn_t wdog_bark_irq_handler(int irq, void *data);
+irqreturn_t typec_or_rid_detection_change_irq_handler(int irq, void *data);
int smblib_get_prop_input_suspend(struct smb_charger *chg,
union power_supply_propval *val);
@@ -470,8 +479,6 @@
const union power_supply_propval *val);
int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_set_prop_boost_current(struct smb_charger *chg,
- const union power_supply_propval *val);
int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
@@ -484,7 +491,6 @@
int smblib_rerun_apsd_if_required(struct smb_charger *chg);
int smblib_get_prop_fcc_delta(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_icl_override(struct smb_charger *chg, bool override);
int smblib_dp_dm(struct smb_charger *chg, int val);
int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable);
int smblib_rerun_aicl(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 1534f7c..9a418c8 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -178,6 +178,8 @@
#define APSD_RERUN_BIT BIT(0)
#define CMD_HVDCP_2_REG (USBIN_BASE + 0x43)
+#define FORCE_12V_BIT BIT(5)
+#define FORCE_9V_BIT BIT(4)
#define FORCE_5V_BIT BIT(3)
#define SINGLE_DECREMENT_BIT BIT(1)
#define SINGLE_INCREMENT_BIT BIT(0)
@@ -196,6 +198,7 @@
};
#define USBIN_OPTIONS_1_CFG_REG (USBIN_BASE + 0x62)
+#define HVDCP_AUTH_ALG_EN_CFG_BIT BIT(6)
#define HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT BIT(5)
#define BC1P2_SRC_DETECT_BIT BIT(3)
@@ -299,6 +302,8 @@
#define TYPEC_U_USB_CFG_REG (TYPEC_BASE + 0x70)
#define EN_MICRO_USB_MODE_BIT BIT(0)
+#define TYPEC_MICRO_USB_MODE_REG (TYPEC_BASE + 0x70)
+#define MICRO_USB_MODE_ONLY_BIT BIT(0)
/********************************
* MISC Peripheral Registers *
********************************/
diff --git a/drivers/regulator/msm_gfx_ldo.c b/drivers/regulator/msm_gfx_ldo.c
index 2800607..115a9b7 100644
--- a/drivers/regulator/msm_gfx_ldo.c
+++ b/drivers/regulator/msm_gfx_ldo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. 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 version 2 and
@@ -773,12 +773,34 @@
return ldo_vreg->vreg_enabled;
}
+/**
+ * msm_gfx_ldo_list_corner_voltage() - return the ldo voltage mapped to
+ * the specified voltage corner
+ * @rdev: Regulator device pointer for the msm_gfx_ldo
+ * @corner: Voltage corner
+ *
+ * Return: voltage value in microvolts or -EINVAL if the corner is out of range
+ */
+static int msm_gfx_ldo_list_corner_voltage(struct regulator_dev *rdev,
+ int corner)
+{
+ struct msm_gfx_ldo *ldo_vreg = rdev_get_drvdata(rdev);
+
+ corner -= MIN_CORNER_OFFSET;
+
+ if (corner >= 0 && corner < ldo_vreg->num_corners)
+ return ldo_vreg->open_loop_volt[corner];
+ else
+ return -EINVAL;
+}
+
static struct regulator_ops msm_gfx_ldo_corner_ops = {
- .enable = msm_gfx_ldo_corner_enable,
- .disable = msm_gfx_ldo_disable,
- .is_enabled = msm_gfx_ldo_is_enabled,
- .set_voltage = msm_gfx_ldo_set_corner,
- .get_voltage = msm_gfx_ldo_get_corner,
+ .enable = msm_gfx_ldo_corner_enable,
+ .disable = msm_gfx_ldo_disable,
+ .is_enabled = msm_gfx_ldo_is_enabled,
+ .set_voltage = msm_gfx_ldo_set_corner,
+ .get_voltage = msm_gfx_ldo_get_corner,
+ .list_corner_voltage = msm_gfx_ldo_list_corner_voltage,
};
static int msm_gfx_ldo_get_bypass(struct regulator_dev *rdev,
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 0255761..c882403 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -65,9 +65,9 @@
obj-$(CONFIG_ICNSS) += icnss.o wlan_firmware_service_v01.o
obj-$(CONFIG_MEM_SHARE_QMI_SERVICE) += memshare/
+obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
obj-$(CONFIG_MSM_PIL_SSR_GENERIC) += subsys-pil-tz.o
obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o
-obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o
diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c
index ada7d5e..c93e0e1 100644
--- a/drivers/soc/qcom/ipc_router_glink_xprt.c
+++ b/drivers/soc/qcom/ipc_router_glink_xprt.c
@@ -44,6 +44,7 @@
#define MIN_FRAG_SZ (IPC_ROUTER_HDR_SIZE + sizeof(union rr_control_msg))
#define IPC_RTR_XPRT_NAME_LEN (2 * GLINK_NAME_SIZE)
#define PIL_SUBSYSTEM_NAME_LEN 32
+#define IPC_RTR_WS_NAME_LEN ((2 * GLINK_NAME_SIZE) + 4)
#define MAX_NUM_LO_INTENTS 5
#define MAX_NUM_MD_INTENTS 3
@@ -60,6 +61,7 @@
* @transport: Physical Transport Name as identified by Glink.
* @pil_edge: Edge name understood by PIL.
* @ipc_rtr_xprt_name: XPRT Name to be registered with IPC Router.
+ * @notify_rx_ws_name: Name of wakesource used in notify rx path.
* @xprt: IPC Router XPRT structure to contain XPRT specific info.
* @ch_hndl: Opaque Channel handle returned by GLink.
* @xprt_wq: Workqueue to queue read & other XPRT related works.
@@ -80,9 +82,11 @@
char transport[GLINK_NAME_SIZE];
char pil_edge[PIL_SUBSYSTEM_NAME_LEN];
char ipc_rtr_xprt_name[IPC_RTR_XPRT_NAME_LEN];
+ char notify_rx_ws_name[IPC_RTR_WS_NAME_LEN];
struct msm_ipc_router_xprt xprt;
void *ch_hndl;
struct workqueue_struct *xprt_wq;
+ struct wakeup_source notify_rxv_ws;
struct rw_semaphore ss_reset_rwlock;
int ss_reset;
void *pil;
@@ -380,6 +384,7 @@
glink_rx_done(glink_xprtp->ch_hndl, rx_work->iovec, reuse_intent);
kfree(rx_work);
up_read(&glink_xprtp->ss_reset_rwlock);
+ __pm_relax(&glink_xprtp->notify_rxv_ws);
}
static void glink_xprt_open_event(struct work_struct *work)
@@ -494,6 +499,8 @@
rx_work->iovec_size = size;
rx_work->vbuf_provider = vbuf_provider;
rx_work->pbuf_provider = pbuf_provider;
+ if (!glink_xprtp->dynamic_wakeup_source)
+ __pm_stay_awake(&glink_xprtp->notify_rxv_ws);
INIT_WORK(&rx_work->work, glink_xprt_read_data);
queue_work(glink_xprtp->xprt_wq, &rx_work->work);
}
@@ -762,7 +769,10 @@
kfree(glink_xprtp);
return -EFAULT;
}
-
+ scnprintf(glink_xprtp->notify_rx_ws_name, IPC_RTR_WS_NAME_LEN,
+ "%s_%s_rx", glink_xprtp->ch_name, glink_xprtp->edge);
+ wakeup_source_init(&glink_xprtp->notify_rxv_ws,
+ glink_xprtp->notify_rx_ws_name);
mutex_lock(&glink_xprt_list_lock_lha1);
list_add(&glink_xprtp->list, &glink_xprt_list);
mutex_unlock(&glink_xprt_list_lock_lha1);
diff --git a/drivers/soc/qcom/lpm-stats.c b/drivers/soc/qcom/lpm-stats.c
index 4a41eee..a4d59f4 100644
--- a/drivers/soc/qcom/lpm-stats.c
+++ b/drivers/soc/qcom/lpm-stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 2018 The Linux Foundation. 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 version 2 and
@@ -697,8 +697,10 @@
centry = &stats->child;
list_for_each_entry_reverse(pos, centry, sibling) {
- if (!list_empty(&pos->child))
+ if (!list_empty(&pos->child)) {
cleanup_stats(pos);
+ continue;
+ }
list_del_init(&pos->child);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 83b46d4..a1602e4 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -510,17 +510,36 @@
if (test_task_flag(tsk, TIF_MM_RELEASED))
continue;
- if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
- if (test_task_lmk_waiting(tsk)) {
- rcu_read_unlock();
- mutex_unlock(&scan_mutex);
- return 0;
- }
- }
+ if (oom_reaper) {
+ p = find_lock_task_mm(tsk);
+ if (!p)
+ continue;
- p = find_lock_task_mm(tsk);
- if (!p)
- continue;
+ if (test_bit(MMF_OOM_VICTIM, &p->mm->flags)) {
+ if (test_bit(MMF_OOM_SKIP, &p->mm->flags)) {
+ task_unlock(p);
+ continue;
+ } else if (time_before_eq(jiffies,
+ lowmem_deathpending_timeout)) {
+ task_unlock(p);
+ rcu_read_unlock();
+ mutex_unlock(&scan_mutex);
+ return 0;
+ }
+ }
+ } else {
+ if (time_before_eq(jiffies,
+ lowmem_deathpending_timeout))
+ if (test_task_lmk_waiting(tsk)) {
+ rcu_read_unlock();
+ mutex_unlock(&scan_mutex);
+ return 0;
+ }
+
+ p = find_lock_task_mm(tsk);
+ if (!p)
+ continue;
+ }
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 27bf54b..1259654 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -58,4 +58,4 @@
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o
-obj-$(CONFIG_THERMAL_TSENS) += msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o
+obj-$(CONFIG_THERMAL_TSENS) += msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o tsens1xxx.o
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index fe0a7c7..c137d3d 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
@@ -49,6 +49,11 @@
return tmdev->ops->hw_init(tmdev);
}
+static int tsens_calib(struct tsens_device *tmdev)
+{
+ return tmdev->ops->calibrate(tmdev);
+}
+
static int tsens_register_interrupts(struct tsens_device *tmdev)
{
if (tmdev->ops->interrupts_reg)
@@ -82,6 +87,9 @@
{ .compatible = "qcom,tsens24xx",
.data = &data_tsens24xx,
},
+ { .compatible = "qcom,msm8937-tsens",
+ .data = &data_tsens14xx,
+ },
{}
};
MODULE_DEVICE_TABLE(of, tsens_table);
@@ -97,6 +105,7 @@
struct device_node *of_node = pdev->dev.of_node;
const struct of_device_id *id;
const struct tsens_data *data;
+ int rc = 0;
struct resource *res_tsens_mem;
if (!of_match_node(tsens_table, of_node)) {
@@ -150,7 +159,27 @@
return PTR_ERR(tmdev->tsens_tm_addr);
}
- return 0;
+ /* TSENS eeprom register region */
+ res_tsens_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "tsens_eeprom_physical");
+ if (!res_tsens_mem) {
+ pr_debug("Could not get tsens physical address resource\n");
+ } else {
+ tmdev->tsens_calib_addr = devm_ioremap_resource(&pdev->dev,
+ res_tsens_mem);
+ if (IS_ERR(tmdev->tsens_calib_addr)) {
+ dev_err(&pdev->dev, "Failed to IO map TSENS EEPROM registers.\n");
+ rc = PTR_ERR(tmdev->tsens_calib_addr);
+ } else {
+ rc = tsens_calib(tmdev);
+ if (rc) {
+ pr_err("Error initializing TSENS controller\n");
+ return rc;
+ }
+ }
+ }
+
+ return rc;
}
static int tsens_thermal_zone_register(struct tsens_device *tmdev)
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index ae4741d..885b15c 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. 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 version 2 and
@@ -23,10 +23,15 @@
#define DEBUG_SIZE 10
#define TSENS_MAX_SENSORS 16
+#define TSENS_1x_MAX_SENSORS 11
#define TSENS_CONTROLLER_ID(n) (n)
#define TSENS_CTRL_ADDR(n) (n)
#define TSENS_TM_SN_STATUS(n) ((n) + 0xa0)
+#define ONE_PT_CALIB 0x1
+#define ONE_PT_CALIB2 0x2
+#define TWO_PT_CALIB 0x3
+
enum tsens_dbg_type {
TSENS_DBG_POLL,
TSENS_DBG_LOG_TEMP_READS,
@@ -70,6 +75,8 @@
int high_temp;
int low_temp;
int crit_temp;
+ int high_adc_code;
+ int low_adc_code;
};
struct tsens_sensor {
@@ -79,6 +86,8 @@
u32 id;
const char *sensor_name;
struct tsens_context thr_state;
+ int offset;
+ int slope;
};
/**
@@ -93,6 +102,7 @@
int (*interrupts_reg)(struct tsens_device *);
int (*dbg)(struct tsens_device *, u32, u32, int *);
int (*sensor_en)(struct tsens_device *, u32);
+ int (*calibrate)(struct tsens_device *);
};
struct tsens_irqs {
@@ -116,14 +126,15 @@
bool wd_bark;
u32 wd_bark_mask;
bool mtc;
+ bool valid_status_check;
};
struct tsens_mtc_sysfs {
- uint32_t zone_log;
+ u32 zone_log;
int zone_mtc;
int th1;
int th2;
- uint32_t zone_hist;
+ u32 zone_hist;
};
struct tsens_device {
@@ -134,6 +145,7 @@
struct regmap_field *status_field;
void __iomem *tsens_srot_addr;
void __iomem *tsens_tm_addr;
+ void __iomem *tsens_calib_addr;
const struct tsens_ops *ops;
struct tsens_dbg_context tsens_dbg;
spinlock_t tsens_crit_lock;
@@ -144,6 +156,7 @@
};
extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx;
+extern const struct tsens_data data_tsens14xx;
extern struct list_head tsens_device_list;
#endif /* __QCOM_TSENS_H__ */
diff --git a/drivers/thermal/tsens1xxx.c b/drivers/thermal/tsens1xxx.c
new file mode 100644
index 0000000..e2fad32
--- /dev/null
+++ b/drivers/thermal/tsens1xxx.c
@@ -0,0 +1,654 @@
+/* Copyright (c) 2012-2018, The Linux Foundation. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/vmalloc.h>
+#include "tsens.h"
+#include "thermal_core.h"
+
+#define TSENS_DRIVER_NAME "msm-tsens"
+
+#define TSENS_UPPER_LOWER_INTERRUPT_CTRL(n) (n)
+#define TSENS_INTERRUPT_EN BIT(0)
+
+#define TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(n) ((n) + 0x04)
+#define TSENS_UPPER_STATUS_CLR BIT(21)
+#define TSENS_LOWER_STATUS_CLR BIT(20)
+#define TSENS_UPPER_THRESHOLD_MASK 0xffc00
+#define TSENS_LOWER_THRESHOLD_MASK 0x3ff
+#define TSENS_UPPER_THRESHOLD_SHIFT 10
+
+#define TSENS_S0_STATUS_ADDR(n) ((n) + 0x30)
+#define TSENS_SN_ADDR_OFFSET 0x4
+#define TSENS_SN_STATUS_TEMP_MASK 0x3ff
+#define TSENS_SN_STATUS_LOWER_STATUS BIT(11)
+#define TSENS_SN_STATUS_UPPER_STATUS BIT(12)
+#define TSENS_STATUS_ADDR_OFFSET 2
+
+#define TSENS_TRDY_MASK BIT(0)
+
+#define TSENS_SN_STATUS_ADDR(n) ((n) + 0x44)
+#define TSENS_SN_STATUS_VALID BIT(14)
+#define TSENS_SN_STATUS_VALID_MASK 0x4000
+#define TSENS_TRDY_ADDR(n) ((n) + 0x84)
+
+#define TSENS_CTRL_ADDR(n) (n)
+#define TSENS_EN BIT(0)
+#define TSENS_CTRL_SENSOR_EN_MASK(n) ((n >> 3) & 0x7ff)
+#define TSENS_TRDY_RDY_MIN_TIME 2000
+#define TSENS_TRDY_RDY_MAX_TIME 2100
+#define TSENS_THRESHOLD_MAX_CODE 0x3ff
+#define TSENS_THRESHOLD_MIN_CODE 0x0
+
+/* eeprom layout data for 8937 */
+#define BASE0_MASK 0x000000ff
+#define BASE1_MASK 0xff000000
+#define BASE1_SHIFT 24
+
+#define S0_P1_MASK 0x000001f8
+#define S1_P1_MASK 0x001f8000
+#define S2_P1_MASK_0_4 0xf8000000
+#define S2_P1_MASK_5 0x00000001
+#define S3_P1_MASK 0x00001f80
+#define S4_P1_MASK 0x01f80000
+#define S5_P1_MASK 0x00003f00
+#define S6_P1_MASK 0x03f00000
+#define S7_P1_MASK 0x0000003f
+#define S8_P1_MASK 0x0003f000
+#define S9_P1_MASK 0x0000003f
+#define S10_P1_MASK 0x0003f000
+
+#define S0_P2_MASK 0x00007e00
+#define S1_P2_MASK 0x07e00000
+#define S2_P2_MASK 0x0000007e
+#define S3_P2_MASK 0x0007e000
+#define S4_P2_MASK 0x7e000000
+#define S5_P2_MASK 0x000fc000
+#define S6_P2_MASK 0xfc000000
+#define S7_P2_MASK 0x00000fc0
+#define S8_P2_MASK 0x00fc0000
+#define S9_P2_MASK 0x00000fc0
+#define S10_P2_MASK 0x00fc0000
+
+#define S0_P1_SHIFT 3
+#define S1_P1_SHIFT 15
+#define S2_P1_SHIFT_0_4 27
+#define S2_P1_SHIFT_5 5
+#define S3_P1_SHIFT 7
+#define S4_P1_SHIFT 19
+#define S5_P1_SHIFT 8
+#define S6_P1_SHIFT 20
+#define S8_P1_SHIFT 12
+#define S10_P1_SHIFT 12
+
+#define S0_P2_SHIFT 9
+#define S1_P2_SHIFT 21
+#define S2_P2_SHIFT 1
+#define S3_P2_SHIFT 13
+#define S4_P2_SHIFT 25
+#define S5_P2_SHIFT 14
+#define S6_P2_SHIFT 26
+#define S7_P2_SHIFT 6
+#define S8_P2_SHIFT 18
+#define S9_P2_SHIFT 6
+#define S10_P2_SHIFT 18
+
+#define CAL_SEL_MASK 0x00000007
+
+#define CAL_DEGC_PT1 30
+#define CAL_DEGC_PT2 120
+#define SLOPE_FACTOR 1000
+#define SLOPE_DEFAULT 3200
+
+/*
+ * Use this function on devices where slope and offset calculations
+ * depend on calibration data read from qfprom. On others the slope
+ * and offset values are derived from tz->tzp->slope and tz->tzp->offset
+ * resp.
+ */
+static void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+ u32 *p2, u32 mode)
+{
+ int i;
+ int num, den;
+
+ for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
+ pr_debug(
+ "sensor%d - data_point1:%#x data_point2:%#x\n",
+ i, p1[i], p2[i]);
+
+ tmdev->sensor[i].slope = SLOPE_DEFAULT;
+ if (mode == TWO_PT_CALIB) {
+ /*
+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+ * temp_120_degc - temp_30_degc (x2 - x1)
+ */
+ num = p2[i] - p1[i];
+ num *= SLOPE_FACTOR;
+ den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
+ tmdev->sensor[i].slope = num / den;
+ }
+
+ tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+ (CAL_DEGC_PT1 *
+ tmdev->sensor[i].slope);
+ pr_debug("offset:%d\n", tmdev->sensor[i].offset);
+ }
+}
+
+static int code_to_degc(u32 adc_code, const struct tsens_sensor *sensor)
+{
+ int degc, num, den;
+
+ num = (adc_code * SLOPE_FACTOR) - sensor->offset;
+ den = sensor->slope;
+
+ if (num > 0)
+ degc = num + (den / 2);
+ else if (num < 0)
+ degc = num - (den / 2);
+ else
+ degc = num;
+
+ degc /= den;
+
+ return degc;
+}
+
+static int degc_to_code(int degc, const struct tsens_sensor *sensor)
+{
+ int code = ((degc * sensor->slope)
+ + sensor->offset)/SLOPE_FACTOR;
+
+ if (code > TSENS_THRESHOLD_MAX_CODE)
+ code = TSENS_THRESHOLD_MAX_CODE;
+ else if (code < TSENS_THRESHOLD_MIN_CODE)
+ code = TSENS_THRESHOLD_MIN_CODE;
+ pr_debug("raw_code:0x%x, degc:%d\n",
+ code, degc);
+ return code;
+}
+
+static int calibrate_8937(struct tsens_device *tmdev)
+{
+ int base0 = 0, base1 = 0, i;
+ u32 p1[TSENS_1x_MAX_SENSORS], p2[TSENS_1x_MAX_SENSORS];
+ int mode = 0, tmp = 0;
+ u32 qfprom_cdata[5] = {0, 0, 0, 0, 0};
+
+ qfprom_cdata[0] = readl_relaxed(tmdev->tsens_calib_addr + 0x1D8);
+ qfprom_cdata[1] = readl_relaxed(tmdev->tsens_calib_addr + 0x1DC);
+ qfprom_cdata[2] = readl_relaxed(tmdev->tsens_calib_addr + 0x210);
+ qfprom_cdata[3] = readl_relaxed(tmdev->tsens_calib_addr + 0x214);
+ qfprom_cdata[4] = readl_relaxed(tmdev->tsens_calib_addr + 0x230);
+
+ mode = (qfprom_cdata[2] & CAL_SEL_MASK);
+ pr_debug("calibration mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
+ p2[0] = (qfprom_cdata[2] & S0_P2_MASK) >> S0_P2_SHIFT;
+ p2[1] = (qfprom_cdata[2] & S1_P2_MASK) >> S1_P2_SHIFT;
+ p2[2] = (qfprom_cdata[3] & S2_P2_MASK) >> S2_P2_SHIFT;
+ p2[3] = (qfprom_cdata[3] & S3_P2_MASK) >> S3_P2_SHIFT;
+ p2[4] = (qfprom_cdata[3] & S4_P2_MASK) >> S4_P2_SHIFT;
+ p2[5] = (qfprom_cdata[0] & S5_P2_MASK) >> S5_P2_SHIFT;
+ p2[6] = (qfprom_cdata[0] & S6_P2_MASK) >> S6_P2_SHIFT;
+ p2[7] = (qfprom_cdata[1] & S7_P2_MASK) >> S7_P2_SHIFT;
+ p2[8] = (qfprom_cdata[1] & S8_P2_MASK) >> S8_P2_SHIFT;
+ p2[9] = (qfprom_cdata[4] & S9_P2_MASK) >> S9_P2_SHIFT;
+ p2[10] = (qfprom_cdata[4] & S10_P2_MASK) >> S10_P2_SHIFT;
+
+ for (i = 0; i < TSENS_1x_MAX_SENSORS; i++)
+ p2[i] = ((base1 + p2[i]) << 2);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = (qfprom_cdata[0] & BASE0_MASK);
+ p1[0] = (qfprom_cdata[2] & S0_P1_MASK) >> S0_P1_SHIFT;
+ p1[1] = (qfprom_cdata[2] & S1_P1_MASK) >> S1_P1_SHIFT;
+ p1[2] = (qfprom_cdata[2] & S2_P1_MASK_0_4) >> S2_P1_SHIFT_0_4;
+ tmp = (qfprom_cdata[3] & S2_P1_MASK_5) << S2_P1_SHIFT_5;
+ p1[2] |= tmp;
+ p1[3] = (qfprom_cdata[3] & S3_P1_MASK) >> S3_P1_SHIFT;
+ p1[4] = (qfprom_cdata[3] & S4_P1_MASK) >> S4_P1_SHIFT;
+ p1[5] = (qfprom_cdata[0] & S5_P1_MASK) >> S5_P1_SHIFT;
+ p1[6] = (qfprom_cdata[0] & S6_P1_MASK) >> S6_P1_SHIFT;
+ p1[7] = (qfprom_cdata[1] & S7_P1_MASK);
+ p1[8] = (qfprom_cdata[1] & S8_P1_MASK) >> S8_P1_SHIFT;
+ p1[9] = (qfprom_cdata[4] & S9_P1_MASK);
+ p1[10] = (qfprom_cdata[4] & S10_P1_MASK) >> S10_P1_SHIFT;
+
+ for (i = 0; i < TSENS_1x_MAX_SENSORS; i++)
+ p1[i] = (((base0) + p1[i]) << 2);
+ break;
+ default:
+ for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope(tmdev, p1, p2, mode);
+
+ return 0;
+}
+
+static int tsens1xxx_get_temp(struct tsens_sensor *sensor, int *temp)
+{
+ struct tsens_device *tmdev = NULL;
+ unsigned int code;
+ void __iomem *sensor_addr;
+ void __iomem *trdy_addr;
+ int last_temp = 0, last_temp2 = 0, last_temp3 = 0;
+ bool last_temp_valid = false, last_temp2_valid = false;
+ bool last_temp3_valid = false;
+
+ if (!sensor)
+ return -EINVAL;
+
+ tmdev = sensor->tmdev;
+
+ trdy_addr = TSENS_TRDY_ADDR(tmdev->tsens_tm_addr);
+ sensor_addr = TSENS_SN_STATUS_ADDR(tmdev->tsens_tm_addr);
+
+ code = readl_relaxed(sensor_addr +
+ (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
+ last_temp = code & TSENS_SN_STATUS_TEMP_MASK;
+
+ if (tmdev->ctrl_data->valid_status_check) {
+ if (code & TSENS_SN_STATUS_VALID)
+ last_temp_valid = true;
+ else {
+ code = readl_relaxed(sensor_addr +
+ (sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
+ last_temp2 = code & TSENS_SN_STATUS_TEMP_MASK;
+ if (code & TSENS_SN_STATUS_VALID) {
+ last_temp = last_temp2;
+ last_temp2_valid = true;
+ } else {
+ code = readl_relaxed(sensor_addr +
+ (sensor->hw_id <<
+ TSENS_STATUS_ADDR_OFFSET));
+ last_temp3 = code & TSENS_SN_STATUS_TEMP_MASK;
+ if (code & TSENS_SN_STATUS_VALID) {
+ last_temp = last_temp3;
+ last_temp3_valid = true;
+ }
+ }
+ }
+ }
+
+ if ((tmdev->ctrl_data->valid_status_check) &&
+ (!last_temp_valid && !last_temp2_valid && !last_temp3_valid)) {
+ if (last_temp == last_temp2)
+ last_temp = last_temp2;
+ else if (last_temp2 == last_temp3)
+ last_temp = last_temp3;
+ }
+
+ *temp = code_to_degc(last_temp, sensor);
+
+ return 0;
+}
+
+static int tsens_tz_activate_trip_type(struct tsens_sensor *tm_sensor,
+ int trip, enum thermal_device_mode mode)
+{
+ struct tsens_device *tmdev = NULL;
+ unsigned int reg_cntl, code, hi_code, lo_code, mask;
+
+ /* clear the interrupt and unmask */
+ if (!tm_sensor || trip < 0)
+ return -EINVAL;
+
+ tmdev = tm_sensor->tmdev;
+ if (!tmdev)
+ return -EINVAL;
+
+ lo_code = TSENS_THRESHOLD_MIN_CODE;
+ hi_code = TSENS_THRESHOLD_MAX_CODE;
+
+ reg_cntl = readl_relaxed((TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id *
+ TSENS_SN_ADDR_OFFSET)));
+
+ switch (trip) {
+ case THERMAL_TRIP_CONFIGURABLE_HI:
+ tmdev->sensor[tm_sensor->hw_id].thr_state.high_th_state = mode;
+
+ code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
+ >> TSENS_UPPER_THRESHOLD_SHIFT;
+ mask = TSENS_UPPER_STATUS_CLR;
+
+ if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
+ lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
+ break;
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
+ tmdev->sensor[tm_sensor->hw_id].thr_state.low_th_state = mode;
+
+ code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
+ mask = TSENS_LOWER_STATUS_CLR;
+
+ if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
+ hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
+ >> TSENS_UPPER_THRESHOLD_SHIFT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (mode == THERMAL_DEVICE_DISABLED)
+ writel_relaxed(reg_cntl | mask,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id * TSENS_SN_ADDR_OFFSET)));
+ else
+ writel_relaxed(reg_cntl & ~mask,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id * TSENS_SN_ADDR_OFFSET)));
+ /* Enable the thresholds */
+ mb();
+
+ return 0;
+}
+
+static int tsens1xxx_set_trip_temp(struct tsens_sensor *tm_sensor,
+ int low_temp, int high_temp)
+{
+ unsigned int reg_cntl;
+ unsigned long flags;
+ struct tsens_device *tmdev = NULL;
+ int high_code, low_code, rc = 0;
+
+ if (!tm_sensor)
+ return -EINVAL;
+
+ tmdev = tm_sensor->tmdev;
+ if (!tmdev)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
+
+ if (high_temp != INT_MAX) {
+ high_code = degc_to_code(high_temp, tm_sensor);
+ tmdev->sensor[tm_sensor->hw_id].thr_state.high_adc_code =
+ high_code;
+ tmdev->sensor[tm_sensor->hw_id].thr_state.high_temp =
+ high_temp;
+
+ reg_cntl = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id *
+ TSENS_SN_ADDR_OFFSET));
+
+ high_code <<= TSENS_UPPER_THRESHOLD_SHIFT;
+ reg_cntl &= ~TSENS_UPPER_THRESHOLD_MASK;
+ writel_relaxed(reg_cntl | high_code,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id *
+ TSENS_SN_ADDR_OFFSET)));
+ }
+
+ if (low_temp != INT_MIN) {
+ low_code = degc_to_code(low_temp, tm_sensor);
+ tmdev->sensor[tm_sensor->hw_id].thr_state.low_adc_code =
+ low_code;
+ tmdev->sensor[tm_sensor->hw_id].thr_state.low_temp =
+ low_temp;
+
+ reg_cntl = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id *
+ TSENS_SN_ADDR_OFFSET));
+
+ reg_cntl &= ~TSENS_LOWER_THRESHOLD_MASK;
+ writel_relaxed(reg_cntl | low_code,
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id *
+ TSENS_SN_ADDR_OFFSET)));
+ }
+ /* Set trip temperature thresholds */
+ mb();
+
+ if (high_temp != INT_MAX) {
+ rc = tsens_tz_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_HI,
+ THERMAL_DEVICE_ENABLED);
+ if (rc) {
+ pr_err("trip high enable error :%d\n", rc);
+ goto fail;
+ }
+ } else {
+ rc = tsens_tz_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_HI,
+ THERMAL_DEVICE_DISABLED);
+ if (rc) {
+ pr_err("trip high disable error :%d\n", rc);
+ goto fail;
+ }
+ }
+
+ if (low_temp != INT_MIN) {
+ rc = tsens_tz_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_DEVICE_ENABLED);
+ if (rc) {
+ pr_err("trip low enable activation error :%d\n", rc);
+ goto fail;
+ }
+ } else {
+ rc = tsens_tz_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_DEVICE_DISABLED);
+ if (rc) {
+ pr_err("trip low disable error :%d\n", rc);
+ goto fail;
+ }
+ }
+
+fail:
+ spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
+ return rc;
+}
+
+static irqreturn_t tsens_irq_thread(int irq, void *data)
+{
+ struct tsens_device *tm = data;
+ unsigned int i, status, threshold, temp, th_temp;
+ unsigned long flags;
+ void __iomem *sensor_status_addr;
+ void __iomem *sensor_status_ctrl_addr;
+ u32 rc = 0, addr_offset;
+
+ sensor_status_addr = TSENS_SN_STATUS_ADDR(tm->tsens_tm_addr);
+ sensor_status_ctrl_addr =
+ TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tm->tsens_tm_addr);
+
+ for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
+ bool upper_thr = false, lower_thr = false;
+
+ if (IS_ERR(tm->sensor[i].tzd))
+ continue;
+
+ rc = tsens1xxx_get_temp(&tm->sensor[i], &temp);
+ if (rc) {
+ pr_debug("Error:%d reading temp sensor:%d\n", rc, i);
+ continue;
+ }
+
+ spin_lock_irqsave(&tm->tsens_upp_low_lock, flags);
+
+ addr_offset = tm->sensor[i].hw_id *
+ TSENS_SN_ADDR_OFFSET;
+ status = readl_relaxed(sensor_status_addr + addr_offset);
+ threshold = readl_relaxed(sensor_status_ctrl_addr +
+ addr_offset);
+
+ if (status & TSENS_SN_STATUS_UPPER_STATUS) {
+ writel_relaxed(threshold | TSENS_UPPER_STATUS_CLR,
+ TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
+ tm->tsens_tm_addr + addr_offset));
+ th_temp = code_to_degc((threshold &
+ TSENS_UPPER_THRESHOLD_MASK) >>
+ TSENS_UPPER_THRESHOLD_SHIFT,
+ tm->sensor);
+ if (th_temp > temp) {
+ pr_debug("Re-arm high threshold\n");
+ rc = tsens_tz_activate_trip_type(
+ &tm->sensor[i],
+ THERMAL_TRIP_CONFIGURABLE_HI,
+ THERMAL_DEVICE_ENABLED);
+ if (rc)
+ pr_err("high rearm failed");
+ } else {
+ upper_thr = true;
+ tm->sensor[i].thr_state.high_th_state =
+ THERMAL_DEVICE_DISABLED;
+ }
+ }
+
+ if (status & TSENS_SN_STATUS_LOWER_STATUS) {
+ writel_relaxed(threshold | TSENS_LOWER_STATUS_CLR,
+ TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
+ tm->tsens_tm_addr + addr_offset));
+ th_temp = code_to_degc((threshold &
+ TSENS_LOWER_THRESHOLD_MASK),
+ tm->sensor);
+ if (th_temp < temp) {
+ pr_debug("Re-arm Low threshold\n");
+ rc = tsens_tz_activate_trip_type(
+ &tm->sensor[i],
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_DEVICE_ENABLED);
+ if (rc)
+ pr_err("low rearm failed");
+ } else {
+ lower_thr = true;
+ tm->sensor[i].thr_state.low_th_state =
+ THERMAL_DEVICE_DISABLED;
+ }
+ }
+ spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags);
+
+ if (upper_thr || lower_thr) {
+ pr_debug("sensor:%d trigger temp (%d degC)\n",
+ tm->sensor[i].hw_id,
+ code_to_degc((status &
+ TSENS_SN_STATUS_TEMP_MASK),
+ tm->sensor));
+ of_thermal_handle_trip(tm->sensor[i].tzd);
+ }
+ }
+
+ /* Disable monitoring sensor trip threshold for triggered sensor */
+ mb();
+
+ return IRQ_HANDLED;
+}
+
+static int tsens1xxx_hw_sensor_en(struct tsens_device *tmdev,
+ u32 sensor_id)
+{
+ void __iomem *srot_addr;
+ unsigned int srot_val, sensor_en;
+
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+ srot_val = readl_relaxed(srot_addr);
+ srot_val = TSENS_CTRL_SENSOR_EN_MASK(srot_val);
+
+ sensor_en = ((1 << sensor_id) & srot_val);
+
+ return sensor_en;
+}
+
+static int tsens1xxx_hw_init(struct tsens_device *tmdev)
+{
+ void __iomem *srot_addr;
+ unsigned int srot_val;
+
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+ srot_val = readl_relaxed(srot_addr);
+ if (!(srot_val & TSENS_EN)) {
+ pr_err("TSENS device is not enabled\n");
+ return -ENODEV;
+ }
+
+ writel_relaxed(TSENS_INTERRUPT_EN,
+ TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_tm_addr));
+
+ spin_lock_init(&tmdev->tsens_upp_low_lock);
+
+ return 0;
+}
+
+static const struct tsens_irqs tsens1xxx_irqs[] = {
+ { "tsens-upper-lower", tsens_irq_thread},
+};
+
+static int tsens1xxx_register_interrupts(struct tsens_device *tmdev)
+{
+ struct platform_device *pdev;
+ int i, rc;
+
+ if (!tmdev)
+ return -EINVAL;
+
+ pdev = tmdev->pdev;
+
+ for (i = 0; i < ARRAY_SIZE(tsens1xxx_irqs); i++) {
+ int irq;
+
+ irq = platform_get_irq_byname(pdev, tsens1xxx_irqs[i].name);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq %s\n",
+ tsens1xxx_irqs[i].name);
+ return irq;
+ }
+
+ rc = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ tsens1xxx_irqs[i].handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ tsens1xxx_irqs[i].name, tmdev);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to get irq %s\n",
+ tsens1xxx_irqs[i].name);
+ return rc;
+ }
+ enable_irq_wake(irq);
+ }
+
+ return 0;
+}
+
+static const struct tsens_ops ops_tsens1xxx = {
+ .hw_init = tsens1xxx_hw_init,
+ .get_temp = tsens1xxx_get_temp,
+ .set_trips = tsens1xxx_set_trip_temp,
+ .interrupts_reg = tsens1xxx_register_interrupts,
+ .sensor_en = tsens1xxx_hw_sensor_en,
+ .calibrate = calibrate_8937,
+};
+
+const struct tsens_data data_tsens14xx = {
+ .ops = &ops_tsens1xxx,
+ .valid_status_check = true,
+ .mtc = true,
+};
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index 50c847f..af60a4b 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. 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 version 2 and
@@ -59,9 +59,11 @@
#define TSENS_TM_SCALE_DECI_MILLIDEG 100
#define TSENS_DEBUG_WDOG_TRIGGER_COUNT 5
#define TSENS_TM_WATCHDOG_LOG(n) ((n) + 0x13c)
-
#define TSENS_EN BIT(0)
#define TSENS_CTRL_SENSOR_EN_MASK(n) ((n >> 3) & 0xffff)
+#define TSENS_TM_TRDY(n) ((n) + 0xe4)
+#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE BIT(3)
+#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT 3
static void msm_tsens_convert_temp(int last_temp, int *temp)
{
@@ -79,7 +81,7 @@
{
struct tsens_device *tmdev = NULL;
unsigned int code;
- void __iomem *sensor_addr;
+ void __iomem *sensor_addr, *trdy;
int last_temp = 0, last_temp2 = 0, last_temp3 = 0;
if (!sensor)
@@ -87,6 +89,14 @@
tmdev = sensor->tmdev;
sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_tm_addr);
+ trdy = TSENS_TM_TRDY(tmdev->tsens_tm_addr);
+
+ code = readl_relaxed_no_log(trdy);
+ if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >>
+ TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) {
+ pr_err("TSENS device first round not complete0x%x\n", code);
+ return -ENODATA;
+ }
code = readl_relaxed_no_log(sensor_addr +
(sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
diff --git a/drivers/usb/gadget/ci13xxx_msm.c b/drivers/usb/gadget/ci13xxx_msm.c
index a9c073b..d4c243c 100644
--- a/drivers/usb/gadget/ci13xxx_msm.c
+++ b/drivers/usb/gadget/ci13xxx_msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2018, The Linux Foundation. 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 version 2 and
@@ -11,6 +11,7 @@
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/ulpi.h>
#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
#include "ci13xxx_udc.c"
@@ -24,9 +25,13 @@
int wake_gpio;
int wake_irq;
bool wake_irq_state;
+ struct pinctrl *ci13xxx_pinctrl;
+ struct timer_list irq_enable_timer;
+ bool irq_disabled;
};
static struct ci13xxx_udc_context _udc_ctxt;
+#define IRQ_ENABLE_DELAY (jiffies + msecs_to_jiffies(1000))
static irqreturn_t msm_udc_irq(int irq, void *data)
{
@@ -36,6 +41,7 @@
static void ci13xxx_msm_suspend(void)
{
struct device *dev = _udc->gadget.dev.parent;
+
dev_dbg(dev, "ci13xxx_msm_suspend\n");
if (_udc_ctxt.wake_irq && !_udc_ctxt.wake_irq_state) {
@@ -48,6 +54,7 @@
static void ci13xxx_msm_resume(void)
{
struct device *dev = _udc->gadget.dev.parent;
+
dev_dbg(dev, "ci13xxx_msm_resume\n");
if (_udc_ctxt.wake_irq && _udc_ctxt.wake_irq_state) {
@@ -62,11 +69,27 @@
struct ci13xxx *udc = _udc;
struct usb_phy *phy = udc->transceiver;
- if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP))
+ if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) {
+ u32 temp;
+
usb_phy_io_write(phy,
ULPI_MISC_A_VBUSVLDEXT |
ULPI_MISC_A_VBUSVLDEXTSEL,
ULPI_CLR(ULPI_MISC_A));
+
+ /* Notify LINK of VBUS LOW */
+ temp = readl_relaxed(USB_USBCMD);
+ temp &= ~USBCMD_SESS_VLD_CTRL;
+ writel_relaxed(temp, USB_USBCMD);
+
+ /*
+ * Add memory barrier as it is must to complete
+ * above USB PHY and Link register writes before
+ * moving ahead with USB peripheral mode enumeration,
+ * otherwise USB peripheral mode may not work.
+ */
+ mb();
+ }
}
/* Link power management will reduce power consumption by
@@ -102,9 +125,9 @@
ULPI_MISC_A_VBUSVLDEXTSEL,
ULPI_SET(ULPI_MISC_A));
- temp = readl_relaxed(USB_GENCONFIG2);
- temp |= GENCFG2_SESS_VLD_CTRL_EN;
- writel_relaxed(temp, USB_GENCONFIG2);
+ temp = readl_relaxed(USB_GENCONFIG_2);
+ temp |= GENCONFIG_2_SESS_VLD_CTRL_EN;
+ writel_relaxed(temp, USB_GENCONFIG_2);
temp = readl_relaxed(USB_USBCMD);
temp |= USBCMD_SESS_VLD_CTRL;
@@ -125,10 +148,17 @@
struct ci13xxx *udc = _udc;
struct usb_phy *phy = udc->transceiver;
struct device *dev = udc->gadget.dev.parent;
+ int temp;
writel_relaxed(0, USB_AHBBURST);
writel_relaxed(0x08, USB_AHBMODE);
+ /* workaround for rx buffer collision issue */
+ temp = readl_relaxed(USB_GENCONFIG);
+ temp &= ~GENCONFIG_TXFIFO_IDLE_FORCE_DISABLE;
+ temp &= ~GENCONFIG_ULPI_SERIAL_EN;
+ writel_relaxed(temp, USB_GENCONFIG);
+
if (udc->gadget.l1_supported)
ci13xxx_msm_set_l1(udc);
@@ -149,7 +179,24 @@
}
}
-static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
+static void ci13xxx_msm_mark_err_event(void)
+{
+ struct ci13xxx *udc = _udc;
+ struct msm_otg *otg;
+
+ if (udc == NULL)
+ return;
+
+ if (udc->transceiver == NULL)
+ return;
+
+ otg = container_of(udc->transceiver, struct msm_otg, phy);
+
+ /* This will trigger hardware reset before next connection */
+ otg->err_event_seen = true;
+}
+
+static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned int event)
{
struct device *dev = udc->gadget.dev.parent;
@@ -175,13 +222,36 @@
dev_info(dev, "CI13XXX_CONTROLLER_RESUME_EVENT received\n");
ci13xxx_msm_resume();
break;
-
+ case CI13XXX_CONTROLLER_ERROR_EVENT:
+ dev_info(dev, "CI13XXX_CONTROLLER_ERROR_EVENT received\n");
+ ci13xxx_msm_mark_err_event();
+ break;
+ case CI13XXX_CONTROLLER_UDC_STARTED_EVENT:
+ dev_info(dev,
+ "CI13XXX_CONTROLLER_UDC_STARTED_EVENT received\n");
+ break;
default:
dev_dbg(dev, "unknown ci13xxx_udc event\n");
break;
}
}
+static bool ci13xxx_msm_in_lpm(struct ci13xxx *udc)
+{
+ struct msm_otg *otg;
+
+ if (udc == NULL)
+ return false;
+
+ if (udc->transceiver == NULL)
+ return false;
+
+ otg = container_of(udc->transceiver, struct msm_otg, phy);
+
+ return (atomic_read(&otg->in_lpm) != 0);
+}
+
+
static irqreturn_t ci13xxx_msm_resume_irq(int irq, void *data)
{
struct ci13xxx *udc = _udc;
@@ -200,10 +270,10 @@
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
CI13XXX_ZERO_ITC |
- CI13XXX_DISABLE_STREAMING |
- CI13XXX_IS_OTG,
+ CI13XXX_DISABLE_STREAMING,
.nz_itc = 0,
.notify_event = ci13xxx_msm_notify_event,
+ .in_lpm = ci13xxx_msm_in_lpm,
};
static int ci13xxx_msm_install_wake_gpio(struct platform_device *pdev,
@@ -211,10 +281,20 @@
{
int wake_irq;
int ret;
+ struct pinctrl_state *set_state;
dev_dbg(&pdev->dev, "ci13xxx_msm_install_wake_gpio\n");
_udc_ctxt.wake_gpio = res->start;
+ if (_udc_ctxt.ci13xxx_pinctrl) {
+ set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
+ "ci13xxx_active");
+ if (IS_ERR(set_state)) {
+ pr_err("cannot get ci13xxx pinctrl active state\n");
+ return PTR_ERR(set_state);
+ }
+ pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl, set_state);
+ }
gpio_request(_udc_ctxt.wake_gpio, "USB_RESUME");
gpio_direction_input(_udc_ctxt.wake_gpio);
wake_irq = gpio_to_irq(_udc_ctxt.wake_gpio);
@@ -238,20 +318,42 @@
gpio_free:
gpio_free(_udc_ctxt.wake_gpio);
+ if (_udc_ctxt.ci13xxx_pinctrl) {
+ set_state = pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
+ "ci13xxx_sleep");
+ if (IS_ERR(set_state))
+ pr_err("cannot get ci13xxx pinctrl sleep state\n");
+ else
+ pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
+ set_state);
+ }
_udc_ctxt.wake_gpio = 0;
return ret;
}
static void ci13xxx_msm_uninstall_wake_gpio(struct platform_device *pdev)
{
+ struct pinctrl_state *set_state;
+
dev_dbg(&pdev->dev, "ci13xxx_msm_uninstall_wake_gpio\n");
if (_udc_ctxt.wake_gpio) {
gpio_free(_udc_ctxt.wake_gpio);
+ if (_udc_ctxt.ci13xxx_pinctrl) {
+ set_state =
+ pinctrl_lookup_state(_udc_ctxt.ci13xxx_pinctrl,
+ "ci13xxx_sleep");
+ if (IS_ERR(set_state))
+ pr_err("cannot get ci13xxx pinctrl sleep state\n");
+ else
+ pinctrl_select_state(_udc_ctxt.ci13xxx_pinctrl,
+ set_state);
+ }
_udc_ctxt.wake_gpio = 0;
}
}
+static void enable_usb_irq_timer_func(unsigned long data);
static int ci13xxx_msm_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -271,6 +373,15 @@
1 << (pdata->log2_itc-1);
is_l1_supported = pdata->l1_supported;
+ /* Set ahb2ahb bypass flag if it is requested. */
+ if (pdata->enable_ahb2ahb_bypass)
+ ci13xxx_msm_udc_driver.flags |=
+ CI13XXX_ENABLE_AHB2AHB_BYPASS;
+
+ /* Clear disable streaming flag if is requested. */
+ if (pdata->enable_streaming)
+ ci13xxx_msm_udc_driver.flags &=
+ ~CI13XXX_DISABLE_STREAMING;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -301,6 +412,17 @@
}
res = platform_get_resource_byname(pdev, IORESOURCE_IO, "USB_RESUME");
+ /* Get pinctrl if target uses pinctrl */
+ _udc_ctxt.ci13xxx_pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR(_udc_ctxt.ci13xxx_pinctrl)) {
+ if (of_property_read_bool(pdev->dev.of_node, "pinctrl-names")) {
+ dev_err(&pdev->dev, "Error encountered while getting pinctrl");
+ ret = PTR_ERR(_udc_ctxt.ci13xxx_pinctrl);
+ goto udc_remove;
+ }
+ dev_dbg(&pdev->dev, "Target does not use pinctrl\n");
+ _udc_ctxt.ci13xxx_pinctrl = NULL;
+ }
if (res) {
ret = ci13xxx_msm_install_wake_gpio(pdev, res);
if (ret < 0) {
@@ -316,7 +438,11 @@
goto gpio_uninstall;
}
+ setup_timer(&_udc_ctxt.irq_enable_timer, enable_usb_irq_timer_func,
+ (unsigned long)NULL);
+
pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
@@ -341,6 +467,18 @@
return 0;
}
+void ci13xxx_msm_shutdown(struct platform_device *pdev)
+{
+ ci13xxx_pullup(&_udc->gadget, 0);
+}
+
+void msm_hw_soft_reset(void)
+{
+ struct ci13xxx *udc = _udc;
+
+ hw_device_reset(udc);
+}
+
void msm_hw_bam_disable(bool bam_disable)
{
u32 val;
@@ -354,12 +492,52 @@
writel_relaxed(val, USB_GENCONFIG);
}
+void msm_usb_irq_disable(bool disable)
+{
+ struct ci13xxx *udc = _udc;
+ unsigned long flags;
+
+ spin_lock_irqsave(udc->lock, flags);
+
+ if (_udc_ctxt.irq_disabled == disable) {
+ pr_debug("Interrupt state already disable = %d\n", disable);
+ if (disable)
+ mod_timer(&_udc_ctxt.irq_enable_timer,
+ IRQ_ENABLE_DELAY);
+ spin_unlock_irqrestore(udc->lock, flags);
+ return;
+ }
+
+ if (disable) {
+ disable_irq_nosync(_udc_ctxt.irq);
+ /* start timer here */
+ pr_debug("%s: Disabling interrupts\n", __func__);
+ mod_timer(&_udc_ctxt.irq_enable_timer, IRQ_ENABLE_DELAY);
+ _udc_ctxt.irq_disabled = true;
+
+ } else {
+ pr_debug("%s: Enabling interrupts\n", __func__);
+ del_timer(&_udc_ctxt.irq_enable_timer);
+ enable_irq(_udc_ctxt.irq);
+ _udc_ctxt.irq_disabled = false;
+ }
+
+ spin_unlock_irqrestore(udc->lock, flags);
+}
+
+static void enable_usb_irq_timer_func(unsigned long data)
+{
+ pr_debug("enabling interrupt from timer\n");
+ msm_usb_irq_disable(false);
+}
+
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
.driver = {
.name = "msm_hsusb",
},
.remove = ci13xxx_msm_remove,
+ .shutdown = ci13xxx_msm_shutdown,
};
MODULE_ALIAS("platform:msm_hsusb");
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index b8389e2..28aaa1f 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -58,6 +58,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -66,22 +67,17 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/usb/msm_hsusb.h>
-#include <linux/tracepoint.h>
-#include <mach/usb_trace.h>
-#include "ci13xxx_udc.h"
-/* Turns on streaming. overrides CI13XXX_DISABLE_STREAMING */
-static unsigned int streaming;
-module_param(streaming, uint, S_IRUGO | S_IWUSR);
+#include "ci13xxx_udc.h"
/******************************************************************************
* DEFINE
*****************************************************************************/
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define USB_MAX_TIMEOUT 25 /* 25msec timeout */
#define EP_PRIME_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
#define MAX_PRIME_CHECK_RETRY 3 /*Wait for 3sec for EP prime failure */
+#define EXTRA_ALLOCATION_SIZE 256
/* ctrl register bank access */
static DEFINE_SPINLOCK(udc_lock);
@@ -140,27 +136,12 @@
return n ? n-1 : 32;
}
-struct ci13xxx_ebi_err_entry {
- u32 *usb_req_buf;
- u32 usb_req_length;
- u32 ep_info;
- struct ci13xxx_ebi_err_entry *next;
-};
-
-struct ci13xxx_ebi_err_data {
- u32 ebi_err_addr;
- u32 apkt0;
- u32 apkt1;
- struct ci13xxx_ebi_err_entry *ebi_err_entry;
-};
-static struct ci13xxx_ebi_err_data *ebi_err_data;
-
/******************************************************************************
* HW block
*****************************************************************************/
/* register bank descriptor */
static struct {
- unsigned lpm; /* is LPM? */
+ unsigned int lpm; /* is LPM? */
void __iomem *abs; /* bus map offset */
void __iomem *cap; /* bus map offset + CAP offset + CAP data */
size_t size; /* bank size */
@@ -195,7 +176,7 @@
#define REMOTE_WAKEUP_DELAY msecs_to_jiffies(200)
/* maximum number of enpoints: valid only after hw_device_reset() */
-static unsigned hw_ep_max;
+static unsigned int hw_ep_max;
static void dbg_usb_op_fail(u8 addr, const char *name,
const struct ci13xxx_ep *mep);
/**
@@ -394,17 +375,26 @@
struct ci13xxx *udc = _udc;
if (dma) {
- if (streaming || !(udc->udc_driver->flags &
- CI13XXX_DISABLE_STREAMING))
+ if (!(udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)) {
hw_cwrite(CAP_USBMODE, USBMODE_SDIS, 0);
- else
+ pr_debug("%s(): streaming mode is enabled. USBMODE:%x\n",
+ __func__, hw_cread(CAP_USBMODE, ~0));
+
+ } else {
hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
+ pr_debug("%s(): streaming mode is disabled. USBMODE:%x\n",
+ __func__, hw_cread(CAP_USBMODE, ~0));
+ }
hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma);
- if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
- CI13XXX_CONTROLLER_CONNECT_EVENT);
+
+ /* Set BIT(31) to enable AHB2AHB Bypass functionality */
+ if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+ hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, AHB2AHB_BYPASS);
+ pr_debug("%s(): ByPass Mode is enabled. AHBMODE:%x\n",
+ __func__, hw_aread(ABS_AHBMODE, ~0));
+ }
/* interrupt, error, port change, reset, sleep/suspend */
hw_cwrite(CAP_USBINTR, ~0,
@@ -413,6 +403,12 @@
} else {
hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
hw_cwrite(CAP_USBINTR, ~0, 0);
+ /* Clear BIT(31) to disable AHB2AHB Bypass functionality */
+ if (udc->udc_driver->flags & CI13XXX_ENABLE_AHB2AHB_BYPASS) {
+ hw_awrite(ABS_AHBMODE, AHB2AHB_BYPASS, 0);
+ pr_debug("%s(): ByPass Mode is disabled. AHBMODE:%x\n",
+ __func__, hw_aread(ABS_AHBMODE, ~0));
+ }
}
return 0;
}
@@ -469,6 +465,10 @@
dir ? "IN" : "OUT");
debug_ept_flush_info(num, dir);
_udc->skip_flush = true;
+ /* Notify to trigger h/w reset recovery later */
+ if (_udc->udc_driver->notify_event)
+ _udc->udc_driver->notify_event(_udc,
+ CI13XXX_CONTROLLER_ERROR_EVENT);
return 0;
}
}
@@ -716,7 +716,7 @@
*/
static size_t hw_register_read(u32 *buf, size_t size)
{
- unsigned i;
+ unsigned int i;
if (size > hw_bank.size)
size = hw_bank.size;
@@ -827,9 +827,6 @@
/* ESS flushes only at end?!? */
hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */
- /* clear setup token semaphores */
- hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */
-
/* clear complete status */
hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */
@@ -841,8 +838,10 @@
/* reset all endpoints ? */
- /* reset internal status and wait for further instructions
- no need to verify the port reset status (ESS does it) */
+ /*
+ * reset internal status and wait for further instructions
+ * no need to verify the port reset status (ESS does it)
+ */
return 0;
}
@@ -862,7 +861,7 @@
struct usb_gadget *gadget = &udc->gadget;
int n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -890,7 +889,7 @@
return n;
}
-static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
+static DEVICE_ATTR(device, 0400, show_device, NULL);
/**
* show_driver: prints information about attached gadget (if any)
@@ -904,7 +903,7 @@
struct usb_gadget_driver *driver = udc->driver;
int n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -921,7 +920,7 @@
return n;
}
-static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
+static DEVICE_ATTR(driver, 0400, show_driver, NULL);
/* Maximum event message length */
#define DBG_DATA_MSG 64UL
@@ -931,10 +930,10 @@
/* Event buffer descriptor */
static struct {
- char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
- unsigned idx; /* index */
- unsigned tty; /* print to console? */
- rwlock_t lck; /* lock */
+ char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */
+ unsigned int idx; /* index */
+ unsigned int tty; /* print to console? */
+ rwlock_t lck; /* lock */
} dbg_data = {
.idx = 0,
.tty = 0,
@@ -945,7 +944,7 @@
* dbg_dec: decrements debug event index
* @idx: buffer index
*/
-static void dbg_dec(unsigned *idx)
+static void dbg_dec(unsigned int *idx)
{
*idx = (*idx - 1) & (DBG_DATA_MAX-1);
}
@@ -954,16 +953,16 @@
* dbg_inc: increments debug event index
* @idx: buffer index
*/
-static void dbg_inc(unsigned *idx)
+static void dbg_inc(unsigned int *idx)
{
*idx = (*idx + 1) & (DBG_DATA_MAX-1);
}
static unsigned int ep_addr_txdbg_mask;
-module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
+module_param(ep_addr_txdbg_mask, uint, 0644);
static unsigned int ep_addr_rxdbg_mask;
-module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
+module_param(ep_addr_rxdbg_mask, uint, 0644);
static int allow_dbg_print(u8 addr)
{
@@ -985,6 +984,20 @@
return 0;
}
+#define TIME_BUF_LEN 20
+/*get_timestamp - returns time of day in us */
+static char *get_timestamp(char *tbuf)
+{
+ unsigned long long t;
+ unsigned long nanosec_rem;
+
+ t = cpu_clock(smp_processor_id());
+ nanosec_rem = do_div(t, 1000000000)/1000;
+ scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
+ nanosec_rem);
+ return tbuf;
+}
+
/**
* dbg_print: prints the common part of the event
* @addr: endpoint address
@@ -994,30 +1007,25 @@
*/
static void dbg_print(u8 addr, const char *name, int status, const char *extra)
{
- struct timeval tval;
- unsigned int stamp;
unsigned long flags;
+ char tbuf[TIME_BUF_LEN];
if (!allow_dbg_print(addr))
return;
write_lock_irqsave(&dbg_data.lck, flags);
- do_gettimeofday(&tval);
- stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */
- stamp = stamp * 1000000 + tval.tv_usec;
-
scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
- "%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
+ "%s\t? %02X %-7.7s %4i ?\t%s\n",
+ get_timestamp(tbuf), addr, name, status, extra);
dbg_inc(&dbg_data.idx);
write_unlock_irqrestore(&dbg_data.lck, flags);
if (dbg_data.tty != 0)
- pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
- stamp, addr, name, status, extra);
+ pr_notice("%s\t? %02X %-7.7s %4i ?\t%s\n",
+ get_timestamp(tbuf), addr, name, status, extra);
}
/**
@@ -1110,8 +1118,8 @@
list_for_each(ptr, &mep->qh.queue) {
req = list_entry(ptr, struct ci13xxx_req, queue);
scnprintf(msg, sizeof(msg),
- "%08X:%08X:%08X\n",
- req->dma, req->ptr->next,
+ "%pKa:%08X:%08X\n",
+ &req->dma, req->ptr->next,
req->ptr->token);
dbg_print(addr, "REQ", 0, msg);
scnprintf(msg, sizeof(msg), "%08X:%d\n",
@@ -1131,9 +1139,9 @@
char *buf)
{
unsigned long flags;
- unsigned i, j, n = 0;
+ unsigned int i, j, n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -1166,15 +1174,15 @@
static ssize_t store_events(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- unsigned tty;
+ unsigned int tty;
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
+ dbg_trace("[%s] %pK, %d\n", __func__, buf, count);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
goto done;
}
- if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
+ if (kstrtouint(buf, 10, &tty) || tty > 1) {
dev_err(dev, "<1|0>: enable|disable console log\n");
goto done;
}
@@ -1185,7 +1193,7 @@
done:
return count;
}
-static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
+static DEVICE_ATTR(events, 0600, show_events, store_events);
/**
* show_inters: interrupt status, enable status and historic
@@ -1198,9 +1206,9 @@
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 intr;
- unsigned i, j, n = 0;
+ unsigned int i, j, n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -1271,9 +1279,9 @@
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
- unsigned en, bit;
+ unsigned int en, bit;
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
+ dbg_trace("[%s] %pK, %d\n", __func__, buf, count);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
goto done;
@@ -1299,7 +1307,7 @@
done:
return count;
}
-static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
+static DEVICE_ATTR(inters, 0600, show_inters, store_inters);
/**
* show_port_test: reads port test mode
@@ -1311,9 +1319,9 @@
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
- unsigned mode;
+ unsigned int mode;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -1337,15 +1345,15 @@
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
- unsigned mode;
+ unsigned int mode;
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
+ dbg_trace("[%s] %pK, %d\n", __func__, buf, count);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
goto done;
}
- if (sscanf(buf, "%u", &mode) != 1) {
+ if (kstrtouint(buf, 10, &mode)) {
dev_err(dev, "<mode>: set port test mode");
goto done;
}
@@ -1358,8 +1366,7 @@
done:
return count;
}
-static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
- show_port_test, store_port_test);
+static DEVICE_ATTR(port_test, 0600, show_port_test, store_port_test);
/**
* show_qheads: DMA contents of all queue heads
@@ -1371,9 +1378,9 @@
{
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
- unsigned i, j, n = 0;
+ unsigned int i, j, n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -1383,6 +1390,7 @@
for (i = 0; i < hw_ep_max/2; i++) {
struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2];
+
n += scnprintf(buf + n, PAGE_SIZE - n,
"EP=%02i: RX=%08X TX=%08X\n",
i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
@@ -1397,7 +1405,7 @@
return n;
}
-static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
+static DEVICE_ATTR(qheads, 0400, show_qheads, NULL);
/**
* show_registers: dumps all registers
@@ -1411,19 +1419,17 @@
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 *dump;
- unsigned i, k, n = 0;
+ unsigned int i, k, n = 0;
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
}
dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
- if (!dump) {
- dev_err(dev, "%s: out of memory\n", __func__);
+ if (!dump)
return 0;
- }
spin_lock_irqsave(udc->lock, flags);
k = hw_register_read(dump, DUMP_ENTRIES);
@@ -1432,7 +1438,7 @@
for (i = 0; i < k; i++) {
n += scnprintf(buf + n, PAGE_SIZE - n,
"reg[0x%04X] = 0x%08X\n",
- i * (unsigned)sizeof(u32), dump[i]);
+ i * (unsigned int)sizeof(u32), dump[i]);
}
kfree(dump);
@@ -1451,7 +1457,7 @@
struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long addr, data, flags;
- dbg_trace("[%s] %p, %d\n", __func__, buf, count);
+ dbg_trace("[%s] %pK, %d\n", __func__, buf, count);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
goto done;
@@ -1470,8 +1476,7 @@
done:
return count;
}
-static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
- show_registers, store_registers);
+static DEVICE_ATTR(registers, 0600, show_registers, store_registers);
/**
* show_requests: DMA contents of all requests currently queued (all endpts)
@@ -1485,9 +1490,9 @@
unsigned long flags;
struct list_head *ptr = NULL;
struct ci13xxx_req *req = NULL;
- unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
+ unsigned int i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
- dbg_trace("[%s] %p\n", __func__, buf);
+ dbg_trace("[%s] %pK\n", __func__, buf);
if (attr == NULL || buf == NULL) {
dev_err(dev, "[%s] EINVAL\n", __func__);
return 0;
@@ -1513,7 +1518,7 @@
return n;
}
-static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
+static DEVICE_ATTR(requests, 0400, show_requests, NULL);
/* EP# and Direction */
static ssize_t prime_ept(struct device *dev,
@@ -1541,6 +1546,7 @@
mEp->qh.ptr->td.next = mReq->dma;
mEp->qh.ptr->td.token &= ~TD_STATUS;
+ /* Makes sure that above write goes through */
wmb();
hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n));
@@ -1555,7 +1561,7 @@
return count;
}
-static DEVICE_ATTR(prime, S_IWUSR, NULL, prime_ept);
+static DEVICE_ATTR(prime, 0200, NULL, prime_ept);
/* EP# and Direction */
static ssize_t print_dtds(struct device *dev,
@@ -1580,15 +1586,14 @@
mEp = &udc->ci13xxx_ep[ep_num];
n = hw_ep_bit(mEp->num, mEp->dir);
- pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s"
- "dTD_update_fail_count: %lu "
- "mEp->dTD_update_fail_count: %lu"
- "mEp->prime_fail_count: %lu\n", __func__,
+ pr_info("%s: prime:%08x stat:%08x ep#%d dir:%s dTD_update_fail_count: %lu mEp->dTD_update_fail_count: %lu mEp->dTD_active_re_q_count: %lu mEp->prime_fail_count: %lu\n",
+ __func__,
hw_cread(CAP_ENDPTPRIME, ~0),
hw_cread(CAP_ENDPTSTAT, ~0),
mEp->num, mEp->dir ? "IN" : "OUT",
udc->dTD_update_fail_count,
mEp->dTD_update_fail_count,
+ mEp->dTD_active_re_q_count,
mEp->prime_fail_count);
pr_info("QH: cap:%08x cur:%08x next:%08x token:%08x\n",
@@ -1598,15 +1603,15 @@
list_for_each(ptr, &mEp->qh.queue) {
req = list_entry(ptr, struct ci13xxx_req, queue);
- pr_info("\treq:%08x next:%08x token:%08x page0:%08x status:%d\n",
- req->dma, req->ptr->next, req->ptr->token,
+ pr_info("\treq:%pKa next:%08x token:%08x page0:%08x status:%d\n",
+ &req->dma, req->ptr->next, req->ptr->token,
req->ptr->page[0], req->req.status);
}
done:
return count;
}
-static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);
+static DEVICE_ATTR(dtds, 0200, NULL, print_dtds);
static int ci13xxx_wakeup(struct usb_gadget *_gadget)
{
@@ -1617,13 +1622,15 @@
trace();
spin_lock_irqsave(udc->lock, flags);
- if (!udc->remote_wakeup) {
+ if (!udc->gadget.remote_wakeup) {
ret = -EOPNOTSUPP;
dbg_trace("remote wakeup feature is not enabled\n");
goto out;
}
spin_unlock_irqrestore(udc->lock, flags);
+ pm_runtime_get_sync(&_gadget->dev);
+
udc->udc_driver->notify_event(udc,
CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);
@@ -1634,9 +1641,13 @@
if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
ret = -EINVAL;
dbg_trace("port is not suspended\n");
+ pm_runtime_put(&_gadget->dev);
goto out;
}
hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
+
+ pm_runtime_mark_last_busy(&_gadget->dev);
+ pm_runtime_put_autosuspend(&_gadget->dev);
out:
spin_unlock_irqrestore(udc->lock, flags);
return ret;
@@ -1653,7 +1664,7 @@
* if wakeup conditions are still met.
*/
spin_lock_irqsave(udc->lock, flags);
- do_wake = udc->suspended && udc->remote_wakeup;
+ do_wake = udc->suspended && udc->gadget.remote_wakeup;
spin_unlock_irqrestore(udc->lock, flags);
if (do_wake)
@@ -1669,7 +1680,7 @@
return count;
}
-static DEVICE_ATTR(wakeup, S_IWUSR, 0, usb_remote_wakeup);
+static DEVICE_ATTR(wakeup, 0200, 0, usb_remote_wakeup);
/**
* dbg_create_files: initializes the attribute interface
@@ -1677,7 +1688,7 @@
*
* This function returns an error code
*/
-__maybe_unused static int dbg_create_files(struct device *dev)
+static int __maybe_unused dbg_create_files(struct device *dev)
{
int retval = 0;
@@ -1749,7 +1760,7 @@
*
* This function returns an error code
*/
-__maybe_unused static int dbg_remove_files(struct device *dev)
+static int __maybe_unused dbg_remove_files(struct device *dev)
{
if (dev == NULL)
return -EINVAL;
@@ -1765,72 +1776,6 @@
return 0;
}
-static void dump_usb_info(void *ignore, unsigned int ebi_addr,
- unsigned int ebi_apacket0, unsigned int ebi_apacket1)
-{
- struct ci13xxx *udc = _udc;
- unsigned long flags;
- struct list_head *ptr = NULL;
- struct ci13xxx_req *req = NULL;
- struct ci13xxx_ep *mEp;
- unsigned i;
- struct ci13xxx_ebi_err_entry *temp_dump;
- static int count;
- u32 epdir = 0;
-
- if (count)
- return;
- count++;
-
- pr_info("%s: USB EBI error detected\n", __func__);
-
- ebi_err_data = kmalloc(sizeof(struct ci13xxx_ebi_err_data),
- GFP_ATOMIC);
- if (!ebi_err_data) {
- pr_err("%s: memory alloc failed for ebi_err_data\n", __func__);
- return;
- }
-
- ebi_err_data->ebi_err_entry = kmalloc(
- sizeof(struct ci13xxx_ebi_err_entry),
- GFP_ATOMIC);
- if (!ebi_err_data->ebi_err_entry) {
- kfree(ebi_err_data);
- pr_err("%s: memory alloc failed for ebi_err_entry\n", __func__);
- return;
- }
-
- ebi_err_data->ebi_err_addr = ebi_addr;
- ebi_err_data->apkt0 = ebi_apacket0;
- ebi_err_data->apkt1 = ebi_apacket1;
-
- temp_dump = ebi_err_data->ebi_err_entry;
- pr_info("\n DUMPING USB Requests Information\n");
- spin_lock_irqsave(udc->lock, flags);
- for (i = 0; i < hw_ep_max; i++) {
- list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) {
- mEp = &udc->ci13xxx_ep[i];
- req = list_entry(ptr, struct ci13xxx_req, queue);
-
- temp_dump->usb_req_buf = req->req.buf;
- temp_dump->usb_req_length = req->req.length;
- epdir = mEp->dir;
- temp_dump->ep_info = mEp->num | (epdir << 15);
-
- temp_dump->next = kmalloc(
- sizeof(struct ci13xxx_ebi_err_entry),
- GFP_ATOMIC);
- if (!temp_dump->next) {
- pr_err("%s: memory alloc failed\n", __func__);
- spin_unlock_irqrestore(udc->lock, flags);
- return;
- }
- temp_dump = temp_dump->next;
- }
- }
- spin_unlock_irqrestore(udc->lock, flags);
-}
-
/******************************************************************************
* UTIL block
*****************************************************************************/
@@ -1869,6 +1814,7 @@
req = list_entry(mep->qh.queue.next, struct ci13xxx_req, queue);
+ /* clean speculative fetches on req->ptr->token */
mb();
if (!(TD_STATUS_ACTIVE & req->ptr->token))
goto out;
@@ -1882,8 +1828,8 @@
mep->qh.ptr->td.next, mep->qh.ptr->td.token);
list_for_each(ptr, &mep->qh.queue) {
req = list_entry(ptr, struct ci13xxx_req, queue);
- pr_info("\treq:%08xnext:%08xtkn:%08xpage0:%08xsts:%d\n",
- req->dma, req->ptr->next,
+ pr_info("\treq:%pKa:%08xtkn:%08xpage0:%08xsts:%d\n",
+ &req->dma, req->ptr->next,
req->ptr->token, req->ptr->page[0],
req->req.status);
}
@@ -1911,23 +1857,22 @@
*/
static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
{
- unsigned i;
+ unsigned int i;
int ret = 0;
- unsigned length = mReq->req.length;
+ unsigned int length = mReq->req.length;
struct ci13xxx *udc = _udc;
- trace("%p, %p", mEp, mReq);
+ trace("%pK, %pK", mEp, mReq);
/* don't queue twice */
if (mReq->req.status == -EALREADY)
return -EALREADY;
mReq->req.status = -EALREADY;
- if (length && mReq->req.dma == DMA_ADDR_INVALID) {
- mReq->req.dma = \
- dma_map_single(mEp->device, mReq->req.buf,
- length, mEp->dir ? DMA_TO_DEVICE :
- DMA_FROM_DEVICE);
+ if (length && mReq->req.dma == DMA_ERROR_CODE) {
+ mReq->req.dma = dma_map_single(mEp->device, mReq->req.buf,
+ length, mEp->dir ? DMA_TO_DEVICE :
+ DMA_FROM_DEVICE);
if (mReq->req.dma == 0)
return -ENOMEM;
@@ -1942,7 +1887,7 @@
dma_unmap_single(mEp->device, mReq->req.dma,
length, mEp->dir ? DMA_TO_DEVICE :
DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
+ mReq->req.dma = DMA_ERROR_CODE;
mReq->map = 0;
}
return -ENOMEM;
@@ -1953,6 +1898,7 @@
if (!mReq->req.no_interrupt)
mReq->zptr->token |= TD_IOC;
}
+
/*
* TD configuration
* TODO - handle requests which spawns into several TDs
@@ -1970,7 +1916,7 @@
}
/* MSM Specific: updating the request as required for
- * SPS mode. Enable MSM DMA engine acording
+ * SPS mode. Enable MSM DMA engine according
* to the UDC private data in the request.
*/
if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
@@ -1990,16 +1936,22 @@
for (i = 1; i < 5; i++)
mReq->ptr->page[i] = (mReq->req.dma + i * CI13XXX_PAGE_SIZE) &
~TD_RESERVED_MASK;
+ /* Makes sure that above write goes through */
wmb();
/* Remote Wakeup */
if (udc->suspended) {
- if (!udc->remote_wakeup) {
+ if (!udc->gadget.remote_wakeup) {
mReq->req.status = -EAGAIN;
- dev_dbg(mEp->device, "%s: queue failed (suspend) ept #%d\n",
- __func__, mEp->num);
+
+ dev_dbg(mEp->device, "%s: queue failed (suspend).",
+ __func__);
+ dev_dbg(mEp->device, "%s: Remote wakeup is not supported. ept #%d\n",
+ __func__, mEp->num);
+
return -EAGAIN;
}
+
usb_phy_set_suspend(udc->transceiver, 0);
schedule_delayed_work(&udc->rw_work, REMOTE_WAKEUP_DELAY);
}
@@ -2016,6 +1968,7 @@
mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
else
mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+ /* Makes sure that above write goes through */
wmb();
if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
goto done;
@@ -2039,19 +1992,37 @@
goto done;
}
- /* QH configuration */
+ /* Hardware may leave few TDs unprocessed, check and reprime with 1st */
if (!list_empty(&mEp->qh.queue)) {
- struct ci13xxx_req *mReq = \
- list_entry(mEp->qh.queue.next,
- struct ci13xxx_req, queue);
+ struct ci13xxx_req *mReq_active, *mReq_next;
+ u32 i = 0;
- if (TD_STATUS_ACTIVE & mReq->ptr->token) {
- mEp->qh.ptr->td.next = mReq->dma;
- mEp->qh.ptr->td.token &= ~TD_STATUS;
- goto prime;
+ /* Nothing to be done if hardware already finished this TD */
+ if ((TD_STATUS_ACTIVE & mReq->ptr->token) == 0)
+ goto done;
+
+ /* Iterate forward to find first TD with ACTIVE bit set */
+ mReq_active = mReq;
+ list_for_each_entry(mReq_next, &mEp->qh.queue, queue) {
+ i++;
+ mEp->dTD_active_re_q_count++;
+ if (TD_STATUS_ACTIVE & mReq_next->ptr->token) {
+ mReq_active = mReq_next;
+ dbg_event(_usb_addr(mEp), "ReQUE",
+ mReq_next->ptr->token);
+ pr_debug("!!ReQ(%u-%u-%x)-%u!!\n", mEp->num,
+ mEp->dir, mReq_next->ptr->token, i);
+ break;
+ }
}
+
+ /* QH configuration */
+ mEp->qh.ptr->td.next = mReq_active->dma;
+ mEp->qh.ptr->td.token &= ~TD_STATUS;
+ goto prime;
}
+ /* QH configuration */
mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */
if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
@@ -2063,8 +2034,10 @@
i = (mEp->dir == TX) ?
((i >> MSM_TX_PIPE_ID_OFS) & MSM_PIPE_ID_MASK) :
(i & MSM_PIPE_ID_MASK);
- /* If requested pipe id is different from current,
- then write it */
+ /*
+ * If requested pipe id is different from current,
+ * then write it
+ */
if (i != (mReq->req.udc_priv & MSM_PIPE_ID_MASK)) {
if (mEp->dir == TX)
hw_cwrite(
@@ -2090,12 +2063,14 @@
mEp->qh.ptr->cap |= QH_ZLT;
prime:
+ /* Makes sure that above write goes through */
wmb(); /* synchronize before ep prime */
ret = hw_ep_prime(mEp->num, mEp->dir,
mEp->type == USB_ENDPOINT_XFER_CONTROL);
if (!ret)
mod_timer(&mEp->prime_timer, EP_PRIME_CHECK_DELAY);
+
done:
return ret;
}
@@ -2109,7 +2084,7 @@
*/
static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
{
- trace("%p, %p", mEp, mReq);
+ trace("%pK, %pK", mEp, mReq);
if (mReq->req.status != -EALREADY)
return -EINVAL;
@@ -2147,7 +2122,7 @@
if (mReq->map) {
dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
+ mReq->req.dma = DMA_ERROR_CODE;
mReq->map = 0;
}
@@ -2168,6 +2143,65 @@
}
/**
+ * purge_rw_queue: Purge requests pending at the remote-wakeup
+ * queue and send them to the HW.
+ *
+ * Go over all of the endpoints and push any pending requests to
+ * the HW queue.
+ */
+static void purge_rw_queue(struct ci13xxx *udc)
+{
+ int i;
+ struct ci13xxx_ep *mEp = NULL;
+ struct ci13xxx_req *mReq = NULL;
+
+ /*
+ * Go over all of the endpoints and push any pending requests to
+ * the HW queue.
+ */
+ for (i = 0; i < hw_ep_max; i++) {
+ mEp = &udc->ci13xxx_ep[i];
+
+ while (!list_empty(&udc->ci13xxx_ep[i].rw_queue)) {
+ int retval;
+
+ /* pop oldest request */
+ mReq = list_entry(udc->ci13xxx_ep[i].rw_queue.next,
+ struct ci13xxx_req, queue);
+
+ list_del_init(&mReq->queue);
+
+ retval = _hardware_enqueue(mEp, mReq);
+
+ if (retval != 0) {
+ dbg_event(_usb_addr(mEp), "QUEUE", retval);
+ mReq->req.status = retval;
+ if (mReq->req.complete != NULL) {
+ if (mEp->type ==
+ USB_ENDPOINT_XFER_CONTROL)
+ mReq->req.complete(
+ &(_udc->ep0in.ep),
+ &mReq->req);
+ else
+ mReq->req.complete(
+ &mEp->ep,
+ &mReq->req);
+ }
+ retval = 0;
+ }
+
+ if (!retval)
+ list_add_tail(&mReq->queue, &mEp->qh.queue);
+ else if (mEp->multi_req)
+ mEp->multi_req = false;
+
+ }
+ }
+
+ udc->rw_pending = false;
+}
+
+/**
* restore_original_req: Restore original req's attributes
* @mReq: Request
*
@@ -2187,6 +2221,67 @@
}
/**
+ * release_ep_request: Free and endpoint request and release
+ * resources
+ * @mReq: request
+ * @mEp: endpoint
+ *
+ */
+static void release_ep_request(struct ci13xxx_ep *mEp,
+ struct ci13xxx_req *mReq)
+{
+ struct ci13xxx_ep *mEpTemp = mEp;
+
+ unsigned int val;
+
+ /* MSM Specific: Clear end point specific register */
+ if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
+ if (mReq->req.udc_priv & MSM_SPS_MODE) {
+ val = hw_cread(CAP_ENDPTPIPEID +
+ mEp->num * sizeof(u32),
+ ~0);
+
+ if (val != MSM_EP_PIPE_ID_RESET_VAL)
+ hw_cwrite(
+ CAP_ENDPTPIPEID +
+ mEp->num * sizeof(u32),
+ ~0, MSM_EP_PIPE_ID_RESET_VAL);
+ }
+ }
+ mReq->req.status = -ESHUTDOWN;
+
+ if (mReq->map) {
+ dma_unmap_single(mEp->device, mReq->req.dma,
+ mReq->req.length,
+ mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ mReq->req.dma = DMA_ERROR_CODE;
+ mReq->map = 0;
+ }
+
+ if (mReq->zptr) {
+ dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+ mReq->zptr = NULL;
+ mReq->zdma = 0;
+ }
+
+ if (mEp->multi_req) {
+ restore_original_req(mReq);
+ mEp->multi_req = false;
+ }
+
+ if (mReq->req.complete != NULL) {
+ spin_unlock(mEp->lock);
+ if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
+ mReq->req.length)
+ mEpTemp = &_udc->ep0in;
+ mReq->req.complete(&mEpTemp->ep, &mReq->req);
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
+ mReq->req.complete = NULL;
+ spin_lock(mEp->lock);
+ }
+}
+
+/**
* _ep_nuke: dequeues all endpoint requests
* @mEp: endpoint
*
@@ -2197,10 +2292,7 @@
__releases(mEp->lock)
__acquires(mEp->lock)
{
- struct ci13xxx_ep *mEpTemp = mEp;
- unsigned val;
-
- trace("%p", mEp);
+ trace("%pK", mEp);
if (mEp == NULL)
return -EINVAL;
@@ -2211,53 +2303,34 @@
hw_ep_flush(mEp->num, mEp->dir);
while (!list_empty(&mEp->qh.queue)) {
-
/* pop oldest request */
- struct ci13xxx_req *mReq = \
+ struct ci13xxx_req *mReq =
list_entry(mEp->qh.queue.next,
struct ci13xxx_req, queue);
list_del_init(&mReq->queue);
- /* MSM Specific: Clear end point specific register */
- if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
- if (mReq->req.udc_priv & MSM_SPS_MODE) {
- val = hw_cread(CAP_ENDPTPIPEID +
- mEp->num * sizeof(u32),
- ~0);
-
- if (val != MSM_EP_PIPE_ID_RESET_VAL)
- hw_cwrite(
- CAP_ENDPTPIPEID +
- mEp->num * sizeof(u32),
- ~0, MSM_EP_PIPE_ID_RESET_VAL);
- }
- }
- mReq->req.status = -ESHUTDOWN;
-
- if (mReq->map) {
- dma_unmap_single(mEp->device, mReq->req.dma,
- mReq->req.length,
- mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
- mReq->map = 0;
- }
-
- if (mEp->multi_req) {
- restore_original_req(mReq);
- mEp->multi_req = false;
- }
-
- if (mReq->req.complete != NULL) {
- spin_unlock(mEp->lock);
- if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
- mReq->req.length)
- mEpTemp = &_udc->ep0in;
- mReq->req.complete(&mEpTemp->ep, &mReq->req);
- if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
- mReq->req.complete = NULL;
- spin_lock(mEp->lock);
- }
+ release_ep_request(mEp, mReq);
}
+
+ /* Clear the requests pending at the remote-wakeup queue */
+ while (!list_empty(&mEp->rw_queue)) {
+
+ /* pop oldest request */
+ struct ci13xxx_req *mReq =
+ list_entry(mEp->rw_queue.next,
+ struct ci13xxx_req, queue);
+
+ list_del_init(&mReq->queue);
+
+ release_ep_request(mEp, mReq);
+ }
+
+ if (mEp->last_zptr) {
+ dma_pool_free(mEp->td_pool, mEp->last_zptr, mEp->last_zdma);
+ mEp->last_zptr = NULL;
+ mEp->last_zdma = 0;
+ }
+
return 0;
}
@@ -2272,23 +2345,18 @@
struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
unsigned long flags;
- trace("%p", gadget);
+ trace("%pK", gadget);
if (gadget == NULL)
return -EINVAL;
spin_lock_irqsave(udc->lock, flags);
udc->gadget.speed = USB_SPEED_UNKNOWN;
- udc->remote_wakeup = 0;
+ udc->gadget.remote_wakeup = 0;
udc->suspended = 0;
udc->configured = 0;
spin_unlock_irqrestore(udc->lock, flags);
- gadget->b_hnp_enable = 0;
- gadget->a_hnp_support = 0;
- gadget->host_request = 0;
- gadget->otg_srp_reqd = 0;
-
udc->driver->disconnect(gadget);
spin_lock_irqsave(udc->lock, flags);
@@ -2296,12 +2364,6 @@
_ep_nuke(&udc->ep0in);
spin_unlock_irqrestore(udc->lock, flags);
- if (udc->ep0in.last_zptr) {
- dma_pool_free(udc->ep0in.td_pool, udc->ep0in.last_zptr,
- udc->ep0in.last_zdma);
- udc->ep0in.last_zptr = NULL;
- }
-
return 0;
}
@@ -2320,7 +2382,7 @@
{
int retval;
- trace("%p", udc);
+ trace("%pK", udc);
if (udc == NULL) {
err("EINVAL");
@@ -2349,6 +2411,9 @@
if (retval)
goto done;
+ if (udc->rw_pending)
+ purge_rw_queue(udc);
+
_udc->skip_flush = false;
retval = hw_usb_reset();
if (retval)
@@ -2377,9 +2442,13 @@
CI13XXX_CONTROLLER_RESUME_EVENT);
if (udc->transceiver)
usb_phy_set_suspend(udc->transceiver, 0);
+ udc->suspended = 0;
udc->driver->resume(&udc->gadget);
spin_lock(udc->lock);
- udc->suspended = 0;
+
+ if (udc->rw_pending)
+ purge_rw_queue(udc);
+
}
}
@@ -2415,7 +2484,7 @@
*/
static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
{
- trace("%p, %p", ep, req);
+ trace("%pK, %pK", ep, req);
if (ep == NULL || req == NULL) {
err("EINVAL");
@@ -2442,7 +2511,7 @@
struct usb_request *req = udc->status;
int dir, num, retval;
- trace("%p, %p", mEp, setup);
+ trace("%pK, %pK", mEp, setup);
if (mEp == NULL || setup == NULL)
return -EINVAL;
@@ -2452,18 +2521,11 @@
req->buf = udc->status_buf;
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
- if (setup->wIndex == OTG_STATUS_SELECTOR) {
- *((u8 *)req->buf) = _udc->gadget.host_request <<
- HOST_REQUEST_FLAG;
- req->length = 1;
- } else {
- /* Assume that device is bus powered for now. */
- *((u16 *)req->buf) = _udc->remote_wakeup << 1;
- }
- /* TODO: D1 - Remote Wakeup; D0 - Self Powered */
+ /* Assume that device is bus powered for now. */
+ *((u16 *)req->buf) = _udc->gadget.remote_wakeup << 1;
retval = 0;
- } else if ((setup->bRequestType & USB_RECIP_MASK) \
- == USB_RECIP_ENDPOINT) {
+ } else if ((setup->bRequestType & USB_RECIP_MASK) ==
+ USB_RECIP_ENDPOINT) {
dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
TX : RX;
num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK;
@@ -2491,7 +2553,7 @@
struct ci13xxx *udc = req->context;
unsigned long flags;
- trace("%p, %p", ep, req);
+ trace("%pK, %pK", ep, req);
spin_lock_irqsave(udc->lock, flags);
if (udc->test_mode)
@@ -2512,7 +2574,7 @@
int retval;
struct ci13xxx_ep *mEp;
- trace("%p", udc);
+ trace("%pK", udc);
mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
udc->status->context = udc;
@@ -2539,11 +2601,11 @@
{
struct ci13xxx_req *mReq, *mReqTemp;
struct ci13xxx_ep *mEpTemp = mEp;
- int uninitialized_var(retval);
+ int retval = 0;
int req_dequeue = 1;
struct ci13xxx *udc = _udc;
- trace("%p", mEp);
+ trace("%pK", mEp);
if (list_empty(&mEp->qh.queue))
return 0;
@@ -2574,7 +2636,7 @@
req_dequeue = 0;
if (mEp->multi_req) { /* Large request in progress */
- unsigned remain_len;
+ unsigned int remain_len;
mReq->multi.actual += mReq->req.actual;
remain_len = mReq->multi.len - mReq->multi.actual;
@@ -2585,8 +2647,9 @@
} else {
mReq->req.buf = mReq->multi.buf +
mReq->multi.actual;
- mReq->req.length = min_t(unsigned, remain_len,
- (4 * CI13XXX_PAGE_SIZE));
+ mReq->req.length = min_t(unsigned int,
+ remain_len,
+ 4 * CI13XXX_PAGE_SIZE);
mReq->req.status = -EINPROGRESS;
mReq->req.actual = 0;
@@ -2638,10 +2701,10 @@
__releases(udc->lock)
__acquires(udc->lock)
{
- unsigned i;
+ unsigned int i;
u8 tmode = 0;
- trace("%p", udc);
+ trace("%pK", udc);
if (udc == NULL) {
err("EINVAL");
@@ -2728,7 +2791,7 @@
USB_DEVICE_REMOTE_WAKEUP) {
if (req.wLength != 0)
break;
- udc->remote_wakeup = 0;
+ udc->gadget.remote_wakeup = 0;
err = isr_setup_status_phase(udc);
} else {
goto delegate;
@@ -2739,7 +2802,8 @@
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
goto delegate;
- if (le16_to_cpu(req.wValue) != 0)
+ if (le16_to_cpu(req.wLength) != 2 ||
+ le16_to_cpu(req.wValue) != 0)
break;
err = isr_get_status_response(udc, &req);
break;
@@ -2780,19 +2844,9 @@
break;
switch (le16_to_cpu(req.wValue)) {
case USB_DEVICE_REMOTE_WAKEUP:
- udc->remote_wakeup = 1;
+ udc->gadget.remote_wakeup = 1;
err = isr_setup_status_phase(udc);
break;
- case USB_DEVICE_B_HNP_ENABLE:
- udc->gadget.b_hnp_enable = 1;
- err = isr_setup_status_phase(udc);
- break;
- case USB_DEVICE_A_HNP_SUPPORT:
- udc->gadget.a_hnp_support = 1;
- err = isr_setup_status_phase(udc);
- break;
- case USB_DEVICE_A_ALT_HNP_SUPPORT:
- break;
case USB_DEVICE_TEST_MODE:
tmode = le16_to_cpu(req.wIndex) >> 8;
switch (tmode) {
@@ -2805,21 +2859,11 @@
err = isr_setup_status_phase(
udc);
break;
- case TEST_OTG_SRP_REQD:
- udc->gadget.otg_srp_reqd = 1;
- err = isr_setup_status_phase(
- udc);
- break;
- case TEST_OTG_HNP_REQD:
- udc->gadget.host_request = 1;
- err = isr_setup_status_phase(
- udc);
- break;
default:
break;
}
default:
- break;
+ goto delegate;
}
} else {
goto delegate;
@@ -2861,9 +2905,9 @@
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
int retval = 0;
unsigned long flags;
- unsigned mult = 0;
+ unsigned int mult = 0;
- trace("ep = %p, desc = %p", ep, desc);
+ trace("ep = %pK, desc = %pK", ep, desc);
if (ep == NULL || desc == NULL)
return -EINVAL;
@@ -2926,7 +2970,7 @@
int direction, retval = 0;
unsigned long flags;
- trace("%p", ep);
+ trace("%pK", ep);
if (ep == NULL)
return -EINVAL;
@@ -2949,12 +2993,6 @@
} while (mEp->dir != direction);
- if (mEp->last_zptr) {
- dma_pool_free(mEp->td_pool, mEp->last_zptr,
- mEp->last_zdma);
- mEp->last_zptr = NULL;
- }
-
mEp->desc = NULL;
mEp->ep.desc = NULL;
mEp->ep.maxpacket = USHRT_MAX;
@@ -2973,7 +3011,7 @@
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
struct ci13xxx_req *mReq = NULL;
- trace("%p, %i", ep, gfp_flags);
+ trace("%pK, %i", ep, gfp_flags);
if (ep == NULL) {
err("EINVAL");
@@ -2983,7 +3021,7 @@
mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
if (mReq != NULL) {
INIT_LIST_HEAD(&mReq->queue);
- mReq->req.dma = DMA_ADDR_INVALID;
+ mReq->req.dma = DMA_ERROR_CODE;
mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
&mReq->dma);
@@ -3009,7 +3047,7 @@
struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
unsigned long flags;
- trace("%p, %p", ep, req);
+ trace("%pK, %pK", ep, req);
if (ep == NULL || req == NULL) {
err("EINVAL");
@@ -3044,10 +3082,13 @@
unsigned long flags;
struct ci13xxx *udc = _udc;
- trace("%p, %p, %X", ep, req, gfp_flags);
+ trace("%pK, %pK, %X", ep, req, gfp_flags);
+
+ if (ep == NULL)
+ return -EINVAL;
spin_lock_irqsave(mEp->lock, flags);
- if (ep == NULL || req == NULL || mEp->desc == NULL) {
+ if (req == NULL || mEp->desc == NULL) {
retval = -EINVAL;
goto done;
}
@@ -3059,8 +3100,7 @@
if (!udc->configured && mEp->type !=
USB_ENDPOINT_XFER_CONTROL) {
- trace("usb is not configured"
- "ept #%d, ept name#%s\n",
+ trace("usb is not configured ept #%d, ept name#%s\n",
mEp->num, mEp->ep.name);
retval = -ESHUTDOWN;
goto done;
@@ -3077,6 +3117,12 @@
}
}
+ if (ep->endless && udc->gadget.speed == USB_SPEED_FULL) {
+ err("Queueing endless req is not supported for FS");
+ retval = -EINVAL;
+ goto done;
+ }
+
/* first nuke then test link, e.g. previous status has not sent */
if (!list_empty(&mReq->queue)) {
retval = -EBUSY;
@@ -3113,6 +3159,36 @@
mReq->req.status = -EINPROGRESS;
mReq->req.actual = 0;
+ if (udc->rw_pending) {
+ list_add_tail(&mReq->queue, &mEp->rw_queue);
+ retval = 0;
+ goto done;
+ }
+
+ if (udc->suspended) {
+ /* Remote Wakeup */
+ if (!udc->gadget.remote_wakeup) {
+
+ dev_dbg(mEp->device, "%s: queue failed (suspend).",
+ __func__);
+ dev_dbg(mEp->device, "%s: Remote wakeup is not supported. ept #%d\n",
+ __func__, mEp->num);
+ mEp->multi_req = false;
+
+ retval = -EAGAIN;
+ goto done;
+ }
+
+ list_add_tail(&mReq->queue, &mEp->rw_queue);
+
+ udc->rw_pending = true;
+ schedule_delayed_work(&udc->rw_work,
+ REMOTE_WAKEUP_DELAY);
+
+ retval = 0;
+ goto done;
+ }
+
retval = _hardware_enqueue(mEp, mReq);
if (retval == -EALREADY) {
@@ -3139,16 +3215,27 @@
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
struct ci13xxx_ep *mEpTemp = mEp;
struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+ struct ci13xxx *udc = _udc;
unsigned long flags;
- trace("%p, %p", ep, req);
+ trace("%pK, %pK", ep, req);
+
+ if (udc->udc_driver->in_lpm && udc->udc_driver->in_lpm(udc)) {
+ dev_err(udc->transceiver->dev,
+ "%s: Unable to dequeue while in LPM\n",
+ __func__);
+ return -EAGAIN;
+ }
+
+ if (ep == NULL)
+ return -EINVAL;
spin_lock_irqsave(mEp->lock, flags);
/*
* Only ep0 IN is exposed to composite. When a req is dequeued
* on ep0, check both ep0 IN and ep0 OUT queues.
*/
- if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
+ if (req == NULL || mReq->req.status != -EALREADY ||
mEp->desc == NULL || list_empty(&mReq->queue) ||
(list_empty(&mEp->qh.queue) && ((mEp->type !=
USB_ENDPOINT_XFER_CONTROL) ||
@@ -3159,7 +3246,7 @@
dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
- if ((mEp->type == USB_ENDPOINT_XFER_CONTROL)) {
+ if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
hw_ep_flush(_udc->ep0out.num, RX);
hw_ep_flush(_udc->ep0in.num, TX);
} else {
@@ -3171,10 +3258,23 @@
if (mReq->map) {
dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- mReq->req.dma = DMA_ADDR_INVALID;
+ mReq->req.dma = DMA_ERROR_CODE;
mReq->map = 0;
}
req->status = -ECONNRESET;
+
+ if (mEp->last_zptr) {
+ dma_pool_free(mEp->td_pool, mEp->last_zptr, mEp->last_zdma);
+ mEp->last_zptr = NULL;
+ mEp->last_zdma = 0;
+ }
+
+ if (mReq->zptr) {
+ dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+ mReq->zptr = NULL;
+ mReq->zdma = 0;
+ }
+
if (mEp->multi_req) {
restore_original_req(mReq);
mEp->multi_req = false;
@@ -3209,14 +3309,21 @@
static int ep_set_halt(struct usb_ep *ep, int value)
{
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
+ struct ci13xxx *udc = _udc;
int direction, retval = 0;
unsigned long flags;
- trace("%p, %i", ep, value);
+ trace("%pK, %i", ep, value);
if (ep == NULL || mEp->desc == NULL)
return -EINVAL;
+ if (udc->suspended) {
+ dev_err(udc->transceiver->dev,
+ "%s: Unable to halt EP while suspended\n", __func__);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(mEp->lock, flags);
#ifndef STALL_IN
@@ -3257,7 +3364,7 @@
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
unsigned long flags;
- trace("%p", ep);
+ trace("%pK", ep);
if (ep == NULL || mEp->desc == NULL)
return -EINVAL;
@@ -3279,16 +3386,24 @@
*/
static void ep_fifo_flush(struct usb_ep *ep)
{
+ struct ci13xxx *udc = _udc;
struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
unsigned long flags;
- trace("%p", ep);
+ trace("%pK", ep);
if (ep == NULL) {
err("%02X: -EINVAL", _usb_addr(mEp));
return;
}
+ if (udc->udc_driver->in_lpm && udc->udc_driver->in_lpm(udc)) {
+ dev_err(udc->transceiver->dev,
+ "%s: Unable to fifo_flush while in LPM\n",
+ __func__);
+ return;
+ }
+
spin_lock_irqsave(mEp->lock, flags);
dbg_event(_usb_addr(mEp), "FFLUSH", 0);
@@ -3337,28 +3452,51 @@
gadget_ready = 1;
spin_unlock_irqrestore(udc->lock, flags);
- if (gadget_ready) {
- if (is_active) {
- pm_runtime_get_sync(&_gadget->dev);
- hw_device_reset(udc);
- if (udc->softconnect)
- hw_device_state(udc->ep0out.qh.dma);
- } else {
- hw_device_state(0);
- _gadget_stop_activity(&udc->gadget);
- if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
- CI13XXX_CONTROLLER_DISCONNECT_EVENT);
- pm_runtime_put_sync(&_gadget->dev);
+ if (!gadget_ready)
+ return 0;
+
+ if (is_active) {
+ hw_device_reset(udc);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_CONNECT_EVENT);
+ /* Enable BAM (if needed) before starting controller */
+ if (udc->softconnect) {
+ dbg_event(0xFF, "BAM EN2",
+ _gadget->bam2bam_func_enabled);
+ msm_usb_bam_enable(CI_CTRL,
+ _gadget->bam2bam_func_enabled);
+ hw_device_state(udc->ep0out.qh.dma);
}
+ } else {
+ hw_device_state(0);
+ _gadget_stop_activity(&udc->gadget);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_DISCONNECT_EVENT);
}
return 0;
}
-static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
+#define VBUS_DRAW_BUF_LEN 10
+#define MAX_OVERRIDE_VBUS_ALLOWED 900 /* 900 mA */
+static char vbus_draw_mA[VBUS_DRAW_BUF_LEN];
+module_param_string(vbus_draw_mA, vbus_draw_mA, VBUS_DRAW_BUF_LEN, 0644);
+
+static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned int mA)
{
struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+ unsigned int override_mA = 0;
+
+ /* override param to draw more current if battery draining faster */
+ if ((mA == CONFIG_USB_GADGET_VBUS_DRAW) &&
+ (vbus_draw_mA[0] != '\0')) {
+ if ((!kstrtoint(vbus_draw_mA, 10, &override_mA)) &&
+ (override_mA <= MAX_OVERRIDE_VBUS_ALLOWED)) {
+ mA = override_mA;
+ }
+ }
if (udc->transceiver)
return usb_phy_set_power(udc->transceiver, mA);
@@ -3379,17 +3517,41 @@
}
spin_unlock_irqrestore(udc->lock, flags);
- if (is_active)
+ pm_runtime_get_sync(&_gadget->dev);
+
+ /* Enable BAM (if needed) before starting controller */
+ if (is_active) {
+ dbg_event(0xFF, "BAM EN1", _gadget->bam2bam_func_enabled);
+ msm_usb_bam_enable(CI_CTRL, _gadget->bam2bam_func_enabled);
+ }
+
+ spin_lock_irqsave(udc->lock, flags);
+ if (!udc->vbus_active) {
+ spin_unlock_irqrestore(udc->lock, flags);
+ pm_runtime_put_sync(&_gadget->dev);
+ return 0;
+ }
+ if (is_active) {
+ spin_unlock(udc->lock);
+ if (udc->udc_driver->notify_event)
+ udc->udc_driver->notify_event(udc,
+ CI13XXX_CONTROLLER_CONNECT_EVENT);
+ spin_lock(udc->lock);
hw_device_state(udc->ep0out.qh.dma);
- else
+ } else {
hw_device_state(0);
+ }
+ spin_unlock_irqrestore(udc->lock, flags);
+
+ pm_runtime_mark_last_busy(&_gadget->dev);
+ pm_runtime_put_autosuspend(&_gadget->dev);
return 0;
}
-static int ci13xxx_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *));
-static int ci13xxx_stop(struct usb_gadget_driver *driver);
+static int ci13xxx_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver);
+static int ci13xxx_stop(struct usb_gadget *gadget);
/**
* Device operations part of the API to the USB controller hardware,
@@ -3401,31 +3563,27 @@
.wakeup = ci13xxx_wakeup,
.vbus_draw = ci13xxx_vbus_draw,
.pullup = ci13xxx_pullup,
- .start = ci13xxx_start,
- .stop = ci13xxx_stop,
+ .udc_start = ci13xxx_start,
+ .udc_stop = ci13xxx_stop,
};
/**
* ci13xxx_start: register a gadget driver
+ * @gadget: our gadget
* @driver: the driver being registered
- * @bind: the driver's bind callback
*
- * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
* Interrupts are enabled here.
*/
-static int ci13xxx_start(struct usb_gadget_driver *driver,
- int (*bind)(struct usb_gadget *))
+static int ci13xxx_start(struct usb_gadget *gadget,
+ struct usb_gadget_driver *driver)
{
struct ci13xxx *udc = _udc;
unsigned long flags;
- int i, j;
int retval = -ENOMEM;
- bool put = false;
- trace("%p", driver);
+ trace("%pK", driver);
if (driver == NULL ||
- bind == NULL ||
driver->setup == NULL ||
driver->disconnect == NULL)
return -EINVAL;
@@ -3434,82 +3592,37 @@
else if (udc->driver != NULL)
return -EBUSY;
- /* alloc resources */
- udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
- sizeof(struct ci13xxx_qh),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->qh_pool == NULL)
- return -ENOMEM;
-
- udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
- sizeof(struct ci13xxx_td),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->td_pool == NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- return -ENOMEM;
- }
-
spin_lock_irqsave(udc->lock, flags);
info("hw_ep_max = %d", hw_ep_max);
udc->gadget.dev.driver = NULL;
- retval = 0;
- for (i = 0; i < hw_ep_max/2; i++) {
- for (j = RX; j <= TX; j++) {
- int k = i + j * hw_ep_max/2;
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
-
- scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
- (j == TX) ? "in" : "out");
-
- mEp->lock = udc->lock;
- mEp->device = &udc->gadget.dev;
- mEp->td_pool = udc->td_pool;
-
- mEp->ep.name = mEp->name;
- mEp->ep.ops = &usb_ep_ops;
- mEp->ep.maxpacket =
- k ? USHRT_MAX : CTRL_PAYLOAD_MAX;
-
- INIT_LIST_HEAD(&mEp->qh.queue);
- spin_unlock_irqrestore(udc->lock, flags);
- mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
- &mEp->qh.dma);
- spin_lock_irqsave(udc->lock, flags);
- if (mEp->qh.ptr == NULL)
- retval = -ENOMEM;
- else
- memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
-
- /* skip ep0 out and in endpoints */
- if (i == 0)
- continue;
-
- list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
- }
- }
- if (retval)
- goto done;
spin_unlock_irqrestore(udc->lock, flags);
+
+ pm_runtime_get_sync(&udc->gadget.dev);
+
udc->ep0out.ep.desc = &ctrl_endpt_out_desc;
retval = usb_ep_enable(&udc->ep0out.ep);
if (retval)
- return retval;
+ goto pm_put;
udc->ep0in.ep.desc = &ctrl_endpt_in_desc;
retval = usb_ep_enable(&udc->ep0in.ep);
if (retval)
- return retval;
+ goto pm_put;
udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_KERNEL);
- if (!udc->status)
- return -ENOMEM;
- udc->status_buf = kzalloc(2, GFP_KERNEL); /* for GET_STATUS */
+ if (!udc->status) {
+ retval = -ENOMEM;
+ goto pm_put;
+ }
+
+ udc->status_buf = kzalloc(2 + udc->gadget.extra_buf_alloc,
+ GFP_KERNEL); /* for GET_STATUS */
if (!udc->status_buf) {
usb_ep_free_request(&udc->ep0in.ep, udc->status);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto pm_put;
}
spin_lock_irqsave(udc->lock, flags);
@@ -3517,17 +3630,6 @@
/* bind gadget */
driver->driver.bus = NULL;
udc->gadget.dev.driver = &driver->driver;
- udc->softconnect = 1;
-
- spin_unlock_irqrestore(udc->lock, flags);
- pm_runtime_get_sync(&udc->gadget.dev);
- retval = bind(&udc->gadget); /* MAY SLEEP */
- spin_lock_irqsave(udc->lock, flags);
-
- if (retval) {
- udc->gadget.dev.driver = NULL;
- goto done;
- }
udc->driver = driver;
if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
@@ -3535,26 +3637,23 @@
if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
hw_device_reset(udc);
} else {
- put = true;
goto done;
}
}
- if (!udc->softconnect) {
- put = true;
+ if (!udc->softconnect)
goto done;
- }
retval = hw_device_state(udc->ep0out.qh.dma);
- done:
+done:
spin_unlock_irqrestore(udc->lock, flags);
- if (retval || put)
- pm_runtime_put_sync(&udc->gadget.dev);
if (udc->udc_driver->notify_event)
- udc->udc_driver->notify_event(udc,
+ udc->udc_driver->notify_event(udc,
CI13XXX_CONTROLLER_UDC_STARTED_EVENT);
+pm_put:
+ pm_runtime_put(&udc->gadget.dev);
return retval;
}
@@ -3564,19 +3663,10 @@
*
* Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
*/
-static int ci13xxx_stop(struct usb_gadget_driver *driver)
+static int ci13xxx_stop(struct usb_gadget *gadget)
{
struct ci13xxx *udc = _udc;
- unsigned long i, flags;
-
- trace("%p", driver);
-
- if (driver == NULL ||
- driver->unbind == NULL ||
- driver->setup == NULL ||
- driver->disconnect == NULL ||
- driver != udc->driver)
- return -EINVAL;
+ unsigned long flags;
spin_lock_irqsave(udc->lock, flags);
@@ -3586,44 +3676,13 @@
spin_unlock_irqrestore(udc->lock, flags);
_gadget_stop_activity(&udc->gadget);
spin_lock_irqsave(udc->lock, flags);
- pm_runtime_put(&udc->gadget.dev);
}
- /* unbind gadget */
spin_unlock_irqrestore(udc->lock, flags);
- driver->unbind(&udc->gadget); /* MAY SLEEP */
- spin_lock_irqsave(udc->lock, flags);
usb_ep_free_request(&udc->ep0in.ep, udc->status);
kfree(udc->status_buf);
- udc->gadget.dev.driver = NULL;
-
- /* free resources */
- for (i = 0; i < hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
-
- if (!list_empty(&mEp->ep.ep_list))
- list_del_init(&mEp->ep.ep_list);
-
- if (mEp->qh.ptr != NULL)
- dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
- }
-
- udc->gadget.ep0 = NULL;
- udc->driver = NULL;
-
- spin_unlock_irqrestore(udc->lock, flags);
-
- if (udc->td_pool != NULL) {
- dma_pool_destroy(udc->td_pool);
- udc->td_pool = NULL;
- }
- if (udc->qh_pool != NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- }
-
return 0;
}
@@ -3651,6 +3710,11 @@
spin_lock(udc->lock);
+ if (udc->udc_driver->in_lpm && udc->udc_driver->in_lpm(udc)) {
+ spin_unlock(udc->lock);
+ return IRQ_NONE;
+ }
+
if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) {
if (hw_cread(CAP_USBMODE, USBMODE_CM) !=
USBMODE_CM_DEVICE) {
@@ -3667,6 +3731,9 @@
/* order defines priority - do NOT change it */
if (USBi_URI & intr) {
isr_statistics.uri++;
+ if (!hw_cread(CAP_PORTSC, PORTSC_PR))
+ pr_info("%s: USB reset interrupt is delayed\n",
+ __func__);
isr_reset_handler(udc);
}
if (USBi_PCI & intr) {
@@ -3693,18 +3760,15 @@
return retval;
}
-/**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
+static void destroy_eps(struct ci13xxx *ci)
{
- trace("%p", dev);
+ int i;
- if (dev == NULL)
- err("EINVAL");
+ for (i = 0; i < hw_ep_max; i++) {
+ struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
+
+ dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+ }
}
/**
@@ -3722,9 +3786,9 @@
{
struct ci13xxx *udc;
struct ci13xxx_platform_data *pdata;
- int retval = 0, i;
+ int retval = 0, i, j;
- trace("%p, %p, %p", dev, regs, driver->name);
+ trace("%pK, %pK, %pK", dev, regs, driver->name);
if (dev == NULL || regs == NULL || driver == NULL ||
driver->name == NULL)
@@ -3741,100 +3805,146 @@
udc->gadget.ops = &usb_gadget_ops;
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_HIGH;
- if (udc->udc_driver->flags & CI13XXX_IS_OTG)
- udc->gadget.is_otg = 1;
- else
- udc->gadget.is_otg = 0;
+ udc->gadget.is_otg = 0;
udc->gadget.name = driver->name;
- INIT_LIST_HEAD(&udc->gadget.ep_list);
- udc->gadget.ep0 = NULL;
+ /* alloc resources */
+ udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
+ sizeof(struct ci13xxx_qh),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->qh_pool == NULL) {
+ retval = -ENOMEM;
+ goto free_udc;
+ }
- pdata = dev->platform_data;
- if (pdata)
- udc->gadget.usb_core_id = pdata->usb_core_id;
-
- dev_set_name(&udc->gadget.dev, "gadget");
- udc->gadget.dev.dma_mask = dev->dma_mask;
- udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
- udc->gadget.dev.parent = dev;
- udc->gadget.dev.release = udc_release;
-
- if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
- udc->transceiver = usb_get_transceiver();
- if (udc->transceiver == NULL) {
- retval = -ENODEV;
- goto free_udc;
- }
+ udc->td_pool = dma_pool_create("ci13xxx_td", dev,
+ sizeof(struct ci13xxx_td),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->td_pool == NULL) {
+ retval = -ENOMEM;
+ goto free_qh_pool;
}
INIT_DELAYED_WORK(&udc->rw_work, usb_do_remote_wakeup);
retval = hw_device_init(regs);
if (retval < 0)
- goto put_transceiver;
+ goto free_qh_pool;
+ INIT_LIST_HEAD(&udc->gadget.ep_list);
for (i = 0; i < hw_ep_max; i++) {
struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+
INIT_LIST_HEAD(&mEp->ep.ep_list);
+ INIT_LIST_HEAD(&mEp->rw_queue);
setup_timer(&mEp->prime_timer, ep_prime_timer_func,
(unsigned long) mEp);
}
+ for (i = 0; i < hw_ep_max/2; i++) {
+ for (j = RX; j <= TX; j++) {
+ int k = i + j * hw_ep_max/2;
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
+
+ scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
+ (j == TX) ? "in" : "out");
+
+ mEp->lock = udc->lock;
+ mEp->device = &udc->gadget.dev;
+ mEp->td_pool = udc->td_pool;
+
+ mEp->ep.name = mEp->name;
+ mEp->ep.ops = &usb_ep_ops;
+ usb_ep_set_maxpacket_limit(&mEp->ep,
+ k ? USHRT_MAX : CTRL_PAYLOAD_MAX);
+
+ INIT_LIST_HEAD(&mEp->qh.queue);
+ mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
+ &mEp->qh.dma);
+ if (mEp->qh.ptr == NULL)
+ retval = -ENOMEM;
+ else
+ memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
+
+ /* skip ep0 out and in endpoints */
+ if (i == 0)
+ continue;
+
+ list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
+ }
+ }
+
+ if (retval)
+ goto free_dma_pools;
+
+ udc->gadget.ep0 = &udc->ep0in.ep;
+
+ pdata = dev->platform_data;
+ if (pdata) {
+ if (pdata->enable_axi_prefetch)
+ udc->gadget.extra_buf_alloc = EXTRA_ALLOCATION_SIZE;
+ }
+
+ if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
+ udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (udc->transceiver == NULL) {
+ retval = -ENODEV;
+ goto destroy_eps;
+ }
+ }
+
if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) {
retval = hw_device_reset(udc);
if (retval)
goto put_transceiver;
}
- retval = device_register(&udc->gadget.dev);
- if (retval) {
- put_device(&udc->gadget.dev);
- goto put_transceiver;
- }
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- retval = dbg_create_files(&udc->gadget.dev);
-#endif
- if (retval)
- goto unreg_device;
-
if (udc->transceiver) {
retval = otg_set_peripheral(udc->transceiver->otg,
&udc->gadget);
if (retval)
- goto remove_dbg;
+ goto put_transceiver;
}
retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval)
goto remove_trans;
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+ retval = dbg_create_files(&udc->gadget.dev);
+ if (retval) {
+ pr_err("Registering sysfs files for debug failed!!!!\n");
+ goto del_udc;
+ }
+#endif
+
pm_runtime_no_callbacks(&udc->gadget.dev);
+ pm_runtime_set_active(&udc->gadget.dev);
pm_runtime_enable(&udc->gadget.dev);
- if (register_trace_usb_daytona_invalid_access(dump_usb_info, NULL))
- pr_err("Registering trace failed\n");
+ /* Use delayed LPM especially for composition-switch in LPM (suspend) */
+ pm_runtime_set_autosuspend_delay(&udc->gadget.dev, 2000);
+ pm_runtime_use_autosuspend(&udc->gadget.dev);
_udc = udc;
return retval;
+del_udc:
+ usb_del_gadget_udc(&udc->gadget);
remove_trans:
- if (udc->transceiver) {
+ if (udc->transceiver)
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
- }
err("error = %i", retval);
-remove_dbg:
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
- dbg_remove_files(&udc->gadget.dev);
-#endif
-unreg_device:
- device_unregister(&udc->gadget.dev);
put_transceiver:
if (udc->transceiver)
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
+destroy_eps:
+ destroy_eps(udc);
+free_dma_pools:
+ dma_pool_destroy(udc->td_pool);
+free_qh_pool:
+ dma_pool_destroy(udc->qh_pool);
free_udc:
kfree(udc);
_udc = NULL;
@@ -3849,27 +3959,24 @@
static void udc_remove(void)
{
struct ci13xxx *udc = _udc;
- int retval;
if (udc == NULL) {
err("EINVAL");
return;
}
- retval = unregister_trace_usb_daytona_invalid_access(dump_usb_info,
- NULL);
- if (retval)
- pr_err("Unregistering trace failed\n");
usb_del_gadget_udc(&udc->gadget);
if (udc->transceiver) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
- usb_put_transceiver(udc->transceiver);
+ usb_put_phy(udc->transceiver);
}
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
dbg_remove_files(&udc->gadget.dev);
#endif
- device_unregister(&udc->gadget.dev);
+ destroy_eps(udc);
+ dma_pool_destroy(udc->td_pool);
+ dma_pool_destroy(udc->qh_pool);
kfree(udc);
_udc = NULL;
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index f90ea86..8c93080 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -57,7 +57,7 @@
#define TD_CURR_OFFSET (0x0FFFUL << 0)
#define TD_FRAME_NUM (0x07FFUL << 0)
#define TD_RESERVED_MASK (0x0FFFUL << 0)
-} __attribute__ ((packed, aligned(4)));
+} __packed __aligned(4);
/* DMA layout of queue heads */
struct ci13xxx_qh {
@@ -75,19 +75,19 @@
/* 9 */
u32 RESERVED;
struct usb_ctrlrequest setup;
-} __attribute__ ((packed, aligned(4)));
+} __packed __aligned(4);
/* cache of larger request's original attributes */
struct ci13xxx_multi_req {
- unsigned len;
- unsigned actual;
+ unsigned int len;
+ unsigned int actual;
void *buf;
};
/* Extension of usb_request */
struct ci13xxx_req {
struct usb_request req;
- unsigned map;
+ unsigned int map;
struct list_head queue;
struct ci13xxx_td *ptr;
dma_addr_t dma;
@@ -109,6 +109,7 @@
struct ci13xxx_qh *ptr;
dma_addr_t dma;
} qh;
+ struct list_head rw_queue;
int wedge;
/* global resources */
@@ -117,7 +118,8 @@
struct dma_pool *td_pool;
struct ci13xxx_td *last_zptr;
dma_addr_t last_zdma;
- unsigned long dTD_update_fail_count;
+ unsigned long dTD_update_fail_count;
+ unsigned long dTD_active_re_q_count;
unsigned long prime_fail_count;
int prime_timer_count;
struct timer_list prime_timer;
@@ -135,7 +137,7 @@
#define CI13XXX_PULLUP_ON_VBUS BIT(2)
#define CI13XXX_DISABLE_STREAMING BIT(3)
#define CI13XXX_ZERO_ITC BIT(4)
-#define CI13XXX_IS_OTG BIT(5)
+#define CI13XXX_ENABLE_AHB2AHB_BYPASS BIT(6)
#define CI13XXX_CONTROLLER_RESET_EVENT 0
#define CI13XXX_CONTROLLER_CONNECT_EVENT 1
@@ -144,8 +146,10 @@
#define CI13XXX_CONTROLLER_RESUME_EVENT 4
#define CI13XXX_CONTROLLER_DISCONNECT_EVENT 5
#define CI13XXX_CONTROLLER_UDC_STARTED_EVENT 6
+#define CI13XXX_CONTROLLER_ERROR_EVENT 7
- void (*notify_event) (struct ci13xxx *udc, unsigned event);
+ void (*notify_event)(struct ci13xxx *udc, unsigned int event);
+ bool (*in_lpm)(struct ci13xxx *udc);
};
/* CI13XXX UDC descriptor & global resources */
@@ -163,12 +167,10 @@
u32 ep0_dir; /* ep0 direction */
#define ep0out ci13xxx_ep[0]
#define ep0in ci13xxx_ep[hw_ep_max / 2]
- u8 remote_wakeup; /* Is remote wakeup feature
- enabled by the host? */
u8 suspended; /* suspended by the host */
u8 configured; /* is device configured */
u8 test_mode; /* the selected test mode */
-
+ bool rw_pending; /* Remote wakeup pending flag */
struct delayed_work rw_work; /* remote wakeup delayed work */
struct usb_gadget_driver *driver; /* 3rd party gadget driver */
struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
@@ -176,9 +178,11 @@
int softconnect; /* is pull-up enable allowed */
unsigned long dTD_update_fail_count;
struct usb_phy *transceiver; /* Transceiver struct */
- bool skip_flush; /* skip flushing remaining EP
- upon flush timeout for the
- first EP. */
+ bool skip_flush; /*
+ * skip flushing remaining EP
+ * upon flush timeout for the
+ * first EP.
+ */
};
/******************************************************************************
@@ -197,6 +201,9 @@
/* TESTMODE */
#define TESTMODE_FORCE BIT(0)
+/* AHB_MODE */
+#define AHB2AHB_BYPASS BIT(31)
+
/* USBCMD */
#define USBCMD_RS BIT(0)
#define USBCMD_RST BIT(1)
@@ -217,6 +224,7 @@
/* PORTSC */
#define PORTSC_FPR BIT(6)
#define PORTSC_SUSP BIT(7)
+#define PORTSC_PR BIT(8)
#define PORTSC_HSP BIT(9)
#define PORTSC_PTC (0x0FUL << 16)
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
index f472b2b..42028cc 100644
--- a/drivers/usb/gadget/udc/Kconfig
+++ b/drivers/usb/gadget/udc/Kconfig
@@ -391,7 +391,6 @@
config USB_CI13XXX_MSM
tristate "MIPS USB CI13xxx for MSM"
- depends on ARCH_MSM
select USB_MSM_OTG
help
MSM SoC has chipidea USB controller. This driver uses
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index d84cf5e..1cbaa44 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -79,10 +79,10 @@
if (level == 0) {
if (ctrl->pwm_enabled) {
- ret = pwm_config_us(ctrl->pwm_bl, level,
- ctrl->pwm_period);
+ ret = pwm_config(ctrl->pwm_bl, 0,
+ ctrl->pwm_period * NSEC_PER_USEC);
if (ret)
- pr_err("%s: pwm_config_us() failed err=%d.\n",
+ pr_err("%s: pwm_config() failed err=%d.\n",
__func__, ret);
pwm_disable(ctrl->pwm_bl);
}
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6..07b2e96 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -59,6 +59,23 @@
void (*detach)(struct drm_bridge *bridge);
/**
+ * @connector_init:
+ *
+ * This callback is used to init the connector from bridge side. In some
+ * cases connector and bridge are created in different modules, and the
+ * connector ops might need extra info from bridge. This callback offers
+ * the opportunity to overwrite connector's behavior in external bridge.
+ *
+ * The connector_init callback is optional.
+ *
+ * RETURNS:
+ *
+ * Zero on success, error code on failure.
+ */
+ int (*connector_init)(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+
+ /**
* @mode_fixup:
*
* This callback is used to validate and adjust a mode. The paramater
@@ -214,5 +231,7 @@
struct drm_display_mode *adjusted_mode);
void drm_bridge_pre_enable(struct drm_bridge *bridge);
void drm_bridge_enable(struct drm_bridge *bridge);
+int drm_bridge_connector_init(struct drm_bridge *bridge,
+ struct drm_connector *connector);
#endif
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index b28c4a3..9a5114d 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -560,6 +560,7 @@
* @tile_v_loc: vertical location of this tile
* @tile_h_size: horizontal size of this tile.
* @tile_v_size: vertical size of this tile.
+ * @private: connector private data.
*
* Each connector may be connected to one or more CRTCs, or may be clonable by
* another connector if they can share a CRTC. Each connector also has a specific
@@ -726,6 +727,8 @@
uint8_t num_h_tile, num_v_tile;
uint8_t tile_h_loc, tile_v_loc;
uint16_t tile_h_size, tile_v_size;
+
+ void *private;
};
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index 0dbddb3..3c2024d 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -140,6 +140,10 @@
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
/* transmit data in low power */
#define MIPI_DSI_MODE_LPM BIT(11)
+/* disable BLLP area */
+#define MIPI_DSI_MODE_VIDEO_BLLP BIT(12)
+/* disable EOF BLLP area */
+#define MIPI_DSI_MODE_VIDEO_EOF_BLLP BIT(13)
enum mipi_dsi_pixel_format {
MIPI_DSI_FMT_RGB888,
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 21dd697..61c557a 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -275,6 +275,8 @@
POWER_SUPPLY_PROP_PARALLEL_FCC_MAX,
POWER_SUPPLY_PROP_MIN_ICL,
POWER_SUPPLY_PROP_MOISTURE_DETECTED,
+ POWER_SUPPLY_PROP_BATT_FULL_CURRENT,
+ POWER_SUPPLY_PROP_RECHARGE_SOC,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3fda92f..6acd229 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -478,6 +478,9 @@
* @deactivated: True if gadget is deactivated - in deactivated state it cannot
* be connected.
* @connected: True if gadget is connected.
+ * @bam2bam_func_enabled; Indicates function using bam2bam is enabled or not.
+ * @extra_buf_alloc: Extra allocation size for AXI prefetch so that out of
+ * boundary access is protected.
*
* Gadgets have a mostly-portable "gadget driver" implementing device
* functions, handling all usb configurations and interfaces. Gadget
@@ -531,6 +534,9 @@
unsigned deactivated:1;
unsigned connected:1;
bool remote_wakeup;
+ bool bam2bam_func_enabled;
+ u32 extra_buf_alloc;
+ bool l1_supported;
};
#define work_to_gadget(w) (container_of((w), struct usb_gadget, work))
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index daa245d..2f90ddc 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -21,6 +21,7 @@
#define USB_AHBBURST (MSM_USB_BASE + 0x0090)
#define USB_AHBMODE (MSM_USB_BASE + 0x0098)
+#define USB_GENCONFIG (MSM_USB_BASE + 0x009C)
#define USB_GENCONFIG_2 (MSM_USB_BASE + 0x00a0)
#define ULPI_TX_PKT_EN_CLR_FIX BIT(19)
@@ -47,6 +48,14 @@
#define AHB2AHB_BYPASS BIT(31)
#define AHB2AHB_BYPASS_BIT_MASK BIT(31)
#define AHB2AHB_BYPASS_CLEAR (0 << 31)
+#define USB_L1_EP_CTRL (MSM_USB_BASE + 0x0250)
+#define USB_L1_CONFIG (MSM_USB_BASE + 0x0254)
+
+#define L1_CONFIG_LPM_EN BIT(4)
+#define L1_CONFIG_REMOTE_WAKEUP BIT(5)
+#define L1_CONFIG_GATE_SYS_CLK BIT(7)
+#define L1_CONFIG_PHY_LPM BIT(10)
+#define L1_CONFIG_PLL BIT(11)
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
#define PORTSC_PTS_MASK (3 << 30)
@@ -64,6 +73,10 @@
#define ULPI_DATA(n) ((n) & 255)
#define ULPI_DATA_READ(n) (((n) >> 8) & 255)
+#define GENCONFIG_BAM_DISABLE (1 << 13)
+#define GENCONFIG_TXFIFO_IDLE_FORCE_DISABLE (1 << 4)
+#define GENCONFIG_ULPI_SERIAL_EN (1 << 5)
+
/* synopsys 28nm phy registers */
#define ULPI_PWR_CLK_MNG_REG 0x88
#define OTG_COMP_DISABLE BIT(0)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 4a60459..d3ea11f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3288,6 +3288,46 @@
return NULL;
}
+#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER
+static inline bool
+should_compact_lmk_retry(struct alloc_context *ac, int order, int alloc_flags)
+{
+ struct zone *zone;
+ struct zoneref *z;
+
+ /* Let costly order requests check for compaction progress */
+ if (order > PAGE_ALLOC_COSTLY_ORDER)
+ return false;
+
+ /*
+ * For (0 < order < PAGE_ALLOC_COSTLY_ORDER) allow the shrinkers
+ * to run and free up memory. Do not let these allocations fail
+ * if shrinkers can free up memory. This is similar to
+ * should_compact_retry implementation for !CONFIG_COMPACTION.
+ */
+ for_each_zone_zonelist_nodemask(zone, z, ac->zonelist,
+ ac->high_zoneidx, ac->nodemask) {
+ unsigned long available;
+
+ available = zone_reclaimable_pages(zone);
+ available +=
+ zone_page_state_snapshot(zone, NR_FREE_PAGES);
+
+ if (__zone_watermark_ok(zone, 0, min_wmark_pages(zone),
+ ac_classzone_idx(ac), alloc_flags, available))
+ return true;
+ }
+
+ return false;
+}
+#else
+static inline bool
+should_compact_lmk_retry(struct alloc_context *ac, int order, int alloc_flags)
+{
+ return false;
+}
+#endif
+
static inline bool
should_compact_retry(struct alloc_context *ac, int order, int alloc_flags,
enum compact_result compact_result,
@@ -3300,6 +3340,9 @@
if (!order)
return false;
+ if (should_compact_lmk_retry(ac, order, alloc_flags))
+ return true;
+
if (compaction_made_progress(compact_result))
(*compaction_retries)++;
@@ -3537,7 +3580,8 @@
* their order will become available due to high fragmentation so
* always increment the no progress counter for them
*/
- if (did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER)
+ if ((did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER) ||
+ IS_ENABLED(CONFIG_ANDROID_LOW_MEMORY_KILLER))
*no_progress_loops = 0;
else
(*no_progress_loops)++;
@@ -3815,7 +3859,8 @@
* implementation of the compaction depends on the sufficient amount
* of free memory (see __compaction_suitable)
*/
- if (did_some_progress > 0 &&
+ if ((did_some_progress > 0 ||
+ IS_ENABLED(CONFIG_ANDROID_LOW_MEMORY_KILLER)) &&
should_compact_retry(ac, order, alloc_flags,
compact_result, &compact_priority,
&compaction_retries))
diff --git a/mm/vmscan.c b/mm/vmscan.c
index bb18b47..2740973 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -212,7 +212,8 @@
nr = zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_FILE) +
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_FILE);
- if (get_nr_swap_pages() > 0)
+ if (get_nr_swap_pages() > 0
+ || IS_ENABLED(CONFIG_ANDROID_LOW_MEMORY_KILLER))
nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) +
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON);
diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch
index ac5f1267..aab8585 100644
--- a/scripts/const_structs.checkpatch
+++ b/scripts/const_structs.checkpatch
@@ -9,7 +9,6 @@
dev_pm_ops
dma_map_ops
driver_info
-drm_connector_funcs
drm_encoder_funcs
drm_encoder_helper_funcs
ethtool_ops