Merge "defconfig: sdm670: Enable regmap debugfs write"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index b3f3431..0d955ed 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -139,6 +139,7 @@
the command DB driver.
qcom,drv-id: The DRV id associated with the RSC, used to differentiate
between RSCS owned by different execution environments.
+qcom,defer-init-qos: Flag to force defer initial QoS configuration at probe time.
Example:
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index dd668cb..c8cffb5 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -281,6 +281,18 @@
core ib calculation.
- qcom,sde-core-clk-ff: A string entry indicating the fudge factor for
core clock calculation.
+- qcom,sde-min-core-ib-kbps: This u32 value indicates the minimum mnoc ib
+ vote in Kbps that can be reduced without hitting underflow.
+ BW calculation logic will choose the IB bandwidth requirement
+ based on usecase if this floor value is not defined.
+- qcom,sde-min-llcc-ib-kbps: This u32 value indicates the minimum llcc ib
+ vote in Kbps that can be reduced without hitting underflow.
+ BW calculation logic will choose the IB bandwidth requirement
+ based on usecase if this floor value is not defined.
+- qcom,sde-min-dram-ib-kbps: This u32 value indicates the minimum dram ib
+ vote in Kbps that can be reduced without hitting underflow.
+ BW calculation logic will choose the IB bandwidth requirement
+ based on usecase if this floor value is not defined.
- qcom,sde-comp-ratio-rt: A string entry indicating the compression ratio
for each supported compressed format on realtime interface.
The string is composed of one or more of
@@ -572,6 +584,9 @@
qcom,sde-core-ib-ff = "1.1";
qcom,sde-core-clk-ff = "1.0";
+ qcom,sde-min-core-ib-kbps = <2400000>;
+ qcom,sde-min-llcc-ib-kbps = <800000>;
+ qcom,sde-min-dram-ib-kbps = <800000>;
qcom,sde-comp-ratio-rt = "NV12/5/1/1.1 AB24/5/1/1.2 XB24/5/1/1.3";
qcom,sde-comp-ratio-nrt = "NV12/5/1/1.1 AB24/5/1/1.2 XB24/5/1/1.3";
qcom,sde-undersized-prefill-lines = <4>;
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
index e46fd5c..ada2eab 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dp.txt
@@ -10,6 +10,7 @@
"dp_mmss_cc" - Display Clock Control memory region.
"qfprom_physical" - QFPROM Phys memory region.
"dp_pll" - USB3 DP combo PLL memory region.
+ "usb3_dp_com" - USB3 DP PHY combo memory region.
"hdcp_physical" - DP HDCP memory region.
- cell-index: Specifies the controller instance.
- clocks: Clocks required for Display Port operation.
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 0f8dc27..8fcdd82 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -96,6 +96,10 @@
retention. No cache invalidation operations involving asid
may be used.
+- qcom,disable-atos:
+ Some hardware may not have full support for atos debugging
+ in tandem with other features like power collapse.
+
- qcom,deferred-regulator-disable-delay : The time delay for deferred regulator
disable in ms. In case of unmap call, regulator is
enabled/disabled. This may introduce additional delay. For
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 271703f..85b0fe9 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -67,6 +67,9 @@
service.
- qcom,sysmon-id: platform device id that sysmon is probed with for the subsystem.
- qcom,override-acc: Boolean- Present if we need to override the default ACC settings
+- qcom,mss_pdc_offset: Integer- Mandatory if PDC register is specified. It is
+ used to specify which bit in the PDC register
+ corresponds to the modem.
- qcom,ahb-clk-vote: Boolean- Present if we need to remove the vote for the mss_cfg_ahb
clock after the modem boots up
- qcom,pnoc-clk-vote: Boolean- Present if the modem needs the PNOC bus to be
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index d0d878b..a3fd951 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -271,6 +271,14 @@
Definition: A boolean property that when defined holds SOC at 100% when
the battery is full.
+- qcom,linearize-soc
+ Usage: optional
+ Value type: <empty>
+ Definition: A boolean property that when defined linearizes SOC when
+ the SOC drops after charge termination monotonically to
+ improve the user experience. This is applicable only if
+ "qcom,hold-soc-while-full" is specified.
+
- qcom,ki-coeff-soc-dischg
Usage: optional
Value type: <prop-encoded-array>
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
index 4901fa0..c3e2cab 100644
--- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
+++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt
@@ -23,6 +23,8 @@
with "phys" attribute, provides phandle to UFS PHY node
- vdd-hba-supply : phandle to UFS host controller supply regulator node
- vcc-supply : phandle to VCC supply regulator node
+- vcc-voltage-level : specifies voltage levels for VCC supply.
+ Should be specified in pairs (min, max), units uV.
- vccq-supply : phandle to VCCQ supply regulator node
- vccq2-supply : phandle to VCCQ2 supply regulator node
- vcc-supply-1p8 : For embedded UFS devices, valid VCC range is 1.7-1.95V
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index ff8a523..bde40e0 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -276,6 +276,7 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_USB_BAM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MAILBOX=y
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_SMEM=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 6965607..c239ca8 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -271,6 +271,7 @@
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_MAILBOX=y
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMD=y
CONFIG_QCOM_SCM=y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index f2cf941..bc0c962 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -8,45 +8,54 @@
sdm845-mtp-overlay.dtbo \
sdm845-qrd-overlay.dtbo \
sdm845-qvr-overlay.dtbo \
- sdm845-v2-cdp-overlay.dtbo \
- sdm845-v2-mtp-overlay.dtbo \
- sdm845-v2-qrd-overlay.dtbo \
sdm845-4k-panel-mtp-overlay.dtbo \
sdm845-4k-panel-cdp-overlay.dtbo \
sdm845-4k-panel-qrd-overlay.dtbo \
+ sdm845-v2-cdp-overlay.dtbo \
+ sdm845-v2-mtp-overlay.dtbo \
+ sdm845-v2-qrd-overlay.dtbo \
+ sdm845-v2-4k-panel-mtp-overlay.dtbo \
+ sdm845-v2-4k-panel-cdp-overlay.dtbo \
+ sdm845-v2-4k-panel-qrd-overlay.dtbo \
sda845-cdp-overlay.dtbo \
sda845-mtp-overlay.dtbo \
sda845-qrd-overlay.dtbo \
- sda845-v2-cdp-overlay.dtbo \
- sda845-v2-mtp-overlay.dtbo \
- sda845-v2-qrd-overlay.dtbo \
sda845-4k-panel-mtp-overlay.dtbo \
sda845-4k-panel-cdp-overlay.dtbo \
sda845-4k-panel-qrd-overlay.dtbo \
- sdm845-interposer-sdm670-cdp-overlay.dtbo \
- sdm845-interposer-sdm670-mtp-overlay.dtbo
+ sda845-v2-cdp-overlay.dtbo \
+ sda845-v2-mtp-overlay.dtbo \
+ sda845-v2-qrd-overlay.dtbo \
+ sda845-v2-4k-panel-mtp-overlay.dtbo \
+ sda845-v2-4k-panel-cdp-overlay.dtbo \
+ sda845-v2-4k-panel-qrd-overlay.dtbo
sdm845-cdp-overlay.dtbo-base := sdm845.dtb
sdm845-mtp-overlay.dtbo-base := sdm845.dtb
sdm845-qrd-overlay.dtbo-base := sdm845.dtb
sdm845-qvr-overlay.dtbo-base := sdm845-v2.dtb
-sdm845-v2-cdp-overlay.dtbo-base := sdm845-v2.dtb
-sdm845-v2-mtp-overlay.dtbo-base := sdm845-v2.dtb
-sdm845-v2-qrd-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-qvr-overlay.dtbo-base := sdm845.dtb
sdm845-4k-panel-mtp-overlay.dtbo-base := sdm845.dtb
sdm845-4k-panel-cdp-overlay.dtbo-base := sdm845.dtb
sdm845-4k-panel-qrd-overlay.dtbo-base := sdm845.dtb
+sdm845-v2-cdp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-mtp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-qrd-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-4k-panel-mtp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-4k-panel-cdp-overlay.dtbo-base := sdm845-v2.dtb
+sdm845-v2-4k-panel-qrd-overlay.dtbo-base := sdm845-v2.dtb
sda845-cdp-overlay.dtbo-base := sda845.dtb
sda845-mtp-overlay.dtbo-base := sda845.dtb
sda845-qrd-overlay.dtbo-base := sda845.dtb
-sda845-v2-cdp-overlay.dtbo-base := sda845-v2.dtb
-sda845-v2-mtp-overlay.dtbo-base := sda845-v2.dtb
-sda845-v2-qrd-overlay.dtbo-base := sda845-v2.dtb
sda845-4k-panel-mtp-overlay.dtbo-base := sda845.dtb
sda845-4k-panel-cdp-overlay.dtbo-base := sda845.dtb
sda845-4k-panel-qrd-overlay.dtbo-base := sda845.dtb
-sdm845-interposer-sdm670-cdp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
-sdm845-interposer-sdm670-mtp-overlay.dtbo-base := sdm845-interposer-sdm670.dtb
+sda845-v2-cdp-overlay.dtbo-base := sda845-v2.dtb
+sda845-v2-mtp-overlay.dtbo-base := sda845-v2.dtb
+sda845-v2-qrd-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
else
dtb-$(CONFIG_ARCH_SDM845) += sdm845-sim.dtb \
sdm845-rumi.dtb \
@@ -71,19 +80,31 @@
sdm670-mtp-overlay.dtbo \
sdm670-rumi-overlay.dtbo \
sdm670-pm660a-cdp-overlay.dtbo \
- sdm670-pm660a-mtp-overlay.dtbo
+ sdm670-pm660a-mtp-overlay.dtbo \
+ sdm670-external-codec-cdp-overlay.dtbo \
+ sdm670-external-codec-mtp-overlay.dtbo \
+ sdm670-external-codec-pm660a-cdp-overlay.dtbo \
+ sdm670-external-codec-pm660a-mtp-overlay.dtbo
sdm670-cdp-overlay.dtbo-base := sdm670.dtb
sdm670-mtp-overlay.dtbo-base := sdm670.dtb
sdm670-rumi-overlay.dtbo-base := sdm670.dtb
sdm670-pm660a-cdp-overlay.dtbo-base := sdm670.dtb
sdm670-pm660a-mtp-overlay.dtbo-base := sdm670.dtb
+sdm670-external-codec-cdp-overlay.dtbo-base := sdm670.dtb
+sdm670-external-codec-mtp-overlay.dtbo-base := sdm670.dtb
+sdm670-external-codec-pm660a-cdp-overlay.dtbo-base := sdm670.dtb
+sdm670-external-codec-pm660a-mtp-overlay.dtbo-base := sdm670.dtb
else
dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
sdm670-mtp.dtb \
sdm670-cdp.dtb \
sdm670-pm660a-mtp.dtb \
- sdm670-pm660a-cdp.dtb
+ sdm670-pm660a-cdp.dtb \
+ sdm670-external-codec-cdp.dtb \
+ sdm670-external-codec-mtp.dtb \
+ sdm670-external-codec-pm660a-cdp.dtb \
+ sdm670-external-codec-pm660a-mtp.dtb
endif
always := $(dtb-y)
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 5de0e44..2156a5d 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -21,6 +21,7 @@
#iommu-cells = <1>;
qcom,dynamic;
qcom,use-3-lvl-tables;
+ qcom,disable-atos;
#global-interrupts = <2>;
qcom,regulator-names = "vdd";
vdd-supply = <&gpu_cx_gdsc>;
@@ -62,6 +63,7 @@
qcom,skip-init;
qcom,use-3-lvl-tables;
qcom,no-asid-retention;
+ qcom,disable-atos;
#global-interrupts = <1>;
#size-cells = <1>;
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 48d68a7..54a05df 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/spmi/spmi.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/thermal/thermal.h>
&spmi_bus {
pm660_0: qcom,pm660@0 {
@@ -58,13 +59,14 @@
};
};
- qcom,temp-alarm@2400 {
+ pm660_tz: qcom,temp-alarm@2400 {
compatible = "qcom,qpnp-temp-alarm";
reg = <0x2400 0x100>;
interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
label = "pm660_tz";
qcom,channel-num = <6>;
qcom,temp_alarm-vadc = <&pm660_vadc>;
+ #thermal-sensor-cells = <0>;
};
pm660_gpios: pinctrl@c000 {
@@ -358,18 +360,23 @@
qcom,pmic-revid = <&pm660_revid>;
};
- bcl@4200 {
+ bcl_sensor: bcl@4200 {
compatible = "qcom,msm-bcl-lmh";
reg = <0x4200 0xff>,
<0x4300 0xff>;
reg-names = "fg_user_adc",
"fg_lmh";
interrupts = <0x0 0x42 0x0 IRQ_TYPE_NONE>,
- <0x0 0x42 0x2 IRQ_TYPE_NONE>;
- interrupt-names = "bcl-high-ibat-int",
- "bcl-low-vbat-int";
- qcom,vbat-polling-delay-ms = <100>;
- qcom,ibat-polling-delay-ms = <100>;
+ <0x0 0x42 0x1 IRQ_TYPE_NONE>,
+ <0x0 0x42 0x2 IRQ_TYPE_NONE>,
+ <0x0 0x42 0x3 IRQ_TYPE_NONE>,
+ <0x0 0x42 0x4 IRQ_TYPE_NONE>;
+ interrupt-names = "bcl-high-ibat",
+ "bcl-very-high-ibat",
+ "bcl-low-vbat",
+ "bcl-very-low-vbat",
+ "bcl-crit-low-vbat";
+ #thermal-sensor-cells = <1>;
};
};
@@ -456,4 +463,243 @@
};
};
};
+
+ ibat-high {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ thermal-sensors = <&bcl_sensor 0>;
+
+ trips {
+ ibat-high {
+ temperature = <4200>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+ };
+ };
+
+ ibat-vhigh {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ thermal-sensors = <&bcl_sensor 1>;
+
+ trips {
+ ibat-vhigh {
+ temperature = <4300>;
+ hysteresis = <100>;
+ type = "passive";
+ };
+ };
+ };
+
+ vbat_adc {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 2>;
+ tracks-low;
+
+ trips {
+ pm660_vbat_adc: vbat-adc {
+ temperature = <3300>;
+ hysteresis = <100>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ vbat_map6 {
+ trip = <&pm660_vbat_adc>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ vbat_map7 {
+ trip = <&pm660_vbat_adc>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+
+ vbat_low {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 3>;
+ tracks-low;
+
+ trips {
+ vbat-low {
+ temperature = <3100>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+
+ vbat_too_low {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 4>;
+ tracks-low;
+
+ trips {
+ vbat-too-low {
+ temperature = <2900>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+
+ soc {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 5>;
+ tracks-low;
+
+ trips {
+ pm660_low_soc: low-soc {
+ temperature = <10>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ soc_map6 {
+ trip = <&pm660_low_soc>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ soc_map7 {
+ trip = <&pm660_low_soc>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+
+ pm660_temp_alarm: pm660_tz {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ thermal-sensors = <&pm660_tz>;
+
+ trips {
+ pm660_trip0: pm660-trip0 {
+ temperature = <105000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ pm660_trip1: pm660-trip1 {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ pm660_trip2: pm660-trip2 {
+ temperature = <145000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ cooling-maps {
+ trip0_cpu0 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu1 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu2 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu3 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu4 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU4 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu5 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU5 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu6 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU6 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip0_cpu7 {
+ trip = <&pm660_trip0>;
+ cooling-device =
+ <&CPU7 (THERMAL_MAX_LIMIT-1)
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ trip1_cpu1 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU1 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu2 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU2 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu3 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU3 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu4 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU4 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu5 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU5 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu6 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU6 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ trip1_cpu7 {
+ trip = <&pm660_trip1>;
+ cooling-device =
+ <&CPU7 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi
index 771154a..aaf5d05 100644
--- a/arch/arm64/boot/dts/qcom/pm660l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi
@@ -39,11 +39,12 @@
<PON_POWER_OFF_SHUTDOWN>;
};
- qcom,temp-alarm@2400 {
+ pm660l_tz: qcom,temp-alarm@2400 {
compatible = "qcom,qpnp-temp-alarm";
reg = <0x2400 0x100>;
interrupts = <0x2 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
label = "pm660l_tz";
+ #thermal-sensor-cells = <0>;
};
pm660l_gpios: pinctrl@c000 {
@@ -295,3 +296,29 @@
};
};
};
+
+&thermal_zones {
+ pm660l_tz {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm660l_tz>;
+
+ trips {
+ pm660l_trip0: pm660l-trip0 {
+ temperature = <105000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ pm660l_trip1: pm660l-trip1 {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ pm660l_trip2: pm660l-trip2 {
+ temperature = <145000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-cdp-overlay.dts
new file mode 100644
index 0000000..9b7449e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-cdp-overlay.dts
@@ -0,0 +1,66 @@
+/* Copyright (c) 2017, 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-cdp.dtsi"
+#include "sdm845-cdp-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sda845 v2 4K Display Panel CDP";
+ compatible = "qcom,sda845-cdp", "qcom,sda845", "qcom,cdp";
+ qcom,msm-id = <341 0x20000>;
+ qcom,board-id = <1 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_rscc &sde_wb>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-mtp-overlay.dts
new file mode 100644
index 0000000..bb310d3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-mtp-overlay.dts
@@ -0,0 +1,66 @@
+/* Copyright (c) 2017, 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-mtp.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sda845 v2 4K Display Panel MTP";
+ compatible = "qcom,sda845-mtp", "qcom,sda845", "qcom,mtp";
+ qcom,msm-id = <341 0x20000>;
+ qcom,board-id = <8 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_rscc &sde_wb &sde_dp>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-qrd-overlay.dts
new file mode 100644
index 0000000..ab61f2e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-4k-panel-qrd-overlay.dts
@@ -0,0 +1,64 @@
+/* Copyright (c) 2017, 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-qrd.dtsi"
+#include "sdm845-qrd-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sda845 v2 4K Display Panel QRD";
+ compatible = "qcom,sda845-qrd", "qcom,sda845", "qcom,qrd";
+ qcom,msm-id = <341 0x20000>;
+ qcom,board-id = <11 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
index 4f40678..d5d4847 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
@@ -12,6 +12,31 @@
#include "sdm670-pmic-overlay.dtsi"
+&ufsphy_mem {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm660l_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm660_l1>; /* 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 = <&pm660l_l4>;
+ vccq2-supply = <&pm660_l8>;
+ vcc-max-microamp = <600000>;
+ vccq2-max-microamp = <600000>;
+
+ qcom,vddp-ref-clk-supply = <&pm660_l1>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
+
&qupv3_se9_2uart {
status = "disabled";
};
@@ -35,3 +60,41 @@
&qupv3_se6_4uart {
status = "disabled";
};
+
+&sdhc_1 {
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ status = "ok";
+};
+
+&pm660_charger {
+ qcom,batteryless-platform;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp-overlay.dts
new file mode 100644
index 0000000..32a8580
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp-overlay.dts
@@ -0,0 +1,33 @@
+/* Copyright (c) 2017, 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 "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660L Ext. Audio Codec CDP";
+ compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+ qcom,msm-id = <336 0x0>;
+ qcom,board-id = <1 1>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0102001a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp.dts
new file mode 100644
index 0000000..6a87d3a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2017, 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 "sdm670.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 670 PM660 + PM660L Ext. Audio Codec CDP";
+ compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+ qcom,board-id = <1 1>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0102001a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..970209ca
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp-overlay.dts
@@ -0,0 +1,33 @@
+/* Copyright (c) 2017, 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 "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660L Ext. Audio Codec MTP";
+ compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+ qcom,msm-id = <336 0x0>;
+ qcom,board-id = <8 1>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0102001a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp.dts
new file mode 100644
index 0000000..87ac190
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2017, 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 "sdm670.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 670 PM660 + PM660L Ext. Audio Codec MTP";
+ compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+ qcom,board-id = <8 1>;
+ qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+ <0x0001001b 0x0102001a 0x0 0x0>,
+ <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..48a6066
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp-overlay.dts
@@ -0,0 +1,35 @@
+/* Copyright (c) 2017, 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 "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660A Ext. Audio Codec CDP";
+ compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+ qcom,msm-id = <336 0x0>;
+ qcom,board-id = <1 1>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+ <0x0001001b 0x0002001a 0x0 0x0>,
+ <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp.dts
new file mode 100644
index 0000000..e64d13b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-cdp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 "sdm670.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 670 PM660 + PM660A Ext. Audio Codec CDP";
+ compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+ qcom,board-id = <1 1>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+ <0x0001001b 0x0002001a 0x0 0x0>,
+ <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..8715ddc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2017, 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 "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660A Ext. Audio Codec MTP";
+ compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+ qcom,msm-id = <336 0x0>;
+ qcom,board-id = <8 1>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+ <0x0001001b 0x0002001a 0x0 0x0>,
+ <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp.dts
new file mode 100644
index 0000000..0beaddb3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec-pm660a-mtp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2017, 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 "sdm670.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM 670 PM660 + PM660A Ext. Audio Codec MTP";
+ compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+ qcom,board-id = <8 1>;
+ qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+ <0x0001001b 0x0002001a 0x0 0x0>,
+ <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi b/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi
new file mode 100644
index 0000000..6ea92ee
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi
@@ -0,0 +1,11 @@
+/* Copyright (c) 2017, 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.
+ */
diff --git a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
index d13aa15..7718bca 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
@@ -73,6 +73,7 @@
/* base addr, size */
qcom,gpu-qdss-stm = <0x161c0000 0x40000>;
+ #cooling-cells = <2>;
clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK>,
<&clock_gpucc GPU_CC_CXO_CLK>,
@@ -170,7 +171,7 @@
reg = <0>;
qcom,gpu-freq = <430000000>;
qcom,bus-freq = <11>;
- qcom,bus-min = <10>;
+ qcom,bus-min = <8>;
qcom,bus-max = <11>;
};
@@ -178,9 +179,9 @@
qcom,gpu-pwrlevel@1 {
reg = <1>;
qcom,gpu-freq = <355000000>;
- qcom,bus-freq = <9>;
- qcom,bus-min = <8>;
- qcom,bus-max = <10>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <9>;
};
/* LOW SVS */
@@ -198,7 +199,7 @@
qcom,gpu-freq = <180000000>;
qcom,bus-freq = <4>;
qcom,bus-min = <3>;
- qcom,bus-max = <5>;
+ qcom,bus-max = <4>;
};
/* XO */
diff --git a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
index 4f40678..0f3a61f 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
@@ -12,6 +12,31 @@
#include "sdm670-pmic-overlay.dtsi"
+&ufsphy_mem {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm660l_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm660_l1>; /* 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 = <&pm660l_l4>;
+ vccq2-supply = <&pm660_l8>;
+ vcc-max-microamp = <600000>;
+ vccq2-max-microamp = <600000>;
+
+ qcom,vddp-ref-clk-supply = <&pm660_l1>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
+
&qupv3_se9_2uart {
status = "disabled";
};
@@ -35,3 +60,50 @@
&qupv3_se6_4uart {
status = "disabled";
};
+
+&sdhc_1 {
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ status = "ok";
+};
+
+&vendor {
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "fg-gen3-batterydata-itech-3000mah.dtsi"
+ #include "fg-gen3-batterydata-ascent-3450mah.dtsi"
+ #include "fg-gen3-batterydata-demo-6000mah.dtsi"
+ };
+};
+
+&pm660_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 73df253..a080db4 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1196,6 +1196,20 @@
};
};
+ sdc1_rclk_on: sdc1_rclk_on {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
+
+ sdc1_rclk_off: sdc1_rclk_off {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
+
sdc2_clk_on: sdc2_clk_on {
config {
pins = "sdc2_clk";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
index cd8bfba..24d92eb 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
@@ -15,6 +15,7 @@
compatible = "qcom,qpnp-smb2";
#address-cells = <1>;
#size-cells = <1>;
+ #cooling-cells = <2>;
qcom,pmic-revid = <&pm660_revid>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index 1f76288..23792b1 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -96,6 +96,14 @@
regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
};
+
+ mx_cdev: mx-cdev-lvl {
+ compatible = "qcom,regulator-cooling-device";
+ regulator-cdev-supply = <&pm660l_s1_level>;
+ regulator-levels = <RPMH_REGULATOR_LEVEL_NOM
+ RPMH_REGULATOR_LEVEL_OFF>;
+ #cooling-cells = <2>;
+ };
};
/* pm660l S2 - VDD_GFX supply */
@@ -137,6 +145,13 @@
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
qcom,min-dropout-voltage-level = <(-1)>;
};
+
+ cx_cdev: regulator-cdev {
+ compatible = "qcom,rpmh-reg-cdev";
+ mboxes = <&qmp_aop 0>;
+ qcom,reg-resource-name = "cx";
+ #cooling-cells = <2>;
+ };
};
rpmh-regulator-ldoa1 {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
index ca9d8c7..4ba16e4 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-rumi.dtsi
@@ -49,6 +49,7 @@
/delete-node/ rpmh-regulator-ldoa28;
/delete-node/ rpmh-regulator-bobb1;
/delete-node/ rpmh-regulator-gfxlvl;
+ /delete-node/ thermal-zones;
};
#include "sdm670-stub-regulator.dtsi"
@@ -127,6 +128,8 @@
qcom,clk-rates = <400000 20000000 25000000 50000000>;
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ /delete-property/qcom,devfreq,freq-table;
+
status = "ok";
};
@@ -146,6 +149,8 @@
qcom,clk-rates = <400000 20000000 25000000 50000000>;
qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50";
+ /delete-property/qcom,devfreq,freq-table;
+
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
new file mode 100644
index 0000000..e4993d6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
@@ -0,0 +1,1507 @@
+/* Copyright (c) 2017, 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 <dt-bindings/thermal/thermal.h>
+
+&clock_cpucc {
+ lmh_dcvs0: qcom,limits-dcvs@0 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,affinity = <0>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ lmh_dcvs1: qcom,limits-dcvs@1 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,affinity = <1>;
+ #thermal-sensor-cells = <0>;
+ };
+};
+
+&soc {
+ qmi-tmd-devices {
+ compatible = "qcom,qmi_cooling_devices";
+
+ modem {
+ qcom,instance-id = <0x0>;
+
+ modem_pa: modem_pa {
+ qcom,qmi-dev-name = "pa";
+ #cooling-cells = <2>;
+ };
+
+ modem_proc: modem_proc {
+ qcom,qmi-dev-name = "modem";
+ #cooling-cells = <2>;
+ };
+
+ modem_current: modem_current {
+ qcom,qmi-dev-name = "modem_current";
+ #cooling-cells = <2>;
+ };
+
+ modem_vdd: modem_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+
+ adsp {
+ qcom,instance-id = <0x1>;
+
+ adsp_vdd: adsp_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+
+ cdsp {
+ qcom,instance-id = <0x43>;
+
+ cdsp_vdd: cdsp_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+ };
+};
+
+&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";
+ };
+ };
+ };
+
+ cpu0-silver-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";
+ };
+ };
+ };
+
+ cpu1-silver-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";
+ };
+ };
+ };
+
+ cpu2-silver-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";
+ };
+ };
+ };
+
+ cpu3-silver-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";
+ };
+ };
+ };
+
+ cpu4-silver-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";
+ };
+ };
+ };
+
+ cpu5-silver-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";
+ };
+ };
+ };
+
+ kryo-l3-0-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";
+ };
+ };
+ };
+
+ kryo-l3-1-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";
+ };
+ };
+ };
+
+ cpu0-gold-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";
+ };
+ };
+ };
+
+ cpu1-gold-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";
+ };
+ };
+ };
+
+ gpu0-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 11>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu1-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 12>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ aoss1-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 0>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-dsp-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 1>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ ddr-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 2>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ wlan-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 3>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ compute-hvx-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 4>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 5>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mmss-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 6>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-core-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 7>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu-virt-max-step {
+ polling-delay-passive = <10>;
+ polling-delay = <100>;
+ thermal-governor = "step_wise";
+ trips {
+ gpu_trip0: gpu-trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ gpu_cdev0 {
+ trip = <&gpu_trip0>;
+ cooling-device =
+ <&msm_gpu THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ hexa-silv-max-step {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ trips {
+ silver-trip {
+ temperature = <120000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+
+ dual-gold-max-step {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ trips {
+ gold-trip {
+ temperature = <120000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+
+ pop-mem-step {
+ polling-delay-passive = <10>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 2>;
+ thermal-governor = "step_wise";
+ trips {
+ pop_trip: pop-trip {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ pop_cdev6 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU6 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ pop_cdev7 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU7 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ };
+ };
+
+ aoss0-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 0>;
+ tracks-low;
+ trips {
+ aoss0_trip: aoss0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu0-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 1>;
+ tracks-low;
+ trips {
+ cpu0_trip: cpu0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu1-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 2>;
+ tracks-low;
+ trips {
+ cpu1_trip: cpu1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu2-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 3>;
+ tracks-low;
+ trips {
+ cpu2_trip: cpu2-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu3-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 4>;
+ tracks-low;
+ trips {
+ cpu3_trip: cpu3-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu4-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 5>;
+ tracks-low;
+ trips {
+ cpu4_trip: cpu4-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu4_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu5-silver-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 6>;
+ tracks-low;
+ trips {
+ cpu5_trip: cpu5-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpu5_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ kryo-l3-0-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 7>;
+ tracks-low;
+ trips {
+ l3_0_trip: l3-0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ kryo-l3-1-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 8>;
+ tracks-low;
+ trips {
+ l3_1_trip: l3-1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu0-gold-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 9>;
+ tracks-low;
+ trips {
+ cpug0_trip: cpug0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ cpu1-gold-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 10>;
+ tracks-low;
+ trips {
+ cpug1_trip: cpug1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ gpu0-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 11>;
+ tracks-low;
+ trips {
+ gpu0_trip_l: gpu0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ gpu1-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 12>;
+ tracks-low;
+ trips {
+ gpu1_trip_l: gpu1-trip_l {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ aoss1-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 0>;
+ tracks-low;
+ trips {
+ aoss1_trip: aoss1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mdm-dsp-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 1>;
+ tracks-low;
+ trips {
+ dsp_trip: dsp-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ ddr-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 2>;
+ tracks-low;
+ trips {
+ ddr_trip: ddr-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ wlan-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 3>;
+ tracks-low;
+ trips {
+ wlan_trip: wlan-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ compute-hvx-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 4>;
+ tracks-low;
+ trips {
+ hvx_trip: hvx-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ camera-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 5>;
+ tracks-low;
+ trips {
+ camera_trip: camera-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mmss-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 6>;
+ tracks-low;
+ trips {
+ mmss_trip: mmss-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ mdm-core-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 7>;
+ tracks-low;
+ trips {
+ mdm_trip: mdm-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&CPU0 4 4>;
+ };
+ cpu6_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&CPU6 9 9>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 1 1>;
+ };
+ cx_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&cx_cdev 0 0>;
+ };
+ mx_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&mx_cdev 0 0>;
+ };
+ modem_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&modem_vdd 0 0>;
+ };
+ adsp_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&adsp_vdd 0 0>;
+ };
+ cdsp_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&cdsp_vdd 0 0>;
+ };
+ };
+ };
+
+ lmh-dcvs-01 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&lmh_dcvs1>;
+
+ trips {
+ active-config {
+ temperature = <95000>;
+ hysteresis = <30000>;
+ type = "passive";
+ };
+ };
+ };
+
+ lmh-dcvs-00 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&lmh_dcvs0>;
+
+ trips {
+ active-config {
+ temperature = <95000>;
+ hysteresis = <30000>;
+ type = "passive";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
index bd35cf2..1064a16 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
@@ -17,9 +17,18 @@
/delete-node/ ssusb@a800000;
/delete-node/ qusb@88e3000;
/delete-node/ ssphy@88eb000;
+ /delete-node/ usb_audio_qmi_dev;
+ usb_audio_qmi_dev {
+ compatible = "qcom,usb-audio-qmi-dev";
+ iommus = <&apps_smmu 0x180f 0x0>;
+ qcom,usb-audio-stream-id = <0xf>;
+ qcom,usb-audio-intr-num = <2>;
+ };
};
&usb0 {
+ /delete-property/ iommus;
+ /delete-property/ qcom,smmu-s1-bypass;
extcon = <&pm660_pdphy>, <&pm660_pdphy>, <0> /* <&eud> */;
};
@@ -30,6 +39,6 @@
};
&usb_qmp_dp_phy {
- vdd-supply = <&pm660_l1>;
- core-supply = <&pm660l_l1>;
+ vdd-supply = <&pm660l_l1>; /* 0.88v */
+ core-supply = <&pm660_l1>; /* 1.2v */
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 692d75f..3ada991 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -53,6 +53,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_0>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_0: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -86,6 +88,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_100>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_100: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -114,6 +118,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_200>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_200: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -142,6 +148,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_300>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_300: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -170,6 +178,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_400>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_400: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -198,6 +208,8 @@
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_500>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
L2_500: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x20000>;
@@ -226,6 +238,8 @@
cache-size = <0x10000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_600>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
L2_600: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x40000>;
@@ -254,6 +268,8 @@
cache-size = <0x10000>;
cpu-release-addr = <0x0 0x90000000>;
next-level-cache = <&L2_700>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
L2_700: l2-cache {
compatible = "arm,arch-cache";
cache-size = <0x40000>;
@@ -439,6 +455,12 @@
size = <0 0x5c00000>;
};
+ dump_mem: mem_dump_region {
+ compatible = "shared-dma-pool";
+ reusable;
+ size = <0 0x2400000>;
+ };
+
/* global autoconfigured region for contiguous allocations */
linux,cma {
compatible = "shared-dma-pool";
@@ -490,301 +512,7 @@
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";
- };
- };
- };
-
- cpu0-silver-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";
- };
- };
- };
-
- cpu1-silver-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";
- };
- };
- };
-
- cpu2-silver-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";
- };
- };
- };
-
- cpu3-silver-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";
- };
- };
- };
-
- cpu4-silver-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";
- };
- };
- };
-
- cpu5-silver-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";
- };
- };
- };
-
- kryo-l3-0-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";
- };
- };
- };
-
- kryo-l3-1-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";
- };
- };
- };
-
- cpu0-gold-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";
- };
- };
- };
-
- cpu1-gold-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";
- };
- };
- };
-
- gpu0-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens0 11>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- gpu1-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-governor = "user_space";
- thermal-sensors = <&tsens0 12>;
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- aoss1-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 0>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- mdm-dsp-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 1>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- ddr-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 2>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- wlan-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 3>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- compute-hvx-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 4>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- camera-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 5>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- mmss-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 6>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
-
- mdm-core-usr {
- polling-delay-passive = <0>;
- polling-delay = <0>;
- thermal-sensors = <&tsens1 7>;
- thermal-governor = "user_space";
- trips {
- active-config0 {
- temperature = <125000>;
- hysteresis = <1000>;
- type = "passive";
- };
- };
- };
- };
+ thermal_zones: thermal-zones {};
tsens0: tsens@c222000 {
compatible = "qcom,tsens24xx";
@@ -881,53 +609,88 @@
};
clock_rpmh: qcom,rpmhclk {
- compatible = "qcom,dummycc";
- clock-output-names = "rpmh_clocks";
+ compatible = "qcom,rpmh-clk-sdm670";
#clock-cells = <1>;
+ mboxes = <&apps_rsc 0>;
+ mbox-names = "apps";
};
clock_gcc: qcom,gcc@100000 {
- compatible = "qcom,dummycc";
- clock-output-names = "gcc_clocks";
+ compatible = "qcom,gcc-sdm670", "syscon";
+ reg = <0x100000 0x1f0000>;
+ reg-names = "cc_base";
+ vdd_cx-supply = <&pm660l_s3_level>;
+ vdd_cx_ao-supply = <&pm660l_s3_level_ao>;
#clock-cells = <1>;
#reset-cells = <1>;
};
clock_videocc: qcom,videocc@ab00000 {
- compatible = "qcom,dummycc";
- clock-output-names = "videocc_clocks";
+ compatible = "qcom,video_cc-sdm670", "syscon";
+ reg = <0xab00000 0x10000>;
+ reg-names = "cc_base";
+ vdd_cx-supply = <&pm660l_s3_level>;
#clock-cells = <1>;
#reset-cells = <1>;
};
clock_camcc: qcom,camcc@ad00000 {
- compatible = "qcom,dummycc";
- clock-output-names = "camcc_clocks";
+ compatible = "qcom,cam_cc-sdm670", "syscon";
+ reg = <0xad00000 0x10000>;
+ reg-names = "cc_base";
+ vdd_cx-supply = <&pm660l_s3_level>;
+ vdd_mx-supply = <&pm660l_s1_level>;
#clock-cells = <1>;
#reset-cells = <1>;
};
clock_dispcc: qcom,dispcc@af00000 {
- compatible = "qcom,dummycc";
- clock-output-names = "dispcc_clocks";
+ compatible = "qcom,dispcc-sdm670", "syscon";
+ reg = <0xaf00000 0x10000>;
+ reg-names = "cc_base";
+ vdd_cx-supply = <&pm660l_s3_level>;
#clock-cells = <1>;
#reset-cells = <1>;
};
clock_gpucc: qcom,gpucc@5090000 {
- compatible = "qcom,dummycc";
- clock-output-names = "gpucc_clocks";
+ compatible = "qcom,gpucc-sdm670", "syscon";
+ reg = <0x5090000 0x9000>;
+ reg-names = "cc_base";
+ vdd_cx-supply = <&pm660l_s3_level>;
+ vdd_mx-supply = <&pm660l_s1_level>;
#clock-cells = <1>;
#reset-cells = <1>;
};
clock_gfx: qcom,gfxcc@5090000 {
- compatible = "qcom,dummycc";
- clock-output-names = "gfxcc_clocks";
+ compatible = "qcom,gfxcc-sdm670";
+ reg = <0x5090000 0x9000>;
+ reg-names = "cc_base";
+ vdd_gfx-supply = <&pm660l_s2_level>;
#clock-cells = <1>;
#reset-cells = <1>;
};
+ cpucc_debug: syscon@17970018 {
+ compatible = "syscon";
+ reg = <0x17970018 0x4>;
+ };
+
+ clock_debug: qcom,cc-debug {
+ compatible = "qcom,debugcc-sdm845";
+ qcom,cc-count = <5>;
+ qcom,gcc = <&clock_gcc>;
+ qcom,videocc = <&clock_videocc>;
+ qcom,camcc = <&clock_camcc>;
+ qcom,dispcc = <&clock_dispcc>;
+ qcom,gpucc = <&clock_gpucc>;
+ qcom,cpucc = <&cpucc_debug>;
+ clock-names = "xo_clk_src";
+ clocks = <&clock_rpmh RPMH_CXO_CLK>;
+ #clock-cells = <1>;
+ };
+
clock_cpucc: qcom,cpucc {
compatible = "qcom,dummycc";
clock-output-names = "cpucc_clocks";
@@ -953,6 +716,16 @@
qcom,apps-ch-pipes = <0x780000>;
qcom,ea-pc = <0x290>;
status = "disabled";
+ qcom,iommu-s1-bypass;
+
+ iommu_slim_aud_ctrl_cb: qcom,iommu_slim_ctrl_cb {
+ compatible = "qcom,iommu-slim-ctrl-cb";
+ iommus = <&apps_smmu 0x1826 0x0>,
+ <&apps_smmu 0x182d 0x0>,
+ <&apps_smmu 0x182e 0x1>,
+ <&apps_smmu 0x1830 0x1>;
+ };
+
};
slim_qca: slim@62e40000 {
@@ -964,6 +737,13 @@
interrupts = <0 291 0>, <0 292 0>;
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
status = "disabled";
+ qcom,iommu-s1-bypass;
+
+ iommu_slim_qca_ctrl_cb: qcom,iommu_slim_ctrl_cb {
+ compatible = "qcom,iommu-slim-ctrl-cb";
+ iommus = <&apps_smmu 0x1833 0x0>;
+ };
+
};
wdog: qcom,wdt@17980000{
@@ -1160,6 +940,61 @@
};
};
+ mem_dump {
+ compatible = "qcom,mem-dump";
+ memory-region = <&dump_mem>;
+
+ rpmh_dump {
+ qcom,dump-size = <0x2000000>;
+ qcom,dump-id = <0xec>;
+ };
+
+ rpm_sw_dump {
+ qcom,dump-size = <0x28000>;
+ qcom,dump-id = <0xea>;
+ };
+
+ pmic_dump {
+ qcom,dump-size = <0x10000>;
+ qcom,dump-id = <0xe4>;
+ };
+
+ tmc_etf_dump {
+ qcom,dump-size = <0x10000>;
+ qcom,dump-id = <0xf0>;
+ };
+
+ tmc_etf_swao_dump {
+ qcom,dump-size = <0x8400>;
+ qcom,dump-id = <0xf1>;
+ };
+
+ tmc_etr_reg_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0x100>;
+ };
+
+ tmc_etf_reg_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0x101>;
+ };
+
+ tmc_etf_swao_reg_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0x102>;
+ };
+
+ misc_data_dump {
+ qcom,dump-size = <0x1000>;
+ qcom,dump-id = <0xe8>;
+ };
+
+ power_regs_data_dump {
+ qcom,dump-size = <0x100000>;
+ qcom,dump-id = <0xed>;
+ };
+ };
+
kryo3xx-erp {
compatible = "arm,arm64-kryo3xx-cpu-erp";
interrupts = <1 6 4>,
@@ -1574,6 +1409,44 @@
<0 0>,
<0 0>;
+ qcom,msm-bus,name = "ufshc_mem";
+ qcom,msm-bus,num-cases = <12>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ /*
+ * During HS G3 UFS runs at nominal voltage corner, vote
+ * higher bandwidth to push other buses in the data path
+ * to run at nominal to achieve max throughput.
+ * 4GBps pushes BIMC to run at nominal.
+ * 200MBps pushes CNOC to run at nominal.
+ * Vote for half of this bandwidth for HS G3 1-lane.
+ * For max bandwidth, vote high enough to push the buses
+ * to run in turbo voltage corner.
+ */
+ <123 512 0 0>, <1 757 0 0>, /* No vote */
+ <123 512 922 0>, <1 757 1000 0>, /* PWM G1 */
+ <123 512 1844 0>, <1 757 1000 0>, /* PWM G2 */
+ <123 512 3688 0>, <1 757 1000 0>, /* PWM G3 */
+ <123 512 7376 0>, <1 757 1000 0>, /* PWM G4 */
+ <123 512 127796 0>, <1 757 1000 0>, /* HS G1 RA */
+ <123 512 255591 0>, <1 757 1000 0>, /* HS G2 RA */
+ <123 512 2097152 0>, <1 757 102400 0>, /* HS G3 RA */
+ <123 512 149422 0>, <1 757 1000 0>, /* HS G1 RB */
+ <123 512 298189 0>, <1 757 1000 0>, /* HS G2 RB */
+ <123 512 2097152 0>, <1 757 102400 0>, /* HS G3 RB */
+ <123 512 7643136 0>, <1 757 307200 0>; /* Max. bandwidth */
+
+ qcom,bus-vector-names = "MIN",
+ "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1",
+ "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1",
+ "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1",
+ "MAX";
+
+ /* PM QoS */
+ qcom,pm-qos-cpu-groups = <0x3f 0xC0>;
+ qcom,pm-qos-cpu-group-latency-us = <70 70>;
+ qcom,pm-qos-default-cpu = <0>;
+
resets = <&clock_gcc GCC_UFS_PHY_BCR>;
reset-names = "core_reset";
@@ -1817,6 +1690,7 @@
qcom,ssctl-instance-id = <0x12>;
qcom,override-acc;
qcom,qdsp6v65-1-0;
+ qcom,mss_pdc_offset = <8>;
status = "ok";
memory-region = <&pil_modem_mem>;
qcom,mem-protect-id = <0xF>;
@@ -1905,6 +1779,12 @@
qcom,bus-width = <8>;
qcom,large-address-bus;
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 192000000 384000000>;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
<&clock_gcc GCC_SDCC1_APPS_CLK>;
clock-names = "iface_clk", "core_clk";
@@ -1926,6 +1806,12 @@
qcom,bus-width = <4>;
qcom,large-address-bus;
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 201500000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50",
+ "SDR104";
+
+ qcom,devfreq,freq-table = <50000000 201500000>;
clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
<&clock_gcc GCC_SDCC2_APPS_CLK>;
clock-names = "iface_clk", "core_clk";
@@ -2015,6 +1901,26 @@
dma-coherent;
};
};
+
+ qcom,icnss@18800000 {
+ status = "disabled";
+ compatible = "qcom,icnss";
+ reg = <0x18800000 0x800000>;
+ interrupts = <0 414 0 /* CE0 */ >,
+ <0 415 0 /* CE1 */ >,
+ <0 416 0 /* CE2 */ >,
+ <0 417 0 /* CE3 */ >,
+ <0 418 0 /* CE4 */ >,
+ <0 419 0 /* CE5 */ >,
+ <0 420 0 /* CE6 */ >,
+ <0 421 0 /* CE7 */ >,
+ <0 422 0 /* CE8 */ >,
+ <0 423 0 /* CE9 */ >,
+ <0 424 0 /* CE10 */ >,
+ <0 425 0 /* CE11 */ >;
+ qcom,wlan-msa-memory = <0x100000>;
+ qcom,smmu-s1-bypass;
+ };
};
#include "sdm670-pinctrl.dtsi"
@@ -2114,3 +2020,4 @@
#include "sdm670-audio.dtsi"
#include "sdm670-usb.dtsi"
#include "sdm670-gpu.dtsi"
+#include "sdm670-thermal.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
index 5fbb1db..646dbad 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
@@ -645,7 +645,10 @@
qcom,qport = <2>;
qcom,connections = <&slv_qns_a2noc_snoc>;
qcom,bus-dev = <&fab_aggre2_noc>;
+ qcom,ap-owned;
qcom,prio = <2>;
+ qcom,defer-init-qos;
+ qcom,node-qos-bcms = <7035 0 1>;
};
mas_xm_pcie3_1: mas-xm-pcie3-1 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index dddf1fb..fe19658 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -110,6 +110,7 @@
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>;
@@ -146,6 +147,7 @@
vdd-hba-supply = <&ufs_card_gdsc>;
vdd-hba-fixed-regulator;
vcc-supply = <&pm8998_l21>;
+ vcc-voltage-level = <2950000 2960000>;
vccq2-supply = <&pm8998_s4>;
vcc-max-microamp = <300000>;
vccq2-max-microamp = <300000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
index ad15615..e435cdd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
@@ -13,3 +13,28 @@
#include "sdm845-cdp.dtsi"
#include "sdm845-interposer-pm660.dtsi"
#include "sdm845-interposer-sdm670-audio.dtsi"
+
+&soc {
+ /delete-node/ ssusb@a800000;
+ /delete-node/ qusb@88e3000;
+ /delete-node/ ssphy@88eb000;
+};
+
+&usb0 {
+ extcon = <&pm660_pdphy>, <&pm660_pdphy>, <0> /* <&eud> */;
+};
+
+&qusb_phy0 {
+ vdd-supply = <&pm660l_l1>;
+ vdda18-supply = <&pm660_l10>;
+ vdda33-supply = <&pm660l_l7>;
+};
+
+&usb_qmp_dp_phy {
+ vdd-supply = <&pm660l_l1>; /* 0.88v */
+ core-supply = <&pm660_l1>; /* 1.2v */
+};
+
+&pcie0 {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
index c709770..4b24b0d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
@@ -16,4 +16,30 @@
&qupv3_se10_i2c {
/delete-node/ qcom,smb1355@8;
+ /delete-node/ qcom,smb1355@c;
+};
+
+&soc {
+ /delete-node/ ssusb@a800000;
+ /delete-node/ qusb@88e3000;
+ /delete-node/ ssphy@88eb000;
+};
+
+&usb0 {
+ extcon = <&pm660_pdphy>, <&pm660_pdphy>, <0> /* <&eud> */;
+};
+
+&qusb_phy0 {
+ vdd-supply = <&pm660l_l1>;
+ vdda18-supply = <&pm660_l10>;
+ vdda33-supply = <&pm660l_l7>;
+};
+
+&usb_qmp_dp_phy {
+ vdd-supply = <&pm660l_l1>; /* 0.88v */
+ core-supply = <&pm660_l1>; /* 1.2v */
+};
+
+&pcie0 {
+ status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 3d58dc1..3756197 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -198,6 +198,7 @@
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>;
@@ -234,6 +235,7 @@
vdd-hba-supply = <&ufs_card_gdsc>;
vdd-hba-fixed-regulator;
vcc-supply = <&pm8998_l21>;
+ vcc-voltage-level = <2950000 2960000>;
vccq2-supply = <&pm8998_s4>;
vcc-max-microamp = <300000>;
vccq2-max-microamp = <300000>;
@@ -291,7 +293,11 @@
qcom,battery-data = <&mtp_batterydata>;
};
-&smb1355_charger {
+&smb1355_charger_0 {
+ status = "ok";
+};
+
+&smb1355_charger_1 {
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 6122eee..02f30fd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -88,7 +88,11 @@
qcom,fg-bmd-en-delay-ms = <300>;
};
-&smb1355_charger {
+&smb1355_charger_0 {
+ status = "ok";
+};
+
+&smb1355_charger_1 {
status = "ok";
};
@@ -111,6 +115,7 @@
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>;
@@ -147,6 +152,7 @@
vdd-hba-supply = <&ufs_card_gdsc>;
vdd-hba-fixed-regulator;
vcc-supply = <&pm8998_l21>;
+ vcc-voltage-level = <2950000 2960000>;
vccq2-supply = <&pm8998_s4>;
vcc-max-microamp = <300000>;
vccq2-max-microamp = <300000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qvr.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qvr.dtsi
index 6ea92ee..0da0e67 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qvr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qvr.dtsi
@@ -9,3 +9,28 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+&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>;
+ 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";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index f50df47..d22c28a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -1389,12 +1389,24 @@
compatible = "qcom,rpmh-vrm-regulator";
mboxes = <&apps_rsc 0>;
qcom,resource-name = "bobb1";
+ qcom,send-defaults;
+
pmi8998_bob: regulator-bob {
regulator-name = "pmi8998_bob";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3600000>;
qcom,init-voltage = <3312000>;
+ qcom,init-mode = <RPMH_REGULATOR_MODE_BOB_PASS>;
+ };
+
+ pmi8998_bob_ao: regulator-bob-ao {
+ regulator-name = "pmi8998_bob_ao";
+ qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3600000>;
+ qcom,init-voltage = <3312000>;
+ qcom,init-mode = <RPMH_REGULATOR_MODE_BOB_AUTO>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
index e7fd8a0..99004bf 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
@@ -33,6 +33,7 @@
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>;
@@ -157,6 +158,7 @@
vdd-hba-supply = <&ufs_card_gdsc>;
vdd-hba-fixed-regulator;
vcc-supply = <&pm8998_l21>;
+ vcc-voltage-level = <2950000 2960000>;
vccq2-supply = <&pm8998_s4>;
vcc-max-microamp = <300000>;
vccq2-max-microamp = <300000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index db3d23c..03b40b3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -430,10 +430,11 @@
<0xaf02000 0x1a0>,
<0x780000 0x621c>,
<0x88ea030 0x10>,
+ <0x88e8000 0x20>,
<0x0aee1000 0x034>;
reg-names = "dp_ctrl", "dp_phy", "dp_ln_tx0", "dp_ln_tx1",
"dp_mmss_cc", "qfprom_physical", "dp_pll",
- "hdcp_physical";
+ "usb3_dp_com", "hdcp_physical";
interrupt-parent = <&mdss_mdp>;
interrupts = <12 0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 0618f92..6051106 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -130,6 +130,9 @@
qcom,sde-has-idle-pc;
qcom,sde-max-bw-low-kbps = <9600000>;
qcom,sde-max-bw-high-kbps = <9600000>;
+ qcom,sde-min-core-ib-kbps = <2400000>;
+ qcom,sde-min-llcc-ib-kbps = <800000>;
+ qcom,sde-min-dram-ib-kbps = <800000>;
qcom,sde-dram-channels = <2>;
qcom,sde-num-nrt-paths = <0>;
qcom,sde-dspp-ad-version = <0x00040000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-cdp-overlay.dts
new file mode 100644
index 0000000..5b3e964
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-cdp-overlay.dts
@@ -0,0 +1,66 @@
+/* Copyright (c) 2017, 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-cdp.dtsi"
+#include "sdm845-cdp-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sdm845 v2 4K Display Panel CDP";
+ compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+ qcom,msm-id = <321 0x20000>;
+ qcom,board-id = <1 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_rscc &sde_wb>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-mtp-overlay.dts
new file mode 100644
index 0000000..0d6c5e0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-mtp-overlay.dts
@@ -0,0 +1,66 @@
+/* Copyright (c) 2017, 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-mtp.dtsi"
+#include "sdm845-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sdm845 v2 4K Display Panel MTP";
+ compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+ qcom,msm-id = <321 0x20000>;
+ qcom,board-id = <8 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ connectors = <&sde_rscc &sde_wb &sde_dp>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-qrd-overlay.dts
new file mode 100644
index 0000000..764c145
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-4k-panel-qrd-overlay.dts
@@ -0,0 +1,64 @@
+/* Copyright (c) 2017, 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-qrd.dtsi"
+#include "sdm845-qrd-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. sdm845 v2 4K Display Panel QRD";
+ compatible = "qcom,sdm845-qrd", "qcom,sdm845", "qcom,qrd";
+ qcom,msm-id = <321 0x20000>;
+ qcom,board-id = <11 1>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,mdss-dsi-panel-orientation = "180";
+};
+
+&dsi_sharp_4k_dsc_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 98ab8d4..0b55736 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -477,6 +477,10 @@
};
};
+&pil_modem {
+ qcom,mss_pdc_offset = <9>;
+};
+
/* VDD_APC0 */
&pm8998_s13 {
regulator-min-microvolt = <568000>;
@@ -843,6 +847,25 @@
qcom,count-unit = <0x10000>;
};
+&cpubw {
+ qcom,bw-tbl =
+ < MHZ_TO_MBPS(150, 16) >, /* 2288 MB/s */
+ < MHZ_TO_MBPS(300, 16) >, /* 4577 MB/s */
+ < MHZ_TO_MBPS(426, 16) >, /* 6500 MB/s */
+ < MHZ_TO_MBPS(533, 16) >, /* 8132 MB/s */
+ < MHZ_TO_MBPS(600, 16) >, /* 9155 MB/s */
+ < MHZ_TO_MBPS(806, 16) >, /* 12298 MB/s */
+ < MHZ_TO_MBPS(933, 16) >; /* 14236 MB/s */
+};
+
+&devfreq_cpufreq {
+ mincpubw-cpufreq {
+ cpu-to-dev-map-4 =
+ < 1881600 MHZ_TO_MBPS(200, 4) >,
+ < 2400000 MHZ_TO_MBPS(681, 4) >;
+ };
+};
+
&clock_gcc {
compatible = "qcom,gcc-sdm845-v2", "syscon";
};
@@ -885,15 +908,16 @@
&mdss_mdp {
clock-max-rate = <0 0 0 0 430000000 19200000 0>;
+ qcom,sde-min-core-ib-kbps = <4800000>;
};
&energy_costs {
CPU_COST_0: core-cost0 {
busy-cost-data = <
- 300000 11
+ 300000 12
403200 17
480000 21
- 576000 26
+ 576000 27
652800 31
748800 37
825600 42
@@ -901,13 +925,13 @@
979200 52
1056000 57
1132800 62
- 1228800 69
+ 1228800 70
1324800 78
1420800 89
1516800 103
1612800 122
- 1689600 140
- 1766400 159
+ 1689600 141
+ 1766400 160
>;
idle-cost-data = <
22 18 14 12
@@ -915,37 +939,37 @@
};
CPU_COST_1: core-cost1 {
busy-cost-data = <
- 300000 130
- 403200 480
- 480000 730
- 576000 1030
- 652800 1260
- 748800 1530
- 825600 1740
- 902400 1930
- 979200 2110
- 1056000 2290
- 1132800 2460
- 1209600 2630
- 1286400 2800
- 1363200 2980
- 1459200 3240
- 1536000 3490
- 1612800 3780
- 1689600 4120
- 1766400 4530
- 1843200 5020
- 1920000 5590
- 1996800 6230
+ 300000 189
+ 403200 523
+ 480000 763
+ 576000 1052
+ 652800 1273
+ 748800 1536
+ 825600 1736
+ 902400 1926
+ 979200 2108
+ 1056000 2284
+ 1132800 2456
+ 1209600 2628
+ 1286400 2804
+ 1363200 2992
+ 1459200 3255
+ 1536000 3499
+ 1612800 3786
+ 1689600 4128
+ 1766400 4535
+ 1843200 5019
+ 1920000 5583
+ 1996800 6226
2092800 7120
- 2169600 7870
- 2246400 8620
- 2323200 9330
+ 2169600 7876
+ 2246400 8628
+ 2323200 9344
2400000 10030
- 2476800 10830
- 2553600 12080
- 2630400 14580
- 2707200 19960
+ 2476800 10806
+ 2553600 12045
+ 2649600 15686
+ 2745600 25586
>;
idle-cost-data = <
100 80 60 40
@@ -1007,8 +1031,8 @@
2400000 135
2476800 140
2553600 145
- 2630400 150
- 2707200 155
+ 2649600 150
+ 2745600 155
>;
idle-cost-data = <
4 3 2 1
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index d72c91c..1a88ec8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -828,12 +828,12 @@
<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_LLCC>;
qcom,active-only;
qcom,bw-tbl =
- < 2288 /* 150 MHz */ >,
- < 4577 /* 300 MHz */ >,
- < 6500 /* 426 MHz */ >,
- < 8132 /* 533 MHz */ >,
- < 9155 /* 600 MHz */ >,
- < 10681 /* 700 MHz */ >;
+ < MHZ_TO_MBPS(150, 16) >, /* 2288 MB/s */
+ < MHZ_TO_MBPS(300, 16) >, /* 4577 MB/s */
+ < MHZ_TO_MBPS(426, 16) >, /* 6500 MB/s */
+ < MHZ_TO_MBPS(533, 16) >, /* 8132 MB/s */
+ < MHZ_TO_MBPS(600, 16) >, /* 9155 MB/s */
+ < MHZ_TO_MBPS(700, 16) >; /* 10681 MB/s */
};
bwmon: qcom,cpu-bwmon {
@@ -853,16 +853,16 @@
<MSM_BUS_MASTER_LLCC MSM_BUS_SLAVE_EBI_CH0>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 200 MHz */ >,
- < 1144 /* 300 MHz */ >,
- < 1720 /* 451 MHz */ >,
- < 2086 /* 547 MHz */ >,
- < 2597 /* 681 MHz */ >,
- < 2929 /* 768 MHz */ >,
- < 3879 /* 1017 MHz */ >,
- < 4943 /* 1296 MHz */ >,
- < 5931 /* 1555 MHz */ >,
- < 6881 /* 1804 MHz */ >;
+ < MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+ < MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+ < MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+ < MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+ < MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+ < MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+ < MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+ < MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+ < MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+ < MHZ_TO_MBPS(1804, 4) >; /* 6881 MB/s */
};
llcc_bwmon: qcom,llcc-bwmon {
@@ -883,16 +883,16 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 200 MHz */ >,
- < 1144 /* 300 MHz */ >,
- < 1720 /* 451 MHz */ >,
- < 2086 /* 547 MHz */ >,
- < 2597 /* 681 MHz */ >,
- < 2929 /* 768 MHz */ >,
- < 3879 /* 1017 MHz */ >,
- < 4943 /* 1296 MHz */ >,
- < 5931 /* 1555 MHz */ >,
- < 6881 /* 1804 MHz */ >;
+ < MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+ < MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+ < MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+ < MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+ < MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+ < MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+ < MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+ < MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+ < MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+ < MHZ_TO_MBPS(1804, 4) >; /* 6881 MB/s */
};
memlat_cpu4: qcom,memlat-cpu4 {
@@ -902,16 +902,16 @@
qcom,active-only;
status = "ok";
qcom,bw-tbl =
- < 762 /* 200 MHz */ >,
- < 1144 /* 300 MHz */ >,
- < 1720 /* 451 MHz */ >,
- < 2086 /* 547 MHz */ >,
- < 2597 /* 681 MHz */ >,
- < 2929 /* 768 MHz */ >,
- < 3879 /* 1017 MHz */ >,
- < 4943 /* 1296 MHz */ >,
- < 5931 /* 1555 MHz */ >,
- < 6881 /* 1804 MHz */ >;
+ < MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+ < MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+ < MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+ < MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+ < MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+ < MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+ < MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+ < MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+ < MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+ < MHZ_TO_MBPS(1804, 4) >; /* 6881 MB/s */
};
snoc_cnoc_keepalive: qcom,snoc_cnoc_keepalive {
@@ -930,11 +930,11 @@
qcom,target-dev = <&memlat_cpu0>;
qcom,cachemiss-ev = <0x2A>;
qcom,core-dev-table =
- < 300000 762 >,
- < 748800 1720 >,
- < 1132800 2086 >,
- < 1440000 2929 >,
- < 1593600 3879 >;
+ < 300000 MHZ_TO_MBPS( 200, 4) >,
+ < 748800 MHZ_TO_MBPS( 451, 4) >,
+ < 1132800 MHZ_TO_MBPS( 547, 4) >,
+ < 1440000 MHZ_TO_MBPS( 768, 4) >,
+ < 1593600 MHZ_TO_MBPS(1017, 4) >;
};
devfreq_memlat_4: qcom,cpu4-memlat-mon {
@@ -943,14 +943,14 @@
qcom,target-dev = <&memlat_cpu4>;
qcom,cachemiss-ev = <0x2A>;
qcom,core-dev-table =
- < 300000 762 >,
- < 499200 1720 >,
- < 806400 2086 >,
- < 1036800 2929 >,
- < 1190400 3879 >,
- < 1574400 4943 >,
- < 1728000 5931 >,
- < 1958400 6881 >;
+ < 300000 MHZ_TO_MBPS( 200, 4) >,
+ < 499200 MHZ_TO_MBPS( 451, 4) >,
+ < 806400 MHZ_TO_MBPS( 547, 4) >,
+ < 1036800 MHZ_TO_MBPS( 768, 4) >,
+ < 1190400 MHZ_TO_MBPS(1017, 4) >,
+ < 1574400 MHZ_TO_MBPS(1296, 4) >,
+ < 1728000 MHZ_TO_MBPS(1555, 4) >,
+ < 1958400 MHZ_TO_MBPS(1804, 4) >;
};
l3_cpu0: qcom,l3-cpu0 {
@@ -1008,26 +1008,26 @@
qcom,src-dst-ports = <1 512>;
qcom,active-only;
qcom,bw-tbl =
- < 762 /* 200 MHz */ >,
- < 1144 /* 300 MHz */ >,
- < 1720 /* 451 MHz */ >,
- < 2086 /* 547 MHz */ >,
- < 2597 /* 681 MHz */ >,
- < 2929 /* 768 MHz */ >,
- < 3879 /* 1017 MHz */ >,
- < 4943 /* 1296 MHz */ >,
- < 5931 /* 1555 MHz */ >,
- < 6881 /* 1804 MHz */ >;
+ < MHZ_TO_MBPS( 200, 4) >, /* 762 MB/s */
+ < MHZ_TO_MBPS( 300, 4) >, /* 1144 MB/s */
+ < MHZ_TO_MBPS( 451, 4) >, /* 1720 MB/s */
+ < MHZ_TO_MBPS( 547, 4) >, /* 2086 MB/s */
+ < MHZ_TO_MBPS( 681, 4) >, /* 2597 MB/s */
+ < MHZ_TO_MBPS( 768, 4) >, /* 2929 MB/s */
+ < MHZ_TO_MBPS(1017, 4) >, /* 3879 MB/s */
+ < MHZ_TO_MBPS(1296, 4) >, /* 4943 MB/s */
+ < MHZ_TO_MBPS(1555, 4) >, /* 5931 MB/s */
+ < MHZ_TO_MBPS(1804, 4) >; /* 6881 MB/s */
};
- devfreq-cpufreq {
+ devfreq_cpufreq: devfreq-cpufreq {
mincpubw-cpufreq {
target-dev = <&mincpubw>;
cpu-to-dev-map-0 =
- < 1708800 762 >;
+ < 1708800 MHZ_TO_MBPS(200, 4) >;
cpu-to-dev-map-4 =
- < 1881600 762 >,
- < 2208000 2597 >;
+ < 1881600 MHZ_TO_MBPS(200, 4) >,
+ < 2208000 MHZ_TO_MBPS(681, 4) >;
};
};
@@ -1742,6 +1742,7 @@
qcom,ssctl-instance-id = <0x12>;
qcom,override-acc;
qcom,qdsp6v65-1-0;
+ qcom,mss_pdc_offset = <8>;
status = "ok";
memory-region = <&pil_modem_mem>;
qcom,mem-protect-id = <0xF>;
@@ -2540,6 +2541,18 @@
qcom,fragmented-data;
};
+ qcom,qsee_ipc_irq_bridge {
+ compatible = "qcom,qsee-ipc-irq-bridge";
+
+ qcom,qsee-ipq-irq-spss {
+ qcom,rx-irq-clr = <0x1888008 0x4>;
+ qcom,rx-irq-clr-mask = <0x1>;
+ qcom,dev-name = "qsee_ipc_irq_spss";
+ interrupts = <0 349 4>;
+ label = "spss";
+ };
+ };
+
qcom,spcom {
compatible = "qcom,spcom";
@@ -3041,6 +3054,11 @@
#cooling-cells = <2>;
};
+ modem_skin: modem_skin {
+ qcom,qmi-dev-name = "modem_skin";
+ #cooling-cells = <2>;
+ };
+
modem_vdd: modem_vdd {
qcom,qmi-dev-name = "cpuv_restriction_cold";
#cooling-cells = <2>;
diff --git a/arch/arm64/boot/dts/qcom/smb1355.dtsi b/arch/arm64/boot/dts/qcom/smb1355.dtsi
index 6b7ebbd..bde4d1e 100644
--- a/arch/arm64/boot/dts/qcom/smb1355.dtsi
+++ b/arch/arm64/boot/dts/qcom/smb1355.dtsi
@@ -13,30 +13,75 @@
#include <dt-bindings/interrupt-controller/irq.h>
&qupv3_se10_i2c {
- smb1355: qcom,smb1355@8 {
+ smb1355_0: qcom,smb1355@8 {
compatible = "qcom,i2c-pmic";
reg = <0x8>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&spmi_bus>;
interrupts = <0x0 0xd1 0x0 IRQ_TYPE_LEVEL_LOW>;
- interrupt_names = "smb1355";
+ interrupt_names = "smb1355_0";
interrupt-controller;
#interrupt-cells = <3>;
qcom,periph-map = <0x10 0x12 0x13 0x16>;
- smb1355_revid: qcom,revid@100 {
+ smb1355_revid_0: qcom,revid@100 {
compatible = "qcom,qpnp-revid";
reg = <0x100 0x100>;
};
- smb1355_charger: qcom,smb1355-charger@1000 {
+ smb1355_charger_0: qcom,smb1355-charger@1000 {
compatible = "qcom,smb1355";
- qcom,pmic-revid = <&smb1355_revid>;
+ qcom,pmic-revid = <&smb1355_revid_0>;
reg = <0x1000 0x700>;
#address-cells = <1>;
#size-cells = <1>;
- interrupt-parent = <&smb1355>;
+ interrupt-parent = <&smb1355_0>;
+ status = "disabled";
+
+ io-channels = <&pmi8998_rradc 2>,
+ <&pmi8998_rradc 12>;
+ io-channel-names = "charger_temp",
+ "charger_temp_max";
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x10 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "chg-state-change";
+ };
+
+ qcom,chgr-misc@1600 {
+ reg = <0x1600 0x100>;
+ interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog-bark";
+ };
+ };
+ };
+
+ smb1355_1: qcom,smb1355@c {
+ compatible = "qcom,i2c-pmic";
+ reg = <0xc>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x0 0xd1 0x0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt_names = "smb1355_1";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ qcom,periph-map = <0x10 0x12 0x13 0x16>;
+
+ smb1355_revid_1: qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ smb1355_charger_1: qcom,smb1355-charger@1000 {
+ compatible = "qcom,smb1355";
+ qcom,pmic-revid = <&smb1355_revid_1>;
+ reg = <0x1000 0x700>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&smb1355_1>;
status = "disabled";
io-channels = <&pmi8998_rradc 2>,
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 07e7ee9..dc09f04 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -321,10 +321,12 @@
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_VIRTUAL_SENSOR=y
CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -390,6 +392,7 @@
CONFIG_USB_PD_POLICY=y
CONFIG_QPNP_USB_PDPHY=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
@@ -454,9 +457,14 @@
CONFIG_MSM_11AD=m
CONFIG_SEEMP_CORE=y
CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
CONFIG_CLOCK_QPNP_DIV=y
CONFIG_MSM_CLK_RPMH=y
CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
CONFIG_MSM_CLK_AOP_QMP=y
CONFIG_QCOM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 48512be..8d3bd72 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -331,6 +331,8 @@
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_VIRTUAL_SENSOR=y
CONFIG_QTI_AOP_REG_COOLING_DEVICE=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -386,6 +388,7 @@
CONFIG_USB_PD_POLICY=y
CONFIG_QPNP_USB_PDPHY=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
@@ -458,9 +461,14 @@
CONFIG_MSM_11AD=m
CONFIG_SEEMP_CORE=y
CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
CONFIG_CLOCK_QPNP_DIV=y
CONFIG_MSM_CLK_RPMH=y
CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
CONFIG_MSM_CLK_AOP_QMP=y
CONFIG_QCOM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index d2d2bf0..a04d0f4 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -528,6 +528,7 @@
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 6cc9459..4933500 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -551,6 +551,7 @@
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QMP_DEBUGFS_CLIENT=y
CONFIG_MSM_REMOTEQDSS=y
+CONFIG_QSEE_IPC_IRQ_BRIDGE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
CONFIG_QCOMCCI_HWMON=y
@@ -611,6 +612,7 @@
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 88edacd..9f1a1bb 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3252,6 +3252,7 @@
err_dead_proc_or_thread:
return_error = BR_DEAD_REPLY;
return_error_line = __LINE__;
+ binder_dequeue_work(proc, tcomplete);
err_translate_failed:
err_bad_object_type:
err_bad_offset:
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 55687b8..e17ad53 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -208,6 +208,59 @@
#endif
+static ssize_t show_sched_load_boost(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t rc;
+ unsigned int boost;
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ int cpuid = cpu->dev.id;
+
+ boost = per_cpu(sched_load_boost, cpuid);
+ rc = snprintf(buf, PAGE_SIZE-2, "%d\n", boost);
+
+ return rc;
+}
+
+static ssize_t __ref store_sched_load_boost(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err;
+ int boost;
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ int cpuid = cpu->dev.id;
+
+ err = kstrtoint(strstrip((char *)buf), 0, &boost);
+ if (err)
+ return err;
+
+ /*
+ * -100 is low enough to cancel out CPU's load and make it near zro.
+ * 1000 is close to the maximum value that cpu_util_freq_{walt,pelt}
+ * can take without overflow.
+ */
+ if (boost < -100 || boost > 1000)
+ return -EINVAL;
+
+ per_cpu(sched_load_boost, cpuid) = boost;
+
+ return count;
+}
+
+static DEVICE_ATTR(sched_load_boost, 0644,
+ show_sched_load_boost,
+ store_sched_load_boost);
+
+static struct attribute *sched_cpu_attrs[] = {
+ &dev_attr_sched_load_boost.attr,
+ NULL
+};
+
+static struct attribute_group sched_cpu_attr_group = {
+ .attrs = sched_cpu_attrs,
+};
+
static const struct attribute_group *common_cpu_attr_groups[] = {
#ifdef CONFIG_KEXEC
&crash_note_cpu_attr_group,
@@ -215,6 +268,7 @@
#ifdef CONFIG_HOTPLUG_CPU
&cpu_isolated_attr_group,
#endif
+ &sched_cpu_attr_group,
NULL
};
@@ -225,6 +279,7 @@
#ifdef CONFIG_HOTPLUG_CPU
&cpu_isolated_attr_group,
#endif
+ &sched_cpu_attr_group,
NULL
};
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 636c982..874639f 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -60,6 +60,7 @@
#define NUM_SESSIONS 9 /*8 compute, 1 cpz*/
#define M_FDLIST (16)
#define M_CRCLIST (64)
+#define SESSION_ID_INDEX (30)
#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)
@@ -282,6 +283,7 @@
struct fastrpc_session_ctx *secsctx;
uint32_t mode;
uint32_t profile;
+ int sessionid;
int tgid;
int cid;
int ssrcount;
@@ -860,7 +862,7 @@
}
ctx->retval = -1;
ctx->pid = current->pid;
- ctx->tgid = current->tgid;
+ ctx->tgid = fl->tgid;
init_completion(&ctx->work);
spin_lock(&fl->hlock);
@@ -1351,8 +1353,10 @@
VERIFY(err, 0 != channel_ctx->chan);
if (err)
goto bail;
- msg->pid = current->tgid;
+ msg->pid = fl->tgid;
msg->tid = current->pid;
+ if (fl->sessionid)
+ msg->tid |= (1 << SESSION_ID_INDEX);
if (kernel)
msg->pid = 0;
msg->invoke.header.ctx = ptr_to_uint64(ctx) | fl->pd;
@@ -1407,6 +1411,7 @@
if (fl->profile)
getnstimeofday(&invoket);
+
VERIFY(err, fl->sctx != NULL);
if (err)
goto bail;
@@ -1504,7 +1509,7 @@
goto bail;
if (init->flags == FASTRPC_INIT_ATTACH) {
remote_arg_t ra[1];
- int tgid = current->tgid;
+ int tgid = fl->tgid;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
@@ -1532,7 +1537,7 @@
int siglen;
} inbuf;
- inbuf.pgid = current->tgid;
+ inbuf.pgid = fl->tgid;
inbuf.namelen = strlen(current->comm) + 1;
inbuf.filelen = init->filelen;
fl->pd = 1;
@@ -1645,7 +1650,7 @@
uintptr_t vaddrout;
} routargs;
- inargs.pid = current->tgid;
+ inargs.pid = fl->tgid;
inargs.vaddrin = (uintptr_t)map->va;
inargs.flags = flags;
inargs.num = fl->apps->compat ? num * sizeof(page) : num;
@@ -1687,7 +1692,7 @@
ssize_t size;
} inargs;
- inargs.pid = current->tgid;
+ inargs.pid = fl->tgid;
inargs.size = map->size;
inargs.vaddrout = map->raddr;
ra[0].buf.pv = (void *)&inargs;
@@ -2226,6 +2231,7 @@
INIT_HLIST_HEAD(&fl->maps);
INIT_HLIST_HEAD(&fl->bufs);
INIT_HLIST_NODE(&fl->hn);
+ fl->sessionid = 0;
fl->tgid = current->tgid;
fl->apps = me;
fl->mode = FASTRPC_MODE_SERIAL;
@@ -2386,6 +2392,10 @@
case FASTRPC_MODE_PROFILE:
fl->profile = (uint32_t)ioctl_param;
break;
+ case FASTRPC_MODE_SESSION:
+ fl->sessionid = 1;
+ fl->tgid |= (1 << SESSION_ID_INDEX);
+ break;
default:
err = -ENOTTY;
break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 9f964d2..2e8bfc2 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -52,6 +52,9 @@
/* Driver should operate in profile mode with the co-processor */
#define FASTRPC_MODE_PROFILE 2
+/* Set FastRPC session ID to 1 */
+#define FASTRPC_MODE_SESSION 4
+
/* INIT a new process or attach to guestos */
#define FASTRPC_INIT_ATTACH 0
#define FASTRPC_INIT_CREATE 1
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index 3684b8d..5de7897 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, 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
@@ -90,6 +90,18 @@
{
if (id < 0 || id >= NUM_REMOTE_DEV)
return -EINVAL;
+
+ if ((mode == DIAG_USB_MODE &&
+ driver->logging_mode == DIAG_MEMORY_DEVICE_MODE) ||
+ (mode == DIAG_MEMORY_DEVICE_MODE &&
+ driver->logging_mode == DIAG_USB_MODE)) {
+ /*
+ * Don't close the MHI channels when usb is disconnected
+ * and a process is running in memory device mode.
+ */
+ return 0;
+ }
+
if (bridge_info[id].dev_ops && bridge_info[id].dev_ops->close)
bridge_info[id].dev_ops->close(bridge_info[id].ctxt);
return 0;
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index d7e24fc..354c6a0 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -729,8 +729,9 @@
struct diagfwd_info *fwd_info_cmd = NULL;
char *process_name = NULL;
int err = 0;
+ char *root_str = NULL;
uint8_t local_diag_id = 0;
- uint8_t new_request = 0;
+ uint8_t new_request = 0, i = 0;
if (!buf || len == 0 || peripheral >= NUM_PERIPHERALS)
return;
@@ -753,20 +754,31 @@
ctrl_pkt.diag_id = diag_id;
new_request = 1;
}
+ root_str = strnstr(process_name, DIAG_ID_ROOT_STRING,
+ strlen(process_name));
if (new_request) {
fwd_info_data->num_pd++;
fwd_info_cmd->num_pd++;
+ if (root_str) {
+ fwd_info_cmd->diagid_root = ctrl_pkt.diag_id;
+ fwd_info_data->diagid_root = ctrl_pkt.diag_id;
+ } else {
+ i = fwd_info_cmd->num_pd - 2;
+ if (i >= 0)
+ fwd_info_cmd->diagid_user[i] =
+ ctrl_pkt.diag_id;
+
+ i = fwd_info_data->num_pd - 2;
+ if (i >= 0)
+ fwd_info_data->diagid_user[i] =
+ ctrl_pkt.diag_id;
+ }
}
- if (strnstr(process_name, DIAG_ID_ROOT_STRING, strlen(process_name))) {
- fwd_info_cmd->diagid_root = diag_id;
- fwd_info_data->diagid_root = diag_id;
+ if (root_str)
driver->diag_id_sent[peripheral] = 0;
- } else {
- fwd_info_cmd->diagid_user[fwd_info_cmd->num_pd - 2] = diag_id;
- fwd_info_data->diagid_user[fwd_info_data->num_pd - 2] = diag_id;
- }
+
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag: peripheral = %d: diag_id string = %s,diag_id = %d\n",
@@ -794,6 +806,10 @@
* to peripherals.
*/
driver->diag_id_sent[peripheral] = 1;
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: diag_id sent = %d to peripheral = %d with diag_id = %d for %s :\n",
+ driver->diag_id_sent[peripheral], peripheral,
+ ctrl_pkt.diag_id, process_name);
diag_send_updates_peripheral(peripheral);
diagfwd_buffers_init(fwd_info_data);
}
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 13904fd..9f7f699 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1058,7 +1058,7 @@
return -ENODEV;
if (type == TYPE_CMD) {
- if (driver->feature[peripheral].untag_header)
+ if (driver->feature[peripheral].diag_id_support)
if (!fwd_info->diagid_root ||
(!driver->diag_id_sent[peripheral])) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index e7d3ee4..afb2c01 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -459,6 +459,37 @@
}
}
+static int clk_fabia_pll_latch_input(struct clk_alpha_pll *pll,
+ struct regmap *regmap)
+{
+ u32 regval;
+ int ret = 0;
+
+ /* Latch the PLL input */
+ ret = regmap_update_bits(regmap, pll->offset + PLL_MODE,
+ FABIA_PLL_UPDATE, FABIA_PLL_UPDATE);
+ if (ret)
+ return ret;
+
+ /* Wait for 2 reference cycles before checking the ACK bit. */
+ udelay(1);
+ regmap_read(regmap, pll->offset + PLL_MODE, ®val);
+ if (!(regval & FABIA_PLL_ACK_LATCH)) {
+ WARN(1, "clk: PLL latch failed. Output may be unstable!\n");
+ return -EINVAL;
+ }
+
+ /* Return the latch input to 0 */
+ ret = regmap_update_bits(regmap, pll->offset + PLL_MODE,
+ FABIA_PLL_UPDATE, 0);
+ if (ret)
+ return ret;
+
+ /* Wait for PLL output to stabilize */
+ udelay(100);
+ return ret;
+}
+
void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct pll_config *config)
{
@@ -471,6 +502,7 @@
if (config->frac)
regmap_write(regmap, pll->offset + FABIA_FRAC_VAL,
config->frac);
+
if (config->config_ctl_val)
regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
config->config_ctl_val);
@@ -482,6 +514,14 @@
mask, val);
}
+ /*
+ * If the PLL has already been initialized, it would now be in a STANDBY
+ * state. Any new updates to the PLL frequency will require setting the
+ * PLL_UPDATE bit.
+ */
+ if (pll->inited)
+ clk_fabia_pll_latch_input(pll, regmap);
+
regmap_update_bits(regmap, pll->offset + PLL_MODE,
FABIA_PLL_HW_UPDATE_LOGIC_BYPASS,
FABIA_PLL_HW_UPDATE_LOGIC_BYPASS);
@@ -627,29 +667,8 @@
regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
regmap_write(pll->clkr.regmap, off + FABIA_FRAC_VAL, a);
- /* Latch the PLL input */
- ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
- FABIA_PLL_UPDATE, FABIA_PLL_UPDATE);
- if (ret)
- return ret;
-
- /* Wait for 2 reference cycles before checking the ACK bit. */
- udelay(1);
- regmap_read(pll->clkr.regmap, off + PLL_MODE, ®val);
- if (!(regval & FABIA_PLL_ACK_LATCH)) {
- WARN(1, "clk: PLL latch failed. Output may be unstable!\n");
- return -EINVAL;
- }
-
- /* Return the latch input to 0 */
- ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
- FABIA_PLL_UPDATE, 0);
- if (ret)
- return ret;
-
- /* Wait for PLL output to stabilize */
- udelay(100);
- return 0;
+ ret = clk_fabia_pll_latch_input(pll, pll->clkr.regmap);
+ return ret;
}
static void clk_fabia_pll_list_registers(struct seq_file *f, struct clk_hw *hw)
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index 4b89cbf..038e89c 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.c
@@ -397,21 +397,6 @@
if (rc)
goto out_mem;
- if (interrupt_mode) {
- drv->ecc_irq = platform_get_irq_byname(pdev, "ecc_irq");
- if (!drv->ecc_irq) {
- rc = -ENODEV;
- goto out_dev;
- }
-
- rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
- IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
- if (rc) {
- dev_err(dev, "failed to request ecc irq\n");
- goto out_dev;
- }
- }
-
drv->llcc_banks = devm_kzalloc(&pdev->dev,
sizeof(u32) * drv->num_banks, GFP_KERNEL);
@@ -437,6 +422,21 @@
platform_set_drvdata(pdev, edev_ctl);
+ if (interrupt_mode) {
+ drv->ecc_irq = platform_get_irq_byname(pdev, "ecc_irq");
+ if (!drv->ecc_irq) {
+ rc = -ENODEV;
+ goto out_dev;
+ }
+
+ rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
+ IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
+ if (rc) {
+ dev_err(dev, "failed to request ecc irq\n");
+ goto out_dev;
+ }
+ }
+
return 0;
out_dev:
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index c263115..67b6072 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -379,7 +379,7 @@
case DP_LINK_BW_5_4:
select = 2;
break;
- case DP_LINK_RATE_810:
+ case DP_LINK_BW_8_1:
select = 3;
break;
default:
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 94bd199..3a33ce4 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -15,6 +15,7 @@
#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
#include <linux/delay.h>
+#include <drm/drm_dp_helper.h>
#include "dp_catalog.h"
#include "dp_reg.h"
@@ -408,7 +409,8 @@
u32 mvid, nvid;
u64 mvid_calc;
u32 const nvid_fixed = 0x8000;
- u32 const link_rate = 540000;
+ u32 const link_rate_hbr2 = 540000;
+ u32 const link_rate_hbr3 = 810000;
struct dp_catalog_private *catalog;
void __iomem *base_cc, *base_ctrl;
@@ -449,8 +451,11 @@
pr_debug("rate = %d\n", rate);
- if (link_rate == rate)
+ if (link_rate_hbr2 == rate)
nvid *= 2;
+
+ if (link_rate_hbr3 == rate)
+ nvid *= 3;
}
base_ctrl = catalog->io->ctrl_io.base;
@@ -493,6 +498,43 @@
pr_err("set link_train=%d failed\n", pattern);
}
+static void dp_catalog_ctrl_usb_reset(struct dp_catalog_ctrl *ctrl, bool flip)
+{
+ struct dp_catalog_private *catalog;
+ void __iomem *base;
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ dp_catalog_get_priv(ctrl);
+
+ base = catalog->io->usb3_dp_com.base;
+
+ dp_write(base + USB3_DP_COM_RESET_OVRD_CTRL, 0x0a);
+ dp_write(base + USB3_DP_COM_PHY_MODE_CTRL, 0x02);
+ dp_write(base + USB3_DP_COM_SW_RESET, 0x01);
+ /* make sure usb3 com phy software reset is done */
+ wmb();
+
+ if (!flip) /* CC1 */
+ dp_write(base + USB3_DP_COM_TYPEC_CTRL, 0x02);
+ else /* CC2 */
+ dp_write(base + USB3_DP_COM_TYPEC_CTRL, 0x03);
+
+ dp_write(base + USB3_DP_COM_SWI_CTRL, 0x00);
+ dp_write(base + USB3_DP_COM_SW_RESET, 0x00);
+ /* make sure the software reset is done */
+ wmb();
+
+ dp_write(base + USB3_DP_COM_POWER_DOWN_CTRL, 0x01);
+ dp_write(base + USB3_DP_COM_RESET_OVRD_CTRL, 0x00);
+ /* make sure phy is brought out of reset */
+ wmb();
+
+}
+
static void dp_catalog_ctrl_reset(struct dp_catalog_ctrl *ctrl)
{
u32 sw_reset;
@@ -706,6 +748,82 @@
}
}
+static void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog_ctrl *ctrl,
+ u32 pattern)
+{
+ struct dp_catalog_private *catalog;
+ u32 value = 0x0;
+ void __iomem *base = NULL;
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ dp_catalog_get_priv(ctrl);
+
+ base = catalog->io->ctrl_io.base;
+
+ dp_write(base + DP_STATE_CTRL, 0x0);
+
+ switch (pattern) {
+ case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
+ dp_write(base + DP_STATE_CTRL, 0x1);
+ break;
+ case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
+ value &= ~(1 << 16);
+ dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
+ value |= 0xFC;
+ dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
+ dp_write(base + DP_MAINLINK_LEVELS, 0x2);
+ dp_write(base + DP_STATE_CTRL, 0x10);
+ break;
+ case DP_TEST_PHY_PATTERN_PRBS7:
+ dp_write(base + DP_STATE_CTRL, 0x20);
+ break;
+ case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
+ dp_write(base + DP_STATE_CTRL, 0x40);
+ /* 00111110000011111000001111100000 */
+ dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG0, 0x3E0F83E0);
+ /* 00001111100000111110000011111000 */
+ dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG1, 0x0F83E0F8);
+ /* 1111100000111110 */
+ dp_write(base + DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 0x0000F83E);
+ break;
+ case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
+ value = BIT(16);
+ dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
+ value |= 0xFC;
+ dp_write(base + DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value);
+ dp_write(base + DP_MAINLINK_LEVELS, 0x2);
+ dp_write(base + DP_STATE_CTRL, 0x10);
+ break;
+ default:
+ pr_debug("No valid test pattern requested: 0x%x\n", pattern);
+ return;
+ }
+
+ /* Make sure the test pattern is programmed in the hardware */
+ wmb();
+}
+
+static u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog_ctrl *ctrl)
+{
+ struct dp_catalog_private *catalog;
+ void __iomem *base = NULL;
+
+ if (!ctrl) {
+ pr_err("invalid input\n");
+ return 0;
+ }
+
+ dp_catalog_get_priv(ctrl);
+
+ base = catalog->io->ctrl_io.base;
+
+ return dp_read(base + DP_MAINLINK_READY);
+}
+
/* panel related catalog functions */
static int dp_catalog_panel_timing_cfg(struct dp_catalog_panel *panel)
{
@@ -937,6 +1055,7 @@
.config_msa = dp_catalog_ctrl_config_msa,
.set_pattern = dp_catalog_ctrl_set_pattern,
.reset = dp_catalog_ctrl_reset,
+ .usb_reset = dp_catalog_ctrl_usb_reset,
.mainlink_ready = dp_catalog_ctrl_mainlink_ready,
.enable_irq = dp_catalog_ctrl_enable_irq,
.hpd_config = dp_catalog_ctrl_hpd_config,
@@ -946,6 +1065,8 @@
.get_interrupt = dp_catalog_ctrl_get_interrupt,
.update_transfer_unit = dp_catalog_ctrl_update_transfer_unit,
.read_hdcp_status = dp_catalog_ctrl_read_hdcp_status,
+ .send_phy_pattern = dp_catalog_ctrl_send_phy_pattern,
+ .read_phy_pattern = dp_catalog_ctrl_read_phy_pattern,
};
struct dp_catalog_audio audio = {
.init = dp_catalog_audio_init,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 47c10bf..4523b4f 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -65,6 +65,7 @@
u32 stream_rate_khz, bool fixed_nvid);
void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
void (*reset)(struct dp_catalog_ctrl *ctrl);
+ void (*usb_reset)(struct dp_catalog_ctrl *ctrl, bool flip);
bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl);
void (*enable_irq)(struct dp_catalog_ctrl *ctrl, bool enable);
void (*hpd_config)(struct dp_catalog_ctrl *ctrl, bool enable);
@@ -76,6 +77,9 @@
void (*get_interrupt)(struct dp_catalog_ctrl *ctrl);
void (*update_transfer_unit)(struct dp_catalog_ctrl *ctrl);
u32 (*read_hdcp_status)(struct dp_catalog_ctrl *ctrl);
+ void (*send_phy_pattern)(struct dp_catalog_ctrl *ctrl,
+ u32 pattern);
+ u32 (*read_phy_pattern)(struct dp_catalog_ctrl *ctrl);
};
enum dp_catalog_audio_sdp_type {
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 51abcf5..9ce23b1 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -36,6 +36,11 @@
#define ST_SEND_VIDEO BIT(7)
#define ST_PUSH_IDLE BIT(8)
+#define MR_LINK_TRAINING1 0x8
+#define MR_LINK_SYMBOL_ERM 0x80
+#define MR_LINK_PRBS7 0x100
+#define MR_LINK_CUSTOM80 0x200
+
struct dp_vc_tu_mapping_table {
u32 vic;
u8 lanes;
@@ -63,7 +68,6 @@
struct completion idle_comp;
struct completion video_comp;
- struct completion irq_comp;
bool psm_enabled;
bool orientation;
@@ -155,7 +159,7 @@
config |= tbd << 8;
/* Num of Lanes */
- config |= ((ctrl->link->lane_count - 1) << 4);
+ config |= ((ctrl->link->link_params.lane_count - 1) << 4);
if (drm_dp_enhanced_frame_cap(dpcd))
config |= 0x40;
@@ -303,7 +307,7 @@
u64 brute_force_threshold = 10;
u64 diff_abs;
- ln_cnt = ctrl->link->lane_count;
+ ln_cnt = ctrl->link->link_params.lane_count;
bpp = pinfo->bpp;
lwidth = pinfo->h_active;
@@ -322,7 +326,8 @@
even_distribution = 0;
min_hblank = 0;
- lclk = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code) * DP_KHZ_TO_HZ;
+ lclk = drm_dp_bw_code_to_link_rate(
+ ctrl->link->link_params.bw_code) * DP_KHZ_TO_HZ;
pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n",
pclk, lwidth, h_blank);
@@ -761,9 +766,10 @@
struct dp_link *link = ctrl->link;
ctrl->catalog->update_vx_px(ctrl->catalog,
- link->v_level, link->p_level);
+ link->phy_params.v_level, link->phy_params.p_level);
- dp_ctrl_update_sink_vx_px(ctrl, link->v_level, link->p_level);
+ dp_ctrl_update_sink_vx_px(ctrl, link->phy_params.v_level,
+ link->phy_params.p_level);
}
static void dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,
@@ -816,7 +822,7 @@
dp_ctrl_update_vx_px(ctrl);
tries = 0;
- old_v_level = ctrl->link->v_level;
+ old_v_level = ctrl->link->phy_params.v_level;
while (1) {
drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);
@@ -825,26 +831,26 @@
break;
if (drm_dp_clock_recovery_ok(link_status,
- ctrl->link->lane_count)) {
+ ctrl->link->link_params.lane_count)) {
break;
}
- if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) {
+ if (ctrl->link->phy_params.v_level == DP_LINK_VOLTAGE_MAX) {
pr_err_ratelimited("max v_level reached\n");
ret = -EAGAIN;
break;
}
- if (old_v_level == ctrl->link->v_level) {
+ if (old_v_level == ctrl->link->phy_params.v_level) {
tries++;
if (tries >= maximum_retries) {
pr_err("max tries reached\n");
- ret = -EAGAIN;
+ ret = -ETIMEDOUT;
break;
}
} else {
tries = 0;
- old_v_level = ctrl->link->v_level;
+ old_v_level = ctrl->link->phy_params.v_level;
}
pr_debug("clock recovery not done, adjusting vx px\n");
@@ -859,41 +865,25 @@
static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
{
int ret = 0;
- u32 min_req_link_rate_khz;
- u32 new_proposed_link_bw_code;
- u32 new_proposed_link_rate_khz;
if (!ctrl)
return -EINVAL;
- min_req_link_rate_khz = ctrl->panel->get_min_req_link_rate(ctrl->panel);
-
- switch (ctrl->link->bw_code) {
- case DP_LINK_RATE_810:
- new_proposed_link_bw_code = DP_LINK_BW_5_4;
+ switch (ctrl->link->link_params.bw_code) {
+ case DP_LINK_BW_8_1:
+ ctrl->link->link_params.bw_code = DP_LINK_BW_5_4;
break;
case DP_LINK_BW_5_4:
- new_proposed_link_bw_code = DP_LINK_BW_2_7;
+ ctrl->link->link_params.bw_code = DP_LINK_BW_2_7;
break;
case DP_LINK_BW_2_7:
case DP_LINK_BW_1_62:
default:
- new_proposed_link_bw_code = DP_LINK_BW_1_62;
+ ctrl->link->link_params.bw_code = DP_LINK_BW_1_62;
break;
};
- new_proposed_link_rate_khz = drm_dp_bw_code_to_link_rate(
- new_proposed_link_bw_code);
-
- pr_debug("new proposed link rate=%d khz\n", new_proposed_link_rate_khz);
- pr_debug("min required link rate=%d khz\n", min_req_link_rate_khz);
-
- if (new_proposed_link_rate_khz >= min_req_link_rate_khz)
- ctrl->link->bw_code = new_proposed_link_bw_code;
- else
- pr_debug("can't go below min required link rate\n");
-
- pr_debug("new bw code=0x%x\n", ctrl->link->bw_code);
+ pr_debug("new bw code=0x%x\n", ctrl->link->link_params.bw_code);
return ret;
}
@@ -931,11 +921,12 @@
if (ret)
break;
- if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count))
+ if (drm_dp_channel_eq_ok(link_status,
+ ctrl->link->link_params.lane_count))
break;
if (tries > maximum_retries) {
- ret = -EAGAIN;
+ ret = -ETIMEDOUT;
break;
}
tries++;
@@ -953,13 +944,14 @@
u8 encoding = 0x1;
struct drm_dp_link link_info = {0};
- ctrl->link->p_level = 0;
- ctrl->link->v_level = 0;
+ ctrl->link->phy_params.p_level = 0;
+ ctrl->link->phy_params.v_level = 0;
dp_ctrl_config_ctrl(ctrl);
- link_info.num_lanes = ctrl->link->lane_count;
- link_info.rate = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code);
+ link_info.num_lanes = ctrl->link->link_params.lane_count;
+ link_info.rate = drm_dp_bw_code_to_link_rate(
+ ctrl->link->link_params.bw_code);
link_info.capabilities = ctrl->panel->link_info.capabilities;
drm_dp_link_configure(ctrl->aux->drm_aux, &link_info);
@@ -1002,7 +994,7 @@
drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->link_info);
- if (ctrl->link->phy_pattern_requested(ctrl->link))
+ if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
goto end;
if (!train)
@@ -1060,7 +1052,7 @@
ctrl->power->set_pixel_clk_parent(ctrl->power);
dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk",
- drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
+ drm_dp_bw_code_to_link_rate(ctrl->link->link_params.bw_code));
dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate);
@@ -1093,6 +1085,7 @@
ctrl->orientation = flip;
catalog = ctrl->catalog;
+ catalog->usb_reset(ctrl->catalog, flip);
catalog->reset(ctrl->catalog);
catalog->phy_reset(ctrl->catalog);
catalog->enable_irq(ctrl->catalog, true);
@@ -1147,95 +1140,223 @@
return false;
}
-static int dp_ctrl_on_irq(struct dp_ctrl_private *ctrl, bool lt_needed)
+static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)
{
int ret = 0;
+ ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
+ ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
+
+ ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
+
do {
- if (ret == -EAGAIN)
+ if (ret == -EAGAIN) {
+ /* try with lower link rate */
+ dp_ctrl_link_rate_down_shift(ctrl);
+
ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
+ }
ctrl->catalog->phy_lane_cfg(ctrl->catalog,
- ctrl->orientation, ctrl->link->lane_count);
+ ctrl->orientation, ctrl->link->link_params.lane_count);
- if (lt_needed) {
- /*
- * Diasable and re-enable the mainlink clock since the
- * link clock might have been adjusted as part of the
- * link maintenance.
- */
- if (!ctrl->link->phy_pattern_requested(
- ctrl->link))
- dp_ctrl_disable_mainlink_clocks(ctrl);
+ /*
+ * Disable and re-enable the mainlink clock since the
+ * link clock might have been adjusted as part of the
+ * link maintenance.
+ */
+ dp_ctrl_disable_mainlink_clocks(ctrl);
- ret = dp_ctrl_enable_mainlink_clocks(ctrl);
- if (ret)
- continue;
- }
+ ret = dp_ctrl_enable_mainlink_clocks(ctrl);
+ if (ret)
+ continue;
dp_ctrl_configure_source_params(ctrl);
ctrl->catalog->config_msa(ctrl->catalog,
- drm_dp_bw_code_to_link_rate(ctrl->link->bw_code),
+ drm_dp_bw_code_to_link_rate(
+ ctrl->link->link_params.bw_code),
ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
reinit_completion(&ctrl->idle_comp);
- if (ctrl->psm_enabled) {
- ret = ctrl->link->send_psm_request(ctrl->link, false);
- if (ret) {
- pr_err("failed to exit low power mode, rc=%d\n",
- ret);
- continue;
- }
- }
-
- ret = dp_ctrl_setup_main_link(ctrl, lt_needed);
+ ret = dp_ctrl_setup_main_link(ctrl, true);
} while (ret == -EAGAIN);
return ret;
}
-static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl)
+static void dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)
{
int ret = 0;
- u32 rate = ctrl->panel->link_info.rate;
+
+ if (!ctrl->link->phy_params.phy_test_pattern_sel) {
+ pr_debug("no test pattern selected by sink\n");
+ return;
+ }
+
+ pr_debug("start\n");
+
+ ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
+ /*
+ * The global reset will need DP link ralated clocks to be
+ * running. Add the global reset just before disabling the
+ * link clocks and core clocks.
+ */
+ ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
+ ctrl->dp_ctrl.off(&ctrl->dp_ctrl);
+
+ ret = ctrl->dp_ctrl.on(&ctrl->dp_ctrl);
+ if (ret)
+ pr_err("failed to enable DP controller\n");
+
+ pr_debug("end\n");
+}
+
+static void dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)
+{
+ bool success = false;
+ u32 pattern_sent = 0x0;
+ u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
+
+ pr_debug("request: %s\n",
+ dp_link_get_phy_test_pattern(pattern_requested));
+
+ ctrl->catalog->update_vx_px(ctrl->catalog,
+ ctrl->link->phy_params.v_level,
+ ctrl->link->phy_params.p_level);
+ ctrl->catalog->send_phy_pattern(ctrl->catalog, pattern_requested);
+ ctrl->link->send_test_response(ctrl->link);
+
+ pattern_sent = ctrl->catalog->read_phy_pattern(ctrl->catalog);
+
+ switch (pattern_sent) {
+ case MR_LINK_TRAINING1:
+ if (pattern_requested ==
+ DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING)
+ success = true;
+ break;
+ case MR_LINK_SYMBOL_ERM:
+ if ((pattern_requested ==
+ DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT)
+ || (pattern_requested ==
+ DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN))
+ success = true;
+ break;
+ case MR_LINK_PRBS7:
+ if (pattern_requested == DP_TEST_PHY_PATTERN_PRBS7)
+ success = true;
+ break;
+ case MR_LINK_CUSTOM80:
+ if (pattern_requested ==
+ DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN)
+ success = true;
+ break;
+ default:
+ success = false;
+ return;
+ }
+
+ pr_debug("%s: %s\n", success ? "success" : "failed",
+ dp_link_get_phy_test_pattern(pattern_requested));
+}
+
+static void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)
+{
+ struct dp_ctrl_private *ctrl;
+ u32 sink_request = 0x0;
+
+ if (!dp_ctrl) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ sink_request = ctrl->link->sink_request;
+
+ if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
+ pr_info("PHY_TEST_PATTERN request\n");
+ dp_ctrl_process_phy_test_request(ctrl);
+ }
+
+ if (sink_request & DP_LINK_STATUS_UPDATED)
+ dp_ctrl_link_maintenance(ctrl);
+
+ if (sink_request & DP_TEST_LINK_TRAINING) {
+ ctrl->link->send_test_response(ctrl->link);
+ dp_ctrl_link_maintenance(ctrl);
+ }
+}
+
+static void dp_ctrl_reset(struct dp_ctrl *dp_ctrl)
+{
+ struct dp_ctrl_private *ctrl;
+
+ if (!dp_ctrl) {
+ pr_err("invalid params\n");
+ return;
+ }
+
+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+ ctrl->catalog->reset(ctrl->catalog);
+}
+
+static int dp_ctrl_on(struct dp_ctrl *dp_ctrl)
+{
+ int rc = 0;
+ struct dp_ctrl_private *ctrl;
+ u32 rate = 0;
u32 link_train_max_retries = 100;
+ u32 const phy_cts_pixel_clk_khz = 148500;
+
+ if (!dp_ctrl) {
+ rc = -EINVAL;
+ goto end;
+ }
+
+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
atomic_set(&ctrl->aborted, 0);
+ rate = ctrl->panel->link_info.rate;
ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
ctrl->catalog->hpd_config(ctrl->catalog, true);
- ctrl->link->bw_code = drm_dp_link_rate_to_bw_code(rate);
- ctrl->link->lane_count = ctrl->panel->link_info.num_lanes;
- ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
+ if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
+ pr_debug("using phy test link parameters\n");
+ if (!ctrl->panel->pinfo.pixel_clk_khz)
+ ctrl->pixel_rate = phy_cts_pixel_clk_khz;
+ } else {
+ ctrl->link->link_params.bw_code =
+ drm_dp_link_rate_to_bw_code(rate);
+ ctrl->link->link_params.lane_count =
+ ctrl->panel->link_info.num_lanes;
+ ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
+ }
pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n",
- ctrl->link->bw_code, ctrl->link->lane_count,
- ctrl->pixel_rate);
+ ctrl->link->link_params.bw_code,
+ ctrl->link->link_params.lane_count, ctrl->pixel_rate);
ctrl->catalog->phy_lane_cfg(ctrl->catalog,
- ctrl->orientation, ctrl->link->lane_count);
+ ctrl->orientation, ctrl->link->link_params.lane_count);
- ret = dp_ctrl_enable_mainlink_clocks(ctrl);
- if (ret)
- goto exit;
+ rc = dp_ctrl_enable_mainlink_clocks(ctrl);
+ if (rc)
+ goto end;
reinit_completion(&ctrl->idle_comp);
dp_ctrl_configure_source_params(ctrl);
- if (ctrl->psm_enabled)
- ret = ctrl->link->send_psm_request(ctrl->link, false);
-
while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
ctrl->catalog->config_msa(ctrl->catalog,
- drm_dp_bw_code_to_link_rate(ctrl->link->bw_code),
+ drm_dp_bw_code_to_link_rate(
+ ctrl->link->link_params.bw_code),
ctrl->pixel_rate, dp_ctrl_use_fixed_nvid(ctrl));
- ret = dp_ctrl_setup_main_link(ctrl, true);
- if (!ret)
+ rc = dp_ctrl_setup_main_link(ctrl, true);
+ if (!rc)
break;
/* try with lower link rate */
@@ -1250,50 +1371,16 @@
dp_ctrl_enable_mainlink_clocks(ctrl);
}
+ if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
+ dp_ctrl_send_phy_test_pattern(ctrl);
+
pr_debug("End-\n");
-exit:
- return ret;
-}
-
-static void dp_ctrl_off_irq(struct dp_ctrl_private *ctrl)
-{
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
-
- /* Make sure DP mainlink and audio engines are disabled */
- wmb();
-
- complete_all(&ctrl->irq_comp);
- pr_debug("end\n");
-}
-
-static void dp_ctrl_off_hpd(struct dp_ctrl_private *ctrl)
-{
- ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
- pr_debug("DP off done\n");
-}
-
-static int dp_ctrl_on(struct dp_ctrl *dp_ctrl, bool hpd_irq)
-{
- int rc = 0;
- struct dp_ctrl_private *ctrl;
-
- if (!dp_ctrl) {
- rc = -EINVAL;
- goto end;
- }
-
- ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
-
- if (hpd_irq)
- rc = dp_ctrl_on_irq(ctrl, false);
- else
- rc = dp_ctrl_on_hpd(ctrl);
end:
return rc;
}
-static void dp_ctrl_off(struct dp_ctrl *dp_ctrl, bool hpd_irq)
+static void dp_ctrl_off(struct dp_ctrl *dp_ctrl)
{
struct dp_ctrl_private *ctrl;
@@ -1302,10 +1389,9 @@
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- if (hpd_irq)
- dp_ctrl_off_irq(ctrl);
- else
- dp_ctrl_off_hpd(ctrl);
+ ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
+ pr_debug("DP off done\n");
+
}
static void dp_ctrl_isr(struct dp_ctrl *dp_ctrl)
@@ -1347,7 +1433,6 @@
init_completion(&ctrl->idle_comp);
init_completion(&ctrl->video_comp);
- init_completion(&ctrl->irq_comp);
/* in parameters */
ctrl->parser = in->parser;
@@ -1367,6 +1452,8 @@
dp_ctrl->push_idle = dp_ctrl_push_idle;
dp_ctrl->abort = dp_ctrl_abort;
dp_ctrl->isr = dp_ctrl_isr;
+ dp_ctrl->reset = dp_ctrl_reset;
+ dp_ctrl->handle_sink_request = dp_ctrl_handle_sink_request;
return dp_ctrl;
error:
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 2ecfa0d..69cf6b6 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -23,13 +23,16 @@
#include "dp_catalog.h"
struct dp_ctrl {
+
int (*init)(struct dp_ctrl *dp_ctrl, bool flip);
void (*deinit)(struct dp_ctrl *dp_ctrl);
- int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
- void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
+ int (*on)(struct dp_ctrl *dp_ctrl);
+ void (*off)(struct dp_ctrl *dp_ctrl);
+ void (*reset)(struct dp_ctrl *dp_ctrl);
void (*push_idle)(struct dp_ctrl *dp_ctrl);
void (*abort)(struct dp_ctrl *dp_ctrl);
void (*isr)(struct dp_ctrl *dp_ctrl);
+ void (*handle_sink_request)(struct dp_ctrl *dp_ctrl);
};
struct dp_ctrl_in {
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 82e34df..cc9e623 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -306,33 +306,34 @@
/* Link Information */
rc = snprintf(buf + len, max_size,
"\tdp_link:\n\t\ttest_requested = %d\n",
- debug->link->test_requested);
+ debug->link->sink_request);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tlane_count = %d\n", debug->link->lane_count);
+ "\t\tlane_count = %d\n", debug->link->link_params.lane_count);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tbw_code = %d\n", debug->link->bw_code);
+ "\t\tbw_code = %d\n", debug->link->link_params.bw_code);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- lclk = drm_dp_bw_code_to_link_rate(debug->link->bw_code) * 1000;
+ lclk = drm_dp_bw_code_to_link_rate(
+ debug->link->link_params.bw_code) * 1000;
rc = snprintf(buf + len, max_size,
"\t\tlclk = %lld\n", lclk);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tv_level = %d\n", debug->link->v_level);
+ "\t\tv_level = %d\n", debug->link->phy_params.v_level);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tp_level = %d\n", debug->link->p_level);
+ "\t\tp_level = %d\n", debug->link->phy_params.p_level);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 7e40cc6..3fa376b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -422,6 +422,50 @@
.unbind = dp_display_unbind,
};
+static bool dp_display_is_ds_bridge(struct dp_panel *panel)
+{
+ return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
+ DP_DWN_STRM_PORT_PRESENT);
+}
+
+static bool dp_display_is_sink_count_zero(struct dp_display_private *dp)
+{
+ return dp_display_is_ds_bridge(dp->panel) &&
+ (dp->link->sink_count.count == 0);
+}
+
+static int dp_display_send_hpd_notification(struct dp_display_private *dp,
+ bool hpd)
+{
+
+ if ((hpd && dp->dp_display.is_connected) ||
+ (!hpd && !dp->dp_display.is_connected)) {
+ pr_info("HPD already %s\n", (hpd ? "on" : "off"));
+ return 0;
+ }
+
+ dp->dp_display.is_connected = hpd;
+ reinit_completion(&dp->notification_comp);
+ drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+
+ if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) {
+ pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void dp_display_handle_test_edid(struct dp_display_private *dp)
+{
+ if (dp->link->sink_request & DP_TEST_LINK_EDID_READ) {
+ drm_dp_dpcd_write(dp->aux->drm_aux, DP_TEST_EDID_CHECKSUM,
+ &dp->panel->edid_ctrl->edid->checksum, 1);
+ drm_dp_dpcd_write(dp->aux->drm_aux, DP_TEST_RESPONSE,
+ &dp->link->test_response, 1);
+ }
+}
+
static int dp_display_process_hpd_high(struct dp_display_private *dp)
{
int rc = 0;
@@ -432,23 +476,28 @@
if (rc)
return rc;
+ dp->link->process_request(dp->link);
+
+ if (dp_display_is_sink_count_zero(dp)) {
+ pr_debug("no downstream devices connected\n");
+ rc = -EINVAL;
+ goto end;
+ }
+
edid = dp->panel->edid_ctrl->edid;
dp->audio_supported = drm_detect_monitor_audio(edid);
+ dp_display_handle_test_edid(dp);
+
max_pclk_from_edid = dp->panel->get_max_pclk(dp->panel);
dp->dp_display.max_pclk_khz = min(max_pclk_from_edid,
dp->parser->max_pclk_khz);
- dp->dp_display.is_connected = true;
+ dp_display_send_hpd_notification(dp, true);
- drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
-
- reinit_completion(&dp->notification_comp);
- if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
- pr_warn("timeout\n");
-
+end:
return rc;
}
@@ -498,12 +547,7 @@
if (dp->audio_supported)
dp->audio->off(dp->audio);
- dp->dp_display.is_connected = false;
- drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
-
- reinit_completion(&dp->notification_comp);
- if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
- pr_warn("timeout\n");
+ dp_display_send_hpd_notification(dp, false);
}
static int dp_display_usbpd_configure_cb(struct device *dev)
@@ -543,7 +587,7 @@
}
dp->ctrl->push_idle(dp->ctrl);
- dp->ctrl->off(dp->ctrl, false);
+ dp->ctrl->off(dp->ctrl);
}
static int dp_display_usbpd_disconnect_cb(struct device *dev)
@@ -570,22 +614,34 @@
if (dp->audio_supported)
dp->audio->off(dp->audio);
- dp->dp_display.is_connected = false;
- drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+ rc = dp_display_send_hpd_notification(dp, false);
- reinit_completion(&dp->notification_comp);
- if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) {
- pr_warn("timeout\n");
-
- if (dp->power_on)
- dp_display_clean(dp);
- }
+ if ((rc < 0) && dp->power_on)
+ dp_display_clean(dp);
dp_display_host_deinit(dp);
end:
return rc;
}
+static int dp_display_handle_hpd_irq(struct dp_display_private *dp)
+{
+ if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) {
+ dp_display_send_hpd_notification(dp, false);
+
+ if (dp_display_is_sink_count_zero(dp)) {
+ pr_debug("sink count is zero, nothing to do\n");
+ return 0;
+ }
+
+ return dp_display_process_hpd_high(dp);
+ }
+
+ dp->ctrl->handle_sink_request(dp->ctrl);
+
+ return 0;
+}
+
static int dp_display_usbpd_attention_cb(struct device *dev)
{
int rc = 0;
@@ -611,9 +667,12 @@
}
rc = dp->link->process_request(dp->link);
- dp->hpd_irq_on = false;
+ /* check for any test request issued by sink */
if (!rc)
- goto end;
+ dp_display_handle_hpd_irq(dp);
+
+ dp->hpd_irq_on = false;
+ goto end;
}
if (!dp->usbpd->hpd_high) {
@@ -757,7 +816,12 @@
dp = container_of(dp_display, struct dp_display_private, dp_display);
- rc = dp->ctrl->on(dp->ctrl, dp->hpd_irq_on);
+ if (dp->power_on) {
+ pr_debug("Link already setup, return\n");
+ return 0;
+ }
+
+ rc = dp->ctrl->on(dp->ctrl);
if (!rc)
dp->power_on = true;
error:
@@ -778,8 +842,8 @@
dp = container_of(dp_display, struct dp_display_private, dp_display);
if (dp->audio_supported) {
- dp->audio->bw_code = dp->link->bw_code;
- dp->audio->lane_count = dp->link->lane_count;
+ dp->audio->bw_code = dp->link->link_params.bw_code;
+ dp->audio->lane_count = dp->link->link_params.lane_count;
dp->audio->on(dp->audio);
}
@@ -840,7 +904,7 @@
if (!dp->power_on || !dp->core_initialized)
goto error;
- dp->ctrl->off(dp->ctrl, dp->hpd_irq_on);
+ dp->ctrl->off(dp->ctrl);
dp->power_on = false;
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 48e6c8f..b62c1e9 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -17,8 +17,6 @@
#include "dp_link.h"
#include "dp_panel.h"
-#define DP_LINK_ENUM_STR(x) #x
-
enum dp_lane_count {
DP_LANE_COUNT_1 = 1,
DP_LANE_COUNT_2 = 2,
@@ -50,48 +48,15 @@
u32 test_requested;
u32 test_link_rate;
u32 test_lane_count;
- u32 phy_test_pattern_sel;
- u32 test_video_pattern;
- u32 test_bit_depth;
- u32 test_dyn_range;
- u32 test_h_total;
- u32 test_v_total;
- u32 test_h_start;
- u32 test_v_start;
- u32 test_hsync_pol;
- u32 test_hsync_width;
- u32 test_vsync_pol;
- u32 test_vsync_width;
- u32 test_h_width;
- u32 test_v_height;
- u32 test_rr_d;
- u32 test_rr_n;
- u32 test_audio_sampling_rate;
- u32 test_audio_channel_count;
- u32 test_audio_pattern_type;
- u32 test_audio_period_ch_1;
- u32 test_audio_period_ch_2;
- u32 test_audio_period_ch_3;
- u32 test_audio_period_ch_4;
- u32 test_audio_period_ch_5;
- u32 test_audio_period_ch_6;
- u32 test_audio_period_ch_7;
- u32 test_audio_period_ch_8;
- u32 response;
-};
-
-struct dp_link_sink_count {
- u32 count;
- bool cp_ready;
};
struct dp_link_private {
+ u32 prev_sink_count;
struct device *dev;
struct dp_aux *aux;
struct dp_link dp_link;
struct dp_link_request request;
- struct dp_link_sink_count sink_count;
u8 link_status[DP_LINK_STATUS_SIZE];
};
@@ -131,30 +96,6 @@
return bpp;
}
-static char *dp_link_get_phy_test_pattern(u32 phy_test_pattern_sel)
-{
- switch (phy_test_pattern_sel) {
- case DP_TEST_PHY_PATTERN_NONE:
- return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_NONE);
- case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING);
- case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT);
- case DP_TEST_PHY_PATTERN_PRBS7:
- return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_PRBS7);
- case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN);
- case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
- return DP_LINK_ENUM_STR(
- DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN);
- default:
- return "unknown";
- }
-}
-
static char *dp_link_get_audio_test_pattern(u32 pattern)
{
switch (pattern) {
@@ -223,7 +164,7 @@
static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
{
int ret = 0;
- struct dp_link_request *req = &link->request;
+ struct dp_link_test_audio *req = &link->dp_link.test_audio;
ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
if (ret == -EINVAL)
@@ -310,7 +251,7 @@
goto exit;
}
- link->request.test_audio_pattern_type = data;
+ link->dp_link.test_audio.test_audio_pattern_type = data;
pr_debug("audio pattern type = %s\n",
dp_link_get_audio_test_pattern(data));
exit:
@@ -356,8 +297,8 @@
goto exit;
}
- link->request.test_audio_sampling_rate = sampling_rate;
- link->request.test_audio_channel_count = channel_count;
+ link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
+ link->dp_link.test_audio.test_audio_channel_count = channel_count;
pr_debug("sampling_rate = %s, channel_count = 0x%x\n",
dp_link_get_audio_sample_rate(sampling_rate), channel_count);
exit:
@@ -578,11 +519,11 @@
goto exit;
}
- link->request.test_video_pattern = data;
+ link->dp_link.test_video.test_video_pattern = data;
pr_debug("link video pattern = 0x%x (%s)\n",
- link->request.test_video_pattern,
+ link->dp_link.test_video.test_video_pattern,
dp_link_video_pattern_to_string(
- link->request.test_video_pattern));
+ link->dp_link.test_video.test_video_pattern));
/* Read the requested color bit depth and dynamic range (Byte 0x232) */
rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_TEST_MISC0,
@@ -601,11 +542,11 @@
ret = -EINVAL;
goto exit;
}
- link->request.test_dyn_range = dyn_range;
+ link->dp_link.test_video.test_dyn_range = dyn_range;
pr_debug("link dynamic range = 0x%x (%s)\n",
- link->request.test_dyn_range,
+ link->dp_link.test_video.test_dyn_range,
dp_link_dynamic_range_to_string(
- link->request.test_dyn_range));
+ link->dp_link.test_video.test_dyn_range));
/* Color bit depth */
data &= DP_TEST_BIT_DEPTH_MASK;
@@ -615,96 +556,104 @@
goto exit;
}
- link->request.test_bit_depth = data;
+ link->dp_link.test_video.test_bit_depth = data;
pr_debug("link bit depth = 0x%x (%s)\n",
- link->request.test_bit_depth,
- dp_link_bit_depth_to_string(link->request.test_bit_depth));
+ link->dp_link.test_video.test_bit_depth,
+ dp_link_bit_depth_to_string(
+ link->dp_link.test_video.test_bit_depth));
/* resolution timing params */
ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
- &link->request.test_h_total);
+ &link->dp_link.test_video.test_h_total);
if (ret) {
pr_err("failed to parse test_h_total (DP_TEST_H_TOTAL_HI)\n");
goto exit;
}
- pr_debug("TEST_H_TOTAL = %d\n", link->request.test_h_total);
+ pr_debug("TEST_H_TOTAL = %d\n", link->dp_link.test_video.test_h_total);
ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
- &link->request.test_v_total);
+ &link->dp_link.test_video.test_v_total);
if (ret) {
pr_err("failed to parse test_v_total (DP_TEST_V_TOTAL_HI)\n");
goto exit;
}
- pr_debug("TEST_V_TOTAL = %d\n", link->request.test_v_total);
+ pr_debug("TEST_V_TOTAL = %d\n", link->dp_link.test_video.test_v_total);
ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
- &link->request.test_h_start);
+ &link->dp_link.test_video.test_h_start);
if (ret) {
pr_err("failed to parse test_h_start (DP_TEST_H_START_HI)\n");
goto exit;
}
- pr_debug("TEST_H_START = %d\n", link->request.test_h_start);
+ pr_debug("TEST_H_START = %d\n", link->dp_link.test_video.test_h_start);
ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
- &link->request.test_v_start);
+ &link->dp_link.test_video.test_v_start);
if (ret) {
pr_err("failed to parse test_v_start (DP_TEST_V_START_HI)\n");
goto exit;
}
- pr_debug("TEST_V_START = %d\n", link->request.test_v_start);
+ pr_debug("TEST_V_START = %d\n", link->dp_link.test_video.test_v_start);
ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
- &link->request.test_hsync_pol,
- &link->request.test_hsync_width);
+ &link->dp_link.test_video.test_hsync_pol,
+ &link->dp_link.test_video.test_hsync_width);
if (ret) {
pr_err("failed to parse (DP_TEST_HSYNC_HI)\n");
goto exit;
}
- pr_debug("TEST_HSYNC_POL = %d\n", link->request.test_hsync_pol);
- pr_debug("TEST_HSYNC_WIDTH = %d\n", link->request.test_hsync_width);
+ pr_debug("TEST_HSYNC_POL = %d\n",
+ link->dp_link.test_video.test_hsync_pol);
+ pr_debug("TEST_HSYNC_WIDTH = %d\n",
+ link->dp_link.test_video.test_hsync_width);
ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
- &link->request.test_vsync_pol,
- &link->request.test_vsync_width);
+ &link->dp_link.test_video.test_vsync_pol,
+ &link->dp_link.test_video.test_vsync_width);
if (ret) {
pr_err("failed to parse (DP_TEST_VSYNC_HI)\n");
goto exit;
}
- pr_debug("TEST_VSYNC_POL = %d\n", link->request.test_vsync_pol);
- pr_debug("TEST_VSYNC_WIDTH = %d\n", link->request.test_vsync_width);
+ pr_debug("TEST_VSYNC_POL = %d\n",
+ link->dp_link.test_video.test_vsync_pol);
+ pr_debug("TEST_VSYNC_WIDTH = %d\n",
+ link->dp_link.test_video.test_vsync_width);
ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
- &link->request.test_h_width);
+ &link->dp_link.test_video.test_h_width);
if (ret) {
pr_err("failed to parse test_h_width (DP_TEST_H_WIDTH_HI)\n");
goto exit;
}
- pr_debug("TEST_H_WIDTH = %d\n", link->request.test_h_width);
+ pr_debug("TEST_H_WIDTH = %d\n", link->dp_link.test_video.test_h_width);
ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
- &link->request.test_v_height);
+ &link->dp_link.test_video.test_v_height);
if (ret) {
pr_err("failed to parse test_v_height (DP_TEST_V_HEIGHT_HI)\n");
goto exit;
}
- pr_debug("TEST_V_HEIGHT = %d\n", link->request.test_v_height);
+ pr_debug("TEST_V_HEIGHT = %d\n",
+ link->dp_link.test_video.test_v_height);
ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1,
- &link->request.test_rr_d);
- link->request.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
+ &link->dp_link.test_video.test_rr_d);
+ link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
if (ret) {
pr_err("failed to parse test_rr_d (DP_TEST_MISC1)\n");
goto exit;
}
- pr_debug("TEST_REFRESH_DENOMINATOR = %d\n", link->request.test_rr_d);
+ pr_debug("TEST_REFRESH_DENOMINATOR = %d\n",
+ link->dp_link.test_video.test_rr_d);
ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
- &link->request.test_rr_n);
+ &link->dp_link.test_video.test_rr_n);
if (ret) {
pr_err("failed to parse test_rr_n (DP_TEST_REFRESH_RATE_NUMERATOR)\n");
goto exit;
}
- pr_debug("TEST_REFRESH_NUMERATOR = %d\n", link->request.test_rr_n);
+ pr_debug("TEST_REFRESH_NUMERATOR = %d\n",
+ link->dp_link.test_video.test_rr_n);
exit:
return ret;
}
@@ -720,7 +669,7 @@
return ((bw_code == DP_LINK_BW_1_62) ||
(bw_code == DP_LINK_BW_2_7) ||
(bw_code == DP_LINK_BW_5_4) ||
- (bw_code == DP_LINK_RATE_810));
+ (bw_code == DP_LINK_BW_8_1));
}
/**
@@ -832,7 +781,7 @@
data = bp;
- link->request.phy_test_pattern_sel = data;
+ link->dp_link.phy_params.phy_test_pattern_sel = data;
pr_debug("phy_test_pattern_sel = %s\n",
dp_link_get_phy_test_pattern(data));
@@ -891,6 +840,11 @@
dp_link_is_video_audio_test_requested(test_requested);
}
+static bool dp_link_is_test_edid_read(struct dp_link_private *link)
+{
+ return (link->request.test_requested == DP_TEST_LINK_EDID_READ);
+}
+
/**
* dp_sink_parse_test_request() - parses link request parameters from sink
* @link: Display Port Driver data
@@ -972,10 +926,15 @@
* Send a DP_TEST_ACK if all link parameters are valid, otherwise send
* a DP_TEST_NAK.
*/
- if (ret)
- link->request.response = DP_TEST_NAK;
- else
- link->request.response = DP_TEST_ACK;
+ if (ret) {
+ link->dp_link.test_response = DP_TEST_NAK;
+ } else {
+ if (!dp_link_is_test_edid_read(link))
+ link->dp_link.test_response = DP_TEST_ACK;
+ else
+ link->dp_link.test_response =
+ DP_TEST_EDID_CHECKSUM_WRITE;
+ }
return ret;
}
@@ -987,46 +946,49 @@
* (Byte 0x200), and whether all the sink devices connected have Content
* Protection enabled.
*/
-static void dp_link_parse_sink_count(struct dp_link_private *link)
+static int dp_link_parse_sink_count(struct dp_link *dp_link)
{
- u8 bp;
- u8 data;
int rlen;
int const param_len = 0x1;
+ struct dp_link_private *link = container_of(dp_link,
+ struct dp_link_private, dp_link);
rlen = drm_dp_dpcd_read(link->aux->drm_aux, DP_SINK_COUNT,
- &bp, param_len);
+ &link->dp_link.sink_count.count, param_len);
if (rlen < param_len) {
pr_err("failed to read sink count\n");
- return;
+ return -EINVAL;
}
- data = bp;
-
+ link->dp_link.sink_count.cp_ready =
+ link->dp_link.sink_count.count & DP_SINK_CP_READY;
/* BIT 7, BIT 5:0 */
- link->sink_count.count = (data & BIT(7)) << 6 | (data & 0x63);
- /* BIT 6*/
- link->sink_count.cp_ready = data & BIT(6);
+ link->dp_link.sink_count.count =
+ DP_GET_SINK_COUNT(link->dp_link.sink_count.count);
pr_debug("sink_count = 0x%x, cp_ready = 0x%x\n",
- link->sink_count.count, link->sink_count.cp_ready);
+ link->dp_link.sink_count.count,
+ link->dp_link.sink_count.cp_ready);
+ return 0;
}
static void dp_link_parse_sink_status_field(struct dp_link_private *link)
{
int len = 0;
- dp_link_parse_sink_count(link);
- dp_link_parse_request(link);
+ link->prev_sink_count = link->dp_link.sink_count.count;
+ dp_link_parse_sink_count(&link->dp_link);
+
len = drm_dp_dpcd_read_link_status(link->aux->drm_aux,
link->link_status);
if (len < DP_LINK_STATUS_SIZE)
pr_err("DP link status read failed\n");
+ dp_link_parse_request(link);
}
static bool dp_link_is_link_training_requested(struct dp_link_private *link)
{
- return (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN);
+ return (link->request.test_requested == DP_TEST_LINK_TRAINING);
}
/**
@@ -1046,24 +1008,34 @@
return -EINVAL;
pr_debug("%s link rate = 0x%x, lane count = 0x%x\n",
- dp_link_get_test_name(DP_TEST_LINK_PHY_TEST_PATTERN),
+ dp_link_get_test_name(DP_TEST_LINK_TRAINING),
link->request.test_link_rate,
link->request.test_lane_count);
- link->dp_link.lane_count = link->request.test_lane_count;
- link->dp_link.bw_code = link->request.test_link_rate;
+ link->dp_link.link_params.lane_count = link->request.test_lane_count;
+ link->dp_link.link_params.bw_code = link->request.test_link_rate;
return 0;
}
-static bool dp_link_phy_pattern_requested(struct dp_link *dp_link)
+static void dp_link_send_test_response(struct dp_link *dp_link)
{
- struct dp_link_private *link = container_of(dp_link,
- struct dp_link_private, dp_link);
+ struct dp_link_private *link = NULL;
+ u32 const test_response_addr = 0x260;
+ u32 const response_len = 0x1;
- return (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN);
+ if (!dp_link) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ link = container_of(dp_link, struct dp_link_private, dp_link);
+
+ drm_dp_dpcd_write(link->aux->drm_aux, test_response_addr,
+ &dp_link->test_response, response_len);
}
+
static int dp_link_parse_vx_px(struct dp_link_private *link)
{
u8 bp;
@@ -1127,10 +1099,11 @@
* vector.
*/
pr_debug("Current: v_level = 0x%x, p_level = 0x%x\n",
- link->dp_link.v_level, link->dp_link.p_level);
+ link->dp_link.phy_params.v_level,
+ link->dp_link.phy_params.p_level);
pr_debug("Requested: v_level = 0x%x, p_level = 0x%x\n", v0, p0);
- link->dp_link.v_level = v0;
- link->dp_link.p_level = p0;
+ link->dp_link.phy_params.v_level = v0;
+ link->dp_link.phy_params.p_level = p0;
pr_debug("Success\n");
end:
@@ -1150,8 +1123,10 @@
{
u32 test_link_rate = 0, test_lane_count = 0;
- if (!dp_link_phy_pattern_requested(&link->dp_link))
+ if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) {
+ pr_debug("no phy test\n");
return -EINVAL;
+ }
test_link_rate = link->request.test_link_rate;
test_lane_count = link->request.test_lane_count;
@@ -1165,8 +1140,15 @@
pr_debug("start\n");
- link->dp_link.lane_count = link->request.test_lane_count;
- link->dp_link.bw_code = link->request.test_link_rate;
+ pr_info("Current: bw_code = 0x%x, lane count = 0x%x\n",
+ link->dp_link.link_params.bw_code,
+ link->dp_link.link_params.lane_count);
+
+ pr_info("Requested: bw_code = 0x%x, lane count = 0x%x\n",
+ test_link_rate, test_lane_count);
+
+ link->dp_link.link_params.lane_count = link->request.test_lane_count;
+ link->dp_link.link_params.bw_code = link->request.test_link_rate;
dp_link_parse_vx_px(link);
@@ -1196,16 +1178,16 @@
if (!(get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) &
DP_LINK_STATUS_UPDATED) || /* link status updated */
(drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.lane_count) &&
+ link->dp_link.link_params.lane_count) &&
drm_dp_channel_eq_ok(link->link_status,
- link->dp_link.lane_count)))
+ link->dp_link.link_params.lane_count)))
return -EINVAL;
pr_debug("channel_eq_done = %d, clock_recovery_done = %d\n",
drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.lane_count),
+ link->dp_link.link_params.lane_count),
drm_dp_clock_recovery_ok(link->link_status,
- link->dp_link.lane_count));
+ link->dp_link.link_params.lane_count));
return 0;
}
@@ -1216,6 +1198,9 @@
DP_DOWNSTREAM_PORT_STATUS_CHANGED) /* port status changed */
return true;
+ if (link->prev_sink_count != link->dp_link.sink_count.count)
+ return true;
+
return false;
}
@@ -1235,6 +1220,9 @@
if (!dp_link_is_ds_port_status_changed(link))
return -EINVAL;
+ /* reset prev_sink_count */
+ link->prev_sink_count = link->dp_link.sink_count.count;
+
return 0;
}
@@ -1267,10 +1255,11 @@
pr_debug("%s: bit depth=%d(%d bpp) pattern=%s\n",
dp_link_get_test_name(DP_TEST_LINK_VIDEO_PATTERN),
- link->request.test_bit_depth,
- dp_link_bit_depth_to_bpp(link->request.test_bit_depth),
+ link->dp_link.test_video.test_bit_depth,
+ dp_link_bit_depth_to_bpp(
+ link->dp_link.test_video.test_bit_depth),
dp_link_video_pattern_to_string(
- link->request.test_video_pattern));
+ link->dp_link.test_video.test_video_pattern));
return 0;
end:
@@ -1293,22 +1282,22 @@
pr_debug("sampling_rate=%s, channel_count=%d, pattern_type=%s\n",
dp_link_get_audio_sample_rate(
- link->request.test_audio_sampling_rate),
- link->request.test_audio_channel_count,
+ link->dp_link.test_audio.test_audio_sampling_rate),
+ link->dp_link.test_audio.test_audio_channel_count,
dp_link_get_audio_test_pattern(
- link->request.test_audio_pattern_type));
+ link->dp_link.test_audio.test_audio_pattern_type));
pr_debug("audio_period: ch1=0x%x, ch2=0x%x, ch3=0x%x, ch4=0x%x\n",
- link->request.test_audio_period_ch_1,
- link->request.test_audio_period_ch_2,
- link->request.test_audio_period_ch_3,
- link->request.test_audio_period_ch_4);
+ link->dp_link.test_audio.test_audio_period_ch_1,
+ link->dp_link.test_audio.test_audio_period_ch_2,
+ link->dp_link.test_audio.test_audio_period_ch_3,
+ link->dp_link.test_audio.test_audio_period_ch_4);
pr_debug("audio_period: ch5=0x%x, ch6=0x%x, ch7=0x%x, ch8=0x%x\n",
- link->request.test_audio_period_ch_5,
- link->request.test_audio_period_ch_6,
- link->request.test_audio_period_ch_7,
- link->request.test_audio_period_ch_8);
+ link->dp_link.test_audio.test_audio_period_ch_5,
+ link->dp_link.test_audio.test_audio_period_ch_6,
+ link->dp_link.test_audio.test_audio_period_ch_7,
+ link->dp_link.test_audio.test_audio_period_ch_8);
return 0;
}
@@ -1316,8 +1305,12 @@
static void dp_link_reset_data(struct dp_link_private *link)
{
link->request = (const struct dp_link_request){ 0 };
- link->request.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
- link->dp_link.test_requested = 0;
+ link->dp_link.test_video = (const struct dp_link_test_video){ 0 };
+ link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
+ link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 };
+ link->dp_link.phy_params.phy_test_pattern_sel = 0;
+ link->dp_link.sink_request = 0;
+ link->dp_link.test_response = 0;
}
/**
@@ -1346,39 +1339,44 @@
dp_link_parse_sink_status_field(link);
- ret = dp_link_process_link_training_request(link);
- if (!ret) {
- dp_link->test_requested |= DP_TEST_LINK_TRAINING;
- goto exit;
- }
-
- ret = dp_link_process_phy_test_pattern_request(link);
- if (!ret) {
- dp_link->test_requested |= DP_TEST_LINK_PHY_TEST_PATTERN;
- goto exit;
- }
-
- ret = dp_link_process_link_status_update(link);
- if (!ret) {
- dp_link->test_requested |= DP_LINK_STATUS_UPDATED;
+ if (dp_link_is_test_edid_read(link)) {
+ dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
goto exit;
}
ret = dp_link_process_ds_port_status_change(link);
if (!ret) {
- dp_link->test_requested |= DS_PORT_STATUS_CHANGED;
+ dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
+ goto exit;
+ }
+
+ ret = dp_link_process_link_training_request(link);
+ if (!ret) {
+ dp_link->sink_request |= DP_TEST_LINK_TRAINING;
+ goto exit;
+ }
+
+ ret = dp_link_process_phy_test_pattern_request(link);
+ if (!ret) {
+ dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
+ goto exit;
+ }
+
+ ret = dp_link_process_link_status_update(link);
+ if (!ret) {
+ dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
goto exit;
}
ret = dp_link_process_video_pattern_request(link);
if (!ret) {
- dp_link->test_requested |= DP_TEST_LINK_VIDEO_PATTERN;
+ dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
goto exit;
}
ret = dp_link_process_audio_pattern_request(link);
if (!ret) {
- dp_link->test_requested |= DP_TEST_LINK_AUDIO_PATTERN;
+ dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
goto exit;
}
@@ -1402,7 +1400,7 @@
/* unless a video pattern CTS test is ongoing, use CEA_VESA */
if (dp_link_is_video_pattern_requested(link))
- dr = link->request.test_dyn_range;
+ dr = link->dp_link.test_video.test_dyn_range;
else
dr = DP_DYNAMIC_RANGE_RGB_VESA;
@@ -1434,51 +1432,52 @@
link = container_of(dp_link, struct dp_link_private, dp_link);
/* use the max level across lanes */
- for (i = 0; i < dp_link->lane_count; i++) {
+ for (i = 0; i < dp_link->link_params.lane_count; i++) {
data = drm_dp_get_adjust_request_voltage(link_status, i);
pr_debug("lane=%d req_voltage_swing=%d\n", i, data);
if (max < data)
max = data;
}
- dp_link->v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
+ dp_link->phy_params.v_level = max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
/* use the max level across lanes */
max = 0;
- for (i = 0; i < dp_link->lane_count; i++) {
+ for (i = 0; i < dp_link->link_params.lane_count; i++) {
data = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
pr_debug("lane=%d req_pre_emphasis=%d\n", i, data);
if (max < data)
max = data;
}
- dp_link->p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
+ dp_link->phy_params.p_level = max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
/**
* Adjust the voltage swing and pre-emphasis level combination to within
* the allowable range.
*/
- if (dp_link->v_level > DP_LINK_VOLTAGE_MAX) {
+ if (dp_link->phy_params.v_level > DP_LINK_VOLTAGE_MAX) {
pr_debug("Requested vSwingLevel=%d, change to %d\n",
- dp_link->v_level, DP_LINK_VOLTAGE_MAX);
- dp_link->v_level = DP_LINK_VOLTAGE_MAX;
+ dp_link->phy_params.v_level, DP_LINK_VOLTAGE_MAX);
+ dp_link->phy_params.v_level = DP_LINK_VOLTAGE_MAX;
}
- if (dp_link->p_level > DP_LINK_PRE_EMPHASIS_MAX) {
+ if (dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_MAX) {
pr_debug("Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->p_level, DP_LINK_PRE_EMPHASIS_MAX);
- dp_link->p_level = DP_LINK_PRE_EMPHASIS_MAX;
+ dp_link->phy_params.p_level, DP_LINK_PRE_EMPHASIS_MAX);
+ dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_MAX;
}
- if ((dp_link->p_level > DP_LINK_PRE_EMPHASIS_LEVEL_1)
- && (dp_link->v_level == DP_LINK_VOLTAGE_LEVEL_2)) {
+ if ((dp_link->phy_params.p_level > DP_LINK_PRE_EMPHASIS_LEVEL_1)
+ && (dp_link->phy_params.v_level == DP_LINK_VOLTAGE_LEVEL_2)) {
pr_debug("Requested preEmphasisLevel=%d, change to %d\n",
- dp_link->p_level, DP_LINK_PRE_EMPHASIS_LEVEL_1);
- dp_link->p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
+ dp_link->phy_params.p_level,
+ DP_LINK_PRE_EMPHASIS_LEVEL_1);
+ dp_link->phy_params.p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
}
pr_debug("adjusted: v_level=%d, p_level=%d\n",
- dp_link->v_level, dp_link->p_level);
+ dp_link->phy_params.v_level, dp_link->phy_params.p_level);
return 0;
}
@@ -1555,7 +1554,7 @@
dp_link->get_colorimetry_config = dp_link_get_colorimetry_config;
dp_link->adjust_levels = dp_link_adjust_levels;
dp_link->send_psm_request = dp_link_send_psm_request;
- dp_link->phy_pattern_requested = dp_link_phy_pattern_requested;
+ dp_link->send_test_response = dp_link_send_test_response;
return dp_link;
error:
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 419186f..9a5b75a 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -17,6 +17,10 @@
#include "dp_aux.h"
+#define DS_PORT_STATUS_CHANGED 0x200
+#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF
+#define DP_LINK_ENUM_STR(x) #x
+
enum dp_link_voltage_level {
DP_LINK_VOLTAGE_LEVEL_0 = 0,
DP_LINK_VOLTAGE_LEVEL_1 = 1,
@@ -31,25 +35,96 @@
DP_LINK_PRE_EMPHASIS_MAX = DP_LINK_PRE_EMPHASIS_LEVEL_2,
};
-#define DS_PORT_STATUS_CHANGED 0x200
-#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF
+struct dp_link_sink_count {
+ u32 count;
+ bool cp_ready;
+};
-struct dp_link {
- u32 test_requested;
+struct dp_link_test_video {
+ u32 test_video_pattern;
+ u32 test_bit_depth;
+ u32 test_dyn_range;
+ u32 test_h_total;
+ u32 test_v_total;
+ u32 test_h_start;
+ u32 test_v_start;
+ u32 test_hsync_pol;
+ u32 test_hsync_width;
+ u32 test_vsync_pol;
+ u32 test_vsync_width;
+ u32 test_h_width;
+ u32 test_v_height;
+ u32 test_rr_d;
+ u32 test_rr_n;
+};
+struct dp_link_test_audio {
+ u32 test_audio_sampling_rate;
+ u32 test_audio_channel_count;
+ u32 test_audio_pattern_type;
+ u32 test_audio_period_ch_1;
+ u32 test_audio_period_ch_2;
+ u32 test_audio_period_ch_3;
+ u32 test_audio_period_ch_4;
+ u32 test_audio_period_ch_5;
+ u32 test_audio_period_ch_6;
+ u32 test_audio_period_ch_7;
+ u32 test_audio_period_ch_8;
+};
+
+struct dp_link_phy_params {
+ u32 phy_test_pattern_sel;
+ u8 v_level;
+ u8 p_level;
+};
+
+struct dp_link_params {
u32 lane_count;
u32 bw_code;
- u32 v_level;
- u32 p_level;
+};
+
+struct dp_link {
+ u32 sink_request;
+ u32 test_response;
+
+ struct dp_link_sink_count sink_count;
+ struct dp_link_test_video test_video;
+ struct dp_link_test_audio test_audio;
+ struct dp_link_phy_params phy_params;
+ struct dp_link_params link_params;
u32 (*get_test_bits_depth)(struct dp_link *dp_link, u32 bpp);
int (*process_request)(struct dp_link *dp_link);
int (*get_colorimetry_config)(struct dp_link *dp_link);
int (*adjust_levels)(struct dp_link *dp_link, u8 *link_status);
int (*send_psm_request)(struct dp_link *dp_link, bool req);
- bool (*phy_pattern_requested)(struct dp_link *dp_link);
+ void (*send_test_response)(struct dp_link *dp_link);
};
+static inline char *dp_link_get_phy_test_pattern(u32 phy_test_pattern_sel)
+{
+ switch (phy_test_pattern_sel) {
+ case DP_TEST_PHY_PATTERN_NONE:
+ return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_NONE);
+ case DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING:
+ return DP_LINK_ENUM_STR(
+ DP_TEST_PHY_PATTERN_D10_2_NO_SCRAMBLING);
+ case DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT:
+ return DP_LINK_ENUM_STR(
+ DP_TEST_PHY_PATTERN_SYMBOL_ERR_MEASUREMENT_CNT);
+ case DP_TEST_PHY_PATTERN_PRBS7:
+ return DP_LINK_ENUM_STR(DP_TEST_PHY_PATTERN_PRBS7);
+ case DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN:
+ return DP_LINK_ENUM_STR(
+ DP_TEST_PHY_PATTERN_80_BIT_CUSTOM_PATTERN);
+ case DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN:
+ return DP_LINK_ENUM_STR(
+ DP_TEST_PHY_PATTERN_HBR2_CTS_EYE_PATTERN);
+ default:
+ return "unknown";
+ }
+}
+
/**
* dp_link_get() - get the functionalities of dp test module
*
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 2e21033..56b2d37 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -17,6 +17,7 @@
#include "dp_panel.h"
#define DP_PANEL_DEFAULT_BPP 24
+#define DP_MAX_DS_PORT_COUNT 1
enum {
DP_LINK_RATE_MULTIPLIER = 27000000,
@@ -27,7 +28,6 @@
struct dp_panel dp_panel;
struct dp_aux *aux;
struct dp_catalog_panel *catalog;
- bool lane_switch_supported;
bool aux_cfg_update_done;
};
@@ -36,7 +36,8 @@
int rlen, rc = 0;
struct dp_panel_private *panel;
struct drm_dp_link *link_info;
- u8 major = 0, minor = 0;
+ u8 *dpcd, major = 0, minor = 0;
+ u32 dfp_count = 0;
unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;
if (!dp_panel) {
@@ -45,11 +46,13 @@
goto end;
}
+ dpcd = dp_panel->dpcd;
+
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
link_info = &dp_panel->link_info;
rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DPCD_REV,
- dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1));
+ dpcd, (DP_RECEIVER_CAP_SIZE + 1));
if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) {
pr_err("dpcd read failed, rlen=%d\n", rlen);
rc = -EINVAL;
@@ -66,17 +69,33 @@
drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
pr_debug("link_rate=%d\n", link_info->rate);
- if (panel->lane_switch_supported)
- link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
- DP_MAX_LANE_COUNT_MASK;
- else
- link_info->num_lanes = 2;
+ link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
+ DP_MAX_LANE_COUNT_MASK;
pr_debug("lane_count=%d\n", link_info->num_lanes);
- if (dp_panel->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)
+ if (drm_dp_enhanced_frame_cap(dpcd))
link_info->capabilities |= caps;
+ dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] &
+ DP_DOWN_STREAM_PORT_COUNT;
+
+ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)
+ && (dpcd[DP_DPCD_REV] > 0x10)) {
+ rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
+ DP_DOWNSTREAM_PORT_0, dp_panel->ds_ports,
+ DP_MAX_DOWNSTREAM_PORTS);
+ if (rlen < DP_MAX_DOWNSTREAM_PORTS) {
+ pr_err("ds port status failed, rlen=%d\n", rlen);
+ rc = -EINVAL;
+ goto end;
+ }
+ }
+
+ if (dfp_count > DP_MAX_DS_PORT_COUNT)
+ pr_debug("DS port count %d greater that max (%d) supported\n",
+ dfp_count, DP_MAX_DS_PORT_COUNT);
+
end:
return rc;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index ab9a451..a94f4b8 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -18,7 +18,7 @@
#include "dp_aux.h"
#include "sde_edid_parser.h"
-#define DP_LINK_RATE_810 30 /* 8.10G = 270M * 30 */
+#define DP_MAX_DOWNSTREAM_PORTS 0x10
struct dp_panel_info {
u32 h_active;
@@ -40,8 +40,9 @@
struct dp_panel {
/* dpcd raw data */
u8 dpcd[DP_RECEIVER_CAP_SIZE];
- struct drm_dp_link link_info;
+ u8 ds_ports[DP_MAX_DOWNSTREAM_PORTS];
+ struct drm_dp_link link_info;
struct sde_edid_ctrl *edid_ctrl;
struct drm_connector *connector;
struct dp_panel_info pinfo;
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c
index c85c2a2..c8da99a 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.c
+++ b/drivers/gpu/drm/msm/dp/dp_parser.c
@@ -22,22 +22,15 @@
{
struct dp_io *io = &parser->io;
- if (&io->ctrl_io)
- msm_dss_iounmap(&io->ctrl_io);
- if (&io->phy_io)
- msm_dss_iounmap(&io->phy_io);
- if (&io->ln_tx0_io)
- msm_dss_iounmap(&io->ln_tx0_io);
- if (&io->ln_tx1_io)
- msm_dss_iounmap(&io->ln_tx0_io);
- if (&io->dp_pll_io)
- msm_dss_iounmap(&io->dp_pll_io);
- if (&io->dp_cc_io)
- msm_dss_iounmap(&io->dp_cc_io);
- if (&io->qfprom_io)
- msm_dss_iounmap(&io->qfprom_io);
- if (&io->hdcp_io)
- msm_dss_iounmap(&io->hdcp_io);
+ msm_dss_iounmap(&io->ctrl_io);
+ msm_dss_iounmap(&io->phy_io);
+ msm_dss_iounmap(&io->ln_tx0_io);
+ msm_dss_iounmap(&io->ln_tx0_io);
+ msm_dss_iounmap(&io->dp_pll_io);
+ msm_dss_iounmap(&io->dp_cc_io);
+ msm_dss_iounmap(&io->usb3_dp_com);
+ msm_dss_iounmap(&io->qfprom_io);
+ msm_dss_iounmap(&io->hdcp_io);
}
static int dp_parser_ctrl_res(struct dp_parser *parser)
@@ -84,6 +77,12 @@
goto err;
}
+ rc = msm_dss_ioremap_byname(pdev, &io->usb3_dp_com, "usb3_dp_com");
+ if (rc) {
+ pr_err("unable to remap USB3 DP com resources\n");
+ goto err;
+ }
+
if (msm_dss_ioremap_byname(pdev, &io->dp_cc_io, "dp_mmss_cc")) {
pr_err("unable to remap dp MMSS_CC resources\n");
goto err;
diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h
index 7794da5..76a72a2 100644
--- a/drivers/gpu/drm/msm/dp/dp_parser.h
+++ b/drivers/gpu/drm/msm/dp/dp_parser.h
@@ -65,6 +65,7 @@
* @dp_cc_io: DP cc's mapped memory address
* @qfprom_io: qfprom's mapped memory address
* @dp_pll_io: DP PLL mapped memory address
+ * @usb3_dp_com: USB3 DP PHY combo mapped memory address
* @hdcp_io: hdcp's mapped memory address
*/
struct dp_io {
@@ -75,6 +76,7 @@
struct dss_io_data dp_cc_io;
struct dss_io_data qfprom_io;
struct dss_io_data dp_pll_io;
+ struct dss_io_data usb3_dp_com;
struct dss_io_data hdcp_io;
};
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index 30377a0..27cf147 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -205,4 +205,14 @@
#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C)
#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020)
+/* USB3 DP COM registers */
+#define USB3_DP_COM_RESET_OVRD_CTRL (0x1C)
+#define USB3_DP_COM_PHY_MODE_CTRL (0x00)
+#define USB3_DP_COM_SW_RESET (0x04)
+#define USB3_DP_COM_TYPEC_CTRL (0x10)
+#define USB3_DP_COM_SWI_CTRL (0x0c)
+#define USB3_DP_COM_POWER_DOWN_CTRL (0x08)
+
+
+
#endif /* _DP_REG_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index bd7a66e..c0bcdda 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -377,6 +377,18 @@
pd->dp_usbpd.orientation = usbpd_get_plug_orientation(pd->pd);
+ /*
+ * By default, USB reserves two lanes for Super Speed.
+ * Which means DP has remaining two lanes to operate on.
+ * If multi-function is not supported, request USB to
+ * release the Super Speed lanes so that DP can use
+ * all four lanes in case DPCD indicates support for
+ * four lanes.
+ */
+ if (!pd->dp_usbpd.multi_func)
+ pd->svid_handler.request_usb_ss_lane(pd->pd,
+ &pd->svid_handler);
+
if (pd->dp_cb && pd->dp_cb->configure)
pd->dp_cb->configure(pd->dev);
break;
diff --git a/drivers/gpu/drm/msm/sde/sde_core_perf.c b/drivers/gpu/drm/msm/sde/sde_core_perf.c
index 7243fe2..9ddca8c 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_perf.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_perf.c
@@ -722,6 +722,12 @@
(u32 *)&catalog->perf.max_bw_low);
debugfs_create_u32("threshold_high", 0600, perf->debugfs_root,
(u32 *)&catalog->perf.max_bw_high);
+ debugfs_create_u32("min_core_ib", 0600, perf->debugfs_root,
+ (u32 *)&catalog->perf.min_core_ib);
+ debugfs_create_u32("min_llcc_ib", 0600, perf->debugfs_root,
+ (u32 *)&catalog->perf.min_llcc_ib);
+ debugfs_create_u32("min_dram_ib", 0600, perf->debugfs_root,
+ (u32 *)&catalog->perf.min_dram_ib);
debugfs_create_file("perf_mode", 0600, perf->debugfs_root,
(u32 *)perf, &sde_core_perf_mode_fops);
debugfs_create_u32("bw_vote_mode", 0600, perf->debugfs_root,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 387f08d..30cf3df 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1524,7 +1524,6 @@
static int _sde_crtc_find_plane_fb_modes(struct drm_crtc_state *state,
uint32_t *fb_ns,
uint32_t *fb_sec,
- uint32_t *fb_ns_dir,
uint32_t *fb_sec_dir)
{
struct drm_plane *plane;
@@ -1540,7 +1539,6 @@
*fb_ns = 0;
*fb_sec = 0;
- *fb_ns_dir = 0;
*fb_sec_dir = 0;
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
if (IS_ERR_OR_NULL(pstate)) {
@@ -1560,16 +1558,12 @@
case SDE_DRM_FB_SEC:
(*fb_sec)++;
break;
- case SDE_DRM_FB_NON_SEC_DIR_TRANS:
- (*fb_ns_dir)++;
- break;
case SDE_DRM_FB_SEC_DIR_TRANS:
(*fb_sec_dir)++;
break;
default:
SDE_ERROR("Error: Plane[%d], fb_trans_mode:%d",
- plane->base.id,
- mode);
+ plane->base.id, mode);
return -EINVAL;
}
}
@@ -1593,7 +1587,7 @@
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
struct sde_crtc_smmu_state_data *smmu_state;
- uint32_t translation_mode = 0;
+ uint32_t translation_mode = 0, secure_level;
int ops = 0;
bool post_commit = false;
@@ -1605,10 +1599,10 @@
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(crtc->state);
smmu_state = &sde_crtc->smmu_state;
+ secure_level = sde_crtc_get_secure_level(crtc, crtc->state);
- SDE_DEBUG("crtc%d, secure_level%d\n",
- crtc->base.id,
- sde_crtc_get_secure_level(crtc, crtc->state));
+ SDE_DEBUG("crtc%d, secure_level%d old_valid_fb%d\n",
+ crtc->base.id, secure_level, old_valid_fb);
/**
* SMMU operations need to be delayed in case of
@@ -1632,8 +1626,7 @@
PLANE_PROP_FB_TRANSLATION_MODE);
if (translation_mode > SDE_DRM_FB_SEC_DIR_TRANS) {
SDE_ERROR("crtc%d, invalid translation_mode%d\n",
- crtc->base.id,
- translation_mode);
+ crtc->base.id, translation_mode);
return -EINVAL;
}
@@ -1641,14 +1634,15 @@
* we can break if we find sec_fir or non_sec_dir
* plane
*/
- if ((translation_mode == SDE_DRM_FB_NON_SEC_DIR_TRANS) ||
- (translation_mode == SDE_DRM_FB_SEC_DIR_TRANS))
+ if (translation_mode == SDE_DRM_FB_SEC_DIR_TRANS)
break;
}
switch (translation_mode) {
- case SDE_DRM_FB_NON_SEC_DIR_TRANS:
- if (smmu_state->state == ATTACHED) {
+ case SDE_DRM_FB_SEC_DIR_TRANS:
+ /* secure display usecase */
+ if ((smmu_state->state == ATTACHED) &&
+ (secure_level == SDE_DRM_SEC_ONLY)) {
smmu_state->state = DETACH_ALL_REQ;
smmu_state->transition_type = PRE_COMMIT;
ops |= SDE_KMS_OPS_CRTC_SECURE_STATE_CHANGE;
@@ -1656,10 +1650,8 @@
ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE |
SDE_KMS_OPS_CLEANUP_PLANE_FB);
}
- }
- break;
- case SDE_DRM_FB_SEC_DIR_TRANS:
- if (smmu_state->state == ATTACHED) {
+ /* secure camera usecase */
+ } else if (smmu_state->state == ATTACHED) {
smmu_state->state = DETACH_SEC_REQ;
smmu_state->transition_type = PRE_COMMIT;
ops |= SDE_KMS_OPS_CRTC_SECURE_STATE_CHANGE;
@@ -1667,14 +1659,18 @@
break;
case SDE_DRM_FB_SEC:
case SDE_DRM_FB_NON_SEC:
- if (smmu_state->state == DETACHED_SEC) {
+ if ((smmu_state->state == DETACHED_SEC) ||
+ (smmu_state->state == DETACH_SEC_REQ)) {
smmu_state->state = ATTACH_SEC_REQ;
smmu_state->transition_type = post_commit ?
POST_COMMIT : PRE_COMMIT;
ops |= SDE_KMS_OPS_CRTC_SECURE_STATE_CHANGE;
if (translation_mode == SDE_DRM_FB_SEC)
ops |= SDE_KMS_OPS_PREPARE_PLANE_FB;
- } else if (smmu_state->state == DETACHED) {
+ if (old_valid_fb)
+ ops |= SDE_KMS_OPS_WAIT_FOR_TX_DONE;
+ } else if ((smmu_state->state == DETACHED) ||
+ (smmu_state->state == DETACH_ALL_REQ)) {
smmu_state->state = ATTACH_ALL_REQ;
smmu_state->transition_type = post_commit ?
POST_COMMIT : PRE_COMMIT;
@@ -1686,15 +1682,13 @@
}
break;
default:
- SDE_ERROR("invalid plane fb_mode:%d\n",
- translation_mode);
+ SDE_ERROR("invalid plane fb_mode:%d\n", translation_mode);
ops = 0;
return -EINVAL;
}
SDE_DEBUG("SMMU State:%d, type:%d ops:%x\n", smmu_state->state,
- smmu_state->transition_type,
- ops);
+ smmu_state->transition_type, ops);
return ops;
}
@@ -1722,13 +1716,13 @@
*/
sec_sid[0] = SEC_SID_MASK_0;
sec_sid[1] = SEC_SID_MASK_1;
- dmac_flush_range(&sec_sid, &sec_sid + num_sids);
+ dmac_flush_range(sec_sid, sec_sid + num_sids);
SDE_DEBUG("calling scm_call for vmid %d", vmid);
desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
desc.args[0] = MDP_DEVICE_ID;
- desc.args[1] = SCM_BUFFER_PHYS(&sec_sid);
+ desc.args[1] = SCM_BUFFER_PHYS(sec_sid);
desc.args[2] = sizeof(uint32_t) * num_sids;
desc.args[3] = vmid;
@@ -1736,8 +1730,7 @@
mem_protect_sd_ctrl_id), &desc);
if (ret) {
SDE_ERROR("Error:scm_call2, vmid (%lld): ret%d\n",
- desc.args[3],
- ret);
+ desc.args[3], ret);
}
kfree(sec_sid);
@@ -1780,7 +1773,6 @@
/* Bail out */
return 0;
-
/* Secure UI use case enable */
switch (smmu_state->state) {
case DETACH_ALL_REQ:
@@ -1856,11 +1848,10 @@
SDE_DEBUG("crtc: %d, old_state %d new_state %d\n", crtc->base.id,
old_smmu_state,
smmu_state->state);
- smmu_state->transition_error = false;
smmu_state->transition_type = NONE;
error:
- smmu_state->transition_error = true;
+ smmu_state->transition_error = ret ? true : false;
return ret;
}
@@ -2573,7 +2564,7 @@
* apply color processing properties only if
* smmu state is attached,
*/
- if ((smmu_state->state != DETACHED) ||
+ if ((smmu_state->state != DETACHED) &&
(smmu_state->state != DETACH_ALL_REQ))
sde_cp_crtc_apply_properties(crtc);
@@ -2814,9 +2805,11 @@
}
sde_crtc->play_count++;
- if (cstate->sbuf_cfg.rot_op_mode != SDE_CTL_ROT_OP_MODE_OFFLINE)
- drm_atomic_crtc_for_each_plane(plane, crtc)
+ if (cstate->sbuf_cfg.rot_op_mode != SDE_CTL_ROT_OP_MODE_OFFLINE) {
+ drm_atomic_crtc_for_each_plane(plane, crtc) {
sde_plane_kickoff(plane);
+ }
+ }
for (i = 0; i < sde_crtc->num_mixers; i++) {
ctl = sde_crtc->mixers[i].hw_ctl;
@@ -3416,7 +3409,7 @@
struct drm_encoder *encoder;
struct sde_crtc_state *cstate;
uint32_t secure;
- uint32_t fb_ns = 0, fb_sec = 0, fb_ns_dir = 0, fb_sec_dir = 0;
+ uint32_t fb_ns = 0, fb_sec = 0, fb_sec_dir = 0;
int encoder_cnt = 0;
int rc;
@@ -3433,26 +3426,21 @@
rc = _sde_crtc_find_plane_fb_modes(state,
&fb_ns,
&fb_sec,
- &fb_ns_dir,
&fb_sec_dir);
if (rc)
return rc;
/**
* validate planes
- * fb_ns_dir is for secure display use case,
- * fb_sec_dir is for secure camera preview use case,
+ * fb_sec_dir is for secure camera preview and secure display use case,
* fb_sec is for secure video playback,
* fb_ns is for normal non secure use cases.
*/
- if (((secure == SDE_DRM_SEC_ONLY) &&
- (fb_ns || fb_sec || fb_sec_dir)) ||
- (fb_sec && fb_sec_dir)) {
+ if ((secure == SDE_DRM_SEC_ONLY) &&
+ (fb_ns || fb_sec || (fb_sec && fb_sec_dir))) {
SDE_ERROR(
- "crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d, NS_Dir%d\n",
- crtc->base.id,
- fb_sec, fb_ns, fb_sec_dir,
- fb_ns_dir);
+ "crtc%d: invalid planes fb_modes Sec:%d, NS:%d, Sec_Dir:%d\n",
+ crtc->base.id, fb_sec, fb_ns, fb_sec_dir);
return -EINVAL;
}
@@ -3460,7 +3448,7 @@
* secure_crtc is not allowed in a shared toppolgy
* across different encoders.
*/
- if (fb_ns_dir || fb_sec_dir) {
+ if (fb_sec_dir) {
drm_for_each_encoder(encoder, crtc->dev)
if (encoder->crtc == crtc)
encoder_cnt++;
@@ -3922,6 +3910,15 @@
if (catalog->perf.max_bw_high)
sde_kms_info_add_keyint(info, "max_bandwidth_high",
catalog->perf.max_bw_high * 1000LL);
+ if (catalog->perf.min_core_ib)
+ sde_kms_info_add_keyint(info, "min_core_ib",
+ catalog->perf.min_core_ib * 1000LL);
+ if (catalog->perf.min_llcc_ib)
+ sde_kms_info_add_keyint(info, "min_llcc_ib",
+ catalog->perf.min_llcc_ib * 1000LL);
+ if (catalog->perf.min_dram_ib)
+ sde_kms_info_add_keyint(info, "min_dram_ib",
+ catalog->perf.min_dram_ib * 1000LL);
if (sde_kms->perf.max_core_clk_rate)
sde_kms_info_add_keyint(info, "max_mdp_clk",
sde_kms->perf.max_core_clk_rate);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 3e1ed7b..270e677 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -2224,11 +2224,13 @@
sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_STOP);
- if (sde_enc->cur_master) {
- sde_enc->cur_master->connector = NULL;
- sde_enc->cur_master = NULL;
+ for (i = 0; i < sde_enc->num_phys_encs; i++) {
+ if (sde_enc->phys_encs[i])
+ sde_enc->phys_encs[i]->connector = NULL;
}
+ sde_enc->cur_master = NULL;
+
SDE_DEBUG_ENC(sde_enc, "encoder disabled\n");
sde_rm_release(&sde_kms->rm, drm_enc);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index ccc4443..d3c2654 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -146,6 +146,9 @@
enum {
PERF_MAX_BW_LOW,
PERF_MAX_BW_HIGH,
+ PERF_MIN_CORE_IB,
+ PERF_MIN_LLCC_IB,
+ PERF_MIN_DRAM_IB,
PERF_CORE_IB_FF,
PERF_CORE_CLK_FF,
PERF_COMP_RATIO_RT,
@@ -376,6 +379,9 @@
static struct sde_prop_type sde_perf_prop[] = {
{PERF_MAX_BW_LOW, "qcom,sde-max-bw-low-kbps", false, PROP_TYPE_U32},
{PERF_MAX_BW_HIGH, "qcom,sde-max-bw-high-kbps", false, PROP_TYPE_U32},
+ {PERF_MIN_CORE_IB, "qcom,sde-min-core-ib-kbps", false, PROP_TYPE_U32},
+ {PERF_MIN_LLCC_IB, "qcom,sde-min-llcc-ib-kbps", false, PROP_TYPE_U32},
+ {PERF_MIN_DRAM_IB, "qcom,sde-min-dram-ib-kbps", false, PROP_TYPE_U32},
{PERF_CORE_IB_FF, "qcom,sde-core-ib-ff", false, PROP_TYPE_STRING},
{PERF_CORE_CLK_FF, "qcom,sde-core-clk-ff", false, PROP_TYPE_STRING},
{PERF_COMP_RATIO_RT, "qcom,sde-comp-ratio-rt", false,
@@ -2691,6 +2697,18 @@
prop_exists[PERF_MAX_BW_HIGH] ?
PROP_VALUE_ACCESS(prop_value, PERF_MAX_BW_HIGH, 0) :
DEFAULT_MAX_BW_HIGH;
+ cfg->perf.min_core_ib =
+ prop_exists[PERF_MIN_CORE_IB] ?
+ PROP_VALUE_ACCESS(prop_value, PERF_MIN_CORE_IB, 0) :
+ DEFAULT_MAX_BW_LOW;
+ cfg->perf.min_llcc_ib =
+ prop_exists[PERF_MIN_LLCC_IB] ?
+ PROP_VALUE_ACCESS(prop_value, PERF_MIN_LLCC_IB, 0) :
+ DEFAULT_MAX_BW_LOW;
+ cfg->perf.min_dram_ib =
+ prop_exists[PERF_MIN_DRAM_IB] ?
+ PROP_VALUE_ACCESS(prop_value, PERF_MIN_DRAM_IB, 0) :
+ DEFAULT_MAX_BW_LOW;
/*
* The following performance parameters (e.g. core_ib_ff) are
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 48c3db7..d85c8720 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -803,6 +803,10 @@
* struct sde_perf_cfg - performance control settings
* @max_bw_low low threshold of maximum bandwidth (kbps)
* @max_bw_high high threshold of maximum bandwidth (kbps)
+ * @min_core_ib minimum bandwidth for core (kbps)
+ * @min_core_ib minimum mnoc ib vote in kbps
+ * @min_llcc_ib minimum llcc ib vote in kbps
+ * @min_dram_ib minimum dram ib vote in kbps
* @core_ib_ff core instantaneous bandwidth fudge factor
* @core_clk_ff core clock fudge factor
* @comp_ratio_rt string of 0 or more of <fourcc>/<ven>/<mod>/<comp ratio>
@@ -824,6 +828,9 @@
struct sde_perf_cfg {
u32 max_bw_low;
u32 max_bw_high;
+ u32 min_core_ib;
+ u32 min_llcc_ib;
+ u32 min_dram_ib;
const char *core_ib_ff;
const char *core_clk_ff;
const char *comp_ratio_rt;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index a4564c1..e7e39d3 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -422,19 +422,19 @@
if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
return;
- if (rect_mode == SDE_SSPP_RECT_SOLO || rect_mode == SDE_SSPP_RECT_0)
- secure_bit_mask = (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF :
- 0x5;
- else
- secure_bit_mask = 0xA;
-
c = &ctx->hw;
- secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
- if (enable)
+ if (enable) {
+ if ((rect_mode == SDE_SSPP_RECT_SOLO)
+ || (rect_mode == SDE_SSPP_RECT_0))
+ secure_bit_mask =
+ (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
+ else
+ secure_bit_mask = 0xA;
+
+ secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
secure |= secure_bit_mask;
- else
- secure &= ~secure_bit_mask;
+ }
SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index a121b2e..10f796f 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -878,7 +878,6 @@
return -EINVAL;
break;
case SDE_DRM_FB_SEC_DIR_TRANS:
- case SDE_DRM_FB_NON_SEC_DIR_TRANS:
*aspace = NULL;
break;
default:
@@ -2791,6 +2790,18 @@
new_rstate = &to_sde_plane_state(new_state)->rot;
if (pstate->aspace) {
+ /*
+ * when transitioning from secure to non-secure,
+ * plane->prepare_fb happens before the commit. In such case,
+ * return early, as prepare_fb would be handled as part
+ * of the transition after attaching the domains,
+ * during the commit
+ */
+ if (!pstate->aspace->domain_attached) {
+ SDE_DEBUG_PLANE(psde,
+ "domain not attached, prepare_fb handled later\n");
+ return 0;
+ }
ret = msm_framebuffer_prepare(new_rstate->out_fb,
pstate->aspace);
if (ret) {
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d16e42d..780cefe 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2464,7 +2464,7 @@
dev_err(device->dev, " hwfault=%8.8X\n", hwfault);
- kgsl_device_snapshot(device, NULL);
+ kgsl_device_snapshot(device, NULL, adreno_gmu_gpu_fault(adreno_dev));
}
/**
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 36bd656..49dc5ed 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1329,6 +1329,10 @@
smp_wmb();
}
+static inline bool adreno_gmu_gpu_fault(struct adreno_device *adreno_dev)
+{
+ return adreno_gpu_fault(adreno_dev) & ADRENO_GMU_FAULT;
+}
/**
* adreno_clear_gpu_fault() - Clear the GPU fault register
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 5d7fb21..356d7c2 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -685,7 +685,7 @@
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
dev_err(device->dev, "CP initialization failed to idle\n");
- kgsl_device_snapshot(device, NULL);
+ kgsl_device_snapshot(device, NULL, false);
}
return ret;
@@ -1823,7 +1823,7 @@
if (ret) {
KGSL_DRV_ERR(device, "microcode bootstrap failed to idle\n");
- kgsl_device_snapshot(device, NULL);
+ kgsl_device_snapshot(device, NULL, false);
}
/* Clear the chicken bit for speed up on A430 and its derivatives */
diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c
index c807b67..0cf909e 100644
--- a/drivers/gpu/msm/adreno_a4xx.c
+++ b/drivers/gpu/msm/adreno_a4xx.c
@@ -1535,7 +1535,7 @@
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
dev_err(device->dev, "CP initialization failed to idle\n");
- kgsl_device_snapshot(device, NULL);
+ kgsl_device_snapshot(device, NULL, false);
}
return ret;
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 12824b0..b9df4ec 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1943,9 +1943,7 @@
/* If SPTP_RAC is on, turn off SPTP_RAC HS */
a6xx_sptprac_disable(adreno_dev);
- /* Disconnect GPU from BUS. Clear and reconnected after reset */
- adreno_vbif_clear_pending_transactions(device);
- /* Unnecessary: a6xx_soft_reset(adreno_dev); */
+ /* Disconnect GPU from BUS is not needed if CX GDSC goes off later */
/* Check no outstanding RPMh voting */
a6xx_complete_rpmh_votes(device);
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 25aeaef..21ecaa1 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -2046,7 +2046,7 @@
kfree(replay);
}
-static void do_header_and_snapshot(struct kgsl_device *device,
+static void do_header_and_snapshot(struct kgsl_device *device, int fault,
struct adreno_ringbuffer *rb, struct kgsl_drawobj_cmd *cmdobj)
{
struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj);
@@ -2054,7 +2054,7 @@
/* Always dump the snapshot on a non-drawobj failure */
if (cmdobj == NULL) {
adreno_fault_header(device, rb, NULL);
- kgsl_device_snapshot(device, NULL);
+ kgsl_device_snapshot(device, NULL, fault & ADRENO_GMU_FAULT);
return;
}
@@ -2066,7 +2066,7 @@
adreno_fault_header(device, rb, cmdobj);
if (!(drawobj->context->flags & KGSL_CONTEXT_NO_SNAPSHOT))
- kgsl_device_snapshot(device, drawobj->context);
+ kgsl_device_snapshot(device, NULL, fault & ADRENO_GMU_FAULT);
}
static int dispatcher_do_fault(struct adreno_device *adreno_dev)
@@ -2192,7 +2192,7 @@
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
ADRENO_REG_CP_IB1_BASE_HI, &base);
- do_header_and_snapshot(device, hung_rb, cmdobj);
+ do_header_and_snapshot(device, fault, hung_rb, cmdobj);
/* Turn off the KEEPALIVE vote from the ISR for hard fault */
if (gpudev->gpu_keepalive && fault & ADRENO_HARD_FAULT)
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 0882447..2615d44 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -533,7 +533,8 @@
drawctxt->internal_timestamp,
drawctxt->type, ret);
device->force_panic = 1;
- kgsl_device_snapshot(device, context);
+ kgsl_device_snapshot(device, context,
+ adreno_gmu_gpu_fault(adreno_dev));
}
kgsl_sharedmem_writel(device, &device->memstore,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 8b87ee2..09c1ae6 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -25,6 +25,7 @@
#include "adreno_iommu.h"
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
+#include "adreno_trace.h"
#include "a3xx_reg.h"
#include "adreno_a5xx.h"
@@ -37,6 +38,7 @@
((_rb)->buffer_desc.gpuaddr + ((_pos) * sizeof(unsigned int)))
static void adreno_get_submit_time(struct adreno_device *adreno_dev,
+ struct adreno_ringbuffer *rb,
struct adreno_submit_time *time)
{
unsigned long flags;
@@ -66,6 +68,9 @@
} else
time->ticks = 0;
+ /* Trace the GPU time to create a mapping to ftrace time */
+ trace_adreno_cmdbatch_sync(rb->drawctxt_active, time->ticks);
+
/* Get the kernel clock for time since boot */
time->ktime = local_clock();
@@ -148,7 +153,7 @@
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
if (time != NULL)
- adreno_get_submit_time(adreno_dev, time);
+ adreno_get_submit_time(adreno_dev, rb, time);
adreno_ringbuffer_wptr(adreno_dev, rb);
}
diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h
index 7bc4c93..e33060a 100644
--- a/drivers/gpu/msm/adreno_trace.h
+++ b/drivers/gpu/msm/adreno_trace.h
@@ -148,6 +148,29 @@
)
);
+TRACE_EVENT(adreno_cmdbatch_sync,
+ TP_PROTO(struct adreno_context *drawctxt,
+ uint64_t ticks),
+ TP_ARGS(drawctxt, ticks),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ __field(unsigned int, timestamp)
+ __field(uint64_t, ticks)
+ __field(int, prio)
+ ),
+ TP_fast_assign(
+ __entry->id = drawctxt->base.id;
+ __entry->timestamp = drawctxt->timestamp;
+ __entry->ticks = ticks;
+ __entry->prio = drawctxt->base.priority;
+ ),
+ TP_printk(
+ "ctx=%u ctx_prio=%d ts=%u ticks=%lld",
+ __entry->id, __entry->prio, __entry->timestamp,
+ __entry->ticks
+ )
+);
+
TRACE_EVENT(adreno_cmdbatch_fault,
TP_PROTO(struct kgsl_drawobj_cmd *cmdobj, unsigned int fault),
TP_ARGS(cmdobj, fault),
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2cc1869..f8d5f5b 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -493,7 +493,9 @@
* @work: worker to dump the frozen memory
* @dump_gate: completion gate signaled by worker when it is finished.
* @process: the process that caused the hang, if known.
- * @sysfs_read: An atomic for concurrent snapshot reads via syfs.
+ * @sysfs_read: Count of current reads via sysfs
+ * @first_read: True until the snapshot read is started
+ * @gmu_fault: Snapshot collected when GMU fault happened
*/
struct kgsl_snapshot {
uint64_t ib1base;
@@ -514,7 +516,9 @@
struct work_struct work;
struct completion dump_gate;
struct kgsl_process_private *process;
- atomic_t sysfs_read;
+ unsigned int sysfs_read;
+ bool first_read;
+ bool gmu_fault;
};
/**
@@ -700,7 +704,7 @@
int kgsl_device_snapshot_init(struct kgsl_device *device);
void kgsl_device_snapshot(struct kgsl_device *device,
- struct kgsl_context *context);
+ struct kgsl_context *context, bool gmu_fault);
void kgsl_device_snapshot_close(struct kgsl_device *device);
void kgsl_snapshot_save_frozen_objs(struct work_struct *work);
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 9b04543..3bd7cf3 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -456,11 +456,12 @@
GMU_DCVS_NOHFI, perf_idx, bw_idx);
if (ret) {
- dev_err(&gmu->pdev->dev,
+ dev_err_ratelimited(&gmu->pdev->dev,
"Failed to set GPU perf idx %d, bw idx %d\n",
perf_idx, bw_idx);
- gmu_snapshot(device);
+ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(device);
}
return ret;
@@ -1341,6 +1342,7 @@
gmu_disable_clks(gmu);
gmu_disable_gdsc(gmu);
+ dev_err(&gmu->pdev->dev, "Suspended GMU\n");
return 0;
}
@@ -1349,7 +1351,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct gmu_device *gmu = &device->gmu;
- if (!test_and_set_bit(GMU_FAULT, &gmu->flags)) {
+ if (!gmu->fault_count) {
/* Mask so there's no interrupt caused by NMI */
adreno_write_gmureg(adreno_dev,
ADRENO_REG_GMU_GMU2HOST_INTR_MASK, 0xFFFFFFFF);
@@ -1364,7 +1366,7 @@
/* Wait for the NMI to be handled */
wmb();
udelay(100);
- kgsl_device_snapshot(device, ERR_PTR(-EINVAL));
+ kgsl_device_snapshot(device, ERR_PTR(-EINVAL), true);
adreno_write_gmureg(adreno_dev,
ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF);
@@ -1372,6 +1374,8 @@
ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
(unsigned int) ~HFI_IRQ_MASK);
}
+
+ gmu->fault_count++;
}
/* To be called to power on both GPU and GMU */
@@ -1389,32 +1393,29 @@
WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags));
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
+ gmu_irq_enable(device);
/* Vote for 300MHz DDR for GMU to init */
ret = msm_bus_scale_client_update_request(gmu->pcl,
pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
- if (ret) {
+ if (ret)
dev_err(&gmu->pdev->dev,
- "Failed to allocate gmu b/w\n");
- goto error_clks;
- }
+ "Failed to allocate gmu b/w: %d\n", ret);
ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
GMU_COLD_BOOT, 0);
if (ret)
- goto error_bus;
-
- gmu_irq_enable(device);
+ goto error_gmu;
ret = hfi_start(gmu, GMU_COLD_BOOT);
if (ret)
- goto error_gpu;
+ goto error_gmu;
/* Send default DCVS level */
ret = gmu_dcvs_set(gmu, pwr->default_pwrlevel,
pwr->pwrlevels[pwr->default_pwrlevel].bus_freq);
if (ret)
- goto error_gpu;
+ goto error_gmu;
msm_bus_scale_client_update_request(gmu->pcl, 0);
break;
@@ -1423,49 +1424,49 @@
WARN_ON(test_bit(GMU_CLK_ON, &gmu->flags));
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
+ gmu_irq_enable(device);
ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
GMU_WARM_BOOT, 0);
if (ret)
- goto error_clks;
-
- gmu_irq_enable(device);
+ goto error_gmu;
ret = hfi_start(gmu, GMU_WARM_BOOT);
if (ret)
- goto error_gpu;
+ goto error_gmu;
ret = gmu_dcvs_set(gmu, gmu->wakeup_pwrlevel,
pwr->pwrlevels[gmu->wakeup_pwrlevel].bus_freq);
if (ret)
- goto error_gpu;
+ goto error_gmu;
gmu->wakeup_pwrlevel = pwr->default_pwrlevel;
break;
case KGSL_STATE_RESET:
- if (test_bit(ADRENO_DEVICE_HARD_RESET, &adreno_dev->priv)) {
+ if (test_bit(ADRENO_DEVICE_HARD_RESET, &adreno_dev->priv) ||
+ test_bit(GMU_FAULT, &gmu->flags)) {
gmu_suspend(device);
gmu_enable_gdsc(gmu);
gmu_enable_clks(gmu);
+ gmu_irq_enable(device);
ret = gpudev->rpmh_gpu_pwrctrl(
adreno_dev, GMU_FW_START, GMU_RESET, 0);
if (ret)
- goto error_clks;
+ goto error_gmu;
- gmu_irq_enable(device);
ret = hfi_start(gmu, GMU_COLD_BOOT);
if (ret)
- goto error_gpu;
+ goto error_gmu;
/* Send DCVS level prior to reset*/
ret = gmu_dcvs_set(gmu, pwr->active_pwrlevel,
pwr->pwrlevels[pwr->active_pwrlevel]
.bus_freq);
if (ret)
- goto error_gpu;
+ goto error_gmu;
ret = gpudev->oob_set(adreno_dev,
OOB_CPINIT_SET_MASK,
@@ -1485,20 +1486,8 @@
return ret;
-error_gpu:
+error_gmu:
gmu_snapshot(device);
- hfi_stop(gmu);
- gmu_irq_disable(device);
- if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
- gpudev->oob_clear(adreno_dev,
- OOB_BOOT_SLUMBER_CLEAR_MASK);
- gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
-error_bus:
- msm_bus_scale_client_update_request(gmu->pcl, 0);
-error_clks:
- gmu_snapshot(device);
- gmu_disable_clks(gmu);
- gmu_disable_gdsc(gmu);
return ret;
}
@@ -1535,18 +1524,30 @@
if (!idle || (gpudev->wait_for_gmu_idle &&
gpudev->wait_for_gmu_idle(adreno_dev))) {
dev_err(&gmu->pdev->dev, "Stopping GMU before it is idle\n");
+ idle = false;
+ set_bit(GMU_FAULT, &gmu->flags);
+ } else {
+ idle = true;
}
- /* Pending message in all queues are abandoned */
- hfi_stop(gmu);
- clear_bit(GMU_HFI_ON, &gmu->flags);
- gmu_irq_disable(device);
+ if (idle) {
+ /* Pending message in all queues are abandoned */
+ hfi_stop(gmu);
+ clear_bit(GMU_HFI_ON, &gmu->flags);
+ gmu_irq_disable(device);
- gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
- gmu_disable_clks(gmu);
- gmu_disable_gdsc(gmu);
-
- /* TODO: Vote CX, MX retention off */
+ gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
+ gmu_disable_clks(gmu);
+ gmu_disable_gdsc(gmu);
+ } else {
+ /*
+ * The power controller will change state to SLUMBER anyway
+ * Set GMU_FAULT flag to indicate to power contrller
+ * that hang recovery is needed to power on GPU
+ */
+ set_bit(GMU_FAULT, &gmu->flags);
+ gmu_snapshot(device);
+ }
msm_bus_scale_client_update_request(gmu->pcl, 0);
}
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index 63ca028..ff65f66 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -193,6 +193,7 @@
* @pcl: GPU BW scaling client
* @ccl: CNOC BW scaling client
* @idle_level: Minimal GPU idle power level
+ * @fault_count: GMU fault count
*/
struct gmu_device {
unsigned int ver;
@@ -226,6 +227,7 @@
unsigned int pcl;
unsigned int ccl;
unsigned int idle_level;
+ unsigned int fault_count;
};
bool kgsl_gmu_isenabled(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
index 685ce3e..c31a85b 100644
--- a/drivers/gpu/msm/kgsl_pool.c
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -65,19 +65,26 @@
/* Map the page into kernel and zero it out */
static void
-_kgsl_pool_zero_page(struct page *p)
+_kgsl_pool_zero_page(struct page *p, unsigned int pool_order)
{
- void *addr = kmap_atomic(p);
+ int i;
- memset(addr, 0, PAGE_SIZE);
- dmac_flush_range(addr, addr + PAGE_SIZE);
- kunmap_atomic(addr);
+ for (i = 0; i < (1 << pool_order); i++) {
+ struct page *page = nth_page(p, i);
+ void *addr = kmap_atomic(page);
+
+ memset(addr, 0, PAGE_SIZE);
+ dmac_flush_range(addr, addr + PAGE_SIZE);
+ kunmap_atomic(addr);
+ }
}
/* Add a page to specified pool */
static void
_kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p)
{
+ _kgsl_pool_zero_page(p, pool->pool_order);
+
spin_lock(&pool->list_lock);
list_add_tail(&p->lru, &pool->page_list);
pool->page_count++;
@@ -322,6 +329,7 @@
} else
return -ENOMEM;
}
+ _kgsl_pool_zero_page(page, order);
goto done;
}
@@ -341,6 +349,7 @@
page = alloc_pages(gfp_mask, order);
if (page == NULL)
return -ENOMEM;
+ _kgsl_pool_zero_page(page, order);
goto done;
}
}
@@ -370,12 +379,13 @@
} else
return -ENOMEM;
}
+
+ _kgsl_pool_zero_page(page, order);
}
done:
for (j = 0; j < (*page_size >> PAGE_SHIFT); j++) {
p = nth_page(page, j);
- _kgsl_pool_zero_page(p);
pages[pcount] = p;
pcount++;
}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6e55395..007121c 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -2629,6 +2629,7 @@
_aware(struct kgsl_device *device)
{
int status = 0;
+ struct gmu_device *gmu = &device->gmu;
switch (device->state) {
case KGSL_STATE_RESET:
@@ -2648,15 +2649,42 @@
kgsl_pwrscale_midframe_timer_cancel(device);
break;
case KGSL_STATE_SLUMBER:
+ /* if GMU already in FAULT */
+ if (kgsl_gmu_isenabled(device) &&
+ test_bit(GMU_FAULT, &gmu->flags)) {
+ status = -EINVAL;
+ break;
+ }
+
status = kgsl_pwrctrl_enable(device);
break;
default:
status = -EINVAL;
}
- if (status)
+
+ if (status) {
+ if (kgsl_gmu_isenabled(device)) {
+ /* GMU hang recovery */
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_RESET);
+ set_bit(GMU_FAULT, &gmu->flags);
+ status = kgsl_pwrctrl_enable(device);
+ if (status) {
+ /*
+ * Cannot recover GMU failure
+ * GPU will not be powered on
+ */
+ WARN_ONCE(1, "Failed to recover GMU\n");
+ }
+
+ clear_bit(GMU_FAULT, &gmu->flags);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_AWARE);
+ return status;
+ }
+
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
- else
+ } else {
kgsl_pwrctrl_set_state(device, KGSL_STATE_AWARE);
+ }
return status;
}
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index e704db7..f9494a4 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -573,16 +573,34 @@
snapshot->size += header->size;
}
+static void kgsl_free_snapshot(struct kgsl_snapshot *snapshot)
+{
+ struct kgsl_snapshot_object *obj, *tmp;
+
+ wait_for_completion(&snapshot->dump_gate);
+
+ list_for_each_entry_safe(obj, tmp,
+ &snapshot->obj_list, node)
+ kgsl_snapshot_put_object(obj);
+
+ if (snapshot->mempool)
+ vfree(snapshot->mempool);
+
+ kfree(snapshot);
+ KGSL_CORE_ERR("snapshot: objects released\n");
+}
+
/**
* kgsl_snapshot() - construct a device snapshot
* @device: device to snapshot
* @context: the context that is hung, might be NULL if unknown.
+ * @gmu_fault: whether this snapshot is triggered by a GMU fault.
*
* Given a device, construct a binary snapshot dump of the current device state
* and store it in the device snapshot memory.
*/
void kgsl_device_snapshot(struct kgsl_device *device,
- struct kgsl_context *context)
+ struct kgsl_context *context, bool gmu_fault)
{
struct kgsl_snapshot_header *header = device->snapshot_memory.ptr;
struct kgsl_snapshot *snapshot;
@@ -603,11 +621,20 @@
device->snapshot_faultcount++;
/*
- * The first hang is always the one we are interested in. Don't capture
- * a new snapshot instance if the old one hasn't been grabbed yet
+ * Overwrite a non-GMU fault snapshot if a GMU fault occurs.
*/
- if (device->snapshot != NULL)
- return;
+ if (device->snapshot != NULL) {
+ if (!gmu_fault || device->snapshot->gmu_fault)
+ return;
+
+ /*
+ * If another thread is currently reading it, that thread
+ * will free it, otherwise free it now.
+ */
+ if (!device->snapshot->sysfs_read)
+ kgsl_free_snapshot(device->snapshot);
+ device->snapshot = NULL;
+ }
/* Allocate memory for the snapshot instance */
snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
@@ -622,7 +649,9 @@
snapshot->start = device->snapshot_memory.ptr;
snapshot->ptr = device->snapshot_memory.ptr;
snapshot->remain = device->snapshot_memory.size;
- atomic_set(&snapshot->sysfs_read, 0);
+ snapshot->gmu_fault = gmu_fault;
+ snapshot->first_read = true;
+ snapshot->sysfs_read = 0;
header = (struct kgsl_snapshot_header *) snapshot->ptr;
@@ -711,6 +740,30 @@
#define kobj_to_device(a) \
container_of(a, struct kgsl_device, snapshot_kobj)
+static int snapshot_release(struct kgsl_device *device,
+ struct kgsl_snapshot *snapshot)
+{
+ bool snapshot_free = false;
+ int ret = 0;
+
+ mutex_lock(&device->mutex);
+ snapshot->sysfs_read--;
+
+ /*
+ * If someone's replaced the snapshot, return an error and free
+ * the snapshot if this is the last thread to read it.
+ */
+ if (device->snapshot != snapshot) {
+ ret = -EIO;
+ if (!snapshot->sysfs_read)
+ snapshot_free = true;
+ }
+ mutex_unlock(&device->mutex);
+ if (snapshot_free)
+ kgsl_free_snapshot(snapshot);
+ return ret;
+}
+
/* Dump the sysfs binary data to the user */
static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off,
@@ -718,20 +771,35 @@
{
struct kgsl_device *device = kobj_to_device(kobj);
struct kgsl_snapshot *snapshot;
- struct kgsl_snapshot_object *obj, *tmp;
struct kgsl_snapshot_section_header head;
struct snapshot_obj_itr itr;
- int ret;
+ int ret = 0;
if (device == NULL)
return 0;
mutex_lock(&device->mutex);
snapshot = device->snapshot;
- if (snapshot != NULL)
- atomic_inc(&snapshot->sysfs_read);
+ if (snapshot != NULL) {
+ /*
+ * If we're reading at a non-zero offset from a new snapshot,
+ * that means we want to read from the previous snapshot (which
+ * was overwritten), so return an error
+ */
+ if (snapshot->first_read) {
+ if (off)
+ ret = -EIO;
+ else
+ snapshot->first_read = false;
+ }
+ if (!ret)
+ snapshot->sysfs_read++;
+ }
mutex_unlock(&device->mutex);
+ if (ret)
+ return ret;
+
/* Return nothing if we haven't taken a snapshot yet */
if (snapshot == NULL)
return 0;
@@ -742,7 +810,7 @@
*/
ret = wait_for_completion_interruptible(&snapshot->dump_gate);
if (ret) {
- atomic_dec(&snapshot->sysfs_read);
+ snapshot_release(device, snapshot);
return ret;
}
@@ -779,29 +847,21 @@
bool snapshot_free = false;
mutex_lock(&device->mutex);
- if (atomic_dec_and_test(&snapshot->sysfs_read)) {
- device->snapshot = NULL;
+ if (--snapshot->sysfs_read == 0) {
+ if (device->snapshot == snapshot)
+ device->snapshot = NULL;
snapshot_free = true;
}
mutex_unlock(&device->mutex);
- if (snapshot_free) {
- list_for_each_entry_safe(obj, tmp,
- &snapshot->obj_list, node)
- kgsl_snapshot_put_object(obj);
-
- if (snapshot->mempool)
- vfree(snapshot->mempool);
-
- kfree(snapshot);
- KGSL_CORE_ERR("snapshot: objects released\n");
- }
+ if (snapshot_free)
+ kgsl_free_snapshot(snapshot);
return 0;
}
done:
- atomic_dec(&snapshot->sysfs_read);
- return itr.write;
+ ret = snapshot_release(device, snapshot);
+ return (ret < 0) ? ret : itr.write;
}
/* Show the total number of hangs since device boot */
@@ -872,9 +932,11 @@
/* Show the timestamp of the last collected snapshot */
static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
{
- unsigned long timestamp =
- device->snapshot ? device->snapshot->timestamp : 0;
+ unsigned long timestamp;
+ mutex_lock(&device->mutex);
+ timestamp = device->snapshot ? device->snapshot->timestamp : 0;
+ mutex_unlock(&device->mutex);
return snprintf(buf, PAGE_SIZE, "%lu\n", timestamp);
}
diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c
index b055ff6..357bfb2 100644
--- a/drivers/iio/adc/qcom-rradc.c
+++ b/drivers/iio/adc/qcom-rradc.c
@@ -180,6 +180,9 @@
#define FG_ADC_RR_VOLT_INPUT_FACTOR 8
#define FG_ADC_RR_CURR_INPUT_FACTOR 2000
#define FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL 1886
+#define FG_ADC_RR_CURR_USBIN_660_FACTOR_MIL 9
+#define FG_ADC_RR_CURR_USBIN_660_UV_VAL 579500
+
#define FG_ADC_SCALE_MILLI_FACTOR 1000
#define FG_ADC_KELVINMIL_CELSIUSMIL 273150
@@ -192,6 +195,9 @@
#define FG_RR_CONV_CONTINUOUS_TIME_MIN_US 50000
#define FG_RR_CONV_CONTINUOUS_TIME_MAX_US 51000
#define FG_RR_CONV_MAX_RETRY_CNT 50
+#define FG_RR_TP_REV_VERSION1 21
+#define FG_RR_TP_REV_VERSION2 29
+#define FG_RR_TP_REV_VERSION3 32
/*
* The channel number is not a physical index in hardware,
@@ -228,6 +234,7 @@
struct rradc_chan_prop *chan_props;
struct device_node *revid_dev_node;
struct pmic_revid_data *pmic_fab_id;
+ int volt;
};
struct rradc_channels {
@@ -353,7 +360,7 @@
return 0;
}
-static int rradc_post_process_curr(struct rradc_chip *chip,
+static int rradc_post_process_usbin_curr(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u16 adc_code,
int *result_ua)
{
@@ -361,11 +368,33 @@
if (!prop)
return -EINVAL;
-
- if (prop->channel == RR_ADC_USBIN_I)
- scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
- else
- scale = FG_ADC_RR_CURR_INPUT_FACTOR;
+ if (chip->revid_dev_node) {
+ switch (chip->pmic_fab_id->pmic_subtype) {
+ case PM660_SUBTYPE:
+ if (((chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION1)
+ && (chip->pmic_fab_id->tp_rev
+ <= FG_RR_TP_REV_VERSION2))
+ || (chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION3)) {
+ chip->volt = div64_s64(chip->volt, 1000);
+ chip->volt = chip->volt *
+ FG_ADC_RR_CURR_USBIN_660_FACTOR_MIL;
+ chip->volt = FG_ADC_RR_CURR_USBIN_660_UV_VAL -
+ (chip->volt);
+ chip->volt = div64_s64(1000000000, chip->volt);
+ scale = chip->volt;
+ } else
+ scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
+ break;
+ case PMI8998_SUBTYPE:
+ scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
+ break;
+ default:
+ pr_err("No PMIC subtype found\n");
+ return -EINVAL;
+ }
+ }
/* scale * V/A; 2.5V ADC full scale */
ua = ((int64_t)adc_code * scale);
@@ -376,6 +405,24 @@
return 0;
}
+static int rradc_post_process_dcin_curr(struct rradc_chip *chip,
+ struct rradc_chan_prop *prop, u16 adc_code,
+ int *result_ua)
+{
+ int64_t ua = 0;
+
+ if (!prop)
+ return -EINVAL;
+
+ /* 0.5 V/A; 2.5V ADC full scale */
+ ua = ((int64_t)adc_code * FG_ADC_RR_CURR_INPUT_FACTOR);
+ ua *= (FG_ADC_RR_FS_VOLTAGE_MV * FG_ADC_SCALE_MILLI_FACTOR);
+ ua = div64_s64(ua, (FG_MAX_ADC_READINGS * 1000));
+ *result_ua = ua;
+
+ return 0;
+}
+
static int rradc_post_process_die_temp(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u16 adc_code,
int *result_millidegc)
@@ -591,13 +638,13 @@
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),
FG_ADC_RR_SKIN_TEMP_LSB, FG_ADC_RR_SKIN_TEMP_MSB,
FG_ADC_RR_AUX_THERM_STS)
- RR_ADC_CHAN_CURRENT("usbin_i", &rradc_post_process_curr,
+ RR_ADC_CHAN_CURRENT("usbin_i", &rradc_post_process_usbin_curr,
FG_ADC_RR_USB_IN_I_LSB, FG_ADC_RR_USB_IN_I_MSB,
FG_ADC_RR_USB_IN_I_STS)
RR_ADC_CHAN_VOLT("usbin_v", &rradc_post_process_volt,
FG_ADC_RR_USB_IN_V_LSB, FG_ADC_RR_USB_IN_V_MSB,
FG_ADC_RR_USB_IN_V_STS)
- RR_ADC_CHAN_CURRENT("dcin_i", &rradc_post_process_curr,
+ RR_ADC_CHAN_CURRENT("dcin_i", &rradc_post_process_dcin_curr,
FG_ADC_RR_DC_IN_I_LSB, FG_ADC_RR_DC_IN_I_MSB,
FG_ADC_RR_DC_IN_I_STS)
RR_ADC_CHAN_VOLT("dcin_v", &rradc_post_process_volt,
@@ -955,6 +1002,21 @@
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ if (((chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION1)
+ && (chip->pmic_fab_id->tp_rev
+ <= FG_RR_TP_REV_VERSION2))
+ || (chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION3)) {
+ if (chan->address == RR_ADC_USBIN_I) {
+ prop = &chip->chan_props[RR_ADC_USBIN_V];
+ rc = rradc_do_conversion(chip, prop, &adc_code);
+ if (rc)
+ break;
+ prop->scale(chip, prop, adc_code, &chip->volt);
+ }
+ }
+
prop = &chip->chan_props[chan->address];
rc = rradc_do_conversion(chip, prop, &adc_code);
if (rc)
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 7a6f50b..66d1499 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -92,6 +92,7 @@
struct kobject *sysfs_kobject;
s16 ROI[MAX_ROI_SIZE];
s16 accelBuffer[MAX_ACCEL_SIZE];
+ u32 display_status;
};
static struct hbtp_data *hbtp;
@@ -1425,10 +1426,11 @@
if (ret) {
pr_err("hbtp: ret error: %zd\n", ret);
mutex_unlock(&hbtp->mutex);
- return ret;
+ return 0;
}
- if (!hbtp || !hbtp->input_dev) {
- pr_err("hbtp: hbtp or hbtp->input_dev not ready!\n");
+ hbtp->display_status = status;
+ if (!hbtp->input_dev) {
+ pr_err("hbtp: hbtp->input_dev not ready!\n");
mutex_unlock(&hbtp->mutex);
return ret;
}
@@ -1445,8 +1447,20 @@
return count;
}
+static ssize_t hbtp_display_pwr_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ mutex_lock(&hbtp->mutex);
+ ret = snprintf(buf, PAGE_SIZE, "%u\n", hbtp->display_status);
+ mutex_unlock(&hbtp->mutex);
+ return ret;
+}
+
static struct kobj_attribute hbtp_display_attribute =
- __ATTR(display_pwr, 0660, NULL, hbtp_display_pwr_store);
+ __ATTR(display_pwr, 0660, hbtp_display_pwr_show,
+ hbtp_display_pwr_store);
static int __init hbtp_init(void)
{
@@ -1463,6 +1477,7 @@
mutex_init(&hbtp->mutex);
mutex_init(&hbtp->sensormutex);
+ hbtp->display_status = 1;
error = misc_register(&hbtp_input_misc);
if (error) {
@@ -1545,6 +1560,8 @@
sysfs_remove_bin_file(sensor_kobject, &vibdata_attr);
sysfs_remove_bin_file(sensor_kobject, &capdata_attr);
kobject_put(sensor_kobject);
+ sysfs_remove_file(hbtp->sysfs_kobject, &hbtp_display_attribute.attr);
+ kobject_put(hbtp->sysfs_kobject);
misc_deregister(&hbtp_input_misc);
if (hbtp->input_dev)
input_unregister_device(hbtp->input_dev);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index a2c5579..9c0dde4 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -427,6 +427,7 @@
#define ARM_SMMU_OPT_DYNAMIC (1 << 3)
#define ARM_SMMU_OPT_3LVL_TABLES (1 << 4)
#define ARM_SMMU_OPT_NO_ASID_RETENTION (1 << 5)
+#define ARM_SMMU_OPT_DISABLE_ATOS (1 << 6)
u32 options;
enum arm_smmu_arch_version version;
enum arm_smmu_implementation model;
@@ -547,6 +548,7 @@
{ ARM_SMMU_OPT_DYNAMIC, "qcom,dynamic" },
{ ARM_SMMU_OPT_3LVL_TABLES, "qcom,use-3-lvl-tables" },
{ ARM_SMMU_OPT_NO_ASID_RETENTION, "qcom,no-asid-retention" },
+ { ARM_SMMU_OPT_DISABLE_ATOS, "qcom,disable-atos" },
{ 0, NULL},
};
@@ -2490,6 +2492,10 @@
phys_addr_t ret = 0;
unsigned long flags;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+
+ if (smmu->options & ARM_SMMU_OPT_DISABLE_ATOS)
+ return 0;
if (smmu_domain->smmu->arch_ops &&
smmu_domain->smmu->arch_ops->iova_to_phys_hard) {
@@ -3265,11 +3271,6 @@
u32 sctlr, sctlr_orig, fsr;
void __iomem *cb_base;
- if (smmu->model == QCOM_SMMUV2) {
- dev_err(smmu->dev, "ATOS support is disabled\n");
- return 0;
- }
-
ret = arm_smmu_power_on(smmu_domain->smmu->pwr);
if (ret)
return ret;
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index d92a352..da4d283 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -202,39 +202,58 @@
}
}
-static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
- dma_addr_t dma_limit)
+static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
+ size_t size, dma_addr_t dma_limit, struct device *dev)
{
struct iova_domain *iovad = cookie_iovad(domain);
unsigned long shift = iova_shift(iovad);
- unsigned long length = iova_align(iovad, size) >> shift;
+ unsigned long iova_len = size >> shift;
+ unsigned long iova = 0;
+ dma_addr_t limit;
+
+ /*
+ * Freeing non-power-of-two-sized allocations back into the IOVA caches
+ * will come back to bite us badly, so we have to waste a bit of space
+ * rounding up anything cacheable to make sure that can't happen. The
+ * order of the unadjusted size will still match upon freeing.
+ */
+ if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+ iova_len = roundup_pow_of_two(iova_len);
if (domain->geometry.force_aperture)
dma_limit = min(dma_limit, domain->geometry.aperture_end);
+
/*
- * Enforce size-alignment to be safe - there could perhaps be an
- * attribute to control this per-device, or at least per-domain...
+ * Ensure iova is within range specified in iommu_dma_init_domain().
+ * This also prevents unnecessary work iterating through the entire
+ * rb_tree.
*/
- return alloc_iova(iovad, length, dma_limit >> shift, true);
+ limit = min_t(dma_addr_t, dma_limit >> shift, iovad->dma_32bit_pfn);
+ iova = alloc_iova_fast(iovad, iova_len, limit);
+
+ return (dma_addr_t)iova << shift;
}
-/* The IOVA allocator knows what we mapped, so just unmap whatever that was */
-static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr)
+static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
+ dma_addr_t iova, size_t size)
+{
+ struct iova_domain *iovad = &cookie->iovad;
+ unsigned long shift = iova_shift(iovad);
+
+ free_iova_fast(iovad, iova >> shift, size >> shift);
+}
+
+static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr,
+ size_t size)
{
struct iova_domain *iovad = cookie_iovad(domain);
- unsigned long shift = iova_shift(iovad);
- unsigned long pfn = dma_addr >> shift;
- struct iova *iova = find_iova(iovad, pfn);
- size_t size;
+ size_t iova_off = iova_offset(iovad, dma_addr);
- if (WARN_ON(!iova))
- return;
+ dma_addr -= iova_off;
+ size = iova_align(iovad, size + iova_off);
- size = iova_size(iova) << shift;
- size -= iommu_unmap(domain, pfn << shift, size);
- /* ...and if we can't, then something is horribly, horribly wrong */
- WARN_ON(size > 0);
- __free_iova(iovad, iova);
+ WARN_ON(iommu_unmap(domain, dma_addr, size) != size);
+ iommu_dma_free_iova(domain->iova_cookie, dma_addr, size);
}
static void __iommu_dma_free_pages(struct page **pages, int count)
@@ -316,7 +335,7 @@
void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
dma_addr_t *handle)
{
- __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle);
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle, size);
__iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
*handle = DMA_ERROR_CODE;
}
@@ -344,11 +363,11 @@
void (*flush_page)(struct device *, const void *, phys_addr_t))
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
- struct iova_domain *iovad = cookie_iovad(domain);
- struct iova *iova;
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+ struct iova_domain *iovad = &cookie->iovad;
struct page **pages;
struct sg_table sgt;
- dma_addr_t dma_addr;
+ dma_addr_t iova;
unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
*handle = DMA_ERROR_CODE;
@@ -368,11 +387,11 @@
if (!pages)
return NULL;
- iova = __alloc_iova(domain, size, dev->coherent_dma_mask);
+ size = iova_align(iovad, size);
+ iova = iommu_dma_alloc_iova(domain, size, dev->coherent_dma_mask, dev);
if (!iova)
goto out_free_pages;
- size = iova_align(iovad, size);
if (sg_alloc_table_from_pages(&sgt, pages, count, 0, size, GFP_KERNEL))
goto out_free_iova;
@@ -388,19 +407,18 @@
sg_miter_stop(&miter);
}
- dma_addr = iova_dma_addr(iovad, iova);
- if (iommu_map_sg(domain, dma_addr, sgt.sgl, sgt.orig_nents, prot)
+ if (iommu_map_sg(domain, iova, sgt.sgl, sgt.orig_nents, prot)
< size)
goto out_free_sg;
- *handle = dma_addr;
+ *handle = iova;
sg_free_table(&sgt);
return pages;
out_free_sg:
sg_free_table(&sgt);
out_free_iova:
- __free_iova(iovad, iova);
+ iommu_dma_free_iova(cookie, iova, size);
out_free_pages:
__iommu_dma_free_pages(pages, count);
return NULL;
@@ -434,22 +452,22 @@
static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
size_t size, int prot)
{
- dma_addr_t dma_addr;
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
- struct iova_domain *iovad = cookie_iovad(domain);
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+ struct iova_domain *iovad = &cookie->iovad;
size_t iova_off = iova_offset(iovad, phys);
- size_t len = iova_align(iovad, size + iova_off);
- struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
+ dma_addr_t iova;
+ size = iova_align(iovad, size + iova_off);
+ iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
if (!iova)
return DMA_ERROR_CODE;
- dma_addr = iova_dma_addr(iovad, iova);
- if (iommu_map(domain, dma_addr, phys - iova_off, len, prot)) {
- __free_iova(iovad, iova);
+ if (iommu_map(domain, iova, phys - iova_off, size, prot)) {
+ iommu_dma_free_iova(cookie, iova, size);
return DMA_ERROR_CODE;
}
- return dma_addr + iova_off;
+ return iova + iova_off;
}
dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
@@ -461,7 +479,7 @@
void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir, unsigned long attrs)
{
- __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle, size);
}
/*
@@ -550,10 +568,10 @@
int nents, int prot)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
- struct iova_domain *iovad = cookie_iovad(domain);
- struct iova *iova;
+ struct iommu_dma_cookie *cookie = domain->iova_cookie;
+ struct iova_domain *iovad = &cookie->iovad;
struct scatterlist *s, *prev = NULL;
- dma_addr_t dma_addr;
+ dma_addr_t iova;
size_t iova_len = 0;
unsigned long mask = dma_get_seg_boundary(dev);
int i;
@@ -597,7 +615,7 @@
prev = s;
}
- iova = __alloc_iova(domain, iova_len, dma_get_mask(dev));
+ iova = iommu_dma_alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
if (!iova)
goto out_restore_sg;
@@ -605,14 +623,13 @@
* We'll leave any physical concatenation to the IOMMU driver's
* implementation - it knows better than we do.
*/
- dma_addr = iova_dma_addr(iovad, iova);
- if (iommu_map_sg(domain, dma_addr, sg, nents, prot) < iova_len)
+ if (iommu_map_sg(domain, iova, sg, nents, prot) < iova_len)
goto out_free_iova;
- return __finalise_sg(dev, sg, nents, dma_addr);
+ return __finalise_sg(dev, sg, nents, iova);
out_free_iova:
- __free_iova(iovad, iova);
+ iommu_dma_free_iova(cookie, iova, iova_len);
out_restore_sg:
__invalidate_sg(sg, nents);
return 0;
@@ -621,11 +638,21 @@
void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, unsigned long attrs)
{
+ dma_addr_t start, end;
+ struct scatterlist *tmp;
+ int i;
/*
* The scatterlist segments are mapped into a single
* contiguous IOVA allocation, so this is incredibly easy.
*/
- __iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
+ start = sg_dma_address(sg);
+ for_each_sg(sg_next(sg), tmp, nents - 1, i) {
+ if (sg_dma_len(tmp) == 0)
+ break;
+ sg = tmp;
+ }
+ end = sg_dma_address(sg) + sg_dma_len(sg);
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), start, end - start);
}
dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
@@ -638,7 +665,7 @@
void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir, unsigned long attrs)
{
- __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle, size);
}
int iommu_dma_supported(struct device *dev, u64 mask)
@@ -662,7 +689,7 @@
struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iommu_dma_msi_page *msi_page;
struct iova_domain *iovad = &cookie->iovad;
- struct iova *iova;
+ dma_addr_t iova;
int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
msi_addr &= ~(phys_addr_t)iova_mask(iovad);
@@ -674,12 +701,13 @@
if (!msi_page)
return NULL;
- iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev));
+ iova = iommu_dma_alloc_iova(domain, iovad->granule, dma_get_mask(dev),
+ dev);
if (!iova)
goto out_free_page;
msi_page->phys = msi_addr;
- msi_page->iova = iova_dma_addr(iovad, iova);
+ msi_page->iova = iova;
if (iommu_map(domain, msi_page->iova, msi_addr, iovad->granule, prot))
goto out_free_iova;
@@ -688,7 +716,7 @@
return msi_page;
out_free_iova:
- __free_iova(iovad, iova);
+ iommu_dma_free_iova(cookie, iova, iovad->granule);
out_free_page:
kfree(msi_page);
return NULL;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 03c5eb3..b015452 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -71,6 +71,16 @@
PACKER_FMT_MAX = 0xF,
};
+enum cam_vfe_bus_comp_grp_id {
+ CAM_VFE_BUS_COMP_GROUP_NONE = -EINVAL,
+ CAM_VFE_BUS_COMP_GROUP_ID_0 = 0x0,
+ CAM_VFE_BUS_COMP_GROUP_ID_1 = 0x1,
+ CAM_VFE_BUS_COMP_GROUP_ID_2 = 0x2,
+ CAM_VFE_BUS_COMP_GROUP_ID_3 = 0x3,
+ CAM_VFE_BUS_COMP_GROUP_ID_4 = 0x4,
+ CAM_VFE_BUS_COMP_GROUP_ID_5 = 0x5,
+};
+
struct cam_vfe_bus_ver2_common_data {
uint32_t core_index;
void __iomem *mem_base;
@@ -136,6 +146,9 @@
uint32_t intra_client_mask;
uint32_t composite_mask;
+ uint32_t acquire_dev_cnt;
+ uint32_t irq_trigger_cnt;
+
void *ctx;
};
@@ -187,6 +200,28 @@
return 0;
}
+static enum cam_vfe_bus_comp_grp_id
+ cam_vfe_bus_comp_grp_id_convert(uint32_t comp_grp)
+{
+ switch (comp_grp) {
+ case CAM_ISP_RES_COMP_GROUP_ID_0:
+ return CAM_VFE_BUS_COMP_GROUP_ID_0;
+ case CAM_ISP_RES_COMP_GROUP_ID_1:
+ return CAM_VFE_BUS_COMP_GROUP_ID_1;
+ case CAM_ISP_RES_COMP_GROUP_ID_2:
+ return CAM_VFE_BUS_COMP_GROUP_ID_2;
+ case CAM_ISP_RES_COMP_GROUP_ID_3:
+ return CAM_VFE_BUS_COMP_GROUP_ID_3;
+ case CAM_ISP_RES_COMP_GROUP_ID_4:
+ return CAM_VFE_BUS_COMP_GROUP_ID_4;
+ case CAM_ISP_RES_COMP_GROUP_ID_5:
+ return CAM_VFE_BUS_COMP_GROUP_ID_5;
+ case CAM_ISP_RES_COMP_GROUP_NONE:
+ default:
+ return CAM_VFE_BUS_COMP_GROUP_NONE;
+ }
+}
+
static int cam_vfe_bus_put_evt_payload(void *core_info,
struct cam_vfe_bus_irq_evt_payload **evt_payload)
{
@@ -1188,12 +1223,18 @@
struct cam_isp_resource_node **comp_grp)
{
int rc = 0;
+ uint32_t bus_comp_grp_id;
struct cam_isp_resource_node *comp_grp_local = NULL;
struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
- /* Check if matching comp_grp already acquired */
- cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
- out_port_info->comp_grp_id, unique_id);
+ bus_comp_grp_id = cam_vfe_bus_comp_grp_id_convert(
+ out_port_info->comp_grp_id);
+ /* Perform match only if there is valid comp grp request */
+ if (out_port_info->comp_grp_id != CAM_ISP_RES_COMP_GROUP_NONE) {
+ /* Check if matching comp_grp already acquired */
+ cam_vfe_bus_match_comp_grp(ver2_bus_priv, &comp_grp_local,
+ bus_comp_grp_id, unique_id);
+ }
if (!comp_grp_local) {
/* First find a free group */
@@ -1228,7 +1269,7 @@
rsrc_data->is_master = is_master;
rsrc_data->composite_mask = 0;
rsrc_data->unique_id = unique_id;
- rsrc_data->comp_grp_local_idx = out_port_info->comp_grp_id;
+ rsrc_data->comp_grp_local_idx = bus_comp_grp_id;
list_add_tail(&comp_grp_local->list,
&ver2_bus_priv->used_comp_grp);
@@ -1246,6 +1287,7 @@
}
rsrc_data->ctx = ctx;
+ rsrc_data->acquire_dev_cnt++;
*comp_grp = comp_grp_local;
return rc;
@@ -1260,15 +1302,21 @@
int match_found = 0;
if (!in_comp_grp) {
- CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_rsrc_data);
+ CAM_ERR(CAM_ISP, "Invalid Params Comp Grp %pK", in_comp_grp);
return -EINVAL;
}
if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE) {
- /* Already Released. Do Nothing */
+ CAM_ERR(CAM_ISP, "Already released Comp Grp");
return 0;
}
+ if (in_comp_grp->res_state == CAM_ISP_RESOURCE_STATE_STREAMING) {
+ CAM_ERR(CAM_ISP, "Invalid State %d",
+ in_comp_grp->res_state);
+ return -EBUSY;
+ }
+
in_rsrc_data = in_comp_grp->res_priv;
list_for_each_entry(comp_grp, &ver2_bus_priv->used_comp_grp, list) {
@@ -1284,23 +1332,31 @@
return -ENODEV;
}
+ in_rsrc_data->acquire_dev_cnt--;
+ if (in_rsrc_data->acquire_dev_cnt == 0) {
+ list_del(&comp_grp->list);
- list_del(&comp_grp->list);
- if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
- in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
- list_add_tail(&comp_grp->list,
- &ver2_bus_priv->free_dual_comp_grp);
- else if (in_rsrc_data->comp_grp_type >= CAM_VFE_BUS_VER2_COMP_GRP_0
- && in_rsrc_data->comp_grp_type <= CAM_VFE_BUS_VER2_COMP_GRP_5)
- list_add_tail(&comp_grp->list, &ver2_bus_priv->free_comp_grp);
+ in_rsrc_data->unique_id = 0;
+ in_rsrc_data->comp_grp_local_idx = CAM_VFE_BUS_COMP_GROUP_NONE;
+ in_rsrc_data->composite_mask = 0;
+ in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
- in_rsrc_data->unique_id = 0;
- in_rsrc_data->comp_grp_local_idx = 0;
- in_rsrc_data->composite_mask = 0;
- in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
+ comp_grp->tasklet_info = NULL;
+ comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
- comp_grp->tasklet_info = NULL;
- comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
+ if (in_rsrc_data->comp_grp_type >=
+ CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0 &&
+ in_rsrc_data->comp_grp_type <=
+ CAM_VFE_BUS_VER2_COMP_GRP_DUAL_5)
+ list_add_tail(&comp_grp->list,
+ &ver2_bus_priv->free_dual_comp_grp);
+ else if (in_rsrc_data->comp_grp_type >=
+ CAM_VFE_BUS_VER2_COMP_GRP_0 &&
+ in_rsrc_data->comp_grp_type <=
+ CAM_VFE_BUS_VER2_COMP_GRP_5)
+ list_add_tail(&comp_grp->list,
+ &ver2_bus_priv->free_comp_grp);
+ }
return 0;
}
@@ -1491,8 +1547,13 @@
/* Regular Composite SUCCESS */
if (status_reg & BIT(comp_grp_id + 5)) {
- cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
- ~BIT(comp_grp_id + 5);
+ rsrc_data->irq_trigger_cnt++;
+ if (rsrc_data->irq_trigger_cnt ==
+ rsrc_data->acquire_dev_cnt) {
+ cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0] &=
+ ~BIT(comp_grp_id + 5);
+ rsrc_data->irq_trigger_cnt = 0;
+ }
rc = CAM_VFE_IRQ_STATUS_SUCCESS;
}
@@ -1530,8 +1591,13 @@
/* DUAL Composite SUCCESS */
if (status_reg & BIT(comp_grp_id)) {
- cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
- ~BIT(comp_grp_id + 5);
+ rsrc_data->irq_trigger_cnt++;
+ if (rsrc_data->irq_trigger_cnt ==
+ rsrc_data->acquire_dev_cnt) {
+ cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2] &=
+ ~BIT(comp_grp_id + 5);
+ rsrc_data->irq_trigger_cnt = 0;
+ }
rc = CAM_VFE_IRQ_STATUS_SUCCESS;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
index b66480c..94a591c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/Makefile
@@ -6,3 +6,4 @@
obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/
obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/Makefile
new file mode 100644
index 0000000..ec1d2fd
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/Makefile
@@ -0,0 +1,9 @@
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+
+obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois_dev.o cam_ois_core.o cam_ois_soc.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
new file mode 100644
index 0000000..72cabf1
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -0,0 +1,594 @@
+/* Copyright (c) 2017, 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/firmware.h>
+#include <cam_sensor_cmn_header.h>
+#include "cam_ois_core.h"
+#include "cam_ois_soc.h"
+#include "cam_sensor_util.h"
+#include "cam_debug_util.h"
+
+/**
+ * cam_ois_get_dev_handle - get device handle
+ * @o_ctrl: ctrl structure
+ * @arg: Camera control command argument
+ *
+ * Returns success or failure
+ */
+static int cam_ois_get_dev_handle(struct cam_ois_ctrl_t *o_ctrl,
+ void *arg)
+{
+ struct cam_sensor_acquire_dev ois_acq_dev;
+ struct cam_create_dev_hdl bridge_params;
+ struct cam_control *cmd = (struct cam_control *)arg;
+
+ if (o_ctrl->bridge_intf.device_hdl != -1) {
+ CAM_ERR(CAM_OIS, "Device is already acquired");
+ return -EFAULT;
+ }
+ if (copy_from_user(&ois_acq_dev, (void __user *) cmd->handle,
+ sizeof(ois_acq_dev)))
+ return -EFAULT;
+
+ bridge_params.session_hdl = ois_acq_dev.session_handle;
+ bridge_params.ops = &o_ctrl->bridge_intf.ops;
+ bridge_params.v4l2_sub_dev_flag = 0;
+ bridge_params.media_entity_flag = 0;
+ bridge_params.priv = o_ctrl;
+
+ ois_acq_dev.device_handle =
+ cam_create_device_hdl(&bridge_params);
+ o_ctrl->bridge_intf.device_hdl = ois_acq_dev.device_handle;
+ o_ctrl->bridge_intf.session_hdl = ois_acq_dev.session_handle;
+
+ CAM_DBG(CAM_OIS, "Device Handle: %d", ois_acq_dev.device_handle);
+ if (copy_to_user((void __user *) cmd->handle, &ois_acq_dev,
+ sizeof(struct cam_sensor_acquire_dev))) {
+ CAM_ERR(CAM_OIS, "ACQUIRE_DEV: copy to user failed");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int cam_ois_vreg_control(struct cam_ois_ctrl_t *o_ctrl,
+ int config)
+{
+ int rc = 0, cnt;
+ struct cam_hw_soc_info *soc_info;
+
+ soc_info = &o_ctrl->soc_info;
+ cnt = soc_info->num_rgltr;
+
+ if (!cnt)
+ return 0;
+
+ if (cnt >= CAM_SOC_MAX_REGULATOR) {
+ CAM_ERR(CAM_OIS, "Regulators more than supported %d", cnt);
+ return -EINVAL;
+ }
+
+ if (config)
+ rc = cam_soc_util_enable_platform_resource(soc_info, false, 0,
+ false);
+ else
+ rc = cam_soc_util_disable_platform_resource(soc_info, false,
+ false);
+
+ return rc;
+}
+
+static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl)
+{
+ int rc = 0;
+ struct cam_hw_soc_info *soc_info =
+ &o_ctrl->soc_info;
+ struct msm_camera_gpio_num_info *gpio_num_info = NULL;
+
+ rc = cam_ois_vreg_control(o_ctrl, 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "OIS Reg Failed %d", rc);
+ return rc;
+ }
+
+ gpio_num_info = o_ctrl->gpio_num_info;
+
+ if (soc_info->gpio_data &&
+ gpio_num_info &&
+ gpio_num_info->valid[SENSOR_VAF] == 1) {
+ rc = cam_soc_util_request_platform_resource(&o_ctrl->soc_info,
+ NULL, NULL);
+ rc = cam_soc_util_enable_platform_resource(&o_ctrl->soc_info,
+ false, 0, false);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "Failed in req gpio: %d", rc);
+ return rc;
+ }
+
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_VAF],
+ 1);
+ }
+
+ /* VREG needs some delay to power up */
+ usleep_range(2000, 2050);
+
+ return rc;
+}
+
+static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl)
+{
+ int32_t rc = 0;
+ struct cam_hw_soc_info *soc_info =
+ &o_ctrl->soc_info;
+ struct msm_camera_gpio_num_info *gpio_num_info = NULL;
+
+ rc = cam_ois_vreg_control(o_ctrl, 0);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "Failed %d");
+ return rc;
+ }
+
+ gpio_num_info = o_ctrl->gpio_num_info;
+
+ if (soc_info->gpio_data &&
+ gpio_num_info &&
+ gpio_num_info->valid[SENSOR_VAF] == 1) {
+
+ gpio_set_value_cansleep(
+ gpio_num_info->gpio_num[SENSOR_VAF],
+ GPIOF_OUT_INIT_LOW);
+
+ rc = cam_soc_util_release_platform_resource(&o_ctrl->soc_info);
+ rc |= cam_soc_util_disable_platform_resource(&o_ctrl->soc_info,
+ 0, 0);
+ if (rc < 0)
+ CAM_ERR(CAM_OIS,
+ "Failed to disable platform resources: %d", rc);
+ }
+
+ return rc;
+}
+
+static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl,
+ struct i2c_settings_array *i2c_set)
+{
+ struct i2c_settings_list *i2c_list;
+ int32_t rc = 0;
+ uint32_t i, size;
+
+ if (o_ctrl == NULL || i2c_set == NULL) {
+ CAM_ERR(CAM_OIS, "Invalid Args");
+ return -EINVAL;
+ }
+
+ if (i2c_set->is_settings_valid != 1) {
+ CAM_ERR(CAM_OIS, " Invalid settings");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(i2c_list,
+ &(i2c_set->list_head), list) {
+ if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) {
+ rc = camera_io_dev_write(&(o_ctrl->io_master_info),
+ &(i2c_list->i2c_settings));
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS,
+ "Failed in Applying i2c wrt settings");
+ return rc;
+ }
+ } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) {
+ size = i2c_list->i2c_settings.size;
+ for (i = 0; i < size; i++) {
+ rc = camera_io_dev_poll(
+ &(o_ctrl->io_master_info),
+ i2c_list->i2c_settings.
+ reg_setting[i].reg_addr,
+ i2c_list->i2c_settings.
+ reg_setting[i].reg_data,
+ i2c_list->i2c_settings.
+ reg_setting[i].data_mask,
+ i2c_list->i2c_settings.addr_type,
+ i2c_list->i2c_settings.data_type,
+ i2c_list->i2c_settings.
+ reg_setting[i].delay);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS,
+ "i2c poll apply setting Fail");
+ return rc;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+static int cam_ois_slaveInfo_pkt_parser(struct cam_ois_ctrl_t *o_ctrl,
+ uint32_t *cmd_buf)
+{
+ int32_t rc = 0;
+ struct cam_cmd_ois_info *ois_info;
+
+ if (!o_ctrl || !cmd_buf) {
+ CAM_ERR(CAM_OIS, "Invalid Args");
+ return -EINVAL;
+ }
+
+ ois_info = (struct cam_cmd_ois_info *)cmd_buf;
+ if (o_ctrl->io_master_info.master_type == CCI_MASTER) {
+ o_ctrl->io_master_info.cci_client->i2c_freq_mode =
+ ois_info->i2c_freq_mode;
+ o_ctrl->io_master_info.cci_client->sid =
+ ois_info->slave_addr >> 1;
+ o_ctrl->ois_fw_flag = ois_info->ois_fw_flag;
+ o_ctrl->is_ois_calib = ois_info->is_ois_calib;
+ memcpy(o_ctrl->ois_name, ois_info->ois_name, 32);
+ o_ctrl->io_master_info.cci_client->retries = 3;
+ o_ctrl->io_master_info.cci_client->id_map = 0;
+ memcpy(&(o_ctrl->opcode), &(ois_info->opcode),
+ sizeof(struct cam_ois_opcode));
+ CAM_DBG(CAM_OIS, "Slave addr: 0x%x Freq Mode: %d",
+ ois_info->slave_addr, ois_info->i2c_freq_mode);
+ } else if (o_ctrl->io_master_info.master_type == I2C_MASTER) {
+ o_ctrl->io_master_info.client->addr = ois_info->slave_addr;
+ CAM_DBG(CAM_OIS, "Slave addr: 0x%x", ois_info->slave_addr);
+ } else {
+ CAM_ERR(CAM_OIS, "Invalid Master type : %d",
+ o_ctrl->io_master_info.master_type);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int cam_ois_fw_download(struct cam_ois_ctrl_t *o_ctrl)
+{
+ uint16_t total_bytes = 0;
+ uint8_t *ptr = NULL;
+ int32_t rc = 0, cnt;
+ const struct firmware *fw = NULL;
+ const char *fw_name_prog = NULL;
+ const char *fw_name_coeff = NULL;
+ char name_prog[32] = {0};
+ char name_coeff[32] = {0};
+ struct device *dev = &(o_ctrl->pdev->dev);
+ struct cam_sensor_i2c_reg_setting i2c_reg_setting;
+
+ if (!o_ctrl) {
+ CAM_ERR(CAM_OIS, "Invalid Args");
+ return -EINVAL;
+ }
+
+ snprintf(name_coeff, 32, "%s.coeff", o_ctrl->ois_name);
+
+ snprintf(name_prog, 32, "%s.prog", o_ctrl->ois_name);
+
+ /* cast pointer as const pointer*/
+ fw_name_prog = name_prog;
+ fw_name_coeff = name_coeff;
+
+ /* Load FW */
+ rc = request_firmware(&fw, fw_name_prog, dev);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_prog);
+ return rc;
+ }
+
+ total_bytes = fw->size;
+ i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
+ i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
+ i2c_reg_setting.size = total_bytes;
+ i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
+ kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
+ GFP_KERNEL);
+ if (!i2c_reg_setting.reg_setting) {
+ CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
+ cnt++, ptr++) {
+ i2c_reg_setting.reg_setting[cnt].reg_addr =
+ o_ctrl->opcode.prog;
+ i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
+ i2c_reg_setting.reg_setting[cnt].delay = 0;
+ i2c_reg_setting.reg_setting[cnt].data_mask = 0;
+ }
+
+ rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
+ &i2c_reg_setting, 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
+ goto release_firmware;
+ }
+ kfree(i2c_reg_setting.reg_setting);
+ release_firmware(fw);
+
+ rc = request_firmware(&fw, fw_name_coeff, dev);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Failed to locate %s", fw_name_coeff);
+ return rc;
+ }
+
+ total_bytes = fw->size;
+ i2c_reg_setting.addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
+ i2c_reg_setting.data_type = CAMERA_SENSOR_I2C_TYPE_BYTE;
+ i2c_reg_setting.size = total_bytes;
+ i2c_reg_setting.reg_setting = (struct cam_sensor_i2c_reg_array *)
+ kzalloc(sizeof(struct cam_sensor_i2c_reg_array) * total_bytes,
+ GFP_KERNEL);
+ if (!i2c_reg_setting.reg_setting) {
+ CAM_ERR(CAM_OIS, "Failed in allocating i2c_array");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ for (cnt = 0, ptr = (uint8_t *)fw->data; cnt < total_bytes;
+ cnt++, ptr++) {
+ i2c_reg_setting.reg_setting[cnt].reg_addr =
+ o_ctrl->opcode.coeff;
+ i2c_reg_setting.reg_setting[cnt].reg_data = *ptr;
+ i2c_reg_setting.reg_setting[cnt].delay = 0;
+ i2c_reg_setting.reg_setting[cnt].data_mask = 0;
+ }
+
+ rc = camera_io_dev_write_continuous(&(o_ctrl->io_master_info),
+ &i2c_reg_setting, 1);
+ if (rc < 0)
+ CAM_ERR(CAM_OIS, "OIS FW download failed %d", rc);
+
+release_firmware:
+ kfree(i2c_reg_setting.reg_setting);
+ release_firmware(fw);
+
+ return rc;
+}
+
+/**
+ * cam_ois_pkt_parse - Parse csl packet
+ * @o_ctrl: ctrl structure
+ * @arg: Camera control command argument
+ *
+ * Returns success or failure
+ */
+static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
+{
+ int32_t rc = 0;
+ uint64_t generic_ptr;
+ struct cam_control *ioctl_ctrl = NULL;
+ struct cam_config_dev_cmd dev_config;
+ struct i2c_settings_array *i2c_reg_settings = NULL;
+ struct cam_cmd_buf_desc *cmd_desc = NULL;
+ uint64_t generic_pkt_addr;
+ size_t pkt_len;
+ struct cam_packet *csl_packet = NULL;
+ size_t len_of_buff = 0;
+ uint32_t *offset = NULL, *cmd_buf;
+
+ ioctl_ctrl = (struct cam_control *)arg;
+ if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
+ sizeof(dev_config)))
+ return -EFAULT;
+ rc = cam_mem_get_cpu_buf(dev_config.packet_handle,
+ (uint64_t *)&generic_pkt_addr, &pkt_len);
+ if (rc) {
+ CAM_ERR(CAM_OIS,
+ "error in converting command Handle Error: %d", rc);
+ return rc;
+ }
+
+ if (dev_config.offset > pkt_len) {
+ CAM_ERR(CAM_OIS,
+ "offset is out of bound: off: %lld len: %zu",
+ dev_config.offset, pkt_len);
+ return -EINVAL;
+ }
+
+ csl_packet = (struct cam_packet *)
+ (generic_pkt_addr + dev_config.offset);
+ switch (csl_packet->header.op_code & 0xFFFFFF) {
+ case CAM_OIS_PACKET_OPCODE_INIT:
+ offset = (uint32_t *)&csl_packet->payload;
+ offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
+ cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+
+ if ((csl_packet->num_cmd_buf < 2) &&
+ (csl_packet->num_cmd_buf > 3)) {
+ CAM_ERR(CAM_OIS, "wrong cmd Buffer count: %d",
+ csl_packet->num_cmd_buf);
+ return -EINVAL;
+ }
+
+ rc = cam_mem_get_cpu_buf(cmd_desc[0].mem_handle,
+ (uint64_t *)&generic_ptr, &len_of_buff);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "Failed to get cpu buf");
+ return rc;
+ }
+
+ cmd_buf = (uint32_t *)generic_ptr;
+ cmd_buf += cmd_desc->offset / sizeof(uint32_t);
+ rc = cam_ois_slaveInfo_pkt_parser(o_ctrl, cmd_buf);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "Failed in parsing the pkt");
+ return rc;
+ }
+
+ cmd_buf += (sizeof(struct cam_cmd_i2c_info)/sizeof(uint32_t));
+
+ i2c_reg_settings = &(o_ctrl->i2c_init_data);
+ i2c_reg_settings->is_settings_valid = 1;
+ i2c_reg_settings->request_id = 0;
+ rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
+ &cmd_desc[1], 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d",
+ rc);
+ return rc;
+ }
+
+ if (o_ctrl->is_ois_calib) {
+ i2c_reg_settings = &(o_ctrl->i2c_calib_data);
+ i2c_reg_settings->is_settings_valid = 1;
+ i2c_reg_settings->request_id = 0;
+ rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
+ &cmd_desc[2], 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS,
+ "OIS pkt parsing failed: %d", rc);
+ return rc;
+ }
+ }
+ break;
+ case CAM_OIS_PACKET_OPCODE_OIS_CONTROL:
+ offset = (uint32_t *)&csl_packet->payload;
+ offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t));
+ cmd_desc = (struct cam_cmd_buf_desc *)(offset);
+ i2c_reg_settings = &(o_ctrl->i2c_mode_data);
+ i2c_reg_settings->is_settings_valid = 1;
+ i2c_reg_settings->request_id = 0;
+ rc = cam_sensor_i2c_pkt_parser(i2c_reg_settings,
+ cmd_desc, 1);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc);
+ return rc;
+ }
+
+ rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings);
+ if (rc < 0)
+ CAM_ERR(CAM_OIS, "Cannot apply mode settings");
+ break;
+ default:
+ break;
+ }
+ return rc;
+}
+
+/**
+ * cam_ois_driver_cmd - Handle ois cmds
+ * @e_ctrl: ctrl structure
+ * @arg: Camera control command argument
+ *
+ * Returns success or failure
+ */
+int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg)
+{
+ int rc = 0;
+ struct cam_ois_query_cap_t ois_cap = {0};
+ struct cam_control *cmd = (struct cam_control *)arg;
+
+ if (!o_ctrl) {
+ CAM_ERR(CAM_OIS, "e_ctrl is NULL");
+ return -EINVAL;
+ }
+
+ mutex_lock(&(o_ctrl->ois_mutex));
+ switch (cmd->op_code) {
+ case CAM_QUERY_CAP:
+ ois_cap.slot_info = o_ctrl->subdev_id;
+
+ if (copy_to_user((void __user *) cmd->handle,
+ &ois_cap,
+ sizeof(struct cam_ois_query_cap_t))) {
+ CAM_ERR(CAM_OIS, "Failed Copy to User");
+ return -EFAULT;
+ goto release_mutex;
+ }
+ CAM_DBG(CAM_OIS, "ois_cap: ID: %d", ois_cap.slot_info);
+ break;
+ case CAM_ACQUIRE_DEV:
+ rc = cam_ois_get_dev_handle(o_ctrl, arg);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Failed to acquire dev");
+ goto release_mutex;
+ }
+ break;
+ case CAM_START_DEV:
+ rc = cam_ois_power_up(o_ctrl);
+ if (rc) {
+ CAM_ERR(CAM_OIS, " OIS Power up failed");
+ goto release_mutex;
+ }
+ rc = camera_io_init(&o_ctrl->io_master_info);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "cci_init failed");
+ goto pwr_dwn;
+ }
+
+ if (o_ctrl->ois_fw_flag) {
+ rc = cam_ois_fw_download(o_ctrl);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Failed OIS FW Download");
+ goto pwr_dwn;
+ }
+ }
+
+ rc = cam_ois_apply_settings(o_ctrl, &o_ctrl->i2c_init_data);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "Cannot apply Init settings");
+ goto pwr_dwn;
+ }
+
+ if (o_ctrl->is_ois_calib) {
+ rc = cam_ois_apply_settings(o_ctrl,
+ &o_ctrl->i2c_calib_data);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Cannot apply calib data");
+ goto pwr_dwn;
+ }
+ }
+ break;
+ case CAM_CONFIG_DEV:
+ rc = cam_ois_pkt_parse(o_ctrl, arg);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "Failed in ois pkt Parsing");
+ goto release_mutex;
+ }
+ break;
+ case CAM_RELEASE_DEV:
+ if (o_ctrl->bridge_intf.device_hdl == -1) {
+ CAM_ERR(CAM_OIS, "link hdl: %d device hdl: %d",
+ o_ctrl->bridge_intf.device_hdl,
+ o_ctrl->bridge_intf.link_hdl);
+ rc = -EINVAL;
+ goto release_mutex;
+ }
+ rc = cam_destroy_device_hdl(o_ctrl->bridge_intf.device_hdl);
+ if (rc < 0)
+ CAM_ERR(CAM_OIS, "destroying the device hdl");
+ o_ctrl->bridge_intf.device_hdl = -1;
+ o_ctrl->bridge_intf.link_hdl = -1;
+ o_ctrl->bridge_intf.session_hdl = -1;
+ break;
+ case CAM_STOP_DEV:
+ rc = camera_io_release(&o_ctrl->io_master_info);
+ if (rc < 0)
+ CAM_ERR(CAM_OIS, "Failed in releasing CCI");
+ rc = cam_ois_power_down(o_ctrl);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "OIS Power down failed");
+ goto release_mutex;
+ }
+ break;
+ default:
+ CAM_ERR(CAM_OIS, "invalid opcode");
+ goto release_mutex;
+ }
+pwr_dwn:
+ cam_ois_power_down(o_ctrl);
+release_mutex:
+ mutex_unlock(&(o_ctrl->ois_mutex));
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h
new file mode 100644
index 0000000..13da82a
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2017, 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.
+ */
+#ifndef _CAM_OIS_CORE_H_
+#define _CAM_OIS_CORE_H_
+
+#include "cam_ois_dev.h"
+
+int cam_ois_driver_cmd(struct cam_ois_ctrl_t *e_ctrl, void *arg);
+
+#endif
+/* _CAM_OIS_CORE_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
new file mode 100644
index 0000000..aeab388
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
@@ -0,0 +1,362 @@
+/* Copyright (c) 2017, 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 "cam_ois_dev.h"
+#include "cam_req_mgr_dev.h"
+#include "cam_ois_soc.h"
+#include "cam_ois_core.h"
+#include "cam_debug_util.h"
+
+static long cam_ois_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ int rc = 0;
+ struct cam_ois_ctrl_t *o_ctrl = v4l2_get_subdevdata(sd);
+
+ switch (cmd) {
+ case VIDIOC_CAM_CONTROL:
+ rc = cam_ois_driver_cmd(o_ctrl, arg);
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+
+ return rc;
+}
+
+static int32_t cam_ois_update_i2c_info(struct cam_ois_ctrl_t *o_ctrl,
+ struct cam_ois_i2c_info_t *i2c_info)
+{
+ struct cam_sensor_cci_client *cci_client = NULL;
+
+ if (o_ctrl->io_master_info.master_type == CCI_MASTER) {
+ cci_client = o_ctrl->io_master_info.cci_client;
+ if (!cci_client) {
+ CAM_ERR(CAM_OIS, "failed: cci_client %pK",
+ cci_client);
+ return -EINVAL;
+ }
+ cci_client->cci_i2c_master = o_ctrl->cci_i2c_master;
+ cci_client->sid = (i2c_info->slave_addr) >> 1;
+ cci_client->retries = 3;
+ cci_client->id_map = 0;
+ cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long cam_ois_init_subdev_do_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, unsigned long arg)
+{
+ struct cam_control cmd_data;
+ int32_t rc = 0;
+
+ if (copy_from_user(&cmd_data, (void __user *)arg,
+ sizeof(cmd_data))) {
+ CAM_ERR(CAM_OIS,
+ "Failed to copy from user_ptr=%pK size=%zu",
+ (void __user *)arg, sizeof(cmd_data));
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case VIDIOC_CAM_CONTROL:
+ rc = cam_ois_subdev_ioctl(sd, cmd, &cmd_data);
+ if (rc) {
+ CAM_ERR(CAM_OIS,
+ "Failed in ois suddev handling rc %d",
+ rc);
+ return rc;
+ }
+ break;
+ default:
+ CAM_ERR(CAM_OIS, "Invalid compat ioctl: %d", cmd);
+ rc = -EINVAL;
+ }
+
+ if (!rc) {
+ if (copy_to_user((void __user *)arg, &cmd_data,
+ sizeof(cmd_data))) {
+ CAM_ERR(CAM_OIS,
+ "Failed to copy from user_ptr=%pK size=%zu",
+ (void __user *)arg, sizeof(cmd_data));
+ rc = -EFAULT;
+ }
+ }
+ return rc;
+}
+#endif
+
+static const struct v4l2_subdev_internal_ops cam_ois_internal_ops;
+
+static struct v4l2_subdev_core_ops cam_ois_subdev_core_ops = {
+ .ioctl = cam_ois_subdev_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = cam_ois_init_subdev_do_ioctl,
+#endif
+};
+
+static struct v4l2_subdev_ops cam_ois_subdev_ops = {
+ .core = &cam_ois_subdev_core_ops,
+};
+
+static int cam_ois_init_subdev_param(struct cam_ois_ctrl_t *o_ctrl)
+{
+ int rc = 0;
+
+ o_ctrl->v4l2_dev_str.internal_ops = &cam_ois_internal_ops;
+ o_ctrl->v4l2_dev_str.ops = &cam_ois_subdev_ops;
+ strlcpy(o_ctrl->device_name, CAM_OIS_NAME,
+ sizeof(o_ctrl->device_name));
+ o_ctrl->v4l2_dev_str.name = o_ctrl->device_name;
+ o_ctrl->v4l2_dev_str.sd_flags =
+ (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
+ o_ctrl->v4l2_dev_str.ent_function = CAM_OIS_DEVICE_TYPE;
+ o_ctrl->v4l2_dev_str.token = o_ctrl;
+
+ rc = cam_register_subdev(&(o_ctrl->v4l2_dev_str));
+ if (rc)
+ CAM_ERR(CAM_OIS, "fail to create subdev");
+
+ return rc;
+}
+
+static int cam_ois_i2c_driver_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct cam_ois_ctrl_t *o_ctrl = NULL;
+ struct cam_ois_soc_private *soc_private = NULL;
+
+ if (client == NULL || id == NULL) {
+ CAM_ERR(CAM_OIS, "Invalid Args client: %pK id: %pK",
+ client, id);
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ CAM_ERR(CAM_OIS, "i2c_check_functionality failed");
+ goto probe_failure;
+ }
+
+ o_ctrl = kzalloc(sizeof(*o_ctrl), GFP_KERNEL);
+ if (!o_ctrl) {
+ CAM_ERR(CAM_OIS, "kzalloc failed");
+ rc = -ENOMEM;
+ goto probe_failure;
+ }
+
+ i2c_set_clientdata(client, o_ctrl);
+
+ o_ctrl->soc_info.dev = &client->dev;
+ o_ctrl->soc_info.dev_name = client->name;
+ o_ctrl->ois_device_type = MSM_CAMERA_I2C_DEVICE;
+ o_ctrl->io_master_info.master_type = I2C_MASTER;
+ o_ctrl->io_master_info.client = client;
+
+ soc_private = kzalloc(sizeof(struct cam_ois_soc_private),
+ GFP_KERNEL);
+ if (!soc_private) {
+ rc = -ENOMEM;
+ goto octrl_free;
+ }
+
+ o_ctrl->soc_info.soc_private = soc_private;
+ rc = cam_ois_driver_soc_init(o_ctrl);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "failed: cam_sensor_parse_dt rc %d", rc);
+ goto octrl_free;
+ }
+
+ rc = cam_ois_init_subdev_param(o_ctrl);
+ if (rc)
+ goto octrl_free;
+
+ return rc;
+
+octrl_free:
+ kfree(o_ctrl);
+probe_failure:
+ return rc;
+}
+
+static int cam_ois_i2c_driver_remove(struct i2c_client *client)
+{
+ struct cam_ois_ctrl_t *o_ctrl = i2c_get_clientdata(client);
+
+ if (!o_ctrl) {
+ CAM_ERR(CAM_OIS, "ois device is NULL");
+ return -EINVAL;
+ }
+
+ kfree(o_ctrl->soc_info.soc_private);
+ kfree(o_ctrl);
+
+ return 0;
+}
+
+static int32_t cam_ois_platform_driver_probe(
+ struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ struct cam_ois_ctrl_t *o_ctrl = NULL;
+ struct cam_ois_soc_private *soc_private = NULL;
+
+ o_ctrl = kzalloc(sizeof(struct cam_ois_ctrl_t), GFP_KERNEL);
+ if (!o_ctrl)
+ return -ENOMEM;
+
+ o_ctrl->soc_info.pdev = pdev;
+ o_ctrl->soc_info.dev = &pdev->dev;
+ o_ctrl->soc_info.dev_name = pdev->name;
+
+ o_ctrl->ois_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+
+ o_ctrl->io_master_info.master_type = CCI_MASTER;
+ o_ctrl->io_master_info.cci_client = kzalloc(
+ sizeof(struct cam_sensor_cci_client), GFP_KERNEL);
+ if (!o_ctrl->io_master_info.cci_client)
+ goto free_o_ctrl;
+
+ soc_private = kzalloc(sizeof(struct cam_ois_soc_private),
+ GFP_KERNEL);
+ if (!soc_private) {
+ rc = -ENOMEM;
+ goto free_cci_client;
+ }
+ o_ctrl->soc_info.soc_private = soc_private;
+
+ INIT_LIST_HEAD(&(o_ctrl->i2c_init_data.list_head));
+ INIT_LIST_HEAD(&(o_ctrl->i2c_calib_data.list_head));
+ INIT_LIST_HEAD(&(o_ctrl->i2c_mode_data.list_head));
+ mutex_init(&(o_ctrl->ois_mutex));
+ rc = cam_ois_driver_soc_init(o_ctrl);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "failed: soc init rc %d", rc);
+ goto free_soc;
+ }
+
+ rc = cam_ois_init_subdev_param(o_ctrl);
+ if (rc)
+ goto free_soc;
+
+ rc = cam_ois_update_i2c_info(o_ctrl, &soc_private->i2c_info);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "failed: to update i2c info rc %d", rc);
+ goto unreg_subdev;
+ }
+ o_ctrl->bridge_intf.device_hdl = -1;
+
+ platform_set_drvdata(pdev, o_ctrl);
+ v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, o_ctrl);
+
+ return rc;
+unreg_subdev:
+ cam_unregister_subdev(&(o_ctrl->v4l2_dev_str));
+free_soc:
+ kfree(soc_private);
+free_cci_client:
+ kfree(o_ctrl->io_master_info.cci_client);
+free_o_ctrl:
+ kfree(o_ctrl);
+ return rc;
+}
+
+static int cam_ois_platform_driver_remove(struct platform_device *pdev)
+{
+ struct cam_ois_ctrl_t *o_ctrl;
+
+ o_ctrl = platform_get_drvdata(pdev);
+ if (!o_ctrl) {
+ CAM_ERR(CAM_OIS, "ois device is NULL");
+ return -EINVAL;
+ }
+
+ kfree(o_ctrl->soc_info.soc_private);
+ kfree(o_ctrl->io_master_info.cci_client);
+ kfree(o_ctrl);
+ return 0;
+}
+
+static const struct of_device_id cam_ois_dt_match[] = {
+ { .compatible = "qcom,ois" },
+ { }
+};
+
+
+MODULE_DEVICE_TABLE(of, cam_ois_dt_match);
+
+static struct platform_driver cam_ois_platform_driver = {
+ .driver = {
+ .name = "qcom,ois",
+ .owner = THIS_MODULE,
+ .of_match_table = cam_ois_dt_match,
+ },
+ .probe = cam_ois_platform_driver_probe,
+ .remove = cam_ois_platform_driver_remove,
+};
+static const struct i2c_device_id cam_ois_i2c_id[] = {
+ { "msm_ois", (kernel_ulong_t)NULL},
+ { }
+};
+
+static struct i2c_driver cam_ois_i2c_driver = {
+ .id_table = cam_ois_i2c_id,
+ .probe = cam_ois_i2c_driver_probe,
+ .remove = cam_ois_i2c_driver_remove,
+ .driver = {
+ .name = "msm_ois",
+ },
+};
+
+static struct cam_ois_registered_driver_t registered_driver = {
+ 0, 0};
+
+static int __init cam_ois_driver_init(void)
+{
+ int rc = 0;
+
+ rc = platform_driver_register(&cam_ois_platform_driver);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "platform_driver_register failed rc = %d",
+ rc);
+ return rc;
+ }
+
+ registered_driver.platform_driver = 1;
+
+ rc = i2c_add_driver(&cam_ois_i2c_driver);
+ if (rc) {
+ CAM_ERR(CAM_OIS, "i2c_add_driver failed rc = %d", rc);
+ return rc;
+ }
+
+ registered_driver.i2c_driver = 1;
+ return rc;
+}
+
+static void __exit cam_ois_driver_exit(void)
+{
+ if (registered_driver.platform_driver)
+ platform_driver_unregister(&cam_ois_platform_driver);
+
+ if (registered_driver.i2c_driver)
+ i2c_del_driver(&cam_ois_i2c_driver);
+}
+
+module_init(cam_ois_driver_init);
+module_exit(cam_ois_driver_exit);
+MODULE_DESCRIPTION("CAM OIS driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h
new file mode 100644
index 0000000..95ebed1
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2017, 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.
+ */
+#ifndef _CAM_OIS_DEV_H_
+#define _CAM_OIS_DEV_H_
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/cam_sensor.h>
+#include <cam_sensor_i2c.h>
+#include <cam_sensor_spi.h>
+#include <cam_sensor_io.h>
+#include <cam_cci_dev.h>
+#include <cam_req_mgr_util.h>
+#include <cam_req_mgr_interface.h>
+#include <cam_mem_mgr.h>
+#include <cam_subdev.h>
+#include "cam_soc_util.h"
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+/**
+ * struct cam_ois_registered_driver_t - registered driver info
+ * @platform_driver : flag indicates if platform driver is registered
+ * @i2c_driver : flag indicates if i2c driver is registered
+ *
+ */
+struct cam_ois_registered_driver_t {
+ bool platform_driver;
+ bool i2c_driver;
+};
+
+/**
+ * struct cam_ois_i2c_info_t - I2C info
+ * @slave_addr : slave address
+ * @i2c_freq_mode : i2c frequency mode
+ *
+ */
+struct cam_ois_i2c_info_t {
+ uint16_t slave_addr;
+ uint8_t i2c_freq_mode;
+};
+
+/**
+ * struct cam_ois_soc_private - ois soc private data structure
+ * @ois_name : ois name
+ * @i2c_info : i2c info structure
+ * @power_info : ois power info
+ *
+ */
+struct cam_ois_soc_private {
+ const char *ois_name;
+ struct cam_ois_i2c_info_t i2c_info;
+ struct cam_sensor_power_ctrl_t power_info;
+};
+
+/**
+ * struct cam_ois_intf_params - bridge interface params
+ * @device_hdl : Device Handle
+ * @session_hdl : Session Handle
+ * @ops : KMD operations
+ * @crm_cb : Callback API pointers
+ */
+struct cam_ois_intf_params {
+ int32_t device_hdl;
+ int32_t session_hdl;
+ int32_t link_hdl;
+ struct cam_req_mgr_kmd_ops ops;
+ struct cam_req_mgr_crm_cb *crm_cb;
+};
+
+/**
+ * struct cam_ois_ctrl_t - OIS ctrl private data
+ * @pdev : platform device
+ * @ois_mutex : ois mutex
+ * @soc_info : ois soc related info
+ * @io_master_info : Information about the communication master
+ * @gpio_num_info : gpio info
+ * @cci_i2c_master : I2C structure
+ * @v4l2_dev_str : V4L2 device structure
+ * @bridge_intf : bridge interface params
+ * @i2c_init_data : ois i2c init settings
+ * @i2c_mode_data : ois i2c mode settings
+ * @i2c_calib_data : ois i2c calib settings
+ * @ois_device_type : ois device type
+ * @subdev_id : subdev id
+ * @ois_name : ois name
+ * @ois_fw_flag : flag for firmware download
+ * @is_ois_calib : flag for Calibration data
+ * @opcode : ois opcode
+ * @device_name : Device name
+ *
+ */
+struct cam_ois_ctrl_t {
+ struct platform_device *pdev;
+ struct mutex ois_mutex;
+ struct cam_hw_soc_info soc_info;
+ struct camera_io_master io_master_info;
+ struct msm_camera_gpio_num_info *gpio_num_info;
+ enum cci_i2c_master_t cci_i2c_master;
+ struct cam_subdev v4l2_dev_str;
+ struct cam_ois_intf_params bridge_intf;
+ struct i2c_settings_array i2c_init_data;
+ struct i2c_settings_array i2c_calib_data;
+ struct i2c_settings_array i2c_mode_data;
+ enum msm_camera_device_type_t ois_device_type;
+ uint32_t subdev_id;
+ char device_name[20];
+ char ois_name[32];
+ uint8_t ois_fw_flag;
+ uint8_t is_ois_calib;
+ struct cam_ois_opcode opcode;
+};
+
+#endif /*_CAM_OIS_DEV_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.c
new file mode 100644
index 0000000..916e699
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.c
@@ -0,0 +1,114 @@
+/* Copyright (c) 2017, 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/of.h>
+#include <linux/of_gpio.h>
+#include <cam_sensor_cmn_header.h>
+#include <cam_sensor_util.h>
+#include <cam_sensor_io.h>
+#include <cam_req_mgr_util.h>
+
+#include "cam_ois_soc.h"
+#include "cam_debug_util.h"
+
+/**
+ * @e_ctrl: ctrl structure
+ *
+ * Parses ois dt
+ */
+static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl)
+{
+ int rc = 0;
+ struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info;
+ struct cam_ois_soc_private *soc_private =
+ (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
+ struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
+ struct device_node *of_node = NULL;
+
+ of_node = soc_info->dev->of_node;
+
+ if (!of_node) {
+ CAM_ERR(CAM_OIS, "of_node is NULL, device type %d",
+ o_ctrl->ois_device_type);
+ return -EINVAL;
+ }
+ rc = cam_soc_util_get_dt_properties(soc_info);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "cam_soc_util_get_dt_properties rc %d",
+ rc);
+ return rc;
+ }
+
+ if (!soc_info->gpio_data) {
+ CAM_INFO(CAM_OIS, "No GPIO found");
+ return 0;
+ }
+
+ if (!soc_info->gpio_data->cam_gpio_common_tbl_size) {
+ CAM_INFO(CAM_OIS, "No GPIO found");
+ return -EINVAL;
+ }
+
+ rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
+ &power_info->gpio_num_info);
+ if ((rc < 0) || (!power_info->gpio_num_info)) {
+ CAM_ERR(CAM_OIS, "No/Error OIS GPIOs");
+ return -EINVAL;
+ }
+
+ return rc;
+}
+/**
+ * @o_ctrl: ctrl structure
+ *
+ * This function is called from cam_ois_platform/i2c_driver_probe, it parses
+ * the ois dt node.
+ */
+int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl)
+{
+ int rc = 0;
+ struct cam_hw_soc_info *soc_info = &o_ctrl->soc_info;
+ struct device_node *of_node = NULL;
+
+ if (!soc_info->dev) {
+ CAM_ERR(CAM_OIS, "soc_info is not initialized");
+ return -EINVAL;
+ }
+
+ of_node = soc_info->dev->of_node;
+ if (!of_node) {
+ CAM_ERR(CAM_OIS, "dev.of_node NULL");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(of_node, "cell-index",
+ &o_ctrl->subdev_id);
+ if (rc < 0) {
+ CAM_ERR(CAM_OIS, "failed rc %d", rc);
+ return rc;
+ }
+
+ if (o_ctrl->ois_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = of_property_read_u32(of_node, "cci-master",
+ &o_ctrl->cci_i2c_master);
+ if (rc < 0) {
+ CAM_DBG(CAM_OIS, "failed rc %d", rc);
+ return rc;
+ }
+ }
+
+ rc = cam_ois_get_dt_data(o_ctrl);
+ if (rc < 0)
+ CAM_DBG(CAM_OIS, "failed: ois get dt data rc %d", rc);
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.h
new file mode 100644
index 0000000..af04134
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_soc.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2017, 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.
+ */
+#ifndef _CAM_OIS_SOC_H_
+#define _CAM_OIS_SOC_H_
+
+#include "cam_ois_dev.h"
+
+int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl);
+
+#endif/* _CAM_OIS_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 6ebd58b..97b4c01 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -33,6 +33,7 @@
#define CAM_CSIPHY_NAME "cam-csiphy"
#define CAM_FLASH_NAME "cam-flash"
#define CAM_EEPROM_NAME "cam-eeprom"
+#define CAM_OIS_NAME "cam-ois"
#define MAX_SYSTEM_PIPELINE_DELAY 2
@@ -165,6 +166,11 @@
CAM_EEPROM_PACKET_OPCODE_INIT
};
+enum cam_ois_packet_opcodes {
+ CAM_OIS_PACKET_OPCODE_INIT,
+ CAM_OIS_PACKET_OPCODE_OIS_CONTROL
+};
+
enum msm_bus_perf_setting {
S_INIT,
S_PREVIEW,
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
index 21f90ca..f451155 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
@@ -83,6 +83,9 @@
case CAM_HFI:
name = "CAM-HFI";
break;
+ case CAM_OIS:
+ name = "CAM-OIS";
+ break;
default:
name = "CAM";
break;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
index 7275d56..40dbe00 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
@@ -33,6 +33,7 @@
#define CAM_UTIL (1 << 17)
#define CAM_HFI (1 << 18)
#define CAM_CTXT (1 << 19)
+#define CAM_OIS (1 << 20)
#define STR_BUFFER_MAX_LENGTH 1024
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index f16c1ba..39793b6 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -523,13 +523,17 @@
int level;
struct mpq_demux *mpq_demux = fp->private_data;
- if (count >= 16)
+ if (count == 0 || count >= 16)
return -EINVAL;
- ret_count = simple_write_to_buffer(user_str, 16, position, user_buffer,
+ memset(user_str, '\0', sizeof(user_str));
+
+ ret_count = simple_write_to_buffer(user_str, 15, position, user_buffer,
count);
if (ret_count < 0)
return ret_count;
+ else if (ret_count == 0)
+ return -EINVAL;
ret = kstrtoint(user_str, 0, &level);
if (ret)
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index b1438d5..47e8d5f 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -157,6 +157,7 @@
struct reg_bus_client *reg_bus_clt;
bool domain_attached;
int domain;
+ u32 sid;
};
/*
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index 0704602..a7717f2 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -45,18 +45,12 @@
/* Rotator device id to be used in SCM call */
#define SDE_ROTATOR_DEVICE 21
-#ifndef VMID_CP_CAMERA_PREVIEW
-#define VMID_CP_CAMERA_PREVIEW VMID_INVAL
-#endif
-
-/* SCM call function id to be used for switching between secure and non
+/*
+ * SCM call function id to be used for switching between secure and non
* secure context
*/
#define MEM_PROTECT_SD_CTRL_SWITCH 0x18
-/* Rotator secure SID */
-#define SDE_ROTATOR_SECURE_SID 0xe01
-
/* waiting for hw time out, 3 vsync for 30fps*/
#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100
@@ -601,7 +595,7 @@
if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
mdata->sde_caps_map)) {
- sid_info = SDE_ROTATOR_SECURE_SID;
+ sid_info = mdata->sde_smmu[SDE_IOMMU_DOMAIN_ROT_SECURE].sid;
desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
desc.args[0] = SDE_ROTATOR_DEVICE;
desc.args[1] = SCM_BUFFER_PHYS(&sid_info);
@@ -631,9 +625,12 @@
return -EINVAL;
}
- SDEROT_DBG("scm_call(1) ret=%d, resp=%x",
+ SDEROT_DBG(
+ "scm(1) sid0x%x dev0x%llx vmid0x%llx ret%d resp%x\n",
+ sid_info, desc.args[0], desc.args[3],
ret, resp);
- SDEROT_EVTLOG(1);
+ SDEROT_EVTLOG(1, sid_info, desc.args[0], desc.args[3],
+ ret, resp);
} else if (mdata->sec_cam_en && !enable) {
/*
* Disable secure camera operation
@@ -648,12 +645,16 @@
MEM_PROTECT_SD_CTRL_SWITCH), &desc);
resp = desc.ret[0];
- SDEROT_DBG("scm_call(0): ret=%d, resp=%x",
+ SDEROT_DBG(
+ "scm(0) sid0x%x dev0x%llx vmid0x%llx ret%d resp%d\n",
+ sid_info, desc.args[0], desc.args[3],
ret, resp);
/* force smmu to reattach */
sde_smmu_secure_ctrl(1);
- SDEROT_EVTLOG(0);
+
+ SDEROT_EVTLOG(0, sid_info, desc.args[0], desc.args[3],
+ ret, resp);
}
} else {
return 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
index 9e47187..cc1407a 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
@@ -517,6 +517,7 @@
const struct of_device_id *match;
struct sde_module_power *mp;
char name[MAX_CLIENT_NAME_LEN];
+ u32 sid = 0;
if (!mdata) {
SDEROT_INFO(
@@ -538,6 +539,11 @@
if (of_find_property(pdev->dev.of_node, "iommus", NULL)) {
dev = &pdev->dev;
+ rc = of_property_read_u32_index(pdev->dev.of_node, "iommus",
+ 1, &sid);
+ if (rc)
+ SDEROT_DBG("SID not defined for domain:%d",
+ smmu_domain.domain);
} else {
SDEROT_ERR("Invalid SMMU ctx for domain:%d\n",
smmu_domain.domain);
@@ -546,6 +552,7 @@
sde_smmu = &mdata->sde_smmu[smmu_domain.domain];
sde_smmu->domain = smmu_domain.domain;
+ sde_smmu->sid = sid;
mp = &sde_smmu->mp;
memset(mp, 0, sizeof(struct sde_module_power));
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index a531cb4..a378b8c 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -403,6 +403,7 @@
return ret;
mmc_card_set_present(card);
+ device_enable_async_suspend(&card->dev);
return 0;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 409718b..c41f580 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1357,10 +1357,6 @@
int err;
u8 val;
- /* Reduce frequency to HS */
- max_dtr = card->ext_csd.hs_max_dtr;
- mmc_set_clock(host, max_dtr);
-
/* Switch HS400 to HS DDR */
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
@@ -1371,6 +1367,10 @@
mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
+ /* Reduce frequency to HS */
+ max_dtr = card->ext_csd.hs_max_dtr;
+ mmc_set_clock(host, max_dtr);
+
err = mmc_switch_status(card, false);
if (err)
goto out_err;
@@ -2159,11 +2159,11 @@
}
card->clk_scaling_lowest = host->f_min;
- if ((card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS400) ||
- (card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS200))
+ if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400) ||
+ (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS200))
card->clk_scaling_highest = card->ext_csd.hs200_max_dtr;
- else if ((card->mmc_avail_type | EXT_CSD_CARD_TYPE_HS) ||
- (card->mmc_avail_type | EXT_CSD_CARD_TYPE_DDR_52))
+ else if ((card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS) ||
+ (card->mmc_avail_type & EXT_CSD_CARD_TYPE_DDR_52))
card->clk_scaling_highest = card->ext_csd.hs_max_dtr;
else
card->clk_scaling_highest = card->csd.max_dtr;
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index d624b48..2cb13bd 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -312,6 +312,42 @@
return 0;
}
+int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
+ struct mmc_request *mrq, u32 slot, u64 *ice_ctx)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ int err = 0;
+ short key_index;
+ sector_t lba = 0;
+ unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
+ struct request *req;
+
+ if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
+ pr_err("%s: ice is in invalid state %d\n",
+ mmc_hostname(host->mmc), msm_host->ice.state);
+ return -EINVAL;
+ }
+
+ WARN_ON(!mrq);
+ if (!mrq)
+ return -EINVAL;
+ req = mrq->req;
+ if (req) {
+ lba = req->__sector;
+ err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
+ if (err)
+ return err;
+ pr_debug("%s: %s: slot %d bypass %d key_index %d\n",
+ mmc_hostname(host->mmc),
+ (rq_data_dir(req) == WRITE) ? "WRITE" : "READ",
+ slot, bypass, key_index);
+ }
+
+ sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
+ return 0;
+}
+
int sdhci_msm_ice_reset(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h
index 23922cf..4c813a0 100644
--- a/drivers/mmc/host/sdhci-msm-ice.h
+++ b/drivers/mmc/host/sdhci-msm-ice.h
@@ -99,6 +99,8 @@
void sdhci_msm_ice_cfg_reset(struct sdhci_host *host, u32 slot);
int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq,
u32 slot);
+int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
+ struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
int sdhci_msm_ice_reset(struct sdhci_host *host);
int sdhci_msm_ice_resume(struct sdhci_host *host);
int sdhci_msm_ice_suspend(struct sdhci_host *host);
@@ -130,6 +132,11 @@
{
return 0;
}
+static inline int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
+ struct mmc_request *mrq, u32 slot, u64 *ice_ctx)
+{
+ return 0;
+}
inline int sdhci_msm_ice_reset(struct sdhci_host *host)
{
return 0;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 1e25b31..f1364a1 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -146,6 +146,7 @@
#define CORE_START_CDC_TRAFFIC (1 << 6)
#define CORE_PWRSAVE_DLL (1 << 3)
+#define CORE_FIFO_ALT_EN (1 << 10)
#define CORE_CMDEN_HS400_INPUT_MASK_CNT (1 << 13)
#define CORE_DDR_CAL_EN (1 << 0)
@@ -1143,6 +1144,7 @@
bool drv_type_changed = false;
struct mmc_card *card = host->mmc->card;
int sts_retry;
+ u8 last_good_phase = 0;
/*
* Tuning is required for SDR104, HS200 and HS400 cards and
@@ -1228,6 +1230,22 @@
mmc_wait_for_req(mmc, &mrq);
if (card && (cmd.error || data.error)) {
+ /*
+ * Set the dll to last known good phase while sending
+ * status command to ensure that status command won't
+ * fail due to bad phase.
+ */
+ if (tuned_phase_cnt)
+ last_good_phase =
+ tuned_phases[tuned_phase_cnt-1];
+ else if (msm_host->saved_tuning_phase !=
+ INVALID_TUNING_PHASE)
+ last_good_phase = msm_host->saved_tuning_phase;
+
+ rc = msm_config_cm_dll_phase(host, last_good_phase);
+ if (rc)
+ goto kfree;
+
sts_cmd.opcode = MMC_SEND_STATUS;
sts_cmd.arg = card->rca << 16;
sts_cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
@@ -4097,6 +4115,8 @@
static struct sdhci_ops sdhci_msm_ops = {
.crypto_engine_cfg = sdhci_msm_ice_cfg,
+ .crypto_engine_cmdq_cfg = sdhci_msm_ice_cmdq_cfg,
+ .crypto_cfg_reset = sdhci_msm_ice_cfg_reset,
.crypto_engine_reset = sdhci_msm_ice_reset,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.check_power_status = sdhci_msm_check_power_status,
@@ -4196,7 +4216,7 @@
* starts coming.
*/
if ((major == 1) && ((minor == 0x42) || (minor == 0x46) ||
- (minor == 0x49)))
+ (minor == 0x49) || (minor >= 0x6b)))
msm_host->use_14lpp_dll = true;
/* Fake 3.0V support for SDIO devices which requires such voltage */
@@ -4221,8 +4241,10 @@
/* keep track of the value in SDHCI_CAPABILITIES */
msm_host->caps_0 = caps;
- if ((major == 1) && (minor >= 0x6b))
+ if ((major == 1) && (minor >= 0x6b)) {
msm_host->ice_hci_support = true;
+ host->cdr_support = true;
+ }
}
#ifdef CONFIG_MMC_CQ_HCI
@@ -4518,6 +4540,14 @@
writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC);
+ /*
+ * Ensure SDHCI FIFO is enabled by disabling alternative FIFO
+ */
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3) &
+ ~CORE_FIFO_ALT_EN), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3);
+
if (!msm_host->mci_removed) {
/* Set HC_MODE_EN bit in HC_MODE register */
writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
@@ -5050,7 +5080,7 @@
}
static const struct dev_pm_ops sdhci_msm_pmops = {
- SET_SYSTEM_SLEEP_PM_OPS(sdhci_msm_suspend, sdhci_msm_resume)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(sdhci_msm_suspend, sdhci_msm_resume)
SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend, sdhci_msm_runtime_resume,
NULL)
.suspend_noirq = sdhci_msm_suspend_noirq,
@@ -5074,6 +5104,7 @@
.driver = {
.name = "sdhci_msm",
.owner = THIS_MODULE,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sdhci_msm_dt_match,
.pm = SDHCI_MSM_PMOPS,
},
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 68e49bb..bf32a87 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3088,12 +3088,6 @@
* above in sdhci_cmd_irq().
*/
if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) {
- if (intmask & SDHCI_INT_DATA_TIMEOUT) {
- host->data_cmd = NULL;
- data_cmd->error = -ETIMEDOUT;
- sdhci_finish_mrq(host, data_cmd->mrq);
- return;
- }
if (intmask & SDHCI_INT_DATA_END) {
host->data_cmd = NULL;
/*
@@ -3108,8 +3102,21 @@
return;
}
if (host->quirks2 &
- SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD)
+ SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD) {
+ pr_err_ratelimited("%s: %s: ignoring interrupt: 0x%08x due to DATATOUT_FOR_R1B quirk\n",
+ mmc_hostname(host->mmc),
+ __func__, intmask);
+ MMC_TRACE(host->mmc,
+ "%s: Quirk ignoring intr: 0x%08x\n",
+ __func__, intmask);
return;
+ }
+ if (intmask & SDHCI_INT_DATA_TIMEOUT) {
+ host->data_cmd = NULL;
+ data_cmd->error = -ETIMEDOUT;
+ sdhci_finish_mrq(host, data_cmd->mrq);
+ return;
+ }
}
/*
@@ -3689,7 +3696,7 @@
ctrl |= SDHCI_CTRL_ADMA32;
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
- if (host->ops->toggle_cdr)
+ if (host->ops->toggle_cdr && !host->cdr_support)
host->ops->toggle_cdr(host, false);
}
@@ -3771,11 +3778,31 @@
struct mmc_request *mrq, u32 slot)
{
struct sdhci_host *host = mmc_priv(mmc);
+ int err = 0;
if (!host->is_crypto_en)
return 0;
- return sdhci_crypto_cfg(host, mrq, slot);
+ if (host->crypto_reset_reqd && host->ops->crypto_engine_reset) {
+ err = host->ops->crypto_engine_reset(host);
+ if (err) {
+ pr_err("%s: crypto reset failed\n",
+ mmc_hostname(host->mmc));
+ goto out;
+ }
+ host->crypto_reset_reqd = false;
+ }
+
+ if (host->ops->crypto_engine_cmdq_cfg) {
+ err = host->ops->crypto_engine_cmdq_cfg(host, mrq, slot, NULL);
+ if (err) {
+ pr_err("%s: failed to configure crypto\n",
+ mmc_hostname(host->mmc));
+ goto out;
+ }
+ }
+out:
+ return err;
}
static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 04e806c..a463e45 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -518,7 +518,7 @@
* Some controllers may use PIO mode to workaround HW issues in ADMA for
* eMMC tuning commands.
*/
-#define SDHCI_QUIRK2_USE_PIO_FOR_EMMC_TUNING (1 << 23)
+#define SDHCI_QUIRK2_USE_PIO_FOR_EMMC_TUNING (1 << 29)
int irq; /* Device IRQ */
@@ -569,6 +569,7 @@
bool bus_on; /* Bus power prevents runtime suspend */
bool preset_enabled; /* Preset is enabled */
bool pending_reset; /* Cmd/data reset is pending */
+ bool cdr_support;
struct mmc_request *mrqs_done[SDHCI_MAX_MRQS]; /* Requests done */
struct mmc_request *mrq; /* Current request */
@@ -670,6 +671,8 @@
int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
int (*crypto_engine_cfg)(struct sdhci_host *host,
struct mmc_request *mrq, u32 slot);
+ int (*crypto_engine_cmdq_cfg)(struct sdhci_host *host,
+ struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
int (*crypto_engine_reset)(struct sdhci_host *host);
void (*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot);
void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig
index 0e66348..2ab6c59 100644
--- a/drivers/net/wireless/ath/wil6210/Kconfig
+++ b/drivers/net/wireless/ath/wil6210/Kconfig
@@ -60,3 +60,15 @@
---help---
Say Y here to enable wil6210 driver support for MSM
platform specific features
+
+config WIL6210_DEBUGFS
+ bool "wil6210 debugfs support"
+ depends on WIL6210
+ depends on DEBUG_FS
+ default y
+ ---help---
+ Say Y here to enable wil6210 debugfs support, using the
+ kernel debugfs infrastructure. Select this
+ option if you are interested in debugging the driver.
+
+ If unsure, say Y to make it easier to debug problems.
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 4874c5b..94df1de 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -4,7 +4,7 @@
wil6210-y += netdev.o
wil6210-y += cfg80211.o
wil6210-y += pcie_bus.o
-wil6210-y += debugfs.o
+wil6210-$(CONFIG_WIL6210_DEBUGFS) += debugfs.o
wil6210-y += sysfs.o
wil6210-y += wmi.o
wil6210-y += interrupt.o
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 7a0b226..9552d2a 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -454,6 +454,34 @@
return rc;
}
+static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ wil_dbg_misc(wil, "start_p2p_device: entered\n");
+ wil->p2p.p2p_dev_started = 1;
+ return 0;
+}
+
+static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ struct wil_p2p_info *p2p = &wil->p2p;
+
+ if (!p2p->p2p_dev_started)
+ return;
+
+ wil_dbg_misc(wil, "stop_p2p_device: entered\n");
+ mutex_lock(&wil->mutex);
+ mutex_lock(&wil->p2p_wdev_mutex);
+ wil_p2p_stop_radio_operations(wil);
+ p2p->p2p_dev_started = 0;
+ mutex_unlock(&wil->p2p_wdev_mutex);
+ mutex_unlock(&wil->mutex);
+}
+
static struct wireless_dev *
wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
unsigned char name_assign_type,
@@ -502,6 +530,7 @@
return -EINVAL;
}
+ wil_cfg80211_stop_p2p_device(wiphy, wdev);
wil_p2p_wdev_free(wil);
return 0;
@@ -886,7 +915,7 @@
wil->bss = bss;
/* Connect can take lots of time */
mod_timer(&wil->connect_timer,
- jiffies + msecs_to_jiffies(2000));
+ jiffies + msecs_to_jiffies(5000));
} else {
clear_bit(wil_status_fwconnecting, wil->status);
}
@@ -1736,34 +1765,6 @@
return 0;
}
-static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
- struct wireless_dev *wdev)
-{
- struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-
- wil_dbg_misc(wil, "start_p2p_device: entered\n");
- wil->p2p.p2p_dev_started = 1;
- return 0;
-}
-
-static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
- struct wireless_dev *wdev)
-{
- struct wil6210_priv *wil = wiphy_to_wil(wiphy);
- struct wil_p2p_info *p2p = &wil->p2p;
-
- if (!p2p->p2p_dev_started)
- return;
-
- wil_dbg_misc(wil, "stop_p2p_device: entered\n");
- mutex_lock(&wil->mutex);
- mutex_lock(&wil->p2p_wdev_mutex);
- wil_p2p_stop_radio_operations(wil);
- p2p->p2p_dev_started = 0;
- mutex_unlock(&wil->p2p_wdev_mutex);
- mutex_unlock(&wil->mutex);
-}
-
static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
struct net_device *dev,
bool enabled, int timeout)
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index cad8a95c4..59def4f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -244,7 +244,7 @@
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
if (unlikely(!isr)) {
- wil_err(wil, "spurious IRQ: RX\n");
+ wil_err_ratelimited(wil, "spurious IRQ: RX\n");
return IRQ_NONE;
}
@@ -269,11 +269,12 @@
need_unmask = false;
napi_schedule(&wil->napi_rx);
} else {
- wil_err(wil,
+ wil_err_ratelimited(
+ wil,
"Got Rx interrupt while stopping interface\n");
}
} else {
- wil_err(wil, "Got Rx interrupt while in reset\n");
+ wil_err_ratelimited(wil, "Got Rx interrupt while in reset\n");
}
}
@@ -302,7 +303,7 @@
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
if (unlikely(!isr)) {
- wil_err(wil, "spurious IRQ: TX\n");
+ wil_err_ratelimited(wil, "spurious IRQ: TX\n");
return IRQ_NONE;
}
@@ -318,12 +319,13 @@
need_unmask = false;
napi_schedule(&wil->napi_tx);
} else {
- wil_err(wil, "Got Tx interrupt while in reset\n");
+ wil_err_ratelimited(wil, "Got Tx interrupt while in reset\n");
}
}
if (unlikely(isr))
- wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
+ wil_err_ratelimited(wil, "un-handled TX ISR bits 0x%08x\n",
+ isr);
/* Tx IRQ will be enabled when NAPI processing finished */
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index d90fe1c..b91298d 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -934,6 +934,29 @@
return rc;
}
+static void wil_pre_fw_config(struct wil6210_priv *wil)
+{
+ /* Mark FW as loaded from host */
+ wil_s(wil, RGF_USER_USAGE_6, 1);
+
+ /* clear any interrupts which on-card-firmware
+ * may have set
+ */
+ wil6210_clear_irq(wil);
+ /* CAF_ICR - clear and mask */
+ /* it is W1C, clear by writing back same value */
+ wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
+ wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
+ /* clear PAL_UNIT_ICR (potential D0->D3 leftover) */
+ wil_s(wil, RGF_PAL_UNIT_ICR + offsetof(struct RGF_ICR, ICR), 0);
+
+ if (wil->fw_calib_result > 0) {
+ __le32 val = cpu_to_le32(wil->fw_calib_result |
+ (CALIB_RESULT_SIGNATURE << 8));
+ wil_w(wil, RGF_USER_FW_CALIB_RESULT, (u32 __force)val);
+ }
+}
+
/*
* We reset all the structures, and we reset the UMAC.
* After calling this routine, you're expected to reload
@@ -1031,24 +1054,7 @@
if (rc)
return rc;
- /* Mark FW as loaded from host */
- wil_s(wil, RGF_USER_USAGE_6, 1);
-
- /* clear any interrupts which on-card-firmware
- * may have set
- */
- wil6210_clear_irq(wil);
- /* CAF_ICR - clear and mask */
- /* it is W1C, clear by writing back same value */
- wil_s(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, ICR), 0);
- wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0);
-
- if (wil->fw_calib_result > 0) {
- __le32 val = cpu_to_le32(wil->fw_calib_result |
- (CALIB_RESULT_SIGNATURE << 8));
- wil_w(wil, RGF_USER_FW_CALIB_RESULT, (u32 __force)val);
- }
-
+ wil_pre_fw_config(wil);
wil_release_cpu(wil);
}
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index b4ca4e3..d5b8ea6 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -272,6 +272,7 @@
#define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
#define RGF_HP_CTRL (0x88265c)
+#define RGF_PAL_UNIT_ICR (0x88266c) /* struct RGF_ICR */
#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
/* MAC timer, usec, for packet lifetime */
@@ -951,8 +952,13 @@
struct cfg80211_mgmt_tx_params *params,
u64 *cookie);
+#if defined(CONFIG_WIL6210_DEBUGFS)
int wil6210_debugfs_init(struct wil6210_priv *wil);
void wil6210_debugfs_remove(struct wil6210_priv *wil);
+#else
+static inline int wil6210_debugfs_init(struct wil6210_priv *wil) { return 0; }
+static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {}
+#endif
int wil6210_sysfs_init(struct wil6210_priv *wil);
void wil6210_sysfs_remove(struct wil6210_priv *wil);
int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 1b426d7..5263ee7 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -36,6 +36,11 @@
#define WMI_PROX_RANGE_NUM (3)
#define WMI_MAX_LOSS_DMG_BEACONS (20)
#define MAX_NUM_OF_SECTORS (128)
+#define WMI_SCHED_MAX_ALLOCS_PER_CMD (4)
+#define WMI_RF_DTYPE_LENGTH (3)
+#define WMI_RF_ETYPE_LENGTH (3)
+#define WMI_RF_RX2TX_LENGTH (3)
+#define WMI_RF_ETYPE_VAL_PER_RANGE (5)
/* Mailbox interface
* used for commands and events
@@ -52,15 +57,20 @@
* the host
*/
enum wmi_fw_capability {
- WMI_FW_CAPABILITY_FTM = 0,
- WMI_FW_CAPABILITY_PS_CONFIG = 1,
- WMI_FW_CAPABILITY_RF_SECTORS = 2,
- WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3,
- WMI_FW_CAPABILITY_DISABLE_AP_SME = 4,
- WMI_FW_CAPABILITY_WMI_ONLY = 5,
- WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7,
- WMI_FW_CAPABILITY_D3_SUSPEND = 8,
- WMI_FW_CAPABILITY_RSSI_REPORTING = 12,
+ WMI_FW_CAPABILITY_FTM = 0,
+ WMI_FW_CAPABILITY_PS_CONFIG = 1,
+ WMI_FW_CAPABILITY_RF_SECTORS = 2,
+ WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3,
+ WMI_FW_CAPABILITY_DISABLE_AP_SME = 4,
+ WMI_FW_CAPABILITY_WMI_ONLY = 5,
+ WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7,
+ WMI_FW_CAPABILITY_D3_SUSPEND = 8,
+ WMI_FW_CAPABILITY_LONG_RANGE = 9,
+ WMI_FW_CAPABILITY_FIXED_SCHEDULING = 10,
+ WMI_FW_CAPABILITY_MULTI_DIRECTED_OMNIS = 11,
+ WMI_FW_CAPABILITY_RSSI_REPORTING = 12,
+ WMI_FW_CAPABILITY_SET_SILENT_RSSI_TABLE = 13,
+ WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP = 14,
WMI_FW_CAPABILITY_MAX,
};
@@ -80,6 +90,7 @@
WMI_START_SCAN_CMDID = 0x07,
WMI_SET_BSS_FILTER_CMDID = 0x09,
WMI_SET_PROBED_SSID_CMDID = 0x0A,
+ /* deprecated */
WMI_SET_LISTEN_INT_CMDID = 0x0B,
WMI_BCON_CTRL_CMDID = 0x0F,
WMI_ADD_CIPHER_KEY_CMDID = 0x16,
@@ -94,26 +105,28 @@
WMI_ECHO_CMDID = 0x803,
WMI_DEEP_ECHO_CMDID = 0x804,
WMI_CONFIG_MAC_CMDID = 0x805,
+ /* deprecated */
WMI_CONFIG_PHY_DEBUG_CMDID = 0x806,
WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808,
WMI_PHY_GET_STATISTICS_CMDID = 0x809,
+ /* deprecated */
WMI_FS_TUNE_CMDID = 0x80A,
+ /* deprecated */
WMI_CORR_MEASURE_CMDID = 0x80B,
WMI_READ_RSSI_CMDID = 0x80C,
WMI_TEMP_SENSE_CMDID = 0x80E,
WMI_DC_CALIB_CMDID = 0x80F,
+ /* deprecated */
WMI_SEND_TONE_CMDID = 0x810,
+ /* deprecated */
WMI_IQ_TX_CALIB_CMDID = 0x811,
+ /* deprecated */
WMI_IQ_RX_CALIB_CMDID = 0x812,
- WMI_SET_UCODE_IDLE_CMDID = 0x813,
WMI_SET_WORK_MODE_CMDID = 0x815,
WMI_LO_LEAKAGE_CALIB_CMDID = 0x816,
- WMI_MARLON_R_READ_CMDID = 0x818,
- WMI_MARLON_R_WRITE_CMDID = 0x819,
- WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A,
- MAC_IO_STATIC_PARAMS_CMDID = 0x81B,
- MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C,
+ WMI_LO_POWER_CALIB_FROM_OTP_CMDID = 0x817,
WMI_SILENT_RSSI_CALIB_CMDID = 0x81D,
+ /* deprecated */
WMI_RF_RX_TEST_CMDID = 0x81E,
WMI_CFG_RX_CHAIN_CMDID = 0x820,
WMI_VRING_CFG_CMDID = 0x821,
@@ -127,11 +140,6 @@
WMI_SET_PCP_CHANNEL_CMDID = 0x829,
WMI_GET_PCP_CHANNEL_CMDID = 0x82A,
WMI_SW_TX_REQ_CMDID = 0x82B,
- WMI_READ_MAC_RXQ_CMDID = 0x830,
- WMI_READ_MAC_TXQ_CMDID = 0x831,
- WMI_WRITE_MAC_RXQ_CMDID = 0x832,
- WMI_WRITE_MAC_TXQ_CMDID = 0x833,
- WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834,
WMI_MLME_PUSH_CMDID = 0x835,
WMI_BEAMFORMING_MGMT_CMDID = 0x836,
WMI_BF_TXSS_MGMT_CMDID = 0x837,
@@ -145,9 +153,13 @@
WMI_MAINTAIN_RESUME_CMDID = 0x851,
WMI_RS_MGMT_CMDID = 0x852,
WMI_RF_MGMT_CMDID = 0x853,
- WMI_OTP_READ_CMDID = 0x856,
- WMI_OTP_WRITE_CMDID = 0x857,
+ WMI_RF_XPM_READ_CMDID = 0x856,
+ WMI_RF_XPM_WRITE_CMDID = 0x857,
WMI_LED_CFG_CMDID = 0x858,
+ WMI_SET_CONNECT_SNR_THR_CMDID = 0x85B,
+ WMI_SET_ACTIVE_SILENT_RSSI_TABLE_CMDID = 0x85C,
+ WMI_RF_PWR_ON_DELAY_CMDID = 0x85D,
+ WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID = 0x85E,
/* Performance monitoring commands */
WMI_BF_CTRL_CMDID = 0x862,
WMI_NOTIFY_REQ_CMDID = 0x863,
@@ -155,7 +167,6 @@
WMI_GET_RF_STATUS_CMDID = 0x866,
WMI_GET_BASEBAND_TYPE_CMDID = 0x867,
WMI_UNIT_TEST_CMDID = 0x900,
- WMI_HICCUP_CMDID = 0x901,
WMI_FLASH_READ_CMDID = 0x902,
WMI_FLASH_WRITE_CMDID = 0x903,
/* Power management */
@@ -175,16 +186,6 @@
WMI_GET_PCP_FACTOR_CMDID = 0x91B,
/* Power Save Configuration Commands */
WMI_PS_DEV_PROFILE_CFG_CMDID = 0x91C,
- /* Not supported yet */
- WMI_PS_DEV_CFG_CMDID = 0x91D,
- /* Not supported yet */
- WMI_PS_DEV_CFG_READ_CMDID = 0x91E,
- /* Per MAC Power Save Configuration commands
- * Not supported yet
- */
- WMI_PS_MID_CFG_CMDID = 0x91F,
- /* Not supported yet */
- WMI_PS_MID_CFG_READ_CMDID = 0x920,
WMI_RS_CFG_CMDID = 0x921,
WMI_GET_DETAILED_RS_RES_CMDID = 0x922,
WMI_AOA_MEAS_CMDID = 0x923,
@@ -195,13 +196,16 @@
WMI_DEL_STA_CMDID = 0x936,
WMI_SET_THERMAL_THROTTLING_CFG_CMDID = 0x940,
WMI_GET_THERMAL_THROTTLING_CFG_CMDID = 0x941,
+ /* Read Power Save profile type */
+ WMI_PS_DEV_PROFILE_CFG_READ_CMDID = 0x942,
WMI_TOF_SESSION_START_CMDID = 0x991,
WMI_TOF_GET_CAPABILITIES_CMDID = 0x992,
WMI_TOF_SET_LCR_CMDID = 0x993,
WMI_TOF_SET_LCI_CMDID = 0x994,
- WMI_TOF_CHANNEL_INFO_CMDID = 0x995,
+ WMI_TOF_CFG_RESPONDER_CMDID = 0x996,
WMI_TOF_SET_TX_RX_OFFSET_CMDID = 0x997,
WMI_TOF_GET_TX_RX_OFFSET_CMDID = 0x998,
+ WMI_TOF_CHANNEL_INFO_CMDID = 0x999,
WMI_GET_RF_SECTOR_PARAMS_CMDID = 0x9A0,
WMI_SET_RF_SECTOR_PARAMS_CMDID = 0x9A1,
WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID = 0x9A2,
@@ -210,12 +214,20 @@
WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5,
WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6,
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7,
+ WMI_SCHEDULING_SCHEME_CMDID = 0xA01,
+ WMI_FIXED_SCHEDULING_CONFIG_CMDID = 0xA02,
+ WMI_ENABLE_FIXED_SCHEDULING_CMDID = 0xA03,
+ WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_CMDID = 0xA04,
+ WMI_SET_LONG_RANGE_CONFIG_CMDID = 0xA05,
WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
WMI_ABORT_SCAN_CMDID = 0xF007,
WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
+ /* deprecated */
WMI_GET_PMK_CMDID = 0xF048,
WMI_SET_PASSPHRASE_CMDID = 0xF049,
+ /* deprecated */
WMI_SEND_ASSOC_RES_CMDID = 0xF04A,
+ /* deprecated */
WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B,
WMI_MAC_ADDR_REQ_CMDID = 0xF04D,
WMI_FW_VER_CMDID = 0xF04E,
@@ -441,11 +453,6 @@
__le32 rf_mgmt_type;
} __packed;
-/* WMI_RF_RX_TEST_CMDID */
-struct wmi_rf_rx_test_cmd {
- __le32 sector;
-} __packed;
-
/* WMI_CORR_MEASURE_CMDID */
struct wmi_corr_measure_cmd {
__le32 freq_mhz;
@@ -658,6 +665,20 @@
struct wmi_bcast_vring_cfg vring_cfg;
} __packed;
+/* WMI_LO_POWER_CALIB_FROM_OTP_CMDID */
+struct wmi_lo_power_calib_from_otp_cmd {
+ /* index to read from OTP. zero based */
+ u8 index;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_LO_POWER_CALIB_FROM_OTP_EVENTID */
+struct wmi_lo_power_calib_from_otp_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
/* WMI_VRING_BA_EN_CMDID */
struct wmi_vring_ba_en_cmd {
u8 ringid;
@@ -693,6 +714,24 @@
WMI_SNIFFER_ON = 0x01,
};
+/* WMI_SILENT_RSSI_TABLE */
+enum wmi_silent_rssi_table {
+ RF_TEMPERATURE_CALIB_DEFAULT_DB = 0x00,
+ RF_TEMPERATURE_CALIB_HIGH_POWER_DB = 0x01,
+};
+
+/* WMI_SILENT_RSSI_STATUS */
+enum wmi_silent_rssi_status {
+ SILENT_RSSI_SUCCESS = 0x00,
+ SILENT_RSSI_FAILURE = 0x01,
+};
+
+/* WMI_SET_ACTIVE_SILENT_RSSI_TABLE_CMDID */
+struct wmi_set_active_silent_rssi_table_cmd {
+ /* enum wmi_silent_rssi_table */
+ __le32 table;
+} __packed;
+
enum wmi_sniffer_cfg_phy_info_mode {
WMI_SNIFFER_PHY_INFO_DISABLED = 0x00,
WMI_SNIFFER_PHY_INFO_ENABLED = 0x01,
@@ -836,18 +875,85 @@
__le32 value;
} __packed;
-/* WMI_OTP_READ_CMDID */
-struct wmi_otp_read_cmd {
- __le32 addr;
- __le32 size;
- __le32 values;
+/* WMI_RF_PWR_ON_DELAY_CMDID
+ * set FW time parameters used through RF resetting
+ * RF reset consists of bringing its power down for a period of time, then
+ * bringing the power up
+ * Returned event: WMI_RF_PWR_ON_DELAY_RSP_EVENTID
+ */
+struct wmi_rf_pwr_on_delay_cmd {
+ /* time in usec the FW waits after bringing the RF PWR down,
+ * set 0 for default
+ */
+ __le16 down_delay_usec;
+ /* time in usec the FW waits after bringing the RF PWR up,
+ * set 0 for default
+ */
+ __le16 up_delay_usec;
} __packed;
-/* WMI_OTP_WRITE_CMDID */
-struct wmi_otp_write_cmd {
- __le32 addr;
- __le32 size;
- __le32 values;
+/* \WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID
+ * This API controls the Tx and Rx gain over temperature.
+ * It controls the Tx D-type, Rx D-type and Rx E-type amplifiers.
+ * It also controls the Tx gain index, by controlling the Rx to Tx gain index
+ * offset.
+ * The control is divided by 3 temperature values to 4 temperature ranges.
+ * Each parameter uses its own temperature values.
+ * Returned event: WMI_SET_HIGH_POWER_TABLE_PARAMS_EVENTID
+ */
+struct wmi_set_high_power_table_params_cmd {
+ /* Temperature range for Tx D-type parameters */
+ u8 tx_dtype_temp[WMI_RF_DTYPE_LENGTH];
+ u8 reserved0;
+ /* Tx D-type values to be used for each temperature range */
+ __le32 tx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1];
+ /* Temperature range for Rx D-type parameters */
+ u8 rx_dtype_temp[WMI_RF_DTYPE_LENGTH];
+ u8 reserved1;
+ /* Rx D-type values to be used for each temperature range */
+ __le32 rx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1];
+ /* Temperature range for Rx E-type parameters */
+ u8 rx_etype_temp[WMI_RF_ETYPE_LENGTH];
+ u8 reserved2;
+ /* Rx E-type values to be used for each temperature range.
+ * The last 4 values of any range are the first 4 values of the next
+ * range and so on
+ */
+ __le32 rx_etype_conf[WMI_RF_ETYPE_VAL_PER_RANGE + WMI_RF_ETYPE_LENGTH];
+ /* Temperature range for rx_2_tx_offs parameters */
+ u8 rx_2_tx_temp[WMI_RF_RX2TX_LENGTH];
+ u8 reserved3;
+ /* Rx to Tx gain index offset */
+ s8 rx_2_tx_offs[WMI_RF_RX2TX_LENGTH + 1];
+} __packed;
+
+/* CMD: WMI_RF_XPM_READ_CMDID */
+struct wmi_rf_xpm_read_cmd {
+ u8 rf_id;
+ u8 reserved[3];
+ /* XPM bit start address in range [0,8191]bits - rounded by FW to
+ * multiple of 8bits
+ */
+ __le32 xpm_bit_address;
+ __le32 num_bytes;
+} __packed;
+
+/* CMD: WMI_RF_XPM_WRITE_CMDID */
+struct wmi_rf_xpm_write_cmd {
+ u8 rf_id;
+ u8 reserved0[3];
+ /* XPM bit start address in range [0,8191]bits - rounded by FW to
+ * multiple of 8bits
+ */
+ __le32 xpm_bit_address;
+ __le32 num_bytes;
+ /* boolean flag indicating whether FW should verify the write
+ * operation
+ */
+ u8 verify;
+ u8 reserved1[3];
+ /* actual size=num_bytes */
+ u8 data_bytes[0];
} __packed;
/* WMI_TEMP_SENSE_CMDID
@@ -990,19 +1096,26 @@
*/
__le16 burst_period;
u8 dst_mac[WMI_MAC_LEN];
- __le16 reserved;
+ u8 reserved;
+ u8 num_burst_per_aoa_meas;
} __packed;
/* WMI_TOF_SESSION_START_CMDID */
struct wmi_tof_session_start_cmd {
__le32 session_id;
- u8 num_of_aoa_measures;
+ u8 reserved1;
u8 aoa_type;
__le16 num_of_dest;
u8 reserved[4];
struct wmi_ftm_dest_info ftm_dest_info[0];
} __packed;
+/* WMI_TOF_CFG_RESPONDER_CMDID */
+struct wmi_tof_cfg_responder_cmd {
+ u8 enable;
+ u8 reserved[3];
+} __packed;
+
enum wmi_tof_channel_info_report_type {
WMI_TOF_CHANNEL_INFO_TYPE_CIR = 0x1,
WMI_TOF_CHANNEL_INFO_TYPE_RSSI = 0x2,
@@ -1023,7 +1136,99 @@
__le32 tx_offset;
/* RX delay offset */
__le32 rx_offset;
- __le32 reserved[2];
+ /* Mask to define which RFs to configure. 0 means all RFs */
+ __le32 rf_mask;
+ /* Offset to strongest tap of CIR */
+ __le32 precursor;
+} __packed;
+
+/* WMI_TOF_GET_TX_RX_OFFSET_CMDID */
+struct wmi_tof_get_tx_rx_offset_cmd {
+ /* rf index to read offsets from */
+ u8 rf_index;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_FIXED_SCHEDULING_CONFIG_CMDID */
+struct wmi_map_mcs_to_schd_params {
+ u8 mcs;
+ /* time in usec from start slot to start tx flow - default 15 */
+ u8 time_in_usec_before_initiate_tx;
+ /* RD enable - if yes consider RD according to STA mcs */
+ u8 rd_enabled;
+ u8 reserved;
+ /* time in usec from start slot to stop vring */
+ __le16 time_in_usec_to_stop_vring;
+ /* timeout to force flush from start of slot */
+ __le16 flush_to_in_usec;
+ /* per mcs the mac buffer limit size in bytes */
+ __le32 mac_buff_size_in_bytes;
+} __packed;
+
+/* WMI_FIXED_SCHEDULING_CONFIG_COMPLETE_EVENTID */
+struct wmi_fixed_scheduling_config_complete_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+#define WMI_NUM_MCS (13)
+
+/* WMI_FIXED_SCHEDULING_CONFIG_CMDID */
+struct wmi_fixed_scheduling_config_cmd {
+ /* defaults in the SAS table */
+ struct wmi_map_mcs_to_schd_params mcs_to_schd_params_map[WMI_NUM_MCS];
+ /* default 150 uSec */
+ __le16 max_sta_rd_ppdu_duration_in_usec;
+ /* default 300 uSec */
+ __le16 max_sta_grant_ppdu_duration_in_usec;
+ /* default 1000 uSec */
+ __le16 assoc_slot_duration_in_usec;
+ /* default 360 uSec */
+ __le16 virtual_slot_duration_in_usec;
+ /* each this field value slots start with grant frame to the station
+ * - default 2
+ */
+ u8 number_of_ap_slots_for_initiate_grant;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_ENABLE_FIXED_SCHEDULING_CMDID */
+struct wmi_enable_fixed_scheduling_cmd {
+ __le32 reserved;
+} __packed;
+
+/* WMI_ENABLE_FIXED_SCHEDULING_COMPLETE_EVENTID */
+struct wmi_enable_fixed_scheduling_complete_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_CMDID */
+struct wmi_set_multi_directed_omnis_config_cmd {
+ /* number of directed omnis at destination AP */
+ u8 dest_ap_num_directed_omnis;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_EVENTID */
+struct wmi_set_multi_directed_omnis_config_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_SET_LONG_RANGE_CONFIG_CMDID */
+struct wmi_set_long_range_config_cmd {
+ __le32 reserved;
+} __packed;
+
+/* WMI_SET_LONG_RANGE_CONFIG_COMPLETE_EVENTID */
+struct wmi_set_long_range_config_complete_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
} __packed;
/* WMI Events
@@ -1039,19 +1244,22 @@
WMI_FW_READY_EVENTID = 0x1801,
WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200,
WMI_ECHO_RSP_EVENTID = 0x1803,
+ /* deprecated */
WMI_FS_TUNE_DONE_EVENTID = 0x180A,
+ /* deprecated */
WMI_CORR_MEASURE_EVENTID = 0x180B,
WMI_READ_RSSI_EVENTID = 0x180C,
WMI_TEMP_SENSE_DONE_EVENTID = 0x180E,
WMI_DC_CALIB_DONE_EVENTID = 0x180F,
+ /* deprecated */
WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811,
+ /* deprecated */
WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812,
WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815,
WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816,
- WMI_MARLON_R_READ_DONE_EVENTID = 0x1818,
- WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819,
- WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181A,
+ WMI_LO_POWER_CALIB_FROM_OTP_EVENTID = 0x1817,
WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181D,
+ /* deprecated */
WMI_RF_RX_TEST_DONE_EVENTID = 0x181E,
WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820,
WMI_VRING_CFG_DONE_EVENTID = 0x1821,
@@ -1062,11 +1270,6 @@
WMI_GET_SSID_EVENTID = 0x1828,
WMI_GET_PCP_CHANNEL_EVENTID = 0x182A,
WMI_SW_TX_COMPLETE_EVENTID = 0x182B,
- WMI_READ_MAC_RXQ_EVENTID = 0x1830,
- WMI_READ_MAC_TXQ_EVENTID = 0x1831,
- WMI_WRITE_MAC_RXQ_EVENTID = 0x1832,
- WMI_WRITE_MAC_TXQ_EVENTID = 0x1833,
- WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834,
WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836,
WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837,
WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839,
@@ -1077,8 +1280,12 @@
WMI_TX_MGMT_PACKET_EVENTID = 0x1841,
WMI_LINK_MAINTAIN_CFG_WRITE_DONE_EVENTID = 0x1842,
WMI_LINK_MAINTAIN_CFG_READ_DONE_EVENTID = 0x1843,
- WMI_OTP_READ_RESULT_EVENTID = 0x1856,
+ WMI_RF_XPM_READ_RESULT_EVENTID = 0x1856,
+ WMI_RF_XPM_WRITE_RESULT_EVENTID = 0x1857,
WMI_LED_CFG_DONE_EVENTID = 0x1858,
+ WMI_SET_SILENT_RSSI_TABLE_DONE_EVENTID = 0x185C,
+ WMI_RF_PWR_ON_DELAY_RSP_EVENTID = 0x185D,
+ WMI_SET_HIGH_POWER_TABLE_PARAMS_EVENTID = 0x185E,
/* Performance monitoring events */
WMI_DATA_PORT_OPEN_EVENTID = 0x1860,
WMI_WBE_LINK_DOWN_EVENTID = 0x1861,
@@ -1107,14 +1314,6 @@
WMI_PCP_FACTOR_EVENTID = 0x191A,
/* Power Save Configuration Events */
WMI_PS_DEV_PROFILE_CFG_EVENTID = 0x191C,
- /* Not supported yet */
- WMI_PS_DEV_CFG_EVENTID = 0x191D,
- /* Not supported yet */
- WMI_PS_DEV_CFG_READ_EVENTID = 0x191E,
- /* Not supported yet */
- WMI_PS_MID_CFG_EVENTID = 0x191F,
- /* Not supported yet */
- WMI_PS_MID_CFG_READ_EVENTID = 0x1920,
WMI_RS_CFG_DONE_EVENTID = 0x1921,
WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922,
WMI_AOA_MEAS_EVENTID = 0x1923,
@@ -1123,14 +1322,17 @@
WMI_GET_MGMT_RETRY_LIMIT_EVENTID = 0x1931,
WMI_SET_THERMAL_THROTTLING_CFG_EVENTID = 0x1940,
WMI_GET_THERMAL_THROTTLING_CFG_EVENTID = 0x1941,
+ /* return the Power Save profile */
+ WMI_PS_DEV_PROFILE_CFG_READ_EVENTID = 0x1942,
WMI_TOF_SESSION_END_EVENTID = 0x1991,
WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992,
WMI_TOF_SET_LCR_EVENTID = 0x1993,
WMI_TOF_SET_LCI_EVENTID = 0x1994,
WMI_TOF_FTM_PER_DEST_RES_EVENTID = 0x1995,
- WMI_TOF_CHANNEL_INFO_EVENTID = 0x1996,
+ WMI_TOF_CFG_RESPONDER_EVENTID = 0x1996,
WMI_TOF_SET_TX_RX_OFFSET_EVENTID = 0x1997,
WMI_TOF_GET_TX_RX_OFFSET_EVENTID = 0x1998,
+ WMI_TOF_CHANNEL_INFO_EVENTID = 0x1999,
WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A0,
WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID = 0x19A1,
WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID = 0x19A2,
@@ -1139,12 +1341,18 @@
WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5,
WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6,
WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7,
+ WMI_SCHEDULING_SCHEME_EVENTID = 0x1A01,
+ WMI_FIXED_SCHEDULING_CONFIG_COMPLETE_EVENTID = 0x1A02,
+ WMI_ENABLE_FIXED_SCHEDULING_COMPLETE_EVENTID = 0x1A03,
+ WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_EVENTID = 0x1A04,
+ WMI_SET_LONG_RANGE_CONFIG_COMPLETE_EVENTID = 0x1A05,
WMI_SET_CHANNEL_EVENTID = 0x9000,
WMI_ASSOC_REQ_EVENTID = 0x9001,
WMI_EAPOL_RX_EVENTID = 0x9002,
WMI_MAC_ADDR_RESP_EVENTID = 0x9003,
WMI_FW_VER_EVENTID = 0x9004,
WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005,
+ WMI_COMMAND_NOT_SUPPORTED_EVENTID = 0xFFFF,
};
/* Events data structures */
@@ -1201,7 +1409,7 @@
__le32 bl_minor;
__le32 bl_subminor;
__le32 bl_build;
- /* The number of entries in the FW capabilies array */
+ /* The number of entries in the FW capabilities array */
u8 fw_capabilities_len;
u8 reserved[3];
/* FW capabilities info
@@ -1246,7 +1454,9 @@
__le32 board_file_platform_type;
/* board file version */
__le32 board_file_version;
- __le32 reserved[2];
+ /* enabled XIFs bit vector */
+ __le32 enabled_xif_vector;
+ __le32 reserved;
} __packed;
/* WMI_GET_BASEBAND_TYPE_EVENTID */
@@ -1300,6 +1510,7 @@
/* enum wmi_phy_capability */
u8 phy_capability;
u8 numof_additional_mids;
+ /* rfc read calibration result. 5..15 */
u8 rfc_read_calib_result;
u8 reserved[3];
} __packed;
@@ -1580,7 +1791,7 @@
u8 reserved[3];
} __packed;
-/* WMI_CORR_MEASURE_EVENTID */
+/* WMI_CORR_MEASURE_EVENTID - deprecated */
struct wmi_corr_measure_event {
/* signed */
__le32 i;
@@ -1612,25 +1823,29 @@
__le16 stype;
__le16 status;
__le32 len;
- /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */
+ /* Not resolved when == 0xFFFFFFFF == > Broadcast to all MIDS */
u8 qid;
- /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */
+ /* Not resolved when == 0xFFFFFFFF == > Broadcast to all MIDS */
u8 mid;
u8 cid;
/* From Radio MNGR */
u8 channel;
} __packed;
-/* wmi_otp_read_write_cmd */
-struct wmi_otp_read_write_cmd {
- __le32 addr;
- __le32 size;
- u8 values[0];
+/* EVENT: WMI_RF_XPM_READ_RESULT_EVENTID */
+struct wmi_rf_xpm_read_result_event {
+ /* enum wmi_fw_status_e - success=0 or fail=1 */
+ u8 status;
+ u8 reserved[3];
+ /* requested num_bytes of data */
+ u8 data_bytes[0];
} __packed;
-/* WMI_OTP_READ_RESULT_EVENTID */
-struct wmi_otp_read_result_event {
- u8 payload[0];
+/* EVENT: WMI_RF_XPM_WRITE_RESULT_EVENTID */
+struct wmi_rf_xpm_write_result_event {
+ /* enum wmi_fw_status_e - success=0 or fail=1 */
+ u8 status;
+ u8 reserved[3];
} __packed;
/* WMI_TX_MGMT_PACKET_EVENTID */
@@ -1649,6 +1864,20 @@
__le32 echoed_value;
} __packed;
+/* WMI_RF_PWR_ON_DELAY_RSP_EVENTID */
+struct wmi_rf_pwr_on_delay_rsp_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_SET_HIGH_POWER_TABLE_PARAMS_EVENTID */
+struct wmi_set_high_power_table_params_event {
+ /* wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
/* WMI_TEMP_SENSE_DONE_EVENTID
*
* Measure MAC and radio temperatures
@@ -1726,14 +1955,22 @@
u8 reserved;
} __packed;
+/* \WMI_SET_CONNECT_SNR_THR_CMDID */
+struct wmi_set_connect_snr_thr_cmd {
+ u8 enable;
+ u8 reserved;
+ /* 1/4 Db units */
+ __le16 omni_snr_thr;
+ /* 1/4 Db units */
+ __le16 direct_snr_thr;
+} __packed;
+
/* WMI_LED_CFG_DONE_EVENTID */
struct wmi_led_cfg_done_event {
/* led config status */
__le32 status;
} __packed;
-#define WMI_NUM_MCS (13)
-
/* Rate search parameters configuration per connection */
struct wmi_rs_cfg {
/* The maximal allowed PER for each MCS
@@ -1758,6 +1995,98 @@
__le32 mcs_en_vec;
} __packed;
+/* Slot types */
+enum wmi_sched_scheme_slot_type {
+ WMI_SCHED_SLOT_SP = 0x0,
+ WMI_SCHED_SLOT_CBAP = 0x1,
+ WMI_SCHED_SLOT_IDLE = 0x2,
+ WMI_SCHED_SLOT_ANNOUNCE_NO_ACK = 0x3,
+ WMI_SCHED_SLOT_DISCOVERY = 0x4,
+};
+
+enum wmi_sched_scheme_slot_flags {
+ WMI_SCHED_SCHEME_SLOT_PERIODIC = 0x1,
+};
+
+struct wmi_sched_scheme_slot {
+ /* in microsecond */
+ __le32 tbtt_offset;
+ /* wmi_sched_scheme_slot_flags */
+ u8 flags;
+ /* wmi_sched_scheme_slot_type */
+ u8 type;
+ /* in microsecond */
+ __le16 duration;
+ /* frame_exchange_sequence_duration */
+ __le16 tx_op;
+ /* time in microseconds between two consecutive slots
+ * relevant only if flag WMI_SCHED_SCHEME_SLOT_PERIODIC set
+ */
+ __le16 period;
+ /* relevant only if flag WMI_SCHED_SCHEME_SLOT_PERIODIC set
+ * number of times to repeat allocation
+ */
+ u8 num_of_blocks;
+ /* relevant only if flag WMI_SCHED_SCHEME_SLOT_PERIODIC set
+ * every idle_period allocation will be idle
+ */
+ u8 idle_period;
+ u8 src_aid;
+ u8 dest_aid;
+ __le32 reserved;
+} __packed;
+
+enum wmi_sched_scheme_flags {
+ /* should not be set when clearing scheduling scheme */
+ WMI_SCHED_SCHEME_ENABLE = 0x01,
+ WMI_SCHED_PROTECTED_SP = 0x02,
+ /* should be set only on first WMI fragment of scheme */
+ WMI_SCHED_FIRST = 0x04,
+ /* should be set only on last WMI fragment of scheme */
+ WMI_SCHED_LAST = 0x08,
+ WMI_SCHED_IMMEDIATE_START = 0x10,
+};
+
+enum wmi_sched_scheme_advertisment {
+ /* ESE is not advertised at all, STA has to be configured with WMI
+ * also
+ */
+ WMI_ADVERTISE_ESE_DISABLED = 0x0,
+ WMI_ADVERTISE_ESE_IN_BEACON = 0x1,
+ WMI_ADVERTISE_ESE_IN_ANNOUNCE_FRAME = 0x2,
+};
+
+/* WMI_SCHEDULING_SCHEME_CMD */
+struct wmi_scheduling_scheme_cmd {
+ u8 serial_num;
+ /* wmi_sched_scheme_advertisment */
+ u8 ese_advertisment;
+ /* wmi_sched_scheme_flags */
+ __le16 flags;
+ u8 num_allocs;
+ u8 reserved[3];
+ __le64 start_tbtt;
+ /* allocations list */
+ struct wmi_sched_scheme_slot allocs[WMI_SCHED_MAX_ALLOCS_PER_CMD];
+} __packed;
+
+enum wmi_sched_scheme_failure_type {
+ WMI_SCHED_SCHEME_FAILURE_NO_ERROR = 0x00,
+ WMI_SCHED_SCHEME_FAILURE_OLD_START_TSF_ERR = 0x01,
+};
+
+/* WMI_SCHEDULING_SCHEME_EVENTID */
+struct wmi_scheduling_scheme_event {
+ /* wmi_fw_status_e */
+ u8 status;
+ /* serial number given in command */
+ u8 serial_num;
+ /* wmi_sched_scheme_failure_type */
+ u8 failure_type;
+ /* alignment to 32b */
+ u8 reserved[1];
+} __packed;
+
/* WMI_RS_CFG_CMDID */
struct wmi_rs_cfg_cmd {
/* connection id */
@@ -1975,6 +2304,19 @@
WMI_PS_PROFILE_TYPE_LOW_LATENCY_PS = 0x03,
};
+/* WMI_PS_DEV_PROFILE_CFG_READ_CMDID */
+struct wmi_ps_dev_profile_cfg_read_cmd {
+ /* reserved */
+ __le32 reserved;
+} __packed;
+
+/* WMI_PS_DEV_PROFILE_CFG_READ_EVENTID */
+struct wmi_ps_dev_profile_cfg_read_event {
+ /* wmi_ps_profile_type_e */
+ u8 ps_profile;
+ u8 reserved[3];
+} __packed;
+
/* WMI_PS_DEV_PROFILE_CFG_CMDID
*
* Power save profile to be used by the device
@@ -2023,157 +2365,6 @@
WMI_PS_D3_RESP_POLICY_APPROVED = 0x02,
};
-/* Device common power save configurations */
-struct wmi_ps_dev_cfg {
- /* lowest level of PS allowed while unassociated, enum wmi_ps_level_e
- */
- u8 ps_unassoc_min_level;
- /* lowest deep sleep clock level while nonassoc, enum
- * wmi_ps_deep_sleep_clk_level_e
- */
- u8 ps_unassoc_deep_sleep_min_level;
- /* lowest level of PS allowed while associated, enum wmi_ps_level_e */
- u8 ps_assoc_min_level;
- /* lowest deep sleep clock level while assoc, enum
- * wmi_ps_deep_sleep_clk_level_e
- */
- u8 ps_assoc_deep_sleep_min_level;
- /* enum wmi_ps_deep_sleep_clk_level_e */
- u8 ps_assoc_low_latency_ds_min_level;
- /* enum wmi_ps_d3_resp_policy_e */
- u8 ps_D3_response_policy;
- /* BOOL */
- u8 ps_D3_pm_pme_enabled;
- /* BOOL */
- u8 ps_halp_enable;
- u8 ps_deep_sleep_enter_thresh_msec;
- /* BOOL */
- u8 ps_voltage_scaling_en;
-} __packed;
-
-/* WMI_PS_DEV_CFG_CMDID
- *
- * Configure common Power Save parameters of the device and all MIDs.
- *
- * Returned event:
- * - WMI_PS_DEV_CFG_EVENTID
- */
-struct wmi_ps_dev_cfg_cmd {
- /* Device Power Save configuration to be applied */
- struct wmi_ps_dev_cfg ps_dev_cfg;
- /* alignment to 32b */
- u8 reserved[2];
-} __packed;
-
-/* WMI_PS_DEV_CFG_EVENTID */
-struct wmi_ps_dev_cfg_event {
- /* wmi_ps_cfg_cmd_status_e */
- __le32 status;
-} __packed;
-
-/* WMI_PS_DEV_CFG_READ_CMDID
- *
- * request to retrieve device Power Save configuration
- * (WMI_PS_DEV_CFG_CMD params)
- *
- * Returned event:
- * - WMI_PS_DEV_CFG_READ_EVENTID
- */
-struct wmi_ps_dev_cfg_read_cmd {
- __le32 reserved;
-} __packed;
-
-/* WMI_PS_DEV_CFG_READ_EVENTID */
-struct wmi_ps_dev_cfg_read_event {
- /* wmi_ps_cfg_cmd_status_e */
- __le32 status;
- /* Retrieved device Power Save configuration (WMI_PS_DEV_CFG_CMD
- * params)
- */
- struct wmi_ps_dev_cfg dev_ps_cfg;
- /* alignment to 32b */
- u8 reserved[2];
-} __packed;
-
-/* Per Mac Power Save configurations */
-struct wmi_ps_mid_cfg {
- /* Low power RX in BTI is enabled, BOOL */
- u8 beacon_lprx_enable;
- /* Sync to sector ID enabled, BOOL */
- u8 beacon_sync_to_sectorId_enable;
- /* Low power RX in DTI is enabled, BOOL */
- u8 frame_exchange_lprx_enable;
- /* Sleep Cycle while in scheduled PS, 1-31 */
- u8 scheduled_sleep_cycle_pow2;
- /* Stay Awake for k BIs every (sleep_cycle - k) BIs, 1-31 */
- u8 scheduled_num_of_awake_bis;
- u8 am_to_traffic_load_thresh_mbp;
- u8 traffic_to_am_load_thresh_mbps;
- u8 traffic_to_am_num_of_no_traffic_bis;
- /* BOOL */
- u8 continuous_traffic_psm;
- __le16 no_traffic_to_min_usec;
- __le16 no_traffic_to_max_usec;
- __le16 snoozing_sleep_interval_milisec;
- u8 max_no_data_awake_events;
- /* Trigger WEB after k failed beacons */
- u8 num_of_failed_beacons_rx_to_trigger_web;
- /* Trigger BF after k failed beacons */
- u8 num_of_failed_beacons_rx_to_trigger_bf;
- /* Trigger SOB after k successful beacons */
- u8 num_of_successful_beacons_rx_to_trigger_sob;
-} __packed;
-
-/* WMI_PS_MID_CFG_CMDID
- *
- * Configure Power Save parameters of a specific MID.
- * These parameters are relevant for the specific BSS this MID belongs to.
- *
- * Returned event:
- * - WMI_PS_MID_CFG_EVENTID
- */
-struct wmi_ps_mid_cfg_cmd {
- /* MAC ID */
- u8 mid;
- /* mid PS configuration to be applied */
- struct wmi_ps_mid_cfg ps_mid_cfg;
-} __packed;
-
-/* WMI_PS_MID_CFG_EVENTID */
-struct wmi_ps_mid_cfg_event {
- /* MAC ID */
- u8 mid;
- /* alignment to 32b */
- u8 reserved[3];
- /* wmi_ps_cfg_cmd_status_e */
- __le32 status;
-} __packed;
-
-/* WMI_PS_MID_CFG_READ_CMDID
- *
- * request to retrieve Power Save configuration of mid
- * (WMI_PS_MID_CFG_CMD params)
- *
- * Returned event:
- * - WMI_PS_MID_CFG_READ_EVENTID
- */
-struct wmi_ps_mid_cfg_read_cmd {
- /* MAC ID */
- u8 mid;
- /* alignment to 32b */
- u8 reserved[3];
-} __packed;
-
-/* WMI_PS_MID_CFG_READ_EVENTID */
-struct wmi_ps_mid_cfg_read_event {
- /* MAC ID */
- u8 mid;
- /* Retrieved MID Power Save configuration(WMI_PS_MID_CFG_CMD params) */
- struct wmi_ps_mid_cfg mid_ps_cfg;
- /* wmi_ps_cfg_cmd_status_e */
- __le32 status;
-} __packed;
-
#define WMI_AOA_MAX_DATA_SIZE (128)
enum wmi_aoa_meas_status {
@@ -2264,6 +2455,20 @@
u8 reserved[3];
} __packed;
+/* WMI_TOF_SET_LCI_EVENTID */
+struct wmi_tof_set_lci_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
+/* WMI_TOF_SET_LCR_EVENTID */
+struct wmi_tof_set_lcr_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
/* Responder FTM Results */
struct wmi_responder_ftm_res {
u8 t1[6];
@@ -2317,10 +2522,19 @@
__le32 tsf_sync;
/* actual received ftm per burst */
u8 actual_ftm_per_burst;
- u8 reserved0[7];
+ /* Measurments are from RFs, defined by the mask */
+ __le32 meas_rf_mask;
+ u8 reserved0[3];
struct wmi_responder_ftm_res responder_ftm_res[0];
} __packed;
+/* WMI_TOF_CFG_RESPONDER_EVENTID */
+struct wmi_tof_cfg_responder_event {
+ /* enum wmi_fw_status */
+ u8 status;
+ u8 reserved[3];
+} __packed;
+
enum wmi_tof_channel_info_type {
WMI_TOF_CHANNEL_INFO_AOA = 0x00,
WMI_TOF_CHANNEL_INFO_LCI = 0x01,
@@ -2357,12 +2571,15 @@
struct wmi_tof_get_tx_rx_offset_event {
/* enum wmi_fw_status */
u8 status;
- u8 reserved1[3];
+ /* RF index used to read the offsets */
+ u8 rf_index;
+ u8 reserved1[2];
/* TX delay offset */
__le32 tx_offset;
/* RX delay offset */
__le32 rx_offset;
- __le32 reserved2[2];
+ /* Offset to strongest tap of CIR */
+ __le32 precursor;
} __packed;
/* Result status codes for WMI commands */
@@ -2625,4 +2842,23 @@
u8 reserved[3];
} __packed;
+/* WMI_SET_SILENT_RSSI_TABLE_DONE_EVENTID */
+struct wmi_set_silent_rssi_table_done_event {
+ /* enum wmi_silent_rssi_status */
+ __le32 status;
+ /* enum wmi_silent_rssi_table */
+ __le32 table;
+} __packed;
+
+/* \WMI_COMMAND_NOT_SUPPORTED_EVENTID */
+struct wmi_command_not_supported_event {
+ /* device id */
+ u8 mid;
+ u8 reserved0;
+ __le16 command_id;
+ /* for UT command only, otherwise reserved */
+ __le16 command_subtype;
+ __le16 reserved1;
+} __packed;
+
#endif /* __WILOCITY_WMI_H__ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 02c5991..26d5f5e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -2683,6 +2683,21 @@
return 0;
}
+ if (in->client == IPA_CLIENT_APPS_WAN_PROD) {
+ sys->policy = IPA_POLICY_INTR_MODE;
+ sys->use_comm_evt_ring = true;
+ INIT_WORK(&sys->work, ipa3_send_nop_desc);
+
+ /*
+ * enable source notification status for exception packets
+ * (i.e. QMAP commands) to be routed to modem.
+ */
+ sys->ep->status.status_en = true;
+ sys->ep->status.status_ep =
+ ipa3_get_ep_mapping(IPA_CLIENT_Q6_WAN_CONS);
+ return 0;
+ }
+
if (IPA_CLIENT_IS_MEMCPY_DMA_PROD(in->client)) {
sys->policy = IPA_POLICY_NOINTR_MODE;
return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c
index 6d82da2..d69d6ae 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c
@@ -336,7 +336,7 @@
ipa3_process_interrupts(true);
IPADBG_LOW("Exit\n");
- ipa3_dec_client_disable_clks(&log_info);
+ ipa3_dec_client_disable_clks_no_block(&log_info);
return IRQ_HANDLED;
}
/**
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index b119a69..48be199 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1086,7 +1086,6 @@
int ret = 0;
bool qmap_check;
struct ipa3_wwan_private *wwan_ptr = netdev_priv(dev);
- struct ipa_tx_meta meta;
if (skb->protocol != htons(ETH_P_MAP)) {
IPAWANDBG_LOW
@@ -1142,17 +1141,11 @@
}
/* IPA_RM checking end */
- if (RMNET_MAP_GET_CD_BIT(skb)) {
- memset(&meta, 0, sizeof(meta));
- meta.pkt_init_dst_ep_valid = true;
- meta.pkt_init_dst_ep_remote = true;
- meta.pkt_init_dst_ep =
- ipa3_get_ep_mapping(IPA_CLIENT_Q6_WAN_CONS);
- ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, &meta);
- } else {
- ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, NULL);
- }
-
+ /*
+ * both data packets and command will be routed to
+ * IPA_CLIENT_Q6_WAN_CONS based on status configuration
+ */
+ ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, NULL);
if (ret) {
ret = NETDEV_TX_BUSY;
goto out;
@@ -1373,9 +1366,7 @@
}
if ((e->u.data) & RMNET_IOCTL_EGRESS_FORMAT_AGGREGATION) {
- IPAWANERR("WAN UL Aggregation not supported!!\n");
- WARN_ON(1);
- return -EINVAL;
+ IPAWANDBG("WAN UL Aggregation enabled\n");
ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR;
ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr = IPA_QCMAP;
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index a013edd..b929d8b 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -261,6 +261,8 @@
POWER_SUPPLY_ATTR(low_power),
POWER_SUPPLY_ATTR(temp_cool),
POWER_SUPPLY_ATTR(temp_warm),
+ POWER_SUPPLY_ATTR(temp_cold),
+ POWER_SUPPLY_ATTR(temp_hot),
POWER_SUPPLY_ATTR(system_temp_level),
POWER_SUPPLY_ATTR(resistance),
POWER_SUPPLY_ATTR(resistance_capacitive),
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index c793ee5..271c523 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -105,7 +105,7 @@
};
/* JEITA */
-enum {
+enum jeita_levels {
JEITA_COLD = 0,
JEITA_COOL,
JEITA_WARM,
@@ -252,6 +252,7 @@
struct fg_dt_props {
bool force_load_profile;
bool hold_soc_while_full;
+ bool linearize_soc;
bool auto_recharge_soc;
int cutoff_volt_mv;
int empty_volt_mv;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 6f615e4..5e346dc 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -576,6 +576,41 @@
return 0;
}
+static int fg_get_jeita_threshold(struct fg_chip *chip,
+ enum jeita_levels level, int *temp_decidegC)
+{
+ int rc;
+ u8 val;
+ u16 reg;
+
+ switch (level) {
+ case JEITA_COLD:
+ reg = BATT_INFO_JEITA_TOO_COLD(chip);
+ break;
+ case JEITA_COOL:
+ reg = BATT_INFO_JEITA_COLD(chip);
+ break;
+ case JEITA_WARM:
+ reg = BATT_INFO_JEITA_HOT(chip);
+ break;
+ case JEITA_HOT:
+ reg = BATT_INFO_JEITA_TOO_HOT(chip);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rc = fg_read(chip, reg, &val, 1);
+ if (rc < 0) {
+ pr_err("Error in reading jeita level %d, rc=%d\n", level, rc);
+ return rc;
+ }
+
+ /* Resolution is 0.5C. Base is -30C. */
+ *temp_decidegC = (((5 * val) / 10) - 30) * 10;
+ return 0;
+}
+
#define BATT_TEMP_NUMR 1
#define BATT_TEMP_DENR 1
static int fg_get_battery_temp(struct fg_chip *chip, int *val)
@@ -838,7 +873,7 @@
if (rc < 0)
return rc;
- if (chip->delta_soc > 0)
+ if (chip->dt.linearize_soc && chip->delta_soc > 0)
*val = chip->maint_soc;
else
*val = msoc;
@@ -978,12 +1013,6 @@
return 0;
}
-static inline void get_temp_setpoint(int threshold, u8 *val)
-{
- /* Resolution is 0.5C. Base is -30C. */
- *val = DIV_ROUND_CLOSEST((threshold + 30) * 10, 5);
-}
-
static inline void get_batt_temp_delta(int delta, u8 *val)
{
switch (delta) {
@@ -1658,12 +1687,38 @@
return 0;
}
+static int fg_configure_full_soc(struct fg_chip *chip, int bsoc)
+{
+ int rc;
+ u8 full_soc[2] = {0xFF, 0xFF};
+
+ /*
+ * Once SOC masking condition is cleared, FULL_SOC and MONOTONIC_SOC
+ * needs to be updated to reflect the same. Write battery SOC to
+ * FULL_SOC and write a full value to MONOTONIC_SOC.
+ */
+ rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET,
+ (u8 *)&bsoc, 2, FG_IMA_ATOMIC);
+ if (rc < 0) {
+ pr_err("failed to write full_soc rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
+ full_soc, 2, FG_IMA_ATOMIC);
+ if (rc < 0) {
+ pr_err("failed to write monotonic_soc rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
#define AUTO_RECHG_VOLT_LOW_LIMIT_MV 3700
static int fg_charge_full_update(struct fg_chip *chip)
{
union power_supply_propval prop = {0, };
int rc, msoc, bsoc, recharge_soc, msoc_raw;
- u8 full_soc[2] = {0xFF, 0xFF};
if (!chip->dt.hold_soc_while_full)
return 0;
@@ -1722,24 +1777,24 @@
fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
msoc);
}
- } else if (msoc_raw < recharge_soc && chip->charge_full) {
- chip->delta_soc = FULL_CAPACITY - msoc;
+ } else if (msoc_raw <= recharge_soc && chip->charge_full) {
+ if (chip->dt.linearize_soc) {
+ chip->delta_soc = FULL_CAPACITY - msoc;
- /*
- * We're spreading out the delta SOC over every 10% change
- * in monotonic SOC. We cannot spread more than 9% in the
- * range of 0-100 skipping the first 10%.
- */
- if (chip->delta_soc > 9) {
- chip->delta_soc = 0;
- chip->maint_soc = 0;
- } else {
- chip->maint_soc = FULL_CAPACITY;
- chip->last_msoc = msoc;
+ /*
+ * We're spreading out the delta SOC over every 10%
+ * change in monotonic SOC. We cannot spread more than
+ * 9% in the range of 0-100 skipping the first 10%.
+ */
+ if (chip->delta_soc > 9) {
+ chip->delta_soc = 0;
+ chip->maint_soc = 0;
+ } else {
+ chip->maint_soc = FULL_CAPACITY;
+ chip->last_msoc = msoc;
+ }
}
- chip->charge_full = false;
-
/*
* Raise the recharge voltage so that VBAT_LT_RECHG signal
* will be asserted soon as battery SOC had dropped below
@@ -1752,35 +1807,23 @@
rc);
goto out;
}
+
+ /*
+ * If charge_done is still set, wait for recharging or
+ * discharging to happen.
+ */
+ if (chip->charge_done)
+ goto out;
+
+ rc = fg_configure_full_soc(chip, bsoc);
+ if (rc < 0)
+ goto out;
+
+ chip->charge_full = false;
fg_dbg(chip, FG_STATUS, "msoc_raw = %d bsoc: %d recharge_soc: %d delta_soc: %d\n",
msoc_raw, bsoc >> 8, recharge_soc, chip->delta_soc);
- } else {
- goto out;
}
- if (!chip->charge_full)
- goto out;
-
- /*
- * During JEITA conditions, charge_full can happen early. FULL_SOC
- * and MONOTONIC_SOC needs to be updated to reflect the same. Write
- * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
- */
- rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
- FG_IMA_ATOMIC);
- if (rc < 0) {
- pr_err("failed to write full_soc rc=%d\n", rc);
- goto out;
- }
-
- rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
- full_soc, 2, FG_IMA_ATOMIC);
- if (rc < 0) {
- pr_err("failed to write monotonic_soc rc=%d\n", rc);
- goto out;
- }
-
- fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
out:
mutex_unlock(&chip->charge_full_lock);
return rc;
@@ -1863,6 +1906,44 @@
return 0;
}
+static int fg_set_jeita_threshold(struct fg_chip *chip,
+ enum jeita_levels level, int temp_decidegC)
+{
+ int rc;
+ u8 val;
+ u16 reg;
+
+ if (temp_decidegC < -300 || temp_decidegC > 970)
+ return -EINVAL;
+
+ /* Resolution is 0.5C. Base is -30C. */
+ val = DIV_ROUND_CLOSEST(((temp_decidegC / 10) + 30) * 10, 5);
+ switch (level) {
+ case JEITA_COLD:
+ reg = BATT_INFO_JEITA_TOO_COLD(chip);
+ break;
+ case JEITA_COOL:
+ reg = BATT_INFO_JEITA_COLD(chip);
+ break;
+ case JEITA_WARM:
+ reg = BATT_INFO_JEITA_HOT(chip);
+ break;
+ case JEITA_HOT:
+ reg = BATT_INFO_JEITA_TOO_HOT(chip);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rc = fg_write(chip, reg, &val, 1);
+ if (rc < 0) {
+ pr_err("Error in setting jeita level %d, rc=%d\n", level, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int fg_set_constant_chg_voltage(struct fg_chip *chip, int volt_uv)
{
u8 buf[2];
@@ -3137,6 +3218,9 @@
{
int rc = 0, msoc;
+ if (!chip->dt.linearize_soc)
+ return 0;
+
mutex_lock(&chip->charge_full_lock);
if (chip->delta_soc <= 0)
goto out;
@@ -3365,6 +3449,9 @@
case POWER_SUPPLY_PROP_CAPACITY:
rc = fg_get_prop_capacity(chip, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_CAPACITY_RAW:
+ rc = fg_get_msoc_raw(chip, &pval->intval);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
if (chip->battery_missing)
pval->intval = 3700000;
@@ -3377,6 +3464,34 @@
case POWER_SUPPLY_PROP_TEMP:
rc = fg_get_battery_temp(chip, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_COLD_TEMP:
+ rc = fg_get_jeita_threshold(chip, JEITA_COLD, &pval->intval);
+ if (rc < 0) {
+ pr_err("Error in reading jeita_cold, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ rc = fg_get_jeita_threshold(chip, JEITA_COOL, &pval->intval);
+ if (rc < 0) {
+ pr_err("Error in reading jeita_cool, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ rc = fg_get_jeita_threshold(chip, JEITA_WARM, &pval->intval);
+ if (rc < 0) {
+ pr_err("Error in reading jeita_warm, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_HOT_TEMP:
+ rc = fg_get_jeita_threshold(chip, JEITA_HOT, &pval->intval);
+ if (rc < 0) {
+ pr_err("Error in reading jeita_hot, rc=%d\n", rc);
+ return rc;
+ }
+ break;
case POWER_SUPPLY_PROP_RESISTANCE:
rc = fg_get_battery_resistance(chip, &pval->intval);
break;
@@ -3500,6 +3615,48 @@
return -EINVAL;
}
break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ if (chip->cl.active) {
+ pr_warn("Capacity learning active!\n");
+ return 0;
+ }
+ if (pval->intval <= 0 || pval->intval > chip->cl.nom_cap_uah) {
+ pr_err("charge_full is out of bounds\n");
+ return -EINVAL;
+ }
+ chip->cl.learned_cc_uah = pval->intval;
+ rc = fg_save_learned_cap_to_sram(chip);
+ if (rc < 0)
+ pr_err("Error in saving learned_cc_uah, rc=%d\n", rc);
+ break;
+ case POWER_SUPPLY_PROP_COLD_TEMP:
+ rc = fg_set_jeita_threshold(chip, JEITA_COLD, pval->intval);
+ if (rc < 0) {
+ pr_err("Error in writing jeita_cold, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ rc = fg_set_jeita_threshold(chip, JEITA_COOL, pval->intval);
+ if (rc < 0) {
+ pr_err("Error in writing jeita_cool, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ rc = fg_set_jeita_threshold(chip, JEITA_WARM, pval->intval);
+ if (rc < 0) {
+ pr_err("Error in writing jeita_warm, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+ case POWER_SUPPLY_PROP_HOT_TEMP:
+ rc = fg_set_jeita_threshold(chip, JEITA_HOT, pval->intval);
+ if (rc < 0) {
+ pr_err("Error in writing jeita_hot, rc=%d\n", rc);
+ return rc;
+ }
+ break;
default:
break;
}
@@ -3515,6 +3672,11 @@
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
case POWER_SUPPLY_PROP_CC_STEP:
case POWER_SUPPLY_PROP_CC_STEP_SEL:
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_COLD_TEMP:
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ case POWER_SUPPLY_PROP_HOT_TEMP:
return 1;
default:
break;
@@ -3555,7 +3717,12 @@
static enum power_supply_property fg_psy_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_RAW,
POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_COLD_TEMP,
+ POWER_SUPPLY_PROP_COOL_TEMP,
+ POWER_SUPPLY_PROP_WARM_TEMP,
+ POWER_SUPPLY_PROP_HOT_TEMP,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_OCV,
POWER_SUPPLY_PROP_CURRENT_NOW,
@@ -3734,29 +3901,29 @@
}
}
- get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COLD], &val);
- rc = fg_write(chip, BATT_INFO_JEITA_TOO_COLD(chip), &val, 1);
+ rc = fg_set_jeita_threshold(chip, JEITA_COLD,
+ chip->dt.jeita_thresholds[JEITA_COLD] * 10);
if (rc < 0) {
pr_err("Error in writing jeita_cold, rc=%d\n", rc);
return rc;
}
- get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_COOL], &val);
- rc = fg_write(chip, BATT_INFO_JEITA_COLD(chip), &val, 1);
+ rc = fg_set_jeita_threshold(chip, JEITA_COOL,
+ chip->dt.jeita_thresholds[JEITA_COOL] * 10);
if (rc < 0) {
pr_err("Error in writing jeita_cool, rc=%d\n", rc);
return rc;
}
- get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_WARM], &val);
- rc = fg_write(chip, BATT_INFO_JEITA_HOT(chip), &val, 1);
+ rc = fg_set_jeita_threshold(chip, JEITA_WARM,
+ chip->dt.jeita_thresholds[JEITA_WARM] * 10);
if (rc < 0) {
pr_err("Error in writing jeita_warm, rc=%d\n", rc);
return rc;
}
- get_temp_setpoint(chip->dt.jeita_thresholds[JEITA_HOT], &val);
- rc = fg_write(chip, BATT_INFO_JEITA_TOO_HOT(chip), &val, 1);
+ rc = fg_set_jeita_threshold(chip, JEITA_HOT,
+ chip->dt.jeita_thresholds[JEITA_HOT] * 10);
if (rc < 0) {
pr_err("Error in writing jeita_hot, rc=%d\n", rc);
return rc;
@@ -4680,6 +4847,9 @@
chip->dt.hold_soc_while_full = of_property_read_bool(node,
"qcom,hold-soc-while-full");
+ chip->dt.linearize_soc = of_property_read_bool(node,
+ "qcom,linearize-soc");
+
rc = fg_parse_ki_coefficients(chip);
if (rc < 0)
pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
@@ -5002,6 +5172,29 @@
return 0;
}
+static void fg_gen3_shutdown(struct platform_device *pdev)
+{
+ struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
+ int rc, bsoc;
+
+ if (chip->charge_full) {
+ rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
+ if (rc < 0) {
+ pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
+ return;
+ }
+
+ /* We need 2 most significant bytes here */
+ bsoc = (u32)bsoc >> 16;
+
+ rc = fg_configure_full_soc(chip, bsoc);
+ if (rc < 0) {
+ pr_err("Error in configuring full_soc, rc=%d\n", rc);
+ return;
+ }
+ }
+}
+
static const struct of_device_id fg_gen3_match_table[] = {
{.compatible = FG_GEN3_DEV_NAME},
{},
@@ -5016,6 +5209,7 @@
},
.probe = fg_gen3_probe,
.remove = fg_gen3_remove,
+ .shutdown = fg_gen3_shutdown,
};
static int __init fg_gen3_init(void)
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 5304405..6abbaeb 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -795,6 +795,7 @@
*************************/
static enum power_supply_property smb2_dc_props[] = {
+ POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -810,6 +811,9 @@
int rc = 0;
switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+ val->intval = get_effective_result(chg->dc_suspend_votable);
+ break;
case POWER_SUPPLY_PROP_PRESENT:
rc = smblib_get_prop_dc_present(chg, val);
break;
@@ -841,6 +845,10 @@
int rc = 0;
switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_SUSPEND:
+ rc = vote(chg->dc_suspend_votable, WBC_VOTER,
+ (bool)val->intval, 0);
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_prop_dc_current_max(chg, val);
break;
@@ -1199,7 +1207,7 @@
* VBUS REGULATOR REGISTRATION *
******************************/
-struct regulator_ops smb2_vbus_reg_ops = {
+static struct regulator_ops smb2_vbus_reg_ops = {
.enable = smblib_vbus_regulator_enable,
.disable = smblib_vbus_regulator_disable,
.is_enabled = smblib_vbus_regulator_is_enabled,
@@ -1241,7 +1249,7 @@
* VCONN REGULATOR REGISTRATION *
******************************/
-struct regulator_ops smb2_vconn_reg_ops = {
+static struct regulator_ops smb2_vconn_reg_ops = {
.enable = smblib_vconn_regulator_enable,
.disable = smblib_vconn_regulator_disable,
.is_enabled = smblib_vconn_regulator_is_enabled,
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 9b5b592..1b890d5 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -891,7 +891,7 @@
bool override;
/* suspend and return if 25mA or less is requested */
- if (icl_ua < USBIN_25MA)
+ if (icl_ua <= USBIN_25MA)
return smblib_set_usb_suspend(chg, true);
if (icl_ua == INT_MAX)
@@ -1017,7 +1017,7 @@
icl_ua = 0;
}
- suspend = (icl_ua < USBIN_25MA);
+ suspend = (icl_ua <= USBIN_25MA);
if (suspend)
goto suspend;
@@ -4153,7 +4153,7 @@
/* skip suspending input if its already suspended by some other voter */
usb_icl = get_effective_result(chg->usb_icl_votable);
- if ((stat & USE_USBIN_BIT) && usb_icl >= 0 && usb_icl < USBIN_25MA)
+ if ((stat & USE_USBIN_BIT) && usb_icl >= 0 && usb_icl <= USBIN_25MA)
return IRQ_HANDLED;
if (stat & USE_DCIN_BIT)
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5251b6f..80f5bca 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -67,6 +67,7 @@
#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
#define OTG_VOTER "OTG_VOTER"
#define FCC_CHANGE_VOTER "FCC_CHANGE_VOTER"
+#define WBC_VOTER "WBC_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index e0c92c6..28c3512 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -111,7 +111,7 @@
debug_mask, __debug_mask, int, 0600
);
-irqreturn_t smb138x_handle_slave_chg_state_change(int irq, void *data)
+static irqreturn_t smb138x_handle_slave_chg_state_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb138x *chip = irq_data->parent_data;
@@ -730,7 +730,7 @@
* VBUS REGULATOR REGISTRATION *
******************************/
-struct regulator_ops smb138x_vbus_reg_ops = {
+static struct regulator_ops smb138x_vbus_reg_ops = {
.enable = smblib_vbus_regulator_enable,
.disable = smblib_vbus_regulator_disable,
.is_enabled = smblib_vbus_regulator_is_enabled,
@@ -772,7 +772,7 @@
* VCONN REGULATOR REGISTRATION *
******************************/
-struct regulator_ops smb138x_vconn_reg_ops = {
+static struct regulator_ops smb138x_vconn_reg_ops = {
.enable = smblib_vconn_regulator_enable,
.disable = smblib_vconn_regulator_disable,
.is_enabled = smblib_vconn_regulator_is_enabled,
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 792ae42..32edd76 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -21,6 +21,7 @@
#define MAX_UFS_QCOM_HOSTS 2
#define MAX_U32 (~(u32)0)
#define MPHY_TX_FSM_STATE 0x41
+#define MPHY_RX_FSM_STATE 0xC1
#define TX_FSM_HIBERN8 0x1
#define HBRN8_POLL_TOUT_MS 100
#define DEFAULT_CLK_RATE_HZ 1000000
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 7c5a1bc..f5a6736 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -144,10 +144,11 @@
static int ufshcd_populate_vreg(struct device *dev, const char *name,
struct ufs_vreg **out_vreg)
{
- int ret = 0;
+ int len, ret = 0;
char prop_name[MAX_PROP_SIZE];
struct ufs_vreg *vreg = NULL;
struct device_node *np = dev->of_node;
+ const __be32 *prop;
if (!np) {
dev_err(dev, "%s: non DT initialization\n", __func__);
@@ -186,8 +187,16 @@
vreg->min_uV = UFS_VREG_VCC_1P8_MIN_UV;
vreg->max_uV = UFS_VREG_VCC_1P8_MAX_UV;
} else {
- vreg->min_uV = UFS_VREG_VCC_MIN_UV;
- vreg->max_uV = UFS_VREG_VCC_MAX_UV;
+ prop = of_get_property(np, "vcc-voltage-level", &len);
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_warn(dev, "%s vcc-voltage-level property.\n",
+ prop ? "invalid format" : "no");
+ vreg->min_uV = UFS_VREG_VCC_MIN_UV;
+ vreg->max_uV = UFS_VREG_VCC_MAX_UV;
+ } else {
+ vreg->min_uV = be32_to_cpup(&prop[0]);
+ vreg->max_uV = be32_to_cpup(&prop[1]);
+ }
}
} else if (!strcmp(name, "vccq")) {
vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c132dbc..3578b88 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -864,6 +864,24 @@
}
}
+static void ufshcd_print_fsm_state(struct ufs_hba *hba)
+{
+ int err = 0, tx_fsm_val = 0, rx_fsm_val = 0;
+
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+ UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+ &tx_fsm_val);
+ dev_err(hba->dev, "%s: TX_FSM_STATE = %u, err = %d\n", __func__,
+ tx_fsm_val, err);
+ err = ufshcd_dme_get(hba,
+ UIC_ARG_MIB_SEL(MPHY_RX_FSM_STATE,
+ UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)),
+ &rx_fsm_val);
+ dev_err(hba->dev, "%s: RX_FSM_STATE = %u, err = %d\n", __func__,
+ rx_fsm_val, err);
+}
+
static void ufshcd_print_host_state(struct ufs_hba *hba)
{
if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_HOST_STATE_EN))
@@ -888,6 +906,7 @@
hba->capabilities, hba->caps);
dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks,
hba->dev_info.quirks);
+ ufshcd_print_fsm_state(hba);
}
/**
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 43f255e..6019e4b 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -604,10 +604,11 @@
static unsigned long glink_qos_calc_rate_kBps(size_t pkt_size,
unsigned long interval_us)
{
- unsigned long rate_kBps, rem;
+ unsigned long rem;
+ uint64_t rate_kBps;
rate_kBps = pkt_size * USEC_PER_SEC;
- rem = do_div(rate_kBps, (interval_us * 1024));
+ rem = do_div(rate_kBps, interval_us * 1024);
return rate_kBps;
}
@@ -5454,8 +5455,8 @@
static void glink_scheduler_eval_prio(struct channel_ctx *ctx,
struct glink_core_xprt_ctx *xprt_ctx)
{
- unsigned long token_end_time;
- unsigned long token_consume_time, rem;
+ unsigned long token_end_time, rem;
+ uint64_t token_consume_time;
unsigned long obs_rate_kBps;
if (ctx->initial_priority == 0)
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 209209b..ecf72ca 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -152,6 +152,8 @@
#define ICNSS_QMI_ASSERT() do { } while (0)
#endif
+#define QMI_ERR_PLAT_CCPM_CLK_INIT_FAILED 0x77
+
enum icnss_debug_quirks {
HW_ALWAYS_ON,
HW_DEBUG_ENABLE,
@@ -740,7 +742,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI vbatt request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
priv->stats.vbatt_resp++;
@@ -1224,7 +1226,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI MSA Mem info request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
@@ -1296,7 +1298,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI MSA ready request rejected: result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.msa_ready_resp++;
@@ -1359,7 +1361,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI indication register request rejected, resut:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.ind_register_resp++;
@@ -1406,7 +1408,9 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI capability request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
+ if (resp.resp.error == QMI_ERR_PLAT_CCPM_CLK_INIT_FAILED)
+ icnss_pr_err("RF card Not present");
goto out;
}
@@ -1489,7 +1493,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI mode request rejected, mode:%d result:%d error:%d\n",
mode, resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.mode_resp++;
@@ -1539,7 +1543,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI config request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.cfg_resp++;
@@ -1592,7 +1596,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI INI request rejected, fw_log_mode:%d result:%d error:%d\n",
fw_log_mode, resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.ini_resp++;
@@ -1652,7 +1656,7 @@
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI athdiag read request rejected, result:%d error:%d\n",
resp->resp.result, resp->resp.error);
- ret = resp->resp.result;
+ ret = -resp->resp.result;
goto out;
}
@@ -1718,7 +1722,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI athdiag write request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
out:
@@ -1813,7 +1817,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI rejuvenate ack request rejected, result:%d error %d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
priv->stats.rejuvenate_ack_resp++;
@@ -1874,7 +1878,7 @@
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI dynamic feature mask request rejected, result:%d error %d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 739c053..3863b09 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -57,23 +57,24 @@
}
static struct llcc_slice_config sdm845_data[] = {
- SCT_ENTRY("cpuss", 1, 1, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 1),
+ SCT_ENTRY("cpuss", 1, 1, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 1),
SCT_ENTRY("vidsc0", 2, 2, 512, 2, 1, 0x0, 0x0F0, 0, 0, 1, 1, 0),
SCT_ENTRY("vidsc1", 3, 3, 512, 2, 1, 0x0, 0x0F0, 0, 0, 1, 1, 0),
- SCT_ENTRY("rotator", 4, 4, 563, 2, 1, 0x0, 0x00F, 2, 0, 1, 1, 0),
- SCT_ENTRY("voice", 5, 5, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("audio", 6, 6, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0x0F0, 0xF0F, 0, 0, 1, 1, 0),
- SCT_ENTRY("modem", 8, 8, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("compute", 10, 10, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("gpuhtw", 11, 11, 512, 1, 1, 0x0, 0xC, 0, 0, 1, 1, 0),
- SCT_ENTRY("gpu", 12, 12, 2560, 1, 0, 0xFF0, 0x3, 0, 0, 1, 1, 0),
- SCT_ENTRY("mmuhwt", 13, 13, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 0, 1),
- SCT_ENTRY("compute_dma", 15, 15, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("display", 16, 16, 3072, 1, 0, 0xFF0, 0xF, 0, 0, 1, 1, 0),
+ SCT_ENTRY("rotator", 4, 4, 563, 2, 1, 0x0, 0x00e, 2, 0, 1, 1, 0),
+ SCT_ENTRY("voice", 5, 5, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("audio", 6, 6, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0x0FC, 0xF00, 0, 0, 1, 1, 0),
+ SCT_ENTRY("modem", 8, 8, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("compute", 10, 10, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("gpuhtw", 11, 11, 512, 1, 1, 0xC, 0x0, 0, 0, 1, 1, 0),
+ SCT_ENTRY("gpu", 12, 12, 2304, 1, 0, 0xFF0, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("mmuhwt", 13, 13, 256, 2, 0, 0x0, 0x1, 0, 0, 1, 0, 1),
+ SCT_ENTRY("compute_dma", 15, 15, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("display", 16, 16, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+ SCT_ENTRY("videofw", 17, 17, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0x0, 0xF00, 0, 0, 1, 1, 0),
SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0x0, 0xF, 0, 0, 1, 1, 0),
- SCT_ENTRY("audiohw", 22, 22, 1024, 1, 1, 0xFF0, 0xF, 0, 0, 1, 1, 0),
+ SCT_ENTRY("audiohw", 22, 22, 1024, 1, 1, 0xFFC, 0x2, 0, 0, 1, 1, 0),
};
static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index ea01076..707d9e7 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -563,9 +563,6 @@
return ret;
list_for_each_entry_safe(node, node_tmp, clist, link) {
- if (unlikely(node->node_info->defer_qos))
- msm_bus_dev_init_qos(&node->dev, NULL);
-
bcm_clist_add(node);
}
@@ -668,6 +665,12 @@
kfree(cmdlist_active);
kfree(n_active);
+
+ list_for_each_entry_safe(node, node_tmp, clist, link) {
+ if (unlikely(node->node_info->defer_qos))
+ msm_bus_dev_init_qos(&node->dev, NULL);
+ }
+
exit_msm_bus_commit_data:
list_for_each_entry_safe(node, node_tmp, clist, link) {
bcm_clist_clean(node);
@@ -962,6 +965,12 @@
MSM_BUS_DBG("Device = %d", node_dev->node_info->id);
+ if (node_dev->node_info->qos_params.defer_init_qos) {
+ node_dev->node_info->qos_params.defer_init_qos = false;
+ node_dev->node_info->defer_qos = true;
+ goto exit_init_qos;
+ }
+
if (node_dev->ap_owned) {
struct msm_bus_node_device_type *bus_node_info;
@@ -1290,6 +1299,8 @@
pdata_node_info->qos_params.reg_mode.write;
node_info->qos_params.urg_fwd_en =
pdata_node_info->qos_params.urg_fwd_en;
+ node_info->qos_params.defer_init_qos =
+ pdata_node_info->qos_params.defer_init_qos;
node_info->agg_params.buswidth = pdata_node_info->agg_params.buswidth;
node_info->agg_params.agg_scheme =
pdata_node_info->agg_params.agg_scheme;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c
index 77cbbf1..32b6adf 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_of_rpmh.c
@@ -241,6 +241,8 @@
node_info->qos_params.urg_fwd_en = of_property_read_bool(dev_node,
"qcom,forwarding");
+ node_info->qos_params.defer_init_qos = of_property_read_bool(dev_node,
+ "qcom,defer-init-qos");
}
static int msm_bus_of_parse_clk_array(struct device_node *dev_node,
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
index ad04fef..a9733f1 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
@@ -136,6 +136,7 @@
struct msm_bus_noc_regulator reg;
struct msm_bus_noc_regulator_mode reg_mode;
bool urg_fwd_en;
+ bool defer_init_qos;
};
struct node_util_levels_type {
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index 519bb611..25099bb 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.c
@@ -33,7 +33,8 @@
#include <linux/termios.h>
#include <soc/qcom/glink.h>
-
+/* This Limit ensures that auto queue will not exhaust memory on remote side */
+#define MAX_PENDING_GLINK_PKT 5
#define MODULE_NAME "msm_glinkpkt"
#define DEVICE_NAME "glinkpkt"
#define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */
@@ -136,6 +137,7 @@
struct glink_link_info link_info;
void *link_state_handle;
bool link_up;
+ bool auto_intent_enabled;
};
/**
@@ -445,9 +447,26 @@
bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz)
{
struct queue_rx_intent_work *work_item;
+ int pending_pkt_count = 0;
+ struct glink_rx_pkt *pkt = NULL;
+ unsigned long flags;
+ struct glink_pkt_dev *devp = (struct glink_pkt_dev *)priv;
GLINK_PKT_INFO("%s(): QUEUE RX INTENT to receive size[%zu]\n",
__func__, sz);
+ if (devp->auto_intent_enabled) {
+ spin_lock_irqsave(&devp->pkt_list_lock, flags);
+ list_for_each_entry(pkt, &devp->pkt_list, list)
+ pending_pkt_count++;
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
+ if (pending_pkt_count > MAX_PENDING_GLINK_PKT) {
+ GLINK_PKT_ERR("%s failed, max limit reached\n",
+ __func__);
+ return false;
+ }
+ } else {
+ return false;
+ }
work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC);
if (!work_item) {
@@ -456,7 +475,7 @@
}
work_item->intent_size = sz;
- work_item->devp = (struct glink_pkt_dev *)priv;
+ work_item->devp = devp;
INIT_WORK(&work_item->work, glink_pkt_queue_rx_intent_worker);
queue_work(glink_pkt_wq, &work_item->work);
@@ -626,10 +645,11 @@
}
mutex_lock(&devp->ch_lock);
- if (!glink_rx_intent_exists(devp->handle, count)) {
+ if (!glink_pkt_read_avail(devp) &&
+ !glink_rx_intent_exists(devp->handle, count)) {
ret = glink_queue_rx_intent(devp->handle, devp, count);
if (ret) {
- GLINK_PKT_ERR("%s: failed to queue_rx_intent ret[%d]\n",
+ GLINK_PKT_ERR("%s: failed to queue intent ret[%d]\n",
__func__, ret);
mutex_unlock(&devp->ch_lock);
return ret;
@@ -914,6 +934,7 @@
case GLINK_PKT_IOCTL_QUEUE_RX_INTENT:
ret = get_user(size, (uint32_t *)arg);
GLINK_PKT_INFO("%s: intent size[%d]\n", __func__, size);
+ devp->auto_intent_enabled = false;
ret = glink_queue_rx_intent(devp->handle, devp, size);
if (ret) {
GLINK_PKT_ERR("%s: failed to QUEUE_RX_INTENT ret[%d]\n",
@@ -1182,6 +1203,7 @@
glink_pkt_link_state_cb;
devp->i = i;
devp->poll_mode = 0;
+ devp->auto_intent_enabled = true;
devp->ws_locked = 0;
devp->ch_state = GLINK_LOCAL_DISCONNECTED;
/* Default timeout for open wait is 120sec */
diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c
index f5aff4f..926016f 100644
--- a/drivers/soc/qcom/pil-msa.c
+++ b/drivers/soc/qcom/pil-msa.c
@@ -77,9 +77,6 @@
#define MSS_MAGIC 0XAABADEAD
-#define MSS_PDC_OFFSET 8
-#define MSS_PDC_MASK BIT(MSS_PDC_OFFSET)
-
/* Timeout value for MBA boot when minidump is enabled */
#define MBA_ENCRYPTION_TIMEOUT 3000
enum scm_cmd {
@@ -214,13 +211,14 @@
static void pil_mss_pdc_sync(struct q6v5_data *drv, bool pdc_sync)
{
u32 val = 0;
+ u32 mss_pdc_mask = BIT(drv->mss_pdc_offset);
if (drv->pdc_sync) {
val = readl_relaxed(drv->pdc_sync);
if (pdc_sync)
- val |= MSS_PDC_MASK;
+ val |= mss_pdc_mask;
else
- val &= ~MSS_PDC_MASK;
+ val &= ~mss_pdc_mask;
writel_relaxed(val, drv->pdc_sync);
/* Ensure PDC is written before next write */
wmb();
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index 7984dfe..e9d3534 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -293,6 +293,13 @@
if (res) {
q6->pdc_sync = devm_ioremap(&pdev->dev,
res->start, resource_size(res));
+ if (of_property_read_u32(pdev->dev.of_node,
+ "qcom,mss_pdc_offset", &q6->mss_pdc_offset)) {
+ dev_err(&pdev->dev,
+ "Offset for MSS PDC not specified\n");
+ return -EINVAL;
+ }
+
}
q6->alt_reset = NULL;
diff --git a/drivers/soc/qcom/pil-q6v5.h b/drivers/soc/qcom/pil-q6v5.h
index 9b4c811..4961b1f 100644
--- a/drivers/soc/qcom/pil-q6v5.h
+++ b/drivers/soc/qcom/pil-q6v5.h
@@ -74,6 +74,7 @@
bool restart_reg_sec;
bool override_acc;
int override_acc_1;
+ int mss_pdc_offset;
bool ahb_clk_vote;
bool mx_spike_wa;
};
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 6acb731..de3dc69 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -192,16 +192,26 @@
static void spi_setup_word_len(struct spi_geni_master *mas, u32 mode,
int bits_per_word)
{
- int pack_words = 0;
+ int pack_words = 1;
bool msb_first = (mode & SPI_LSB_FIRST) ? false : true;
u32 word_len = geni_read_reg(mas->base, SE_SPI_WORD_LEN);
+ unsigned long cfg0, cfg1;
+ /*
+ * If bits_per_word isn't a byte aligned value, set the packing to be
+ * 1 SPI word per FIFO word.
+ */
if (!(mas->tx_fifo_width % bits_per_word))
pack_words = mas->tx_fifo_width / bits_per_word;
word_len &= ~WORD_LEN_MSK;
word_len |= ((bits_per_word - MIN_WORD_LEN) & WORD_LEN_MSK);
se_config_packing(mas->base, bits_per_word, pack_words, msb_first);
geni_write_reg(word_len, mas->base, SE_SPI_WORD_LEN);
+ se_get_packing_config(bits_per_word, pack_words, msb_first,
+ &cfg0, &cfg1);
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s: cfg0 %lu cfg1 %lu bpw %d pack_words %d\n", __func__,
+ cfg0, cfg1, bits_per_word, pack_words);
}
static int setup_fifo_params(struct spi_device *spi_slv,
@@ -257,6 +267,12 @@
geni_write_reg(demux_output_inv, mas->base, SE_SPI_DEMUX_OUTPUT_INV);
geni_write_reg(clk_sel, mas->base, SE_GENI_CLK_SEL);
geni_write_reg(m_clk_cfg, mas->base, GENI_SER_M_CLK_CFG);
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s:Loopback%d demux_sel0x%x demux_op_inv 0x%x clk_cfg 0x%x\n",
+ __func__, loopback_cfg, demux_sel, demux_output_inv, m_clk_cfg);
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s:clk_sel 0x%x cpol %d cpha %d\n", __func__,
+ clk_sel, cpol, cpha);
/* Ensure message level attributes are written before returning */
mb();
setup_fifo_params_exit:
@@ -316,10 +332,7 @@
flags |= GSI_CS_TOGGLE;
word_len = xfer->bits_per_word - MIN_WORD_LEN;
- if (mas->tx_fifo_width % xfer->bits_per_word)
- pack = 0;
- else
- pack |= (GSI_TX_PACK_EN | GSI_RX_PACK_EN);
+ pack |= (GSI_TX_PACK_EN | GSI_RX_PACK_EN);
ret = get_spi_clk_cfg(mas->cur_speed_hz, mas, &idx, &div);
if (ret) {
dev_err(mas->dev, "%s:Err setting clks:%d\n", __func__, ret);
@@ -504,19 +517,26 @@
}
}
+ if (!(mas->cur_word_len % MIN_WORD_LEN)) {
+ rx_len = ((xfer->len << 3) / mas->cur_word_len);
+ } else {
+ int bytes_per_word = (mas->cur_word_len / BITS_PER_BYTE) + 1;
+
+ rx_len = (xfer->len / bytes_per_word);
+ }
+
if (xfer->tx_buf && xfer->rx_buf) {
cmd = SPI_FULL_DUPLEX;
tx_nent += 2;
rx_nent++;
- rx_len = ((xfer->len << 3) / mas->cur_word_len);
} else if (xfer->tx_buf) {
cmd = SPI_TX_ONLY;
tx_nent += 2;
+ rx_len = 0;
} else if (xfer->rx_buf) {
cmd = SPI_RX_ONLY;
tx_nent++;
rx_nent++;
- rx_len = ((xfer->len << 3) / mas->cur_word_len);
}
cs |= spi_slv->chip_select;
@@ -844,7 +864,14 @@
spi_tx_cfg &= ~CS_TOGGLE;
if (xfer->cs_change)
spi_tx_cfg |= CS_TOGGLE;
- trans_len = ((xfer->len << 3) / mas->cur_word_len) & TRANS_LEN_MSK;
+ if (!(mas->cur_word_len % MIN_WORD_LEN)) {
+ trans_len =
+ ((xfer->len << 3) / mas->cur_word_len) & TRANS_LEN_MSK;
+ } else {
+ int bytes_per_word = (mas->cur_word_len / BITS_PER_BYTE) + 1;
+
+ trans_len = (xfer->len / bytes_per_word) & TRANS_LEN_MSK;
+ }
if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
m_param |= FRAGMENTATION;
@@ -860,6 +887,9 @@
}
geni_write_reg(spi_tx_cfg, mas->base, SE_SPI_TRANS_CFG);
geni_setup_m_cmd(mas->base, m_cmd, m_param);
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s: trans_len %d xferlen%d tx_cfg 0x%x cmd 0x%x\n",
+ __func__, trans_len, xfer->len, spi_tx_cfg, m_cmd);
if (m_cmd & SPI_TX_ONLY)
geni_write_reg(mas->tx_wm, mas->base, SE_GENI_TX_WATERMARK_REG);
/* Ensure all writes are done before the WM interrupt */
@@ -872,6 +902,7 @@
reinit_completion(&mas->xfer_done);
geni_cancel_m_cmd(mas->base);
+ geni_write_reg(0, mas->base, SE_GENI_TX_WATERMARK_REG);
/* Ensure cmd cancel is written */
mb();
timeout = wait_for_completion_timeout(&mas->xfer_done, HZ);
@@ -966,12 +997,25 @@
{
int i = 0;
int tx_fifo_width = (mas->tx_fifo_width >> 3);
- int max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * tx_fifo_width;
+ int max_bytes = 0;
const u8 *tx_buf = NULL;
if (!mas->cur_xfer)
return;
+ /*
+ * For non-byte aligned bits-per-word values:
+ * Assumption is that each SPI word will be accomodated in
+ * ceil (bits_per_word / bits_per_byte)
+ * and the next SPI word starts at the next byte.
+ * In such cases, we can fit 1 SPI word per FIFO word so adjust the
+ * max byte that can be sent per IRQ accordingly.
+ */
+ if ((mas->tx_fifo_width % mas->cur_word_len))
+ max_bytes = (mas->tx_fifo_depth - mas->tx_wm) *
+ ((mas->cur_word_len / BITS_PER_BYTE) + 1);
+ else
+ max_bytes = (mas->tx_fifo_depth - mas->tx_wm) * tx_fifo_width;
tx_buf = mas->cur_xfer->tx_buf;
tx_buf += (mas->cur_xfer->len - mas->tx_rem_bytes);
max_bytes = min_t(int, mas->tx_rem_bytes, max_bytes);
@@ -979,8 +1023,13 @@
int j;
u32 fifo_word = 0;
u8 *fifo_byte;
- int bytes_to_write = min_t(int, (max_bytes - i), tx_fifo_width);
+ int bytes_per_fifo = tx_fifo_width;
+ int bytes_to_write = 0;
+ if ((mas->tx_fifo_width % mas->cur_word_len))
+ bytes_per_fifo =
+ (mas->cur_word_len / BITS_PER_BYTE) + 1;
+ bytes_to_write = min_t(int, (max_bytes - i), bytes_per_fifo);
fifo_byte = (u8 *)&fifo_word;
for (j = 0; j < bytes_to_write; j++)
fifo_byte[j] = tx_buf[i++];
@@ -1019,15 +1068,24 @@
rx_bytes += rx_last_byte_valid;
}
}
- rx_bytes += rx_wc * fifo_width;
+ if (!(mas->tx_fifo_width % mas->cur_word_len))
+ rx_bytes += rx_wc * fifo_width;
+ else
+ rx_bytes += rx_wc *
+ ((mas->cur_word_len / BITS_PER_BYTE) + 1);
rx_bytes = min_t(int, mas->rx_rem_bytes, rx_bytes);
rx_buf += (mas->cur_xfer->len - mas->rx_rem_bytes);
while (i < rx_bytes) {
u32 fifo_word = 0;
u8 *fifo_byte;
- int read_bytes = min_t(int, (rx_bytes - i), fifo_width);
+ int bytes_per_fifo = fifo_width;
+ int read_bytes = 0;
int j;
+ if ((mas->tx_fifo_width % mas->cur_word_len))
+ bytes_per_fifo =
+ (mas->cur_word_len / BITS_PER_BYTE) + 1;
+ read_bytes = min_t(int, (rx_bytes - i), bytes_per_fifo);
fifo_word = geni_read_reg(mas->base, SE_GENI_RX_FIFOn);
fifo_byte = (u8 *)&fifo_word;
for (j = 0; j < read_bytes; j++)
@@ -1039,8 +1097,14 @@
static irqreturn_t geni_spi_irq(int irq, void *dev)
{
struct spi_geni_master *mas = dev;
- u32 m_irq = geni_read_reg(mas->base, SE_GENI_M_IRQ_STATUS);
+ u32 m_irq = 0;
+ if (pm_runtime_status_suspended(dev)) {
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s: device is suspended\n", __func__);
+ goto exit_geni_spi_irq;
+ }
+ m_irq = geni_read_reg(mas->base, SE_GENI_M_IRQ_STATUS);
if ((m_irq & M_RX_FIFO_WATERMARK_EN) || (m_irq & M_RX_FIFO_LAST_EN))
geni_spi_handle_rx(mas);
@@ -1050,7 +1114,26 @@
if ((m_irq & M_CMD_DONE_EN) || (m_irq & M_CMD_CANCEL_EN) ||
(m_irq & M_CMD_ABORT_EN)) {
complete(&mas->xfer_done);
+ /*
+ * If this happens, then a CMD_DONE came before all the buffer
+ * bytes were sent out. This is unusual, log this condition and
+ * disable the WM interrupt to prevent the system from stalling
+ * due an interrupt storm.
+ * If this happens when all Rx bytes haven't been received, log
+ * the condition.
+ */
+ if (mas->tx_rem_bytes) {
+ geni_write_reg(0, mas->base, SE_GENI_TX_WATERMARK_REG);
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s:Premature Done.tx_rem%d bpw%d\n",
+ __func__, mas->tx_rem_bytes, mas->cur_word_len);
+ }
+ if (mas->rx_rem_bytes)
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "%s:Premature Done.rx_rem%d bpw%d\n",
+ __func__, mas->rx_rem_bytes, mas->cur_word_len);
}
+exit_geni_spi_irq:
geni_write_reg(m_irq, mas->base, SE_GENI_M_IRQ_CLEAR);
return IRQ_HANDLED;
}
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 101e51b..bb5f706 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -863,7 +863,7 @@
tzd = thermal_zone_get_zone_by_name(
sensor_data->virt_zone_name);
if (IS_ERR(tzd)) {
- dev_err(dev, "sens:%s not available err: %ld\n",
+ dev_dbg(dev, "sens:%s not available err: %ld\n",
sensor_data->virt_zone_name,
PTR_ERR(tzd));
return tzd;
diff --git a/drivers/thermal/qcom/msm_lmh_dcvs.c b/drivers/thermal/qcom/msm_lmh_dcvs.c
index d590d24..4e5546e 100644
--- a/drivers/thermal/qcom/msm_lmh_dcvs.c
+++ b/drivers/thermal/qcom/msm_lmh_dcvs.c
@@ -354,7 +354,13 @@
mutex_lock(&hw->access_lock);
for_each_cpu(cpu_idx, &hw->core_map) {
if (cpu_idx == cpu)
- hw->cdev_data[idx].max_freq = freq;
+ /*
+ * If there is no limits restriction for CPU scaling max
+ * frequency, vote for a very high value. This will allow
+ * the CPU to use the boost frequencies.
+ */
+ hw->cdev_data[idx].max_freq =
+ (freq == hw->max_freq) ? U32_MAX : freq;
if (max_freq > hw->cdev_data[idx].max_freq)
max_freq = hw->cdev_data[idx].max_freq;
idx++;
diff --git a/drivers/thermal/qcom/qmi_cooling.c b/drivers/thermal/qcom/qmi_cooling.c
index af82030..e1a01d8 100644
--- a/drivers/thermal/qcom/qmi_cooling.c
+++ b/drivers/thermal/qcom/qmi_cooling.c
@@ -85,6 +85,10 @@
.type = QMI_CDEV_MAX_LIMIT_TYPE,
},
{
+ .dev_name = "modem_skin",
+ .type = QMI_CDEV_MAX_LIMIT_TYPE,
+ },
+ {
.dev_name = "modem_bw",
.type = QMI_CDEV_MAX_LIMIT_TYPE,
},
diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c
index 923680a..8cb7dc3 100644
--- a/drivers/thermal/qcom/qti_virtual_sensor.c
+++ b/drivers/thermal/qcom/qti_virtual_sensor.c
@@ -46,6 +46,24 @@
"cpu3-gold-usr"},
.logic = VIRT_MAXIMUM,
},
+ {
+ .virt_zone_name = "hexa-silv-max-step",
+ .num_sensors = 6,
+ .sensor_names = {"cpu0-silver-usr",
+ "cpu1-silver-usr",
+ "cpu2-silver-usr",
+ "cpu3-silver-usr",
+ "cpu4-silver-usr",
+ "cpu5-silver-usr"},
+ .logic = VIRT_MAXIMUM,
+ },
+ {
+ .virt_zone_name = "dual-gold-max-step",
+ .num_sensors = 2,
+ .sensor_names = {"cpu0-gold-usr",
+ "cpu1-gold-usr"},
+ .logic = VIRT_MAXIMUM,
+ },
};
int qti_virtual_sensor_register(struct device *dev)
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index f9054cb..c5e2703 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -98,7 +98,9 @@
#define UART_PARAM (0x1)
/* UART DMA Rx GP_IRQ_BITS */
-#define UART_DMA_RX_ERRS (GENMASK(5, 8))
+#define UART_DMA_RX_PARITY_ERR BIT(5)
+#define UART_DMA_RX_ERRS (GENMASK(5, 6))
+#define UART_DMA_RX_BREAK (GENMASK(7, 8))
#define UART_OVERSAMPLING (32)
#define STALE_TIMEOUT (16)
@@ -125,6 +127,7 @@
} while (0)
#define DMA_RX_BUF_SIZE (2048)
+#define CONSOLE_YIELD_LEN (8 * 1024)
struct msm_geni_serial_port {
struct uart_port uport;
char name[20];
@@ -141,7 +144,8 @@
int (*handle_rx)(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last);
+ unsigned int rx_last,
+ bool drop_rx);
struct device *wrapper_dev;
struct se_geni_rsc serial_rsc;
dma_addr_t tx_dma;
@@ -159,6 +163,7 @@
unsigned int cur_baud;
int ioctl_count;
int edge_count;
+ unsigned int tx_yield_count;
};
static const struct uart_ops msm_geni_serial_pops;
@@ -167,11 +172,13 @@
static int handle_rx_console(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last);
+ unsigned int rx_last,
+ bool drop_rx);
static int handle_rx_hs(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last);
+ unsigned int rx_last,
+ bool drop_rx);
static unsigned int msm_geni_serial_tx_empty(struct uart_port *port);
static int msm_geni_serial_power_on(struct uart_port *uport);
static void msm_geni_serial_power_off(struct uart_port *uport);
@@ -681,7 +688,8 @@
static int handle_rx_console(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last)
+ unsigned int rx_last,
+ bool drop_rx)
{
int i, c;
unsigned char *rx_char;
@@ -694,6 +702,8 @@
*(msm_port->rx_fifo) =
geni_read_reg_nolog(uport->membase, SE_GENI_RX_FIFOn);
+ if (drop_rx)
+ continue;
rx_char = (unsigned char *)msm_port->rx_fifo;
if (i == (rx_fifo_wc - 1)) {
@@ -710,14 +720,16 @@
tty_insert_flip_char(tport, rx_char[c], flag);
}
}
- tty_flip_buffer_push(tport);
+ if (!drop_rx)
+ tty_flip_buffer_push(tport);
return 0;
}
#else
static int handle_rx_console(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last)
+ unsigned int rx_last,
+ bool drop_rx)
{
return -EPERM;
}
@@ -1001,7 +1013,8 @@
static int handle_rx_hs(struct uart_port *uport,
unsigned int rx_fifo_wc,
unsigned int rx_last_byte_valid,
- unsigned int rx_last)
+ unsigned int rx_last,
+ bool drop_rx)
{
unsigned char *rx_char;
struct tty_port *tport;
@@ -1016,6 +1029,8 @@
tport = &uport->state->port;
ioread32_rep((uport->membase + SE_GENI_RX_FIFOn), msm_port->rx_fifo,
rx_fifo_wc);
+ if (drop_rx)
+ return 0;
rx_char = (unsigned char *)msm_port->rx_fifo;
ret = tty_insert_flip_string(tport, rx_char, rx_bytes);
@@ -1031,7 +1046,7 @@
return ret;
}
-static int msm_geni_serial_handle_rx(struct uart_port *uport)
+static int msm_geni_serial_handle_rx(struct uart_port *uport, bool drop_rx)
{
int ret = 0;
unsigned int rx_fifo_status;
@@ -1050,7 +1065,7 @@
rx_last = rx_fifo_status & RX_LAST;
if (rx_fifo_wc)
port->handle_rx(uport, rx_fifo_wc, rx_last_byte_valid,
- rx_last);
+ rx_last, drop_rx);
return ret;
}
@@ -1070,6 +1085,14 @@
xmit->tail = (xmit->tail + msm_port->xmit_size) & (UART_XMIT_SIZE - 1);
msm_port->xmit_size = 0;
+ if (uart_console(uport) &&
+ (uport->icount.tx - msm_port->tx_yield_count) > CONSOLE_YIELD_LEN) {
+ msm_port->tx_yield_count = uport->icount.tx;
+ msm_geni_serial_stop_tx(uport);
+ uart_write_wakeup(uport);
+ goto exit_handle_tx;
+ }
+
tx_fifo_status = geni_read_reg_nolog(uport->membase,
SE_GENI_TX_FIFO_STATUS);
if (uart_circ_empty(xmit) && !tx_fifo_status) {
@@ -1128,13 +1151,13 @@
} else {
msm_port->xmit_size = xmit_size;
}
+exit_handle_tx:
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(uport);
-exit_handle_tx:
return ret;
}
-static int msm_geni_serial_handle_dma_rx(struct uart_port *uport)
+static int msm_geni_serial_handle_dma_rx(struct uart_port *uport, bool drop_rx)
{
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
unsigned int rx_bytes = 0;
@@ -1160,6 +1183,8 @@
__func__, rx_bytes);
goto exit_handle_dma_rx;
}
+ if (drop_rx)
+ goto exit_handle_dma_rx;
tport = &uport->state->port;
ret = tty_insert_flip_string(tport, (unsigned char *)(msm_port->rx_buf),
@@ -1211,6 +1236,7 @@
unsigned long flags;
unsigned int m_irq_en;
struct msm_geni_serial_port *msm_port = GET_DEV_PORT(uport);
+ bool drop_rx = false;
spin_lock_irqsave(&uport->lock, flags);
if (uart_console(uport) && uport->suspended)
@@ -1239,21 +1265,29 @@
}
if (!dma) {
- if ((s_irq_status & S_GP_IRQ_0_EN) ||
- (s_irq_status & S_GP_IRQ_1_EN) ||
- (s_irq_status & S_GP_IRQ_2_EN) ||
- (s_irq_status & S_GP_IRQ_3_EN)) {
- IPC_LOG_MSG(msm_port->ipc_log_misc,
- "%s.sirq 0x%x.\n", __func__, s_irq_status);
- goto exit_geni_serial_isr;
- }
- if ((s_irq_status & S_RX_FIFO_WATERMARK_EN) ||
- (s_irq_status & S_RX_FIFO_LAST_EN))
- msm_geni_serial_handle_rx(uport);
-
if ((m_irq_status & m_irq_en) &
(M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN))
msm_geni_serial_handle_tx(uport);
+
+ if ((s_irq_status & S_GP_IRQ_0_EN) ||
+ (s_irq_status & S_GP_IRQ_1_EN)) {
+ if (s_irq_status & S_GP_IRQ_0_EN)
+ uport->icount.parity++;
+ IPC_LOG_MSG(msm_port->ipc_log_misc,
+ "%s.sirq 0x%x parity:%d\n",
+ __func__, s_irq_status, uport->icount.parity);
+ drop_rx = true;
+ } else if ((s_irq_status & S_GP_IRQ_2_EN) ||
+ (s_irq_status & S_GP_IRQ_3_EN)) {
+ uport->icount.brk++;
+ IPC_LOG_MSG(msm_port->ipc_log_misc,
+ "%s.sirq 0x%x break:%d\n",
+ __func__, s_irq_status, uport->icount.brk);
+ }
+
+ if ((s_irq_status & S_RX_FIFO_WATERMARK_EN) ||
+ (s_irq_status & S_RX_FIFO_LAST_EN))
+ msm_geni_serial_handle_rx(uport, drop_rx);
} else {
if (dma_tx_status) {
geni_write_reg_nolog(dma_tx_status, uport->membase,
@@ -1272,13 +1306,22 @@
goto exit_geni_serial_isr;
}
if (dma_rx_status & UART_DMA_RX_ERRS) {
+ if (dma_rx_status & UART_DMA_RX_PARITY_ERR)
+ uport->icount.parity++;
IPC_LOG_MSG(msm_port->ipc_log_misc,
- "%s.Rx Errors. 0x%x.\n",
- __func__, dma_rx_status);
- goto exit_geni_serial_isr;
+ "%s.Rx Errors. 0x%x parity:%d\n",
+ __func__, dma_rx_status,
+ uport->icount.parity);
+ drop_rx = true;
+ } else if (dma_rx_status & UART_DMA_RX_BREAK) {
+ uport->icount.brk++;
+ IPC_LOG_MSG(msm_port->ipc_log_misc,
+ "%s.Rx Errors. 0x%x break:%d\n",
+ __func__, dma_rx_status,
+ uport->icount.brk);
}
if (dma_rx_status & RX_DMA_DONE)
- msm_geni_serial_handle_dma_rx(uport);
+ msm_geni_serial_handle_dma_rx(uport, drop_rx);
}
}
diff --git a/drivers/usb/gadget/function/f_ccid.h b/drivers/usb/gadget/function/f_ccid.h
index 42a7ebb..935308c 100644
--- a/drivers/usb/gadget/function/f_ccid.h
+++ b/drivers/usb/gadget/function/f_ccid.h
@@ -55,29 +55,29 @@
#define CCID_READ_DTR _IOR('C', 3, int)
struct usb_ccid_notification {
- unsigned char buf[4];
+ __u8 buf[4];
} __packed;
struct ccid_bulk_in_header {
- unsigned char bMessageType;
- unsigned long wLength;
- unsigned char bSlot;
- unsigned char bSeq;
- unsigned char bStatus;
- unsigned char bError;
- unsigned char bSpecific;
- unsigned char abData[ABDATA_SIZE];
- unsigned char bSizeToSend;
+ __u8 bMessageType;
+ __u32 wLength;
+ __u8 bSlot;
+ __u8 bSeq;
+ __u8 bStatus;
+ __u8 bError;
+ __u8 bSpecific;
+ __u8 abData[ABDATA_SIZE];
+ __u8 bSizeToSend;
} __packed;
struct ccid_bulk_out_header {
- unsigned char bMessageType;
- unsigned long wLength;
- unsigned char bSlot;
- unsigned char bSeq;
- unsigned char bSpecific_0;
- unsigned char bSpecific_1;
- unsigned char bSpecific_2;
- unsigned char APDU[ABDATA_SIZE];
+ __u8 bMessageType;
+ __u32 wLength;
+ __u8 bSlot;
+ __u8 bSeq;
+ __u8 bSpecific_0;
+ __u8 bSpecific_1;
+ __u8 bSpecific_2;
+ __u8 APDU[ABDATA_SIZE];
} __packed;
#endif
diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c
index e908ecf..be22de048 100644
--- a/drivers/usb/gadget/function/f_diag.c
+++ b/drivers/usb/gadget/function/f_diag.c
@@ -386,9 +386,11 @@
ch->priv = priv;
ch->notify = notify;
- spin_lock_irqsave(&ch_lock, flags);
- list_add_tail(&ch->list, &usb_diag_ch_list);
- spin_unlock_irqrestore(&ch_lock, flags);
+ if (!found) {
+ spin_lock_irqsave(&ch_lock, flags);
+ list_add_tail(&ch->list, &usb_diag_ch_list);
+ spin_unlock_irqrestore(&ch_lock, flags);
+ }
return ch;
}
@@ -863,6 +865,7 @@
struct diag_context *dev;
struct usb_diag_ch *_ch;
int found = 0;
+ unsigned long flags;
pr_debug("%s\n", __func__);
@@ -872,9 +875,19 @@
break;
}
}
+
if (!found) {
- pr_err("%s: unable to get diag usb channel\n", __func__);
- return ERR_PTR(-ENODEV);
+ pr_warn("%s: unable to get diag usb channel\n", __func__);
+
+ _ch = kzalloc(sizeof(*_ch), GFP_KERNEL);
+ if (_ch == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ _ch->name = name;
+
+ spin_lock_irqsave(&ch_lock, flags);
+ list_add_tail(&_ch->list, &usb_diag_ch_list);
+ spin_unlock_irqrestore(&ch_lock, flags);
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 5a96299..e8961b5 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -430,6 +430,7 @@
int num_svids;
struct vdm_tx *vdm_tx;
struct vdm_tx *vdm_tx_retry;
+ struct mutex svid_handler_lock;
struct list_head svid_handlers;
struct list_head instance;
@@ -581,10 +582,15 @@
{
struct usbpd_svid_handler *handler;
- list_for_each_entry(handler, &pd->svid_handlers, entry)
- if (svid == handler->svid)
+ mutex_lock(&pd->svid_handler_lock);
+ list_for_each_entry(handler, &pd->svid_handlers, entry) {
+ if (svid == handler->svid) {
+ mutex_unlock(&pd->svid_handler_lock);
return handler;
+ }
+ }
+ mutex_unlock(&pd->svid_handler_lock);
return NULL;
}
@@ -1412,9 +1418,11 @@
return -EINVAL;
}
- usbpd_dbg(&pd->dev, "registered handler for SVID 0x%04x\n", hdlr->svid);
-
+ usbpd_dbg(&pd->dev, "registered handler(%pK) for SVID 0x%04x\n",
+ hdlr, hdlr->svid);
+ mutex_lock(&pd->svid_handler_lock);
list_add_tail(&hdlr->entry, &pd->svid_handlers);
+ mutex_unlock(&pd->svid_handler_lock);
hdlr->request_usb_ss_lane = usbpd_release_ss_lane;
/* already connected with this SVID discovered? */
@@ -1436,7 +1444,12 @@
void usbpd_unregister_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr)
{
+
+ usbpd_dbg(&pd->dev, "unregistered handler(%pK) for SVID 0x%04x\n",
+ hdlr, hdlr->svid);
+ mutex_lock(&pd->svid_handler_lock);
list_del_init(&hdlr->entry);
+ mutex_unlock(&pd->svid_handler_lock);
}
EXPORT_SYMBOL(usbpd_unregister_svid);
@@ -1747,6 +1760,7 @@
{
struct usbpd_svid_handler *handler;
+ mutex_lock(&pd->svid_handler_lock);
list_for_each_entry(handler, &pd->svid_handlers, entry) {
if (handler->discovered) {
handler->disconnect(handler);
@@ -1754,6 +1768,7 @@
}
}
+ mutex_unlock(&pd->svid_handler_lock);
pd->vdm_state = VDM_NONE;
kfree(pd->vdm_tx_retry);
pd->vdm_tx_retry = NULL;
@@ -3853,6 +3868,7 @@
hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pd->timer.function = pd_timeout;
mutex_init(&pd->swap_lock);
+ mutex_init(&pd->svid_handler_lock);
pd->usb_psy = power_supply_get_by_name("usb");
if (!pd->usb_psy) {
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index 3ca2526..4443a29 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -24,6 +24,9 @@
#define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT)
#define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT)
+DECLARE_PER_CPU(unsigned long, hrtimer_interrupts);
+DECLARE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
+
/**
* touch_nmi_watchdog - restart NMI watchdog timeout.
*
@@ -31,8 +34,11 @@
* may be used to reset the timeout - for code which intentionally
* disables interrupts for a long time. This call is stateless.
*/
-#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
+#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR_NMI)
#include <asm/nmi.h>
+#endif
+
+#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
extern void touch_nmi_watchdog(void);
#else
static inline void touch_nmi_watchdog(void)
@@ -130,6 +136,7 @@
#define sysctl_softlockup_all_cpu_backtrace 0
#define sysctl_hardlockup_all_cpu_backtrace 0
#endif
+
extern bool is_hardlockup(void);
struct ctl_table;
extern int proc_watchdog(struct ctl_table *, int ,
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 7c5b2b4..b6c8c92 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -199,6 +199,8 @@
POWER_SUPPLY_PROP_LOW_POWER,
POWER_SUPPLY_PROP_COOL_TEMP,
POWER_SUPPLY_PROP_WARM_TEMP,
+ POWER_SUPPLY_PROP_COLD_TEMP,
+ POWER_SUPPLY_PROP_HOT_TEMP,
POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
POWER_SUPPLY_PROP_RESISTANCE,
POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e1345ec..a4ea064 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -3964,4 +3964,6 @@
void cpufreq_remove_update_util_hook(int cpu);
#endif /* CONFIG_CPU_FREQ */
+extern DEFINE_PER_CPU_READ_MOSTLY(int, sched_load_boost);
+
#endif
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 6eb24cc..a700e5f 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -47,7 +47,7 @@
#define THERMAL_WEIGHT_DEFAULT 0
/* Max sensors that can be used for a single virtual thermalzone */
-#define THERMAL_MAX_VIRT_SENSORS 5
+#define THERMAL_MAX_VIRT_SENSORS 8
/* use value, which < 0K, to indicate an invalid/uninitialized temperature */
#define THERMAL_TEMP_INVALID -274000
diff --git a/include/linux/usb/ccid_desc.h b/include/linux/usb/ccid_desc.h
index 9a0c726..2e6dbb5 100644
--- a/include/linux/usb/ccid_desc.h
+++ b/include/linux/usb/ccid_desc.h
@@ -86,27 +86,27 @@
* Table 5.1-1 Smart Card Device Class descriptors
*/
struct usb_ccid_class_descriptor {
- unsigned char bLength;
- unsigned char bDescriptorType;
- unsigned short bcdCCID;
- unsigned char bMaxSlotIndex;
- unsigned char bVoltageSupport;
- unsigned long dwProtocols;
- unsigned long dwDefaultClock;
- unsigned long dwMaximumClock;
- unsigned char bNumClockSupported;
- unsigned long dwDataRate;
- unsigned long dwMaxDataRate;
- unsigned char bNumDataRatesSupported;
- unsigned long dwMaxIFSD;
- unsigned long dwSynchProtocols;
- unsigned long dwMechanical;
- unsigned long dwFeatures;
- unsigned long dwMaxCCIDMessageLength;
- unsigned char bClassGetResponse;
- unsigned char bClassEnvelope;
- unsigned short wLcdLayout;
- unsigned char bPINSupport;
- unsigned char bMaxCCIDBusySlots;
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 bcdCCID;
+ __u8 bMaxSlotIndex;
+ __u8 bVoltageSupport;
+ __u32 dwProtocols;
+ __u32 dwDefaultClock;
+ __u32 dwMaximumClock;
+ __u8 bNumClockSupported;
+ __u32 dwDataRate;
+ __u32 dwMaxDataRate;
+ __u8 bNumDataRatesSupported;
+ __u32 dwMaxIFSD;
+ __u32 dwSynchProtocols;
+ __u32 dwMechanical;
+ __u32 dwFeatures;
+ __u32 dwMaxCCIDMessageLength;
+ __u8 bClassGetResponse;
+ __u8 bClassEnvelope;
+ __u16 wLcdLayout;
+ __u8 bPINSupport;
+ __u8 bMaxCCIDBusySlots;
} __packed;
#endif
diff --git a/include/soc/qcom/memory_dump.h b/include/soc/qcom/memory_dump.h
index 50e4b8c..e67ee0e 100644
--- a/include/soc/qcom/memory_dump.h
+++ b/include/soc/qcom/memory_dump.h
@@ -83,6 +83,7 @@
MSM_DUMP_DATA_RPM = 0xEA,
MSM_DUMP_DATA_SCANDUMP = 0xEB,
MSM_DUMP_DATA_RPMH = 0xEC,
+ MSM_DUMP_DATA_POWER_REGS = 0xED,
MSM_DUMP_DATA_TMC_ETF = 0xF0,
MSM_DUMP_DATA_TMC_REG = 0x100,
MSM_DUMP_DATA_LOG_BUF = 0x110,
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 23a8ccf..fee26a9 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -23,6 +23,7 @@
#define CAM_CCI_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 10)
#define CAM_FLASH_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 11)
#define CAM_EEPROM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 12)
+#define CAM_OIS_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 13)
/* cam_req_mgr hdl info */
#define CAM_REQ_MGR_HDL_IDX_POS 8
diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h
index ac370ba..2fe7f2b 100644
--- a/include/uapi/media/cam_sensor.h
+++ b/include/uapi/media/cam_sensor.h
@@ -7,6 +7,7 @@
#define CAM_SENSOR_PROBE_CMD (CAM_COMMON_OPCODE_MAX + 1)
#define CAM_FLASH_MAX_LED_TRIGGERS 3
+#define MAX_OIS_NAME_SIZE 32
/**
* struct cam_sensor_query_cap - capabilities info for sensor
*
@@ -75,6 +76,16 @@
} __attribute__((packed));
/**
+ * struct cam_ois_query_cap_t - capabilities info for ois
+ *
+ * @slot_info : Indicates about the slotId or cell Index
+ */
+struct cam_ois_query_cap_t {
+ uint32_t slot_info;
+ uint16_t reserved;
+} __attribute__((packed));
+
+/**
* struct cam_cmd_i2c_info - Contains slave I2C related info
*
* @slave_addr : Slave address
@@ -88,6 +99,42 @@
} __attribute__((packed));
/**
+ * struct cam_ois_opcode - Contains OIS opcode
+ *
+ * @prog : OIS FW prog register address
+ * @coeff : OIS FW coeff register address
+ * @pheripheral : OIS pheripheral
+ * @memory : OIS memory
+ */
+struct cam_ois_opcode {
+ uint32_t prog;
+ uint32_t coeff;
+ uint32_t pheripheral;
+ uint32_t memory;
+} __attribute__((packed));
+
+/**
+ * struct cam_cmd_ois_info - Contains OIS slave info
+ *
+ * @slave_addr : OIS i2c slave address
+ * @i2c_freq_mode : i2c frequency mode
+ * @ois_fw_flag : indicates if fw is present or not
+ * @is_ois_calib : indicates the calibration data is available
+ * @ois_name : OIS name
+ * @opcode : opcode
+ * @cmd_type : Explains type of command
+ */
+struct cam_cmd_ois_info {
+ uint16_t slave_addr;
+ uint8_t i2c_freq_mode;
+ uint8_t ois_fw_flag;
+ uint8_t is_ois_calib;
+ char ois_name[MAX_OIS_NAME_SIZE];
+ struct cam_ois_opcode opcode;
+ uint8_t cmd_type;
+} __attribute__((packed));
+
+/**
* struct cam_cmd_probe - Contains sensor slave info
*
* @data_type : Slave register data type
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4573d45..ccfb9bf 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3232,9 +3232,9 @@
static inline
unsigned long sum_capacity_reqs(unsigned long cfs_cap,
- struct sched_capacity_reqs *scr)
+ struct sched_capacity_reqs *scr, int cpu)
{
- unsigned long total = add_capacity_margin(cfs_cap + scr->rt);
+ unsigned long total = add_capacity_margin(cfs_cap + scr->rt, cpu);
return total += scr->dl;
}
@@ -3246,7 +3246,7 @@
struct sched_capacity_reqs *scr;
scr = &per_cpu(cpu_sched_capacity_reqs, cpu);
- if (sum_capacity_reqs(cpu_utilization, scr) < capacity_curr)
+ if (sum_capacity_reqs(cpu_utilization, scr, cpu) < capacity_curr)
return;
/*
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 116ffe4..c2372f8 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -84,6 +84,7 @@
};
static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu);
+static unsigned int stale_ns;
/************************ Governor internals ***********************/
@@ -364,7 +365,7 @@
* idle now (and clear iowait_boost for it).
*/
delta_ns = last_freq_update_time - j_sg_cpu->last_update;
- if (delta_ns > sched_ravg_window) {
+ if (delta_ns > stale_ns) {
j_sg_cpu->iowait_boost = 0;
continue;
}
@@ -716,6 +717,7 @@
policy->governor_data = sg_policy;
sg_policy->tunables = tunables;
+ stale_ns = sched_ravg_window + (sched_ravg_window >> 3);
ret = kobject_init_and_add(&tunables->attr_set.kobj, &sugov_tunables_ktype,
get_governor_parent_kobj(policy), "%s",
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index fde0639..38fa781 100755
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -89,6 +89,7 @@
unsigned int sysctl_sched_sync_hint_enable = 1;
unsigned int sysctl_sched_initial_task_util = 0;
unsigned int sysctl_sched_cstate_aware = 1;
+DEFINE_PER_CPU_READ_MOSTLY(int, sched_load_boost);
#ifdef CONFIG_SCHED_WALT
unsigned int sysctl_sched_use_walt_cpu_util = 1;
@@ -7043,7 +7044,7 @@
cpu_idle_idx = idle_get_state_idx(cpu_rq(i));
if (!need_idle &&
- add_capacity_margin(new_util_cum) <
+ add_capacity_margin(new_util_cum, i) <
capacity_curr_of(i)) {
if (sysctl_sched_cstate_aware) {
if (cpu_idle_idx < min_idle_idx) {
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 6b935e7..1bc4828 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1811,7 +1811,7 @@
cpu_idle_idx =
idle_get_state_idx(cpu_rq(cpu));
- if (add_capacity_margin(new_util_cum) <
+ if (add_capacity_margin(new_util_cum, cpu) <
capacity_curr_of(cpu)) {
if (cpu_idle_idx < best_cpu_idle_idx ||
(best_cpu != task_cpu(task) &&
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 72b79bb..0a1e62f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -29,6 +29,7 @@
#ifdef CONFIG_SCHED_WALT
extern unsigned int sched_ravg_window;
+extern unsigned int walt_cpu_util_freq_divisor;
struct walt_sched_stats {
int nr_big_tasks;
@@ -1805,47 +1806,87 @@
#endif
static inline unsigned long
-cpu_util_freq(int cpu, struct sched_walt_cpu_load *walt_load)
+cpu_util_freq_pelt(int cpu)
{
struct rq *rq = cpu_rq(cpu);
- u64 util = rq->cfs.avg.util_avg;
+ unsigned long util = rq->cfs.avg.util_avg;
unsigned long capacity = capacity_orig_of(cpu);
-#ifdef CONFIG_SCHED_WALT
- if (!walt_disabled && sysctl_sched_use_walt_cpu_util) {
+ util *= (100 + per_cpu(sched_load_boost, cpu));
+ do_div(util, 100);
- util = freq_policy_load(rq);
- util = div64_u64(util,
- sched_ravg_window >> SCHED_CAPACITY_SHIFT);
-
- if (walt_load) {
- u64 nl = cpu_rq(cpu)->nt_prev_runnable_sum +
- rq->grp_time.nt_prev_runnable_sum;
- u64 pl = rq->walt_stats.pred_demands_sum;
-
- nl = div64_u64(nl, sched_ravg_window >>
- SCHED_CAPACITY_SHIFT);
- pl = div64_u64(pl, sched_ravg_window >>
- SCHED_CAPACITY_SHIFT);
-
- walt_load->prev_window_util = util;
- walt_load->nl = nl;
- walt_load->pl = pl;
- rq->old_busy_time = util;
- rq->old_estimated_time = pl;
- walt_load->ws = rq->window_start;
- }
- }
-#endif
return (util >= capacity) ? capacity : util;
}
+
+#ifdef CONFIG_SCHED_WALT
+static inline unsigned long
+cpu_util_freq_walt(int cpu, struct sched_walt_cpu_load *walt_load)
+{
+ u64 util, util_unboosted;
+ struct rq *rq = cpu_rq(cpu);
+ unsigned long capacity = capacity_orig_of(cpu);
+ int boost;
+
+ if (walt_disabled || !sysctl_sched_use_walt_cpu_util)
+ return cpu_util_freq_pelt(cpu);
+
+ boost = per_cpu(sched_load_boost, cpu);
+ util_unboosted = util = freq_policy_load(rq);
+ util = div64_u64(util * (100 + boost),
+ walt_cpu_util_freq_divisor);
+
+ if (walt_load) {
+ u64 nl = cpu_rq(cpu)->nt_prev_runnable_sum +
+ rq->grp_time.nt_prev_runnable_sum;
+ u64 pl = rq->walt_stats.pred_demands_sum;
+
+ /* do_pl_notif() needs unboosted signals */
+ rq->old_busy_time = div64_u64(util_unboosted,
+ sched_ravg_window >>
+ SCHED_CAPACITY_SHIFT);
+ rq->old_estimated_time = div64_u64(pl, sched_ravg_window >>
+ SCHED_CAPACITY_SHIFT);
+
+ nl = div64_u64(nl * (100 + boost),
+ walt_cpu_util_freq_divisor);
+ pl = div64_u64(pl * (100 + boost),
+ walt_cpu_util_freq_divisor);
+
+ walt_load->prev_window_util = util;
+ walt_load->nl = nl;
+ walt_load->pl = pl;
+ walt_load->ws = rq->window_start;
+ }
+
+ return (util >= capacity) ? capacity : util;
+}
+
+static inline unsigned long
+cpu_util_freq(int cpu, struct sched_walt_cpu_load *walt_load)
+{
+ return cpu_util_freq_walt(cpu, walt_load);
+}
+
+#else
+
+static inline unsigned long
+cpu_util_freq(int cpu, struct sched_walt_cpu_load *walt_load)
+{
+ return cpu_util_freq_pelt(cpu);
+}
+
+#endif /* CONFIG_SCHED_WALT */
+
#endif
extern unsigned int capacity_margin_freq;
-static inline unsigned long add_capacity_margin(unsigned long cpu_capacity)
+static inline unsigned long
+add_capacity_margin(unsigned long cpu_capacity, int cpu)
{
- cpu_capacity = cpu_capacity * capacity_margin_freq;
+ cpu_capacity = cpu_capacity * capacity_margin_freq *
+ (100 + per_cpu(sched_load_boost, cpu));
+ cpu_capacity /= 100;
cpu_capacity /= SCHED_CAPACITY_SCALE;
return cpu_capacity;
}
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 60249e4..316c276 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -109,6 +109,12 @@
/* Window size (in ns) */
__read_mostly unsigned int sched_ravg_window = MIN_SCHED_RAVG_WINDOW;
+/*
+ * A after-boot constant divisor for cpu_util_freq_walt() to apply the load
+ * boost.
+ */
+__read_mostly unsigned int walt_cpu_util_freq_divisor;
+
/* Initial task load. Newly created tasks are assigned this load. */
unsigned int __read_mostly sched_init_task_load_windows;
unsigned int __read_mostly sysctl_sched_init_task_load_pct = 15;
@@ -3107,4 +3113,7 @@
clear_top_tasks_bitmap(rq->top_tasks_bitmap[j]);
}
rq->cum_window_demand = 0;
+
+ walt_cpu_util_freq_divisor =
+ (sched_ravg_window >> SCHED_CAPACITY_SHIFT) * 100;
}
diff --git a/kernel/smp.c b/kernel/smp.c
index ee80cc8..313d9a8 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -15,6 +15,7 @@
#include <linux/cpu.h>
#include <linux/sched.h>
#include <linux/hypervisor.h>
+#include <linux/suspend.h>
#include "smpboot.h"
@@ -751,7 +752,8 @@
for_each_online_cpu(cpu) {
if (cpu == smp_processor_id())
continue;
- if (!cpu_isolated(cpu))
+ if (suspend_freeze_state == FREEZE_STATE_ENTER ||
+ !cpu_isolated(cpu))
wake_up_if_idle(cpu);
}
preempt_enable();
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index e671a32..843fb50 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -201,6 +201,7 @@
bool migration_enabled;
bool nohz_active;
bool is_idle;
+ bool must_forward_clk;
DECLARE_BITMAP(pending_map, WHEEL_SIZE);
struct hlist_head vectors[WHEEL_SIZE];
} ____cacheline_aligned;
@@ -874,13 +875,19 @@
static inline void forward_timer_base(struct timer_base *base)
{
- unsigned long jnow = READ_ONCE(jiffies);
+ unsigned long jnow;
/*
- * We only forward the base when it's idle and we have a delta between
- * base clock and jiffies.
+ * We only forward the base when we are idle or have just come out of
+ * idle (must_forward_clk logic), and have a delta between base clock
+ * and jiffies. In the common case, run_timers will take care of it.
*/
- if (!base->is_idle || (long) (jnow - base->clk) < 2)
+ if (likely(!base->must_forward_clk))
+ return;
+
+ jnow = READ_ONCE(jiffies);
+ base->must_forward_clk = base->is_idle;
+ if ((long)(jnow - base->clk) < 2)
return;
/*
@@ -956,6 +963,11 @@
* same array bucket then just return:
*/
if (timer_pending(timer)) {
+ /*
+ * The downside of this optimization is that it can result in
+ * larger granularity than you would get from adding a new
+ * timer with this expiry.
+ */
if (timer->expires == expires)
return 1;
@@ -966,6 +978,7 @@
* dequeue/enqueue dance.
*/
base = lock_timer_base(timer, &flags);
+ forward_timer_base(base);
clk = base->clk;
idx = calc_wheel_index(expires, clk);
@@ -982,6 +995,7 @@
}
} else {
base = lock_timer_base(timer, &flags);
+ forward_timer_base(base);
}
ret = detach_if_pending(timer, base, false);
@@ -1009,12 +1023,10 @@
spin_lock(&base->lock);
WRITE_ONCE(timer->flags,
(timer->flags & ~TIMER_BASEMASK) | base->cpu);
+ forward_timer_base(base);
}
}
- /* Try to forward a stale timer base clock */
- forward_timer_base(base);
-
timer->expires = expires;
/*
* If 'idx' was calculated above and the base time did not advance
@@ -1130,6 +1142,7 @@
WRITE_ONCE(timer->flags,
(timer->flags & ~TIMER_BASEMASK) | cpu);
}
+ forward_timer_base(base);
debug_activate(timer, timer->expires);
internal_add_timer(base, timer);
@@ -1546,10 +1559,16 @@
if (!is_max_delta)
expires = basem + (nextevt - basej) * TICK_NSEC;
/*
- * If we expect to sleep more than a tick, mark the base idle:
+ * If we expect to sleep more than a tick, mark the base idle.
+ * Also the tick is stopped so any added timer must forward
+ * the base clk itself to keep granularity small. This idle
+ * logic is only maintained for the BASE_STD base, deferrable
+ * timers may still see large granularity skew (by design).
*/
- if ((expires - basem) > TICK_NSEC)
+ if ((expires - basem) > TICK_NSEC) {
+ base->must_forward_clk = true;
base->is_idle = true;
+ }
}
spin_unlock(&base->lock);
@@ -1659,6 +1678,19 @@
{
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
+ /*
+ * must_forward_clk must be cleared before running timers so that any
+ * timer functions that call mod_timer will not try to forward the
+ * base. idle trcking / clock forwarding logic is only used with
+ * BASE_STD timers.
+ *
+ * The deferrable base does not do idle tracking at all, so we do
+ * not forward it. This can result in very large variations in
+ * granularity for deferrable timers, but they can be deferred for
+ * long periods due to idle.
+ */
+ base->must_forward_clk = false;
+
__run_timers(base);
if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && base->nohz_active)
__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index cffb5f2..cfbf027 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -81,10 +81,10 @@
static DEFINE_PER_CPU(unsigned int, watchdog_en);
static DEFINE_PER_CPU(bool, softlockup_touch_sync);
static DEFINE_PER_CPU(bool, soft_watchdog_warn);
-static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
static DEFINE_PER_CPU(unsigned long, soft_lockup_hrtimer_cnt);
static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved);
-static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
+DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
+DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
static unsigned long soft_lockup_nmi_warn;
unsigned int __read_mostly softlockup_panic =
@@ -254,6 +254,10 @@
{
}
+void __weak watchdog_check_hardlockup_other_cpu(void)
+{
+}
+
static int watchdog_enable_all_cpus(void);
static void watchdog_disable_all_cpus(void);
@@ -271,6 +275,9 @@
/* kick the hardlockup detector */
watchdog_interrupt_count();
+ /* test for hardlockups on the next cpu */
+ watchdog_check_hardlockup_other_cpu();
+
/* kick the softlockup detector */
wake_up_process(__this_cpu_read(softlockup_watchdog));
diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
index 12b8dd6..5b2c127 100644
--- a/kernel/watchdog_hld.c
+++ b/kernel/watchdog_hld.c
@@ -18,7 +18,11 @@
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
+#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
+static cpumask_t __read_mostly watchdog_cpus;
+#else
static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
+#endif
/* boot commands */
/*
@@ -26,7 +30,10 @@
*/
unsigned int __read_mostly hardlockup_panic =
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
+
+#ifdef CONFIG_HARDLOCKUP_DETECTOR_NMI
static unsigned long hardlockup_allcpu_dumped;
+#endif
/*
* We may not want to enable hard lockup detection by default in all cases,
* for example when running the kernel as a guest on a hypervisor. In these
@@ -68,6 +75,108 @@
}
EXPORT_SYMBOL(touch_nmi_watchdog);
+#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
+static unsigned int watchdog_next_cpu(unsigned int cpu)
+{
+ cpumask_t cpus = watchdog_cpus;
+ unsigned int next_cpu;
+
+ next_cpu = cpumask_next(cpu, &cpus);
+ if (next_cpu >= nr_cpu_ids)
+ next_cpu = cpumask_first(&cpus);
+
+ if (next_cpu == cpu)
+ return nr_cpu_ids;
+
+ return next_cpu;
+}
+
+static int is_hardlockup_other_cpu(unsigned int cpu)
+{
+ unsigned long hrint = per_cpu(hrtimer_interrupts, cpu);
+
+ if (per_cpu(hrtimer_interrupts_saved, cpu) == hrint)
+ return 1;
+
+ per_cpu(hrtimer_interrupts_saved, cpu) = hrint;
+ return 0;
+}
+
+void watchdog_check_hardlockup_other_cpu(void)
+{
+ unsigned int next_cpu;
+
+ /*
+ * Test for hardlockups every 3 samples. The sample period is
+ * watchdog_thresh * 2 / 5, so 3 samples gets us back to slightly over
+ * watchdog_thresh (over by 20%).
+ */
+ if (__this_cpu_read(hrtimer_interrupts) % 3 != 0)
+ return;
+
+ /* check for a hardlockup on the next cpu */
+ next_cpu = watchdog_next_cpu(smp_processor_id());
+ if (next_cpu >= nr_cpu_ids)
+ return;
+
+ smp_rmb();
+
+ if (per_cpu(watchdog_nmi_touch, next_cpu) == true) {
+ per_cpu(watchdog_nmi_touch, next_cpu) = false;
+ return;
+ }
+
+ if (is_hardlockup_other_cpu(next_cpu)) {
+ /* only warn once */
+ if (per_cpu(hard_watchdog_warn, next_cpu) == true)
+ return;
+
+ if (hardlockup_panic)
+ panic("Watchdog detected hard LOCKUP on cpu %u",
+ next_cpu);
+ else
+ WARN(1, "Watchdog detected hard LOCKUP on cpu %u",
+ next_cpu);
+
+ per_cpu(hard_watchdog_warn, next_cpu) = true;
+ } else {
+ per_cpu(hard_watchdog_warn, next_cpu) = false;
+ }
+}
+
+int watchdog_nmi_enable(unsigned int cpu)
+{
+ /*
+ * The new cpu will be marked online before the first hrtimer interrupt
+ * runs on it. If another cpu tests for a hardlockup on the new cpu
+ * before it has run its first hrtimer, it will get a false positive.
+ * Touch the watchdog on the new cpu to delay the first check for at
+ * least 3 sampling periods to guarantee one hrtimer has run on the new
+ * cpu.
+ */
+ per_cpu(watchdog_nmi_touch, cpu) = true;
+ smp_wmb();
+ cpumask_set_cpu(cpu, &watchdog_cpus);
+ return 0;
+}
+
+void watchdog_nmi_disable(unsigned int cpu)
+{
+ unsigned int next_cpu = watchdog_next_cpu(cpu);
+
+ /*
+ * Offlining this cpu will cause the cpu before this one to start
+ * checking the one after this one. If this cpu just finished checking
+ * the next cpu and updating hrtimer_interrupts_saved, and then the
+ * previous cpu checks it within one sample period, it will trigger a
+ * false positive. Touch the watchdog on the next cpu to prevent it.
+ */
+ if (next_cpu < nr_cpu_ids)
+ per_cpu(watchdog_nmi_touch, next_cpu) = true;
+ smp_wmb();
+ cpumask_clear_cpu(cpu, &watchdog_cpus);
+}
+#else
static struct perf_event_attr wd_hw_attr = {
.type = PERF_TYPE_HARDWARE,
.config = PERF_COUNT_HW_CPU_CYCLES,
@@ -228,3 +337,4 @@
cpu0_err = 0;
}
}
+#endif
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2f9f7aa..411b383 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -779,11 +779,20 @@
The frequency of hrtimer and NMI events and the soft and hard lockup
thresholds can be controlled through the sysctl watchdog_thresh.
-config HARDLOCKUP_DETECTOR
+config HARDLOCKUP_DETECTOR_NMI
def_bool y
depends on LOCKUP_DETECTOR && !HAVE_NMI_WATCHDOG
depends on PERF_EVENTS && HAVE_PERF_EVENTS_NMI
+config HARDLOCKUP_DETECTOR_OTHER_CPU
+ def_bool y
+ depends on LOCKUP_DETECTOR && SMP
+ depends on !HARDLOCKUP_DETECTOR_NMI && !HAVE_NMI_WATCHDOG
+
+config HARDLOCKUP_DETECTOR
+ def_bool y
+ depends on HARDLOCKUP_DETECTOR_NMI || HARDLOCKUP_DETECTOR_OTHER_CPU
+
config BOOTPARAM_HARDLOCKUP_PANIC
bool "Panic (Reboot) On Hard Lockups"
depends on HARDLOCKUP_DETECTOR