summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,wcn3990-wifi.txt16
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt3
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt2
-rw-r--r--Documentation/devicetree/bindings/usb/msm-ssusb.txt4
-rw-r--r--Documentation/sysctl/kernel.txt15
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi189
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi185
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi49
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi49
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-rumi.dts49
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi128
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-blsp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-cdp.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-common.dtsi94
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mtp.dts4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi88
-rw-r--r--arch/arm64/kernel/entry.S3
-rw-r--r--arch/arm64/mm/fault.c3
-rw-r--r--drivers/clk/msm/clock-gcc-8998.c1
-rw-r--r--drivers/devfreq/governor_msm_adreno_tz.c6
-rw-r--r--drivers/gpu/msm/adreno_cp_parser.c35
-rw-r--r--drivers/gpu/msm/adreno_cp_parser.h4
-rw-r--r--drivers/gpu/msm/adreno_perfcounter.c11
-rw-r--r--drivers/gpu/msm/adreno_snapshot.c106
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.h4
-rw-r--r--drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c4
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c8
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_debug.h3
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c24
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h9
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c14
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c11
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h61
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c704
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.h204
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c95
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h187
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/ftm.h4
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c40
-rw-r--r--drivers/power/supply/qcom/smb-lib.c39
-rw-r--r--drivers/power/supply/qcom/smb-lib.h1
-rw-r--r--drivers/power/supply/qcom/smb138x-charger.c10
-rw-r--r--drivers/regulator/cpr3-mmss-regulator.c257
-rw-r--r--drivers/regulator/cpr3-regulator.h10
-rw-r--r--drivers/regulator/cpr3-util.c256
-rw-r--r--drivers/regulator/cpr4-mmss-ldo-regulator.c48
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c50
-rw-r--r--drivers/scsi/ufs/ufs-qcom-debugfs.c13
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c46
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c9
-rw-r--r--drivers/scsi/ufs/ufshcd.c26
-rw-r--r--drivers/soc/qcom/icnss.c4
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c16
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c91
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h12
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c52
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c145
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c38
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c12
-rw-r--r--include/net/cfg80211.h49
-rw-r--r--include/uapi/linux/msm_mdp_ext.h12
-rw-r--r--include/uapi/linux/nl80211.h74
-rw-r--r--kernel/sched/fair.c5
-rw-r--r--kernel/sysctl.c2
-rw-r--r--mm/page_alloc.c30
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/nl80211.c155
-rw-r--r--sound/soc/msm/sdm660-common.c8
-rw-r--r--sound/soc/msm/sdm660-external.c49
-rw-r--r--sound/soc/msm/sdm660-internal.c97
81 files changed, 3582 insertions, 564 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,wcn3990-wifi.txt b/Documentation/devicetree/bindings/net/wireless/qcom,wcn3990-wifi.txt
new file mode 100644
index 000000000000..626ca2124366
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,wcn3990-wifi.txt
@@ -0,0 +1,16 @@
+* Qualcomm Technologies, Inc. WCN3990 chipset WLAN platform Driver
+
+This driver adds support for the Integrated WCN3990 WLAN module, WCN3990
+is integrated 802.11ac chipset with SNOC bus interface. It also add support
+for SNOC bus registration, copy engine configuration for the WCN3990 chipset,
+shadow register configuration, create host to target communication interface
+to interact with WLAN firmware, WLAN module interface control and data
+receive(RX)/transmit(TX) control.
+
+Required properties:
+ - compatible: "qcom,wcn3990-wifi";
+
+Example:
+ qcom,msm_ath10k@18000000 {
+ compatible = "qcom,wcn3990-wifi";
+ };
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
index 3e22f178aa82..d08ca957c954 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
@@ -203,10 +203,11 @@ IBB subnode required properties:
- qcom,qpnp-ibb-init-lcd-voltage: The default output voltage when IBB regulator
is configured in lcd mode.
+IBB subnode optional properties:
+
- qcom,qpnp-ibb-discharge-resistor: The discharge resistor in Kilo Ohms which
controls the soft start time. Supported values
are 300, 64, 32 and 16.
-IBB subnode optional properties:
- qcom,qpnp-ibb-slew-rate: The time (in us) taken by the regulator to change
voltage value in one step. This property is not
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 86e1bdb417ab..fc2c89bfbbd5 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1649,6 +1649,7 @@ Optional properties:
capacitor mode.
- qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external
capacitor mode.
+- qcom,wsa-disable : Boolean. Disables WSA speaker dailinks from sound node.
- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
- qcom,msm-mclk-freq : This property is used to inform machine driver about
mclk frequency needs to be configured for internal and external PA.
@@ -1685,6 +1686,7 @@ Example:
qcom,msm-mclk-freq = <9600000>;
qcom,msm-mbhc-hphl-swh = <0>;
qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,wsa-disable;
qcom,msm-mbhc-moist-cfg = <1>, <3>, <0>;
qcom,msm-hs-micbias-type = "internal";
qcom,msm-micbias1-ext-cap;
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index fa6ee8969946..47fad8aa4a1a 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -19,6 +19,7 @@ Required properties :
and reset lines used by this controller.
- reset-names: reset signal name strings sorted in the same order as the resets
property.
+- qcom,core-clk-rate: clock frequency to be set for USB master clock.
Optional properties :
- reg: Additional registers
@@ -54,7 +55,8 @@ Optional properties :
- qcom,disable-dev-mode-pm: If present, it disables PM runtime functionality for device mode.
- qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB
host mode is used.
-- qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock.
+- qcom,core-clk-rate-hs: If present, indicates min core clock frequency required to support
+ hs speed.
- extcon: phandles to external connector devices. First phandle should point to
external connector, which provide "USB" cable events, the second
should point to external connector device, which provide "USB-HOST"
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 2c5137a6fef6..6475fa234065 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -850,14 +850,13 @@ via the /proc/sys interface:
Each write syscall must fully contain the sysctl value to be
written, and multiple writes on the same sysctl file descriptor
will rewrite the sysctl value, regardless of file position.
- 0 - (default) Same behavior as above, but warn about processes that
- perform writes to a sysctl file descriptor when the file position
- is not 0.
- 1 - Respect file position when writing sysctl strings. Multiple writes
- will append to the sysctl value buffer. Anything past the max length
- of the sysctl value buffer will be ignored. Writes to numeric sysctl
- entries must always be at file position 0 and the value must be
- fully contained in the buffer sent in the write syscall.
+ 0 - Same behavior as above, but warn about processes that perform writes
+ to a sysctl file descriptor when the file position is not 0.
+ 1 - (default) Respect file position when writing sysctl strings. Multiple
+ writes will append to the sysctl value buffer. Anything past the max
+ length of the sysctl value buffer will be ignored. Writes to numeric
+ sysctl entries must always be at file position 0 and the value must
+ be fully contained in the buffer sent in the write syscall.
==============================================================
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi
new file mode 100644
index 000000000000..3c0134b665fc
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi
@@ -0,0 +1,189 @@
+/* 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.
+ */
+
+&mdss_mdp {
+ dsi_nt35695b_truly_fhd_cmd: qcom,mdss_dsi_nt35695b_truly_fhd_cmd {
+ qcom,mdss-dsi-panel-name =
+ "nt35695b truly fhd command mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <96>;
+ qcom,mdss-dsi-h-back-porch = <64>;
+ qcom,mdss-dsi-h-pulse-width = <16>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <16>;
+ qcom,mdss-dsi-v-front-porch = <4>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [e6 38 26 00 68 6e 2a
+ 3c 44 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x2f>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-on-command = [15 01 00 00 10 00 02 ff 20
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 01
+ 15 01 00 00 00 00 02 01 55
+ 15 01 00 00 00 00 02 02 45
+ 15 01 00 00 00 00 02 03 55
+ 15 01 00 00 00 00 02 05 50
+ 15 01 00 00 00 00 02 06 a8
+ 15 01 00 00 00 00 02 07 ad
+ 15 01 00 00 00 00 02 08 0c
+ 15 01 00 00 00 00 02 0b aa
+ 15 01 00 00 00 00 02 0c aa
+ 15 01 00 00 00 00 02 0e b0
+ 15 01 00 00 00 00 02 0f b3
+ 15 01 00 00 00 00 02 11 28
+ 15 01 00 00 00 00 02 12 10
+ 15 01 00 00 00 00 02 13 01
+ 15 01 00 00 00 00 02 14 4a
+ 15 01 00 00 00 00 02 15 12
+ 15 01 00 00 00 00 02 16 12
+ 15 01 00 00 00 00 02 30 01
+ 15 01 00 00 00 00 02 72 31
+ 15 01 00 00 00 00 02 58 82
+ 15 01 00 00 00 00 02 59 00
+ 15 01 00 00 00 00 02 5a 02
+ 15 01 00 00 00 00 02 5b 00
+ 15 01 00 00 00 00 02 5c 82
+ 15 01 00 00 00 00 02 5d 80
+ 15 01 00 00 00 00 02 5e 02
+ 15 01 00 00 00 00 02 5f 00
+ 15 01 00 00 00 00 02 ff 24
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 01
+ 15 01 00 00 00 00 02 01 0b
+ 15 01 00 00 00 00 02 02 0c
+ 15 01 00 00 00 00 02 03 89
+ 15 01 00 00 00 00 02 04 8a
+ 15 01 00 00 00 00 02 05 0f
+ 15 01 00 00 00 00 02 06 10
+ 15 01 00 00 00 00 02 07 10
+ 15 01 00 00 00 00 02 08 1c
+ 15 01 00 00 00 00 02 09 00
+ 15 01 00 00 00 00 02 0a 00
+ 15 01 00 00 00 00 02 0b 00
+ 15 01 00 00 00 00 02 0c 00
+ 15 01 00 00 00 00 02 0d 13
+ 15 01 00 00 00 00 02 0e 15
+ 15 01 00 00 00 00 02 0f 17
+ 15 01 00 00 00 00 02 10 01
+ 15 01 00 00 00 00 02 11 0b
+ 15 01 00 00 00 00 02 12 0c
+ 15 01 00 00 00 00 02 13 89
+ 15 01 00 00 00 00 02 14 8a
+ 15 01 00 00 00 00 02 15 0f
+ 15 01 00 00 00 00 02 16 10
+ 15 01 00 00 00 00 02 17 10
+ 15 01 00 00 00 00 02 18 1c
+ 15 01 00 00 00 00 02 19 00
+ 15 01 00 00 00 00 02 1a 00
+ 15 01 00 00 00 00 02 1b 00
+ 15 01 00 00 00 00 02 1c 00
+ 15 01 00 00 00 00 02 1d 13
+ 15 01 00 00 00 00 02 1e 15
+ 15 01 00 00 00 00 02 1f 17
+ 15 01 00 00 00 00 02 20 00
+ 15 01 00 00 00 00 02 21 01
+ 15 01 00 00 00 00 02 22 00
+ 15 01 00 00 00 00 02 23 40
+ 15 01 00 00 00 00 02 24 40
+ 15 01 00 00 00 00 02 25 6d
+ 15 01 00 00 00 00 02 26 40
+ 15 01 00 00 00 00 02 27 40
+ 15 01 00 00 00 00 02 29 d8
+ 15 01 00 00 00 00 02 2a 2a
+ 15 01 00 00 00 00 02 4b 03
+ 15 01 00 00 00 00 02 4c 11
+ 15 01 00 00 00 00 02 4d 10
+ 15 01 00 00 00 00 02 4e 01
+ 15 01 00 00 00 00 02 4f 01
+ 15 01 00 00 00 00 02 50 10
+ 15 01 00 00 00 00 02 51 00
+ 15 01 00 00 00 00 02 52 80
+ 15 01 00 00 00 00 02 53 00
+ 15 01 00 00 00 00 02 54 07
+ 15 01 00 00 00 00 02 55 25
+ 15 01 00 00 00 00 02 56 00
+ 15 01 00 00 00 00 02 58 07
+ 15 01 00 00 00 00 02 5b 43
+ 15 01 00 00 00 00 02 5c 00
+ 15 01 00 00 00 00 02 5f 73
+ 15 01 00 00 00 00 02 60 73
+ 15 01 00 00 00 00 02 63 22
+ 15 01 00 00 00 00 02 64 00
+ 15 01 00 00 00 00 02 67 08
+ 15 01 00 00 00 00 02 68 04
+ 15 01 00 00 00 00 02 7a 80
+ 15 01 00 00 00 00 02 7b 91
+ 15 01 00 00 00 00 02 7c d8
+ 15 01 00 00 00 00 02 7d 60
+ 15 01 00 00 00 00 02 93 06
+ 15 01 00 00 00 00 02 94 06
+ 15 01 00 00 00 00 02 8a 00
+ 15 01 00 00 00 00 02 9b 0f
+ 15 01 00 00 00 00 02 b3 c0
+ 15 01 00 00 00 00 02 b4 00
+ 15 01 00 00 00 00 02 b5 00
+ 15 01 00 00 00 00 02 b6 21
+ 15 01 00 00 00 00 02 b7 22
+ 15 01 00 00 00 00 02 b8 07
+ 15 01 00 00 00 00 02 b9 07
+ 15 01 00 00 00 00 02 ba 22
+ 15 01 00 00 00 00 02 bd 20
+ 15 01 00 00 00 00 02 be 07
+ 15 01 00 00 00 00 02 bf 07
+ 15 01 00 00 00 00 02 c1 6d
+ 15 01 00 00 00 00 02 c4 24
+ 15 01 00 00 00 00 02 e3 00
+ 15 01 00 00 00 00 02 ec 00
+ 15 01 00 00 00 00 02 ff 10
+ 15 01 00 00 00 00 02 bb 10
+ 15 01 00 00 00 00 02 35 02
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 78 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi
new file mode 100644
index 000000000000..d6b24f4e54d2
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi
@@ -0,0 +1,185 @@
+/* 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.
+ */
+
+&mdss_mdp {
+ dsi_nt35695b_truly_fhd_video: qcom,mdss_dsi_nt35695b_truly_fhd_video {
+ qcom,mdss-dsi-panel-name =
+ "nt35695b truly fhd video mode dsi panel";
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1080>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <96>;
+ qcom,mdss-dsi-h-back-porch = <64>;
+ qcom,mdss-dsi-h-pulse-width = <16>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <16>;
+ qcom,mdss-dsi-v-front-porch = <4>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [e6 38 26 00 68 6e 2a
+ 3c 44 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x2f>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-on-command = [15 01 00 00 10 00 02 ff 20
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 01
+ 15 01 00 00 00 00 02 01 55
+ 15 01 00 00 00 00 02 02 45
+ 15 01 00 00 00 00 02 03 55
+ 15 01 00 00 00 00 02 05 50
+ 15 01 00 00 00 00 02 06 a8
+ 15 01 00 00 00 00 02 07 ad
+ 15 01 00 00 00 00 02 08 0c
+ 15 01 00 00 00 00 02 0b aa
+ 15 01 00 00 00 00 02 0c aa
+ 15 01 00 00 00 00 02 0e b0
+ 15 01 00 00 00 00 02 0f b3
+ 15 01 00 00 00 00 02 11 28
+ 15 01 00 00 00 00 02 12 10
+ 15 01 00 00 00 00 02 13 01
+ 15 01 00 00 00 00 02 14 4a
+ 15 01 00 00 00 00 02 15 12
+ 15 01 00 00 00 00 02 16 12
+ 15 01 00 00 00 00 02 30 01
+ 15 01 00 00 00 00 02 72 31
+ 15 01 00 00 00 00 02 58 82
+ 15 01 00 00 00 00 02 59 00
+ 15 01 00 00 00 00 02 5a 02
+ 15 01 00 00 00 00 02 5b 00
+ 15 01 00 00 00 00 02 5c 82
+ 15 01 00 00 00 00 02 5d 80
+ 15 01 00 00 00 00 02 5e 02
+ 15 01 00 00 00 00 02 5f 00
+ 15 01 00 00 00 00 02 ff 24
+ 15 01 00 00 00 00 02 fb 01
+ 15 01 00 00 00 00 02 00 01
+ 15 01 00 00 00 00 02 01 0b
+ 15 01 00 00 00 00 02 02 0c
+ 15 01 00 00 00 00 02 03 89
+ 15 01 00 00 00 00 02 04 8a
+ 15 01 00 00 00 00 02 05 0f
+ 15 01 00 00 00 00 02 06 10
+ 15 01 00 00 00 00 02 07 10
+ 15 01 00 00 00 00 02 08 1c
+ 15 01 00 00 00 00 02 09 00
+ 15 01 00 00 00 00 02 0a 00
+ 15 01 00 00 00 00 02 0b 00
+ 15 01 00 00 00 00 02 0c 00
+ 15 01 00 00 00 00 02 0d 13
+ 15 01 00 00 00 00 02 0e 15
+ 15 01 00 00 00 00 02 0f 17
+ 15 01 00 00 00 00 02 10 01
+ 15 01 00 00 00 00 02 11 0b
+ 15 01 00 00 00 00 02 12 0c
+ 15 01 00 00 00 00 02 13 89
+ 15 01 00 00 00 00 02 14 8a
+ 15 01 00 00 00 00 02 15 0f
+ 15 01 00 00 00 00 02 16 10
+ 15 01 00 00 00 00 02 17 10
+ 15 01 00 00 00 00 02 18 1c
+ 15 01 00 00 00 00 02 19 00
+ 15 01 00 00 00 00 02 1a 00
+ 15 01 00 00 00 00 02 1b 00
+ 15 01 00 00 00 00 02 1c 00
+ 15 01 00 00 00 00 02 1d 13
+ 15 01 00 00 00 00 02 1e 15
+ 15 01 00 00 00 00 02 1f 17
+ 15 01 00 00 00 00 02 20 00
+ 15 01 00 00 00 00 02 21 01
+ 15 01 00 00 00 00 02 22 00
+ 15 01 00 00 00 00 02 23 40
+ 15 01 00 00 00 00 02 24 40
+ 15 01 00 00 00 00 02 25 6d
+ 15 01 00 00 00 00 02 26 40
+ 15 01 00 00 00 00 02 27 40
+ 15 01 00 00 00 00 02 29 d8
+ 15 01 00 00 00 00 02 2a 2a
+ 15 01 00 00 00 00 02 4b 03
+ 15 01 00 00 00 00 02 4c 11
+ 15 01 00 00 00 00 02 4d 10
+ 15 01 00 00 00 00 02 4e 01
+ 15 01 00 00 00 00 02 4f 01
+ 15 01 00 00 00 00 02 50 10
+ 15 01 00 00 00 00 02 51 00
+ 15 01 00 00 00 00 02 52 80
+ 15 01 00 00 00 00 02 53 00
+ 15 01 00 00 00 00 02 54 07
+ 15 01 00 00 00 00 02 55 25
+ 15 01 00 00 00 00 02 56 00
+ 15 01 00 00 00 00 02 58 07
+ 15 01 00 00 00 00 02 5b 43
+ 15 01 00 00 00 00 02 5c 00
+ 15 01 00 00 00 00 02 5f 73
+ 15 01 00 00 00 00 02 60 73
+ 15 01 00 00 00 00 02 63 22
+ 15 01 00 00 00 00 02 64 00
+ 15 01 00 00 00 00 02 67 08
+ 15 01 00 00 00 00 02 68 04
+ 15 01 00 00 00 00 02 7a 80
+ 15 01 00 00 00 00 02 7b 91
+ 15 01 00 00 00 00 02 7c d8
+ 15 01 00 00 00 00 02 7d 60
+ 15 01 00 00 00 00 02 93 06
+ 15 01 00 00 00 00 02 94 06
+ 15 01 00 00 00 00 02 8a 00
+ 15 01 00 00 00 00 02 9b 0f
+ 15 01 00 00 00 00 02 b3 c0
+ 15 01 00 00 00 00 02 b4 00
+ 15 01 00 00 00 00 02 b5 00
+ 15 01 00 00 00 00 02 b6 21
+ 15 01 00 00 00 00 02 b7 22
+ 15 01 00 00 00 00 02 b8 07
+ 15 01 00 00 00 00 02 b9 07
+ 15 01 00 00 00 00 02 ba 22
+ 15 01 00 00 00 00 02 bd 20
+ 15 01 00 00 00 00 02 be 07
+ 15 01 00 00 00 00 02 bf 07
+ 15 01 00 00 00 00 02 c1 6d
+ 15 01 00 00 00 00 02 c4 24
+ 15 01 00 00 00 00 02 e3 00
+ 15 01 00 00 00 00 02 ec 00
+ 15 01 00 00 00 00 02 ff 10
+ 15 01 00 00 00 00 02 bb 10
+ 15 01 00 00 00 00 02 35 02
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 78 00 02 29 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-dsi-tx-eot-append;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-audio.dtsi b/arch/arm/boot/dts/qcom/msm-audio.dtsi
index bc960093fcea..e34cf0426887 100644
--- a/arch/arm/boot/dts/qcom/msm-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-audio.dtsi
@@ -810,6 +810,7 @@
status = "disabled";
compatible = "qcom,sdm660-asoc-snd";
qcom,model = "sdm660-snd-card";
+ qcom,wsa-disable;
qcom,wcn-btfm;
qcom,mi2s-audio-intf;
qcom,auxpcm-audio-intf;
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index b1880c076e1c..be47b6483288 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -534,7 +534,6 @@
qcom,qpnp-ibb-soft-start = <1000>;
- qcom,qpnp-ibb-discharge-resistor = <32>;
qcom,qpnp-ibb-lab-pwrup-delay = <8000>;
qcom,qpnp-ibb-lab-pwrdn-delay = <8000>;
qcom,qpnp-ibb-en-discharge;
diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index 9490046133a3..30679791006b 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -1286,8 +1286,7 @@
compatible = "qcom,glink_ssr";
label = "modem";
qcom,edge = "mpss";
- qcom,notify-edges = <&glink_lpass>, <&glink_dsps>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_lpass>, <&glink_dsps>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1295,8 +1294,7 @@
compatible = "qcom,glink_ssr";
label = "adsp";
qcom,edge = "lpass";
- qcom,notify-edges = <&glink_mpss>, <&glink_dsps>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_mpss>, <&glink_dsps>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1304,8 +1302,7 @@
compatible = "qcom,glink_ssr";
label = "slpi";
qcom,edge = "dsps";
- qcom,notify-edges = <&glink_mpss>, <&glink_lpass>, <&glink_rpm>,
- <&glink_spss>;
+ qcom,notify-edges = <&glink_mpss>, <&glink_lpass>, <&glink_rpm>;
qcom,xprt = "smem";
};
@@ -1739,6 +1736,7 @@
"utmi_clk", "sleep_clk", "xo";
qcom,core-clk-rate = <120000000>;
+ qcom,core-clk-rate-hs = <60000000>;
resets = <&clock_gcc USB_30_BCR>;
reset-names = "core_reset";
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index 534d4c0c7822..e2344063ce16 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -27,3 +27,52 @@
&pm660_charger {
qcom,batteryless-platform;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ 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 = <110 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 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index c3f5d331a734..7a4e36ddda9e 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -36,3 +36,52 @@
&pm660_fg {
qcom,battery-data = <&mtp_batterydata>;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ 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 = <110 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 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-rumi.dts b/arch/arm/boot/dts/qcom/sdm630-rumi.dts
index ddf954f9f6ff..2ea1af4da90c 100644
--- a/arch/arm/boot/dts/qcom/sdm630-rumi.dts
+++ b/arch/arm/boot/dts/qcom/sdm630-rumi.dts
@@ -86,3 +86,52 @@
compatible = "qcom,dummycc";
clock-output-names = "debug_clocks";
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l4>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ 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 = <110 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 {
+ /* device core power supply */
+ vdd-supply = <&pm660l_l5>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <15000 800000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm660l_l2>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 125 0
+ 1 &intc 0 0 221 0
+ 2 &tlmm 54 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&tlmm 54 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index 973d86f52896..9aa83c07ebac 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -26,6 +26,8 @@
aliases {
serial0 = &uartblsp1dm1;
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+ sdhc2 = &sdhc_2; /* SDC2 for SD card */
};
chosen {
@@ -644,6 +646,21 @@
interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
};
+ qcom,bcl {
+ compatible = "qcom,bcl";
+ qcom,bcl-enable;
+ qcom,bcl-framework-interface;
+ qcom,bcl-hotplug-list = <&CPU2 &CPU3>;
+ qcom,bcl-soc-hotplug-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,ibat-monitor {
+ qcom,low-threshold-uamp = <3400000>;
+ qcom,high-threshold-uamp = <4200000>;
+ qcom,vph-high-threshold-uv = <3500000>;
+ qcom,vph-low-threshold-uv = <3300000>;
+ qcom,soc-low-threshold = <10>;
+ };
+ };
+
wdog: qcom,wdt@17817000 {
status = "disabled";
compatible = "qcom,msm-watchdog";
@@ -1108,7 +1125,6 @@
compatible = "qcom,rpm-glink";
qcom,glink-edge = "rpm";
rpm-channel-name = "rpm_requests";
- rpm-standalone;
};
qcom,ipc_router {
@@ -1382,6 +1398,116 @@
qcom,not-wakeup; /* Needed until Full-boot-chain enabled */
status = "ok";
};
+
+ qcom_seecom: qseecom@86d00000 {
+ compatible = "qcom,qseecom";
+ reg = <0x86d00000 0x2200000>;
+ reg-names = "secapp-region";
+ qcom,hlos-num-ce-hw-instances = <1>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,support-fde;
+ qcom,no-clock-support;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 200000 400000>,
+ <55 512 300000 800000>,
+ <55 512 400000 1000000>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_rpmcc QSEECOM_CE1_CLK>,
+ <&clock_rpmcc QSEECOM_CE1_CLK>,
+ <&clock_rpmcc QSEECOM_CE1_CLK>,
+ <&clock_rpmcc QSEECOM_CE1_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,qsee-reentrancy-support = <2>;
+ };
+
+ qcom_cedev: qcedev@1de0000{
+ compatible = "qcom,qcedev";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 206 0>;
+ qcom,bam-pipe-pair = <1>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,ce-hw-shared;
+ qcom,bam-ee = <0>;
+ qcom,msm-bus,name = "qcedev-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_rpmcc QCEDEV_CE1_CLK>,
+ <&clock_rpmcc QCEDEV_CE1_CLK>,
+ <&clock_rpmcc QCEDEV_CE1_CLK>,
+ <&clock_rpmcc QCEDEV_CE1_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ };
+
+ qcom_crypto: qcrypto@1de0000 {
+ compatible = "qcom,qcrypto";
+ reg = <0x1de0000 0x20000>,
+ <0x1dc4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 206 0>;
+ qcom,bam-pipe-pair = <2>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,bam-ee = <0>;
+ qcom,ce-hw-shared;
+ qcom,clk-mgmt-sus-res;
+ qcom,msm-bus,name = "qcrypto-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 393600 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_rpmcc QCRYPTO_CE1_CLK>,
+ <&clock_rpmcc QCRYPTO_CE1_CLK>,
+ <&clock_rpmcc QCRYPTO_CE1_CLK>,
+ <&clock_rpmcc QCRYPTO_CE1_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,use-sw-aes-cbc-ecb-ctr-algo;
+ qcom,use-sw-aes-xts-algo;
+ qcom,use-sw-aes-ccm-algo;
+ qcom,use-sw-ahash-algo;
+ qcom,use-sw-aead-algo;
+ qcom,use-sw-hmac-algo;
+ };
+
+ qcom_tzlog: tz-log@146bf720 {
+ compatible = "qcom,tz-log";
+ reg = <0x146bf720 0x3000>;
+ qcom,hyplog-enabled;
+ hyplog-address-offset = <0x410>;
+ hyplog-size-offset = <0x414>;
+ };
+
+ qcom_rng: qrng@793000 {
+ compatible = "qcom,msm-rng";
+ reg = <0x793000 0x1000>;
+ qcom,msm-rng-iface-clk;
+ qcom,no-qrng-config;
+ qcom,msm-bus,name = "msm-rng-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 618 0 0>, /* No vote */
+ <1 618 0 800>; /* 100 KHz */
+ clocks = <&clock_gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "iface_clk";
+ };
};
#include "sdm630-ion.dtsi"
diff --git a/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi b/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
index 023c34d65680..555d9a285102 100644
--- a/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-blsp.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -518,9 +518,10 @@
clocks = <&clock_gcc GCC_BLSP2_UART1_APPS_CLK>,
<&clock_gcc GCC_BLSP2_AHB_CLK>;
pinctrl-names = "sleep", "default";
- pinctrl-0 = <&blsp2_uart1_sleep>;
- pinctrl-1 = <&blsp2_uart1_active>;
-
+ pinctrl-0 = <&blsp2_uart1_tx_sleep>,
+ <&blsp2_uart1_rxcts_sleep>, <&blsp2_uart1_rfr_sleep>;
+ pinctrl-1 = <&blsp2_uart1_tx_active>,
+ <&blsp2_uart1_rxcts_active>, <&blsp2_uart1_rfr_active>;
qcom,msm-bus,name = "buart3";
qcom,msm-bus,num-cases = <2>;
qcom,msm-bus,num-paths = <1>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
index 676e970a7e73..0b82fbf7ffbc 100644
--- a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi
@@ -125,6 +125,20 @@
qcom,panel-roi-alignment = <720 128 720 128 1440 128>;
};
+&dsi_nt35695b_truly_fhd_video {
+ 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,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_nt35695b_truly_fhd_cmd {
+ 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,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
&sdhc_1 {
/* device core power supply */
vdd-supply = <&pm660l_l4>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
index f9915fbf3f58..a5e66f38df3c 100644
--- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi
@@ -321,4 +321,98 @@
reg = <0xa8f8000 0x300>;
qcom,reset-ep-after-lpm-resume;
};
+
+ sdhc_1: sdhci@c0c4000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0xc0c4000 0x1000>, <0xc0c5000 0x1000>;
+ reg-names = "hc_mem", "cmdq_mem";
+
+ interrupts = <0 110 0>, <0 112 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <8>;
+ qcom,large-address-bus;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <26 81>;
+ qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+ qcom,pm-qos-cmdq-latency-us = <26 81>, <26 81>;
+ qcom,pm-qos-legacy-latency-us = <26 81>, <26 81>;
+
+ qcom,msm-bus,name = "sdhc1";
+ qcom,msm-bus,num-cases = <9>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+ <78 512 1046 3200>, /* 400 KB/s*/
+ <78 512 52286 160000>, /* 20 MB/s */
+ <78 512 65360 200000>, /* 25 MB/s */
+ <78 512 130718 400000>, /* 50 MB/s */
+ <78 512 130718 400000>, /* 100 MB/s */
+ <78 512 261438 800000>, /* 200 MB/s */
+ <78 512 261438 800000>, /* 400 MB/s */
+ <78 512 1338562 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 400000000 4294967295>;
+
+ clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
+ <&clock_gcc GCC_SDCC1_APPS_CLK>,
+ <&clock_gcc GCC_SDCC1_ICE_CORE_CLK>;
+ clock-names = "iface_clk", "core_clk", "ice_core_clk";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 192000000 384000000>;
+
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,ice-clk-rates = <300000000 150000000>;
+
+ status = "disabled";
+ };
+
+ sdhc_2: sdhci@c084000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0xc084000 0x1000>;
+ reg-names = "hc_mem";
+
+ interrupts = <0 125 0>, <0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <4>;
+ qcom,large-address-bus;
+
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+ <81 512 1046 3200>, /* 400 KB/s */
+ <81 512 52286 160000>, /* 20 MB/s */
+ <81 512 65360 200000>, /* 25 MB/s */
+ <81 512 130718 400000>, /* 50 MB/s */
+ <81 512 261438 800000>, /* 100 MB/s */
+ <81 512 261438 800000>, /* 200 MB/s */
+ <81 512 1338562 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ qcom,pm-qos-irq-type = "affine_irq";
+ qcom,pm-qos-irq-latency = <26 81>;
+ qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+ qcom,pm-qos-legacy-latency-us = <26 81>, <26 81>;
+
+ clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
+ <&clock_gcc GCC_SDCC2_APPS_CLK>;
+ clock-names = "iface_clk", "core_clk";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50",
+ "SDR104";
+
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
index a25343981ace..da41c9127d90 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi
@@ -20,6 +20,8 @@
#include "dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi"
#include "dsi-panel-nt35597-dualmipi-wqxga-video.dtsi"
#include "dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi"
+#include "dsi-panel-nt35695b-truly-fhd-video.dtsi"
+#include "dsi-panel-nt35695b-truly-fhd-cmd.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -139,3 +141,19 @@
23 1e 07 08 05 03 04 a0
23 18 07 08 04 03 04 a0];
};
+
+&dsi_nt35695b_truly_fhd_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 18 07 08 04 03 04 a0];
+};
+
+&dsi_nt35695b_truly_fhd_cmd {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 1e 07 08 05 03 04 a0
+ 23 18 07 08 04 03 04 a0];
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dts b/arch/arm/boot/dts/qcom/sdm660-mtp.dts
index 97058d470446..72bfa20b2bf9 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dts
@@ -24,3 +24,7 @@
qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
<0x0001001b 0x0201011a 0x0 0x0>;
};
+
+&tavil_snd {
+ qcom,msm-mbhc-moist-cfg = <0>, <0>, <3>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index 0c933807cdd8..2c207873aa0b 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -1190,29 +1190,83 @@
};
};
- blsp2_uart1_active: blsp2_uart1_active {
- mux {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- function = "blsp_uart5";
+ blsp2_uart1: blsp2_uart1 {
+ blsp2_uart1_tx_active: blsp2_uart1_tx_active {
+ mux {
+ pins = "gpio16";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio16";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- drive-strength = <2>;
- bias-disable;
+ blsp2_uart1_tx_sleep: blsp2_uart1_tx_sleep {
+ mux {
+ pins = "gpio16";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio16";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
- };
- blsp2_uart1_sleep: blsp2_uart1_sleep {
- mux {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- function = "gpio";
+ blsp2_uart1_rxcts_active: blsp2_uart1_rxcts_active {
+ mux {
+ pins = "gpio17", "gpio18";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio17", "gpio18";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
- config {
- pins = "gpio16", "gpio17", "gpio18", "gpio19";
- drive-strength = <2>;
- bias-disable;
+ blsp2_uart1_rxcts_sleep: blsp2_uart1_rxcts_sleep {
+ mux {
+ pins = "gpio17", "gpio18";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio17", "gpio18";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
+ };
+
+ blsp2_uart1_rfr_active: blsp2_uart1_rfr_active {
+ mux {
+ pins = "gpio19";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart1_rfr_sleep: blsp2_uart1_rfr_sleep {
+ mux {
+ pins = "gpio19";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio19";
+ drive-strength = <2>;
+ bias-no-pull;
+ };
};
};
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 9bcc0ad84917..cab1821db191 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -104,6 +104,7 @@
str x20, [sp, #S_ORIG_ADDR_LIMIT]
mov x20, #TASK_SIZE_64
str x20, [tsk, #TI_ADDR_LIMIT]
+ ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO)
.endif /* \el == 0 */
mrs x22, elr_el1
mrs x23, spsr_el1
@@ -139,6 +140,8 @@
/* Restore the task's original addr_limit. */
ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
str x20, [tsk, #TI_ADDR_LIMIT]
+
+ /* No need to restore UAO, it will be restored from SPSR_EL1 */
.endif
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 68cd3bb8eb89..eacaee18645b 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -291,7 +291,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
}
if (permission_fault(esr) && (addr < USER_DS)) {
- if (get_fs() == KERNEL_DS)
+ /* regs->orig_addr_limit may be 0 if we entered from EL0 */
+ if (regs->orig_addr_limit == KERNEL_DS)
die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
if (!search_exception_tables(regs->pc))
diff --git a/drivers/clk/msm/clock-gcc-8998.c b/drivers/clk/msm/clock-gcc-8998.c
index 87cf6cc5631e..8b7efbd093b5 100644
--- a/drivers/clk/msm/clock-gcc-8998.c
+++ b/drivers/clk/msm/clock-gcc-8998.c
@@ -263,6 +263,7 @@ static struct rcg_clk hmss_ahb_clk_src = {
static struct clk_freq_tbl ftbl_usb30_master_clk_src[] = {
F( 19200000, cxo_clk_src, 1, 0, 0),
+ F( 60000000, gpll0_out_main, 10, 0, 0),
F( 120000000, gpll0_out_main, 5, 0, 0),
F( 150000000, gpll0_out_main, 4, 0, 0),
F_END
diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c
index 0276952debbb..de21a231b73f 100644
--- a/drivers/devfreq/governor_msm_adreno_tz.c
+++ b/drivers/devfreq/governor_msm_adreno_tz.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -234,7 +234,7 @@ static int tz_init_ca(struct devfreq_msm_adreno_tz_data *priv)
{
unsigned int tz_ca_data[2];
struct scm_desc desc = {0};
- unsigned int *tz_buf;
+ u8 *tz_buf;
int ret;
/* Set data for TZ */
@@ -279,7 +279,7 @@ static int tz_init(struct devfreq_msm_adreno_tz_data *priv,
scm_is_call_available(SCM_SVC_DCVS, TZ_UPDATE_ID_64) &&
scm_is_call_available(SCM_SVC_DCVS, TZ_RESET_ID_64)) {
struct scm_desc desc = {0};
- unsigned int *tz_buf;
+ u8 *tz_buf;
if (!is_scm_armv8()) {
ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID_64,
diff --git a/drivers/gpu/msm/adreno_cp_parser.c b/drivers/gpu/msm/adreno_cp_parser.c
index 2ccb8139e6b8..d9645375c8a8 100644
--- a/drivers/gpu/msm/adreno_cp_parser.c
+++ b/drivers/gpu/msm/adreno_cp_parser.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -53,7 +53,7 @@ static int load_state_unit_sizes[7][2] = {
static int adreno_ib_find_objs(struct kgsl_device *device,
struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords,
- int obj_type,
+ uint64_t ib2base, int obj_type,
struct adreno_ib_object_list *ib_obj_list,
int ib_level);
@@ -483,7 +483,7 @@ static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt,
ret = adreno_ib_find_objs(device, process,
ib_parse_vars->set_draw_groups[i].cmd_stream_addr,
ib_parse_vars->set_draw_groups[i].cmd_stream_dwords,
- SNAPSHOT_GPU_OBJECT_DRAW,
+ 0, SNAPSHOT_GPU_OBJECT_DRAW,
ib_obj_list, 2);
if (ret)
break;
@@ -686,8 +686,8 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
if (cmd_stream_dwords)
ret = adreno_ib_find_objs(device, process,
cmd_stream_addr, cmd_stream_dwords,
- SNAPSHOT_GPU_OBJECT_DRAW, ib_obj_list,
- 2);
+ 0, SNAPSHOT_GPU_OBJECT_DRAW,
+ ib_obj_list, 2);
if (ret)
break;
continue;
@@ -698,7 +698,7 @@ static int ib_parse_type7_set_draw_state(struct kgsl_device *device,
gpuaddr = gpuaddr << 32 | ptr[i + 1];
ret = adreno_ib_find_objs(device, process,
gpuaddr, (ptr[i] & 0x0000FFFF),
- SNAPSHOT_GPU_OBJECT_IB,
+ 0, SNAPSHOT_GPU_OBJECT_IB,
ib_obj_list, 2);
if (ret)
break;
@@ -760,7 +760,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
if (flags & 0x8) {
ret = adreno_ib_find_objs(device, process,
ptr[i + 1], (ptr[i] & 0x0000FFFF),
- SNAPSHOT_GPU_OBJECT_IB,
+ 0, SNAPSHOT_GPU_OBJECT_IB,
ib_obj_list, 2);
if (ret)
break;
@@ -775,6 +775,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
* @process: Process in which the IB is allocated
* @gpuaddr: IB2 gpuaddr
* @dwords: IB2 size in dwords
+ * @ib2base: Base address of active IB2
* @ib_obj_list: List of objects found in IB
* @ib_level: The level from which function is called, either from IB1 or IB2
*
@@ -783,7 +784,7 @@ static int ib_parse_set_draw_state(struct kgsl_device *device,
*/
static int adreno_cp_parse_ib2(struct kgsl_device *device,
struct kgsl_process_private *process,
- uint64_t gpuaddr, uint64_t dwords,
+ uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
struct adreno_ib_object_list *ib_obj_list,
int ib_level)
{
@@ -794,6 +795,10 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
*/
if (2 == ib_level)
return -EINVAL;
+
+ /* Save current IB2 statically */
+ if (ib2base == gpuaddr)
+ kgsl_snapshot_push_object(process, gpuaddr, dwords);
/*
* only try to find sub objects iff this IB has
* not been processed already
@@ -807,7 +812,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
return 0;
}
- return adreno_ib_find_objs(device, process, gpuaddr, dwords,
+ return adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base,
SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 2);
}
@@ -816,6 +821,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
* @device: The device pointer on which the IB executes
* @process: The process in which the IB and all contained objects are mapped.
* @gpuaddr: The gpu address of the IB
+ * @ib2base: IB2 base address
* @dwords: Size of ib in dwords
* @obj_type: The object type can be either an IB or a draw state sequence
* @ib_obj_list: The list in which the IB and the objects in it are added.
@@ -828,7 +834,7 @@ static int adreno_cp_parse_ib2(struct kgsl_device *device,
static int adreno_ib_find_objs(struct kgsl_device *device,
struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords,
- int obj_type,
+ uint64_t ib2base, int obj_type,
struct adreno_ib_object_list *ib_obj_list,
int ib_level)
{
@@ -904,7 +910,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
uint64_t size = src[i + 2];
ret = adreno_cp_parse_ib2(device, process,
- gpuaddrib2, size,
+ gpuaddrib2, size, ib2base,
ib_obj_list, ib_level);
if (ret)
goto done;
@@ -930,7 +936,7 @@ static int adreno_ib_find_objs(struct kgsl_device *device,
gpuaddrib2 = gpuaddrib2 << 32 | src[i + 1];
ret = adreno_cp_parse_ib2(device, process,
- gpuaddrib2, size,
+ gpuaddrib2, size, ib2base,
ib_obj_list, ib_level);
if (ret)
goto done;
@@ -982,6 +988,7 @@ done:
* @process: The process in which the IB and all contained objects are mapped
* @gpuaddr: The gpu address of the IB
* @dwords: Size of ib in dwords
+ * @ib2base: Base address of active IB2
* @ib_obj_list: The list in which the IB and the objects in it are added.
*
* Find all the memory objects that an IB needs for execution and place
@@ -993,7 +1000,7 @@ done:
*/
int adreno_ib_create_object_list(struct kgsl_device *device,
struct kgsl_process_private *process,
- uint64_t gpuaddr, uint64_t dwords,
+ uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
struct adreno_ib_object_list **out_ib_obj_list)
{
int ret = 0;
@@ -1016,7 +1023,7 @@ int adreno_ib_create_object_list(struct kgsl_device *device,
return -ENOMEM;
}
- ret = adreno_ib_find_objs(device, process, gpuaddr, dwords,
+ ret = adreno_ib_find_objs(device, process, gpuaddr, dwords, ib2base,
SNAPSHOT_GPU_OBJECT_IB, ib_obj_list, 1);
/* Even if there was an error return the remaining objects found */
diff --git a/drivers/gpu/msm/adreno_cp_parser.h b/drivers/gpu/msm/adreno_cp_parser.h
index 0248de2d600a..f4d6cd99226e 100644
--- a/drivers/gpu/msm/adreno_cp_parser.h
+++ b/drivers/gpu/msm/adreno_cp_parser.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014,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
@@ -178,7 +178,7 @@ static inline int adreno_cp_parser_regindex(struct adreno_device *adreno_dev,
int adreno_ib_create_object_list(
struct kgsl_device *device,
struct kgsl_process_private *process,
- uint64_t gpuaddr, uint64_t dwords,
+ uint64_t gpuaddr, uint64_t dwords, uint64_t ib2base,
struct adreno_ib_object_list **out_ib_obj_list);
void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list);
diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c
index f5f99c3ebb4a..5fecdcfb6364 100644
--- a/drivers/gpu/msm/adreno_perfcounter.c
+++ b/drivers/gpu/msm/adreno_perfcounter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -638,6 +638,9 @@ static void _perfcounter_enable_vbif_pwr(struct adreno_device *adreno_dev,
static void _power_counter_enable_alwayson(struct adreno_device *adreno_dev,
struct adreno_perfcounters *counters)
{
+ if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
+ return;
+
kgsl_regwrite(KGSL_DEVICE(adreno_dev),
A5XX_GPMU_ALWAYS_ON_COUNTER_RESET, 1);
counters->groups[KGSL_PERFCOUNTER_GROUP_ALWAYSON_PWR].regs[0].value = 0;
@@ -674,6 +677,9 @@ static void _power_counter_enable_default(struct adreno_device *adreno_dev,
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_perfcount_register *reg;
+ if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
+ return;
+
reg = &counters->groups[group].regs[counter];
kgsl_regwrite(device, reg->select, countable);
kgsl_regwrite(device, A5XX_GPMU_POWER_COUNTER_ENABLE, 1);
@@ -927,6 +933,9 @@ static uint64_t _perfcounter_read_pwrcntr(struct adreno_device *adreno_dev,
struct adreno_perfcount_register *reg;
unsigned int lo = 0, hi = 0;
+ if (!ADRENO_FEATURE(adreno_dev, ADRENO_GPMU))
+ return 0;
+
reg = &group->regs[counter];
kgsl_regread(device, reg->offset, &lo);
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 08d7d3c1b935..711d7ba83e61 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.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
@@ -27,8 +27,6 @@
#define SNAPSHOT_OBJ_BUFSIZE 64
-#define SNAPSHOT_OBJ_TYPE_IB 0
-
/* Used to print error message if an IB has too many objects in it */
static int ib_max_objs;
@@ -53,8 +51,7 @@ static inline int adreno_rb_ctxtswitch(struct adreno_device *adreno_dev,
}
/* Push a new buffer object onto the list */
-static void push_object(int type,
- struct kgsl_process_private *process,
+void kgsl_snapshot_push_object(struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords)
{
int index;
@@ -101,7 +98,6 @@ static void push_object(int type,
}
/* Put it on the list of things to parse */
- objbuf[objbufptr].type = type;
objbuf[objbufptr].gpuaddr = gpuaddr;
objbuf[objbufptr].size = dwords << 2;
objbuf[objbufptr++].entry = entry;
@@ -112,8 +108,7 @@ static void push_object(int type,
* to be dumped
*/
-static int find_object(int type, uint64_t gpuaddr,
- struct kgsl_process_private *process)
+static int find_object(uint64_t gpuaddr, struct kgsl_process_private *process)
{
int index;
@@ -131,14 +126,12 @@ static int find_object(int type, uint64_t gpuaddr,
* @snapshot: The snapshot data.
* @process: The process to which the IB belongs
* @ib_obj_list: List of the IB objects
- * @ib2base: IB2 base address at time of the fault
*
* Returns 0 on success else error code
*/
static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
struct kgsl_process_private *process,
- struct adreno_ib_object_list *ib_obj_list,
- uint64_t ib2base)
+ struct adreno_ib_object_list *ib_obj_list)
{
int ret = 0;
struct adreno_ib_object *ib_objs;
@@ -163,21 +156,15 @@ static int snapshot_freeze_obj_list(struct kgsl_snapshot *snapshot,
}
if (freeze) {
- /* Save current IB2 statically */
- if (ib2base == ib_objs->gpuaddr) {
- push_object(SNAPSHOT_OBJ_TYPE_IB,
- process, ib_objs->gpuaddr, ib_objs->size >> 2);
+ temp_ret = kgsl_snapshot_get_object(snapshot,
+ process, ib_objs->gpuaddr,
+ ib_objs->size,
+ ib_objs->snapshot_obj_type);
+ if (temp_ret < 0) {
+ if (ret >= 0)
+ ret = temp_ret;
} else {
- temp_ret = kgsl_snapshot_get_object(snapshot,
- process, ib_objs->gpuaddr,
- ib_objs->size,
- ib_objs->snapshot_obj_type);
- if (temp_ret < 0) {
- if (ret >= 0)
- ret = temp_ret;
- } else {
- snapshot_frozen_objsize += temp_ret;
- }
+ snapshot_frozen_objsize += temp_ret;
}
}
}
@@ -203,8 +190,7 @@ static inline void parse_ib(struct kgsl_device *device,
* list
*/
if (gpuaddr == snapshot->ib1base) {
- push_object(SNAPSHOT_OBJ_TYPE_IB, process,
- gpuaddr, dwords);
+ kgsl_snapshot_push_object(process, gpuaddr, dwords);
return;
}
@@ -213,7 +199,8 @@ static inline void parse_ib(struct kgsl_device *device,
return;
if (-E2BIG == adreno_ib_create_object_list(device, process,
- gpuaddr, dwords, &ib_obj_list))
+ gpuaddr, dwords, snapshot->ib2base,
+ &ib_obj_list))
ib_max_objs = 1;
if (ib_obj_list)
@@ -559,8 +546,7 @@ void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
int index = -ENOENT;
if (!snapshot->ib1dumped)
- index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
- snapshot->process);
+ index = find_object(snapshot->ib1base, snapshot->process);
/* only do this for IB1 because the IB2's are part of IB1 objects */
if ((index != -ENOENT) &&
@@ -569,19 +555,19 @@ void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
objbuf[index].entry->priv,
objbuf[index].gpuaddr,
objbuf[index].size >> 2,
+ snapshot->ib2base,
&ib_obj_list))
ib_max_objs = 1;
if (ib_obj_list) {
/* freeze the IB objects in the IB */
snapshot_freeze_obj_list(snapshot,
objbuf[index].entry->priv,
- ib_obj_list, snapshot->ib2base);
+ ib_obj_list);
adreno_ib_destroy_obj_list(ib_obj_list);
}
} else {
/* Get the IB2 index from parsed object */
- index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
- snapshot->process);
+ index = find_object(snapshot->ib2base, snapshot->process);
if (index != -ENOENT)
parse_ib(device, snapshot, snapshot->process,
@@ -624,6 +610,7 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
struct adreno_ib_object_list *ib_obj_list;
struct kgsl_snapshot *snapshot;
struct kgsl_snapshot_object *obj;
+ struct kgsl_memdesc *memdesc;
if (meta == NULL || meta->snapshot == NULL || meta->obj == NULL) {
KGSL_CORE_ERR("snapshot: bad metadata");
@@ -631,13 +618,18 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
}
snapshot = meta->snapshot;
obj = meta->obj;
+ memdesc = &obj->entry->memdesc;
+
+ /* If size is zero get it from the medesc size */
+ if (!obj->size)
+ obj->size = (memdesc->size - (obj->gpuaddr - memdesc->gpuaddr));
if (remain < (obj->size + sizeof(*header))) {
KGSL_CORE_ERR("snapshot: Not enough memory for the ib\n");
return 0;
}
- src = kgsl_gpuaddr_to_vaddr(&obj->entry->memdesc, obj->gpuaddr);
+ src = kgsl_gpuaddr_to_vaddr(memdesc, obj->gpuaddr);
if (src == NULL) {
KGSL_DRV_ERR(device,
"snapshot: Unable to map GPU memory object 0x%016llX into the kernel\n",
@@ -653,13 +645,14 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
if (-E2BIG == adreno_ib_create_object_list(device,
obj->entry->priv,
obj->gpuaddr, obj->size >> 2,
+ snapshot->ib2base,
&ib_obj_list))
ib_max_objs = 1;
if (ib_obj_list) {
/* freeze the IB objects in the IB */
snapshot_freeze_obj_list(snapshot,
obj->entry->priv,
- ib_obj_list, meta->ib2base);
+ ib_obj_list);
adreno_ib_destroy_obj_list(ib_obj_list);
}
}
@@ -688,26 +681,18 @@ static void dump_object(struct kgsl_device *device, int obj,
{
struct snapshot_ib_meta meta;
- switch (objbuf[obj].type) {
- case SNAPSHOT_OBJ_TYPE_IB:
- meta.snapshot = snapshot;
- meta.obj = &objbuf[obj];
- meta.ib1base = snapshot->ib1base;
- meta.ib1size = snapshot->ib1size;
- meta.ib2base = snapshot->ib2base;
- meta.ib2size = snapshot->ib2size;
+ meta.snapshot = snapshot;
+ meta.obj = &objbuf[obj];
+ meta.ib1base = snapshot->ib1base;
+ meta.ib1size = snapshot->ib1size;
+ meta.ib2base = snapshot->ib2base;
+ meta.ib2size = snapshot->ib2size;
- kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2,
+ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2,
snapshot, snapshot_ib, &meta);
- if (objbuf[obj].entry) {
- kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc));
- kgsl_mem_entry_put(objbuf[obj].entry);
- }
- break;
- default:
- KGSL_CORE_ERR("snapshot: Invalid snapshot object type: %d\n",
- objbuf[obj].type);
- break;
+ if (objbuf[obj].entry) {
+ kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc));
+ kgsl_mem_entry_put(objbuf[obj].entry);
}
}
@@ -909,10 +894,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* figure how often this really happens.
*/
- if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
- snapshot->process) && snapshot->ib1size) {
- push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
- snapshot->ib1base, snapshot->ib1size);
+ if (-ENOENT == find_object(snapshot->ib1base, snapshot->process) &&
+ snapshot->ib1size) {
+ kgsl_snapshot_push_object(snapshot->process, snapshot->ib1base,
+ snapshot->ib1size);
KGSL_CORE_ERR(
"CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n",
snapshot->ib1size);
@@ -926,10 +911,9 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* correct size.
*/
- if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
- snapshot->process)) {
- push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
- snapshot->ib2base, snapshot->ib2size);
+ if (-ENOENT == find_object(snapshot->ib2base, snapshot->process)) {
+ kgsl_snapshot_push_object(snapshot->process, snapshot->ib2base,
+ snapshot->ib2size);
}
/*
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index e2ded87b7431..2cb8b8fdf890 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -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
@@ -255,4 +255,6 @@ struct kgsl_snapshot_gpu_object_v2 {
__u64 size; /* Size of the object (in dwords) */
} __packed;
+void kgsl_snapshot_push_object(struct kgsl_process_private *process,
+ uint64_t gpuaddr, uint64_t dwords);
#endif
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 782b0eaa3648..78d3dd9d752a 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 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
@@ -298,7 +298,7 @@ static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
vmem_plus = 1;
dprintk(VIDC_WARN,
"could not calculate vmem ab value due to core freq mismatch\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
}
exit:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index babea6824c51..b36e3739e43b 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.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
@@ -1313,7 +1313,11 @@ static void cleanup_instance(struct msm_vidc_inst *inst)
debugfs_remove_recursive(inst->debugfs_root);
mutex_lock(&inst->pending_getpropq.lock);
- WARN_ON(!list_empty(&inst->pending_getpropq.list));
+ if (!list_empty(&inst->pending_getpropq.list)) {
+ dprintk(VIDC_ERR,
+ "pending_getpropq not empty\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
mutex_unlock(&inst->pending_getpropq.lock);
}
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index 11d8621564a6..39ac6273f34e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -23,6 +23,7 @@
#endif
#define VIDC_DBG_TAG VIDC_DBG_LABEL ": %4s: "
+#define VIDC_DBG_WARN_ENABLE (msm_vidc_debug & VIDC_INFO)
/* To enable messages OR these values and
* echo the result to debugfs file.
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 30d1bae48e7d..777fb52b2201 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.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
@@ -105,7 +105,11 @@ static int __tzbsp_set_video_state(enum tzbsp_video_state state);
*/
static inline void __strict_check(struct venus_hfi_device *device)
{
- WARN_ON(!mutex_is_locked(&device->lock));
+ if (!mutex_is_locked(&device->lock)) {
+ dprintk(VIDC_WARN,
+ "device->lock mutex is not locked\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
}
static inline void __set_state(struct venus_hfi_device *device,
@@ -267,7 +271,7 @@ static int __acquire_regulator(struct regulator_info *rinfo)
if (!regulator_is_enabled(rinfo->regulator)) {
dprintk(VIDC_WARN, "Regulator is not enabled %s\n",
rinfo->name);
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
}
return rc;
@@ -617,7 +621,7 @@ static void __write_register(struct venus_hfi_device *device,
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"HFI Write register failed : Power is OFF\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return;
}
@@ -643,7 +647,7 @@ static int __read_register(struct venus_hfi_device *device, u32 reg)
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"HFI Read register failed : Power is OFF\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return -EINVAL;
}
@@ -1360,7 +1364,7 @@ static int __halt_axi(struct venus_hfi_device *device)
if (!device->power_enabled) {
dprintk(VIDC_WARN,
"Clocks are OFF, skipping AXI HALT\n");
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return -EINVAL;
}
@@ -3530,7 +3534,11 @@ static int __response_handler(struct venus_hfi_device *device)
if (session_id) {
struct hal_session *session = NULL;
- WARN_ON(upper_32_bits((uintptr_t)*session_id) != 0);
+ if (upper_32_bits((uintptr_t)*session_id) != 0) {
+ dprintk(VIDC_WARN,
+ "Upper 32 bits of session_id != 0\n");
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
+ }
session = __get_session(device,
(u32)(uintptr_t)*session_id);
if (!session) {
@@ -4088,7 +4096,7 @@ static int __disable_regulator(struct regulator_info *rinfo)
disable_regulator_failed:
/* Bring attention to this issue */
- WARN_ON(1);
+ WARN_ON(VIDC_DBG_WARN_ENABLE);
return rc;
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 46daa96a68a3..3c6dba648574 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -46,11 +46,20 @@ struct ath10k_ce_pipe;
#define CE_DESC_FLAGS_META_DATA_MASK ar->hw_values->ce_desc_meta_data_mask
#define CE_DESC_FLAGS_META_DATA_LSB ar->hw_values->ce_desc_meta_data_lsb
+#ifndef CONFIG_ATH10K_SNOC
struct ce_desc {
__le32 addr;
__le16 nbytes;
__le16 flags; /* %CE_DESC_FLAGS_ */
};
+#else
+struct ce_desc {
+ __le64 addr;
+ u16 nbytes; /* length in register map */
+ u16 flags; /* fw_metadata_high */
+ u32 toeplitz_hash_result;
+};
+#endif
struct ath10k_ce_ring {
/* Number of entries in this ring; must be power of 2 */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 21ae8d663e67..bf77ac66c79e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1560,10 +1560,22 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
+/* WAR: WCN3990 fw loading is done by PIL, assign WMI/HTT version */
+static inline void init_fw_param(struct ath10k *ar,
+ struct ath10k_fw_file *fw_file)
+{
+ if (QCA_REV_WCN3990(ar)) {
+ fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_HL_1_0;
+ fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
+ }
+}
+
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;
+ init_fw_param(ar, &ar->normal_mode_fw.fw_file);
+
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
@@ -1666,6 +1678,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
ar->max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
@@ -1712,6 +1725,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
break;
case ATH10K_FW_WMI_OP_VERSION_10_4:
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 175aae38c375..c01f59955797 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -451,8 +451,16 @@ static const char *htc_service_name(enum ath10k_htc_svc_id id)
return "NMI Data";
case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
return "HTT Data";
+ case ATH10K_HTC_SVC_ID_HTT_DATA2_MSG:
+ return "HTT Data";
+ case ATH10K_HTC_SVC_ID_HTT_DATA3_MSG:
+ return "HTT Data";
+ case ATH10K_HTC_SVC_ID_HTT_IPA_MSG:
+ return "IPA";
case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
return "RAW";
+ case ATH10K_HTC_SVC_ID_HTT_LOG_MSG:
+ return "PKTLOG";
}
return "Unknown";
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 0c55cd92a951..5f28099b2c88 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -222,7 +222,8 @@ enum ath10k_htc_svc_gid {
ATH10K_HTC_SVC_GRP_WMI = 1,
ATH10K_HTC_SVC_GRP_NMI = 2,
ATH10K_HTC_SVC_GRP_HTT = 3,
-
+ ATH10K_IPA_SERVICE_GROUP = 5,
+ ATH10K_LOG_SERVICE_GROUP = 6,
ATH10K_HTC_SVC_GRP_TEST = 254,
ATH10K_HTC_SVC_GRP_LAST = 255,
};
@@ -246,7 +247,10 @@ enum ath10k_htc_svc_id {
ATH10K_HTC_SVC_ID_NMI_DATA = SVC(ATH10K_HTC_SVC_GRP_NMI, 1),
ATH10K_HTC_SVC_ID_HTT_DATA_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 0),
-
+ ATH10K_HTC_SVC_ID_HTT_DATA2_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 1),
+ ATH10K_HTC_SVC_ID_HTT_DATA3_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 2),
+ ATH10K_HTC_SVC_ID_HTT_IPA_MSG = SVC(ATH10K_IPA_SERVICE_GROUP, 0),
+ ATH10K_HTC_SVC_ID_HTT_LOG_MSG = SVC(ATH10K_LOG_SERVICE_GROUP, 0),
/* raw stream service (i.e. flash, tcmd, calibration apps) */
ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0),
};
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 09bdd4bbc3be..78df1d1ad67c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -27,6 +27,7 @@
#define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX
#define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
+#define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
/* when under memory pressure rx ring refill may fail and needs a retry */
#define HTT_RX_RING_REFILL_RETRY_MS 50
@@ -474,7 +475,15 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
*/
htt->rx_ring.size = HTT_RX_RING_SIZE;
htt->rx_ring.size_mask = htt->rx_ring.size - 1;
- htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
+
+ switch (ar->hw_rev) {
+ case ATH10K_HW_WCN3990:
+ htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC;
+ break;
+ default:
+ htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
+ break;
+ }
if (!is_power_of_2(htt->rx_ring.size)) {
ath10k_warn(ar, "htt rx ring size is not power of 2\n");
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index d1c68992ead6..b7d9c23e17fa 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -184,6 +184,7 @@ enum ath10k_fw_wmi_op_version {
ATH10K_FW_WMI_OP_VERSION_TLV = 4,
ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
ATH10K_FW_WMI_OP_VERSION_10_4 = 6,
+ ATH10K_FW_WMI_OP_VERSION_HL_1_0 = 7,
/* keep last */
ATH10K_FW_WMI_OP_VERSION_MAX,
@@ -525,6 +526,11 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
#define TARGET_TLV_NUM_WOW_PATTERNS 22
+/* Target specific defines for WMI-HL-1.0 firmware */
+#define TARGET_HL_10_TLV_NUM_PEERS 14
+#define TARGET_HL_10_TLV_AST_SKID_LIMIT 6
+#define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2
+
/* Diagnostic Window */
#define CE_DIAG_PIPE 7
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index a6bad3e3de56..7a5bfeea8f3d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3899,16 +3899,12 @@ void __ath10k_scan_finish(struct ath10k *ar)
break;
case ATH10K_SCAN_RUNNING:
case ATH10K_SCAN_ABORTING:
- if (!ar->scan.is_roc) {
- struct cfg80211_scan_info info = {
- .aborted = (ar->scan.state ==
- ATH10K_SCAN_ABORTING),
- };
-
- ieee80211_scan_completed(ar->hw, &info);
- } else if (ar->scan.roc_notify) {
+ if (!ar->scan.is_roc)
+ ieee80211_scan_completed(ar->hw,
+ (ar->scan.state ==
+ ATH10K_SCAN_ABORTING));
+ else if (ar->scan.roc_notify)
ieee80211_remain_on_channel_expired(ar->hw);
- }
/* fall through */
case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE;
@@ -7959,6 +7955,7 @@ int ath10k_mac_register(struct ath10k *ar)
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) {
ar->hw->wiphy->iface_combinations =
ath10k_tlv_qcs_if_comb;
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 034e7a54c5b2..6260f11d4e32 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -205,12 +205,25 @@ struct rx_attention {
* descriptor.
*/
+#ifndef CONFIG_ATH10K_SNOC
struct rx_frag_info {
u8 ring0_more_count;
u8 ring1_more_count;
u8 ring2_more_count;
u8 ring3_more_count;
} __packed;
+#else
+struct rx_frag_info {
+ u8 ring0_more_count;
+ u8 ring1_more_count;
+ u8 ring2_more_count;
+ u8 ring3_more_count;
+ u8 ring4_more_count;
+ u8 ring5_more_count;
+ u8 ring6_more_count;
+ u8 ring7_more_count;
+} __packed;
+#endif
/*
* ring0_more_count
@@ -465,11 +478,23 @@ struct rx_msdu_start_qca99x0 {
__le32 info2; /* %RX_MSDU_START_INFO2_ */
} __packed;
+#ifdef CONFIG_ATH10K_SNOC
+struct rx_msdu_start_wcn3990 {
+ __le32 info3;
+} __packed;
+#else
+struct rx_msdu_start_wcn3990 {
+} __packed;
+#endif
+
struct rx_msdu_start {
struct rx_msdu_start_common common;
union {
struct rx_msdu_start_qca99x0 qca99x0;
} __packed;
+ union {
+ struct rx_msdu_start_wcn3990 wcn3990;
+ } __packed;
} __packed;
/*
@@ -589,10 +614,18 @@ struct rx_msdu_end_qca99x0 {
__le32 info2;
} __packed;
+struct rx_msdu_end_wcn3990 {
+ __le32 rule_indication_0;
+ __le32 rule_indication_1;
+ __le32 rule_indication_2;
+ __le32 rule_indication_3;
+} __packed;
+
struct rx_msdu_end {
struct rx_msdu_end_common common;
union {
struct rx_msdu_end_qca99x0 qca99x0;
+ struct rx_msdu_end_wcn3990 wcn3990;
} __packed;
} __packed;
@@ -953,8 +986,13 @@ struct rx_ppdu_end_qca6174 {
struct rx_pkt_end {
__le32 info0; /* %RX_PKT_END_INFO0_ */
+#ifndef CONFIG_ATH10K_SNOC
__le32 phy_timestamp_1;
__le32 phy_timestamp_2;
+#else
+ __le64 phy_timestamp_1;
+ __le64 phy_timestamp_2;
+#endif
} __packed;
#define RX_LOCATION_INFO0_RTT_FAC_LEGACY_MASK 0x00003fff
@@ -990,6 +1028,9 @@ struct rx_pkt_end {
struct rx_location_info {
__le32 rx_location_info0; /* %RX_LOCATION_INFO0_ */
__le32 rx_location_info1; /* %RX_LOCATION_INFO1_ */
+#ifdef CONFIG_ATH10K_SNOC
+ __le32 rx_location_info2; /* %RX_LOCATION_INFO2_ */
+#endif
} __packed;
enum rx_phy_ppdu_end_info0 {
@@ -1080,6 +1121,25 @@ struct rx_ppdu_end_qca9984 {
__le16 info1; /* %RX_PPDU_END_INFO1_ */
} __packed;
+struct rx_timing_offset {
+ __le32 timing_offset;
+ __le32 reserved;
+};
+
+struct rx_ppdu_end_wcn3990 {
+ __le32 reserved_info_0;
+ __le32 reserved_info_1;
+ __le32 rx_antenna_info;
+ __le32 rx_coex_info;
+ __le32 rx_mpdu_cnt_info;
+ __le32 rx_bb_length;
+ __le64 phy_timestamp_tx;
+ struct rx_pkt_end rx_pkt_end;
+ struct rx_phy_ppdu_end rx_phy_ppdu_end;
+ struct rx_timing_offset rx_timing_offset;
+ struct rx_location_info rx_location_info;
+} __packed;
+
struct rx_ppdu_end {
struct rx_ppdu_end_common common;
union {
@@ -1087,6 +1147,7 @@ struct rx_ppdu_end {
struct rx_ppdu_end_qca6174 qca6174;
struct rx_ppdu_end_qca99x0 qca99x0;
struct rx_ppdu_end_qca9984 qca9984;
+ struct rx_ppdu_end_wcn3990 wcn3990;
} __packed;
} __packed;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
new file mode 100644
index 000000000000..44d9e6c053a6
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -0,0 +1,704 @@
+/* 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/kernel.h>
+#include "debug.h"
+#include "hif.h"
+#include "htc.h"
+#include "ce.h"
+#include "snoc.h"
+#include <soc/qcom/icnss.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
+
+static struct ce_attr host_ce_config_wlan[] = {
+ /* CE0: host->target HTC control streams */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 16,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ .send_cb = ath10k_snoc_htc_tx_cb,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_snoc_htt_htc_rx_cb,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 64,
+ .recv_cb = ath10k_snoc_htc_rx_cb,
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ .send_cb = ath10k_snoc_htc_tx_cb,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = 256,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ .send_cb = ath10k_snoc_htt_tx_cb,
+ },
+
+ /* CE5: target->host HTT (ipa_uc->target ) */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 512,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_snoc_htt_rx_cb,
+ },
+
+ /* CE6: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE7: ce_diag, the Diagnostic Window */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 2,
+ .src_sz_max = 2048,
+ .dest_nentries = 2,
+ },
+
+ /* CE8: Target to uMC */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 128,
+ },
+
+ /* CE9 target->host HTT */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_snoc_htt_htc_rx_cb,
+ },
+
+ /* CE10: target->host HTT */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_snoc_htt_htc_rx_cb,
+ },
+
+ /* CE11: target -> host PKTLOG */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 512,
+ .recv_cb = ath10k_snoc_htt_htc_rx_cb,
+ },
+};
+
+static struct ce_pipe_config target_ce_config_wlan[] = {
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .pipenum = __cpu_to_le32(0),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .pipenum = __cpu_to_le32(1),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .pipenum = __cpu_to_le32(2),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(64),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .pipenum = __cpu_to_le32(3),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .pipenum = __cpu_to_le32(4),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(256),
+ .nbytes_max = __cpu_to_le32(256),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE5: target->host HTT (HIF->HTT) */
+ {
+ .pipenum = __cpu_to_le32(5),
+ .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+ .nentries = __cpu_to_le32(1024),
+ .nbytes_max = __cpu_to_le32(64),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE6: Reserved for target autonomous hif_memcpy */
+ {
+ .pipenum = __cpu_to_le32(6),
+ .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(16384),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE7 used only by Host */
+ {
+ .pipenum = __cpu_to_le32(7),
+ .pipedir = __cpu_to_le32(4),
+ .nentries = __cpu_to_le32(0),
+ .nbytes_max = __cpu_to_le32(0),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE8 Target to uMC */
+ {
+ .pipenum = __cpu_to_le32(8),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(0),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE9 target->host HTT */
+ {
+ .pipenum = __cpu_to_le32(9),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE10 target->host HTT */
+ {
+ .pipenum = __cpu_to_le32(10),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+
+ /* CE11 target autonomous qcache memcpy */
+ {
+ .pipenum = __cpu_to_le32(11),
+ .pipedir = __cpu_to_le32(PIPEDIR_IN),
+ .nentries = __cpu_to_le32(32),
+ .nbytes_max = __cpu_to_le32(2048),
+ .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+ .reserved = __cpu_to_le32(0),
+ },
+};
+
+static struct service_to_pipe target_service_to_ce_map_wlan[] = {
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BK),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_BE),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VI),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(3),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_CONTROL),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(0),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_RSVD_CTRL),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ { /* not used */
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(0),
+ },
+ { /* not used */
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(2),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
+ __cpu_to_le32(4),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(1),
+ },
+ {
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_IPA_MSG),
+ __cpu_to_le32(PIPEDIR_OUT),/* IPA service */
+ __cpu_to_le32(5),
+ },
+ { /* in = DL = target -> host */
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA2_MSG),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(9),
+ },
+ { /* in = DL = target -> host */
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA3_MSG),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(10),
+ },
+ { /* in = DL = target -> host pktlog */
+ __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_LOG_MSG),
+ __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
+ __cpu_to_le32(11),
+ },
+ /* (Additions here) */
+
+ { /* must be last */
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ __cpu_to_le32(0),
+ },
+};
+
+void ath10k_snoc_write32(void *ar, u32 offset, u32 value)
+{
+}
+
+u32 ath10k_snoc_read32(void *ar, u32 offset)
+{
+ u32 val = 0;
+ return val;
+}
+
+static int __ath10k_snoc_rx_post_buf(struct ath10k_snoc_pipe *pipe)
+{
+ struct ath10k *ar = pipe->hif_ce_state;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+ int ret;
+
+ skb = dev_alloc_skb(pipe->buf_sz);
+ if (!skb)
+ return -ENOMEM;
+
+ WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
+
+ paddr = dma_map_single(ar->dev, skb->data,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(ar->dev, paddr))) {
+ ath10k_warn(ar, "failed to dma map snoc rx buf\n");
+ dev_kfree_skb_any(skb);
+ return -EIO;
+ }
+
+ ATH10K_SKB_RXCB(skb)->paddr = paddr;
+
+ spin_lock_bh(&ar_snoc->ce_lock);
+ ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr);
+ spin_unlock_bh(&ar_snoc->ce_lock);
+ if (ret) {
+ dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(skb);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ath10k_snoc_rx_post_pipe(struct ath10k_snoc_pipe *pipe)
+{
+ struct ath10k *ar = pipe->hif_ce_state;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl;
+ int ret, num;
+
+ if (pipe->buf_sz == 0)
+ return;
+
+ if (!ce_pipe->dest_ring)
+ return;
+
+ spin_lock_bh(&ar_snoc->ce_lock);
+ num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
+ spin_unlock_bh(&ar_snoc->ce_lock);
+ while (num--) {
+ ret = __ath10k_snoc_rx_post_buf(pipe);
+ if (ret) {
+ if (ret == -ENOSPC)
+ break;
+ ath10k_warn(ar, "failed to post rx buf: %d\n", ret);
+ mod_timer(&ar_snoc->rx_post_retry, jiffies +
+ ATH10K_SNOC_RX_POST_RETRY_MS);
+ break;
+ }
+ }
+}
+
+static void ath10k_snoc_rx_post(struct ath10k *ar)
+{
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ int i;
+
+ for (i = 0; i < CE_COUNT; i++)
+ ath10k_snoc_rx_post_pipe(&ar_snoc->pipe_info[i]);
+}
+
+static void ath10k_snoc_rx_replenish_retry(unsigned long ptr)
+{
+ struct ath10k *ar = (void *)ptr;
+
+ ath10k_snoc_rx_post(ar);
+}
+
+static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ struct ath10k *ar = ce_state->ar;
+ struct sk_buff_head list;
+ struct sk_buff *skb;
+
+ __skb_queue_head_init(&list);
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
+ if (!skb)
+ continue;
+
+ __skb_queue_tail(&list, skb);
+ }
+
+ while ((skb = __skb_dequeue(&list)))
+ ath10k_htc_tx_completion_handler(ar, skb);
+}
+
+static void ath10k_snoc_process_rx_cb(struct ath10k_ce_pipe *ce_state,
+ void (*callback)(struct ath10k *ar,
+ struct sk_buff *skb))
+{
+ struct ath10k *ar = ce_state->ar;
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ struct ath10k_snoc_pipe *pipe_info = &ar_snoc->pipe_info[ce_state->id];
+ struct sk_buff *skb;
+ struct sk_buff_head list;
+ void *transfer_context;
+ unsigned int nbytes, max_nbytes;
+
+ __skb_queue_head_init(&list);
+ while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
+ &nbytes) == 0) {
+ skb = transfer_context;
+ max_nbytes = skb->len + skb_tailroom(skb);
+ dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
+ max_nbytes, DMA_FROM_DEVICE);
+
+ if (unlikely(max_nbytes < nbytes)) {
+ ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)",
+ nbytes, max_nbytes);
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+
+ skb_put(skb, nbytes);
+ __skb_queue_tail(&list, skb);
+ }
+
+ while ((skb = __skb_dequeue(&list))) {
+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc rx ce pipe %d len %d\n",
+ ce_state->id, skb->len);
+
+ callback(ar, skb);
+ }
+
+ ath10k_snoc_rx_post_pipe(pipe_info);
+}
+
+static void ath10k_snoc_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
+}
+
+static void ath10k_snoc_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ /* CE4 polling needs to be done whenever CE pipe which transports
+ * HTT Rx (target->host) is processed.
+ */
+ ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);
+
+ ath10k_snoc_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
+}
+
+static void ath10k_snoc_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ struct ath10k *ar = ce_state->ar;
+ struct sk_buff *skb;
+
+ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
+ /* no need to call tx completion for NULL pointers */
+ if (!skb)
+ continue;
+
+ dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
+ skb->len, DMA_TO_DEVICE);
+ ath10k_htt_hif_tx_complete(ar, skb);
+ }
+}
+
+static void ath10k_snoc_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb)
+{
+ skb_pull(skb, sizeof(struct ath10k_htc_hdr));
+ ath10k_htt_t2h_msg_handler(ar, skb);
+}
+
+static void ath10k_snoc_htt_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ /* CE4 polling needs to be done whenever CE pipe which transports
+ * HTT Rx (target->host) is processed.
+ */
+ ath10k_ce_per_engine_service(ce_state->ar, CE_POLL_PIPE);
+
+ ath10k_snoc_process_rx_cb(ce_state, ath10k_snoc_htt_rx_deliver);
+}
+
+static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
+ struct ath10k_hif_sg_item *items, int n_items)
+{
+ return 0;
+}
+
+static u16 ath10k_snoc_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
+{
+ return 0;
+}
+
+static void ath10k_snoc_hif_send_complete_check(struct ath10k *ar, u8 pipe,
+ int force)
+{
+}
+
+static int ath10k_snoc_hif_map_service_to_pipe(struct ath10k *ar,
+ u16 service_id,
+ u8 *ul_pipe, u8 *dl_pipe)
+{
+ return 0;
+}
+
+static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
+ u8 *ul_pipe, u8 *dl_pipe)
+{
+}
+
+static void ath10k_snoc_hif_stop(struct ath10k *ar)
+{
+}
+
+static void ath10k_snoc_hif_power_down(struct ath10k *ar)
+{
+}
+
+static int ath10k_snoc_hif_start(struct ath10k *ar)
+{
+ return 0;
+}
+
+static int ath10k_snoc_hif_power_up(struct ath10k *ar)
+{
+ return 0;
+}
+
+static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
+ .tx_sg = ath10k_snoc_hif_tx_sg,
+ .start = ath10k_snoc_hif_start,
+ .stop = ath10k_snoc_hif_stop,
+ .map_service_to_pipe = ath10k_snoc_hif_map_service_to_pipe,
+ .get_default_pipe = ath10k_snoc_hif_get_default_pipe,
+ .send_complete_check = ath10k_snoc_hif_send_complete_check,
+ .get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
+ .power_up = ath10k_snoc_hif_power_up,
+ .power_down = ath10k_snoc_hif_power_down,
+ .read32 = ath10k_snoc_read32,
+ .write32 = ath10k_snoc_write32,
+};
+
+static int ath10k_snoc_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct ath10k *ar;
+ struct ath10k_snoc *ar_snoc;
+ enum ath10k_hw_rev hw_rev;
+ struct device *dev;
+
+ dev = &pdev->dev;
+ hw_rev = ATH10K_HW_WCN3990;
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(37));
+ ar = ath10k_core_create(sizeof(*ar_snoc), dev, ATH10K_BUS_SNOC,
+ hw_rev, &ath10k_snoc_hif_ops);
+ if (!ar) {
+ dev_err(dev, "failed to allocate core\n");
+ return -ENOMEM;
+ }
+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 probed\n", __func__);
+
+ return ret;
+}
+
+static int ath10k_snoc_remove(struct platform_device *pdev)
+{
+ struct ath10k *ar = platform_get_drvdata(pdev);
+ struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+
+ if (!ar)
+ return -EINVAL;
+
+ if (!ar_snoc)
+ return -EINVAL;
+
+ ath10k_core_destroy(ar);
+ ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 removed\n", __func__);
+
+ return 0;
+}
+
+static const struct of_device_id ath10k_snoc_dt_match[] = {
+ {.compatible = "qcom,wcn3990-wifi"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, ath10k_snoc_dt_match);
+
+static struct platform_driver ath10k_snoc_driver = {
+ .probe = ath10k_snoc_probe,
+ .remove = ath10k_snoc_remove,
+ .driver = {
+ .name = "ath10k_snoc",
+ .owner = THIS_MODULE,
+ .of_match_table = ath10k_snoc_dt_match,
+ },
+};
+
+static int __init ath10k_snoc_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&ath10k_snoc_driver);
+ if (ret)
+ pr_err("failed to register ath10k snoc driver: %d\n",
+ ret);
+
+ return ret;
+}
+module_init(ath10k_snoc_init);
+
+static void __exit ath10k_snoc_exit(void)
+{
+ platform_driver_unregister(&ath10k_snoc_driver);
+}
+module_exit(ath10k_snoc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Driver support for Atheros WCN3990 SNOC devices");
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
new file mode 100644
index 000000000000..1db8b532f4fa
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -0,0 +1,204 @@
+/* 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 _SNOC_H_
+#define _SNOC_H_
+
+#include "hw.h"
+#include "ce.h"
+#include "pci.h"
+#define ATH10K_SNOC_RX_POST_RETRY_MS 50
+#define CE_POLL_PIPE 4
+
+/* struct snoc_state: SNOC target state
+ * @pipe_cfg_addr: pipe configuration address
+ * @svc_to_pipe_map: pipe services
+ */
+struct snoc_state {
+ u32 pipe_cfg_addr;
+ u32 svc_to_pipe_map;
+};
+
+/* struct ath10k_snoc_pipe: SNOC pipe configuration
+ * @ath10k_ce_pipe: pipe handle
+ * @pipe_num: pipe number
+ * @hif_ce_state: pointer to ce state
+ * @buf_sz: buffer size
+ * @pipe_lock: pipe lock
+ * @ar_snoc: snoc private structure
+ * @intr: tasklet structure
+ */
+
+struct ath10k_snoc_pipe {
+ struct ath10k_ce_pipe *ce_hdl;
+ u8 pipe_num;
+ struct ath10k *hif_ce_state;
+ size_t buf_sz;
+ /* protect ce info */
+ spinlock_t pipe_lock;
+ struct ath10k_snoc *ar_snoc;
+ struct tasklet_struct intr;
+};
+
+/* struct ath10k_snoc_supp_chip: supported chip set
+ * @dev_id: device id
+ * @rev_id: revison id
+ */
+struct ath10k_snoc_supp_chip {
+ u32 dev_id;
+ u32 rev_id;
+};
+
+/* struct ath10k_snoc_info: SNOC info struct
+ * @v_addr: base virtual address
+ * @p_addr: base physical address
+ * @chip_id: chip id
+ * @chip_family: chip family
+ * @board_id: board id
+ * @soc_id: soc id
+ * @fw_version: fw version
+ */
+struct ath10k_snoc_info {
+ void __iomem *v_addr;
+ phys_addr_t p_addr;
+ u32 chip_id;
+ u32 chip_family;
+ u32 board_id;
+ u32 soc_id;
+ u32 fw_version;
+};
+
+/* struct ath10k_target_info: SNOC target info
+ * @target_version: target version
+ * @target_type: target type
+ * @target_revision: target revision
+ * @soc_version: target soc version
+ */
+struct ath10k_target_info {
+ u32 target_version;
+ u32 target_type;
+ u32 target_revision;
+ u32 soc_version;
+};
+
+/* struct ath10k_snoc: SNOC info struct
+ * @dev: device structure
+ * @ar:ath10k base structure
+ * @mem: mem base virtual address
+ * @mem_pa: mem base physical address
+ * @target_info: snoc target info
+ * @mem_len: mempry map length
+ * @intr_tq: rx tasklet handle
+ * @pipe_info: pipe info struct
+ * @ce_lock: protect ce structures
+ * @ce_states: maps ce id to ce state
+ * @rx_post_retry: rx buffer post processing timer
+ * @vaddr_rri_on_ddr: virtual address for RRI
+ * @is_driver_probed: flag to indicate driver state
+ */
+struct ath10k_snoc {
+ struct device *dev;
+ struct ath10k *ar;
+ void __iomem *mem;
+ dma_addr_t mem_pa;
+ struct ath10k_target_info target_info;
+ size_t mem_len;
+ struct tasklet_struct intr_tq;
+ struct ath10k_snoc_pipe pipe_info[CE_COUNT_MAX];
+ /* protects CE info */
+ spinlock_t ce_lock;
+ struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
+ struct timer_list rx_post_retry;
+ u32 *vaddr_rri_on_ddr;
+ bool is_driver_probed;
+};
+
+/* struct ath10k_ce_tgt_pipe_cfg: target pipe configuration
+ * @pipe_num: pipe number
+ * @pipe_dir: pipe direction
+ * @nentries: entries in pipe
+ * @nbytes_max: pipe max size
+ * @flags: pipe flags
+ * @reserved: reserved
+ */
+struct ath10k_ce_tgt_pipe_cfg {
+ u32 pipe_num;
+ u32 pipe_dir;
+ u32 nentries;
+ u32 nbytes_max;
+ u32 flags;
+ u32 reserved;
+};
+
+/* struct ath10k_ce_svc_pipe_cfg: service pipe configuration
+ * @service_id: target version
+ * @pipe_dir: pipe direction
+ * @pipe_num: pipe number
+ */
+struct ath10k_ce_svc_pipe_cfg {
+ u32 service_id;
+ u32 pipe_dir;
+ u32 pipe_num;
+};
+
+/* struct ath10k_shadow_reg_cfg: shadow register configuration
+ * @ce_id: copy engine id
+ * @reg_offset: offset to copy engine
+ */
+struct ath10k_shadow_reg_cfg {
+ u16 ce_id;
+ u16 reg_offset;
+};
+
+/* struct ath10k_wlan_enable_cfg: wlan enable configuration
+ * @num_ce_tgt_cfg: no of ce target configuration
+ * @ce_tgt_cfg: target ce configuration
+ * @num_ce_svc_pipe_cfg: no of ce service configuration
+ * @ce_svc_cfg: ce service configuration
+ * @num_shadow_reg_cfg: no of shadow registers
+ * @shadow_reg_cfg: shadow register configuration
+ */
+struct ath10k_wlan_enable_cfg {
+ u32 num_ce_tgt_cfg;
+ struct ath10k_ce_tgt_pipe_cfg *ce_tgt_cfg;
+ u32 num_ce_svc_pipe_cfg;
+ struct ath10k_ce_svc_pipe_cfg *ce_svc_cfg;
+ u32 num_shadow_reg_cfg;
+ struct ath10k_shadow_reg_cfg *shadow_reg_cfg;
+};
+
+/* enum ath10k_driver_mode: ath10k driver mode
+ * @ATH10K_MISSION: mission mode
+ * @ATH10K_FTM: ftm mode
+ * @ATH10K_EPPING: epping mode
+ * @ATH10K_OFF: off mode
+ */
+enum ath10k_driver_mode {
+ ATH10K_MISSION,
+ ATH10K_FTM,
+ ATH10K_EPPING,
+ ATH10K_OFF
+};
+
+static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
+{
+ return (struct ath10k_snoc *)ar->drv_priv;
+}
+
+void ath10k_snoc_write32(void *ar, u32 offset, u32 value);
+void ath10k_snoc_soc_write32(struct ath10k *ar, u32 addr, u32 val);
+void ath10k_snoc_reg_write32(struct ath10k *ar, u32 addr, u32 val);
+u32 ath10k_snoc_read32(void *ar, u32 offset);
+u32 ath10k_snoc_soc_read32(struct ath10k *ar, u32 addr);
+u32 ath10k_snoc_reg_read32(struct ath10k *ar, u32 addr);
+
+#endif /* _SNOC_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index e64f59300a7c..7a8f9cfd8253 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -937,7 +937,12 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
ev = tb[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT];
reg = tb[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES];
- svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
+ if (QCA_REV_WCN3990(ar)) {
+ svc_bmap = (__le32 *)(skb->data +
+ WMI_TLV_TAG_STRUCT_HL_1_0_SVC_OFFSET);
+ } else {
+ svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
+ }
mem_reqs = tb[WMI_TLV_TAG_ARRAY_STRUCT];
if (!ev || !reg || !svc_bmap || !mem_reqs) {
@@ -1400,7 +1405,18 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
- cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
+ if (QCA_REV_WCN3990(ar)) {
+ cfg->num_peers = __cpu_to_le32(TARGET_HL_10_TLV_NUM_PEERS);
+ cfg->ast_skid_limit =
+ __cpu_to_le32(TARGET_HL_10_TLV_AST_SKID_LIMIT);
+ cfg->num_wds_entries =
+ __cpu_to_le32(TARGET_HL_10_TLV_NUM_WDS_ENTRIES);
+ } else {
+ cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS);
+ cfg->ast_skid_limit = __cpu_to_le32(0x10);
+ cfg->num_wds_entries = __cpu_to_le32(0x20);
+ }
+
if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) {
cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
@@ -1412,7 +1428,6 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_peer_keys = __cpu_to_le32(2);
cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS);
- cfg->ast_skid_limit = __cpu_to_le32(0x10);
cfg->tx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_chain_mask = __cpu_to_le32(0x7);
cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64);
@@ -1428,7 +1443,6 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
cfg->num_mcast_table_elems = __cpu_to_le32(0);
cfg->mcast2ucast_mode = __cpu_to_le32(0);
cfg->tx_dbg_log_size = __cpu_to_le32(0x400);
- cfg->num_wds_entries = __cpu_to_le32(0x20);
cfg->dma_burst_size = __cpu_to_le32(0);
cfg->mac_aggr_delim = __cpu_to_le32(0);
cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0);
@@ -3562,7 +3576,78 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
.pmf = WMI_TLV_PEER_PMF,
};
-/************/
+static const struct wmi_ops wmi_hl_1_0_ops = {
+ .rx = ath10k_wmi_tlv_op_rx,
+ .map_svc = wmi_hl_1_0_svc_map,
+ .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev,
+ .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev,
+ .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev,
+ .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev,
+ .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev,
+ .pull_swba = ath10k_wmi_tlv_op_pull_swba_ev,
+ .pull_phyerr_hdr = ath10k_wmi_tlv_op_pull_phyerr_ev_hdr,
+ .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev,
+ .pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev,
+ .pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev,
+ .pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
+ .pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
+ .pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
+ .get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
+ .gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
+ .gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
+ .gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd,
+ .gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param,
+ .gen_init = ath10k_wmi_tlv_op_gen_init,
+ .gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan,
+ .gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan,
+ .gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create,
+ .gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete,
+ .gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start,
+ .gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop,
+ .gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up,
+ .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down,
+ .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param,
+ .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key,
+ .gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf,
+ .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create,
+ .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete,
+ .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush,
+ .gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param,
+ .gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc,
+ .gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode,
+ .gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps,
+ .gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps,
+ .gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list,
+ .gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma,
+ .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm,
+ .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats,
+ .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
+ .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
+ .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
+ .gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl,
+ .gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl,
+ .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
+ .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
+ .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
+ .gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
+ .gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
+ .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
+ .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
+ .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
+ .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
+ .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
+ .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
+};
+
+void ath10k_wmi_hl_1_0_attach(struct ath10k *ar)
+{
+ ar->wmi.cmd = &wmi_tlv_cmd_map;
+ ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
+ ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
+ ar->wmi.ops = &wmi_hl_1_0_ops;
+}
+
/* TLV init */
/************/
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index b8aa6000573c..496fee5d489b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -889,6 +889,7 @@ enum wmi_tlv_tag {
WMI_TLV_TAG_STRUCT_SAP_OFL_DEL_STA_EVENT,
WMI_TLV_TAG_STRUCT_APFIND_CMD_PARAM,
WMI_TLV_TAG_STRUCT_APFIND_EVENT_HDR,
+ WMI_TLV_TAG_STRUCT_HL_1_0_SVC_OFFSET = 176,
WMI_TLV_TAG_MAX
};
@@ -966,6 +967,125 @@ enum wmi_tlv_service {
WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
};
+enum wmi_hl_10_service {
+ WMI_HL_10_SERVICE_BEACON_OFFLOAD = 0,
+ WMI_HL_10_SERVICE_SCAN_OFFLOAD,
+ WMI_HL_10_SERVICE_ROAM_SCAN_OFFLOAD,
+ WMI_HL_10_SERVICE_BCN_MISS_OFFLOAD,
+ WMI_HL_10_SERVICE_STA_PWRSAVE,
+ WMI_HL_10_SERVICE_STA_ADVANCED_PWRSAVE,
+ WMI_HL_10_SERVICE_AP_UAPSD,
+ WMI_HL_10_SERVICE_AP_DFS,
+ WMI_HL_10_SERVICE_11AC,
+ WMI_HL_10_SERVICE_BLOCKACK,
+ WMI_HL_10_SERVICE_PHYERR,
+ WMI_HL_10_SERVICE_BCN_FILTER,
+ WMI_HL_10_SERVICE_RTT,
+ WMI_HL_10_SERVICE_WOW,
+ WMI_HL_10_SERVICE_RATECTRL_CACHE,
+ WMI_HL_10_SERVICE_IRAM_TIDS,
+ WMI_HL_10_SERVICE_ARPNS_OFFLOAD,
+ WMI_HL_10_SERVICE_NLO,
+ WMI_HL_10_SERVICE_GTK_OFFLOAD,
+ WMI_HL_10_SERVICE_SCAN_SCH,
+ WMI_HL_10_SERVICE_CSA_OFFLOAD,
+ WMI_HL_10_SERVICE_CHATTER,
+ WMI_HL_10_SERVICE_COEX_FREQAVOID,
+ WMI_HL_10_SERVICE_PACKET_POWER_SAVE,
+ WMI_HL_10_SERVICE_FORCE_FW_HANG,
+ WMI_HL_10_SERVICE_GPIO,
+ WMI_HL_10_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
+ WMI_HL_10_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+ WMI_HL_10_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+ WMI_HL_10_SERVICE_STA_KEEP_ALIVE,
+ WMI_HL_10_SERVICE_TX_ENCAP,
+ WMI_HL_10_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
+ WMI_HL_10_SERVICE_EARLY_RX,
+ WMI_HL_10_SERVICE_STA_SMPS,
+ WMI_HL_10_SERVICE_FWTEST,
+ WMI_HL_10_SERVICE_STA_WMMAC,
+ WMI_HL_10_SERVICE_TDLS,
+ WMI_HL_10_SERVICE_BURST,
+ WMI_HL_10_SERVICE_MCC_BCN_INTERVAL_CHANGE,
+ WMI_HL_10_SERVICE_ADAPTIVE_OCS,
+ WMI_HL_10_SERVICE_BA_SSN_SUPPORT,
+ WMI_HL_10_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
+ WMI_HL_10_SERVICE_WLAN_HB,
+ WMI_HL_10_SERVICE_LTE_ANT_SHARE_SUPPORT,
+ WMI_HL_10_SERVICE_BATCH_SCAN,
+ WMI_HL_10_SERVICE_QPOWER,
+ WMI_HL_10_SERVICE_PLMREQ,
+ WMI_HL_10_SERVICE_THERMAL_MGMT,
+ WMI_HL_10_SERVICE_RMC,
+ WMI_HL_10_SERVICE_MHF_OFFLOAD,
+ WMI_HL_10_SERVICE_COEX_SAR,
+ WMI_HL_10_SERVICE_BCN_TXRATE_OVERRIDE,
+ WMI_HL_10_SERVICE_NAN,
+ WMI_HL_10_SERVICE_L1SS_STAT,
+ WMI_HL_10_SERVICE_ESTIMATE_LINKSPEED,
+ WMI_HL_10_SERVICE_OBSS_SCAN,
+ WMI_HL_10_SERVICE_TDLS_OFFCHAN,
+ WMI_HL_10_SERVICE_TDLS_UAPSD_BUFFER_STA,
+ WMI_HL_10_SERVICE_TDLS_UAPSD_SLEEP_STA,
+ WMI_HL_10_SERVICE_IBSS_PWRSAVE,
+ WMI_HL_10_SERVICE_LPASS,
+ WMI_HL_10_SERVICE_EXTSCAN,
+ WMI_HL_10_SERVICE_D0WOW,
+ WMI_HL_10_SERVICE_HSOFFLOAD,
+ WMI_HL_10_SERVICE_ROAM_HO_OFFLOAD,
+ WMI_HL_10_SERVICE_RX_FULL_REORDER,
+ WMI_HL_10_SERVICE_DHCP_OFFLOAD,
+ WMI_HL_10_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
+ WMI_HL_10_SERVICE_MDNS_OFFLOAD,
+ WMI_HL_10_SERVICE_SAP_AUTH_OFFLOAD,
+ WMI_HL_10_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT,
+ WMI_HL_10_SERVICE_OCB,
+ WMI_HL_10_SERVICE_AP_ARPNS_OFFLOAD,
+ WMI_HL_10_SERVICE_PER_BAND_CHAINMASK_SUPPORT,
+ WMI_HL_10_SERVICE_PACKET_FILTER_OFFLOAD,
+ WMI_HL_10_SERVICE_MGMT_TX_HTT,
+ WMI_HL_10_SERVICE_MGMT_TX_WMI,
+ WMI_HL_10_SERVICE_EXT_MSG,
+ WMI_HL_10_SERVICE_MAWC,
+ WMI_HL_10_SERVICE_PEER_ASSOC_CONF,
+ WMI_HL_10_SERVICE_EGAP,
+ WMI_HL_10_SERVICE_STA_PMF_OFFLOAD,
+ WMI_HL_10_SERVICE_UNIFIED_WOW_CAPABILITY,
+ WMI_HL_10_SERVICE_ENHANCED_PROXY_STA,
+ WMI_HL_10_SERVICE_ATF,
+ WMI_HL_10_SERVICE_COEX_GPIO,
+ WMI_HL_10_SERVICE_AUX_SPECTRAL_INTF,
+ WMI_HL_10_SERVICE_AUX_CHAN_LOAD_INTF,
+ WMI_HL_10_SERVICE_BSS_CHANNEL_INFO_64,
+ WMI_HL_10_SERVICE_ENTERPRISE_MESH,
+ WMI_HL_10_SERVICE_RESTRT_CHNL_SUPPORT,
+ WMI_HL_10_SERVICE_BPF_OFFLOAD,
+ WMI_HL_10_SERVICE_SYNC_DELETE_CMDS,
+ WMI_HL_10_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+ WMI_HL_10_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+ WMI_HL_10_SERVICE_RATECTRL_LIMIT_MAX_MIN_RATES,
+ WMI_HL_10_SERVICE_NAN_DATA,
+ WMI_HL_10_SERVICE_NAN_RTT,
+ WMI_HL_10_SERVICE_11AX,
+ WMI_HL_10_SERVICE_DEPRECATED_REPLACE,
+ WMI_HL_10_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
+ WMI_HL_10_SERVICE_ENHANCED_MCAST_FILTER,
+ WMI_HL_10_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
+ WMI_HL_10_SERVICE_MESH_11S,
+ WMI_HL_10_SERVICE_HALF_RATE_QUARTER_RATE_SUPPORT,
+ WMI_HL_10_SERVICE_VDEV_RX_FILTER,
+ WMI_HL_10_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT,
+ WMI_HL_10_SERVICE_MARK_FIRST_WAKEUP_PACKET,
+ WMI_HL_10_SERVICE_MULTIPLE_MCAST_FILTER_SET,
+ WMI_HL_10_SERVICE_HOST_MANAGED_RX_REORDER,
+ WMI_HL_10_SERVICE_FLASH_RDWR_SUPPORT,
+ WMI_HL_10_SERVICE_WLAN_STATS_REPORT,
+ WMI_HL_10_SERVICE_TX_MSDU_ID_NEW_PARTITION_SUPPORT,
+ WMI_HL_10_SERVICE_DFS_PHYERR_OFFLOAD,
+ WMI_HL_10_MAX_SERVICE = 128,
+ WMI_HL_10_MAX_EXT_SERVICE
+};
+
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
((svc_id) < (len) && \
__le32_to_cpu((wmi_svc_bmap)[(svc_id) / (sizeof(u32))]) & \
@@ -978,6 +1098,63 @@ enum wmi_tlv_service {
} while (0)
static inline void
+wmi_hl_1_0_svc_map(const __le32 *in, unsigned long *out, size_t len)
+{
+ SVCMAP(WMI_HL_10_SERVICE_BEACON_OFFLOAD,
+ WMI_SERVICE_BEACON_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_SCAN_OFFLOAD,
+ WMI_SERVICE_SCAN_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_ROAM_SCAN_OFFLOAD,
+ WMI_SERVICE_ROAM_SCAN_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_BCN_MISS_OFFLOAD,
+ WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_STA_PWRSAVE,
+ WMI_SERVICE_STA_PWRSAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_STA_ADVANCED_PWRSAVE,
+ WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_AP_UAPSD,
+ WMI_SERVICE_AP_UAPSD, len);
+ SVCMAP(WMI_HL_10_SERVICE_AP_DFS,
+ WMI_SERVICE_AP_DFS, len);
+ SVCMAP(WMI_HL_10_SERVICE_11AC,
+ WMI_SERVICE_11AC, len);
+ SVCMAP(WMI_HL_10_SERVICE_BLOCKACK,
+ WMI_SERVICE_BLOCKACK, len);
+ SVCMAP(WMI_HL_10_SERVICE_PHYERR,
+ WMI_SERVICE_PHYERR, len);
+ SVCMAP(WMI_HL_10_SERVICE_BCN_FILTER,
+ WMI_SERVICE_BCN_FILTER, len);
+ SVCMAP(WMI_HL_10_SERVICE_RTT,
+ WMI_SERVICE_RTT, len);
+ SVCMAP(WMI_HL_10_SERVICE_WOW,
+ WMI_SERVICE_WOW, len);
+ SVCMAP(WMI_HL_10_SERVICE_RATECTRL_CACHE,
+ WMI_SERVICE_RATECTRL_CACHE, len);
+ SVCMAP(WMI_HL_10_SERVICE_IRAM_TIDS,
+ WMI_SERVICE_IRAM_TIDS, len);
+ SVCMAP(WMI_HL_10_SERVICE_ARPNS_OFFLOAD,
+ WMI_SERVICE_ARPNS_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_NLO,
+ WMI_SERVICE_NLO, len);
+ SVCMAP(WMI_HL_10_SERVICE_GTK_OFFLOAD,
+ WMI_SERVICE_GTK_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_SCAN_SCH,
+ WMI_SERVICE_SCAN_SCH, len);
+ SVCMAP(WMI_HL_10_SERVICE_CSA_OFFLOAD,
+ WMI_SERVICE_CSA_OFFLOAD, len);
+ SVCMAP(WMI_HL_10_SERVICE_CHATTER,
+ WMI_SERVICE_CHATTER, len);
+ SVCMAP(WMI_HL_10_SERVICE_COEX_FREQAVOID,
+ WMI_SERVICE_COEX_FREQAVOID, len);
+ SVCMAP(WMI_HL_10_SERVICE_PACKET_POWER_SAVE,
+ WMI_SERVICE_PACKET_POWER_SAVE, len);
+ SVCMAP(WMI_HL_10_SERVICE_FORCE_FW_HANG,
+ WMI_SERVICE_FORCE_FW_HANG, len);
+ SVCMAP(WMI_HL_10_SERVICE_RX_FULL_REORDER,
+ WMI_SERVICE_RX_FULL_REORDER, len);
+}
+
+static inline void
wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
{
SVCMAP(WMI_TLV_SERVICE_BEACON_OFFLOAD,
@@ -1182,6 +1359,14 @@ struct wmi_tlv_svc_rdy_ev {
__le32 max_num_scan_chans;
__le32 hw_bd_id; /* 0 means hw_bd_info is invalid */
struct wmi_tlv_hw_bd_info hw_bd_info[5];
+#ifdef CONFIG_ATH10K_SNOC
+ __le32 max_supported_macs;
+ __le32 wmi_fw_sub_feat_caps;
+ __le32 num_dbs_hw_modes;
+ __le32 txrx_chainmask;
+ __le32 default_dbs_hw_mode_index;
+ __le32 num_msdu_desc;
+#endif
} __packed;
struct wmi_tlv_rdy_ev {
@@ -1641,5 +1826,5 @@ struct wmi_tlv_tx_pause_ev {
} __packed;
void ath10k_wmi_tlv_attach(struct ath10k *ar);
-
+void ath10k_wmi_hl_1_0_attach(struct ath10k *ar);
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index b1d212fd8fd7..f7ada7147136 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -8196,6 +8196,9 @@ int ath10k_wmi_attach(struct ath10k *ar)
case ATH10K_FW_WMI_OP_VERSION_TLV:
ath10k_wmi_tlv_attach(ar);
break;
+ case ATH10K_FW_WMI_OP_VERSION_HL_1_0:
+ ath10k_wmi_hl_1_0_attach(ar);
+ break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
ath10k_err(ar, "unsupported WMI op version: %d\n",
diff --git a/drivers/net/wireless/ath/wil6210/ftm.h b/drivers/net/wireless/ath/wil6210/ftm.h
index ea186d641d59..8efa292d5ff4 100644
--- a/drivers/net/wireless/ath/wil6210/ftm.h
+++ b/drivers/net/wireless/ath/wil6210/ftm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -96,7 +96,7 @@ enum qca_wlan_vendor_attr_loc {
QCA_WLAN_VENDOR_ATTR_AOA_TYPE = 23,
QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK = 24,
QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25,
- QCA_WLAN_VENDOR_ATTR_FREQ = 26,
+ QCA_WLAN_VENDOR_ATTR_FREQ = 28,
/* keep last */
QCA_WLAN_VENDOR_ATTR_LOC_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_LOC_MAX = QCA_WLAN_VENDOR_ATTR_LOC_AFTER_LAST - 1,
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 4a12af466c36..8dc93f42b059 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -1214,6 +1214,8 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ smblib_rerun_apsd_if_required(chg);
+
/* clear the ICL override if it is set */
if (stat & ICL_OVERRIDE_LATCH_BIT) {
rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT);
@@ -1820,6 +1822,8 @@ static int smb2_probe(struct platform_device *pdev)
struct smb_charger *chg;
int rc = 0;
u8 stat;
+ union power_supply_propval val;
+ int usb_present, batt_present, batt_health, batt_charge_type;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -1943,7 +1947,37 @@ static int smb2_probe(struct platform_device *pdev)
smb2_create_debugfs(chip);
- pr_info("QPNP SMB2 probed successfully\n");
+ rc = smblib_get_prop_usb_present(chg, &val);
+ if (rc < 0) {
+ pr_err("Couldn't get usb present rc=%d\n", rc);
+ goto cleanup;
+ }
+ usb_present = val.intval;
+
+ rc = smblib_get_prop_batt_present(chg, &val);
+ if (rc < 0) {
+ pr_err("Couldn't get batt present rc=%d\n", rc);
+ goto cleanup;
+ }
+ batt_present = val.intval;
+
+ rc = smblib_get_prop_batt_health(chg, &val);
+ if (rc < 0) {
+ pr_err("Couldn't get batt health rc=%d\n", rc);
+ goto cleanup;
+ }
+ batt_health = val.intval;
+
+ rc = smblib_get_prop_batt_charge_type(chg, &val);
+ if (rc < 0) {
+ pr_err("Couldn't get batt charge type rc=%d\n", rc);
+ goto cleanup;
+ }
+ batt_charge_type = val.intval;
+
+ pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
+ usb_present, chg->usb_psy_desc.type,
+ batt_present, batt_health, batt_charge_type);
return rc;
cleanup:
@@ -1987,6 +2021,10 @@ static void smb2_shutdown(struct platform_device *pdev)
smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
+
+ /* force enable APSD */
+ smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ AUTO_SRC_DETECT_BIT, AUTO_SRC_DETECT_BIT);
}
static const struct of_device_id match_table[] = {
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 5f840f233f20..dbda0b6a9c9a 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -660,6 +660,39 @@ void smblib_suspend_on_debug_battery(struct smb_charger *chg)
pr_info("Input suspended: Fake battery\n");
}
+int smblib_rerun_apsd_if_required(struct smb_charger *chg)
+{
+ const struct apsd_result *apsd_result;
+ union power_supply_propval val;
+ int rc;
+
+ rc = smblib_get_prop_usb_present(chg, &val);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get usb present rc = %d\n", rc);
+ return rc;
+ }
+
+ if (!val.intval)
+ return 0;
+
+ apsd_result = smblib_get_apsd_result(chg);
+ if ((apsd_result->pst == POWER_SUPPLY_TYPE_UNKNOWN)
+ || (apsd_result->pst == POWER_SUPPLY_TYPE_USB)) {
+ /* rerun APSD */
+ pr_info("Reruning APSD type = %s at bootup\n",
+ apsd_result->name);
+ rc = smblib_masked_write(chg, CMD_APSD_REG,
+ APSD_RERUN_BIT,
+ APSD_RERUN_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't rerun APSD rc = %d\n", rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
/*********************
* VOTABLE CALLBACKS *
*********************/
@@ -2346,6 +2379,12 @@ int smblib_reg_block_restore(struct smb_charger *chg,
static struct reg_info cc2_detach_settings[] = {
{
+ .reg = TYPE_C_CFG_REG,
+ .mask = APSD_START_ON_CC_BIT,
+ .val = 0,
+ .desc = "TYPE_C_CFG_REG",
+ },
+ {
.reg = TYPE_C_CFG_2_REG,
.mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT,
.val = TYPE_C_UFP_MODE_BIT,
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index c5d014193fd6..a4121224b121 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -385,6 +385,7 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg,
int smblib_set_prop_ship_mode(struct smb_charger *chg,
const union power_supply_propval *val);
void smblib_suspend_on_debug_battery(struct smb_charger *chg);
+int smblib_rerun_apsd_if_required(struct smb_charger *chg);
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index ed76a585ed03..c836e780fc86 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -39,6 +39,9 @@
#define DEAD_TIME_MASK GENMASK(7, 4)
#define HIGH_DEAD_TIME_MASK GENMASK(7, 4)
+#define SMB2CHG_DC_TM_SREFGEN (DCIN_BASE + 0xE2)
+#define STACKED_DIODE_EN_BIT BIT(2)
+
enum {
OOB_COMP_WA_BIT = BIT(0),
};
@@ -1216,6 +1219,13 @@ static int smb138x_slave_probe(struct smb138x *chip)
goto cleanup;
}
+ /* enable stacked diode */
+ rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT);
+ if (rc < 0) {
+ pr_err("Couldn't enable stacked diode rc=%d\n", rc);
+ return rc;
+ }
+
rc = smb138x_init_parallel_psy(chip);
if (rc < 0) {
pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c
index 1ac9791b467b..1070a34073e4 100644
--- a/drivers/regulator/cpr3-mmss-regulator.c
+++ b/drivers/regulator/cpr3-mmss-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -453,45 +453,24 @@ done:
}
/**
- * cpr3_msm8996_mmss_apply_closed_loop_offset_voltages() - modify the
- * closed-loop voltage adjustments by the amounts that are needed
- * for this fuse combo
+ * cpr3_msm8996_mmss_adjust_target_quotients() - adjust the target quotients
+ * for each corner according to device tree values and fuse values
* @vreg: Pointer to the CPR3 regulator
- * @volt_adjust: Array of closed-loop voltage adjustment values of length
- * vreg->corner_count which is further adjusted based upon
- * offset voltage fuse values.
*
* Return: 0 on success, errno on failure
*/
-static int cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(
- struct cpr3_regulator *vreg, int *volt_adjust)
+static int cpr3_msm8996_mmss_adjust_target_quotients(
+ struct cpr3_regulator *vreg)
{
struct cpr3_msm8996_mmss_fuses *fuse = vreg->platform_fuses;
const struct cpr3_fuse_param (*offset_param)[2];
- u32 *corner_map;
int *volt_offset;
- int rc = 0, i, fuse_len;
-
- if (!of_find_property(vreg->of_node,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
- /* No closed-loop offset required. */
- return 0;
- }
+ int i, fuse_len, rc = 0;
- corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
- GFP_KERNEL);
volt_offset = kcalloc(vreg->fuse_corner_count, sizeof(*volt_offset),
GFP_KERNEL);
- if (!corner_map || !volt_offset) {
- rc = -ENOMEM;
- goto done;
- }
-
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
- 1, corner_map);
- if (rc)
- goto done;
+ if (!volt_offset)
+ return -ENOMEM;
offset_param = cpr3_ctrl_is_msm8998(vreg->thread->ctrl)
? msm8998_mmss_offset_voltage_param
@@ -507,223 +486,11 @@ static int cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(
i, volt_offset[i]);
}
- for (i = 0; i < vreg->corner_count; i++) {
- if (corner_map[i] == 0) {
- continue;
- } else if (corner_map[i] > vreg->fuse_corner_count) {
- cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
- i, corner_map[i]);
- rc = -EINVAL;
- goto done;
- }
-
- volt_adjust[i] += volt_offset[corner_map[i] - 1];
- }
+ rc = cpr3_adjust_target_quotients(vreg, volt_offset);
+ if (rc)
+ cpr3_err(vreg, "adjust target quotients failed, rc=%d\n", rc);
-done:
- kfree(corner_map);
kfree(volt_offset);
-
- return rc;
-}
-
-/**
- * cpr3_mmss_enforce_inc_quotient_monotonicity() - Ensure that target quotients
- * increase monotonically from lower to higher corners
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static void cpr3_mmss_enforce_inc_quotient_monotonicity(
- struct cpr3_regulator *vreg)
-{
- int i, j;
-
- for (i = 1; i < vreg->corner_count; i++) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j]
- && vreg->corner[i].target_quot[j]
- < vreg->corner[i - 1].target_quot[j]) {
- cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
- i, j,
- vreg->corner[i].target_quot[j],
- i - 1, j,
- vreg->corner[i - 1].target_quot[j],
- i, j,
- vreg->corner[i - 1].target_quot[j]);
- vreg->corner[i].target_quot[j]
- = vreg->corner[i - 1].target_quot[j];
- }
- }
- }
-}
-
-/**
- * cpr3_mmss_enforce_dec_quotient_monotonicity() - Ensure that target quotients
- * decrease monotonically from higher to lower corners
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static void cpr3_mmss_enforce_dec_quotient_monotonicity(
- struct cpr3_regulator *vreg)
-{
- int i, j;
-
- for (i = vreg->corner_count - 2; i >= 0; i--) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i + 1].target_quot[j]
- && vreg->corner[i].target_quot[j]
- > vreg->corner[i + 1].target_quot[j]) {
- cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
- i, j,
- vreg->corner[i].target_quot[j],
- i + 1, j,
- vreg->corner[i + 1].target_quot[j],
- i, j,
- vreg->corner[i + 1].target_quot[j]);
- vreg->corner[i].target_quot[j]
- = vreg->corner[i + 1].target_quot[j];
- }
- }
- }
-}
-
-/**
- * _cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
- * corner of the regulator according to input adjustment and
- * scaling arrays
- * @vreg: Pointer to the CPR3 regulator
- * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
- * with units of microvolts. The array must have
- * vreg->corner_count number of elements.
- * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
- * The array must have an inner dimension of CPR3_RO_COUNT
- * and an outer dimension of vreg->corner_count
- * @label: Null terminated string providing a label for the type
- * of adjustment.
- *
- * Return: true if any corners received a positive voltage adjustment (> 0),
- * else false
- */
-static bool _cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg,
- const int *volt_adjust, const int *ro_scale, const char *label)
-{
- int i, j, quot_adjust;
- bool is_increasing = false;
- u32 prev_quot;
-
- for (i = 0; i < vreg->corner_count; i++) {
- for (j = 0; j < CPR3_RO_COUNT; j++) {
- if (vreg->corner[i].target_quot[j]) {
- quot_adjust = cpr3_quot_adjustment(
- ro_scale[i * CPR3_RO_COUNT + j],
- volt_adjust[i]);
- if (quot_adjust) {
- prev_quot = vreg->corner[i].
- target_quot[j];
- vreg->corner[i].target_quot[j]
- += quot_adjust;
- cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
- i, j, label, prev_quot,
- vreg->corner[i].target_quot[j],
- volt_adjust[i]);
- }
- }
- }
- if (volt_adjust[i] > 0)
- is_increasing = true;
- }
-
- return is_increasing;
-}
-
-/**
- * cpr3_mmss_adjust_target_quotients() - adjust the target quotients for each
- * corner according to device tree values and fuse values
- * @vreg: Pointer to the CPR3 regulator
- *
- * Return: 0 on success, errno on failure
- */
-static int cpr3_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
-{
- int i, rc;
- int *volt_adjust, *ro_scale;
- bool explicit_adjustment, fused_adjustment, is_increasing;
-
- explicit_adjustment = of_find_property(vreg->of_node,
- "qcom,cpr-closed-loop-voltage-adjustment", NULL);
- fused_adjustment = of_find_property(vreg->of_node,
- "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
-
- if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
- /* No adjustment required. */
- return 0;
- } else if (!of_find_property(vreg->of_node,
- "qcom,cpr-ro-scaling-factor", NULL)) {
- cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
- return -EINVAL;
- }
-
- volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
- GFP_KERNEL);
- ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
- sizeof(*ro_scale), GFP_KERNEL);
- if (!volt_adjust || !ro_scale) {
- rc = -ENOMEM;
- goto done;
- }
-
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
- if (rc) {
- cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
- rc);
- goto done;
- }
-
- for (i = 0; i < vreg->corner_count; i++)
- memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
- sizeof(*ro_scale) * CPR3_RO_COUNT);
-
- if (explicit_adjustment) {
- rc = cpr3_parse_corner_array_property(vreg,
- "qcom,cpr-closed-loop-voltage-adjustment",
- 1, volt_adjust);
- if (rc) {
- cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
- rc);
- goto done;
- }
-
- _cpr3_mmss_adjust_target_quotients(vreg, volt_adjust, ro_scale,
- "from DT");
- cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
- }
-
- if (fused_adjustment) {
- memset(volt_adjust, 0,
- sizeof(*volt_adjust) * vreg->corner_count);
-
- rc = cpr3_msm8996_mmss_apply_closed_loop_offset_voltages(vreg,
- volt_adjust);
- if (rc) {
- cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
- rc);
- goto done;
- }
-
- is_increasing = _cpr3_mmss_adjust_target_quotients(vreg,
- volt_adjust, ro_scale, "from fuse");
- if (is_increasing)
- cpr3_mmss_enforce_inc_quotient_monotonicity(vreg);
- else
- cpr3_mmss_enforce_dec_quotient_monotonicity(vreg);
- }
-
-done:
- kfree(volt_adjust);
- kfree(ro_scale);
return rc;
}
@@ -1112,7 +879,7 @@ static int cpr3_mmss_init_thread(struct cpr3_thread *thread)
return rc;
}
- rc = cpr3_mmss_adjust_target_quotients(vreg);
+ rc = cpr3_msm8996_mmss_adjust_target_quotients(vreg);
if (rc) {
cpr3_err(vreg, "unable to adjust target quotients, rc=%d\n",
rc);
diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h
index 2e997b526b90..f0230b8ae2e5 100644
--- a/drivers/regulator/cpr3-regulator.h
+++ b/drivers/regulator/cpr3-regulator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -904,6 +904,8 @@ int cpr3_apm_init(struct cpr3_controller *ctrl);
int cpr3_mem_acc_init(struct cpr3_regulator *vreg);
void cprh_adjust_voltages_for_apm(struct cpr3_regulator *vreg);
void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg);
+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust);
#else
@@ -1084,6 +1086,12 @@ static inline void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
{
}
+static inline int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust)
+{
+ return 0;
+}
+
#endif /* CONFIG_REGULATOR_CPR3 */
#endif /* __REGULATOR_CPR_REGULATOR_H__ */
diff --git a/drivers/regulator/cpr3-util.c b/drivers/regulator/cpr3-util.c
index 7f712d4f6ee4..0a1a1c56bd16 100644
--- a/drivers/regulator/cpr3-util.c
+++ b/drivers/regulator/cpr3-util.c
@@ -2147,3 +2147,259 @@ void cprh_adjust_voltages_for_mem_acc(struct cpr3_regulator *vreg)
corner->ceiling_volt, corner->open_loop_volt);
}
}
+
+/**
+ * cpr3_apply_closed_loop_offset_voltages() - modify the closed-loop voltage
+ * adjustments by the amounts that are needed for this
+ * fuse combo
+ * @vreg: Pointer to the CPR3 regulator
+ * @volt_adjust: Array of closed-loop voltage adjustment values of length
+ * vreg->corner_count which is further adjusted based upon
+ * offset voltage fuse values.
+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
+ * vreg->fuse_corner_count.
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int cpr3_apply_closed_loop_offset_voltages(struct cpr3_regulator *vreg,
+ int *volt_adjust, int *fuse_volt_adjust)
+{
+ u32 *corner_map;
+ int rc = 0, i;
+
+ if (!of_find_property(vreg->of_node,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL)) {
+ /* No closed-loop offset required. */
+ return 0;
+ }
+
+ corner_map = kcalloc(vreg->corner_count, sizeof(*corner_map),
+ GFP_KERNEL);
+ if (!corner_map)
+ return -ENOMEM;
+
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map",
+ 1, corner_map);
+ if (rc)
+ goto done;
+
+ for (i = 0; i < vreg->corner_count; i++) {
+ if (corner_map[i] == 0) {
+ continue;
+ } else if (corner_map[i] > vreg->fuse_corner_count) {
+ cpr3_err(vreg, "corner %d mapped to invalid fuse corner: %u\n",
+ i, corner_map[i]);
+ rc = -EINVAL;
+ goto done;
+ }
+
+ volt_adjust[i] += fuse_volt_adjust[corner_map[i] - 1];
+ }
+
+done:
+ kfree(corner_map);
+ return rc;
+}
+
+/**
+ * cpr3_enforce_inc_quotient_monotonicity() - Ensure that target quotients
+ * increase monotonically from lower to higher corners
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static void cpr3_enforce_inc_quotient_monotonicity(struct cpr3_regulator *vreg)
+{
+ int i, j;
+
+ for (i = 1; i < vreg->corner_count; i++) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i].target_quot[j]
+ && vreg->corner[i].target_quot[j]
+ < vreg->corner[i - 1].target_quot[j]) {
+ cpr3_debug(vreg, "corner %d RO%u target quot=%u < corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
+ i, j,
+ vreg->corner[i].target_quot[j],
+ i - 1, j,
+ vreg->corner[i - 1].target_quot[j],
+ i, j,
+ vreg->corner[i - 1].target_quot[j]);
+ vreg->corner[i].target_quot[j]
+ = vreg->corner[i - 1].target_quot[j];
+ }
+ }
+ }
+}
+
+/**
+ * cpr3_enforce_dec_quotient_monotonicity() - Ensure that target quotients
+ * decrease monotonically from higher to lower corners
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static void cpr3_enforce_dec_quotient_monotonicity(struct cpr3_regulator *vreg)
+{
+ int i, j;
+
+ for (i = vreg->corner_count - 2; i >= 0; i--) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i + 1].target_quot[j]
+ && vreg->corner[i].target_quot[j]
+ > vreg->corner[i + 1].target_quot[j]) {
+ cpr3_debug(vreg, "corner %d RO%u target quot=%u > corner %d RO%u target quot=%u; overriding: corner %d RO%u target quot=%u\n",
+ i, j,
+ vreg->corner[i].target_quot[j],
+ i + 1, j,
+ vreg->corner[i + 1].target_quot[j],
+ i, j,
+ vreg->corner[i + 1].target_quot[j]);
+ vreg->corner[i].target_quot[j]
+ = vreg->corner[i + 1].target_quot[j];
+ }
+ }
+ }
+}
+
+/**
+ * _cpr3_adjust_target_quotients() - adjust the target quotients for each
+ * corner of the regulator according to input adjustment and
+ * scaling arrays
+ * @vreg: Pointer to the CPR3 regulator
+ * @volt_adjust: Pointer to an array of closed-loop voltage adjustments
+ * with units of microvolts. The array must have
+ * vreg->corner_count number of elements.
+ * @ro_scale: Pointer to a flattened 2D array of RO scaling factors.
+ * The array must have an inner dimension of CPR3_RO_COUNT
+ * and an outer dimension of vreg->corner_count
+ * @label: Null terminated string providing a label for the type
+ * of adjustment.
+ *
+ * Return: true if any corners received a positive voltage adjustment (> 0),
+ * else false
+ */
+static bool _cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ const int *volt_adjust, const int *ro_scale, const char *label)
+{
+ int i, j, quot_adjust;
+ bool is_increasing = false;
+ u32 prev_quot;
+
+ for (i = 0; i < vreg->corner_count; i++) {
+ for (j = 0; j < CPR3_RO_COUNT; j++) {
+ if (vreg->corner[i].target_quot[j]) {
+ quot_adjust = cpr3_quot_adjustment(
+ ro_scale[i * CPR3_RO_COUNT + j],
+ volt_adjust[i]);
+ if (quot_adjust) {
+ prev_quot = vreg->corner[i].
+ target_quot[j];
+ vreg->corner[i].target_quot[j]
+ += quot_adjust;
+ cpr3_debug(vreg, "adjusted corner %d RO%d target quot %s: %u --> %u (%d uV)\n",
+ i, j, label, prev_quot,
+ vreg->corner[i].target_quot[j],
+ volt_adjust[i]);
+ }
+ }
+ }
+ if (volt_adjust[i] > 0)
+ is_increasing = true;
+ }
+
+ return is_increasing;
+}
+
+/**
+ * cpr3_adjust_target_quotients() - adjust the target quotients for each
+ * corner according to device tree values and fuse values
+ * @vreg: Pointer to the CPR3 regulator
+ * @fuse_volt_adjust: Fused closed-loop voltage adjustment values of length
+ * vreg->fuse_corner_count. This parameter could be null
+ * pointer when no fused adjustments are needed.
+ *
+ * Return: 0 on success, errno on failure
+ */
+int cpr3_adjust_target_quotients(struct cpr3_regulator *vreg,
+ int *fuse_volt_adjust)
+{
+ int i, rc;
+ int *volt_adjust, *ro_scale;
+ bool explicit_adjustment, fused_adjustment, is_increasing;
+
+ explicit_adjustment = of_find_property(vreg->of_node,
+ "qcom,cpr-closed-loop-voltage-adjustment", NULL);
+ fused_adjustment = of_find_property(vreg->of_node,
+ "qcom,cpr-fused-closed-loop-voltage-adjustment-map", NULL);
+
+ if (!explicit_adjustment && !fused_adjustment && !vreg->aging_allowed) {
+ /* No adjustment required. */
+ return 0;
+ } else if (!of_find_property(vreg->of_node,
+ "qcom,cpr-ro-scaling-factor", NULL)) {
+ cpr3_err(vreg, "qcom,cpr-ro-scaling-factor is required for closed-loop voltage adjustment, but is missing\n");
+ return -EINVAL;
+ }
+
+ volt_adjust = kcalloc(vreg->corner_count, sizeof(*volt_adjust),
+ GFP_KERNEL);
+ ro_scale = kcalloc(vreg->corner_count * CPR3_RO_COUNT,
+ sizeof(*ro_scale), GFP_KERNEL);
+ if (!volt_adjust || !ro_scale) {
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-ro-scaling-factor", CPR3_RO_COUNT, ro_scale);
+ if (rc) {
+ cpr3_err(vreg, "could not load RO scaling factors, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ for (i = 0; i < vreg->corner_count; i++)
+ memcpy(vreg->corner[i].ro_scale, &ro_scale[i * CPR3_RO_COUNT],
+ sizeof(*ro_scale) * CPR3_RO_COUNT);
+
+ if (explicit_adjustment) {
+ rc = cpr3_parse_corner_array_property(vreg,
+ "qcom,cpr-closed-loop-voltage-adjustment",
+ 1, volt_adjust);
+ if (rc) {
+ cpr3_err(vreg, "could not load closed-loop voltage adjustments, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ _cpr3_adjust_target_quotients(vreg, volt_adjust, ro_scale,
+ "from DT");
+ cpr3_enforce_inc_quotient_monotonicity(vreg);
+ }
+
+ if (fused_adjustment && fuse_volt_adjust) {
+ memset(volt_adjust, 0,
+ sizeof(*volt_adjust) * vreg->corner_count);
+
+ rc = cpr3_apply_closed_loop_offset_voltages(vreg, volt_adjust,
+ fuse_volt_adjust);
+ if (rc) {
+ cpr3_err(vreg, "could not apply fused closed-loop voltage reductions, rc=%d\n",
+ rc);
+ goto done;
+ }
+
+ is_increasing = _cpr3_adjust_target_quotients(vreg, volt_adjust,
+ ro_scale, "from fuse");
+ if (is_increasing)
+ cpr3_enforce_inc_quotient_monotonicity(vreg);
+ else
+ cpr3_enforce_dec_quotient_monotonicity(vreg);
+ }
+
+done:
+ kfree(volt_adjust);
+ kfree(ro_scale);
+ return rc;
+}
diff --git a/drivers/regulator/cpr4-mmss-ldo-regulator.c b/drivers/regulator/cpr4-mmss-ldo-regulator.c
index 2843f71745fc..f8e3ea40ddac 100644
--- a/drivers/regulator/cpr4-mmss-ldo-regulator.c
+++ b/drivers/regulator/cpr4-mmss-ldo-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -417,6 +417,45 @@ done:
}
/**
+ * cpr4_sdm660_mmss_adjust_target_quotients() - adjust the target quotients for
+ * each corner according to device tree values and fuse values
+ * @vreg: Pointer to the CPR3 regulator
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int cpr4_sdm660_mmss_adjust_target_quotients(struct cpr3_regulator *vreg)
+{
+ struct cpr4_sdm660_mmss_fuses *fuse = vreg->platform_fuses;
+ const struct cpr3_fuse_param (*offset_param)[2];
+ int *volt_offset;
+ int i, fuse_len, rc = 0;
+
+ volt_offset = kcalloc(vreg->fuse_corner_count, sizeof(*volt_offset),
+ GFP_KERNEL);
+ if (!volt_offset)
+ return -ENOMEM;
+
+ offset_param = sdm660_mmss_offset_voltage_param;
+ for (i = 0; i < vreg->fuse_corner_count; i++) {
+ fuse_len = offset_param[i][0].bit_end + 1
+ - offset_param[i][0].bit_start;
+ volt_offset[i] = cpr3_convert_open_loop_voltage_fuse(
+ 0, SDM660_MMSS_OFFSET_FUSE_STEP_VOLT,
+ fuse->offset_voltage[i], fuse_len);
+ if (volt_offset[i])
+ cpr3_info(vreg, "fuse_corner[%d] offset=%7d uV\n",
+ i, volt_offset[i]);
+ }
+
+ rc = cpr3_adjust_target_quotients(vreg, volt_offset);
+ if (rc)
+ cpr3_err(vreg, "adjust target quotients failed, rc=%d\n", rc);
+
+ kfree(volt_offset);
+ return rc;
+}
+
+/**
* cpr4_mmss_print_settings() - print out MMSS CPR configuration settings into
* the kernel log for debugging purposes
* @vreg: Pointer to the CPR3 regulator
@@ -489,6 +528,13 @@ static int cpr4_mmss_init_thread(struct cpr3_thread *thread)
return rc;
}
+ rc = cpr4_sdm660_mmss_adjust_target_quotients(vreg);
+ if (rc) {
+ cpr3_err(vreg, "unable to adjust target quotients, rc=%d\n",
+ rc);
+ return rc;
+ }
+
rc = cpr4_sdm660_mmss_calculate_open_loop_voltages(vreg);
if (rc) {
cpr3_err(vreg, "unable to calculate open-loop voltages, rc=%d\n",
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c
index 9a8a3b18d03a..40c62c355188 100644
--- a/drivers/regulator/qpnp-labibb-regulator.c
+++ b/drivers/regulator/qpnp-labibb-regulator.c
@@ -333,7 +333,7 @@ enum ibb_mode {
IBB_HW_SW_CONTROL,
};
-static const int ibb_discharge_resistor_table[] = {
+static const int ibb_dischg_res_table[] = {
300,
64,
32,
@@ -946,38 +946,27 @@ static int qpnp_ibb_soft_start_ctl_v1(struct qpnp_labibb *labibb,
rc = of_property_read_u32(of_node, "qcom,qpnp-ibb-discharge-resistor",
&tmp);
+ if (!rc) {
+ for (val = 0; val < ARRAY_SIZE(ibb_dischg_res_table); val++) {
+ if (ibb_dischg_res_table[val] == tmp)
+ break;
+ }
- if (rc < 0) {
- pr_err("qcom,qpnp-ibb-discharge-resistor is missing, rc = %d\n",
- rc);
- return rc;
- }
-
- if (labibb->mode == QPNP_LABIBB_AMOLED_MODE) {
- /*
- * AMOLED mode needs ibb discharge resistor to be
- * configured for 300KOhm
- */
- if (tmp < ibb_discharge_resistor_table[0])
- tmp = ibb_discharge_resistor_table[0];
- }
-
- for (val = 0; val < ARRAY_SIZE(ibb_discharge_resistor_table); val++)
- if (ibb_discharge_resistor_table[val] == tmp)
- break;
+ if (val == ARRAY_SIZE(ibb_dischg_res_table)) {
+ pr_err("Invalid value in qcom,qpnp-ibb-discharge-resistor\n");
+ return -EINVAL;
+ }
- if (val == ARRAY_SIZE(ibb_discharge_resistor_table)) {
- pr_err("Invalid value in qcom,qpnp-ibb-discharge-resistor\n");
- return -EINVAL;
+ rc = qpnp_labibb_write(labibb, labibb->ibb_base +
+ REG_IBB_SOFT_START_CTL, &val, 1);
+ if (rc < 0) {
+ pr_err("write to register %x failed rc = %d\n",
+ REG_IBB_SOFT_START_CTL, rc);
+ return rc;
+ }
}
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_SOFT_START_CTL, &val, 1);
- if (rc < 0)
- pr_err("write to register %x failed rc = %d\n",
- REG_IBB_SOFT_START_CTL, rc);
-
- return rc;
+ return 0;
}
static int qpnp_ibb_soft_start_ctl_v2(struct qpnp_labibb *labibb,
@@ -3408,7 +3397,8 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
* before by the bootloader.
*/
if (labibb->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE)
- labibb->swire_control = val & IBB_ENABLE_CTL_SWIRE_RDY;
+ labibb->swire_control = ibb_enable_ctl &
+ IBB_ENABLE_CTL_SWIRE_RDY;
if (ibb_enable_ctl &
(IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) {
diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.c b/drivers/scsi/ufs/ufs-qcom-debugfs.c
index 8532439c392d..4547a6dbdb23 100644
--- a/drivers/scsi/ufs/ufs-qcom-debugfs.c
+++ b/drivers/scsi/ufs/ufs-qcom-debugfs.c
@@ -67,6 +67,7 @@ static int ufs_qcom_dbg_testbus_en_read(void *data, u64 *attr_val)
static int ufs_qcom_dbg_testbus_en_set(void *data, u64 attr_id)
{
struct ufs_qcom_host *host = data;
+ int ret = 0;
if (!host)
return -EINVAL;
@@ -76,7 +77,13 @@ static int ufs_qcom_dbg_testbus_en_set(void *data, u64 attr_id)
else
host->dbg_print_en &= ~UFS_QCOM_DBG_PRINT_TEST_BUS_EN;
- return ufs_qcom_testbus_config(host);
+ pm_runtime_get_sync(host->hba->dev);
+ ufshcd_hold(host->hba, false);
+ ret = ufs_qcom_testbus_config(host);
+ ufshcd_release(host->hba, false);
+ pm_runtime_put_sync(host->hba->dev);
+
+ return ret;
}
DEFINE_SIMPLE_ATTRIBUTE(ufs_qcom_dbg_testbus_en_ops,
@@ -142,7 +149,11 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file,
* Sanity check of the {major, minor} tuple is done in the
* config function
*/
+ pm_runtime_get_sync(host->hba->dev);
+ ufshcd_hold(host->hba, false);
ret = ufs_qcom_testbus_config(host);
+ ufshcd_release(host->hba, false);
+ pm_runtime_put_sync(host->hba->dev);
if (!ret)
dev_dbg(host->hba->dev,
"%s: New configuration: major=%d, minor=%d\n",
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index 85f82b2251c1..814d1dcfe90e 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -173,10 +173,19 @@ static void ufs_qcom_ice_cfg_work(struct work_struct *work)
struct ice_data_setting ice_set;
struct ufs_qcom_host *qcom_host =
container_of(work, struct ufs_qcom_host, ice_cfg_work);
+ struct request *req_pending = NULL;
- if (!qcom_host->ice.vops->config_start || !qcom_host->req_pending)
+ if (!qcom_host->ice.vops->config_start)
return;
+ spin_lock_irqsave(&qcom_host->ice_work_lock, flags);
+ req_pending = qcom_host->req_pending;
+ if (!req_pending) {
+ spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
+
/*
* config_start is called again as previous attempt returned -EAGAIN,
* this call shall now take care of the necessary key setup.
@@ -263,6 +272,10 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
if (qcom_host->ice.vops->config_start) {
memset(&ice_set, 0, sizeof(ice_set));
+
+ spin_lock_irqsave(
+ &qcom_host->ice_work_lock, flags);
+
err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
cmd->request, &ice_set, true);
if (err) {
@@ -281,13 +294,11 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
"%s: scheduling task for ice setup\n",
__func__);
- spin_lock_irqsave(
- &qcom_host->ice_work_lock, flags);
-
if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
qcom_host->hba);
qcom_host->req_pending = cmd->request;
+
if (!schedule_work(
&qcom_host->ice_cfg_work)) {
qcom_host->req_pending = NULL;
@@ -302,9 +313,6 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
}
}
- spin_unlock_irqrestore(
- &qcom_host->ice_work_lock, flags);
-
} else {
if (err != -EBUSY)
dev_err(qcom_host->hba->dev,
@@ -312,9 +320,14 @@ int ufs_qcom_ice_req_setup(struct ufs_qcom_host *qcom_host,
__func__, err);
}
+ spin_unlock_irqrestore(&qcom_host->ice_work_lock,
+ flags);
+
return err;
}
+ spin_unlock_irqrestore(&qcom_host->ice_work_lock, flags);
+
if (ufs_qcom_is_data_cmd(cmd_op, true))
*enable = !ice_set.encr_bypass;
else if (ufs_qcom_is_data_cmd(cmd_op, false))
@@ -380,8 +393,13 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
return -EINVAL;
}
- memset(&ice_set, 0, sizeof(ice_set));
+
if (qcom_host->ice.vops->config_start) {
+ memset(&ice_set, 0, sizeof(ice_set));
+
+ spin_lock_irqsave(
+ &qcom_host->ice_work_lock, flags);
+
err = qcom_host->ice.vops->config_start(qcom_host->ice.pdev,
req, &ice_set, true);
if (err) {
@@ -401,9 +419,6 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
"%s: scheduling task for ice setup\n",
__func__);
- spin_lock_irqsave(
- &qcom_host->ice_work_lock, flags);
-
if (!qcom_host->req_pending) {
ufshcd_scsi_block_requests(
qcom_host->hba);
@@ -422,9 +437,6 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
}
}
- spin_unlock_irqrestore(
- &qcom_host->ice_work_lock, flags);
-
} else {
if (err != -EBUSY)
dev_err(qcom_host->hba->dev,
@@ -432,8 +444,14 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
__func__, err);
}
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock, flags);
+
return err;
}
+
+ spin_unlock_irqrestore(
+ &qcom_host->ice_work_lock, flags);
}
cmd_op = cmd->cmnd[0];
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 03b222d8be93..7369478a8c5d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2452,6 +2452,11 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host)
return true;
}
+/*
+ * The caller of this function must make sure that the controller
+ * is out of runtime suspend and appropriate clocks are enabled
+ * before accessing.
+ */
int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
{
int reg;
@@ -2522,8 +2527,6 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
}
mask <<= offset;
- pm_runtime_get_sync(host->hba->dev);
- ufshcd_hold(host->hba, false);
ufshcd_rmwl(host->hba, TEST_BUS_SEL,
(u32)host->testbus.select_major << 19,
REG_UFS_CFG1);
@@ -2536,8 +2539,6 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
* committed before returning.
*/
mb();
- ufshcd_release(host->hba, false);
- pm_runtime_put_sync(host->hba->dev);
return 0;
}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d4acc3c911f5..bf357b50e798 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2769,6 +2769,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
hba = shost_priv(host);
+ if (!cmd || !cmd->request || !hba)
+ return -EINVAL;
+
tag = cmd->request->tag;
if (!ufshcd_valid_tag(hba, tag)) {
dev_err(hba->dev,
@@ -2854,13 +2857,12 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
ufshcd_vops_pm_qos_req_start(hba, cmd->request);
/* IO svc time latency histogram */
- if (hba != NULL && cmd->request != NULL) {
- if (hba->latency_hist_enabled &&
- (cmd->request->cmd_type == REQ_TYPE_FS)) {
- cmd->request->lat_hist_io_start = ktime_get();
- cmd->request->lat_hist_enabled = 1;
- } else
- cmd->request->lat_hist_enabled = 0;
+ if (hba->latency_hist_enabled &&
+ (cmd->request->cmd_type == REQ_TYPE_FS)) {
+ cmd->request->lat_hist_io_start = ktime_get();
+ cmd->request->lat_hist_enabled = 1;
+ } else {
+ cmd->request->lat_hist_enabled = 0;
}
WARN_ON(hba->clk_gating.state != CLKS_ON);
@@ -4141,17 +4143,17 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us)
ufshcd_hold_all(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
- if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
- ret = -EBUSY;
- goto out;
- }
-
/*
* Wait for all the outstanding tasks/transfer requests.
* Verify by checking the doorbell registers are clear.
*/
start = ktime_get();
do {
+ if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
+ ret = -EBUSY;
+ goto out;
+ }
+
tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
if (!tm_doorbell && !tr_doorbell) {
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 4192424df275..873416944b19 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2066,7 +2066,7 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb,
icnss_pr_info("Modem went down, state: %lx\n", priv->state);
- event_data = kzalloc(sizeof(*data), GFP_KERNEL);
+ event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (event_data == NULL)
return notifier_from_errno(-ENOMEM);
@@ -2141,7 +2141,7 @@ static int icnss_service_notifier_notify(struct notifier_block *nb,
case SERVREG_NOTIF_SERVICE_STATE_DOWN_V01:
icnss_pr_info("Service down, data: 0x%p, state: 0x%lx\n", data,
priv->state);
- event_data = kzalloc(sizeof(*data), GFP_KERNEL);
+ event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (event_data == NULL)
return notifier_from_errno(-ENOMEM);
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 5726c3277456..76f9ed046120 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -38,6 +38,7 @@ static void mem_share_svc_recv_msg(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg);
static struct workqueue_struct *mem_share_svc_workqueue;
static uint64_t bootup_request;
+static bool ramdump_event;
static void *memshare_ramdump_dev[MAX_CLIENTS];
static struct device *memshare_dev[MAX_CLIENTS];
@@ -337,18 +338,25 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
bootup_request++;
break;
+ case SUBSYS_RAMDUMP_NOTIFICATION:
+ ramdump_event = 1;
+ break;
+
case SUBSYS_BEFORE_POWERUP:
- if (_cmd)
+ if (_cmd) {
notifdata = (struct notif_data *) _cmd;
- else
+ } else {
+ ramdump_event = 0;
break;
+ }
- if (notifdata->enable_ramdump) {
+ if (notifdata->enable_ramdump && ramdump_event) {
pr_info("memshare: %s, Ramdump collection is enabled\n",
__func__);
ret = mem_share_do_ramdump();
if (ret)
pr_err("Ramdump collection failed\n");
+ ramdump_event = 0;
}
break;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index bc0e0184a917..1e252febc783 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -156,6 +156,7 @@ struct dwc3_msm {
struct clk *xo_clk;
struct clk *core_clk;
long core_clk_rate;
+ long core_clk_rate_hs;
struct clk *iface_clk;
struct clk *sleep_clk;
struct clk *utmi_clk;
@@ -195,6 +196,7 @@ struct dwc3_msm {
struct power_supply *usb_psy;
struct work_struct vbus_draw_work;
bool in_host_mode;
+ enum usb_device_speed max_rh_port_speed;
unsigned int tx_fifo_size;
bool vbus_active;
bool suspend;
@@ -342,6 +344,23 @@ static inline void dwc3_msm_write_readback(void *base, u32 offset,
__func__, val, offset);
}
+static bool dwc3_msm_is_ss_rhport_connected(struct dwc3_msm *mdwc)
+{
+ int i, num_ports;
+ u32 reg;
+
+ reg = dwc3_msm_read_reg(mdwc->base, USB3_HCSPARAMS1);
+ num_ports = HCS_MAX_PORTS(reg);
+
+ for (i = 0; i < num_ports; i++) {
+ reg = dwc3_msm_read_reg(mdwc->base, USB3_PORTSC + i*0x10);
+ if ((reg & PORT_CONNECT) && DEV_SUPERSPEED(reg))
+ return true;
+ }
+
+ return false;
+}
+
static bool dwc3_msm_is_host_superspeed(struct dwc3_msm *mdwc)
{
int i, num_ports;
@@ -2128,6 +2147,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
static int dwc3_msm_resume(struct dwc3_msm *mdwc)
{
int ret;
+ long core_clk_rate;
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__);
@@ -2175,7 +2195,15 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
clk_prepare_enable(mdwc->iface_clk);
if (mdwc->noc_aggr_clk)
clk_prepare_enable(mdwc->noc_aggr_clk);
- clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate);
+
+ core_clk_rate = mdwc->core_clk_rate;
+ if (mdwc->in_host_mode && mdwc->max_rh_port_speed == USB_SPEED_HIGH) {
+ core_clk_rate = mdwc->core_clk_rate_hs;
+ dev_dbg(mdwc->dev, "%s: set hs core clk rate %ld\n", __func__,
+ core_clk_rate);
+ }
+
+ clk_set_rate(mdwc->core_clk, core_clk_rate);
clk_prepare_enable(mdwc->core_clk);
/* set Memory core: ON, Memory periphery: ON */
@@ -2496,6 +2524,11 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
if (ret)
dev_err(mdwc->dev, "fail to set core_clk freq:%d\n", ret);
+ if (of_property_read_u32(mdwc->dev->of_node, "qcom,core-clk-rate-hs",
+ (u32 *)&mdwc->core_clk_rate_hs)) {
+ dev_dbg(mdwc->dev, "USB core-clk-rate-hs is not present\n");
+ mdwc->core_clk_rate_hs = mdwc->core_clk_rate;
+ }
mdwc->core_reset = devm_reset_control_get(mdwc->dev, "core_reset");
if (IS_ERR(mdwc->core_reset)) {
@@ -2723,6 +2756,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node, *dwc3_node;
struct device *dev = &pdev->dev;
+ union power_supply_propval pval = {0};
struct dwc3_msm *mdwc;
struct dwc3 *dwc;
struct resource *res;
@@ -3016,10 +3050,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
*/
mdwc->lpm_flags = MDWC3_POWER_COLLAPSE | MDWC3_SS_PHY_SUSPEND;
atomic_set(&dwc->in_lpm, 1);
- pm_runtime_set_suspended(mdwc->dev);
pm_runtime_set_autosuspend_delay(mdwc->dev, 1000);
pm_runtime_use_autosuspend(mdwc->dev);
- pm_runtime_enable(mdwc->dev);
device_init_wakeup(mdwc->dev, 1);
if (of_property_read_bool(node, "qcom,disable-dev-mode-pm"))
@@ -3036,18 +3068,32 @@ static int dwc3_msm_probe(struct platform_device *pdev)
mdwc->pm_qos_latency = 0;
}
+ mdwc->usb_psy = power_supply_get_by_name("usb");
+ if (!mdwc->usb_psy) {
+ dev_warn(mdwc->dev, "Could not get usb power_supply\n");
+ pval.intval = -EINVAL;
+ } else {
+ power_supply_get_property(mdwc->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ }
+
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))
dwc3_msm_vbus_notifier(&mdwc->vbus_nb, true, mdwc->extcon_vbus);
- if (mdwc->extcon_id && extcon_get_cable_state_(mdwc->extcon_id,
+ else if (mdwc->extcon_id && extcon_get_cable_state_(mdwc->extcon_id,
EXTCON_USB_HOST))
dwc3_msm_id_notifier(&mdwc->id_nb, true, mdwc->extcon_id);
+ else if (!pval.intval) {
+ /* USB cable is not connected */
+ schedule_delayed_work(&mdwc->sm_work, 0);
+ } else {
+ if (pval.intval > 0)
+ dev_info(mdwc->dev, "charger detection in progress\n");
+ }
device_create_file(&pdev->dev, &dev_attr_mode);
- schedule_delayed_work(&mdwc->sm_work, 0);
-
host_mode = usb_get_dr_mode(&mdwc->dwc3->dev) == USB_DR_MODE_HOST;
if (!dwc->is_drd && host_mode) {
dev_dbg(&pdev->dev, "DWC3 in host only mode\n");
@@ -3166,10 +3212,26 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb,
if (udev->parent && !udev->parent->parent &&
udev->dev.parent->parent == &dwc->xhci->dev) {
if (event == USB_DEVICE_ADD && udev->actconfig) {
+ if (!dwc3_msm_is_ss_rhport_connected(mdwc)) {
+ /*
+ * Core clock rate can be reduced only if root
+ * hub SS port is not enabled/connected.
+ */
+ clk_set_rate(mdwc->core_clk,
+ mdwc->core_clk_rate_hs);
+ dev_dbg(mdwc->dev,
+ "set hs core clk rate %ld\n",
+ mdwc->core_clk_rate_hs);
+ mdwc->max_rh_port_speed = USB_SPEED_HIGH;
+ } else {
+ mdwc->max_rh_port_speed = USB_SPEED_SUPER;
+ }
+
if (udev->speed >= USB_SPEED_SUPER)
max_power = udev->actconfig->desc.bMaxPower * 8;
else
max_power = udev->actconfig->desc.bMaxPower * 2;
+
dev_dbg(mdwc->dev, "%s configured bMaxPower:%d (mA)\n",
dev_name(&udev->dev), max_power);
@@ -3181,6 +3243,7 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb,
pval.intval = 0;
power_supply_set_property(mdwc->usb_psy,
POWER_SUPPLY_PROP_BOOST_CURRENT, &pval);
+ mdwc->max_rh_port_speed = USB_SPEED_UNKNOWN;
}
}
@@ -3538,13 +3601,25 @@ static void dwc3_otg_sm_work(struct work_struct *w)
/* Check OTG state */
switch (mdwc->otg_state) {
case OTG_STATE_UNDEFINED:
- /* Do nothing if no cable connected */
+ /* put controller and phy in suspend if no cable connected */
if (test_bit(ID, &mdwc->inputs) &&
- !test_bit(B_SESS_VLD, &mdwc->inputs))
+ !test_bit(B_SESS_VLD, &mdwc->inputs)) {
+ dbg_event(0xFF, "undef_id_!bsv", 0);
+ pm_runtime_set_active(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
+ pm_runtime_get_noresume(mdwc->dev);
+ dwc3_msm_resume(mdwc);
+ pm_runtime_put_sync(mdwc->dev);
+ dbg_event(0xFF, "Undef NoUSB",
+ atomic_read(&mdwc->dev->power.usage_count));
+ mdwc->otg_state = OTG_STATE_B_IDLE;
break;
+ }
dbg_event(0xFF, "Exit UNDEF", 0);
mdwc->otg_state = OTG_STATE_B_IDLE;
+ pm_runtime_set_suspended(mdwc->dev);
+ pm_runtime_enable(mdwc->dev);
/* fall-through */
case OTG_STATE_B_IDLE:
if (!test_bit(ID, &mdwc->inputs)) {
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 7cafd0dd59f5..97d86b6ac69b 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2490,8 +2490,14 @@ static void handle_exception(struct fsg_common *common)
case FSG_STATE_CONFIG_CHANGE:
do_set_interface(common, common->new_fsg);
- if (common->new_fsg)
+ if (common->new_fsg) {
+ /*
+ * make sure delayed_status flag updated when set_alt
+ * returned.
+ */
+ msleep(200);
usb_composite_setup_continue(common->cdev);
+ }
break;
case FSG_STATE_EXIT:
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 656b58eb62d7..111d7cfc7c9a 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -428,6 +428,12 @@ static inline bool mdss_fb_is_power_on_lp(struct msm_fb_data_type *mfd)
return mdss_panel_is_power_on_lp(mfd->panel_power_state);
}
+static inline bool mdss_fb_is_power_on_ulp(struct msm_fb_data_type *mfd)
+{
+ return mdss_panel_is_power_on_ulp(mfd->panel_power_state);
+}
+
+
static inline bool mdss_fb_is_hdmi_primary(struct msm_fb_data_type *mfd)
{
return (mfd && (mfd->index == 0) &&
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index d3d332d780d5..cb9cc08140f0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1,5 +1,5 @@
/*
- * 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
@@ -124,6 +124,7 @@
#define DS_ENHANCER_UPDATE BIT(5)
#define DS_VALIDATE BIT(6)
#define DS_DIRTY_UPDATE BIT(7)
+#define DS_PU_ENABLE BIT(8)
/**
* Destination Scaler DUAL mode overfetch pixel count
@@ -386,6 +387,7 @@ struct mdss_mdp_destination_scaler {
u16 last_mixer_height;
u32 flags;
struct mdp_scale_data_v2 scaler;
+ struct mdss_rect panel_roi;
};
@@ -1169,6 +1171,14 @@ static inline int is_dest_scaling_enable(struct mdss_mdp_mixer *mixer)
mixer && mixer->ds && (mixer->ds->flags & DS_ENABLE));
}
+static inline int is_dest_scaling_pu_enable(struct mdss_mdp_mixer *mixer)
+{
+ if (is_dest_scaling_enable(mixer))
+ return (mixer->ds->flags & DS_PU_ENABLE);
+
+ return 0;
+}
+
static inline u32 get_ds_input_width(struct mdss_mdp_mixer *mixer)
{
struct mdss_mdp_destination_scaler *ds;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index f7840ee8245e..ffbf156e9eed 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -4434,6 +4434,13 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
goto end;
}
+ /*
+ * reset the play_cnt, after the cmd_stop
+ * this will ensure pipes are reconfiged
+ * after every panel power state change
+ */
+ ctl->play_cnt = 0;
+
if (mdss_panel_is_power_on(power_state)) {
pr_debug("panel is not off, leaving ctl power on\n");
goto end;
@@ -4450,8 +4457,6 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl, int power_state)
mdss_mdp_reset_mixercfg(ctl);
- ctl->play_cnt = 0;
-
end:
if (!ret) {
ctl->power_state = power_state;
@@ -4653,7 +4658,15 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
previous_frame_pu_type = mdss_mdp_get_pu_type(ctl);
if (ctl->mixer_left) {
mdss_mdp_set_mixer_roi(ctl->mixer_left, l_roi);
- ctl->roi = ctl->mixer_left->roi;
+ if (is_dest_scaling_enable(ctl->mixer_left))
+ ctl->roi = ctl->mixer_left->ds->panel_roi;
+ else
+ ctl->roi = ctl->mixer_left->roi;
+
+ pr_debug("ctl->mixer_left: [%d %d %d %d] ds:%d\n",
+ ctl->roi.x, ctl->roi.y,
+ ctl->roi.w, ctl->roi.h,
+ is_dest_scaling_enable(ctl->mixer_left));
}
if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) {
@@ -4661,20 +4674,43 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
if (sctl && sctl->mixer_left) {
mdss_mdp_set_mixer_roi(sctl->mixer_left, r_roi);
- sctl->roi = sctl->mixer_left->roi;
+ if (is_dest_scaling_enable(sctl->mixer_left))
+ sctl->roi = sctl->mixer_left->ds->panel_roi;
+ else
+ sctl->roi = sctl->mixer_left->roi;
+
+ pr_debug("sctl->mixer_left: [%d %d %d %d] ds:%d\n",
+ sctl->roi.x, sctl->roi.y,
+ sctl->roi.w, sctl->roi.h,
+ is_dest_scaling_enable(sctl->mixer_left));
+
}
} else if (is_dual_lm_single_display(ctl->mfd) && ctl->mixer_right) {
mdss_mdp_set_mixer_roi(ctl->mixer_right, r_roi);
/* in this case, CTL_ROI is a union of left+right ROIs. */
- ctl->roi.w += ctl->mixer_right->roi.w;
+ if (is_dest_scaling_enable(ctl->mixer_right))
+ ctl->roi.w += ctl->mixer_right->ds->panel_roi.w;
+ else
+ ctl->roi.w += ctl->mixer_right->roi.w;
/* right_only, update roi.x as per CTL ROI guidelines */
if (ctl->mixer_left && !ctl->mixer_left->valid_roi) {
- ctl->roi = ctl->mixer_right->roi;
- ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
- ctl->mixer_right->roi.x;
+ if (is_dest_scaling_enable(ctl->mixer_right)) {
+ ctl->roi = ctl->mixer_right->ds->panel_roi;
+ ctl->roi.x =
+ get_ds_output_width(ctl->mixer_left) +
+ ctl->mixer_right->ds->panel_roi.x;
+ } else {
+ ctl->roi = ctl->mixer_right->roi;
+ ctl->roi.x = left_lm_w_from_mfd(ctl->mfd) +
+ ctl->mixer_right->roi.x;
+ }
+ pr_debug("ctl->mixer_right_only : [%d %d %d %d] ds:%d\n",
+ ctl->roi.x, ctl->roi.y,
+ ctl->roi.w, ctl->roi.h,
+ is_dest_scaling_enable(ctl->mixer_right));
}
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index af763cf6b306..0eb82dd8371d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -67,6 +67,36 @@ static inline void *u64_to_ptr(uint64_t address)
return (void *)(uintptr_t)address;
}
+static inline struct mdp_destination_scaler_data *__dest_scaler_next(
+ struct mdp_destination_scaler_data *ds_data, int ds_count)
+{
+ struct mdp_destination_scaler_data *ds_data_r = ds_data;
+ size_t offset;
+
+ /*
+ * Advanced to next ds_data structure from commit if
+ * there is more than 1 for source split usecase.
+ */
+ if (ds_count > 1) {
+ ds_data_r = ds_data + 1;
+
+ /*
+ * To check for binary compatibility with old user mode
+ * driver which does not have ROI support in destination
+ * scalar.
+ */
+ if ((ds_data_r->dest_scaler_ndx != 1) &&
+ (ds_data_r->lm_height != ds_data->lm_height)) {
+ offset = offsetof(struct mdp_destination_scaler_data,
+ panel_roi);
+ ds_data_r = (struct mdp_destination_scaler_data *)(
+ (void *)ds_data + offset);
+ }
+ }
+
+ return ds_data_r;
+}
+
static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
{
struct mdss_data_type *mdata = ctl->mdata;
@@ -94,6 +124,9 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
ctl->mixer_right->roi = (struct mdss_rect) { 0, 0,
ctl->mixer_right->width,
ctl->mixer_right->height };
+ if (split_ctl)
+ split_ctl->mixer_left->roi =
+ ctl->mixer_right->roi;
/*
* Disable destination scaler by resetting the control
@@ -143,6 +176,46 @@ static void mdss_mdp_disable_destination_scaler_setup(struct mdss_mdp_ctl *ctl)
}
}
+static int __dest_scaler_panel_roi_update(
+ struct mdp_destination_scaler_data *ds_data,
+ struct mdss_mdp_destination_scaler *ds)
+{
+ if (ds_data->flags & MDP_DESTSCALER_ROI_ENABLE) {
+ /*
+ * Updating PANEL ROI info, used in partial update
+ */
+ if ((ds_data->panel_roi.w > ds->scaler.dst_width) ||
+ (ds_data->panel_roi.h >
+ ds->scaler.dst_height) ||
+ (ds_data->panel_roi.w == 0) ||
+ (ds_data->panel_roi.h == 0)) {
+ pr_err("Invalid panel ROI parameter for dest-scaler-%d: [%d %d %d %d]\n",
+ ds_data->dest_scaler_ndx,
+ ds_data->panel_roi.x,
+ ds_data->panel_roi.y,
+ ds_data->panel_roi.w,
+ ds_data->panel_roi.h);
+ ds->flags &= ~DS_PU_ENABLE;
+ return -EINVAL;
+ }
+ ds->panel_roi.x = ds_data->panel_roi.x;
+ ds->panel_roi.y = ds_data->panel_roi.y;
+ ds->panel_roi.w = ds_data->panel_roi.w;
+ ds->panel_roi.h = ds_data->panel_roi.h;
+ ds->flags |= DS_PU_ENABLE;
+ pr_debug("dest-scaler[%d] panel_roi update: [%d,%d,%d,%d]\n",
+ ds->num,
+ ds_data->panel_roi.x, ds_data->panel_roi.y,
+ ds_data->panel_roi.w, ds_data->panel_roi.h);
+ MDSS_XLOG(ds->num, ds_data->panel_roi.x, ds_data->panel_roi.y,
+ ds_data->panel_roi.w, ds_data->panel_roi.h);
+ } else {
+ ds->flags &= ~DS_PU_ENABLE;
+ }
+
+ return 0;
+}
+
static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
struct mdss_mdp_destination_scaler *ds,
u32 max_input_width, u32 max_output_width)
@@ -188,6 +261,9 @@ static int __dest_scaler_data_setup(struct mdp_destination_scaler_data *ds_data,
ds->src_height = ds_data->lm_height;
}
+ if (__dest_scaler_panel_roi_update(ds_data, ds))
+ return -EINVAL;
+
if (ds_data->flags == 0) {
pr_debug("Disabling destination scaler-%d\n",
ds_data->dest_scaler_ndx);
@@ -235,13 +311,7 @@ static int mdss_mdp_destination_scaler_pre_validate(struct mdss_mdp_ctl *ctl,
}
if (ctl->mixer_right && ctl->mixer_right->ds) {
- /*
- * Advanced to next ds_data structure from commit if
- * there is more than 1 for split display usecase.
- */
- if (ds_count > 1)
- ds_data++;
-
+ ds_data = __dest_scaler_next(ds_data, ds_count);
pinfo = &ctl->panel_data->panel_info;
if ((ds_data->lm_width > get_panel_xres(pinfo)) ||
(ds_data->lm_height > get_panel_yres(pinfo)) ||
@@ -317,14 +387,17 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
int ret = 0;
struct mdss_data_type *mdata;
struct mdss_mdp_ctl *ctl;
+ struct mdss_mdp_ctl *sctl;
struct mdss_mdp_destination_scaler *ds_left = NULL;
struct mdss_mdp_destination_scaler *ds_right = NULL;
struct mdss_panel_info *pinfo;
u32 scaler_width, scaler_height;
+ struct mdp_destination_scaler_data *ds_data_r = NULL;
if (ds_data) {
mdata = mfd_to_mdata(mfd);
ctl = mfd_to_ctl(mfd);
+ sctl = mdss_mdp_get_split_ctl(ctl);
if (ctl->mixer_left)
ds_left = ctl->mixer_left->ds;
@@ -332,6 +405,9 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ctl->mixer_right)
ds_right = ctl->mixer_right->ds;
+ if (sctl && sctl->mixer_left && ds_right)
+ sctl->mixer_left->ds = ds_right;
+
switch (ds_mode) {
case DS_DUAL_MODE:
if (!ds_left || !ds_right) {
@@ -346,13 +422,28 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
- ret = __dest_scaler_data_setup(&ds_data[1], ds_right,
+ ds_data_r = __dest_scaler_next(ds_data, 2);
+ ret = __dest_scaler_data_setup(ds_data_r, ds_right,
mdata->max_dest_scaler_input_width -
MDSS_MDP_DS_OVERFETCH_SIZE,
mdata->max_dest_scaler_output_width);
if (ret)
goto reset_mixer;
+ if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
+ pinfo = &ctl->panel_data->panel_info;
+ if (ds_right->panel_roi.x >=
+ get_panel_xres(pinfo)) {
+ ds_right->panel_roi.x -=
+ get_panel_xres(pinfo);
+ } else {
+ pr_err("SCTL DS right roi.x:%d < left panel width:%d\n",
+ ds_right->panel_roi.x,
+ get_panel_xres(pinfo));
+ goto reset_mixer;
+ }
+ }
+
ds_left->flags &= ~(DS_LEFT|DS_RIGHT);
ds_left->flags |= DS_DUAL_MODE;
ds_right->flags &= ~(DS_LEFT|DS_RIGHT);
@@ -377,6 +468,17 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
+ /*
+ * For Partial update usecase, it is possible switching
+ * from Left+Right mode to Left only mode. So make sure
+ * cleanup the DS_RIGHT flags.
+ */
+ if (ds_right) {
+ ds_right->flags &=
+ ~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
+ ds_right->flags |= DS_VALIDATE;
+ }
+
MDSS_XLOG(ds_left->num, ds_left->src_width,
ds_left->src_height, ds_left->flags);
break;
@@ -396,6 +498,26 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
if (ret)
goto reset_mixer;
+ if (ds_left) {
+ ds_left->flags &=
+ ~(DS_DUAL_MODE|DS_ENABLE|DS_PU_ENABLE);
+ ds_left->flags |= DS_VALIDATE;
+ }
+
+ if ((ds_right->flags & DS_PU_ENABLE) && sctl) {
+ pinfo = &ctl->panel_data->panel_info;
+ if (ds_right->panel_roi.x >=
+ get_panel_xres(pinfo)) {
+ ds_right->panel_roi.x -=
+ get_panel_xres(pinfo);
+ } else {
+ pr_err("SCTL DS-right-only roi.x:%d < Left panel width:%d\n",
+ ds_right->panel_roi.x,
+ get_panel_xres(pinfo));
+ goto reset_mixer;
+ }
+ }
+
MDSS_XLOG(ds_right->num, ds_right->src_width,
ds_right->src_height, ds_right->flags);
break;
@@ -418,11 +540,11 @@ static int mdss_mdp_validate_destination_scaler(struct msm_fb_data_type *mfd,
pinfo = &ctl->panel_data->panel_info;
scaler_width = 0;
scaler_height = 0;
- if (ds_left && ds_left->flags) {
+ if (ds_left && (ds_left->flags & DS_ENABLE)) {
scaler_width += ds_left->scaler.dst_width;
scaler_height = ds_left->scaler.dst_height;
}
- if (ds_right && ds_right->flags) {
+ if (ds_right && (ds_right->flags & DS_ENABLE)) {
scaler_width += ds_right->scaler.dst_width;
scaler_height = ds_right->scaler.dst_height;
}
@@ -2731,7 +2853,8 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
return -ENODEV;
}
- if (mdss_fb_is_power_off(mfd)) {
+ if (mdss_fb_is_power_off(mfd) ||
+ mdss_fb_is_power_on_ulp(mfd)) {
pr_err("display interface is in off state fb:%d\n",
mfd->index);
return -EPERM;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index c6fc10833d7f..9864d611e8e4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.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
@@ -1930,6 +1930,39 @@ static void __restore_pipe(struct mdss_mdp_pipe *pipe)
pipe->restore_roi = false;
}
+static void __restore_dest_scaler_roi(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
+ struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+
+ if (is_dest_scaling_pu_enable(ctl->mixer_left)) {
+ ctl->mixer_left->ds->panel_roi.x = 0;
+ ctl->mixer_left->ds->panel_roi.y = 0;
+ ctl->mixer_left->ds->panel_roi.w = get_panel_xres(pinfo);
+ ctl->mixer_left->ds->panel_roi.h = get_panel_yres(pinfo);
+
+ if ((ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) &&
+ sctl) {
+ if (ctl->panel_data->next)
+ pinfo = &ctl->panel_data->next->panel_info;
+ sctl->mixer_left->ds->panel_roi.x = 0;
+ sctl->mixer_left->ds->panel_roi.y = 0;
+ sctl->mixer_left->ds->panel_roi.w =
+ get_panel_xres(pinfo);
+ sctl->mixer_left->ds->panel_roi.h =
+ get_panel_yres(pinfo);
+ } else if (ctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) {
+ ctl->mixer_right->ds->panel_roi.x =
+ get_panel_xres(pinfo);
+ ctl->mixer_right->ds->panel_roi.y = 0;
+ ctl->mixer_right->ds->panel_roi.w =
+ get_panel_xres(pinfo);
+ ctl->mixer_right->ds->panel_roi.h =
+ get_panel_yres(pinfo);
+ }
+ }
+}
+
/**
* __adjust_pipe_rect() - Adjust pipe roi for dual partial update feature.
* @pipe: pipe to check against.
@@ -2145,6 +2178,9 @@ set_roi:
}
dual_roi->enabled = false;
}
+
+ if (pinfo->partial_update_enabled)
+ __restore_dest_scaler_roi(ctl);
}
pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n",
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 6870193166f2..563cb8be1a04 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2406,8 +2406,16 @@ bool mdss_mdp_is_amortizable_pipe(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_mixer *mixer, struct mdss_data_type *mdata)
{
/* do not apply for rotator or WB */
- return ((pipe->dst.y > mdata->prefill_data.ts_threshold) &&
- (mixer->type == MDSS_MDP_MIXER_TYPE_INTF));
+ if (!((pipe->dst.y > mdata->prefill_data.ts_threshold) &&
+ (mixer->type == MDSS_MDP_MIXER_TYPE_INTF)))
+ return false;
+
+ /* do not apply for sdm660 in command mode */
+ if ((IS_MDSS_MAJOR_MINOR_SAME(mdata->mdp_rev,
+ MDSS_MDP_HW_REV_320)) && !mixer->ctl->is_video_mode)
+ return false;
+
+ return true;
}
static inline void __get_ordered_rects(struct mdss_mdp_pipe *pipe,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 294344b3f0f0..e5930177c96a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -70,6 +70,7 @@ struct wiphy;
#define CFG80211_UPDATE_CONNECT_PARAMS 1
#define CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT 1
#define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1
+#define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1
/*
* wireless hardware capability structures
@@ -1569,6 +1570,17 @@ struct cfg80211_sched_scan_plan {
};
/**
+ * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
+ *
+ * @band: band of BSS which should match for RSSI level adjustment.
+ * @delta: value of RSSI level adjustment.
+ */
+struct cfg80211_bss_select_adjust {
+ enum nl80211_band band;
+ s8 delta;
+};
+
+/**
* struct cfg80211_sched_scan_request - scheduled scan request description
*
* @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
@@ -1603,6 +1615,16 @@ struct cfg80211_sched_scan_plan {
* cycle. The driver may ignore this parameter and start
* immediately (or at any other time), if this feature is not
* supported.
+ * @relative_rssi_set: Indicates whether @relative_rssi is set or not.
+ * @relative_rssi: Relative RSSI threshold in dB to restrict scan result
+ * reporting in connected state to cases where a matching BSS is determined
+ * to have better or slightly worse RSSI than the current connected BSS.
+ * The relative RSSI threshold values are ignored in disconnected state.
+ * @rssi_adjust: delta dB of RSSI preference to be given to the BSSs that belong
+ * to the specified band while deciding whether a better BSS is reported
+ * using @relative_rssi. If delta is a negative number, the BSSs that
+ * belong to the specified band will be penalized by delta dB in relative
+ * comparisions.
*/
struct cfg80211_sched_scan_request {
struct cfg80211_ssid *ssids;
@@ -1622,6 +1644,10 @@ struct cfg80211_sched_scan_request {
u8 mac_addr[ETH_ALEN] __aligned(2);
u8 mac_addr_mask[ETH_ALEN] __aligned(2);
+ bool relative_rssi_set;
+ s8 relative_rssi;
+ struct cfg80211_bss_select_adjust rssi_adjust;
+
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
@@ -1907,6 +1933,22 @@ struct cfg80211_ibss_params {
};
/**
+ * struct cfg80211_bss_selection - connection parameters for BSS selection.
+ *
+ * @behaviour: requested BSS selection behaviour.
+ * @param: parameters for requestion behaviour.
+ * @band_pref: preferred band for %NL80211_BSS_SELECT_ATTR_BAND_PREF.
+ * @adjust: parameters for %NL80211_BSS_SELECT_ATTR_RSSI_ADJUST.
+ */
+struct cfg80211_bss_selection {
+ enum nl80211_bss_select_attr behaviour;
+ union {
+ enum ieee80211_band band_pref;
+ struct cfg80211_bss_select_adjust adjust;
+ } param;
+};
+
+/**
* struct cfg80211_connect_params - Connection parameters
*
* This structure provides information needed to complete IEEE 802.11
@@ -1943,6 +1985,7 @@ struct cfg80211_ibss_params {
* @vht_capa_mask: The bits of vht_capa which are to be used.
* @pbss: if set, connect to a PCP instead of AP. Valid for DMG
* networks.
+ * @bss_select: criteria to be used for BSS selection.
* @prev_bssid: previous BSSID, if not %NULL use reassociate frame
*/
struct cfg80211_connect_params {
@@ -1967,6 +2010,7 @@ struct cfg80211_connect_params {
struct ieee80211_vht_cap vht_capa;
struct ieee80211_vht_cap vht_capa_mask;
bool pbss;
+ struct cfg80211_bss_selection bss_select;
const u8 *prev_bssid;
};
@@ -3284,6 +3328,9 @@ struct wiphy_iftype_ext_capab {
* low rssi when a frame is heard on different channel, then it should set
* this variable to the maximal offset for which it can compensate.
* This value should be set in MHz.
+ * @bss_select_support: bitmask indicating the BSS selection criteria supported
+ * by the driver in the .connect() callback. The bit position maps to the
+ * attribute indices defined in &enum nl80211_bss_select_attr.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -3411,6 +3458,8 @@ struct wiphy {
u8 max_num_csa_counters;
u8 max_adj_channel_rssi_comp;
+ u32 bss_select_support;
+
char priv[0] __aligned(NETDEV_ALIGN);
};
diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 24f1e7c7b742..3bd8bea8ae0d 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -125,6 +125,12 @@ DESTINATION SCALER FLAG CONFIGURATION
*/
#define MDP_DESTSCALER_ENHANCER_UPDATE 0x4
+/*
+ * Indicating a partial update to panel ROI. ROI can be
+ * applied anytime when Destination scaler is enabled.
+ */
+#define MDP_DESTSCALER_ROI_ENABLE 0x8
+
/**********************************************************************
VALIDATE/COMMIT FLAG CONFIGURATION
**********************************************************************/
@@ -405,6 +411,12 @@ struct mdp_destination_scaler_data {
* A userspace pointer points to struct mdp_scale_data_v2.
*/
uint64_t __user scale;
+
+ /*
+ * Panel ROI is used when partial update is required in
+ * current commit call.
+ */
+ struct mdp_rect panel_roi;
};
/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 335b331cbf4f..0505b1f9872b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1934,6 +1934,20 @@ enum nl80211_commands {
* @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
* used in various commands/events for specifying the BSSID.
*
+ * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which
+ * other BSSs has to be better or slightly worse than the current
+ * connected BSS so that they get reported to user space.
+ * This will give an opportunity to userspace to consider connecting to
+ * other matching BSSs which have better or slightly worse RSSI than
+ * the current connected BSS by using an offloaded operation to avoid
+ * unnecessary wakeups.
+ *
+ * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for BSSs in
+ * the specified band is to be adjusted before doing
+ * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparision to figure out
+ * better BSSs. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2340,6 +2354,9 @@ enum nl80211_attrs {
NL80211_ATTR_BSSID,
+ NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+ NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3008,6 +3025,13 @@ enum nl80211_reg_rule_attr {
* how this API was implemented in the past. Also, due to the same problem,
* the only way to create a matchset with only an RSSI filter (with this
* attribute) is if there's only a single matchset with the RSSI attribute.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI: Flag indicating whether
+ * %NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to be used as absolute RSSI or
+ * relative to current bss's RSSI.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST: When present the RSSI level for
+ * BSS-es in the specified band is to be adjusted before doing
+ * RSSI-based BSS selection. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
* @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
* attribute number currently defined
* @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3017,6 +3041,8 @@ enum nl80211_sched_scan_match_attr {
NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
/* keep last */
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -4609,6 +4635,9 @@ enum nl80211_feature_flags {
* in @NL80211_CMD_FRAME while not associated.
* @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED: This driver supports
* randomized TA in @NL80211_CMD_FRAME while associated.
+ * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan
+ * for reporting BSSs with better RSSI than the current connected BSS
+ * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4626,6 +4655,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_FILS_STA,
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA,
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED,
+ NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
@@ -4875,4 +4905,48 @@ enum nl80211_sched_scan_plan {
__NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1
};
+/**
+ * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters.
+ *
+ * @band: band of BSS that must match for RSSI value adjustment.
+ * @delta: value used to adjust the RSSI value of matching BSS.
+ */
+struct nl80211_bss_select_rssi_adjust {
+ __u8 band;
+ __s8 delta;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_bss_select_attr - attributes for bss selection.
+ *
+ * @__NL80211_BSS_SELECT_ATTR_INVALID: reserved.
+ * @NL80211_BSS_SELECT_ATTR_RSSI: Flag indicating only RSSI-based BSS selection
+ * is requested.
+ * @NL80211_BSS_SELECT_ATTR_BAND_PREF: attribute indicating BSS
+ * selection should be done such that the specified band is preferred.
+ * When there are multiple BSS-es in the preferred band, the driver
+ * shall use RSSI-based BSS selection as a second step. The value of
+ * this attribute is according to &enum nl80211_band (u32).
+ * @NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: When present the RSSI level for
+ * BSS-es in the specified band is to be adjusted before doing
+ * RSSI-based BSS selection. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ * @NL80211_BSS_SELECT_ATTR_MAX: highest bss select attribute number.
+ * @__NL80211_BSS_SELECT_ATTR_AFTER_LAST: internal use.
+ *
+ * One and only one of these attributes are found within %NL80211_ATTR_BSS_SELECT
+ * for %NL80211_CMD_CONNECT. It specifies the required BSS selection behaviour
+ * which the driver shall use.
+ */
+enum nl80211_bss_select_attr {
+ __NL80211_BSS_SELECT_ATTR_INVALID,
+ NL80211_BSS_SELECT_ATTR_RSSI,
+ NL80211_BSS_SELECT_ATTR_BAND_PREF,
+ NL80211_BSS_SELECT_ATTR_RSSI_ADJUST,
+
+ /* keep last */
+ __NL80211_BSS_SELECT_ATTR_AFTER_LAST,
+ NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index c52655581c4c..ac4c3f1d144a 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7940,10 +7940,11 @@ static int detach_tasks(struct lb_env *env)
if (env->imbalance <= 0)
return 0;
+ if (!same_cluster(env->dst_cpu, env->src_cpu))
+ env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS;
+
if (cpu_capacity(env->dst_cpu) < cpu_capacity(env->src_cpu))
env->flags |= LBF_IGNORE_BIG_TASKS;
- else if (!same_cluster(env->dst_cpu, env->src_cpu))
- env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS;
redo:
while (!list_empty(tasks)) {
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d3873333c766..a2a87c3ad44e 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -178,7 +178,7 @@ extern int no_unaligned_warning;
#define SYSCTL_WRITES_WARN 0
#define SYSCTL_WRITES_STRICT 1
-static int sysctl_writes_strict = SYSCTL_WRITES_WARN;
+static int sysctl_writes_strict = SYSCTL_WRITES_STRICT;
static int proc_do_cad_pid(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d41925306d75..c42587d02190 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1754,13 +1754,25 @@ static void unreserve_highatomic_pageblock(const struct alloc_context *ac)
struct page, lru);
/*
- * It should never happen but changes to locking could
- * inadvertently allow a per-cpu drain to add pages
- * to MIGRATE_HIGHATOMIC while unreserving so be safe
- * and watch for underflows.
+ * In page freeing path, migratetype change is racy so
+ * we can counter several free pages in a pageblock
+ * in this loop althoug we changed the pageblock type
+ * from highatomic to ac->migratetype. So we should
+ * adjust the count once.
*/
- zone->nr_reserved_highatomic -= min(pageblock_nr_pages,
- zone->nr_reserved_highatomic);
+ if (get_pageblock_migratetype(page) ==
+ MIGRATE_HIGHATOMIC) {
+ /*
+ * It should never happen but changes to
+ * locking could inadvertently allow a per-cpu
+ * drain to add pages to MIGRATE_HIGHATOMIC
+ * while unreserving so be safe and watch for
+ * underflows.
+ */
+ zone->nr_reserved_highatomic -= min(
+ pageblock_nr_pages,
+ zone->nr_reserved_highatomic);
+ }
/*
* Convert to ac->migratetype and avoid the normal
@@ -1802,7 +1814,8 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
page = list_entry(area->free_list[fallback_mt].next,
struct page, lru);
- if (can_steal)
+ if (can_steal &&
+ get_pageblock_migratetype(page) != MIGRATE_HIGHATOMIC)
steal_suitable_fallback(zone, page, start_migratetype);
/* Remove the page from the freelists */
@@ -2240,7 +2253,8 @@ int __isolate_free_page(struct page *page, unsigned int order)
struct page *endpage = page + (1 << order) - 1;
for (; page < endpage; page += pageblock_nr_pages) {
int mt = get_pageblock_migratetype(page);
- if (!is_migrate_isolate(mt) && !is_migrate_cma(mt))
+ if (!is_migrate_isolate(mt) && !is_migrate_cma(mt)
+ && mt != MIGRATE_HIGHATOMIC)
set_pageblock_migratetype(page,
MIGRATE_MOVABLE);
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 16043faba52c..14868e42f3ca 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -619,6 +619,13 @@ int wiphy_register(struct wiphy *wiphy)
!rdev->ops->set_mac_acl)))
return -EINVAL;
+ /* assure only valid behaviours are flagged by driver
+ * hence subtract 2 as bit 0 is invalid.
+ */
+ if (WARN_ON(wiphy->bss_select_support &&
+ (wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
+ return -EINVAL;
+
if (wiphy->addresses)
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2d71cafde513..5ec8e5cf8a8e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -402,7 +402,12 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
[NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
+ [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
[NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
+ [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
+ [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
+ .len = sizeof(struct nl80211_bss_select_rssi_adjust)
+ },
};
/* policy for the key attributes */
@@ -487,6 +492,15 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
[NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
};
+static const struct nla_policy
+nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
+ [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
+ [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
+ [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
+ .len = sizeof(struct nl80211_bss_select_rssi_adjust)
+ },
+};
+
static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct cfg80211_registered_device **rdev,
@@ -1778,6 +1792,25 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
}
}
+ if (rdev->wiphy.bss_select_support) {
+ struct nlattr *nested;
+ u32 bss_select_support = rdev->wiphy.bss_select_support;
+
+ nested = nla_nest_start(msg, NL80211_ATTR_BSS_SELECT);
+ if (!nested)
+ goto nla_put_failure;
+
+ i = 0;
+ while (bss_select_support) {
+ if ((bss_select_support & 1) &&
+ nla_put_flag(msg, i))
+ goto nla_put_failure;
+ i++;
+ bss_select_support >>= 1;
+ }
+ nla_nest_end(msg, nested);
+ }
+
/* done */
state->split_start = 0;
break;
@@ -6087,6 +6120,73 @@ static int validate_scan_freqs(struct nlattr *freqs)
return n_channels;
}
+static bool is_band_valid(struct wiphy *wiphy, enum ieee80211_band b)
+{
+ return b < IEEE80211_NUM_BANDS && wiphy->bands[b];
+}
+
+static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
+ struct cfg80211_bss_selection *bss_select)
+{
+ struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
+ struct nlattr *nest;
+ int err;
+ bool found = false;
+ int i;
+
+ /* only process one nested attribute */
+ nest = nla_data(nla);
+ if (!nla_ok(nest, nla_len(nest)))
+ return -EINVAL;
+
+ err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest),
+ nla_len(nest), nl80211_bss_select_policy);
+ if (err)
+ return err;
+
+ /* only one attribute may be given */
+ for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
+ if (attr[i]) {
+ if (found)
+ return -EINVAL;
+ found = true;
+ }
+ }
+
+ bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
+
+ if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
+
+ if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
+ bss_select->param.band_pref =
+ nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
+ if (!is_band_valid(wiphy, bss_select->param.band_pref))
+ return -EINVAL;
+ }
+
+ if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
+ struct nl80211_bss_select_rssi_adjust *adj_param;
+
+ adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
+ bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
+ bss_select->param.adjust.band = adj_param->band;
+ bss_select->param.adjust.delta = adj_param->delta;
+ if (!is_band_valid(wiphy, bss_select->param.adjust.band))
+ return -EINVAL;
+ }
+
+ /* user-space did not provide behaviour attribute */
+ if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
+ return -EINVAL;
+
+ if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
+ return -EINVAL;
+
+ return 0;
+}
+
static int nl80211_parse_random_mac(struct nlattr **attrs,
u8 *mac_addr, u8 *mac_addr_mask)
{
@@ -6557,6 +6657,12 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
return ERR_PTR(-EINVAL);
+ if (!wiphy_ext_feature_isset(
+ wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
+ (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
+ return ERR_PTR(-EINVAL);
+
request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->match_sets) * n_match_sets
@@ -6762,6 +6868,26 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
request->delay =
nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
+ if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
+ request->relative_rssi = nla_get_s8(
+ attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
+ request->relative_rssi_set = true;
+ }
+
+ if (request->relative_rssi_set &&
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
+ struct nl80211_bss_select_rssi_adjust *rssi_adjust;
+
+ rssi_adjust = nla_data(
+ attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
+ request->rssi_adjust.band = rssi_adjust->band;
+ request->rssi_adjust.delta = rssi_adjust->delta;
+ if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
+ err = -EINVAL;
+ goto out_free;
+ }
+ }
+
err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
if (err)
goto out_free;
@@ -8349,6 +8475,21 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
}
+ if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
+ /* bss selection makes no sense if bssid is set */
+ if (connect.bssid) {
+ kzfree(connkeys);
+ return -EINVAL;
+ }
+
+ err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
+ wiphy, &connect.bss_select);
+ if (err) {
+ kzfree(connkeys);
+ return err;
+ }
+ }
+
wdev_lock(dev->ieee80211_ptr);
err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
@@ -9245,6 +9386,20 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
return -ENOBUFS;
+ if (req->relative_rssi_set) {
+ struct nl80211_bss_select_rssi_adjust rssi_adjust;
+
+ if (nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
+ req->relative_rssi))
+ return -ENOBUFS;
+
+ rssi_adjust.band = req->rssi_adjust.band;
+ rssi_adjust.delta = req->rssi_adjust.delta;
+ if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
+ sizeof(rssi_adjust), &rssi_adjust))
+ return -ENOBUFS;
+ }
+
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
if (!freqs)
return -ENOBUFS;
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index 58eb30c39764..5dc5bf9d1b3c 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -2864,10 +2864,12 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
ret = -EPROBE_DEFER;
goto err;
}
- ret = msm_init_wsa_dev(pdev, card);
- if (ret)
- goto err;
+ if (!of_property_read_bool(pdev->dev.of_node, "qcom,wsa-disable")) {
+ ret = msm_init_wsa_dev(pdev, card);
+ if (ret)
+ goto err;
+ }
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret == -EPROBE_DEFER) {
diff --git a/sound/soc/msm/sdm660-external.c b/sound/soc/msm/sdm660-external.c
index 0460d7f9fc68..3fe327ad0442 100644
--- a/sound/soc/msm/sdm660-external.c
+++ b/sound/soc/msm/sdm660-external.c
@@ -48,8 +48,8 @@
#define TLMM_LPI_GPIO22_CFG 0x15078040
#define LPI_GPIO22_CFG_VAL 0x0000009
-#define TLMM_LPI_GPIO22_INOUT 0x15078044
-#define LPI_GPIO22_INOUT_VAL 0x00000000
+#define TLMM_LPI_GPIO22_INOUT 0x179D1318
+#define LPI_GPIO22_INOUT_VAL 0x0020000
#define WSA8810_NAME_1 "wsa881x.20170211"
#define WSA8810_NAME_2 "wsa881x.20170212"
@@ -1227,8 +1227,9 @@ static void msm_snd_interrupt_config(struct msm_asoc_mach_data *pdata)
pdata->msm_snd_intr_lpi.lpi_gpio_intr_cfg);
iowrite32(LPI_GPIO22_CFG_VAL,
pdata->msm_snd_intr_lpi.lpi_gpio_cfg);
- iowrite32(LPI_GPIO22_INOUT_VAL,
- pdata->msm_snd_intr_lpi.lpi_gpio_inout);
+ val = ioread32(pdata->msm_snd_intr_lpi.lpi_gpio_inout);
+ val |= LPI_GPIO22_INOUT_VAL;
+ iowrite32(val, pdata->msm_snd_intr_lpi.lpi_gpio_inout);
}
static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
@@ -1511,6 +1512,17 @@ int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
134, 135, 136, 137, 138, 139,
140, 141, 142, 143};
+ /* Tavil Codec SLIMBUS configuration
+ * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8
+ * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+ * TX14, TX15, TX16
+ */
+ unsigned int rx_ch_tavil[WCD934X_RX_MAX] = {144, 145, 146, 147, 148,
+ 149, 150, 151};
+ unsigned int tx_ch_tavil[WCD934X_TX_MAX] = {128, 129, 130, 131, 132,
+ 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143};
+
pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
rtd->pmdown_time = 0;
@@ -1571,14 +1583,11 @@ int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_ignore_suspend(dapm, "EAR");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
- snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
- snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
- snd_soc_dapm_ignore_suspend(dapm, "AMIC6");
snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
@@ -1586,21 +1595,33 @@ int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
- snd_soc_dapm_ignore_suspend(dapm, "ANC HEADPHONE");
snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
snd_soc_dapm_ignore_suspend(dapm, "HPHL");
snd_soc_dapm_ignore_suspend(dapm, "HPHR");
- snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
- snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
- snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
- snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
+ if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
+ }
+
snd_soc_dapm_sync(dapm);
- snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
- tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+
+ if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
+ snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch_tavil),
+ tx_ch_tavil, ARRAY_SIZE(rx_ch_tavil),
+ rx_ch_tavil);
+ } else {
+ snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch),
+ rx_ch);
+ }
if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c
index c002399beb6b..805ff2335b42 100644
--- a/sound/soc/msm/sdm660-internal.c
+++ b/sound/soc/msm/sdm660-internal.c
@@ -2227,21 +2227,6 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.codec_name = "snd-soc-dummy",
},
{/* hw:x,35 */
- .name = LPASS_BE_INT5_MI2S_TX,
- .stream_name = "INT5 MI2S Capture",
- .cpu_dai_name = "msm-dai-q6-mi2s.12",
- .platform_name = "msm-pcm-hostless",
- .codec_name = "msm_sdw_codec",
- .codec_dai_name = "msm_sdw_vifeedback",
- .be_id = MSM_BACKEND_DAI_INT5_MI2S_TX,
- .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
- .ops = &msm_sdw_mi2s_be_ops,
- .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
- .ignore_suspend = 1,
- .dpcm_capture = 1,
- .ignore_pmdown_time = 1,
- },
- {/* hw:x,36 */
.name = "Primary MI2S_RX Hostless",
.stream_name = "Primary MI2S_RX Hostless",
.cpu_dai_name = "PRI_MI2S_RX_HOSTLESS",
@@ -2258,7 +2243,7 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- {/* hw:x,37 */
+ {/* hw:x,36 */
.name = "Secondary MI2S_RX Hostless",
.stream_name = "Secondary MI2S_RX Hostless",
.cpu_dai_name = "SEC_MI2S_RX_HOSTLESS",
@@ -2275,7 +2260,7 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- {/* hw:x,38 */
+ {/* hw:x,37 */
.name = "Tertiary MI2S_RX Hostless",
.stream_name = "Tertiary MI2S_RX Hostless",
.cpu_dai_name = "TERT_MI2S_RX_HOSTLESS",
@@ -2292,7 +2277,7 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- {/* hw:x,39 */
+ {/* hw:x,38 */
.name = "INT0 MI2S_RX Hostless",
.stream_name = "INT0 MI2S_RX Hostless",
.cpu_dai_name = "INT0_MI2S_RX_HOSTLESS",
@@ -2309,6 +2294,28 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+};
+
+
+static struct snd_soc_dai_link msm_int_wsa_dai[] = {
+ {/* hw:x,39 */
+ .name = LPASS_BE_INT5_MI2S_TX,
+ .stream_name = "INT5_mi2s Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.12",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "msm_sdw_codec",
+ .codec_dai_name = "msm_sdw_vifeedback",
+ .be_id = MSM_BACKEND_DAI_INT5_MI2S_TX,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_sdw_mi2s_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .ignore_pmdown_time = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_int_be_dai[] = {
/* Backend I2S DAI Links */
{
.name = LPASS_BE_INT0_MI2S_RX,
@@ -2344,21 +2351,6 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.ignore_suspend = 1,
},
{
- .name = LPASS_BE_INT4_MI2S_RX,
- .stream_name = "INT4 MI2S Playback",
- .cpu_dai_name = "msm-dai-q6-mi2s.11",
- .platform_name = "msm-pcm-routing",
- .codec_name = "msm_sdw_codec",
- .codec_dai_name = "msm_sdw_i2s_rx1",
- .no_pcm = 1,
- .dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_INT4_MI2S_RX,
- .init = &msm_sdw_audrx_init,
- .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
- .ops = &msm_sdw_mi2s_be_ops,
- .ignore_suspend = 1,
- },
- {
.name = LPASS_BE_INT2_MI2S_TX,
.stream_name = "INT2 MI2S Capture",
.cpu_dai_name = "msm-dai-q6-mi2s.9",
@@ -2898,11 +2890,32 @@ static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
},
};
+static struct snd_soc_dai_link msm_wsa_be_dai_links[] = {
+ {
+ .name = LPASS_BE_INT4_MI2S_RX,
+ .stream_name = "INT4 MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.11",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm_sdw_codec",
+ .codec_dai_name = "msm_sdw_i2s_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_INT4_MI2S_RX,
+ .init = &msm_sdw_audrx_init,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_sdw_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+};
+
static struct snd_soc_dai_link msm_int_dai_links[
ARRAY_SIZE(msm_int_dai) +
+ARRAY_SIZE(msm_int_wsa_dai) +
+ARRAY_SIZE(msm_int_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links)+
-ARRAY_SIZE(msm_wcn_be_dai_links)];
+ARRAY_SIZE(msm_wcn_be_dai_links) +
+ARRAY_SIZE(msm_wsa_be_dai_links)];
static struct snd_soc_card sdm660_card = {
/* snd_soc_card_sdm660 */
@@ -2965,6 +2978,16 @@ static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
len1 = ARRAY_SIZE(msm_int_dai);
memcpy(msm_int_dai_links, msm_int_dai, sizeof(msm_int_dai));
dailink = msm_int_dai_links;
+ if (!of_property_read_bool(dev->of_node,
+ "qcom,wsa-disable")) {
+ memcpy(dailink + len1,
+ msm_int_wsa_dai,
+ sizeof(msm_int_wsa_dai));
+ len1 += ARRAY_SIZE(msm_int_wsa_dai);
+ }
+ memcpy(dailink + len1, msm_int_be_dai, sizeof(msm_int_be_dai));
+ len1 += ARRAY_SIZE(msm_int_be_dai);
+
if (of_property_read_bool(dev->of_node,
"qcom,mi2s-audio-intf")) {
memcpy(dailink + len1,
@@ -2987,6 +3010,12 @@ static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
sizeof(msm_wcn_be_dai_links));
len1 += ARRAY_SIZE(msm_wcn_be_dai_links);
}
+ if (!of_property_read_bool(dev->of_node, "qcom,wsa-disable")) {
+ memcpy(dailink + len1,
+ msm_wsa_be_dai_links,
+ sizeof(msm_wsa_be_dai_links));
+ len1 += ARRAY_SIZE(msm_wsa_be_dai_links);
+ }
card->dai_link = dailink;
card->num_links = len1;
return card;