summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt83
-rw-r--r--Documentation/devicetree/bindings/input/sensors/bmi160.txt27
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts4
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts4
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi35
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi66
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi157
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig11
-rw-r--r--arch/arm64/configs/msm-auto_defconfig11
-rw-r--r--drivers/gpu/msm/adreno.c3
-rw-r--r--drivers/iio/imu/Kconfig1
-rw-r--r--drivers/iio/imu/Makefile1
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/input/Makefile2
-rw-r--r--drivers/media/platform/msm/ais/msm_buf_mgr/msm_generic_buf_mgr.c19
-rw-r--r--drivers/net/wireless/cnss2/usb.c4
-rw-r--r--drivers/platform/msm/ep_pcie/ep_pcie_com.h25
-rw-r--r--drivers/platform/msm/ep_pcie/ep_pcie_core.c168
-rw-r--r--drivers/platform/msm/ep_pcie/ep_pcie_phy.c45
-rw-r--r--drivers/platform/msm/ep_pcie/ep_pcie_phy.h32
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c2
-rw-r--r--drivers/soc/qcom/hab/hab.c74
-rw-r--r--drivers/soc/qcom/hab/hab.h9
-rw-r--r--drivers/soc/qcom/hab/hab_mem_linux.c9
-rw-r--r--drivers/soc/qcom/hab/hab_mimex.c12
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c43
-rw-r--r--drivers/soc/qcom/hab/hab_open.c12
-rw-r--r--drivers/soc/qcom/hab/hab_stat.c9
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c65
-rw-r--r--drivers/soc/qcom/hab/qvm_comm.c17
-rw-r--r--drivers/soc/qcom/socinfo.c1
-rw-r--r--include/linux/habmm.h31
-rw-r--r--kernel/time/timekeeping.c31
-rw-r--r--sound/soc/soc-ops.c4
37 files changed, 885 insertions, 140 deletions
diff --git a/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt b/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt
new file mode 100644
index 000000000000..f5227841b5d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invn-iam20680.txt
@@ -0,0 +1,83 @@
+The IAM20680 sensor is 6-axis gyroscope+accelerometer combo
+device which is made by InvenSense Inc.
+
+Required properties:
+
+ - compatible : Should be "invn,iam20680".
+ - reg : the I2C address which depends on the AD0 pin.
+ - gpios : INVENSENSE GPIO in the format described by ../gpio/gpio.txt
+
+Optional properties:
+ - inven,vdd_ana-supply :
+ - inven,vcc_i2c-supply :
+ - inven,gpio_int1 :
+ - axis_map_x :
+ - axis_map_y :
+ - axis_map_z :
+ - negate_x :
+ - negate_y :
+ - negate_z :
+ - fs_range :
+ - poll_interval :
+ - min_interval :
+ - inven,secondary_reg :
+ - inven,secondary_type :
+ - inven,secondary_name :
+ - inven,secondary_axis_map_x :
+ - inven,secondary_axis_map_y :
+ - inven,secondary_axis_map_z :
+ - inven,secondary_negate_x :
+ - inven,secondary_negate_y :
+ - inven,secondary_negate_z :
+ - inven,aux_type :
+ - inven,aux_name :
+ - inven,aux_reg :
+ - inven,read_only_slave_type :
+ - inven,read_only_slave_name :
+ - inven,read_only_slave_reg :
+
+Example:
+ iam20680@69 {
+ compatible = "inven,iam20680";
+ reg = <0x69>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&int1_default>;
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <78 IRQ_TYPE_EDGE_RISING>;
+ inven,vdd_ana-supply = <&pm8941_l17>;
+ inven,vcc_i2c-supply = <&pm8941_lvs1>;
+ inven,gpio_int1 = <&msmgpio 73 0x00>;
+ axis_map_x = <1>;
+ axis_map_y = <0>;
+ axis_map_z = <2>;
+ negate_x = <1>;
+ negate_y = <0>;
+ negate_z = <0>;
+ fs_range = <0x00>;
+ poll_interval = <200>;
+ min_interval = <5>;
+ inven,secondary_reg = <0x0c>;
+ /* If no compass sensor,
+ * replace "compass" with "none"
+ */
+ inven,secondary_type = "compass";
+ inven,secondary_name = "ak09911";
+ inven,secondary_axis_map_x = <1>;
+ inven,secondary_axis_map_y = <0>;
+ inven,secondary_axis_map_z = <2>;
+ inven,secondary_negate_x = <1>;
+ inven,secondary_negate_y = <1>;
+ inven,secondary_negate_z = <1>;
+ /* If no pressure sensor,
+ * replace "pressure" with "none"
+ */
+ inven,aux_type = "pressure";
+ inven,aux_name = "bmp280";
+ inven,aux_reg = <0x76>;
+ /* If no ALS sensor
+ * replace "als" with "none"
+ */
+ inven,read_only_slave_type = "als";
+ inven,read_only_slave_name = "apds9930";
+ inven,read_only_slave_reg = <0x39>;
+ };
diff --git a/Documentation/devicetree/bindings/input/sensors/bmi160.txt b/Documentation/devicetree/bindings/input/sensors/bmi160.txt
new file mode 100644
index 000000000000..8fd43cd6e52b
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/sensors/bmi160.txt
@@ -0,0 +1,27 @@
+
+The BMI160 is a highly integrated, low power inertial measurement unit (IMU)
+that provides precise acceleration and angular rate (gyroscopic) measurement.
+
+Required properties:
+
+ - compatible : Should be "bosch-sensortec,bmi160".
+ - reg : the Chip select ID.
+ - gpios : BMI GPIO in the format described by ../gpio/gpio.txt
+
+Optional properties:
+ - bmi,init-interval:
+ - bmi,place :
+
+
+Example:
+ bmi160@68{
+ compatible = "bosch-sensortec,bmi160";
+ reg = <0x68>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bmi160_int1_default &bmi160_int2_default>;
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <78 0x2002>;
+ bmi,init-interval = <200>;
+ bmi,place = <1>;
+ bmi,gpio_irq = <&tlmm_pinmux 78 0x2002>;
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index f9097941c192..7354ff18e919 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -259,6 +259,8 @@ xes Extreme Engineering Solutions (X-ES)
xillybus Xillybus Ltd.
xlnx Xilinx
zyxel ZyXEL Communications Corp.
+bosch-sensortec» Bosch Sensortec GmbH
+inven InvenSense, Inc.
zarlink Zarlink Semiconductor
zii Zodiac Inflight Innovations
zte ZTE Corp.
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts
index 1bca588f448e..7fa5b2850635 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,7 @@
/ {
model = "Qualcomm Technologies, Inc. APQ 8096 pro AUTO CDP";
compatible = "qcom,apq8096-cdp", "qcom,apq8096", "qcom,cdp";
- qcom,msm-id = <316 0x10000>;
+ qcom,msm-id = <316 0x10000>, <387 0x10000>;
qcom,board-id = <0x03010001 0>;
};
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
index 0bb04361eabe..c2d9f6696307 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
@@ -21,7 +21,7 @@
/ {
model = "Qualcomm Technologies, Inc. APQ 8096pro V1.1 AUTO ADP LITE";
compatible = "qcom,apq8096-adp", "qcom,msm8996", "qcom,adp";
- qcom,msm-id = <316 0x10001>;
+ qcom,msm-id = <316 0x10001>, <387 0x10001>;
qcom,board-id = <0x03010019 0>;
};
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts
index 908dc4a20372..9ca38fcac0bb 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts
@@ -21,7 +21,7 @@
/ {
model = "Qualcomm Technologies, Inc. MSM 8996pro AUTO ADP";
compatible = "qcom,apq8096-adp", "qcom,msm8996", "qcom,adp";
- qcom,msm-id = <316 0x10001>;
+ qcom,msm-id = <316 0x10001>, <387 0x10001> ;
qcom,board-id = <0x02010019 0>, <0x00010001 0>;
};
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts
index e69640ddd363..422db71b26d4 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,7 +20,7 @@
/ {
model = "Qualcomm Technologies, Inc. APQ 8096 pro v1.1 AUTO CDP";
compatible = "qcom,msm8996-cdp", "qcom,msm8996", "qcom,cdp";
- qcom,msm-id = <316 0x10001>;
+ qcom,msm-id = <316 0x10001>, <387 0x10001>;
qcom,board-id = <0x03010001 0>, <0x00010001 0>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
index e6598fa2d0c5..ee42fe68f430 100644
--- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
@@ -1488,6 +1488,41 @@
};
};
+&i2c_10 {
+ bmi160@68 {
+ compatible = "bosch-sensortec,bmi160";
+ reg = <0x68>;
+ vdd-supply = <&pm8994_lvs2>;
+ vio-supply = <&pm8994_lvs2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sensor_int1_default &sensor_int2_default>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <117 0x2002>;
+ bmi,init-interval = <200>;
+ bmi,place = <1>;
+ bmi,gpio_irq = <&tlmm 117 0x2002>;
+ };
+ iam20680@69 {
+ compatible = "inven,iam20680";
+ reg = <0x69>;
+ vdd-supply = <&pm8994_lvs2>;
+ vio-supply = <&pm8994_lvs2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sensor_int1_default &sensor_int2_default>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <118 IRQ_TYPE_EDGE_RISING>;
+ axis_map_x = <1>;
+ axis_map_y = <0>;
+ axis_map_z = <2>;
+ negate_x = <1>;
+ negate_y = <0>;
+ negate_z = <0>;
+ inven,secondary_type = "none";
+ inven,aux_type = "none";
+ inven,read_only_slave_type = "none";
+ };
+};
+
&dsi_dual_jdi_video {
/delete-property/ pwms;
/delete-property/ qcom,5v-boost-gpio;
diff --git a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
index 0982ead00f8c..50b435547982 100644
--- a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
@@ -850,6 +850,58 @@
};
};
};
+ i2c_10 {
+ i2c_10_active: i2c_10_active {
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "blsp_i2c10";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
+ i2c_10_sleep: i2c_10_sleep {
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "blsp_i2c10";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ sensor_int1_default: sensor_int1_default {
+ mux {
+ pins = "gpio117";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio117";
+ drive-strength = <16>; /* 16 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
+ sensor_int2_default: sensor_int2_default {
+ mux {
+ pins = "gpio118";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio118";
+ drive-strength = <16>; /* 16 mA */
+ bias-pull-down; /* pull down */
+ };
+ };
pmx_fm_int {
fm_int_active: fm_int_active {
@@ -2839,5 +2891,19 @@
bias-pull-down; /* PULL down */
};
};
+
+ pinctrl_pps: ppsgrp {
+ mux {
+ pins = "gpio128";
+ function = "nav_dr";
+ };
+
+ config {
+ pins = "gpio128";
+ drive-strength = <16>;
+ bias-pull-down;
+ };
+ };
+
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 95b100e10e5b..ed88cfeac053 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -39,6 +39,7 @@
i2c6 = &i2c_6;
i2c7 = &i2c_7;
i2c8 = &i2c_8;
+ i2c10 = &i2c_10;
i2c12 = &i2c_12;
spi0 = &spi_0;
serial0 = &uartblsp2dm1;
@@ -387,6 +388,28 @@
clock-names = "core_clk", "iface_clk";
};
+ i2c_10: i2c@75b8000 { /* BLSP2 QUP4 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x75b8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 104 0>;
+ dmas = <&dma_blsp2 18 32 0x20000020 0x20>,
+ <&dma_blsp2 19 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <84>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup4_i2c_apps_clk>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_10_active>;
+ pinctrl-1 = <&i2c_10_sleep>;
+ };
+
i2c_12: i2c@75ba000 {
compatible = "qcom,i2c-msm-v2";
#address-cells = <1>;
@@ -2560,6 +2583,132 @@
qcom,ipa-advertise-sg-support;
};
+ pcie_ep: qcom,pcie-ep@00600000 {
+ compatible = "qcom,pcie-ep";
+
+ reg = <0x0c001000 0x1000>,
+ <0x0c000000 0xf1d>,
+ <0x0c000f20 0xa8>,
+ <0x00600000 0x2000>,
+ <0x00034000 0x4000>,
+ <0x00607000 0x1000>;
+ reg-names = "msi", "dm_core", "elbi", "parf", "phy", "mmio";
+
+ #address-cells = <0>;
+ interrupt-parent = <&pcie_ep>;
+ interrupts = <0 1 2 3 4>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 247 0
+ 1 &intc 0 0 249 0
+ 2 &intc 0 0 253 0
+ 3 &intc 0 0 254 0
+ 4 &intc 0 0 49 0>;
+
+ interrupt-names ="int_pm_turnoff", "int_dstate_change",
+ "int_link_up", "int_link_down", "int_global";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_clkreq_default &pcie0_perst_default
+ &pcie0_wake_default>;
+
+ clkreq-gpio = <&tlmm 36 0>;
+ perst-gpio = <&tlmm 35 0>;
+ wake-gpio = <&tlmm 37 0>;
+
+ gdsc-vdd-supply = <&gdsc_pcie_0>;
+ vreg-1.8-supply = <&pm8994_l12>;
+ vreg-0.9-supply = <&pm8994_l28>;
+
+ qcom,vreg-0.9-voltage-level = <925000 925000 24000>;
+
+ clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>,
+ <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_0_aux_clk>,
+ <&clock_gcc clk_gcc_pcie_clkref_clk>,
+ <&clock_gcc clk_gcc_pcie_phy_reset>,
+ <&clock_gcc clk_gcc_pcie_phy_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_pcie_phy_aux_clk>;
+
+ clock-names = "pcie_0_pipe_clk", "pcie_0_cfg_ahb_clk",
+ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
+ "pcie_0_aux_clk", "pcie_0_ldo", "pcie_0_phy_reset",
+ "pcie_0_phy_cfg_ahb_clk", "pcie_0_phy_aux_clk";
+
+ resets = <&clock_gcc PCIE_PHY_BCR>,
+ <&clock_gcc PCIE_PHY_COM_BCR>,
+ <&clock_gcc PCIE_PHY_NOCSR_COM_PHY_BCR>,
+ <&clock_gcc PCIE_0_PHY_BCR>;
+
+ reset-names = "pcie_phy_reset", "pcie_phy_com_reset",
+ "pcie_phy_nocsr_com_phy_reset","pcie_0_phy_reset";
+
+ max-clock-frequency-hz = <0>, <0>, <0>, <0>, <1010526>,
+ <0>, <0>, <0>, <0>;
+
+ qcom,msm-bus,name = "pcie-ep";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>,
+ <45 512 500 800>;
+
+ qcom,pcie-link-speed = <0>;
+ qcom,pcie-phy-ver = <4>;
+ qcom,pcie-perst-enum;
+
+ qcom,phy-status-reg = <0x448>;
+ qcom,phy-sequence = <0x400 0x01 0x00
+ 0x404 0x01 0x00
+ 0x00AC 0x00 0x00
+ 0x0034 0x18 0x00
+ 0x0174 0x30 0x00
+ 0x00B4 0x20 0x00
+ 0x1094 0x06 0x00
+ 0x00D0 0x19 0x00
+ 0x0078 0x3F 0x00
+ 0x0084 0x1A 0x00
+ 0x0090 0x00 0x00
+ 0x010C 0x00 0x00
+ 0x0108 0xFF 0x00
+ 0x019C 0x01 0x00
+ 0x018C 0x00 0x00
+ 0x0050 0x04 0x00
+ 0x004C 0xff 0x00
+ 0x00C8 0x42 0x00
+ 0x0128 0x00 0x00
+ 0x0148 0x3f 0x00
+ 0x0144 0xff 0x00
+ 0x000C 0x01 0x00
+ 0x0070 0x0f 0x00
+ 0x0048 0x0f 0x00
+ 0x1248 0x4B 0x00
+ 0x120C 0x0A 0x00
+ 0x1200 0x0A 0x00
+ 0x121C 0x04 0x00
+ 0x1210 0x04 0x00
+ 0x12D8 0x01 0x00
+ 0x12DC 0x00 0x00
+ 0x12E0 0xDB 0x00
+ 0x12D4 0x77 0x00
+ 0x130C 0x80 0x00
+ 0x1310 0x1C 0x00
+ 0x1314 0x03 0x00
+ 0x131C 0x14 0x00
+ 0x1054 0x02 0x00
+ 0x1068 0x45 0x00
+ 0x10AC 0x12 0x00
+ 0x0194 0x06 0x00
+ 0x1454 0x00 0x00
+ 0x1404 0x00 0x00
+ 0x400 0x00 0x00
+ 0x408 0x03 0x00>;
+
+ status = "disabled";
+ };
+
qcom_rng: qrng@83000 {
compatible = "qcom,msm-rng";
reg = <0x83000 0x1000>;
@@ -4018,6 +4167,14 @@
qcom,save-reg;
};
+
+ pps {
+ compatible = "pps-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pps>;
+ gpios = <&tlmm 128 0>;
+ status = "okay";
+ };
};
&gdsc_venus {
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig
index 6f631287652a..54f46ac4dbf4 100644
--- a/arch/arm64/configs/msm-auto-perf_defconfig
+++ b/arch/arm64/configs/msm-auto-perf_defconfig
@@ -317,6 +317,11 @@ CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
+CONFIG_BOSCH_DRIVER_LOG_FUNC=y
+CONFIG_SENSORS_BMA2X2=y
+CONFIG_SENSORS_BMA2X2_ENABLE_INT1=y
+CONFIG_SENSORS_BMG=y
+CONFIG_SENSORS_BMG_FIFO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
@@ -514,6 +519,7 @@ CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_TIMER_LEAP=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
@@ -576,6 +582,11 @@ CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_EXTCON=y
+CONFIG_IIO=y
+CONFIG_INV_MPU_IIO_IAM20680=y
+CONFIG_INV_MPU_IIO_I2C=y
+CONFIG_INV_MPU_IIO_SPI=y
+CONFIG_INV_TESTING=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig
index a45fc1ce832a..eb8a244aef6d 100644
--- a/arch/arm64/configs/msm-auto_defconfig
+++ b/arch/arm64/configs/msm-auto_defconfig
@@ -318,6 +318,11 @@ CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
+CONFIG_BOSCH_DRIVER_LOG_FUNC=y
+CONFIG_SENSORS_BMA2X2=y
+CONFIG_SENSORS_BMA2X2_ENABLE_INT1=y
+CONFIG_SENSORS_BMG=y
+CONFIG_SENSORS_BMG_FIFO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
@@ -520,6 +525,7 @@ CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_TIMER_LEAP=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y
CONFIG_ARM_SMMU=y
@@ -585,6 +591,11 @@ CONFIG_DEVFREQ_GOV_MEMLAT=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_EXTCON=y
+CONFIG_IIO=y
+CONFIG_INV_MPU_IIO_IAM20680=y
+CONFIG_INV_MPU_IIO_I2C=y
+CONFIG_INV_MPU_IIO_SPI=y
+CONFIG_INV_TESTING=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 9cb65033ed13..d2aa0a0f9507 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2807,7 +2807,8 @@ static void adreno_suspend_device(struct kgsl_device *device,
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
int pm_event = pm_state.event;
- adreno_dispatcher_halt(device);
+ if (device->state == KGSL_STATE_SUSPEND)
+ adreno_dispatcher_halt(device);
if ((pm_event == PM_EVENT_FREEZE) ||
(pm_event == PM_EVENT_QUIESCE) ||
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 5e610f7de5aa..903beab85e7e 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -37,6 +37,7 @@ config KMX61
be called kmx61.
source "drivers/iio/imu/inv_mpu6050/Kconfig"
+source "drivers/iio/imu/inv_mpu/Kconfig"
endmenu
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index e1e6e3d70e26..54c282cca986 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -14,5 +14,6 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += inv_mpu6050/
+obj-y += inv_mpu/
obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 2557dcda7621..5987a6c2261b 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -214,6 +214,8 @@ source "drivers/input/touchscreen/Kconfig"
source "drivers/input/misc/Kconfig"
+source "drivers/input/sensors/bmi160/Kconfig"
+
endif
menu "Hardware I/O ports"
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 2a6d05ab9170..45286b8e4769 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -28,4 +28,4 @@ obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
obj-$(CONFIG_INPUT_KEYRESET) += keyreset.o
obj-$(CONFIG_INPUT_KEYCOMBO) += keycombo.o
-
+obj-y += sensors/bmi160/
diff --git a/drivers/media/platform/msm/ais/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/ais/msm_buf_mgr/msm_generic_buf_mgr.c
index 66751b1f0657..db41cada4328 100644
--- a/drivers/media/platform/msm/ais/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/ais/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -554,15 +554,16 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
return -EINVAL;
if (!k_ioctl.ioctl_ptr)
return -EINVAL;
-
- MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr,
- sizeof(tmp));
- if (copy_from_user(&buf_info, (void __user *)tmp,
- sizeof(struct msm_buf_mngr_info))) {
- return -EFAULT;
+ if (!is_compat_task()) {
+ MSM_CAM_GET_IOCTL_ARG_PTR(&tmp,
+ &k_ioctl.ioctl_ptr, sizeof(tmp));
+ if (copy_from_user(&buf_info,
+ (void __user *)tmp,
+ sizeof(struct msm_buf_mngr_info))) {
+ return -EFAULT;
+ }
+ k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
}
- k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
-
argp = (void *)&k_ioctl;
rc = msm_cam_buf_mgr_ops(cmd, argp);
}
diff --git a/drivers/net/wireless/cnss2/usb.c b/drivers/net/wireless/cnss2/usb.c
index 60d81b10cc84..4310109987b0 100644
--- a/drivers/net/wireless/cnss2/usb.c
+++ b/drivers/net/wireless/cnss2/usb.c
@@ -108,6 +108,7 @@ int cnss_usb_dev_shutdown(struct cnss_usb_data *usb_priv)
switch (usb_priv->device_id) {
case QCN7605_COMPOSITE_DEVICE_ID:
case QCN7605_STANDALONE_DEVICE_ID:
+ cnss_usb_call_driver_remove(usb_priv);
break;
default:
cnss_pr_err("Unknown device_id found: 0x%x\n",
@@ -175,12 +176,13 @@ int cnss_usb_call_driver_remove(struct cnss_usb_data *usb_priv)
if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
+ cnss_pr_dbg("Recovery set after driver probed.Call shutdown\n");
usb_priv->driver_ops->shutdown(usb_priv->usb_intf);
} else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
+ cnss_pr_dbg("driver_ops->remove\n");
usb_priv->driver_ops->remove(usb_priv->usb_intf);
clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
}
-
return 0;
}
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 4b89c8636141..0c3fb1676eea 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -101,6 +101,14 @@
#define PCIE20_AUX_CLK_FREQ_REG 0xB40
+#define PCIE20_MHISTATUS 0x148
+#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174
+#define PCIE20_PARF_CFG_BITS 0x210
+
+#define PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3C
+#define PCIE20_DEVICE_ID_VENDOR_ID_REG 0x0
+#define PCIE20_L1_SUBSTATES_REG 0xB44
+
#define PERST_TIMEOUT_US_MIN 1000
#define PERST_TIMEOUT_US_MAX 1000
#define PERST_CHECK_MAX_COUNT 30000
@@ -126,7 +134,7 @@
#define EP_PCIE_LOG_PAGES 50
#define EP_PCIE_MAX_VREG 2
-#define EP_PCIE_MAX_CLK 6
+#define EP_PCIE_MAX_CLK 8
#define EP_PCIE_MAX_PIPE_CLK 1
#define EP_PCIE_ERROR -30655
@@ -255,6 +263,12 @@ struct ep_pcie_irq_info_t {
u32 num;
};
+struct ep_pcie_phy_info_t {
+ u32 offset;
+ u32 val;
+ u32 delay;
+};
+
/* pcie endpoint device structure */
struct ep_pcie_dev_t {
struct platform_device *pdev;
@@ -278,6 +292,9 @@ struct ep_pcie_dev_t {
u32 link_speed;
bool active_config;
bool aggregated_irq;
+ u32 phy_status_reg;
+ u32 phy_len;
+ struct ep_pcie_phy_info_t *phy_sequence;
u32 rev;
u32 phy_rev;
@@ -356,5 +373,7 @@ extern bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev);
extern void ep_pcie_reg_dump(struct ep_pcie_dev_t *dev, u32 sel, bool linkdown);
extern void ep_pcie_debugfs_init(struct ep_pcie_dev_t *ep_dev);
extern void ep_pcie_debugfs_exit(void);
-
+#ifdef CONFIG_ARCH_MSM8996
+extern void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev);
+#endif
#endif
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index f3cc96c271a7..f6d39031c5d5 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,7 +64,9 @@ static struct ep_pcie_clk_info_t
{NULL, "pcie_0_slv_axi_clk", 0, true},
{NULL, "pcie_0_aux_clk", 1000000, true},
{NULL, "pcie_0_ldo", 0, true},
- {NULL, "pcie_0_phy_reset", 0, false}
+ {NULL, "pcie_0_phy_reset", 0, false},
+ {NULL, "pcie_0_phy_cfg_ahb_clk", 0, false},
+ {NULL, "pcie_0_phy_aux_clk", 0, false}
};
static struct ep_pcie_clk_info_t
@@ -131,11 +133,18 @@ static int ep_pcie_gpio_init(struct ep_pcie_dev_t *dev)
info = &dev->gpio[i];
if (!info->num) {
- EP_PCIE_ERR(dev,
- "PCIe V%d: the number of gpio %s is invalid\n",
- dev->rev, info->name);
- rc = -EINVAL;
- break;
+ if (i == EP_PCIE_GPIO_MDM2AP) {
+ EP_PCIE_DBG(dev,
+ "PCIe V%d: gpio %s does not exist.\n",
+ dev->rev, info->name);
+ continue;
+ } else {
+ EP_PCIE_ERR(dev,
+ "PCIe V%d: the number of gpio %s is invalid\n",
+ dev->rev, info->name);
+ rc = -EINVAL;
+ break;
+ }
}
rc = gpio_request(info->num, info->name);
@@ -451,6 +460,109 @@ static void ep_pcie_bar_init(struct ep_pcie_dev_t *dev)
ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
}
+#ifdef CONFIG_ARCH_MSM8996
+static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
+{
+ u32 regval;
+
+ EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
+
+ /* Configure PCIe to endpoint mode */
+ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x0);
+
+ /* adjust DBI base address */
+ writel_relaxed(0x0C000000, dev->parf + PCIE20_PARF_DBI_BASE_ADDR);
+
+ /* Configure PCIe core to support 1GB aperture */
+ ep_pcie_write_reg(dev->parf, PCIE20_PARF_SLV_ADDR_SPACE_SIZE,
+ 0x40000000);
+
+ /* Disable the debouncers */
+ ep_pcie_write_reg(dev->parf, PCIE20_PARF_DB_CTRL, 0x73);
+
+ /* Enable Auxiliary Power Detect */
+ ep_pcie_write_mask(dev->parf + PCIE20_PARF_SYS_CTRL, 0x10, BIT(4));
+
+ /* Enable the bit to exit l1ss when sending LTR and MSI */
+ ep_pcie_write_mask(dev->parf + PCIE20_PARF_CFG_BITS, 0x2, BIT(1));
+
+ /* Enable CS for RO(CS) register writes */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0));
+
+ /* Set the INT_LINE Register field to 0 */
+ ep_pcie_write_mask(dev->dm_core +
+ PCIE20_BRIDGE_CTRL_INT_PIN_INT_LINE_REG, 0xff, 0);
+
+ /* Set the PMC Register - to support PME in D0, D3hot and D3cold */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_CAP_ID_NXT_PTR,
+ 0xF8000000, BIT(31) | BIT(30) | BIT(27));
+
+ /* Set the frequency for the AUX clock to 19.2MHz */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_AUX_CLK_FREQ_REG,
+ 0x3FF, BIT(4) | BIT(2));
+
+ /* Set the Endpoint L0s Acceptable Latency to 1us (max) */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES,
+ 0x1C0, BIT(8) | BIT(7) | BIT(6));
+
+ /* Set the Endpoint L1 Acceptable Latency to 2 us (max) */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_DEVICE_CAPABILITIES,
+ 0xE00, BIT(11) | BIT(10) | BIT(9));
+
+ /* Set the L0s Exit Latency to 2us-4us = 0x6 */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES,
+ 0x38000, BIT(17) | BIT(16));
+
+ /* Set the L1 Exit Latency to be 32us-64 us = 0x6 */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES,
+ 0x7000, BIT(14) | BIT(13));
+
+ /* Enable Clock Power Management */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES,
+ 0x40000, BIT(18));
+
+ /* Disable CS for RO(CS) register writes */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
+
+ /* Enable writes for RO(CS2) */
+ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, 0, BIT(0));
+
+ /* Set the Common Clock L0s Exit Latency to 2us-4us = 0x6 */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES,
+ 0x38000, BIT(17) | BIT(16));
+
+ /* Set the Common Clock L1 Exit Latency to be 32us-64 us = 0x6 */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CAPABILITIES,
+ 0x7000, BIT(14) | BIT(13));
+
+ /* Disable writes for RO(CS2) */
+ ep_pcie_write_mask(dev->elbi + PCIE20_ELBI_CS2_ENABLE, BIT(0), 0);
+
+ /* T_Power_Off */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_L1_SUBSTATES_REG,
+ BIT(1) | BIT(0), 0);
+
+ /* Set Device ID and Vendor ID */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, 0, BIT(0));
+ ep_pcie_write_reg(dev->dm_core, PCIE20_DEVICE_ID_VENDOR_ID_REG,
+ 0x030217cb);
+ ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
+
+ /* Configure link speed */
+ ep_pcie_write_mask(dev->dm_core + PCIE20_LINK_CONTROL2_LINK_STATUS2,
+ 0xf, dev->link_speed);
+
+ /* Configure BARs */
+ ep_pcie_bar_init(dev);
+
+ /* Enable MHI clocks */
+ ep_pcie_write_reg(dev->parf, PCIE20_PARF_MHI_CLOCK_RESET_CTRL,
+ BIT(1) | BIT(0));
+
+ ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS, 0x0);
+ ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
+}
+#else
static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
{
EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
@@ -578,6 +690,7 @@ static void ep_pcie_core_init(struct ep_pcie_dev_t *dev)
ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14);
}
+#endif
static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev)
{
@@ -694,6 +807,32 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
+ of_get_property(pdev->dev.of_node, "qcom,phy-sequence", &cnt);
+ if (cnt) {
+ dev->phy_sequence = (struct ep_pcie_phy_info_t *)
+ devm_kzalloc(&pdev->dev, cnt, GFP_KERNEL);
+
+ if (dev->phy_sequence) {
+ dev->phy_len =
+ cnt / sizeof(*dev->phy_sequence);
+
+ of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,phy-sequence",
+ (unsigned int *)dev->phy_sequence,
+ cnt / sizeof(dev->phy_sequence->offset));
+ } else {
+ EP_PCIE_ERR(dev,
+ "PCIe V%d: Failed to alloc mem for phy seq.\n",
+ dev->rev);
+ ret = -ENOMEM;
+ goto out;
+ }
+ } else {
+ EP_PCIE_DBG(dev,
+ "PCIe V%d: phy sequence is not present in DT.\n",
+ dev->rev);
+ }
+
cnt = of_property_count_strings((&pdev->dev)->of_node,
"clock-names");
if (cnt > 0) {
@@ -782,6 +921,7 @@ static int ep_pcie_get_resources(struct ep_pcie_dev_t *dev,
EP_PCIE_DBG(dev,
"GPIO %s is not supported in this configuration.\n",
gpio_info->name);
+ ret = 0;
}
}
@@ -1070,6 +1210,9 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt)
EP_PCIE_INFO(dev, "PCIe V%d: PCIe PHY is ready!\n", dev->rev);
}
+#ifdef CONFIG_ARCH_MSM8996
+ ep_pcie_phy_bringup_port(dev);
+#endif
ep_pcie_core_init(dev);
ep_pcie_config_inbound_iatu(dev);
@@ -1977,6 +2120,17 @@ static int ep_pcie_probe(struct platform_device *pdev)
EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: pcie-link-speed:%d.\n",
ep_pcie_dev.rev, ep_pcie_dev.link_speed);
+ ret = of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,phy-status-reg",
+ &ep_pcie_dev.phy_status_reg);
+ if (ret)
+ EP_PCIE_DBG(&ep_pcie_dev,
+ "PCIe V%d: phy-status-reg does not exist.\n",
+ ep_pcie_dev.rev);
+ else
+ EP_PCIE_DBG(&ep_pcie_dev, "PCIe V%d: phy-status-reg:0x%x.\n",
+ ep_pcie_dev.rev, ep_pcie_dev.phy_status_reg);
+
ep_pcie_dev.phy_rev = 1;
ret = of_property_read_u32((&pdev->dev)->of_node,
"qcom,pcie-phy-ver",
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_phy.c b/drivers/platform/msm/ep_pcie/ep_pcie_phy.c
index 83e74f2c7ba7..3dfabd3ed81f 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_phy.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_phy.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
/*
* MSM PCIe PHY endpoint mode
*/
+#include <linux/delay.h>
#include "ep_pcie_com.h"
#include "ep_pcie_phy.h"
@@ -23,6 +24,28 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev)
"PCIe V%d: PHY V%d: Initializing 14nm QMP phy - 100MHz\n",
dev->rev, dev->phy_rev);
+ if (dev->phy_sequence) {
+ int i;
+ struct ep_pcie_phy_info_t *phy_seq;
+
+ EP_PCIE_DBG(dev,
+ "PCIe V%d: PHY V%d: process the sequence specified by DT.!\n",
+ dev->rev, dev->phy_rev);
+
+ i = dev->phy_len;
+ phy_seq = dev->phy_sequence;
+ while (i--) {
+ ep_pcie_write_reg(dev->phy,
+ phy_seq->offset,
+ phy_seq->val);
+ if (phy_seq->delay)
+ usleep_range(phy_seq->delay,
+ phy_seq->delay + 1);
+ phy_seq++;
+ }
+ return;
+ }
+
ep_pcie_write_reg(dev->phy, PCIE_PHY_SW_RESET, 0x01);
ep_pcie_write_reg(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01);
@@ -104,10 +127,26 @@ void ep_pcie_phy_init(struct ep_pcie_dev_t *dev)
ep_pcie_write_reg(dev->phy, PCIE_PHY_START_CONTROL, 0x03);
}
+#ifdef CONFIG_ARCH_MSM8996
+void ep_pcie_phy_bringup_port(struct ep_pcie_dev_t *dev)
+{
+ ep_pcie_write_reg(dev->phy, PCIE_PORT_POWER_DOWN_CONTROL, 0x03);
+ ep_pcie_write_reg(dev->phy, PCIE_PORT_SW_RESET, 0x0);
+ ep_pcie_write_reg(dev->phy, PCIE_PORT_START_CONTROL, 0x0a);
+}
+#endif
+
bool ep_pcie_phy_is_ready(struct ep_pcie_dev_t *dev)
{
- if (readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS) & BIT(6))
- return false;
+ u32 offset;
+
+ if (dev->phy_status_reg)
+ offset = dev->phy_status_reg;
else
+ offset = PCIE_PHY_PCS_STATUS;
+
+ if (readl_relaxed(dev->phy + offset) & BIT(0))
return true;
+ else
+ return false;
}
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_phy.h b/drivers/platform/msm/ep_pcie/ep_pcie_phy.h
index 199e0760956a..884f9fdf7dba 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_phy.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_phy.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -460,4 +460,34 @@
#define PCIE_PHY_LFPS_PER_TIMER_VAL 0x9EC
#define PCIE_PHY_SIGDET_STARTUP_TIMER_VAL 0x9F0
#define PCIE_PHY_LOCK_DETECT_CONFIG4 0x9F4
+#ifdef CONFIG_ARCH_MSM8996
+#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x1054
+#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x1068
+#define QSERDES_TX_LANE_MODE 0x1094
+#define QSERDES_TX_RCV_DETECT_LVL_2 0x10AC
+#define QSERDES_RX_UCDR_FO_GAIN_HALF 0x1200
+#define QSERDES_RX_UCDR_FO_GAIN 0x120C
+#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x1210
+#define QSERDES_RX_UCDR_SO_GAIN 0x121C
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x1248
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 0x12D4
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x12D8
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x12DC
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x12E0
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x130C
+#define QSERDES_RX_SIGDET_ENABLES 0x1310
+#define QSERDES_RX_SIGDET_CNTRL 0x1314
+#define QSERDES_RX_SIGDET_LVL 0x1318
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x131C
+#define PCIE_PHY_SW_RESET 0x400
+#define PCIE_PHY_POWER_DOWN_CONTROL 0x404
+#define PCIE_PHY_START_CONTROL 0x408
+#define PCIE_PHY_ENDPOINT_REFCLK_DRIVE 0x1454
+#define PCIE_PHY_PWRUP_RESET_DLY_TIME_AUXCLK 0x14A0
+#define PCIE_PORT_ENDPOINT_REFCLK_DRIVE 0x1454
+#define PCIE_PORT_POWER_DOWN_CONTROL 0x1404
+#define PCIE_PORT_SW_RESET 0x1400
+#define PCIE_PORT_START_CONTROL 0x1408
+#define PCIE_COM_PCS_READY_STATUS 0x448
+#endif
#endif
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index c78c8a00aa21..e532f071c9ee 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -2442,6 +2442,7 @@ static int glink_smem_native_probe(struct platform_device *pdev)
}
einfo->irq_line = irq_line;
+ einfo->in_ssr = true;
rc = request_irq(irq_line, irq_handler,
IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND | IRQF_SHARED,
node->name, einfo);
@@ -2450,7 +2451,6 @@ static int glink_smem_native_probe(struct platform_device *pdev)
rc);
goto request_irq_fail;
}
- einfo->in_ssr = true;
rc = enable_irq_wake(irq_line);
if (rc < 0)
pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index ebe7dfc4a5b6..b6dfe2d9ae22 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -209,14 +209,15 @@ void hab_ctx_free(struct kref *ref)
* the local ioctl access based on ctx
*/
struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
- struct uhab_context *ctx)
+ struct uhab_context *ctx, int ignore_remote)
{
struct virtual_channel *vchan;
read_lock(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
if (vcid == vchan->id) {
- if (vchan->otherend_closed || vchan->closed ||
+ if ((ignore_remote ? 0 : vchan->otherend_closed) ||
+ vchan->closed ||
!kref_get_unless_zero(&vchan->refcount)) {
pr_debug("failed to inc vcid %x remote %x session %d refcnt %d close_flg remote %d local %d\n",
vchan->id, vchan->otherend_id,
@@ -550,7 +551,7 @@ long hab_vchan_send(struct uhab_context *ctx,
return -EINVAL;
}
- vchan = hab_get_vchan_fromvcid(vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(vcid, ctx, 0);
if (!vchan || vchan->otherend_closed) {
ret = -ENODEV;
goto err;
@@ -565,6 +566,14 @@ long hab_vchan_send(struct uhab_context *ctx,
sizeof(struct habmm_xing_vm_stat));
return -EINVAL;
}
+ } else if (flags & HABMM_SOCKET_XVM_SCHE_TEST) {
+ HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_SCHE_MSG);
+ } else if (flags & HABMM_SOCKET_XVM_SCHE_TEST_ACK) {
+ HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_SCHE_MSG_ACK);
+ } else if (flags & HABMM_SOCKET_XVM_SCHE_RESULT_REQ) {
+ HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_SCHE_RESULT_REQ);
+ } else if (flags & HABMM_SOCKET_XVM_SCHE_RESULT_RSP) {
+ HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_SCHE_RESULT_RSP);
} else {
HAB_HEADER_SET_TYPE(header, HAB_PAYLOAD_TYPE_MSG);
}
@@ -597,9 +606,9 @@ int hab_vchan_recv(struct uhab_context *ctx,
int ret = 0;
int nonblocking_flag = flags & HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING;
- vchan = hab_get_vchan_fromvcid(vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(vcid, ctx, 1);
if (!vchan) {
- pr_err("vcid %X, vchan %p ctx %p\n", vcid, vchan, ctx);
+ pr_err("vcid %X vchan 0x%pK ctx %pK\n", vcid, vchan, ctx);
return -ENODEV;
}
@@ -719,24 +728,20 @@ void hab_vchan_close(struct uhab_context *ctx, int32_t vcid)
write_lock(&ctx->ctx_lock);
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
if (vchan->id == vcid) {
- write_unlock(&ctx->ctx_lock);
+ /* local close starts */
+ vchan->closed = 1;
+
+ /* vchan is not in this ctx anymore */
+ list_del(&vchan->node);
+ ctx->vcnt--;
+
pr_debug("vcid %x remote %x session %d refcnt %d\n",
vchan->id, vchan->otherend_id,
vchan->session_id, get_refcnt(vchan->refcount));
- /*
- * only set when vc close is called locally by user
- * explicity. Used to block remote msg. if forked once
- * before, this local close is skipped due to child
- * usage. if forked but not closed locally, the local
- * context could NOT be closed, vchan can be prolonged
- * by arrived remote msgs
- */
- if (vchan->forked)
- vchan->forked = 0;
- else {
- vchan->closed = 1;
- hab_vchan_stop_notify(vchan);
- }
+
+ write_unlock(&ctx->ctx_lock);
+ /* unblocking blocked in-calls */
+ hab_vchan_stop_notify(vchan);
hab_vchan_put(vchan); /* there is a lock inside */
write_lock(&ctx->ctx_lock);
break;
@@ -1079,25 +1084,14 @@ static int hab_release(struct inode *inodep, struct file *filep)
write_lock(&ctx->ctx_lock);
/* notify remote side on vchan closing */
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
- list_del(&vchan->node); /* vchan is not in this ctx anymore */
+ /* local close starts */
+ vchan->closed = 1;
- if (!vchan->closed) { /* locally hasn't closed yet */
- if (!kref_get_unless_zero(&vchan->refcount)) {
- pr_err("vchan %x %x refcnt %d mismanaged closed %d remote closed %d\n",
- vchan->id,
- vchan->otherend_id,
- get_refcnt(vchan->refcount),
- vchan->closed, vchan->otherend_closed);
- continue; /* vchan is already being freed */
- } else {
- hab_vchan_stop_notify(vchan);
- /* put for notify. shouldn't cause free */
- hab_vchan_put(vchan);
- }
- } else
- continue;
+ list_del(&vchan->node); /* vchan is not in this ctx anymore */
+ ctx->vcnt--;
write_unlock(&ctx->ctx_lock);
+ hab_vchan_stop_notify(vchan);
hab_vchan_put(vchan); /* there is a lock inside */
write_lock(&ctx->ctx_lock);
}
@@ -1117,12 +1111,6 @@ static int hab_release(struct inode *inodep, struct file *filep)
hab_ctx_put(ctx);
filep->private_data = NULL;
- /* ctx leak check */
- if (get_refcnt(ctx->refcount))
- pr_warn("pending ctx release owner %d refcnt %d total %d\n",
- ctx->owner, get_refcnt(ctx->refcount),
- hab_driver.ctx_cnt);
-
return 0;
}
@@ -1134,7 +1122,7 @@ static long hab_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
struct hab_recv *recv_param;
struct hab_send *send_param;
struct hab_info *info_param;
- struct hab_message *msg;
+ struct hab_message *msg = NULL;
void *send_data;
unsigned char data[256] = { 0 };
long ret = 0;
diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h
index cbc049e89d63..7d0c5f2673a2 100644
--- a/drivers/soc/qcom/hab/hab.h
+++ b/drivers/soc/qcom/hab/hab.h
@@ -58,6 +58,10 @@ enum hab_payload_type {
HAB_PAYLOAD_TYPE_PROFILE,
HAB_PAYLOAD_TYPE_CLOSE,
HAB_PAYLOAD_TYPE_INIT_CANCEL,
+ HAB_PAYLOAD_TYPE_SCHE_MSG,
+ HAB_PAYLOAD_TYPE_SCHE_MSG_ACK,
+ HAB_PAYLOAD_TYPE_SCHE_RESULT_REQ,
+ HAB_PAYLOAD_TYPE_SCHE_RESULT_RSP,
HAB_PAYLOAD_TYPE_MAX,
};
#define LOOPBACK_DOM 0xFF
@@ -214,6 +218,7 @@ struct physical_channel {
/* debug only */
uint32_t sequence_tx;
uint32_t sequence_rx;
+ uint32_t status;
/* vchans on this pchan */
struct list_head vchannels;
@@ -255,8 +260,8 @@ struct hab_export_ack_recvd {
};
struct hab_message {
- size_t sizebytes;
struct list_head node;
+ size_t sizebytes;
uint32_t data[];
};
@@ -493,7 +498,7 @@ struct virtual_channel *hab_vchan_get(struct physical_channel *pchan,
void hab_vchan_put(struct virtual_channel *vchan);
struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
- struct uhab_context *ctx);
+ struct uhab_context *ctx, int ignore_remote);
struct physical_channel *hab_pchan_alloc(struct hab_device *habdev,
int otherend_id);
struct physical_channel *hab_pchan_find_domid(struct hab_device *dev,
diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c
index 60156c6b00f0..670efdea212f 100644
--- a/drivers/soc/qcom/hab/hab_mem_linux.c
+++ b/drivers/soc/qcom/hab/hab_mem_linux.c
@@ -53,6 +53,14 @@ static struct pages_list *pages_list_create(
if (!pfn_table)
return ERR_PTR(-EINVAL);
+ pfn = pfn_table->first_pfn;
+ if (pfn_valid(pfn) == 0 || page_is_ram(pfn) == 0) {
+ pr_err("imp sanity failed pfn %lx valid %d ram %d pchan %s\n",
+ pfn, pfn_valid(pfn),
+ page_is_ram(pfn), exp->pchan->name);
+ return ERR_PTR(-EINVAL);
+ }
+
size = exp->payload_count * sizeof(struct page *);
pages = kmalloc(size, GFP_KERNEL);
if (!pages)
@@ -64,7 +72,6 @@ static struct pages_list *pages_list_create(
return ERR_PTR(-ENOMEM);
}
- pfn = pfn_table->first_pfn;
for (i = 0; i < pfn_table->nregions; i++) {
for (j = 0; j < pfn_table->region[i].size; j++) {
pages[k] = pfn_to_page(pfn+j);
diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c
index efa4bb383ec6..b03739974390 100644
--- a/drivers/soc/qcom/hab/hab_mimex.c
+++ b/drivers/soc/qcom/hab/hab_mimex.c
@@ -246,7 +246,7 @@ int hab_mem_export(struct uhab_context *ctx,
if (!ctx || !param || !param->buffer)
return -EINVAL;
- vchan = hab_get_vchan_fromvcid(param->vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(param->vcid, ctx, 0);
if (!vchan || !vchan->pchan) {
ret = -ENODEV;
goto err;
@@ -277,8 +277,8 @@ int hab_mem_export(struct uhab_context *ctx,
&pdata_size);
}
if (ret < 0) {
- pr_err("habmem_hyp_grant failed size=%d ret=%d\n",
- pdata_size, ret);
+ pr_err("habmem_hyp_grant vc %x failed size=%d ret=%d\n",
+ param->vcid, pdata_size, ret);
goto err;
}
@@ -313,7 +313,7 @@ int hab_mem_unexport(struct uhab_context *ctx,
return -EINVAL;
/* refcnt on the access */
- vchan = hab_get_vchan_fromvcid(param->vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(param->vcid, ctx, 1);
if (!vchan || !vchan->pchan) {
ret = -ENODEV;
goto err_novchan;
@@ -360,7 +360,7 @@ int hab_mem_import(struct uhab_context *ctx,
if (!ctx || !param)
return -EINVAL;
- vchan = hab_get_vchan_fromvcid(param->vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(param->vcid, ctx, 0);
if (!vchan || !vchan->pchan) {
ret = -ENODEV;
goto err_imp;
@@ -420,7 +420,7 @@ int hab_mem_unimport(struct uhab_context *ctx,
if (!ctx || !param)
return -EINVAL;
- vchan = hab_get_vchan_fromvcid(param->vcid, ctx);
+ vchan = hab_get_vchan_fromvcid(param->vcid, ctx, 1);
if (!vchan || !vchan->pchan) {
if (vchan)
hab_vchan_put(vchan);
diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c
index 71010be414d5..e0f4970ce14e 100644
--- a/drivers/soc/qcom/hab/hab_msg.c
+++ b/drivers/soc/qcom/hab/hab_msg.c
@@ -27,6 +27,12 @@ hab_msg_alloc(struct physical_channel *pchan, size_t sizebytes)
{
struct hab_message *message;
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("pchan %s send size too large %zd\n",
+ pchan->name, sizebytes);
+ return NULL;
+ }
+
message = kzalloc(sizeof(*message) + sizebytes, GFP_ATOMIC);
if (!message)
return NULL;
@@ -153,6 +159,12 @@ static int hab_receive_create_export_ack(struct physical_channel *pchan,
pr_err("exp ack size %zu is not as arrived %zu\n",
sizeof(ack_recvd->ack), sizebytes);
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("pchan %s read size too large %zd\n",
+ pchan->name, sizebytes);
+ return -EINVAL;
+ }
+
if (physical_channel_read(pchan,
&ack_recvd->ack,
sizebytes) != sizebytes)
@@ -169,6 +181,11 @@ static void hab_msg_drop(struct physical_channel *pchan, size_t sizebytes)
{
uint8_t *data = NULL;
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("%s read size too large %zd\n", pchan->name, sizebytes);
+ return;
+ }
+
data = kmalloc(sizebytes, GFP_ATOMIC);
if (data == NULL)
return;
@@ -189,6 +206,7 @@ int hab_msg_recv(struct physical_channel *pchan,
struct virtual_channel *vchan = NULL;
struct export_desc *exp_desc;
struct timeval tv;
+ unsigned long long rx_mpm_tv;
/* get the local virtual channel if it isn't an open message */
if (payload_type != HAB_PAYLOAD_TYPE_INIT &&
@@ -210,7 +228,7 @@ int hab_msg_recv(struct physical_channel *pchan,
*/
vchan = hab_vchan_get(pchan, header);
if (!vchan) {
- pr_info("vchan is not found, payload type %d, vchan id %x, sizebytes %zx, session %d\n",
+ pr_debug("vchan not found type %d vcid %x sz %zx sesn %d\n",
payload_type, vchan_id, sizebytes, session_id);
if (sizebytes) {
@@ -245,6 +263,8 @@ int hab_msg_recv(struct physical_channel *pchan,
switch (payload_type) {
case HAB_PAYLOAD_TYPE_MSG:
+ case HAB_PAYLOAD_TYPE_SCHE_RESULT_REQ:
+ case HAB_PAYLOAD_TYPE_SCHE_RESULT_RSP:
message = hab_msg_alloc(pchan, sizebytes);
if (!message)
break;
@@ -275,6 +295,12 @@ int hab_msg_recv(struct physical_channel *pchan,
break;
case HAB_PAYLOAD_TYPE_EXPORT:
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("%s exp size too large %zd\n",
+ pchan->name, sizebytes);
+ break;
+ }
+
exp_desc = kzalloc(sizebytes, GFP_ATOMIC);
if (!exp_desc)
break;
@@ -313,7 +339,7 @@ int hab_msg_recv(struct physical_channel *pchan,
case HAB_PAYLOAD_TYPE_CLOSE:
/* remote request close */
- pr_info("remote request close vcid %pK %X other id %X session %d refcnt %d\n",
+ pr_debug("remote close vcid %pK %X other id %X session %d refcnt %d\n",
vchan, vchan->id, vchan->otherend_id,
session_id, get_refcnt(vchan->refcount));
hab_vchan_stop(vchan);
@@ -334,6 +360,19 @@ int hab_msg_recv(struct physical_channel *pchan,
}
break;
+ case HAB_PAYLOAD_TYPE_SCHE_MSG:
+ case HAB_PAYLOAD_TYPE_SCHE_MSG_ACK:
+ rx_mpm_tv = msm_timer_get_sclk_ticks();
+ /* pull down the incoming data */
+ message = hab_msg_alloc(pchan, sizebytes);
+ if (!message)
+ pr_err("failed to allocate msg Arrived msg will be lost\n");
+ else {
+ ((unsigned long long *)message->data)[0] = rx_mpm_tv;
+ hab_msg_queue(vchan, message);
+ }
+ break;
+
default:
pr_err("unknown msg received, payload type %d, vchan id %x, sizebytes %zx, session %d\n",
payload_type, vchan_id, sizebytes, session_id);
diff --git a/drivers/soc/qcom/hab/hab_open.c b/drivers/soc/qcom/hab/hab_open.c
index f09a1df8aa57..bc2b774883f4 100644
--- a/drivers/soc/qcom/hab/hab_open.c
+++ b/drivers/soc/qcom/hab/hab_open.c
@@ -47,6 +47,12 @@ int hab_open_request_add(struct physical_channel *pchan,
struct hab_open_request *request;
struct timeval tv;
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("pchan %s request size too large %zd\n",
+ pchan->name, sizebytes);
+ return -EINVAL;
+ }
+
node = kzalloc(sizeof(*node), GFP_ATOMIC);
if (!node)
return -ENOMEM;
@@ -187,6 +193,12 @@ int hab_open_receive_cancel(struct physical_channel *pchan,
int bfound = 0;
struct timeval tv;
+ if (sizebytes > HAB_HEADER_SIZE_MASK) {
+ pr_err("pchan %s cancel size too large %zd\n",
+ pchan->name, sizebytes);
+ return -EINVAL;
+ }
+
if (physical_channel_read(pchan, &data, sizebytes) != sizebytes)
return -EIO;
diff --git a/drivers/soc/qcom/hab/hab_stat.c b/drivers/soc/qcom/hab/hab_stat.c
index f0a4207bc871..b78e5e7e9867 100644
--- a/drivers/soc/qcom/hab/hab_stat.c
+++ b/drivers/soc/qcom/hab/hab_stat.c
@@ -61,14 +61,17 @@ int hab_stat_show_vchan(struct hab_driver *driver,
continue;
ret = hab_stat_buffer_print(buf, size,
- "mmid %s role %d local %d remote %d vcnt %d:\n",
+ "nm %s r %d lc %d rm %d sq_t %d sq_r %d st 0x%x vn %d:\n",
pchan->name, pchan->is_be, pchan->vmid_local,
- pchan->vmid_remote, pchan->vcnt);
+ pchan->vmid_remote, pchan->sequence_tx,
+ pchan->sequence_rx, pchan->status, pchan->vcnt);
read_lock(&pchan->vchans_lock);
list_for_each_entry(vc, &pchan->vchannels, pnode) {
ret = hab_stat_buffer_print(buf, size,
- "%08X ", vc->id);
+ "%08X(%d:%d) ", vc->id,
+ get_refcnt(vc->refcount),
+ vc->otherend_closed);
}
ret = hab_stat_buffer_print(buf, size, "\n");
read_unlock(&pchan->vchans_lock);
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index 8d818b8fafb1..a95d6c7451c9 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -85,9 +85,6 @@ hab_vchan_free(struct kref *ref)
}
spin_unlock_bh(&vchan->rx_lock);
- /* the release vchan from ctx was done earlier in vchan close() */
- hab_ctx_put(ctx); /* now ctx is not needed from this vchan's view */
-
/* release vchan from pchan. no more msg for this vchan */
write_lock_bh(&pchan->vchans_lock);
list_for_each_entry_safe(vc, vc_tmp, &pchan->vchannels, pnode) {
@@ -100,6 +97,9 @@ hab_vchan_free(struct kref *ref)
}
write_unlock_bh(&pchan->vchans_lock);
+ /* the release vchan from ctx was done earlier in vchan close() */
+ hab_ctx_put(ctx); /* now ctx is not needed from this vchan's view */
+
/* release idr at the last so same idr will not be used early */
spin_lock_bh(&pchan->vid_lock);
idr_remove(&pchan->vchan_idr, HAB_VCID_GET_ID(vchan->id));
@@ -167,6 +167,7 @@ hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
return vchan;
}
+/* wake up local waiting Q, so stop-vchan can be processed */
void hab_vchan_stop(struct virtual_channel *vchan)
{
if (vchan) {
@@ -190,6 +191,7 @@ void hab_vchans_stop(struct physical_channel *pchan)
read_unlock(&pchan->vchans_lock);
}
+/* send vchan close to remote and stop receiving anything locally */
void hab_vchan_stop_notify(struct virtual_channel *vchan)
{
hab_send_close_msg(vchan);
@@ -204,15 +206,22 @@ static int hab_vchans_per_pchan_empty(struct physical_channel *pchan)
empty = list_empty(&pchan->vchannels);
if (!empty) {
struct virtual_channel *vchan;
+ int vcnt = pchan->vcnt;
list_for_each_entry(vchan, &pchan->vchannels, pnode) {
- pr_err("vchan %pK id %x remote id %x session %d ref %d closed %d remote close %d\n",
- vchan, vchan->id, vchan->otherend_id,
- vchan->session_id,
- get_refcnt(vchan->refcount), vchan->closed,
- vchan->otherend_closed);
+ /* discount open-pending unpaired vchan */
+ if (!vchan->session_id)
+ vcnt--;
+ else
+ pr_err("vchan %pK %x rm %x sn %d rf %d clsd %d rm clsd %d\n",
+ vchan, vchan->id,
+ vchan->otherend_id,
+ vchan->session_id,
+ get_refcnt(vchan->refcount),
+ vchan->closed, vchan->otherend_closed);
}
-
+ if (!vcnt)
+ empty = 1;/* unpaired vchan can exist at init time */
}
read_unlock(&pchan->vchans_lock);
@@ -265,48 +274,18 @@ int hab_vchan_find_domid(struct virtual_channel *vchan)
return vchan ? vchan->pchan->dom_id : -1;
}
-/* this sould be only called once after refcnt is zero */
-static void hab_vchan_schedule_free(struct kref *ref)
-{
- struct virtual_channel *vchanin =
- container_of(ref, struct virtual_channel, refcount);
- struct uhab_context *ctx = vchanin->ctx;
- struct virtual_channel *vchan, *tmp;
- int bnotify = 0;
-
- /*
- * similar logic is in ctx free. if ctx free runs first,
- * this is skipped
- */
- write_lock_bh(&ctx->ctx_lock);
- list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
- if (vchan == vchanin) {
- pr_debug("vchan free refcnt = %d\n",
- get_refcnt(vchan->refcount));
- ctx->vcnt--;
- list_del(&vchan->node);
- bnotify = 1;
- break;
- }
- }
- write_unlock_bh(&ctx->ctx_lock);
-
- if (bnotify)
- hab_vchan_stop_notify(vchan);
-
- hab_vchan_free(ref);
-}
-
void hab_vchan_put(struct virtual_channel *vchan)
{
if (vchan)
- kref_put(&vchan->refcount, hab_vchan_schedule_free);
+ kref_put(&vchan->refcount, hab_vchan_free);
}
int hab_vchan_query(struct uhab_context *ctx, int32_t vcid, uint64_t *ids,
char *names, size_t name_size, uint32_t flags)
{
- struct virtual_channel *vchan = hab_get_vchan_fromvcid(vcid, ctx);
+ struct virtual_channel *vchan;
+
+ vchan = hab_get_vchan_fromvcid(vcid, ctx, 1);
if (!vchan)
return -EINVAL;
diff --git a/drivers/soc/qcom/hab/qvm_comm.c b/drivers/soc/qcom/hab/qvm_comm.c
index cce24d72c28e..25d0208dea4c 100644
--- a/drivers/soc/qcom/hab/qvm_comm.c
+++ b/drivers/soc/qcom/hab/qvm_comm.c
@@ -13,6 +13,8 @@
#include "hab.h"
#include "hab_qvm.h"
+static unsigned long long xvm_sche_tx_tv_buffer[2];
+
inline void habhyp_notify(void *commdev)
{
struct qvm_channel *dev = (struct qvm_channel *)commdev;
@@ -56,6 +58,7 @@ int physical_channel_send(struct physical_channel *pchan,
return -EAGAIN; /* not enough free space */
}
+ header->sequence = pchan->sequence_tx + 1;
header->signature = HAB_HEAD_SIGNATURE;
if (hab_pipe_write(dev->pipe_ep,
@@ -78,6 +81,12 @@ int physical_channel_send(struct physical_channel *pchan,
spin_unlock_bh(&dev->io_lock);
return -EINVAL;
}
+ } else if (HAB_HEADER_GET_TYPE(*header)
+ == HAB_PAYLOAD_TYPE_SCHE_RESULT_REQ) {
+ ((unsigned long long *)payload)[0] = xvm_sche_tx_tv_buffer[0];
+ } else if (HAB_HEADER_GET_TYPE(*header)
+ == HAB_PAYLOAD_TYPE_SCHE_RESULT_RSP) {
+ ((unsigned long long *)payload)[2] = xvm_sche_tx_tv_buffer[1];
}
if (sizebytes) {
@@ -91,8 +100,12 @@ int physical_channel_send(struct physical_channel *pchan,
hab_pipe_write_commit(dev->pipe_ep);
spin_unlock_bh(&dev->io_lock);
+ if (HAB_HEADER_GET_TYPE(*header) == HAB_PAYLOAD_TYPE_SCHE_MSG)
+ xvm_sche_tx_tv_buffer[0] = msm_timer_get_sclk_ticks();
+ else if (HAB_HEADER_GET_TYPE(*header) == HAB_PAYLOAD_TYPE_SCHE_MSG_ACK)
+ xvm_sche_tx_tv_buffer[1] = msm_timer_get_sclk_ticks();
habhyp_notify(dev);
-
+ ++pchan->sequence_tx;
return 0;
}
@@ -117,6 +130,8 @@ void physical_channel_rx_dispatch(unsigned long data)
header.sequence);
}
+ pchan->sequence_rx = header.sequence;
+
hab_msg_recv(pchan, &header);
}
spin_unlock_bh(&pchan->rxbuf_lock);
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 7604affe63a8..b20cf2d65a6a 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -539,6 +539,7 @@ static struct msm_soc_info cpu_of_id[] = {
[312] = {MSM_CPU_8996, "APQ8096pro"},
[315] = {MSM_CPU_8996, "MSM8996pro"},
[316] = {MSM_CPU_8996, "APQ8096pro"},
+ [387] = {MSM_CPU_8996, "APQ8096A"},
/* 8976 ID */
[266] = {MSM_CPU_8976, "MSM8976"},
diff --git a/include/linux/habmm.h b/include/linux/habmm.h
index cd4e2506f9ee..34ba1083a554 100644
--- a/include/linux/habmm.h
+++ b/include/linux/habmm.h
@@ -105,6 +105,37 @@ int32_t habmm_socket_close(int32_t handle);
*/
#define HABMM_SOCKET_SEND_FLAGS_XING_VM_STAT 0x00000002
+/* start to measure cross-vm schedule latency: VM1 send msg with this flag
+ * to VM2 to kick off the measurement. In the hab driver level, the VM1 hab
+ * driver shall record the time of schdule out with mpm_timer, and buffer
+ * it for later usage. The VM2 hab driver shall record the time of schedule
+ * in with mpm_timer and pass it to "habtest" application.
+ */
+#define HABMM_SOCKET_XVM_SCHE_TEST 0x00000004
+
+/* VM2 responds this message to VM1 for HABMM_SOCKET_XVM_SCHE_TEST.
+ * In the hab driver level, the VM2 hab driver shall record the time of schedule
+ * out with mpm_timer, and buffer it for later usage; the VM1 hab driver
+ * shall record the time of schedule in with mpm_timer and pass it to "habtest"
+ * application.
+ */
+#define HABMM_SOCKET_XVM_SCHE_TEST_ACK 0x00000008
+
+/* VM1 sends this message to VM2 asking for collect all the mpm_timer values
+ * to calculate the latency of schduling between VM1 and VM2. In the hab driver
+ * level, the VM1 hab driver shall save the previous restored schduling out
+ * time to the message buffer
+ */
+#define HABMM_SOCKET_XVM_SCHE_RESULT_REQ 0x00000010
+
+/* VM2 responds this message to VM2 for HABMM_SOCKET_XVM_SCHE_RESULT_REQ.
+ * In the habtest application level, VM2 shall save the previous restored
+ * scheduling in time into message buffer, in the hab driver level, VM2
+ * shall save the previous restored scheduling out time to the message
+ * buffer.
+ */
+#define HABMM_SOCKET_XVM_SCHE_RESULT_RSP 0x00000020
+
struct habmm_xing_vm_stat {
uint64_t tx_sec;
uint64_t tx_usec;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 7902ecbce8ec..0651c7f47932 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1669,9 +1669,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
{
s64 interval = tk->cycle_interval;
s64 xinterval = tk->xtime_interval;
+ u32 base = tk->tkr_mono.clock->mult;
+ u32 max = tk->tkr_mono.clock->maxadj;
+ u32 cur_adj = tk->tkr_mono.mult;
s64 tick_error;
bool negative;
- u32 adj;
+ u32 adj_scale;
/* Remove any current error adj from freq calculation */
if (tk->ntp_err_mult)
@@ -1690,13 +1693,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
/* preserve the direction of correction */
negative = (tick_error < 0);
- /* Sort out the magnitude of the correction */
+ /* If any adjustment would pass the max, just return */
+ if (negative && (cur_adj - 1) <= (base - max))
+ return;
+ if (!negative && (cur_adj + 1) >= (base + max))
+ return;
+ /*
+ * Sort out the magnitude of the correction, but
+ * avoid making so large a correction that we go
+ * over the max adjustment.
+ */
+ adj_scale = 0;
tick_error = abs(tick_error);
- for (adj = 0; tick_error > interval; adj++)
+ while (tick_error > interval) {
+ u32 adj = 1 << (adj_scale + 1);
+
+ /* Check if adjustment gets us within 1 unit from the max */
+ if (negative && (cur_adj - adj) <= (base - max))
+ break;
+ if (!negative && (cur_adj + adj) >= (base + max))
+ break;
+
+ adj_scale++;
tick_error >>= 1;
+ }
/* scale the corrections */
- timekeeping_apply_adjustment(tk, offset, negative, adj);
+ timekeeping_apply_adjustment(tk, offset, negative, adj_scale);
}
/*
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index c48d8c8d9766..92ccddea1fc5 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -379,7 +379,7 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol,
unsigned int rshift = mc->rshift;
int max = mc->max;
int min = mc->min;
- int mask = (1 << (fls(min + max) - 1)) - 1;
+ unsigned int mask = (1 << (fls(min + max) - 1)) - 1;
unsigned int val;
int ret;
@@ -424,7 +424,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
unsigned int rshift = mc->rshift;
int max = mc->max;
int min = mc->min;
- int mask = (1 << (fls(min + max) - 1)) - 1;
+ unsigned int mask = (1 << (fls(min + max) - 1)) - 1;
int err = 0;
unsigned int val, val_mask, val2 = 0;