Merge "mm: vmalloc: don't print lowmem information"
diff --git a/Documentation/devicetree/bindings/input/qti-haptics.txt b/Documentation/devicetree/bindings/input/qti-haptics.txt
new file mode 100644
index 0000000..2c4f4f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qti-haptics.txt
@@ -0,0 +1,202 @@
+Qualcomm Technologies, Inc. Haptics driver
+
+Haptics peripheral in QTI PMICs can support different type of actuators or
+vibrators:
+ 1) Eccentric Rotation Mass (ERM);
+ 2) Linear Resonant Actuator (LRA).
+This binding document describes the properties for this module.
+
+Properties:
+
+- compatible
+ Usage: required
+ Value type: <string>
+ Definition: It can be one of the following:
+ "qcom,haptics",
+ "qcom,pm660-haptics",
+ "qcom,pm8150b-haptics".
+
+- reg
+ Usage: required
+ Value type: <u32>
+ Definition: Base address of haptics peripheral.
+
+- interrupts
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+ Usage: required
+ Value type: <stringlist>
+ Definition: Interrupt names. This list must match up 1-to-1 with the
+ interrupts specified in the 'interrupts' property. Following
+ interrupts are required: "hap_play_irq", "hap_sc_irq".
+
+- qcom,actuator-type
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the type of the actuator connected on the output of
+ haptics module. Allowed values: "erm", "lra". If this is
+ not specified, then LRA type will be used by default.
+
+- qcom,vmax-mv
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the maximum allowed output voltage in millivolts
+ for the actuator. Value specified here will be rounded
+ off to the closest multiple of 116 mV. Allowed values:
+ 0 to 3596. If this is not specified, then 1800 mV will be
+ used by default.
+
+- qcom,ilim-ma
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the maximum allowed output current in mA for the
+ actuator. Allowed values: 400 or 800. If this is not
+ specified, 400 mA will be used by default.
+
+- qcom,play-rate-us
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the period at which each sample of the 8-byte waveform
+ registers is played. For ERM, this period is flexible and it
+ can be chosen based on the desired shape of the pattern.
+ For LRA, it should be set equal to the resonance period
+ specified in the LRA actuator datasheet. Allowed values are:
+ 0 to 20475. If this is not specified, 5715us play rate is used.
+
+- qcom,external-waveform-source
+ Usage: optional
+ Value type: <string>
+ Definition: The haptics module supports to play with internal constant
+ Vmax strength or play with patterns specified in its internal
+ 8-bytes waveform buffer. It can also play with the audio
+ LINE-IN signal or PWM waveform coming from LINE-IN/PWM pin.
+ This property specify the kind of the waveform resources
+ on the LINE-IN/PWM pins. Allowed values are: "audio", "pwm".
+ If this is not specified, internal signals (Vmax or buffer)
+ will be selected according to the requriement of the playing
+ waveforms.
+
+- vdd-supply
+ Usage: optional
+ Value type: <phandle>
+ Definition: Specifies the phandle of the regulator device which supplies
+ haptics module through VDD_HAP pin. This is only needed if VDD_HAP
+ is supplied from an external boost regulator instead of VPH_PWR.
+
+Following properties are specific only when LRA actuator is used:
+
+- qcom,lra-resonance-sig-shape
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the shape of the LRA resonance drive signal. Allowed
+ values: "sine", "square". If this is not specified, sinusoid
+ resonance driver signal is used.
+
+- qcom,lra-allow-variable-play-rate
+ Usage: optional
+ Value type: <empty>
+ Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each
+ effect could be different with the resonance period of the
+ LRA actuator.
+
+- qcom,lra-auto-resonance-mode
+ Usage: optional
+ Value type: <string>
+ Definition: Specifies the auto resonance technique for LRA. Allowed values are:
+ "zxd": zero crossing based discontinuous method;
+ "qwd": quarter wave drive method;
+
+Following properties could be specified in child nodes for defining vibrating
+waveforms/effects:
+
+- qcom,effect-id
+ Usage: required
+ Value type: <u32>
+ Definition: Specifies the effect ID that the client can request to play the
+ corresponding waveform defined in this child node. The ID is
+ normaly defined and sent from userspace for certain user
+ notification event.
+
+- qcom,wf-pattern
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Specifies the waveform pattern in a byte array that will be
+ played for the effect-id. The bit fields of each byte are:
+ [7]: drive direction, 0 - forward; 1 - reverse
+ [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive
+ [5:1]: waveform amplitude
+ [0]: reserved.
+
+- qcom,wf-play-rate-us
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the play period in microseconds for each byte pattern.
+ Allowed values are: 0 to 20475. For LRA actuator, if
+ "qcom,lra-allow-variable-play-rate" is defined, it could be
+ set to other values not equal to the resonance period of the
+ LRA actuator.
+
+- qcom,wf-repeat-count
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the repeat times for the waveform pattern. Allowed
+ values are: 1, 2, 4, 8, 16, 32, 64, 128.
+
+- qcom,wf-s-repeat-count
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the repeat times for each sample defined in
+ qcom,wf-pattern. Allowed values are: 1, 2, 4, 8.
+
+- qcom,wf-brake-pattern
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Specifies the brake pattern with 4 elements used to enable the
+ internal reverse braking. Allowed values for each element are:
+ 0: no brake
+ 1: brake with (Vmax / 2) strength
+ 2: brake with Vmax strength
+ 3: brake with (2 * Vmax) strength
+ If this property is specified with an array of non-zero values,
+ then the brake pattern is applied at the end of the playing
+ waveform.
+
+- qcom,lra-auto-resonance-disable
+ Usage: optional
+ Value type: <empty>
+ Definition: If specified, the hardware feature of LRA auto resonance detection
+ is disabled.
+
+Example:
+ qcom,haptics@c000 {
+ compatible = "qcom,haptics";
+ reg = <0xc000 0x100>;
+ interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+ <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "hap-sc-irq", "hap-play-irq";
+ qcom,actuator-type = "lra";
+ qcom,vmax-mv = <1800>;
+ qcom,ilim-ma = <400>;
+ qcom,play-rate-us = <8000>;
+ qcom,lra-resonance-sig-shape = "sine";
+ qcom,lra-auto-resonance-mode = "qwd";
+ qcom,lra-allow-variable-play-rate;
+
+ wf_0 {
+ /* CLICK effect */
+ qcom,effect-id = <0>;
+ qcom,wf-play-rate-us = <6250>;
+ qcom,wf-pattern = [3e 3e 3e];
+ qcom,lra-auto-resonance-disable;
+ };
+
+ wf_5 {
+ /* HEAVY_CLICK effect */
+ qcom,effect-id = <5>;
+ qcom,wf-play-rate-us = <6250>;
+ qcom,wf-pattern = [7e 7e 7e];
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index 54ff110..c8fa87c 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -24,11 +24,11 @@
128, 192. Unit is uS.
- qcom,short-circuit-det : Boolean property which enables short circuit fault detection.
- qcom,open-circuit-det : Boolean property which enables open circuit fault detection.
-- qcom,vph-droop-det : Boolean property which enables VPH droop detection.
-- qcom,vph-droop-hys-mv : Integer property to specify VPH droop hysteresis. It is only used if
- qcom,vph-droop-det is specified. Valid values are 0, 25, 50 and 75.
- Unit is mV.
-- qcom,vph-droop-thresh-mv : Integer property to specify VPH droop threshold. It is only used if
+- qcom,vph-droop-det : Boolean property which enables VPH droop detection.
+- qcom,vph-droop-hysteresis-mv : Integer property to specify VPH droop hysteresis. It is only used if
+ qcom,vph-droop-det is specified. Valid values are 0, 25, 50 and 75.
+ Unit is mV.
+- qcom,vph-droop-threshold-mv : Integer property to specify VPH droop threshold. It is only used if
qcom,vph-droop-det is specified. Valid values are
2500 to 3200 with step size of 100. Unit is mV.
- qcom,vph-droop-debounce-us : Integer property to specify VPH droop debounce time. It is only used
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 1670708..ddcb90c 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -306,6 +306,7 @@
devm_request_any_context_irq()
devm_request_irq()
devm_request_threaded_irq()
+ devm_irq_sim_init()
LED
devm_led_classdev_register()
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 824eefa..b5734c5 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -11,7 +11,9 @@
sdxpoorwills-pcie-ep-cdp-256.dtb \
sdxpoorwills-pcie-ep-mtp-256.dtb \
sdxpoorwills-pcie-ep-cdp.dtb \
- sdxpoorwills-pcie-ep-mtp.dtb
+ sdxpoorwills-pcie-ep-mtp.dtb \
+ sdxpoorwills-v2-mtp.dtb \
+ sdxpoorwills-v2-cdp.dtb
dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-nand-mtp.dtb \
mdm9650-ttp.dtb \
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 642a541..0d36f2a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -33,6 +33,7 @@
qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
qcom,num-gsi-evt-buffs = <0x3>;
qcom,use-pdc-interrupts;
+ qcom,pm-qos-latency = <2 241 271>;
clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
<&clock_gcc GCC_SYS_NOC_USB3_CLK>,
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts
new file mode 100644
index 0000000..4ac0117
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts
@@ -0,0 +1,29 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-cdp.dtsi"
+#include "sdxpoorwills-v2.dtsi"
+#include "sdxpoorwills-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS CDP V2";
+ compatible = "qcom,sdxpoorwills-cdp",
+ "qcom,sdxpoorwills", "qcom,cdp";
+ qcom,board-id = <1 0x102>;
+};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts
new file mode 100644
index 0000000..29f77de
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts
@@ -0,0 +1,31 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-mtp.dtsi"
+#include "sdxpoorwills-v2.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS MTP V2";
+ compatible = "qcom,sdxpoorwills-mtp",
+ "qcom,sdxpoorwills", "qcom,mtp";
+ qcom,board-id = <8 0x102>;
+};
+
+&qcom_seecom {
+ status = "okay";
+};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
new file mode 100644
index 0000000..eef2ffb
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS V2";
+ compatible = "qcom,sdxpoorwills";
+ qcom,msm-id = <334 0x20000>, <335 0x20000>;
+};
+
+&emac_hw {
+ emac-core-version = <5>;
+};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index b4ae846..3d30af6 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -300,6 +300,7 @@
CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -424,6 +425,7 @@
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_EVENT_TIMER=y
+CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_WCNSS_CORE=y
@@ -437,6 +439,7 @@
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_STM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 4d1bda0..787b38e 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -479,6 +479,7 @@
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 0e56f7f..4ee0854 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -80,6 +80,7 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
@@ -91,6 +92,7 @@
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_NETFILTER=y
@@ -122,6 +124,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -468,6 +471,7 @@
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
CONFIG_PAGE_EXTENSION=y
CONFIG_PANIC_ON_RECURSIVE_FAULT=y
CONFIG_WQ_WATCHDOG=y
@@ -486,6 +490,7 @@
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8351322..848c256 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -81,6 +81,7 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
@@ -92,6 +93,7 @@
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
CONFIG_NETFILTER=y
@@ -124,6 +126,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -343,6 +346,8 @@
CONFIG_USB_CONFIGFS_RMNET_BAM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
CONFIG_USB_CONFIGFS_UEVENT=y
@@ -463,6 +468,7 @@
CONFIG_FRAME_WARN=2048
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
@@ -513,7 +519,7 @@
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index e9a5237..26d0d06 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -41,6 +41,7 @@
CONFIG_BPF_SYSCALL=y
# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
CONFIG_CC_STACKPROTECTOR_STRONG=y
diff --git a/arch/arm/configs/sdm670-perf_defconfig b/arch/arm/configs/sdm670-perf_defconfig
new file mode 100644
index 0000000..2f003b9
--- /dev/null
+++ b/arch/arm/configs/sdm670-perf_defconfig
@@ -0,0 +1,567 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDM670=y
+CONFIG_PCI_MSM=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_ARM_PSCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
+CONFIG_CMA=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_AQT_REGMAP=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_SDM670=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB2=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP_OLEDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_LT_LT9611=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_GPI_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
+CONFIG_CLOCK_QPNP_DIV=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_QMP=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_QBT1000=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_MSM_REMOTEQDSS=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PAGE_EXTENSION=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig
index 949b279..702f622 100644
--- a/arch/arm/configs/sdm670_defconfig
+++ b/arch/arm/configs/sdm670_defconfig
@@ -352,9 +352,12 @@
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
@@ -517,7 +520,6 @@
CONFIG_QCOM_SMCINVOKE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_QBT1000=y
-CONFIG_QCOM_DCC_V2=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_QMP_DEBUGFS_CLIENT=y
@@ -533,6 +535,7 @@
CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_TZ_LOG=y
CONFIG_EXT2_FS=y
@@ -552,6 +555,7 @@
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index e1fed15..cdbfebd 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -366,6 +366,8 @@
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 54072cc..b3fef2f 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -371,6 +371,8 @@
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 7ca9180..6b43733 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -107,8 +107,8 @@
select PM_OPP
select MSM_DEVFREQ_DEVBW
select DEVFREQ_SIMPLE_DEV
- select DEVFREQ_GOV_MSM_BW_HWMON
- select MSM_BIMC_BWMON
+ select DEVFREQ_GOV_QCOM_BW_HWMON
+ select QCOM_BIMC_BWMON
select CLKDEV_LOOKUP
select HAVE_CLK
select HAVE_CLK_PREPARE
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index a8f8d46..e5a8a57 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1965,6 +1965,8 @@
total_length += s->length;
iova = __alloc_iova(mapping, total_length);
+ if (iova == DMA_ERROR_CODE)
+ return 0;
ret = iommu_map_sg(mapping->domain, iova, sg, nents, prot);
if (ret != total_length) {
__free_iova(mapping, iova, total_length);
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
index c8330bd..4f9c9f7 100644
--- a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -521,6 +521,13 @@
&pm660_fg {
qcom,battery-data = <&mtp_batterydata>;
+ qcom,fg-rsense-sel = <1>; /* External rsense */
+ qcom,fg-cutoff-voltage = <3400>;
+ qcom,fg-recharge-voltage = <4100>;
+ qcom,fg-use-sw-esr;
+ qcom,fg-esr-pulse-thresh-ma = <40>;
+ qcom,fg-esr-meas-curr-ma = <60>;
+ qcom,fg-cutoff-current = <50>;
};
&pm660_pdphy {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 15f53ee..ef0ac4d 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -223,7 +223,7 @@
qcs605-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
-qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc.dtb
+qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc-ipcamera-base.dtb
qcs605-360camera-overlay.dtbo-base := qcs605.dtb
qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
sdm710-cdp-overlay.dtbo-base := sdm710.dtb
@@ -499,8 +499,11 @@
apq8053-lite-dragon-v2.0.dtb \
apq8053-lite-dragon-v2.1.dtb \
apq8053-lite-dragon-v2.2.dtb \
+ apq8053-lite-dragon-v2.2.1.dtb \
apq8053-lite-dragon-v2.3.dtb \
apq8053-lite-dragon-v2.4.dtb \
+ apq8053-lat-concam-dev.dtb \
+ apq8053-lat-concam-proto.dtb \
msm8953-pmi8940-cdp.dtb \
msm8953-pmi8940-mtp.dtb \
msm8953-pmi8937-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
index 0ac8a31..4a625f8 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
@@ -15,7 +15,6 @@
#include "msm8909-mtp.dtsi"
#include "8909-pm8916.dtsi"
#include "msm8909-pm8916-mtp.dtsi"
-#include "apq8009-audio-external_codec.dtsi"
#include "apq8009-memory.dtsi"
#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
#include "msm8909-pm8916-camera.dtsi"
@@ -29,7 +28,46 @@
};
&audio_codec_mtp {
- status = "disabled";
+ qcom,model = "msm8909-pm8916-snd-card";
+ asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+ <&pmic_analog_codec>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+ "analog-codec";
+
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&lpa>,
+ <&voice_svc>,<&pcm_noirq>;
+
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-pcm-lpa",
+ "msm-voice-svc", "msm-pcm-dsp-noirq";
+
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+ <&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
+ <&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+ <&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+ <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>;
+
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+ "msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+ "msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+ "msm-dai-q6-dev.32770";
};
&pm8916_gpios {
@@ -94,40 +132,79 @@
};
};
+&spmi_bus {
+ pm8916@1 {
+ pmic_analog_codec: analog-codec@f000 {
+ status = "okay";
+ compatible = "qcom,pmic-analog-codec";
+ reg = <0xf000 0x200>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int",
+ "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+
+ cdc-vdda-cp-supply = <&pm8916_s4>;
+ qcom,cdc-vdda-cp-voltage = <1800000 2100000>;
+ qcom,cdc-vdda-cp-current = <1800000>;
+
+ cdc-vdd-io-supply = <&pm8916_l5>;
+ qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-io-current = <5000>;
+
+ cdc-vdd-pa-supply = <&pm8916_s4>;
+ qcom,cdc-vdd-pa-voltage = <1800000 2100000>;
+ qcom,cdc-vdd-pa-current = <1800000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <5000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-io",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+ msm_digital_codec: msm-dig-codec {
+ compatible = "qcom,msm-digital-codec";
+ reg = <0x0771c000 0x0>;
+ };
+ };
+ };
+};
+
&soc {
ext_codec: sound-9335 {
- qcom,audio-routing =
- "AIF4 VI", "MCLK",
- "RX_BIAS", "MCLK",
- "MADINPUT", "MCLK",
- "AMIC2", "MIC BIAS2",
- "MIC BIAS2", "Headset Mic",
- "DMIC0", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic0",
- "DMIC1", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic1",
- "DMIC2", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic2",
- "DMIC3", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic3",
- "SpkrLeft IN", "SPK1 OUT",
- "SpkrRight IN", "SPK2 OUT";
-
- qcom,msm-gpios =
- "us_eu_gpio";
- qcom,pinctrl-names =
- "all_off",
- "us_eu_gpio_act";
- pinctrl-names =
- "all_off",
- "us_eu_gpio_act";
- pinctrl-0 = <&cross_conn_det_sus>;
- pinctrl-1 = <&cross_conn_det_act>;
- qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
- qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
-
- qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
- "SpkrLeft", "SpkrRight";
+ status = "disabled";
};
i2c@78b9000 {
@@ -176,6 +253,7 @@
};
cnss_sdio: qcom,cnss_sdio {
+ status = "disabled";
compatible = "qcom,cnss_sdio";
subsys-name = "AR6320";
/**
@@ -210,37 +288,16 @@
i2c@78b8000 {
wcd9xxx_codec@d {
- status = "okay";
- qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+ status = "disabled";
};
};
cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
compatible = "qcom,msm-cdc-pinctrl";
pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
- &pri_mi2s_dout_active &pri_mi2s_din_active>;
- pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
- &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+ pinctrl-0 = <&cdc_pdm_lines_act>;
+ pinctrl-1 = <&cdc_pdm_lines_sus>;
};
-
- cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
- pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
- };
-
- wcd_rst_gpio: wcd_gpio_ctrl {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&cdc_reset_active>;
- pinctrl-1 = <&cdc_reset_sleep>;
- };
-};
-
-&wcnss {
- status = "disabled";
};
&msm_gpio {
@@ -298,7 +355,7 @@
&sdc2_wlan_gpio_off>;
qcom,nonremovable;
qcom,core_3_0v_support;
- status = "ok";
+ status = "disabled";
};
&i2c_4 {
@@ -365,14 +422,6 @@
status = "disabled";
};
-&wcd_rst_gpio {
- status = "okay";
-};
-
-&ext_codec {
- status = "okay";
-};
-
&blsp1_uart2_hs {
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
index 4677448..0938d86 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
@@ -15,7 +15,6 @@
#include "msm8909-mtp.dtsi"
#include "8909-pm8916.dtsi"
#include "msm8909-pm8916-mtp.dtsi"
-#include "apq8009-audio-external_codec.dtsi"
#include "apq8009-memory.dtsi"
#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
#include "msm8909-pm8916-camera.dtsi"
@@ -29,7 +28,43 @@
};
&audio_codec_mtp {
- status = "disabled";
+ qcom,model = "msm8909-pm8916-snd-card";
+ asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+ <&pmic_analog_codec>;
+ asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+ "analog-codec";
+
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&lpa>,
+ <&voice_svc>,<&pcm_noirq>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-pcm-lpa",
+ "msm-voice-svc","msm-pcm-dsp-noirq";
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+ <&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
+ <&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+ <&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+ <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>;
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+ "msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+ "msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+ "msm-dai-q6-dev.32770";
};
&pm8916_gpios {
@@ -93,41 +128,79 @@
};
};
};
+&spmi_bus {
+ pm8916@1 {
+ pmic_analog_codec: analog-codec@f000 {
+ status = "okay";
+ compatible = "qcom,pmic-analog-codec";
+ reg = <0xf000 0x200>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+ <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+ <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int",
+ "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+
+ cdc-vdda-cp-supply = <&pm8916_s4>;
+ qcom,cdc-vdda-cp-voltage = <1800000 2100000>;
+ qcom,cdc-vdda-cp-current = <1800000>;
+
+ cdc-vdd-io-supply = <&pm8916_l5>;
+ qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-io-current = <5000>;
+
+ cdc-vdd-pa-supply = <&pm8916_s4>;
+ qcom,cdc-vdd-pa-voltage = <1800000 2100000>;
+ qcom,cdc-vdd-pa-current = <1800000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <5000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-io",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+ msm_digital_codec: msm-dig-codec {
+ compatible = "qcom,msm-digital-codec";
+ reg = <0x0771c000 0x0>;
+ };
+ };
+ };
+};
&soc {
ext_codec: sound-9335 {
- qcom,audio-routing =
- "AIF4 VI", "MCLK",
- "RX_BIAS", "MCLK",
- "MADINPUT", "MCLK",
- "AMIC2", "MIC BIAS2",
- "MIC BIAS2", "Headset Mic",
- "DMIC0", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic0",
- "DMIC1", "MIC BIAS1",
- "MIC BIAS1", "Digital Mic1",
- "DMIC2", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic2",
- "DMIC3", "MIC BIAS3",
- "MIC BIAS3", "Digital Mic3",
- "SpkrLeft IN", "SPK1 OUT",
- "SpkrRight IN", "SPK2 OUT";
-
- qcom,msm-gpios =
- "us_eu_gpio";
- qcom,pinctrl-names =
- "all_off",
- "us_eu_gpio_act";
- pinctrl-names =
- "all_off",
- "us_eu_gpio_act";
- pinctrl-0 = <&cross_conn_det_sus>;
- pinctrl-1 = <&cross_conn_det_act>;
- qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
- qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
-
- qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
- "SpkrLeft", "SpkrRight";
+ status = "disabled";
};
i2c@78b9000 {
@@ -210,32 +283,15 @@
i2c@78b8000 {
wcd9xxx_codec@d {
- status = "okay";
- qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+ status = "disabled";
};
};
cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
compatible = "qcom,msm-cdc-pinctrl";
pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
- &pri_mi2s_dout_active &pri_mi2s_din_active>;
- pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
- &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
- };
-
- cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
- pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
- };
-
- wcd_rst_gpio: wcd_gpio_ctrl {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&cdc_reset_active>;
- pinctrl-1 = <&cdc_reset_sleep>;
+ pinctrl-0 = <&cdc_pdm_lines_act>;
+ pinctrl-1 = <&cdc_pdm_lines_sus>;
};
};
@@ -365,16 +421,8 @@
status = "disabled";
};
-&wcd_rst_gpio {
- status = "okay";
-};
-
-&ext_codec {
- status = "okay";
-};
-
&blsp1_uart2_hs {
- status = "okay";
+ status= "okay";
};
/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index ab711dd..8efa0c5 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -256,6 +256,7 @@
compatible = "st,stmvl53l0";
reg = <0x29>;
status = "ok";
+ tof-id = <2>;
};
};
@@ -354,12 +355,12 @@
status = "ok";
};
-&i2c_1 {
- status = "okay";
+&i2c_3 {
vl53l0x@52 {
compatible = "st,stmvl53l0";
reg = <0x29>;
status = "ok";
+ tof-id = <1>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
new file mode 100644
index 0000000..b0fee57
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
@@ -0,0 +1,645 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/* picked up from base file msm8953-audio.dtsi, enables internal codec config */
+
+&soc {
+ &i2c_2 {
+ status = "okay";
+ wsa881x_i2c_f: wsa881x-i2c-codec@f {
+ status = "okay";
+
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x0f>;
+ qcom,msm-gpios = "wsa_clk",
+ "wsa_reset",
+ "wsa_vi";
+ qcom,pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+ pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+ pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+ pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+ pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+ pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+ pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+ pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+ };
+
+ wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+ status = "okay";
+
+ compatible = "qcom,wsa881x-i2c-codec";
+ reg = <0x45>;
+ qcom,msm-gpios = "wsa_clk",
+ "wsa_reset",
+ "wsa_vi";
+ qcom,pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-names = "all_off",
+ "wsa_clk",
+ "wsa_active",
+ "wsa_clk_active",
+ "wsa_vi",
+ "wsa_clk_vi",
+ "wsa_active_vi",
+ "wsa_all";
+ pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+ pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+ pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+ pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+ pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+ pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+ pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+ pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+ };
+ };
+
+ pcm0: qcom,msm-pcm {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
+ };
+
+ routing: qcom,msm-pcm-routing {
+ compatible = "qcom,msm-pcm-routing";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ pcm1: qcom,msm-pcm-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <1>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "regular";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ cpe: qcom,msm-cpe-lsm {
+ compatible = "qcom,msm-cpe-lsm";
+ };
+
+ lpa: qcom,msm-pcm-lpa {
+ compatible = "qcom,msm-pcm-lpa";
+ };
+
+ compress: qcom,msm-compress-dsp {
+ compatible = "qcom,msm-compress-dsp";
+ };
+
+ voip: qcom,msm-voip-dsp {
+ compatible = "qcom,msm-voip-dsp";
+ };
+
+ voice: qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ qcom,destroy-cvd;
+ };
+
+ stub_codec: qcom,msm-stub-codec {
+ compatible = "qcom,msm-stub-codec";
+ };
+
+ qcom,msm-dai-fe {
+ compatible = "qcom,msm-dai-fe";
+ };
+
+ afe: qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
+ loopback: qcom,msm-pcm-loopback {
+ compatible = "qcom,msm-pcm-loopback";
+ };
+
+ qcom,msm-dai-mi2s {
+ compatible = "qcom,msm-dai-mi2s";
+ dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <0>;
+ qcom,msm-mi2s-rx-lines = <3>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s1: qcom,msm-dai-q6-mi2s-sec {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <1>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <3>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <2>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+
+ dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <5>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <6>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+ };
+
+ lsm: qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
+ qcom,msm-dai-q6 {
+ compatible = "qcom,msm-dai-q6";
+ sb_0_rx: qcom,msm-dai-q6-sb-0-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16384>;
+ };
+
+ sb_0_tx: qcom,msm-dai-q6-sb-0-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16385>;
+ };
+
+ sb_1_rx: qcom,msm-dai-q6-sb-1-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16386>;
+ };
+
+ sb_1_tx: qcom,msm-dai-q6-sb-1-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16387>;
+ };
+
+ sb_2_rx: qcom,msm-dai-q6-sb-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16388>;
+ };
+
+ sb_2_tx: qcom,msm-dai-q6-sb-2-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16389>;
+ };
+
+
+ sb_3_rx: qcom,msm-dai-q6-sb-3-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16390>;
+ };
+
+ sb_3_tx: qcom,msm-dai-q6-sb-3-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16391>;
+ };
+
+ sb_4_rx: qcom,msm-dai-q6-sb-4-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16392>;
+ };
+
+ sb_4_tx: qcom,msm-dai-q6-sb-4-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16393>;
+ };
+
+ sb_5_tx: qcom,msm-dai-q6-sb-5-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16395>;
+ };
+
+ sb_5_rx: qcom,msm-dai-q6-sb-5-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16394>;
+ };
+
+ bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12288>;
+ };
+
+ bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12289>;
+ };
+
+ int_fm_rx: qcom,msm-dai-q6-int-fm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12292>;
+ };
+
+ int_fm_tx: qcom,msm-dai-q6-int-fm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12293>;
+ };
+
+ afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
+
+ incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
+
+ incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32770>;
+ };
+
+ sb_6_rx: qcom,msm-dai-q6-sb-6-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16396>;
+ };
+ };
+
+ hostless: qcom,msm-pcm-hostless {
+ compatible = "qcom,msm-pcm-hostless";
+ };
+
+ dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "primary";
+ };
+
+ hdmi_dba: qcom,msm-hdmi-dba-codec-rx {
+ compatible = "qcom,msm-hdmi-dba-codec-rx";
+ qcom,dba-bridge-chip = "adv7533";
+ };
+
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,smmu-version = <1>;
+ qcom,smmu-enabled;
+ iommus = <&adsp_io 1>;
+ };
+
+ qcom,msm-adsp-loader {
+ compatible = "qcom,adsp-loader";
+ qcom,adsp-state = <0>;
+ };
+
+ qcom,avtimer@c0a300c {
+ compatible = "qcom,avtimer";
+ reg = <0x0c0a300c 0x4>,
+ <0x0c0a3010 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ qcom,clk-div = <27>;
+ };
+
+ int_codec: sound {
+ status = "okay";
+ compatible = "qcom,msm8952-audio-codec";
+ qcom,model = "msm8953-snd-card";
+ reg = <0xc051000 0x4>,
+ <0xc051004 0x4>,
+ <0xc055000 0x4>,
+ <0xc052000 0x4>;
+ reg-names = "csr_gp_io_mux_mic_ctl",
+ "csr_gp_io_mux_spkr_ctl",
+ "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+ "csr_gp_io_mux_quin_ctl";
+
+ qcom,msm-ext-pa = "primary";
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-hs-micbias-type = "external";
+ qcom,msm-micbias1-ext-cap;
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS External", "Handset Mic",
+ "MIC BIAS External2", "Headset Mic",
+ "MIC BIAS External", "Secondary Mic",
+ "AMIC1", "MIC BIAS External",
+ "AMIC2", "MIC BIAS External2",
+ "AMIC3", "MIC BIAS External",
+ "DMIC1", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic1",
+ "DMIC2", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic2",
+ "WSA_SPK OUT", "VDD_WSA_SWITCH",
+ "SpkrMono WSA_IN", "WSA_SPK OUT";
+
+ qcom,hdmi-dba-codec-rx;
+
+ qcom,msm-gpios =
+ "pri_i2s",
+ "dmic_gpio",
+ "quin_i2s",
+ "comp_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "pri_i2s_act",
+ "dmic_gpio_act",
+ "pri_i2s_dmic_gpio_act",
+ "quin_act",
+ "quin_pri_i2s_act",
+ "quin_dmic_gpio_act",
+ "quin_dmic_gpio_pri_i2s_act",
+ "comp_gpio_act",
+ "comp_gpio_pri_i2s_act",
+ "comp_gpio_dmic_gpio_act",
+ "comp_gpio_pri_i2s_dmic_gpio_act",
+ "comp_gpio_quin_act",
+ "comp_gpio_quin_pri_i2s_act",
+ "comp_gpio_quin_dmic_gpio_act",
+ "comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+ pinctrl-names =
+ "all_off",
+ "pri_i2s_act",
+ "dmic_gpio_act",
+ "pri_i2s_dmic_gpio_act",
+ "quin_act",
+ "quin_pri_i2s_act",
+ "quin_dmic_gpio_act",
+ "quin_dmic_gpio_pri_i2s_act",
+ "comp_gpio_act",
+ "comp_gpio_pri_i2s_act",
+ "comp_gpio_dmic_gpio_act",
+ "comp_gpio_pri_i2s_dmic_gpio_act",
+ "comp_gpio_quin_act",
+ "comp_gpio_quin_pri_i2s_act",
+ "comp_gpio_quin_dmic_gpio_act",
+ "comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+ pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-4 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-5 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-6 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-7 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-8 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-9 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-10 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-11 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+ pinctrl-12 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-13 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+ &cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-14 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+ &cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+ pinctrl-15 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+ &cdc_pdm_lines_2_act &cdc_dmic_lines_act
+ &cdc_dmic_lines_act &pri_tlmm_lines_act
+ &pri_tlmm_ws_act>;
+
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&lpa>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-pcm-lpa";
+ asoc-cpu = <&dai_pri_auxpcm>,
+ <&dai_mi2s0>, <&dai_mi2s1>,
+ <&dai_mi2s2>, <&dai_mi2s3>,
+ <&dai_mi2s5>, <&dai_mi2s6>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+ <&bt_sco_rx>, <&bt_sco_tx>,
+ <&int_fm_rx>, <&int_fm_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>,
+ <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music_2_rx>;
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+
+ asoc-codec = <&stub_codec>, <&pm8953_diangu_dig>, <&hdmi_dba>;
+ asoc-codec-names = "msm-stub-codec.1", "cajon_codec",
+ "msm-hdmi-dba-codec-rx";
+ asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+ asoc-wsa-codec-prefixes = "SpkrMono";
+
+ msm-vdd-wsa-switch-supply = <&pm8953_l5>;
+ qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+ qcom,msm-vdd-wsa-switch-current = <10000>;
+ };
+
+ clock_audio: audio_ext_clk {
+ status = "disabled";
+ compatible = "qcom,audio-ref-clk";
+ clock-names = "osr_clk";
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ };
+
+};
+
+&adsp_io {
+ qcom,virtual-addr-pool = <0x10000000 0x0fffffff>;
+ #iommu-cells = <1>;
+};
+
+&clock_audio {
+ status = "okay";
+ qcom,audio-ref-clk-gpio = <&pm8953_gpios 1 0>;
+ qcom,lpass-mclk-id = "pri_mclk";
+ clocks = <&clock_gcc clk_div_clk2>;
+ pinctrl-names = "sleep", "active";
+ pinctrl-0 = <&cdc_mclk2_sleep>;
+ pinctrl-1 = <&cdc_mclk2_active>;
+};
+
+&pm8953_1 {
+ status = "okay";
+ pm8953_diangu_dig: 8953_wcd_codec@f000 {
+ status = "okay";
+ compatible = "qcom,msm8x16_wcd_codec";
+ reg = <0xf000 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0>,
+ <0x1 0xf0 0x1>,
+ <0x1 0xf0 0x2>,
+ <0x1 0xf0 0x3>,
+ <0x1 0xf0 0x4>,
+ <0x1 0xf0 0x5>,
+ <0x1 0xf0 0x6>,
+ <0x1 0xf0 0x7>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int";
+
+ cdc-vdda-cp-supply = <&pm8953_s4>;
+ qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
+ qcom,cdc-vdda-cp-current = <500000>;
+
+ cdc-vdd-io-supply = <&pm8953_l5>;
+ qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-io-current = <5000>;
+
+ cdc-vdd-pa-supply = <&pm8953_s4>;
+ qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+ qcom,cdc-vdd-pa-current = <260000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8953_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3125000 3125000>;
+ qcom,cdc-vdd-mic-bias-current = <5000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-io",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+
+ pm8953_diangu_analog: 8953_wcd_codec@f100 {
+ status = "okay";
+ compatible = "qcom,msm8x16_wcd_codec";
+ reg = <0xf100 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf1 0x0>,
+ <0x1 0xf1 0x1>,
+ <0x1 0xf1 0x2>,
+ <0x1 0xf1 0x3>,
+ <0x1 0xf1 0x4>,
+ <0x1 0xf1 0x5>;
+ interrupt-names = "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+ qcom,dig-cdc-base-addr = <0xc0f0000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
new file mode 100644
index 0000000..7947008
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+ compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+ qcom,board-id= <0x56 0x30>;
+};
+
+&pm8953_mpps {
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ qcom,mode = <4>; // A-input
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+ qcom,master-en = <1>; //Enable MPP
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a200 {
+ /* MPP3 - PA_THERM config */
+ reg = <0xa200 0x100>;
+ com,pin-num = <3>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <2>; /* AMUX 7 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a300 {
+ /* MPP4 - CASE_THERM config */
+ reg = <0xa300 0x100>;
+ com,pin-num = <4>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+};
+
+&tlmm {
+ button_active: button_active {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ icr_int {
+ qcom,pins = <&tlmm 53>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "icr-int";
+ icr_int_default: icr_int_default {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-up; /* PULL UP*/
+ };
+ };
+
+ gcc_gp1_clk_pin {
+ qcom,pins = <&tlmm 33>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "gp1-clk-pin";
+ gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable;
+ };
+ };
+
+ bt_host_wake_default: bt_host_wake_default {
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>;
+ };
+ };
+};
+
+&soc {
+ usb_detect: usb_detect {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+ qcom,enable-button-mode;
+
+ pinctrl-names = "button_active";
+ pinctrl-0 = <&button_active>;
+ };
+
+ hbtp {
+ status = "disabled";
+ };
+};
+
+&usb3 {
+ extcon = <&usb_detect>;
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&modem_mem {
+ reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+ config {
+ /delete-property/ bias-pull-up;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
new file mode 100644
index 0000000..f3124bc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+ compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+ qcom,board-id= <0x56 0x31>;
+};
+
+
+
+&pm8953_mpps {
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ qcom,mode = <4>; // A-input
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+ qcom,master-en = <1>; //Enable MPP
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a200 {
+ /* MPP3 - PA_THERM config */
+ reg = <0xa200 0x100>;
+ com,pin-num = <3>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <2>; /* AMUX 7 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+
+ mpp@a300 {
+ /* MPP4 - CASE_THERM config */
+ reg = <0xa300 0x100>;
+ com,pin-num = <4>;
+ qcom,mode = <4>; /* AIN input */
+ qcom,invert = <1>; /* Enable MPP */
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ status = "okay";
+ };
+};
+
+&tlmm {
+ button_active: button_active {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ icr_int {
+ qcom,pins = <&tlmm 53>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "icr-int";
+ icr_int_default: icr_int_default {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-up; /* PULL UP*/
+ };
+ };
+
+ gcc_gp1_clk_pin {
+ qcom,pins = <&tlmm 33>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "gp1-clk-pin";
+ gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable;
+ };
+ };
+
+ bt_host_wake_default: bt_host_wake_default {
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>;
+ };
+ };
+};
+
+&soc {
+ usb_detect: usb_detect {
+ compatible = "linux,extcon-usb-gpio";
+ vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+ qcom,enable-button-mode;
+
+ pinctrl-names = "button_active";
+ pinctrl-0 = <&button_active>;
+ };
+
+ hbtp {
+ status = "disabled";
+ };
+};
+
+&usb3 {
+ extcon = <&usb_detect>;
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&modem_mem {
+ reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+ config {
+ /delete-property/ bias-pull-up;
+ bias-pull-down;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
new file mode 100644
index 0000000..8fae286
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+ rpm-regulator-ldoa18 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ pm8953_l18: regulator-l18 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l18";
+ qcom,set = <3>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <2700000>;
+ };
+
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l9";
+ qcom,set = <3>;
+ regulator-boot-on;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ regulator-boot-on;
+ regulator-always-on;
+ pm8953_l10: regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l10";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+
+ /* L4 for ALS, TMP, Moisture, Image Sensor, PD Control, Thermistor */
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ regulator-boot-on;
+ regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l4";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l2, l7 and l17 for cci */
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l2";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l7";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l17";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l6 for eeprom/ Image sensor */
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l6";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+ /* l5 for WSA8815 Speaker amp */
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l5";
+ qcom,set = <3>;
+ regulator-always-on;
+ regulator-boot-on;
+ status = "okay";
+ };
+ };
+
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
new file mode 100644
index 0000000..b359db3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8953.dtsi"
+#include "msm8953-pinctrl.dtsi"
+/ {
+ model = "Qualcomm Technologies, Inc. APQ 8953";
+ compatible = "qcom,apq8053";
+ qcom,msm-id = <304 0x0>;
+};
+
+/ {
+ /delete-property/ aliases;
+
+ aliases {
+ /* smdtty devices */
+ smd1 = &smdtty_apps_fm;
+ smd2 = &smdtty_apps_riva_bt_acl;
+ smd3 = &smdtty_apps_riva_bt_cmd;
+ smd4 = &smdtty_mbalbridge;
+ smd5 = &smdtty_apps_riva_ant_cmd;
+ smd6 = &smdtty_apps_riva_ant_data;
+ smd7 = &smdtty_data1;
+ smd8 = &smdtty_data4;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd36 = &smdtty_loopback;
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+ sdhc2 = &sdhc_2; /* SDC2 for SD card */
+ i2c1 = &i2c_1;
+ i2c2 = &i2c_2;
+ i2c3 = &i2c_3;
+ i2c4 = &i2c_4;
+ i2c5 = &i2c_5;
+ i2c7 = &i2c_7;
+ i2c8 = &i2c_8;
+ spi3 = &spi_3;
+ };
+
+};
+
+&sdhc_2 {
+ nest,workaround-ocr-add-vio = "VIO_3_3";
+};
+
+&soc {
+ i2c_4: i2c@78b8000 { /* BLSP1 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x78b8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 98 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_4_active>;
+ pinctrl-1 = <&i2c_4_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <86>;
+ dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+ <&dma_blsp1 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c_7: i2c@7AF7000 { /* BLSP2 QUP2 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x7AF7000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 301 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup3_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_7_active>;
+ pinctrl-1 = <&i2c_7_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <84>;
+ dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
+ <&dma_blsp1 9 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c_8: i2c@7AF8000 { /* BLSP2 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ reg = <0x7AF8000 0x600>;
+ interrupt-names = "qup_irq";
+ interrupts = <0 302 0>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+ <&clock_gcc clk_gcc_blsp2_qup4_i2c_apps_clk>;
+
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_8_active>;
+ pinctrl-1 = <&i2c_8_sleep>;
+ qcom,noise-rjct-scl = <0>;
+ qcom,noise-rjct-sda = <0>;
+ qcom,master-id = <84>;
+ dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+ <&dma_blsp1 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-0 = <&gpio_key_active>;
+ pinctrl-1 = <&gpio_key_suspend>;
+
+ camera_focus {
+ label = "camera_focus";
+ gpios = <&tlmm 87 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x210>;
+ debounce-interval = <15>;
+ };
+
+ camera_snapshot {
+ label = "camera_snapshot";
+ gpios = <&tlmm 86 0x1>;
+ linux,input-type = <1>;
+ linux,code = <0x2fe>;
+ debounce-interval = <15>;
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&tlmm 85 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ debounce-interval = <15>;
+ };
+ };
+
+ hbtp {
+ compatible = "qcom,hbtp-input";
+ vcc_ana-supply = <&pm8953_l10>;
+ vcc_dig-supply = <&pm8953_l5>;
+ qcom,afe-load = <50000>;
+ qcom,afe-vtg-min = <2850000>;
+ qcom,afe-vtg-max = <2850000>;
+ qcom,dig-load = <15000>;
+ qcom,dig-vtg-min = <1800000>;
+ qcom,dig-vtg-max = <1800000>;
+ };
+};
+
+&soc {
+ qcom,rmnet-ipa {
+ status = "disabled";
+ };
+};
+
+&ipa_hw {
+ status = "disabled";
+};
+
+&secure_mem {
+ status = "disabled";
+};
+
+&tlmm {
+ i2c_4 {
+ i2c_4_active: i2c_4_active {
+ /* active state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_7 {
+ i2c_7_active: i2c_7_active {
+ /* active state */
+ mux {
+ pins = "gpio135", "gpio136";
+ function = "blsp_i2c7";
+ };
+
+ config {
+ pins = "gpio135", "gpio136";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_7_sleep: i2c_7_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio135", "gpio136";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio135", "gpio136";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+
+ i2c_8 {
+ i2c_8_active: i2c_8_active {
+ /* active state */
+ mux {
+ pins = "gpio98", "gpio99";
+ function = "blsp_i2c8";
+ };
+
+ config {
+ pins = "gpio98", "gpio99";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_8_sleep: i2c_8_sleep {
+ /* suspended state */
+ mux {
+ pins = "gpio98", "gpio99";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio98", "gpio99";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+};
+
+&blsp1_uart0 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+&i2c_4 {
+ status = "ok";
+
+ opt3001@44 {
+ compatible = "ti,opt3001";
+ reg = <0x44>; /* ALS_ADDR connected to ground */
+ status = "okay";
+ };
+
+ ina231@40 {
+ compatible = "ti,ina231";
+ reg = <0x40>;
+ shunt-resistor = <10000>;
+ };
+};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l8>;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+ 384000000>;
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS200_1p8v";
+
+ status = "ok";
+};
+
+&i2c_8 {
+ status = "ok";
+
+ tlc59108@42 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #gpio-cells = <2>;
+ enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+ compatible = "ti,tlc59108";
+ label = "tlc59108";
+ reg = <0x42>;
+
+ chan0@0 {
+ label = "tlc59108:chan0";
+ reg = <0x0>;
+ };
+
+ chan1@1 {
+ label = "tlc59108:chan1";
+ reg = <0x1>;
+ };
+
+ chan2@2 {
+ label = "tlc59108:chan2";
+ reg = <0x2>;
+ };
+
+ chan3@3 {
+ label = "tlc59108:chan3";
+ reg = <0x3>;
+ };
+
+ chan4@4 {
+ label = "tlc59108:chan4";
+ reg = <0x4>;
+ };
+
+ chan5@5 {
+ label = "tlc59108:chan5";
+ reg = <0x5>;
+ };
+
+ chan6@6 {
+ label = "tlc59108:chan6";
+ reg = <0x6>;
+ };
+
+ chan7@7 {
+ label = "tlc59108:chan7";
+ reg = <0x7>;
+ };
+ };
+
+ tlc59116@68 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #gpio-cells = <2>;
+ enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+ compatible = "ti,tlc59116";
+ label = "tlc59116";
+ reg = <0x68>;
+
+ chan0@0 {
+ label = "tlc59116:chan0";
+ reg = <0x0>;
+ };
+
+ chan1@1 {
+ label = "tlc59116:chan1";
+ reg = <0x1>;
+ };
+
+ chan2@2 {
+ label = "tlc59116:chan2";
+ reg = <0x2>;
+ };
+
+ chan3@3 {
+ label = "tlc59116:chan3";
+ reg = <0x3>;
+ };
+
+ chan4@4 {
+ label = "tlc59116:chan4";
+ reg = <0x4>;
+ };
+
+ chan5@5 {
+ label = "tlc59116:chan5";
+ reg = <0x5>;
+ };
+
+ chan6@6 {
+ label = "tlc59116:chan6";
+ reg = <0x6>;
+ };
+
+ chan7@7 {
+ label = "tlc59116:chan7";
+ reg = <0x7>;
+ };
+
+ chan8@8 {
+ label = "tlc59116:chan8";
+ reg = <0x8>;
+ };
+
+ chan9@9 {
+ label = "tlc59116:chan9";
+ reg = <0x9>;
+ };
+
+ chan10@10 {
+ label = "tlc59116:chan10";
+ reg = <0xa>;
+ };
+
+ chan11@11 {
+ label = "tlc59116:chan11";
+ reg = <0xb>;
+ };
+
+ chan12@12 {
+ label = "tlc59116:chan12";
+ reg = <0xc>;
+ };
+
+ chan13@13 {
+ label = "tlc59116:chan13";
+ reg = <0xd>;
+ };
+
+ chan14@14 {
+ label = "tlc59116:chan14";
+ reg = <0xe>;
+ };
+
+ chan15@15 {
+ label = "tlc59116:chan15";
+ reg = <0xf>;
+ };
+ };
+
+};
+
+&i2c_3 {
+ status = "ok";
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0x56>;
+ qcom,eeprom-name = "cat24c512";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x56>;
+ qcom,cci-master = <0>;
+ /* For 512 Kb eeprom chip
+ * add 8 logic eeprom blcoks each is 8KB
+ */
+ qcom,num-blocks = <8>;
+
+ qcom,page0 = <0 0 0 0 0 0>;
+ qcom,poll0 = <0 0 0 0 0 0>;
+ qcom,saddr0 = <0x56>;
+ qcom,mem0 = <8192 0x0000 2 0 1 0>;
+
+ qcom,page1 = <0 0 0 0 0 0>;
+ qcom,poll1 = <0 0 0 0 0 0>;
+ qcom,saddr1 = <0x56>;
+ qcom,mem1 = <8192 0x2000 2 0 1 0>;
+
+ qcom,page2 = <0 0 0 0 0 0>;
+ qcom,poll2 = <0 0 0 0 0 0>;
+ qcom,saddr2 = <0x56>;
+ qcom,mem2 = <8192 0x4000 2 0 1 0>;
+
+ qcom,page3 = <0 0 0 0 0 0>;
+ qcom,poll3 = <0 0 0 0 0 0>;
+ qcom,saddr3 = <0x56>;
+ qcom,mem3 = <8192 0x6000 2 0 1 0>;
+
+ qcom,page4 = <0 0 0 0 0 0>;
+ qcom,poll4 = <0 0 0 0 0 0>;
+ qcom,saddr4 = <0x56>;
+ qcom,mem4 = <8192 0x8000 2 0 1 0>;
+
+ qcom,page5 = <0 0 0 0 0 0>;
+ qcom,poll5 = <0 0 0 0 0 0>;
+ qcom,saddr5 = <0x56>;
+ qcom,mem5 = <8192 0xA000 2 0 1 0>;
+
+ qcom,page6 = <0 0 0 0 0 0>;
+ qcom,poll6 = <0 0 0 0 0 0>;
+ qcom,saddr6 = <0x56>;
+ qcom,mem6 = <8192 0xC000 2 0 1 0>;
+
+ qcom,page7 = <0 0 0 0 0 0>;
+ qcom,poll7 = <0 0 0 0 0 0>;
+ qcom,saddr7 = <0x56>;
+ qcom,mem7 = <8192 0xE000 2 0 1 0>;
+
+ cam_vio-supply = <&pm8953_l6>;
+ qcom,cam-vreg-name = "cam_vio";
+ qcom,cam-vreg-min-voltage = <0>;
+ qcom,cam-vreg-max-voltage = <0>;
+ qcom,cam-vreg-op-mode = <0>;
+ qcom,cam-power-seq-type = "sensor_vreg";
+ qcom,cam-power-seq-val = "cam_vio";
+ qcom,cam-power-seq-cfg-val = <1>;
+ qcom,cam-power-seq-delay = <1>;
+ status = "ok";
+ };
+};
+
+&sdhc_2 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l10>;
+ qcom,vdd-voltage-level = <18000000 1800000>;
+ qcom,vdd-current-level = <200 22000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l12>;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &tlmm 45 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+ /*cd-gpios = <&tlmm 45 0x1>;*/
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+ 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
+&pm8953_typec {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
index 63a364a..6c9c266 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
@@ -25,17 +25,3 @@
&blsp2_uart0 {
status = "okay";
};
-
-&i2c_3 {
- status = "okay";
- elan_ktf@10 {
- compatible = "elan,ekth3500";
- reg = <0x10>;
- vdd-supply = <&pm8953_l10>;
- vccio-supply = <&pm8953_l6>;
- interrupt-parent = <&tlmm>;
- reset-gpio = <&tlmm 64 GPIO_ACTIVE_LOW>;
- elan,irq-gpio = <&tlmm 65 0x2008>;
- interrupts = <65 0x2>;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
index 993799b..de707b8 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
@@ -13,10 +13,23 @@
#include "apq8053-lite-dragon.dtsi"
+&rpm_bus {
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8953_l10: regulator-l10 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <3300000>;
+ status = "okay";
+ };
+ };
+};
+
&mdss_dsi0 {
qcom,ext-vdd-gpio = <&tlmm 100 0>;
qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
+ /delete-property/ vdd-supply;
qcom,platform-lane-config = [00 00 ff 0f
00 00 ff 0f
00 00 ff 0f
@@ -66,3 +79,17 @@
&camera2{
qcom,mount-angle = <270>;
};
+
+&i2c_3 {
+ status = "okay";
+ elan_ktf@10 {
+ compatible = "elan,ekth3500";
+ reg = <0x10>;
+ vdd-supply = <&pm8953_l10>;
+ vccio-supply = <&pm8953_l6>;
+ interrupt-parent = <&tlmm>;
+ reset-gpio = <&tlmm 64 GPIO_ACTIVE_LOW>;
+ elan,irq-gpio = <&tlmm 65 0x2008>;
+ interrupts = <65 0x2>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
new file mode 100644
index 0000000..ef4c7a1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lite.dtsi"
+#include "apq8053-lite-dragon-v2.2.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 Lite DragonBoard V2.2.1";
+ compatible = "qcom,apq8053-lite-dragonboard", "qcom,apq8053",
+ "qcom,dragonboard";
+ qcom,board-id = <0x01010320 0>;
+};
+
+&blsp2_uart0 {
+ status = "okay";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_inxnt51021_1200p_video>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
index 8b5dd2b..ecc4fea 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
@@ -25,81 +25,3 @@
&blsp2_uart0 {
status = "okay";
};
-
-&i2c_3 {
- status = "okay";
- /delete-node/ himax_ts@48;
- gt9xx-i2c@14 {
- compatible = "goodix,gt9xx";
- status = "okay";
- reg = <0x14>;
- vdd_ana-supply = <&pm8953_l10>;
- vcc_i2c-supply = <&pm8953_l6>;
- interrupt-parent = <&tlmm>;
- interrupts = <65 0x2008>;
- pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
- "gdix_ts_int_output_high", "gdix_ts_int_input",
- "gdix_ts_rst_default", "gdix_ts_rst_output_low",
- "gdix_ts_rst_output_high", "gdix_ts_rst_input";
- pinctrl-0 = <&ts_int_default>;
- pinctrl-1 = <&ts_int_output_low>;
- pinctrl-2 = <&ts_int_output_high>;
- pinctrl-3 = <&ts_int_input>;
- pinctrl-4 = <&ts_rst_default>;
- pinctrl-5 = <&ts_rst_output_low>;
- pinctrl-6 = <&ts_rst_output_high>;
- pinctrl-7 = <&ts_rst_input>;
-
- reset-gpios = <&tlmm 64 0x00>;
- irq-gpios = <&tlmm 65 0x2008>;
- irq-flags = <2>;
-
- touchscreen-max-id = <11>;
- touchscreen-size-x = <1200>;
- touchscreen-size-y = <1920>;
- touchscreen-max-w = <1024>;
- touchscreen-max-p = <1024>;
-
- goodix,type-a-report = <0>;
- goodix,driver-send-cfg = <1>;
- goodix,wakeup-with-reset = <0>;
- goodix,resume-in-workqueue = <0>;
- goodix,int-sync = <1>;
- goodix,swap-x2y = <0>;
- goodix,esd-protect = <1>;
- goodix,pen-suppress-finger = <0>;
- goodix,auto-update = <1>;
- goodix,auto-update-cfg = <0>;
- goodix,power-off-sleep = <0>;
-
- goodix,cfg-group0 = [
- 5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
- 01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
- 39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
- 00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
- 3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
- 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
- 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
- 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
- 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
- 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
- 07 06 05 04 03 02 01 00 08 01
- ];
-
- goodix,cfg-group2 = [
- 5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
- 01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
- 39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
- 00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
- 36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
- 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
- 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
- 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
- 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
- 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
- 07 06 05 04 03 02 01 00 81 01
- ];
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
index 1744c90..d4dbc9e 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
@@ -13,9 +13,94 @@
#include "apq8053-lite-dragon.dtsi"
+&rpm_bus {
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8953_l10: regulator-l10 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <3300000>;
+ status = "okay";
+ };
+ };
+};
+
&i2c_3 {
status = "okay";
/delete-node/ himax_ts@48;
+ gt9xx-i2c@14 {
+ compatible = "goodix,gt9xx";
+ status = "okay";
+ reg = <0x14>;
+ vdd_ana-supply = <&pm8953_l10>;
+ vcc_i2c-supply = <&pm8953_l6>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 0x2008>;
+ pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
+ "gdix_ts_int_output_high", "gdix_ts_int_input",
+ "gdix_ts_rst_default", "gdix_ts_rst_output_low",
+ "gdix_ts_rst_output_high", "gdix_ts_rst_input";
+ pinctrl-0 = <&ts_int_default>;
+ pinctrl-1 = <&ts_int_output_low>;
+ pinctrl-2 = <&ts_int_output_high>;
+ pinctrl-3 = <&ts_int_input>;
+ pinctrl-4 = <&ts_rst_default>;
+ pinctrl-5 = <&ts_rst_output_low>;
+ pinctrl-6 = <&ts_rst_output_high>;
+ pinctrl-7 = <&ts_rst_input>;
+
+ reset-gpios = <&tlmm 64 0x00>;
+ irq-gpios = <&tlmm 65 0x2008>;
+ irq-flags = <2>;
+
+ touchscreen-max-id = <11>;
+ touchscreen-size-x = <1200>;
+ touchscreen-size-y = <1920>;
+ touchscreen-max-w = <1024>;
+ touchscreen-max-p = <1024>;
+
+ goodix,type-a-report = <0>;
+ goodix,driver-send-cfg = <1>;
+ goodix,wakeup-with-reset = <0>;
+ goodix,resume-in-workqueue = <0>;
+ goodix,int-sync = <1>;
+ goodix,swap-x2y = <0>;
+ goodix,esd-protect = <1>;
+ goodix,pen-suppress-finger = <0>;
+ goodix,auto-update = <1>;
+ goodix,auto-update-cfg = <0>;
+ goodix,power-off-sleep = <0>;
+
+ goodix,cfg-group0 = [
+ 5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
+ 01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
+ 39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
+ 00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
+ 3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
+ 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+ 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+ 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+ 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+ 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+ 07 06 05 04 03 02 01 00 08 01
+ ];
+
+ goodix,cfg-group2 = [
+ 5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
+ 01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
+ 39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
+ 00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
+ 36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
+ 0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+ 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+ 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+ 28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+ 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+ 07 06 05 04 03 02 01 00 81 01
+ ];
+ };
};
&mdss_mdp {
@@ -32,7 +117,7 @@
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- vdd-supply = <&pm8953_l10>;
+ /delete-property/ vdd-supply;
vddio-supply = <&pm8953_l6>;
lab-supply = <&lab_regulator>;
ibb-supply = <&ibb_regulator>;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
index c682f58..830cb17 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
@@ -13,6 +13,15 @@
#include "apq8053-lite-dragon.dtsi"
+&soc {
+ cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&sec_tlmm_lines_act>;
+ pinctrl-1 = <&sec_tlmm_lines_sus>;
+ };
+};
+
&pm8953_l4 {
status = "okay";
regulator-always-on;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index 186d6ef..6638aac 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -100,8 +100,8 @@
cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
compatible = "qcom,msm-cdc-pinctrl";
pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&sec_tlmm_lines_act>;
- pinctrl-1 = <&sec_tlmm_lines_sus>;
+ pinctrl-0 = <&sec_tlmm_lines_act &ext_amp_ctrl_active>;
+ pinctrl-1 = <&sec_tlmm_lines_sus &ext_amp_ctrl_sleep>;
};
gpio_keys {
@@ -130,11 +130,36 @@
};
};
+&cdc_pdm_comp_lines_act {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>;
+ };
+};
+
+&cdc_pdm_comp_lines_sus {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
&firmware {
android {
vbmeta {
compatible = "android,vbmeta";
- parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,dsp,oem";
};
fstab {
/delete-node/ system;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
new file mode 100644
index 0000000..eae1118
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "apq8053-lite.dtsi"
+#include "msm8953-pinctrl.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
+#include "msm8953-mdss-panels.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. APQ8053 Lite SoM";
+};
+
+&soc {
+ vreg_5p0: vreg_5p0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_5p0";
+ status = "ok";
+ enable-active-high;
+ };
+
+ eldo_cam0_vreg: eldo_cam0_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam0_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam1_vreg: eldo_cam1_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam1_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam2_vreg: eldo_cam2_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam2_vreg";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ status = "ok";
+ enable-active-high;
+ vin-supply = <&pm8953_l5>;
+ };
+
+ eldo_cam1_vcm_vreg: eldo_cam1_vcm_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "eldo_cam1_vcm_vreg";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ status = "ok";
+ enable-active-high;
+ };
+
+ cnss_sdio: qcom,cnss_sdio {
+ compatible = "qcom,cnss_sdio";
+ subsys-name = "AR6320";
+
+ /**
+ * There is no vdd-wlan on board and this is not for DSRC.
+ * IO and XTAL share the same vreg.
+ */
+ vdd-wlan-io-supply = <&pm8953_l6>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
+ qcom,msm-bus,name = "msm-cnss";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <79 512 0 0>, /* No vote */
+ <79 512 6250 200000>, /* 50 Mbps */
+ <79 512 25000 200000>, /* 200 Mbps */
+ <79 512 2048000 4096000>; /* MAX */
+ };
+
+ bluetooth: bt_qca9379 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&tlmm 76 0>; /* BT_EN */
+ };
+
+ cdc_dmic_gpios: cdc_dmic_pinctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+ pinctrl-1 = <&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+ };
+
+ cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&sec_tlmm_lines_act &ext_amp_ctrl_active>;
+ pinctrl-1 = <&sec_tlmm_lines_sus &ext_amp_ctrl_sleep>;
+ };
+};
+
+&cdc_pdm_comp_lines_act {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>;
+ };
+};
+
+&cdc_pdm_comp_lines_sus {
+ mux {
+ pins = "gpio67";
+ function = "cdc_pdm0";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&firmware {
+ android {
+ vbmeta {
+ compatible = "android,vbmeta";
+
+ parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+ };
+ fstab {
+ /delete-node/ system;
+ vendor {
+ fsmgr_flags = "wait,slotselect,avb";
+ };
+ };
+ };
+};
+
+&rpm_bus {
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "okay";
+
+ pm8953_l4: regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm8953_l4";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+};
+
+&int_codec {
+ status = "ok";
+ qcom,model = "msm8953-openq624-snd-card";
+
+ /delete-property/ qcom,cdc-us-euro-gpios;
+ qcom,msm-hs-micbias-type = "internal";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS Internal1", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "MIC BIAS Internal1", "Secondary Mic",
+ "AMIC1", "MIC BIAS Internal1",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS Internal1",
+ "DMIC1", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic1",
+ "DMIC2", "MIC BIAS Internal1",
+ "MIC BIAS Internal1", "Digital Mic2";
+
+ qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+ qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+ /delete-property/ asoc-wsa-codec-names;
+ /delete-property/ asoc-wsa-codec-prefixes;
+ /delete-property/ msm-vdd-wsa-switch-supply;
+ /delete-property/ qcom,msm-vdd-wsa-switch-voltage;
+ /delete-property/ qcom,msm-vdd-wsa-switch-current;
+};
+
+&soc {
+ /delete-node/ hbtp;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>;
+};
+
+&blsp1_uart0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+
+&blsp2_uart0 {
+ status = "okay";
+};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pm8953_l8>;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+ 384000000>;
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ status = "ok";
+};
+
+&tlmm {
+ sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+ mux {
+ pins = "gpio75";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75";
+ drive-strength = <10>;
+ bias-pull-up;
+ output-high;
+ };
+ };
+ sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+ mux {
+ pins = "gpio75";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+};
+
+&sdhc_2 {
+ /* device communication power supply */
+ vdd-io-supply = <&pm8953_l12>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ qcom,core_3_0v_support;
+ qcom,nonremovable;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_wlan_gpio_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_wlan_gpio_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
+&spmi_bus {
+ qcom,pm8953@0 {
+ qcom,power-on@800 {
+ qcom,resin-gpiobase = <1019>;
+ qcom,pon_2 {
+ /delete-property/ linux,code;
+ };
+ };
+ };
+ qcom,pmi8950@2 {
+ qcom,leds@a100 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa100 0x100>;
+ label = "mpp";
+
+ qcom,led_mpp_2 {
+ label = "mpp";
+ linux,name = "green";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "manual";
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x60>;
+ };
+ };
+
+ qcom,leds@a300 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa300 0x100>;
+ label = "mpp";
+
+ qcom,led_mpp_4 {
+ label = "mpp";
+ linux,name = "blue";
+ linux,default-trigger = "none";
+ qcom,default-state = "off";
+ qcom,max-current = <40>;
+ qcom,current-setting = <5>;
+ qcom,id = <6>;
+ qcom,mode = "manual";
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x60>;
+ };
+ };
+ };
+};
+
+&pm8953_typec {
+ ss-mux-supply = <&pm8953_l13>;
+ qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&typec_ssmux_config>;
+};
+
+/{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&pmi_haptic{
+ status = "disabled";
+ qcom,actuator-type = "lra";
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
+&flash_led {
+ status = "disabled";
+};
+
+&pm8953_pwm {
+ status = "ok";
+};
+
+&pm8953_vadc {
+ /delete-node/ chan@13;
+};
+
+&pmi8950_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmi_gpio1_default>;
+ pmi_gpio1_default: pmi8950_gpio1 {
+ pins = "gpio1";
+ function = "normal";
+ input-enable;
+ power-source = <0>;
+ status = "okay";
+ };
+};
+
+&pmi8950_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_fet_wled_pwr_en_default>;
+ ext_fet_wled_pwr_en_default: pmi8950_mpp3 {
+ pins = "mpp3"; /* MPP_3 */
+ function = "digital"; /* Digital */
+ output-high; /* Output */
+ drive-strength = <2>; /* 1.8 mA */
+ power-source = <1>;
+ bias-disable = <0>; /* no pull */
+ status = "okay";
+ };
+};
+
+&pm8953_gpios {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm_gpio1_div_clk2_default>;
+ pm_gpio1_div_clk2_default: pm8953_gpio1 {
+ pins = "gpio1";
+ function = "normal";
+ output-high;
+ power-source = <1>;
+ status = "okay";
+ };
+};
+
+&pm8953_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pm_mpp4_wled_pwm_ctrl_default>;
+ pm_mpp4_wled_pwm_ctrl_default: pm8953_mpp4 {
+ pins = "mpp4"; /* WLED_PWM_CTRL */
+ function = "digital"; /* Digital */
+ output-high; /* Output */
+ drive-strength = <2>; /* 1.8 mA */
+ power-source = <0>; /* VPH_PWR */
+ qcom,dtest = <1>; /* DTEST1 */
+ bias-disable = <0>; /* no pull */
+ status = "okay";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
index 03c3659..995ca4d 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
@@ -41,16 +41,6 @@
39 01 00 00 78 00 02 11 00
/*set display on and delay 20ms*/
39 01 00 00 14 00 02 29 00
- /*enable extended command set*/
- 39 01 00 00 00 00 04 b9 83 10 0a
- /*32KHZ PWM*/
- 39 01 00 00 00 00 08 c9 1f 00 08 1e 81 1e 00
- /*backlight enable*/
- 39 01 00 00 00 00 02 53 24
- /*still picture and delay 5ms*/
- 39 01 00 00 05 00 02 55 02
- /*about 80% duty ratio*/
- 39 01 00 00 00 00 0a ca 40 3c 38 34 33 32 30 2c 28
];
qcom,mdss-dsi-off-command = [05 01 00 00 96 00 02 28 00
05 01 00 00 00 00 02 10 00];
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
new file mode 100644
index 0000000..2131aec
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
@@ -0,0 +1,106 @@
+/* Novatek Android Driver Sample Code for Novatek chipset
+*
+* Copyright (C) 2015 Novatek Microelectronics Corp.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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_inxnt51021_1200p_video: qcom,mdss_dsi_inxnt51021_1200p_video {
+ qcom,mdss-dsi-panel-name = "inxnt51021 1200p video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ 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 = <1200>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <100>;
+ qcom,mdss-dsi-h-back-porch = <32>;
+ qcom,mdss-dsi-h-pulse-width = <1>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <14>;
+ qcom,mdss-dsi-v-front-porch = <25>;
+ 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-on-command = [
+ 23 01 00 00 01 00 02 8F A5
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 00 00 02 84 00
+ 23 01 00 00 00 00 02 8C 84
+ 23 01 00 00 00 00 02 C5 50
+ 23 01 00 00 00 00 02 C7 50
+ 23 01 00 00 00 00 02 85 04
+ 23 01 00 00 00 00 02 86 08
+ 23 01 00 00 00 00 02 83 AA
+ 23 01 00 00 00 00 02 84 11
+ 23 01 00 00 00 00 02 9C 10
+ 23 01 00 00 00 00 02 A9 4B
+ 23 01 00 00 00 00 02 A0 36
+ 23 01 00 00 00 00 02 A1 36
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 83 BB
+ 23 01 00 00 00 00 02 84 22
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 83 CC
+ 23 01 00 00 00 00 02 84 33
+ 23 01 00 00 00 00 02 C0 00
+ 23 01 00 00 00 00 02 E0 3D
+ 23 01 00 00 00 00 02 8F 00
+ ];
+ qcom,mdss-dsi-off-command = [
+ 23 01 00 00 01 00 02 8F A5
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 78 00 02 84 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,cont-splash-enabled;
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ 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 = [f2 3a 28 00 6c 70 2c 3e 2e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0e>;
+ qcom,mdss-dsi-t-clk-pre = <0x33>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-force-clock-lane-hs;
+ //qcom,platform-bklight-en-gpio = <&tlmm 46 0>;
+ //qcom,mdss-dsi-lcden-ctrl = <&tlmm 61 0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ //qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+ //qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+ //qcom,mdss-dsi-pwm-gpio = <&pm8953_mpps 4 0>;
+ qcom,mdss-pan-physical-width-dimension = <135>;
+ qcom,mdss-pan-physical-height-dimension = <216>;
+ //qcom,mdss-dsi-reset-sequence = <1 10>, <0 5>, <1 50>;
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
index fa6498e..ae3900e 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
@@ -50,7 +50,7 @@
"msm-voice-svc";
asoc-cpu = <&dai_pri_auxpcm>,
<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
- <&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+ <&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
@@ -63,7 +63,7 @@
asoc-cpu-names = "msm-dai-q6-auxpcm.1",
"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
- "msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
index e2fbc9e..48448862 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -113,17 +113,17 @@
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
- pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-names = "default";
pinctrl-0 = <&gpio_key_active>;
- pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
gpios = <&msm_gpio 91 0x1>;
linux,input-type = <1>;
linux,code = <0x210>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
camera_snapshot {
@@ -131,8 +131,9 @@
gpios = <&msm_gpio 92 0x1>;
linux,input-type = <1>;
linux,code = <0x2fe>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
vol_up {
@@ -140,8 +141,9 @@
gpios = <&msm_gpio 90 0x1>;
linux,input-type = <1>;
linux,code = <115>;
- gpio-key,wakeup;
debounce-interval = <15>;
+ linux,can-disable;
+ gpio-key,wakeup;
};
};
@@ -209,7 +211,7 @@
"msm-voice-svc";
asoc-cpu = <&dai_pri_auxpcm>,
<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
- <&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+ <&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
@@ -218,7 +220,7 @@
asoc-cpu-names = "msm-dai-q6-auxpcm.1",
"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
- "msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+ "msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 8c06c93..15c6424 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -1421,6 +1421,12 @@
qcom,latency-level = "ultra";
};
+ pcm_noirq: qcom,msm-pcm-dsp-noirq {
+ compatible = "qcom,msm-pcm-dsp-noirq";
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
lpa: qcom,msm-pcm-lpa {
compatible = "qcom,msm-pcm-lpa";
};
@@ -1475,20 +1481,6 @@
qcom,msm-mi2s-tx-lines = <0>;
};
- dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
- compatible = "qcom,msm-dai-q6-mi2s";
- qcom,msm-dai-q6-mi2s-dev-id = <3>;
- qcom,msm-mi2s-rx-lines = <0>;
- qcom,msm-mi2s-tx-lines = <3>;
- };
-
- dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
- compatible = "qcom,msm-dai-q6-mi2s";
- qcom,msm-dai-q6-mi2s-dev-id = <5>;
- qcom,msm-mi2s-rx-lines = <1>;
- qcom,msm-mi2s-tx-lines = <2>;
- };
-
dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
compatible = "qcom,msm-dai-q6-mi2s";
qcom,msm-dai-q6-mi2s-dev-id = <2>;
@@ -1496,7 +1488,21 @@
qcom,msm-mi2s-tx-lines = <3>;
};
- dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+ dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <3>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+
+ dai_mi2s4: qcom,msm-dai-q6-mi2s-quin {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <4>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s5: qcom,msm-dai-q6-mi2s-senary {
compatible = "qcom,msm-dai-q6-mi2s";
qcom,msm-dai-q6-mi2s-dev-id = <6>;
qcom,msm-mi2s-rx-lines = <0>;
@@ -1647,6 +1653,13 @@
compatible = "qcom,msm-audio-ion";
};
+ qcom,msm-audio-apr {
+ compatible = "qcom,msm-audio-apr";
+ msm_audio_apr_dummy {
+ compatible = "qcom,msm-audio-apr-dummy";
+ };
+ };
+
qcom,mdsprpc-mem {
compatible = "qcom,msm-mdsprpc-mem-region";
memory-region = <&adsp_mem>;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
index 9b9cd47..9212d2d 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -33,3 +33,13 @@
qcom,switch-source = <&pmi8940_switch>;
};
};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&mdss_dsi0 {
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
index e86b9d7..95e003b 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
@@ -22,3 +22,13 @@
&usb_otg {
extcon = <&qpnp_smbcharger>;
};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&mdss_dsi0 {
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index d5f5243..8494aef 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -86,19 +86,19 @@
modem_mem: modem_region@0 {
compatible = "removed-dma-pool";
no-map;
- reg = <0x0 0x86800000 0x0 0x5000000>;
+ reg = <0x0 0x86800000 0x0 0x5500000>;
};
adsp_fw_mem: adsp_fw_region@0 {
compatible = "removed-dma-pool";
no-map;
- reg = <0x0 0x8b800000 0x0 0x1100000>;
+ reg = <0x0 0x8bd00000 0x0 0x1100000>;
};
wcnss_fw_mem: wcnss_fw_region@0 {
compatible = "removed-dma-pool";
no-map;
- reg = <0x0 0x8c900000 0x0 0x700000>;
+ reg = <0x0 0x8ce00000 0x0 0x700000>;
};
venus_mem: venus_region@0 {
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 5180d1a..e328b4b 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -914,6 +914,7 @@
qcom,vdd-voltage-level = <0 1200000 1200000>;
vbus_otg-supply = <&smbcharger_charger_otg>;
+ qcom,hsusb-otg-phy-init-seq = <0x06 0x82 0xffffffff>;
qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
qcom,hsusb-otg-mode = <3>; /* OTG mode */
qcom,hsusb-otg-otg-control = <2>; /* PMIC */
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index be6ab79..fa218ca 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -27,6 +27,7 @@
#include "dsi-panel-hx83100a-800p-video.dtsi"
#include "dsi-panel-boent51021-1200p-video.dtsi"
#include "dsi-panel-hx8394d-wxga-video.dtsi"
+#include "dsi-panel-inxnt51021-1200p-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -187,9 +188,17 @@
};
&dsi_hx8394d_kingdisplay_vid {
- qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 19 02 03 01 03 04 a0
- 1c 07 02 03 01 03 04 a0];
+ qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 19 02 03 01 03 04 a0
+ 1c 07 02 03 01 03 04 a0];
+};
+
+&dsi_inxnt51021_1200p_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 20 08 0A 06 03 04 a0
+ 25 1D 08 0A 06 03 04 a0];
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index c58d82e..72513e1 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -466,6 +466,34 @@
};
};
+ ext_amp_ctrl {
+ label = "ext_amp_ctrl";
+ ext_amp_ctrl_active: ext_amp_ctrl_active {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio68";
+ drive-strength = <8>; /* 8 MA */
+ bias-pull-up; /* PULL UP */
+ output-high;
+ };
+ };
+
+ ext_amp_ctrl_sleep: ext_amp_ctrl_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+ configs {
+ pins = "gpio68";
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+ };
+
cdc_dmic0_clk_act: cdc_dmic0_clk_act_default {
mux {
pins = "gpio89";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index 63bb25f..0d47ba6 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -138,15 +138,13 @@
};
};
-&soc {
- qcom,dsi-display@17 {
- qcom,dsi-display-active;
+&ext_dsi_bridge_display {
+ qcom,dsi-display-active;
- ports {
- port@0 {
- endpoint {
- remote-endpoint = <<9611_in>;
- };
+ ports {
+ port@0 {
+ endpoint {
+ remote-endpoint = <<9611_in>;
};
};
};
@@ -184,6 +182,8 @@
"MIC BIAS External2", "Digital Mic3",
"DMIC4", "MIC BIAS External2",
"MIC BIAS External2", "Digital Mic4",
+ "MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+ "VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
"PDM_IN_RX1", "PDM_OUT_RX1",
"PDM_IN_RX2", "PDM_OUT_RX2",
"PDM_IN_RX3", "PDM_OUT_RX3",
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
new file mode 100644
index 0000000..622230c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QCS605 LC SoC Ipcam base";
+ compatible = "qcom,qcs605";
+ qcom,board-id = <0 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
index c7912d6..0cb7c33 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
@@ -26,5 +26,5 @@
model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
qcom,msm-id = <347 0x0>;
- qcom,board-id = <8 6>;
+ qcom,board-id = <0x020208 4>;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
index 90dcd7b..37dc8e0 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
@@ -20,5 +20,5 @@
/ {
model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
- qcom,board-id = <8 6>;
+ qcom,board-id = <0x020208 4>;
};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
index d6d9a17..51e9e1b 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
@@ -194,3 +194,7 @@
&wcd9335 {
/delete-property/ cdc-vdd-mic-bias-supply;
};
+
+&int_codec {
+ status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
index 654f3a1..99bf1e5 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
@@ -10,9 +10,45 @@
* GNU General Public License for more details.
*/
+#include "dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi"
#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
&soc {
+
+ dsi_panel_pwr_supply: dsi_panel_pwr_supply {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,panel-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "vddio";
+ qcom,supply-min-voltage = <1800000>;
+ qcom,supply-max-voltage = <1800000>;
+ qcom,supply-enable-load = <62000>;
+ qcom,supply-disable-load = <80>;
+ qcom,supply-post-on-sleep = <20>;
+ };
+
+ qcom,panel-supply-entry@1 {
+ reg = <1>;
+ qcom,supply-name = "lab";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@2 {
+ reg = <2>;
+ qcom,supply-name = "ibb";
+ qcom,supply-min-voltage = <4600000>;
+ qcom,supply-max-voltage = <6000000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ qcom,supply-post-on-sleep = <20>;
+ };
+ };
+
ext_dsi_bridge_display: qcom,dsi-display@0 {
compatible = "qcom,dsi-display";
label = "ext_dsi_bridge_display";
@@ -36,6 +72,28 @@
};
};
+ dsi_dual_nt35597_truly_video_display: qcom,dsi-display@1 {
+ compatible = "qcom,dsi-display";
+ label = "dsi_dual_nt35597_truly_video_display";
+ qcom,display-type = "primary";
+
+ qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+ qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+ clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+ <&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+ clock-names = "src_byte_clk", "src_pixel_clk";
+
+ pinctrl-names = "panel_active", "panel_suspend";
+ pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+ pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 93 0>;
+ qcom,panel-mode-gpio = <&tlmm 76 0>;
+ qcom,platform-en-gpio = <&tlmm 121 0>;
+
+ qcom,dsi-panel = <&dsi_dual_nt35597_truly_video>;
+ vddio-supply = <&pm660_l13>;
+ };
+
sde_wb: qcom,wb-display@0 {
compatible = "qcom,wb-display";
cell-index = <0>;
@@ -51,6 +109,32 @@
};
};
+&dsi_dual_nt35597_truly_video {
+ qcom,mdss-dsi-t-clk-post = <0x0D>;
+ qcom,mdss-dsi-t-clk-pre = <0x2D>;
+ qcom,mdss-dsi-min-refresh-rate = <53>;
+ qcom,mdss-dsi-max-refresh-rate = <60>;
+ qcom,mdss-dsi-pan-enable-dynamic-fps;
+ qcom,mdss-dsi-pan-fps-update =
+ "dfps_immediate_porch_mode_vfp";
+ qcom,esd-check-enabled;
+ qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+ qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+ qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-panel-status-value = <0x9c>;
+ qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+ qcom,mdss-dsi-panel-status-read-length = <1>;
+ qcom,mdss-dsi-display-timings {
+ timing@0{
+ qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+ 07 05 03 04 00];
+ qcom,display-topology = <2 0 2>,
+ <1 0 2>;
+ qcom,default-topology-index = <0>;
+ };
+ };
+};
+
&mdss_dsi0 {
vdda-1p2-supply = <&pm660_l2>;
};
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
index 378c4a1..d89a60e 100644
--- a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -91,3 +91,8 @@
qcom,afe-power-off-delay-us = <6>;
};
};
+
+&qupv3_se5_i2c {
+ status = "disabled";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
index eae8c56..2987d67 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
@@ -30,7 +30,7 @@
cell-index = <1>;
reg = <0x1>;
compatible = "qcom,actuator";
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
cam_vaf-supply = <&pm8953_l17>;
qcom,cam-vreg-name = "cam_vaf";
qcom,cam-vreg-min-voltage = <2850000>;
@@ -156,6 +156,43 @@
qcom,clock-rates = <19200000 0>;
};
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ compatible = "qcom,eeprom";
+ qcom,cci-master = <1>;
+ reg = <0x2>;
+ cam_vdig-supply = <&pm8953_l3>;
+ cam_vana-supply = <&pm8953_l22>;
+ cam_vio-supply = <&pm8953_l6>;
+ cam_vaf-supply = <&pm8953_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
qcom,camera@0 {
cell-index = <0>;
compatible = "qcom,camera";
@@ -249,9 +286,9 @@
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
- qcom,eeprom-src = <&eeprom1>;
+ qcom,eeprom-src = <&eeprom2>;
qcom,actuator-src = <&actuator1>;
- cam_vdig-supply = <&pm8953_l23>;
+ cam_vdig-supply = <&pm8953_l3>;
cam_vana-supply = <&pm8953_l22>;
cam_vio-supply = <&pm8953_l6>;
cam_vaf-supply = <&pm8953_l17>;
@@ -278,7 +315,7 @@
"CAM_STANDBY2";
qcom,sensor-position = <1>;
qcom,sensor-mode = <0>;
- qcom,cci-master = <0>;
+ qcom,cci-master = <1>;
status = "ok";
clocks = <&clock_gcc clk_mclk2_clk_src>,
<&clock_gcc clk_gcc_camss_mclk2_clk>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index 9067bc9..ef8ea1f3 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -238,6 +238,18 @@
};
};
+&modem_mem {
+ reg = <0x0 0x86800000 0x0 0x5500000>;
+};
+
+&adsp_fw_mem {
+ reg = <0x0 0x8bd00000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+ reg = <0x0 0x8ce00000 0x0 0x700000>;
+};
+
&soc {
pil_gpu: qcom,kgsl-hyp {
compatible = "qcom,pil-tz-generic";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
index 4d6b32f..f55c050 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
@@ -124,6 +124,8 @@
"MIC BIAS External", "Digital Mic3",
"DMIC4", "MIC BIAS External",
"MIC BIAS External", "Digital Mic4",
+ "MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+ "VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT",
"PDM_IN_RX1", "PDM_OUT_RX1",
@@ -501,12 +503,22 @@
qcom,cdc-vdd-mic-bias-voltage = <3088000 3088000>;
qcom,cdc-vdd-mic-bias-current = <5000>;
+ cdc-vdda18-l10-supply = <&pm660_l10>;
+ qcom,cdc-vdda18-l10-voltage = <1800000 1800000>;
+ qcom,cdc-vdda18-l10-current = <30000>;
+
+ cdc-vdd-l1-supply = <&pm660l_l1>;
+ qcom,cdc-vdd-l1-voltage = <880000 880000>;
+ qcom,cdc-vdd-l1-current = <30000>;
+
qcom,cdc-mclk-clk-rate = <9600000>;
qcom,cdc-static-supplies = "cdc-vdda-cp",
"cdc-vdd-pa";
- qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias",
+ "cdc-vdda18-l10",
+ "cdc-vdd-l1";
/*
* Not marking address @ as driver searches this child
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
index 5ff2c32..2b6b641 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
@@ -195,6 +195,8 @@
"AMIC1", "MIC BIAS External",
"MIC BIAS External", "Secondary Mic",
"AMIC3", "MIC BIAS External",
+ "MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+ "VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
"SpkrLeft IN", "SPK1 OUT",
"PDM_IN_RX1", "PDM_OUT_RX1",
"PDM_IN_RX2", "PDM_OUT_RX2",
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index bb07c04..5c40ecc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1875,7 +1875,7 @@
ufs-qcom-crypto = <&ufs_ice>;
lanes-per-direction = <1>;
- spm-level = <5>;
+
dev-ref-clk-freq = <0>; /* 19.2 MHz */
clock-names =
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
index 71566d0..6052074 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
@@ -493,6 +493,48 @@
clock-rates = <24000000>;
};
+ eeprom_depth: qcom,eeprom@4 {
+ cell-index = <4>;
+ reg = <0x4>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>; /* checked, MTP845 */
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_eyetracking_force>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <0 3312000 1050000 0>;
+ rgltr-max-voltage = <0 3600000 1050000 0>;
+ rgltr-load-current = <0 80000 105000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_depth_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_depth_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 23 0>,
+ <&tlmm 24 0>;
+ gpio-reset = <1>; //RESET
+ gpio-vana = <2>;
+ gpio-vdig = <3>;
+ gpio-req-tbl-num = <0 1 2 3> ;
+ gpio-req-tbl-flags = <1 0 0 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1",
+ "CAM_VDIG1";
+ sensor-position = <0>;
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
qcom,cam-sensor@4 {
cell-index = <4>;
compatible = "qcom,cam-sensor";
@@ -501,6 +543,7 @@
sensor-position-roll = <270>; /* checked, MTP845 */
sensor-position-pitch = <0>; /* checked, MTP845 */
sensor-position-yaw = <180>; /* checked, MTP845 */
+ eeprom-src = <&eeprom_depth>;
cam_vio-supply = <&pm8998_lvs1>; /* checked, MTP845 */
cam_vana-supply = <&pmi8998_bob>;
cam_vdig-supply = <&camera_eyetracking_force>;
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
index 270aa0e..8e543ff 100644
--- a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
@@ -12,3 +12,20 @@
*/
#include "qcs605-lc-mtp.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+&sde_dsi_active {
+ pins = "gpio93", "gpio121", "gpio76";
+};
+
+&sde_dsi_suspend {
+ pins = "gpio93", "gpio121", "gpio76";
+};
+
+&sde_te_active {
+ pins = "gpio10";
+};
+
+&sde_te_suspend {
+ pins = "gpio10";
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
index 1413e2c..c5d393c 100644
--- a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
@@ -18,3 +18,33 @@
compatible = "qcom,sxr1120";
qcom,msm-id = <370 0x0>;
};
+
+&soc {
+ qcom,qbt1000 {
+ /delete-property/ qcom,ipc-gpio;
+ };
+};
+
+&ext_dsi_bridge_display {
+ /delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+ /delete-property/ bridges;
+ #cooling-cells = <2>;
+};
+
+&dsi_dual_nt35597_truly_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 76 0>;
+ qcom,platform-reset-gpio = <&tlmm 93 0>;
+ qcom,platform-en-gpio = <&tlmm 121 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+ qcom,dsi-display-active;
+};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 6420837..385714b 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -72,6 +72,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -315,6 +316,7 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 4040863..cbf89b2 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -75,6 +75,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -321,6 +322,7 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_FT5X06=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f3c1e7b..698857a 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -73,6 +73,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 8401173c..6434a8e 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -76,6 +76,7 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 0c54182..358b37b 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -516,6 +516,8 @@
CONFIG_QCOM_LLCC_PERFMON=m
CONFIG_MSM_SERVICE_LOCATOR=y
CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_EUD=y
CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index ab983e0..c9f60b5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -528,6 +528,8 @@
CONFIG_QCOM_LLCC_PERFMON=m
CONFIG_MSM_SERVICE_LOCATOR=y
CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
diff --git a/block/blk-core.c b/block/blk-core.c
index 404629f..ff2e4fd 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1529,6 +1529,7 @@
bio->bi_next = req->bio;
req->bio = bio;
+ WARN_ON(req->__dun || bio->bi_iter.bi_dun);
req->__sector = bio->bi_iter.bi_sector;
req->__data_len += bio->bi_iter.bi_size;
req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
@@ -1644,6 +1645,7 @@
req->errors = 0;
req->__sector = bio->bi_iter.bi_sector;
+ req->__dun = bio->bi_iter.bi_dun;
req->ioprio = bio_prio(bio);
blk_rq_bio_prep(req->q, req, bio);
}
@@ -2646,8 +2648,11 @@
req->__data_len -= total_bytes;
/* update sector only for requests with clear definition of sector */
- if (req->cmd_type == REQ_TYPE_FS)
+ if (req->cmd_type == REQ_TYPE_FS) {
req->__sector += total_bytes >> 9;
+ if (req->__dun)
+ req->__dun += total_bytes >> 12;
+ }
/* mixed attributes always follow the first bio */
if (req->cmd_flags & REQ_MIXED_MERGE) {
@@ -3048,6 +3053,7 @@
(src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE);
dst->cmd_type = src->cmd_type;
dst->__sector = blk_rq_pos(src);
+ dst->__dun = blk_rq_dun(src);
dst->__data_len = blk_rq_bytes(src);
dst->nr_phys_segments = src->nr_phys_segments;
dst->ioprio = src->ioprio;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index f44daa1..c71d1cb 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -876,6 +876,8 @@
int blk_try_merge(struct request *rq, struct bio *bio)
{
+ if (blk_rq_dun(rq) || bio_dun(bio))
+ return ELEVATOR_NO_MERGE;
if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
return ELEVATOR_BACK_MERGE;
else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector)
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b7e61c8..f60978be 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -61,7 +61,9 @@
#define FASTRPC_ENOSUCH 39
#define VMID_SSC_Q6 5
#define VMID_ADSP_Q6 6
-#define DEBUGFS_SIZE 1024
+#define DEBUGFS_SIZE 3072
+#define UL_SIZE 25
+#define PID_SIZE 10
#define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME "audio_pdr_adsprpc"
#define AUDIO_PDR_ADSP_SERVICE_NAME "avs/audio"
@@ -313,6 +315,7 @@
unsigned int latency;
bool glink;
bool legacy;
+ bool secure_flag;
spinlock_t ctxlock;
struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX];
};
@@ -394,6 +397,7 @@
int refcount;
/* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
int dev_minor;
+ char *debug_buf;
};
static struct fastrpc_apps gfa;
@@ -2781,6 +2785,7 @@
spin_lock(&fl->apps->hlock);
hlist_del_init(&fl->hn);
spin_unlock(&fl->apps->hlock);
+ kfree(fl->debug_buf);
if (!fl->sctx) {
kfree(fl);
@@ -2966,101 +2971,225 @@
static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
size_t count, loff_t *position)
{
+ struct fastrpc_apps *me = &gfa;
struct fastrpc_file *fl = filp->private_data;
struct hlist_node *n;
struct fastrpc_buf *buf = NULL;
struct fastrpc_mmap *map = NULL;
+ struct fastrpc_mmap *gmaps = NULL;
struct smq_invoke_ctx *ictx = NULL;
- struct fastrpc_channel_ctx *chan;
- struct fastrpc_session_ctx *sess;
+ struct fastrpc_channel_ctx *chan = NULL;
unsigned int len = 0;
- int i, j, ret = 0;
+ int i, j, sess_used = 0, ret = 0;
char *fileinfo = NULL;
+ char single_line[UL_SIZE] = "----------------";
+ char title[UL_SIZE] = "=========================";
fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL);
if (!fileinfo)
goto bail;
if (fl == NULL) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s %s %s\n", title, " CHANNEL INFO ", title);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-8s|%-9s|%-9s|%-14s|%-9s|%-13s\n",
+ "susbsys", "refcount", "sesscount", "issubsystemup",
+ "ssrcount", "session_used");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "-%s%s%s%s-\n", single_line, single_line,
+ single_line, single_line);
for (i = 0; i < NUM_CHANNELS; i++) {
+ sess_used = 0;
chan = &gcinfo[i];
len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len, "%s\n\n",
- chan->name);
+ DEBUGFS_SIZE - len, "%-8s", chan->subsys);
len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len, "%s %d\n",
- "secure:", chan->secure);
+ DEBUGFS_SIZE - len, "|%-9d",
+ chan->kref.refcount.counter);
len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len, "%s %d\n",
- "sesscount:", chan->sesscount);
+ DEBUGFS_SIZE - len, "|%-9d",
+ chan->sesscount);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "|%-14d",
+ chan->issubsystemup);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "|%-9d",
+ chan->ssrcount);
for (j = 0; j < chan->sesscount; j++) {
- sess = &chan->session[j];
- len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len,
- "%s%d\n\n", "SESSION", j);
- len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len,
- "%s %d\n", "sid:",
- sess->smmu.cb);
- len += scnprintf(fileinfo + len,
- DEBUGFS_SIZE - len,
- "%s %d\n", "SECURE:",
- sess->smmu.secure);
- }
+ sess_used += chan->session[j].used;
+ }
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "|%-13d\n", sess_used);
+
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s%s%s\n", "=============",
+ " CMA HEAP ", "==============");
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "%-20s|%-20s\n", "addr", "size");
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "--%s%s---\n",
+ single_line, single_line);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "0x%-18llX", me->range.addr);
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len, "|0x%-18llX\n", me->range.size);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n==========%s %s %s===========\n",
+ title, " GMAPS ", title);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-20s|%-20s|%-20s\n",
+ "fd", "phys", "size", "va");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n", single_line, single_line,
+ single_line, single_line, single_line);
+ hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n",
+ gmaps->fd, gmaps->phys,
+ (uint32_t)gmaps->size,
+ gmaps->va);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-20s|%-20s|%-20s\n",
+ "len", "refs", "raddr", "flags");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n", single_line, single_line,
+ single_line, single_line, single_line);
+ hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "0x%-18X|%-20d|%-20lu|%-20u\n",
+ (uint32_t)gmaps->len, gmaps->refs,
+ gmaps->raddr, gmaps->flags);
}
} else {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %d\n\n",
- "PROCESS_ID:", fl->tgid);
+ "\n%s %13s %d\n", "cid", ":", fl->cid);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %d\n\n",
- "CHANNEL_ID:", fl->cid);
+ "%s %12s %d\n", "tgid", ":", fl->tgid);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %d\n\n",
- "SSRCOUNT:", fl->ssrcount);
+ "%s %7s %d\n", "sessionid", ":", fl->sessionid);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %d\n\n",
- "DEV_MINOR:", fl->dev_minor);
+ "%s %8s %d\n", "ssrcount", ":", fl->ssrcount);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s\n",
- "LIST OF BUFS:");
- spin_lock(&fl->hlock);
- hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
- len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %pK %s %pK %s %llx\n", "buf:",
- buf, "buf->virt:", buf->virt,
- "buf->phys:", buf->phys);
- }
+ "%s %8s %d\n", "refcount", ":", fl->refcount);
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "\n%s\n",
- "LIST OF MAPS:");
+ "%s %14s %d\n", "pd", ":", fl->pd);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %9s %s\n", "spdname", ":", fl->spdname);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %6s %d\n", "file_close", ":", fl->file_close);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %8s %d\n", "sharedcb", ":", fl->sharedcb);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %9s %d\n", "profile", ":", fl->profile);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %3s %d\n", "smmu.coherent", ":",
+ fl->sctx->smmu.coherent);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %4s %d\n", "smmu.enabled", ":",
+ fl->sctx->smmu.enabled);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %9s %d\n", "smmu.cb", ":", fl->sctx->smmu.cb);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %5s %d\n", "smmu.secure", ":",
+ fl->sctx->smmu.secure);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %5s %d\n", "smmu.faults", ":",
+ fl->sctx->smmu.faults);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s %s %d\n", "link.link_state",
+ ":", *&me->channel[fl->cid].link.link_state);
+
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n=======%s %s %s======\n", title,
+ " LIST OF MAPS ", title);
+
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-20s|%-20s\n", "va", "phys", "size");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n",
+ single_line, single_line, single_line,
+ single_line, single_line);
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
- len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %pK %s %lx %s %llx\n",
- "map:", map,
- "map->va:", map->va,
- "map->phys:", map->phys);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "0x%-20lX|0x%-20llX|0x%-20zu\n\n",
+ map->va, map->phys,
+ map->size);
}
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "\n%s\n",
- "LIST OF PENDING SMQCONTEXTS:");
+ "%-20s|%-20s|%-20s|%-20s\n",
+ "len", "refs",
+ "raddr", "uncached");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n",
+ single_line, single_line, single_line,
+ single_line, single_line);
+ hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20zu|%-20d|0x%-20lX|%-20d\n\n",
+ map->len, map->refs, map->raddr,
+ map->uncached);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-20s\n", "secure", "attr");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n",
+ single_line, single_line, single_line,
+ single_line, single_line);
+ hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20d|0x%-20lX\n\n",
+ map->secure, map->attr);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n======%s %s %s======\n", title,
+ " LIST OF BUFS ", title);
+ spin_lock(&fl->hlock);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-19s|%-19s|%-19s\n",
+ "virt", "phys", "size");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n", single_line, single_line,
+ single_line, single_line, single_line);
+ hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+ len += scnprintf(fileinfo + len,
+ DEBUGFS_SIZE - len,
+ "0x%-17p|0x%-17llX|%-19zu\n",
+ buf->virt, (uint64_t)buf->phys, buf->size);
+ }
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "\n%s %s %s\n", title,
+ " LIST OF PENDING SMQCONTEXTS ", title);
+
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-10s|%-10s|%-10s|%-20s\n",
+ "sc", "pid", "tgid", "used", "ctxid");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n", single_line, single_line,
+ single_line, single_line, single_line);
hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %pK %s %u %s %u %s %u\n",
- "smqcontext:", ictx,
- "sc:", ictx->sc,
- "tid:", ictx->pid,
- "handle", ictx->rpra->h);
+ "0x%-18X|%-10d|%-10d|%-10zu|0x%-20llX\n\n",
+ ictx->sc, ictx->pid, ictx->tgid,
+ ictx->used, ictx->ctxid);
}
+
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "\n%s\n",
- "LIST OF INTERRUPTED SMQCONTEXTS:");
+ "\n%s %s %s\n", title,
+ " LIST OF INTERRUPTED SMQCONTEXTS ", title);
+
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20s|%-10s|%-10s|%-10s|%-20s\n",
+ "sc", "pid", "tgid", "used", "ctxid");
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%s%s%s%s%s\n", single_line, single_line,
+ single_line, single_line, single_line);
hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
- len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %pK %s %u %s %u %s %u\n",
- "smqcontext:", ictx,
- "sc:", ictx->sc,
- "tid:", ictx->pid,
- "handle", ictx->rpra->h);
+ len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+ "%-20u|%-20d|%-20d|%-20zu|0x%-20llX\n\n",
+ ictx->sc, ictx->pid, ictx->tgid,
+ ictx->used, ictx->ctxid);
}
spin_unlock(&fl->hlock);
}
@@ -3155,6 +3284,8 @@
struct dentry *debugfs_file;
struct fastrpc_file *fl = NULL;
struct fastrpc_apps *me = &gfa;
+ char strpid[PID_SIZE];
+ int buf_size = 0;
/*
* Indicates the device node opened
@@ -3172,8 +3303,14 @@
VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL)));
if (err)
return err;
- debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root,
- fl, &debugfs_fops);
+ snprintf(strpid, PID_SIZE, "%d", current->pid);
+ buf_size = strlen(current->comm) + strlen(strpid) + 1;
+ fl->debug_buf = kzalloc(buf_size, GFP_KERNEL);
+ snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d",
+ current->comm, "_", current->pid);
+ debugfs_file = debugfs_create_file(fl->debug_buf, 0644,
+ debugfs_root, fl, &debugfs_fops);
+
context_list_ctor(&fl->clst);
spin_lock_init(&fl->hlock);
INIT_HLIST_HEAD(&fl->maps);
@@ -3215,7 +3352,8 @@
if (err)
goto bail;
/* Check to see if the device node is non-secure */
- if (fl->dev_minor == MINOR_NUM_DEV) {
+ if (fl->dev_minor == MINOR_NUM_DEV &&
+ fl->apps->secure_flag == true) {
/*
* For non secure device node check and make sure that
* the channel allows non-secure access
@@ -3863,10 +4001,13 @@
VERIFY(err, !of_property_read_u32(dev->of_node,
"qcom,secure-domains",
&secure_domains));
- if (!err)
+ if (!err) {
+ me->secure_flag = true;
configure_secure_channels(secure_domains);
- else
+ } else {
+ me->secure_flag = false;
pr_info("adsprpc: unable to read the domain configuration from dts\n");
+ }
}
}
if (of_device_is_compatible(dev->of_node,
@@ -4016,11 +4157,12 @@
struct device *secure_dev = NULL;
int err = 0, i;
+ debugfs_root = debugfs_create_dir("adsprpc", NULL);
memset(me, 0, sizeof(*me));
-
fastrpc_init(me);
me->dev = NULL;
me->glink = true;
+ me->secure_flag = false;
VERIFY(err, 0 == platform_driver_register(&fastrpc_driver));
if (err)
goto register_bail;
@@ -4073,12 +4215,11 @@
gcinfo[i].subsys,
&me->channel[i].nb);
}
-
me->client = msm_ion_client_create(DEVICE_NAME);
VERIFY(err, !IS_ERR_OR_NULL(me->client));
if (err)
goto device_create_bail;
- debugfs_root = debugfs_create_dir("adsprpc", NULL);
+
return 0;
device_create_bail:
for (i = 0; i < NUM_CHANNELS; i++) {
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index e692f660..3c75997 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -83,7 +83,7 @@
};
static struct system_pm_ops *sys_pm_ops;
-
+static DEFINE_SPINLOCK(bc_timer_lock);
struct lpm_cluster *lpm_root_node;
@@ -1029,6 +1029,7 @@
struct lpm_cluster_level *level = &cluster->levels[idx];
struct cpumask online_cpus, cpumask;
unsigned int cpu;
+ int ret = 0;
cpumask_and(&online_cpus, &cluster->num_children_in_sync,
cpu_online_mask);
@@ -1067,9 +1068,13 @@
clear_predict_history();
clear_cl_predict_history();
- if (sys_pm_ops && sys_pm_ops->enter)
- if ((sys_pm_ops->enter(&cpumask)))
+ if (sys_pm_ops && sys_pm_ops->enter) {
+ spin_lock(&bc_timer_lock);
+ ret = sys_pm_ops->enter(&cpumask);
+ spin_unlock(&bc_timer_lock);
+ if (ret)
return -EBUSY;
+ }
}
/* Notify cluster enter event after successfully config completion */
cluster_notify(cluster, level, true);
@@ -1202,8 +1207,11 @@
level = &cluster->levels[cluster->last_level];
if (level->notify_rpm)
- if (sys_pm_ops && sys_pm_ops->exit)
+ if (sys_pm_ops && sys_pm_ops->exit) {
+ spin_lock(&bc_timer_lock);
sys_pm_ops->exit();
+ spin_unlock(&bc_timer_lock);
+ }
update_debug_pc_event(CLUSTER_EXIT, cluster->last_level,
cluster->num_children_in_sync.bits[0],
@@ -1298,6 +1306,7 @@
{
int affinity_level = 0, state_id = 0, power_state = 0;
bool success = false;
+ int ret = 0;
/*
* idx = 0 is the default LPM state
*/
@@ -1310,7 +1319,17 @@
}
if (from_idle && cpu->levels[idx].use_bc_timer) {
- if (tick_broadcast_enter())
+ /*
+ * tick_broadcast_enter can change the affinity of the
+ * broadcast timer interrupt, during which interrupt will
+ * be disabled and enabled back. To avoid system pm ops
+ * doing any interrupt state save or restore in between
+ * this window hold the lock.
+ */
+ spin_lock(&bc_timer_lock);
+ ret = tick_broadcast_enter();
+ spin_unlock(&bc_timer_lock);
+ if (ret)
return success;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c5a1a9f..9e251da 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1161,7 +1161,7 @@
goto error;
}
- if (copy_to_user(user_buf, buf, len)) {
+ if (copy_to_user(user_buf, buf, max_len)) {
rc = -EFAULT;
goto error;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index bf511e3..85b92f59 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -1559,14 +1559,14 @@
return rc;
error_free_payloads:
for (i = i - 1; i >= 0; i--) {
- cmd--;
- kfree(cmd->msg.tx_buf);
+ kfree(cmd[i].msg.tx_buf);
+ cmd[i].msg.tx_buf = NULL;
}
return rc;
}
-static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
+static void dsi_panel_destroy_cmds_packets_buf(struct dsi_panel_cmd_set *set)
{
u32 i = 0;
struct dsi_cmd_desc *cmd;
@@ -1574,12 +1574,15 @@
for (i = 0; i < set->count; i++) {
cmd = &set->cmds[i];
kfree(cmd->msg.tx_buf);
+ cmd->msg.tx_buf = NULL;
}
}
-static void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set)
+static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
{
+ dsi_panel_destroy_cmds_packets_buf(set);
kfree(set->cmds);
+ set->count = 0;
}
static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
@@ -3163,12 +3166,13 @@
if (!mode->priv_info)
return;
- for (i = 0; i < DSI_CMD_SET_MAX; i++) {
+ kfree(mode->priv_info->phy_timing_val);
+
+ for (i = 0; i < DSI_CMD_SET_MAX; i++)
dsi_panel_destroy_cmd_packets(&mode->priv_info->cmd_sets[i]);
- dsi_panel_dealloc_cmd_packets(&mode->priv_info->cmd_sets[i]);
- }
kfree(mode->priv_info);
+ mode->priv_info = NULL;
}
int dsi_panel_get_mode(struct dsi_panel *panel,
@@ -3370,7 +3374,7 @@
panel->name, rc);
}
- dsi_panel_destroy_cmd_packets(set);
+ dsi_panel_destroy_cmds_packets_buf(set);
error:
mutex_unlock(&panel->panel_lock);
return rc;
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index ddd4607..00f9707 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -80,6 +80,9 @@
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ if (obj->import_attach)
+ return msm_obj->pages;
+
if (!msm_obj->pages) {
struct drm_device *dev = obj->dev;
struct page **p;
@@ -572,8 +575,13 @@
struct page **pages = get_pages(obj);
if (IS_ERR(pages))
return ERR_CAST(pages);
- msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
+ if (obj->import_attach)
+ msm_obj->vaddr = dma_buf_vmap(
+ obj->import_attach->dmabuf);
+ else
+ msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+
if (msm_obj->vaddr == NULL)
return ERR_PTR(-ENOMEM);
}
@@ -659,7 +667,11 @@
if (!msm_obj->vaddr || WARN_ON(!is_vunmapable(msm_obj)))
return;
- vunmap(msm_obj->vaddr);
+ if (obj->import_attach)
+ dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr);
+ else
+ vunmap(msm_obj->vaddr);
+
msm_obj->vaddr = NULL;
}
@@ -1012,7 +1024,7 @@
struct msm_gem_object *msm_obj;
struct drm_gem_object *obj = NULL;
uint32_t size;
- int ret, npages;
+ int ret;
/* if we don't have IOMMU, don't bother pretending we can import: */
if (!iommu_present(&platform_bus_type)) {
@@ -1033,19 +1045,9 @@
drm_gem_private_object_init(dev, obj, size);
- npages = size / PAGE_SIZE;
-
msm_obj = to_msm_bo(obj);
msm_obj->sgt = sgt;
- msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
- if (!msm_obj->pages) {
- ret = -ENOMEM;
- goto fail;
- }
-
- ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);
- if (ret)
- goto fail;
+ msm_obj->pages = NULL;
return obj;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 763993c8..e7b7a6e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -259,6 +259,7 @@
struct kthread_work input_event_work;
struct kthread_work esd_trigger_work;
struct input_handler *input_handler;
+ bool input_handler_registered;
struct msm_display_topology topology;
bool vblank_enabled;
@@ -743,6 +744,7 @@
if (sde_enc->input_handler) {
kfree(sde_enc->input_handler);
sde_enc->input_handler = NULL;
+ sde_enc->input_handler_registered = false;
}
kfree(sde_enc);
@@ -2634,6 +2636,7 @@
input_handler->private = sde_enc;
sde_enc->input_handler = input_handler;
+ sde_enc->input_handler_registered = false;
return rc;
}
@@ -2755,12 +2758,14 @@
return;
}
- if (sde_enc->input_handler) {
+ if (sde_enc->input_handler && !sde_enc->input_handler_registered) {
ret = _sde_encoder_input_handler_register(
sde_enc->input_handler);
if (ret)
SDE_ERROR(
"input handler registration failed, rc = %d\n", ret);
+ else
+ sde_enc->input_handler_registered = true;
}
ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
@@ -2838,8 +2843,11 @@
SDE_EVT32(DRMID(drm_enc));
- if (sde_enc->input_handler)
+ if (sde_enc->input_handler && sde_enc->input_handler_registered) {
input_unregister_handler(sde_enc->input_handler);
+ sde_enc->input_handler_registered = false;
+ }
+
/* wait for idle */
sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 572dc40..d3bbea3 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -541,7 +541,7 @@
*/
spin_lock(&proc_priv->ctxt_count_lock);
if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) {
- KGSL_DRV_ERR(device,
+ KGSL_DRV_ERR_RATELIMIT(device,
"Per process context limit reached for pid %u",
dev_priv->process_priv->pid);
spin_unlock(&proc_priv->ctxt_count_lock);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index f8a987a..ee32e1a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -184,6 +184,15 @@
reporting the change in status of the KPDPWR_N line (connected to the
power-key) as well as reset features.
+config INPUT_QTI_HAPTICS
+ tristate "Haptics support for QTI PMIC"
+ depends on MFD_SPMI_PMIC
+ help
+ This option enables device driver support for the haptics peripheral
+ found on Qualcomm Technologies, Inc. PMICs. The haptics peripheral
+ is capable of driving both LRA and ERM vibrators. This module provides
+ haptic feedback for user actions such as a long press on the touch screen.
+
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
depends on PCI && SPARC64
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 149273c..c08ee8f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -61,6 +61,7 @@
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
obj-$(CONFIG_INPUT_QPNP_POWER_ON) += qpnp-power-on.o
+obj-$(CONFIG_INPUT_QTI_HAPTICS) += qti-haptics.o
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c
new file mode 100644
index 0000000..310eb41
--- /dev/null
+++ b/drivers/input/misc/qti-haptics.c
@@ -0,0 +1,1471 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+enum actutor_type {
+ ACT_LRA,
+ ACT_ERM,
+};
+
+enum lra_res_sig_shape {
+ RES_SIG_SINE,
+ RES_SIG_SQUARE,
+};
+
+enum lra_auto_res_mode {
+ AUTO_RES_MODE_ZXD,
+ AUTO_RES_MODE_QWD,
+};
+
+enum wf_src {
+ INT_WF_VMAX,
+ INT_WF_BUFFER,
+ EXT_WF_AUDIO,
+ EXT_WF_PWM,
+};
+
+enum haptics_custom_effect_param {
+ CUSTOM_DATA_EFFECT_IDX,
+ CUSTOM_DATA_TIMEOUT_SEC_IDX,
+ CUSTOM_DATA_TIMEOUT_MSEC_IDX,
+ CUSTOM_DATA_LEN,
+};
+
+/* common definitions */
+#define HAP_BRAKE_PATTERN_MAX 4
+#define HAP_WAVEFORM_BUFFER_MAX 8
+#define HAP_VMAX_MV_DEFAULT 1800
+#define HAP_VMAX_MV_MAX 3596
+#define HAP_ILIM_MA_DEFAULT 400
+#define HAP_ILIM_MA_MAX 800
+#define HAP_PLAY_RATE_US_DEFAULT 5715
+#define HAP_PLAY_RATE_US_MAX 20475
+#define HAP_PLAY_RATE_US_LSB 5
+#define VMAX_MIN_PLAY_TIME_US 20000
+#define HAP_SC_DET_MAX_COUNT 5
+#define HAP_SC_DET_TIME_US 1000000
+#define FF_EFFECT_COUNT_MAX 32
+
+/* haptics module register definitions */
+#define REG_HAP_STATUS1 0x0A
+#define HAP_SC_DET_BIT BIT(3)
+#define HAP_BUSY_BIT BIT(1)
+
+#define REG_HAP_EN_CTL1 0x46
+#define HAP_EN_BIT BIT(7)
+
+#define REG_HAP_EN_CTL2 0x48
+#define HAP_AUTO_STANDBY_EN_BIT BIT(1)
+#define HAP_BRAKE_EN_BIT BIT(0)
+
+#define REG_HAP_EN_CTL3 0x4A
+#define HAP_HBRIDGE_EN_BIT BIT(7)
+#define HAP_PWM_SIGNAL_EN_BIT BIT(6)
+#define HAP_ILIM_EN_BIT BIT(5)
+#define HAP_ILIM_CC_EN_BIT BIT(4)
+#define HAP_AUTO_RES_RBIAS_EN_BIT BIT(3)
+#define HAP_DAC_EN_BIT BIT(2)
+#define HAP_ZX_HYST_EN_BIT BIT(1)
+#define HAP_PWM_CTL_EN_BIT BIT(0)
+
+#define REG_HAP_AUTO_RES_CTRL 0x4B
+#define HAP_AUTO_RES_EN_BIT BIT(7)
+#define HAP_SEL_AUTO_RES_PERIOD BIT(6)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK GENMASK(5, 4)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT 4
+#define HAP_AUTO_RES_ERR_RECOVERY_BIT BIT(3)
+#define HAP_AUTO_RES_EN_DLY_MASK GENMASK(2, 0)
+#define AUTO_RES_CNT_ERR_DELTA(x) (x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
+#define AUTO_RES_EN_DLY(x) x
+
+#define REG_HAP_CFG1 0x4C
+#define REG_HAP_CFG2 0x4D
+#define HAP_LRA_RES_TYPE_BIT BIT(0)
+
+#define REG_HAP_SEL 0x4E
+#define HAP_WF_SOURCE_MASK GENMASK(5, 4)
+#define HAP_WF_SOURCE_SHIFT 4
+#define HAP_WF_TRIGGER_BIT BIT(0)
+#define HAP_WF_SOURCE_VMAX (0 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_BUFFER (1 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_AUDIO (2 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_PWM (3 << HAP_WF_SOURCE_SHIFT)
+
+#define REG_HAP_AUTO_RES_CFG 0x4F
+#define HAP_AUTO_RES_MODE_BIT BIT(7)
+#define HAP_AUTO_RES_MODE_SHIFT 7
+#define HAP_AUTO_RES_CAL_DURATON_MASK GENMASK(6, 5)
+#define HAP_CAL_EOP_EN_BIT BIT(3)
+#define HAP_CAL_PERIOD_MASK GENMASK(2, 0)
+#define HAP_CAL_OPT3_EVERY_8_PERIOD 2
+
+#define REG_HAP_SLEW_CFG 0x50
+#define REG_HAP_VMAX_CFG 0x51
+#define HAP_VMAX_SIGN_BIT BIT(7)
+#define HAP_VMAX_OVD_BIT BIT(6)
+#define HAP_VMAX_MV_MASK GENMASK(5, 1)
+#define HAP_VMAX_MV_SHIFT 1
+#define HAP_VMAX_MV_LSB 116
+
+#define REG_HAP_ILIM_CFG 0x52
+#define REG_HAP_SC_DEB_CFG 0x53
+#define REG_HAP_RATE_CFG1 0x54
+#define REG_HAP_RATE_CFG2 0x55
+#define REG_HAP_INTERNAL_PWM 0x56
+#define REG_HAP_EXTERNAL_PWM 0x57
+#define REG_HAP_PWM 0x58
+
+#define REG_HAP_SC_CLR 0x59
+#define HAP_SC_CLR_BIT BIT(0)
+
+#define REG_HAP_ZX_CFG 0x5A
+#define HAP_ZX_DET_DEB_MASK GENMASK(2, 0)
+#define ZX_DET_DEB_10US 0
+#define ZX_DET_DEB_20US 1
+#define ZX_DET_DEB_40US 2
+#define ZX_DET_DEB_80US 3
+
+#define REG_HAP_BRAKE 0x5C
+#define HAP_BRAKE_PATTERN_MASK 0x3
+#define HAP_BRAKE_PATTERN_SHIFT 2
+
+#define REG_HAP_WF_REPEAT 0x5E
+#define HAP_WF_REPEAT_MASK GENMASK(6, 4)
+#define HAP_WF_REPEAT_SHIFT 4
+#define HAP_WF_S_REPEAT_MASK GENMASK(1, 0)
+
+#define REG_HAP_WF_S1 0x60
+#define HAP_WF_SIGN_BIT BIT(7)
+#define HAP_WF_OVD_BIT BIT(6)
+#define HAP_WF_AMP_BIT GENMASK(5, 1)
+#define HAP_WF_AMP_SHIFT 1
+
+#define REG_HAP_PLAY 0x70
+#define HAP_PLAY_BIT BIT(7)
+
+#define REG_HAP_SEC_ACCESS 0xD0
+
+struct qti_hap_effect {
+ int id;
+ u8 *pattern;
+ int pattern_length;
+ u16 play_rate_us;
+ u8 wf_repeat_n;
+ u8 wf_s_repeat_n;
+ u8 brake[HAP_BRAKE_PATTERN_MAX];
+ int brake_pattern_length;
+ bool brake_en;
+ bool lra_auto_res_disable;
+};
+
+struct qti_hap_play_info {
+ struct qti_hap_effect *effect;
+ u16 vmax_mv;
+ int length_us;
+ int playing_pos;
+ bool playing_pattern;
+};
+
+struct qti_hap_config {
+ enum actutor_type act_type;
+ enum lra_res_sig_shape lra_shape;
+ enum lra_auto_res_mode lra_auto_res_mode;
+ enum wf_src ext_src;
+ u16 vmax_mv;
+ u16 ilim_ma;
+ u16 play_rate_us;
+ bool lra_allow_variable_play_rate;
+ bool use_ext_wf_src;
+};
+
+struct qti_hap_chip {
+ struct platform_device *pdev;
+ struct device *dev;
+ struct regmap *regmap;
+ struct input_dev *input_dev;
+ struct pwm_device *pwm_dev;
+ struct qti_hap_config config;
+ struct qti_hap_play_info play;
+ struct qti_hap_effect *predefined;
+ struct qti_hap_effect constant;
+ struct regulator *vdd_supply;
+ struct hrtimer stop_timer;
+ spinlock_t bus_lock;
+ ktime_t last_sc_time;
+ int play_irq;
+ int sc_irq;
+ int effects_count;
+ int sc_det_count;
+ u16 reg_base;
+ bool perm_disable;
+ bool play_irq_en;
+ bool vdd_enabled;
+};
+
+static int wf_repeat[8] = {1, 2, 4, 8, 16, 32, 64, 128};
+static int wf_s_repeat[4] = {1, 2, 4, 8};
+
+static inline bool is_secure(u8 addr)
+{
+ return ((addr & 0xFF) > 0xD0);
+}
+
+static int qti_haptics_read(struct qti_hap_chip *chip,
+ u8 addr, u8 *val, int len)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+
+ rc = regmap_bulk_read(chip->regmap, chip->reg_base + addr, val, len);
+ if (rc < 0)
+ dev_err(chip->dev, "Reading addr 0x%x failed, rc=%d\n",
+ addr, rc);
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+ return rc;
+}
+
+static int qti_haptics_write(struct qti_hap_chip *chip,
+ u8 addr, u8 *val, int len)
+{
+ int rc = 0, i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+ if (is_secure(addr)) {
+ for (i = 0; i < len; i++) {
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + REG_HAP_SEC_ACCESS,
+ 0xA5);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+ rc);
+ goto unlock;
+ }
+
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + addr + i, val[i]);
+ if (rc < 0) {
+ dev_err(chip->dev, "write val 0x%x to addr 0x%x failed, rc=%d\n",
+ val[i], addr + i, rc);
+ goto unlock;
+ }
+ }
+ } else {
+ if (len > 1)
+ rc = regmap_bulk_write(chip->regmap,
+ chip->reg_base + addr, val, len);
+ else
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + addr, *val);
+
+ if (rc < 0)
+ dev_err(chip->dev, "write addr 0x%x failed, rc=%d\n",
+ addr, rc);
+ }
+
+ for (i = 0; i < len; i++)
+ dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x\n",
+ addr + i, val[i]);
+
+unlock:
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+ return rc;
+}
+
+static int qti_haptics_masked_write(struct qti_hap_chip *chip, u8 addr,
+ u8 mask, u8 val)
+{
+ int rc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->bus_lock, flags);
+ if (is_secure(addr)) {
+ rc = regmap_write(chip->regmap,
+ chip->reg_base + REG_HAP_SEC_ACCESS,
+ 0xA5);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+ rc);
+ goto unlock;
+ }
+ }
+
+ rc = regmap_update_bits(chip->regmap, chip->reg_base + addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
+ addr, val, mask, rc);
+
+ dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x\n",
+ addr, val, mask);
+unlock:
+ spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+ return rc;
+}
+
+static void construct_constant_waveform_in_pattern(
+ struct qti_hap_play_info *play)
+{
+ struct qti_hap_chip *chip = container_of(play,
+ struct qti_hap_chip, play);
+ struct qti_hap_config *config = &chip->config;
+ struct qti_hap_effect *effect = play->effect;
+ int total_samples, samples, left, magnitude, i, j, k;
+ int delta = INT_MAX, delta_min = INT_MAX;
+
+ /* Using play_rate_us in config for constant waveform */
+ effect->play_rate_us = config->play_rate_us;
+ total_samples = play->length_us / effect->play_rate_us;
+ left = play->length_us % effect->play_rate_us;
+
+ if (total_samples <= HAP_WAVEFORM_BUFFER_MAX) {
+ effect->pattern_length = total_samples;
+ effect->wf_s_repeat_n = 0;
+ effect->wf_repeat_n = 0;
+ } else {
+ /*
+ * Find a closest setting to achieve the constant waveform
+ * with the required length by using buffer waveform source:
+ * play_length_us = pattern_length * wf_s_repeat_n
+ * * wf_repeat_n * play_rate_us
+ */
+ for (i = 0; i < ARRAY_SIZE(wf_repeat); i++) {
+ for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++) {
+ for (k = 1; k <= HAP_WAVEFORM_BUFFER_MAX; k++) {
+ samples = k * wf_s_repeat[j] *
+ wf_repeat[i];
+ delta = abs(total_samples - samples);
+ if (delta < delta_min) {
+ delta_min = delta;
+ effect->pattern_length = k;
+ effect->wf_s_repeat_n = j;
+ effect->wf_repeat_n = i;
+ }
+ if (samples > total_samples)
+ break;
+ }
+ }
+ }
+ }
+
+ if (left > 0 && effect->pattern_length < HAP_WAVEFORM_BUFFER_MAX)
+ effect->pattern_length++;
+
+ play->length_us = effect->pattern_length * effect->play_rate_us;
+ dev_dbg(chip->dev, "total_samples = %d, pattern_length = %d, wf_s_repeat = %d, wf_repeat = %d\n",
+ total_samples, effect->pattern_length,
+ wf_s_repeat[effect->wf_s_repeat_n],
+ wf_repeat[effect->wf_repeat_n]);
+
+ for (i = 0; i < effect->pattern_length; i++) {
+ magnitude = play->vmax_mv / HAP_VMAX_MV_LSB;
+ effect->pattern[i] = (u8)magnitude << HAP_WF_AMP_SHIFT;
+ }
+}
+
+static int qti_haptics_config_wf_buffer(struct qti_hap_chip *chip)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_effect *effect = play->effect;
+ u8 addr, pattern[HAP_WAVEFORM_BUFFER_MAX] = {0};
+ int rc = 0;
+ size_t len;
+
+ if (play->playing_pos == effect->pattern_length) {
+ dev_dbg(chip->dev, "pattern playing done\n");
+ return 0;
+ }
+
+ if (effect->pattern_length - play->playing_pos
+ >= HAP_WAVEFORM_BUFFER_MAX)
+ len = HAP_WAVEFORM_BUFFER_MAX;
+ else
+ len = effect->pattern_length - play->playing_pos;
+
+ dev_dbg(chip->dev, "copy %d bytes start from %d\n",
+ (int)len, play->playing_pos);
+ memcpy(pattern, &effect->pattern[play->playing_pos], len);
+
+ play->playing_pos += len;
+
+ addr = REG_HAP_WF_S1;
+ rc = qti_haptics_write(chip, REG_HAP_WF_S1, pattern,
+ HAP_WAVEFORM_BUFFER_MAX);
+ if (rc < 0)
+ dev_err(chip->dev, "Program WF_SAMPLE failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_wf_repeat(struct qti_hap_chip *chip)
+{
+ struct qti_hap_effect *effect = chip->play.effect;
+ u8 addr, mask, val;
+ int rc = 0;
+
+ addr = REG_HAP_WF_REPEAT;
+ mask = HAP_WF_REPEAT_MASK | HAP_WF_S_REPEAT_MASK;
+ val = effect->wf_repeat_n << HAP_WF_REPEAT_SHIFT;
+ val |= effect->wf_s_repeat_n;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "Program WF_REPEAT failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_play(struct qti_hap_chip *chip, bool play)
+{
+ int rc = 0;
+ u8 val = play ? HAP_PLAY_BIT : 0;
+
+ rc = qti_haptics_write(chip,
+ REG_HAP_PLAY, &val, 1);
+ if (rc < 0)
+ dev_err(chip->dev, "%s playing haptics failed, rc=%d\n",
+ play ? "start" : "stop", rc);
+
+ return rc;
+}
+
+static int qti_haptics_module_en(struct qti_hap_chip *chip, bool en)
+{
+ int rc = 0;
+ u8 val = en ? HAP_EN_BIT : 0;
+
+ rc = qti_haptics_write(chip,
+ REG_HAP_EN_CTL1, &val, 1);
+ if (rc < 0)
+ dev_err(chip->dev, "%s haptics failed, rc=%d\n",
+ en ? "enable" : "disable", rc);
+
+
+ return rc;
+}
+
+static int qti_haptics_config_vmax(struct qti_hap_chip *chip, int vmax_mv)
+{
+ u8 addr, mask, val;
+ int rc;
+
+ addr = REG_HAP_VMAX_CFG;
+ mask = HAP_VMAX_MV_MASK;
+ val = (vmax_mv / HAP_VMAX_MV_LSB) << HAP_VMAX_MV_SHIFT;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "write VMAX_CFG failed, rc=%d\n",
+ rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_wf_src(struct qti_hap_chip *chip,
+ enum wf_src src)
+{
+ u8 addr, mask, val = 0;
+ int rc;
+
+ addr = REG_HAP_SEL;
+ mask = HAP_WF_SOURCE_MASK | HAP_WF_TRIGGER_BIT;
+ val = src << HAP_WF_SOURCE_SHIFT;
+ if (src == EXT_WF_AUDIO || src == EXT_WF_PWM)
+ val |= HAP_WF_TRIGGER_BIT;
+
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set HAP_SEL failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_play_rate_us(struct qti_hap_chip *chip,
+ int play_rate_us)
+{
+ u8 addr, val[2];
+ int tmp, rc;
+
+ addr = REG_HAP_RATE_CFG1;
+ tmp = play_rate_us / HAP_PLAY_RATE_US_LSB;
+ val[0] = tmp & 0xff;
+ val[1] = (tmp >> 8) & 0xf;
+ rc = qti_haptics_write(chip, addr, val, 2);
+ if (rc < 0)
+ dev_err(chip->dev, "write play_rate failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake)
+{
+ u8 addr, mask, val;
+ int i, rc;
+ bool en = true;
+
+ addr = REG_HAP_BRAKE;
+ for (val = 0, i = 0; i < HAP_BRAKE_PATTERN_MAX; i++)
+ val |= (brake[i] & HAP_BRAKE_PATTERN_MASK) <<
+ i * HAP_BRAKE_PATTERN_SHIFT;
+
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write brake pattern failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (val == 0)
+ en = false;
+
+ /* Set BRAKE_EN only if brake pattern is non-zero */
+ addr = REG_HAP_EN_CTL2;
+ mask = HAP_BRAKE_EN_BIT;
+ val = en;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set EN_CTL2 failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en)
+{
+ int rc;
+ u8 addr, val, mask;
+
+ addr = REG_HAP_AUTO_RES_CTRL;
+ mask = HAP_AUTO_RES_EN_BIT;
+ val = en ? HAP_AUTO_RES_EN_BIT : 0;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0)
+ dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_config *config = &chip->config;
+ int rc = 0;
+
+ rc = qti_haptics_module_en(chip, true);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Using VMAX waveform source if playing length is >= 20ms,
+ * otherwise using buffer waveform source and calculate the
+ * pattern length and repeating times to achieve accurate
+ * playing time accuracy.
+ */
+ if (play->length_us >= VMAX_MIN_PLAY_TIME_US) {
+ rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ /* Enable Auto-Resonance when VMAX wf-src is selected */
+ if (config->act_type == ACT_LRA) {
+ rc = qti_haptics_lra_auto_res_enable(chip, true);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Set WF_SOURCE to VMAX */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = false;
+ } else {
+ rc = qti_haptics_config_vmax(chip, config->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ play->effect = &chip->constant;
+ play->playing_pos = 0;
+ /* Format and config waveform in patterns */
+ construct_constant_waveform_in_pattern(play);
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ return rc;
+
+ /* Set WF_SOURCE to buffer */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = true;
+ }
+
+ return 0;
+}
+
+static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip,
+ int effect_idx)
+{
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_config *config = &chip->config;
+ int rc = 0;
+
+ if (effect_idx >= chip->effects_count)
+ return -EINVAL;
+
+ play->effect = &chip->predefined[effect_idx];
+ play->playing_pos = 0;
+
+ rc = qti_haptics_module_en(chip, true);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us);
+ if (rc < 0)
+ return rc;
+
+ if (config->act_type == ACT_LRA) {
+ rc = qti_haptics_lra_auto_res_enable(chip,
+ !play->effect->lra_auto_res_disable);
+ if (rc < 0)
+ return rc;
+ }
+
+ /* Set brake pattern in the effect */
+ rc = qti_haptics_config_brake(chip, play->effect->brake);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ return rc;
+
+ /* Set WF_SOURCE to buffer */
+ rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+ if (rc < 0)
+ return rc;
+
+ play->playing_pattern = true;
+
+ return 0;
+}
+
+static irqreturn_t qti_haptics_play_irq_handler(int irq, void *data)
+{
+ struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+ struct qti_hap_play_info *play = &chip->play;
+ struct qti_hap_effect *effect = play->effect;
+ int rc;
+
+ dev_dbg(chip->dev, "play_irq triggered\n");
+ if (play->playing_pos == effect->pattern_length) {
+ dev_dbg(chip->dev, "waveform playing done\n");
+ qti_haptics_play(chip, false);
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+
+ goto handled;
+ }
+
+ /* Config to play remaining patterns */
+ rc = qti_haptics_config_wf_repeat(chip);
+ if (rc < 0)
+ goto handled;
+
+ rc = qti_haptics_config_wf_buffer(chip);
+ if (rc < 0)
+ goto handled;
+
+handled:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data)
+{
+ struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+ u8 addr, val;
+ ktime_t temp;
+ s64 sc_delta_time_us;
+ int rc;
+
+ dev_dbg(chip->dev, "sc_irq triggered\n");
+ addr = REG_HAP_STATUS1;
+ rc = qti_haptics_read(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "read HAP_STATUS1 failed, rc=%d\n", rc);
+ goto handled;
+ }
+
+ if (!(val & HAP_SC_DET_BIT))
+ goto handled;
+
+ temp = ktime_get();
+ sc_delta_time_us = ktime_us_delta(temp, chip->last_sc_time);
+ chip->last_sc_time = temp;
+
+ if (sc_delta_time_us > HAP_SC_DET_TIME_US)
+ chip->sc_det_count = 0;
+ else
+ chip->sc_det_count++;
+
+ addr = REG_HAP_SC_CLR;
+ val = HAP_SC_CLR_BIT;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write SC_CLR failed, rc=%d\n", rc);
+ goto handled;
+ }
+
+ if (chip->sc_det_count > HAP_SC_DET_MAX_COUNT) {
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ goto handled;
+
+ dev_crit(chip->dev, "Short circuit persists, disable haptics\n");
+ chip->perm_disable = true;
+ }
+
+handled:
+ return IRQ_HANDLED;
+}
+
+static inline void get_play_length(struct qti_hap_play_info *play,
+ int *length_us)
+{
+ struct qti_hap_effect *effect = play->effect;
+ int tmp;
+
+ tmp = effect->pattern_length * effect->play_rate_us;
+ tmp *= wf_s_repeat[effect->wf_s_repeat_n];
+ tmp *= wf_repeat[effect->wf_repeat_n];
+ if (effect->brake_en)
+ tmp += effect->play_rate_us * effect->brake_pattern_length;
+
+ *length_us = tmp;
+}
+
+static int qti_haptics_upload_effect(struct input_dev *dev,
+ struct ff_effect *effect, struct ff_effect *old)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ struct qti_hap_config *config = &chip->config;
+ struct qti_hap_play_info *play = &chip->play;
+ int rc = 0, tmp, i;
+ s16 level, data[CUSTOM_DATA_LEN];
+
+ if (chip->vdd_supply && !chip->vdd_enabled) {
+ rc = regulator_enable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Enable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = true;
+ }
+
+ switch (effect->type) {
+ case FF_CONSTANT:
+ play->length_us = effect->replay.length * USEC_PER_MSEC;
+ level = effect->u.constant.level;
+ tmp = level * config->vmax_mv;
+ play->vmax_mv = tmp / 0x7fff;
+ dev_dbg(chip->dev, "upload constant effect, length = %dus, vmax_mv=%d\n",
+ play->length_us, play->vmax_mv);
+
+ rc = qti_haptics_load_constant_waveform(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "Play constant waveform failed, rc=%d\n",
+ rc);
+ goto disable_vdd;
+ }
+ break;
+
+ case FF_PERIODIC:
+ if (chip->effects_count == 0) {
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ if (effect->u.periodic.waveform != FF_CUSTOM) {
+ dev_err(chip->dev, "Only accept custom waveforms\n");
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ level = effect->u.periodic.magnitude;
+ tmp = level * config->vmax_mv;
+ play->vmax_mv = tmp / 0x7fff;
+
+ if (copy_from_user(data, effect->u.periodic.custom_data,
+ sizeof(s16) * CUSTOM_DATA_LEN)) {
+ rc = -EFAULT;
+ goto disable_vdd;
+ }
+
+ for (i = 0; i < chip->effects_count; i++)
+ if (chip->predefined[i].id ==
+ data[CUSTOM_DATA_EFFECT_IDX])
+ break;
+
+ if (i == chip->effects_count) {
+ dev_err(chip->dev, "predefined effect %d is NOT supported\n",
+ data[0]);
+ rc = -EINVAL;
+ goto disable_vdd;
+ }
+
+ dev_dbg(chip->dev, "upload effect %d, vmax_mv=%d\n",
+ chip->predefined[i].id, play->vmax_mv);
+ rc = qti_haptics_load_predefined_effect(chip, i);
+ if (rc < 0) {
+ dev_err(chip->dev, "Play predefined effect %d failed, rc=%d\n",
+ chip->predefined[i].id, rc);
+ goto disable_vdd;
+ }
+
+ get_play_length(play, &play->length_us);
+ data[CUSTOM_DATA_TIMEOUT_SEC_IDX] =
+ play->length_us / USEC_PER_SEC;
+ data[CUSTOM_DATA_TIMEOUT_MSEC_IDX] =
+ (play->length_us % USEC_PER_SEC) / USEC_PER_MSEC;
+
+ /*
+ * Copy the custom data contains the play length back to
+ * userspace so that the userspace client can wait and
+ * send stop playing command after it's done.
+ */
+ if (copy_to_user(effect->u.periodic.custom_data, data,
+ sizeof(s16) * CUSTOM_DATA_LEN)) {
+ rc = -EFAULT;
+ goto disable_vdd;
+ }
+ break;
+
+ default:
+ dev_err(chip->dev, "Unsupported effect type: %d\n",
+ effect->type);
+ break;
+ }
+
+ return 0;
+disable_vdd:
+ if (chip->vdd_supply && chip->vdd_enabled) {
+ rc = regulator_disable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = false;
+ }
+ return rc;
+}
+
+static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ struct qti_hap_play_info *play = &chip->play;
+ s64 secs;
+ unsigned long nsecs;
+ int rc = 0;
+
+ dev_dbg(chip->dev, "playback, val = %d\n", val);
+ if (!!val) {
+ rc = qti_haptics_play(chip, true);
+ if (rc < 0)
+ return rc;
+
+ if (play->playing_pattern) {
+ if (!chip->play_irq_en) {
+ enable_irq(chip->play_irq);
+ chip->play_irq_en = true;
+ }
+ } else {
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+ secs = play->length_us / USEC_PER_SEC;
+ nsecs = (play->length_us % USEC_PER_SEC) *
+ NSEC_PER_USEC;
+ hrtimer_start(&chip->stop_timer, ktime_set(secs, nsecs),
+ HRTIMER_MODE_REL);
+ }
+ } else {
+ play->length_us = 0;
+ rc = qti_haptics_play(chip, false);
+ if (rc < 0)
+ return rc;
+
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ return rc;
+
+ if (chip->play_irq_en) {
+ disable_irq_nosync(chip->play_irq);
+ chip->play_irq_en = false;
+ }
+ }
+
+ return rc;
+}
+
+static int qti_haptics_erase(struct input_dev *dev, int effect_id)
+{
+ struct qti_hap_chip *chip = input_get_drvdata(dev);
+ int rc = 0;
+
+ if (chip->vdd_supply && chip->vdd_enabled) {
+ rc = regulator_disable(chip->vdd_supply);
+ if (rc < 0) {
+ dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ chip->vdd_enabled = false;
+ }
+
+ return rc;
+}
+
+static int qti_haptics_hw_init(struct qti_hap_chip *chip)
+{
+ struct qti_hap_config *config = &chip->config;
+ u8 addr, val, mask;
+ int rc = 0;
+
+ /* Config actuator type */
+ addr = REG_HAP_CFG1;
+ val = config->act_type;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write actuator type failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Config ilim_ma */
+ addr = REG_HAP_ILIM_CFG;
+ val = config->ilim_ma == 400 ? 0 : 1;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write ilim_ma failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Set HAP_EN_CTL3 */
+ addr = REG_HAP_EN_CTL3;
+ val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT |
+ HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT |
+ HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Set ZX_CFG */
+ addr = REG_HAP_ZX_CFG;
+ mask = HAP_ZX_DET_DEB_MASK;
+ val = ZX_DET_DEB_80US;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0) {
+ dev_err(chip->dev, "write ZX_CFG failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /*
+ * Config play rate: this is the resonance period for LRA,
+ * or the play duration of each waveform sample for ERM.
+ */
+ rc = qti_haptics_config_play_rate_us(chip, config->play_rate_us);
+ if (rc < 0)
+ return rc;
+
+ /* Set external waveform source if it's used */
+ if (config->use_ext_wf_src) {
+ rc = qti_haptics_config_wf_src(chip, config->ext_src);
+ if (rc < 0)
+ return rc;
+ }
+
+ /*
+ * Skip configurations below for ERM actuator
+ * as they're only for LRA actuators
+ */
+ if (config->act_type == ACT_ERM)
+ return 0;
+
+ addr = REG_HAP_CFG2;
+ val = config->lra_shape;
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "write lra_sig_shape failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ addr = REG_HAP_AUTO_RES_CFG;
+ mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK;
+ val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT;
+ val |= HAP_CAL_EOP_EN_BIT | HAP_CAL_OPT3_EVERY_8_PERIOD;
+ rc = qti_haptics_masked_write(chip, addr, mask, val);
+ if (rc < 0) {
+ dev_err(chip->dev, "set AUTO_RES_CFG failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ addr = REG_HAP_AUTO_RES_CTRL;
+ val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD |
+ AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT |
+ AUTO_RES_EN_DLY(4);
+ rc = qti_haptics_write(chip, addr, &val, 1);
+ if (rc < 0) {
+ dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static enum hrtimer_restart qti_hap_stop_timer(struct hrtimer *timer)
+{
+ struct qti_hap_chip *chip = container_of(timer, struct qti_hap_chip,
+ stop_timer);
+ int rc;
+
+ chip->play.length_us = 0;
+ rc = qti_haptics_play(chip, false);
+ if (rc < 0) {
+ dev_err(chip->dev, "Stop playing failed, rc=%d\n", rc);
+ goto err_out;
+ }
+
+ rc = qti_haptics_module_en(chip, false);
+ if (rc < 0)
+ dev_err(chip->dev, "Disable module failed, rc=%d\n", rc);
+err_out:
+ return HRTIMER_NORESTART;
+}
+
+static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
+{
+ struct qti_hap_config *config = &chip->config;
+ const struct device_node *node = chip->dev->of_node;
+ struct device_node *child_node;
+ struct qti_hap_effect *effect;
+ const char *str;
+ int rc = 0, tmp, i = 0, j;
+ u8 val;
+
+ rc = of_property_read_u32(node, "reg", &tmp);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to reg base, rc=%d\n", rc);
+ return rc;
+ }
+ chip->reg_base = (u16)tmp;
+
+ chip->sc_irq = platform_get_irq_byname(chip->pdev, "hap-sc-irq");
+ if (chip->sc_irq < 0) {
+ dev_err(chip->dev, "Failed to get hap-sc-irq\n");
+ return chip->sc_irq;
+ }
+
+ chip->play_irq = platform_get_irq_byname(chip->pdev, "hap-play-irq");
+ if (chip->play_irq < 0) {
+ dev_err(chip->dev, "Failed to get hap-play-irq\n");
+ return chip->play_irq;
+ }
+
+ config->act_type = ACT_LRA;
+ rc = of_property_read_string(node, "qcom,actuator-type", &str);
+ if (!rc) {
+ if (strcmp(str, "erm") == 0) {
+ config->act_type = ACT_ERM;
+ } else if (strcmp(str, "lra") == 0) {
+ config->act_type = ACT_LRA;
+ } else {
+ dev_err(chip->dev, "Invalid actuator type: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+
+ config->vmax_mv = HAP_VMAX_MV_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,vmax-mv", &tmp);
+ if (!rc)
+ config->vmax_mv = (tmp > HAP_VMAX_MV_MAX) ?
+ HAP_VMAX_MV_MAX : tmp;
+
+ config->ilim_ma = HAP_ILIM_MA_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ilim-ma", &tmp);
+ if (!rc)
+ config->ilim_ma = (tmp >= HAP_ILIM_MA_MAX) ?
+ HAP_ILIM_MA_MAX : HAP_ILIM_MA_DEFAULT;
+
+ config->play_rate_us = HAP_PLAY_RATE_US_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,play-rate-us", &tmp);
+ if (!rc)
+ config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ?
+ HAP_PLAY_RATE_US_MAX : tmp;
+
+ if (of_find_property(node, "qcom,external-waveform-source", NULL)) {
+ if (!of_property_read_string(node,
+ "qcom,external-waveform-source", &str)) {
+ if (strcmp(str, "audio") == 0) {
+ config->ext_src = EXT_WF_AUDIO;
+ } else if (strcmp(str, "pwm") == 0) {
+ config->ext_src = EXT_WF_PWM;
+ } else {
+ dev_err(chip->dev, "Invalid external waveform source: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+ config->use_ext_wf_src = true;
+ }
+
+ if (of_find_property(node, "vdd-supply", NULL)) {
+ chip->vdd_supply = devm_regulator_get(chip->dev, "vdd");
+ if (IS_ERR(chip->vdd_supply)) {
+ rc = PTR_ERR(chip->vdd_supply);
+ if (rc != -EPROBE_DEFER)
+ dev_err(chip->dev, "Failed to get vdd regulator");
+ return rc;
+ }
+ }
+
+ if (config->act_type == ACT_LRA) {
+ config->lra_shape = RES_SIG_SINE;
+ rc = of_property_read_string(node,
+ "qcom,lra-resonance-sig-shape", &str);
+ if (!rc) {
+ if (strcmp(str, "sine") == 0) {
+ config->lra_shape = RES_SIG_SINE;
+ } else if (strcmp(str, "square") == 0) {
+ config->lra_shape = RES_SIG_SQUARE;
+ } else {
+ dev_err(chip->dev, "Invalid resonance signal shape: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+
+ config->lra_allow_variable_play_rate = of_property_read_bool(
+ node, "qcom,lra-allow-variable-play-rate");
+
+ config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+ rc = of_property_read_string(node,
+ "qcom,lra-auto-resonance-mode", &str);
+ if (!rc) {
+ if (strcmp(str, "zxd") == 0) {
+ config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+ } else if (strcmp(str, "qwd") == 0) {
+ config->lra_auto_res_mode = AUTO_RES_MODE_QWD;
+ } else {
+ dev_err(chip->dev, "Invalid auto resonance mode: %s\n",
+ str);
+ return -EINVAL;
+ }
+ }
+ }
+
+ chip->constant.pattern = devm_kcalloc(chip->dev,
+ HAP_WAVEFORM_BUFFER_MAX,
+ sizeof(u8), GFP_KERNEL);
+ if (!chip->constant.pattern)
+ return -ENOMEM;
+
+ tmp = of_get_available_child_count(node);
+ if (tmp == 0)
+ return 0;
+
+ chip->predefined = devm_kcalloc(chip->dev, tmp,
+ sizeof(*chip->predefined), GFP_KERNEL);
+ if (!chip->predefined)
+ return -ENOMEM;
+
+ chip->effects_count = tmp;
+
+ for_each_available_child_of_node(node, child_node) {
+ effect = &chip->predefined[i++];
+ rc = of_property_read_u32(child_node, "qcom,effect-id",
+ &effect->id);
+ if (rc < 0) {
+ dev_err(chip->dev, "Read qcom,effect-id failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_count_elems_of_size(child_node,
+ "qcom,wf-pattern", sizeof(u8));
+ if (rc < 0) {
+ dev_err(chip->dev, "Count qcom,wf-pattern property failed, rc=%d\n",
+ rc);
+ return rc;
+ } else if (rc == 0) {
+ dev_dbg(chip->dev, "qcom,wf-pattern has no data\n");
+ return -EINVAL;
+ }
+
+ effect->pattern_length = rc;
+ effect->pattern = devm_kcalloc(chip->dev,
+ effect->pattern_length, sizeof(u8), GFP_KERNEL);
+ if (!effect->pattern)
+ return -ENOMEM;
+
+ rc = of_property_read_u8_array(child_node, "qcom,wf-pattern",
+ effect->pattern, effect->pattern_length);
+ if (rc < 0) {
+ dev_err(chip->dev, "Read qcom,wf-pattern property failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ effect->play_rate_us = config->play_rate_us;
+ rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us",
+ &tmp);
+ if (rc < 0)
+ dev_dbg(chip->dev, "Read qcom,wf-play-rate-us failed, rc=%d\n",
+ rc);
+ else
+ effect->play_rate_us = tmp;
+
+ if (config->act_type == ACT_LRA &&
+ !config->lra_allow_variable_play_rate &&
+ config->play_rate_us != effect->play_rate_us) {
+ dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n");
+ effect->play_rate_us = config->play_rate_us;
+ }
+
+ rc = of_property_read_u32(child_node, "qcom,wf-repeat-count",
+ &tmp);
+ if (rc < 0) {
+ dev_dbg(chip->dev, "Read qcom,wf-repeat-count failed, rc=%d\n",
+ rc);
+ } else {
+ for (j = 0; j < ARRAY_SIZE(wf_repeat); j++)
+ if (tmp <= wf_repeat[j])
+ break;
+
+ effect->wf_repeat_n = j;
+ }
+
+ rc = of_property_read_u32(child_node, "qcom,wf-s-repeat-count",
+ &tmp);
+ if (rc < 0) {
+ dev_dbg(chip->dev, "Read qcom,wf-s-repeat-count failed, rc=%d\n",
+ rc);
+ } else {
+ for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++)
+ if (tmp <= wf_s_repeat[j])
+ break;
+
+ effect->wf_s_repeat_n = j;
+ }
+
+ effect->lra_auto_res_disable = of_property_read_bool(node,
+ "qcom,lra-auto-resonance-disable");
+
+ tmp = of_property_count_elems_of_size(child_node,
+ "qcom,wf-brake-pattern", sizeof(u8));
+ if (tmp <= 0)
+ continue;
+
+ if (tmp > HAP_BRAKE_PATTERN_MAX) {
+ dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n",
+ HAP_BRAKE_PATTERN_MAX);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u8_array(child_node,
+ "qcom,wf-brake-pattern", effect->brake, tmp);
+ if (rc < 0) {
+ dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ effect->brake_pattern_length = tmp;
+ for (j = tmp - 1; j >= 0; j--) {
+ if (effect->brake[j] != 0)
+ break;
+ effect->brake_pattern_length--;
+ }
+
+ for (val = 0, j = 0; j < effect->brake_pattern_length; j++)
+ val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK)
+ << j * HAP_BRAKE_PATTERN_SHIFT;
+
+ effect->brake_en = (val != 0);
+ }
+
+ return 0;
+}
+
+static int qti_haptics_probe(struct platform_device *pdev)
+{
+ struct qti_hap_chip *chip;
+ struct input_dev *input_dev;
+ struct ff_device *ff;
+ int rc = 0, effect_count_max;
+
+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ input_dev = devm_input_allocate_device(&pdev->dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ chip->pdev = pdev;
+ chip->dev = &pdev->dev;
+ chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+ if (!chip->regmap) {
+ dev_err(chip->dev, "Failed to get regmap handle\n");
+ return -ENXIO;
+ }
+
+ rc = qti_haptics_parse_dt(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ spin_lock_init(&chip->bus_lock);
+
+ rc = qti_haptics_hw_init(chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = devm_request_threaded_irq(chip->dev, chip->play_irq, NULL,
+ qti_haptics_play_irq_handler,
+ IRQF_ONESHOT, "hap_play_irq", chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "request play-irq failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ disable_irq(chip->play_irq);
+ chip->play_irq_en = false;
+
+ rc = devm_request_threaded_irq(chip->dev, chip->sc_irq, NULL,
+ qti_haptics_sc_irq_handler,
+ IRQF_ONESHOT, "hap_sc_irq", chip);
+ if (rc < 0) {
+ dev_err(chip->dev, "request sc-irq failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ hrtimer_init(&chip->stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ chip->stop_timer.function = qti_hap_stop_timer;
+
+ input_dev->name = "qti-haptics";
+ input_set_drvdata(input_dev, chip);
+ chip->input_dev = input_dev;
+
+ input_set_capability(input_dev, EV_FF, FF_CONSTANT);
+ if (chip->effects_count != 0) {
+ input_set_capability(input_dev, EV_FF, FF_PERIODIC);
+ input_set_capability(input_dev, EV_FF, FF_CUSTOM);
+ }
+
+ if (chip->effects_count + 1 > FF_EFFECT_COUNT_MAX)
+ effect_count_max = chip->effects_count + 1;
+ else
+ effect_count_max = FF_EFFECT_COUNT_MAX;
+ rc = input_ff_create(input_dev, effect_count_max);
+ if (rc < 0) {
+ dev_err(chip->dev, "create FF input device failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ ff = input_dev->ff;
+ ff->upload = qti_haptics_upload_effect;
+ ff->playback = qti_haptics_playback;
+ ff->erase = qti_haptics_erase;
+
+ rc = input_register_device(input_dev);
+ if (rc < 0) {
+ dev_err(chip->dev, "register input device failed, rc=%d\n",
+ rc);
+ goto destroy_ff;
+ }
+
+ dev_set_drvdata(chip->dev, chip);
+ return 0;
+
+destroy_ff:
+ input_ff_destroy(chip->input_dev);
+ return rc;
+}
+
+static int qti_haptics_remove(struct platform_device *pdev)
+{
+ struct qti_hap_chip *chip = dev_get_drvdata(&pdev->dev);
+
+ input_ff_destroy(chip->input_dev);
+ dev_set_drvdata(chip->dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id haptics_match_table[] = {
+ { .compatible = "qcom,haptics" },
+ { .compatible = "qcom,pm660-haptics" },
+ { .compatible = "qcom,pm8150b-haptics" },
+ {},
+};
+
+static struct platform_driver qti_haptics_driver = {
+ .driver = {
+ .name = "qcom,haptics",
+ .of_match_table = haptics_match_table,
+ },
+ .probe = qti_haptics_probe,
+ .remove = qti_haptics_remove,
+};
+module_platform_driver(qti_haptics_driver);
+
+MODULE_DESCRIPTION("QTI haptics driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 34508b2..357a17c 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -1130,6 +1130,25 @@
stmvl53l0x_set_XTalkCompensationRateMegaCps);
+static ssize_t stmvl53l0x_show_GetSensorID(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ u32 SensorID = 0;
+ int ret = 0;
+ struct vl_data *data = dev_get_drvdata(dev);
+ struct i2c_data *i2c_object = (struct i2c_data *)data->client_object;
+
+ ret = of_property_read_u32(i2c_object->client->dev.of_node,
+ "tof-id",
+ &SensorID);
+ return snprintf(buf, 5, "%d\n", SensorID);
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(show_sensorid, 0660/*S_IWUGO | S_IRUGO*/,
+ stmvl53l0x_show_GetSensorID,
+ NULL);
static struct attribute *stmvl53l0x_attributes[] = {
&dev_attr_enable_ps_sensor.attr,
@@ -1144,6 +1163,7 @@
&dev_attr_ref_cal.attr,
&dev_attr_set_offsetdata.attr,
&dev_attr_set_xtalkdata.attr,
+ &dev_attr_show_sensorid.attr,
NULL,
};
@@ -1948,12 +1968,6 @@
input_set_drvdata(data->input_dev_ps, data);
/* Register sysfs hooks */
- data->range_kobj = kobject_create_and_add("range", kernel_kobj);
- if (!data->range_kobj) {
- rc = -ENOMEM;
- err("%d error:%d\n", __LINE__, rc);
- goto exit_unregister_dev_ps;
- }
rc = sysfs_create_group(&data->input_dev_ps->dev.kobj,
&stmvl53l0x_attr_group);
if (rc) {
@@ -1981,7 +1995,6 @@
return 0;
exit_unregister_dev_ps_1:
kobject_put(data->range_kobj);
-exit_unregister_dev_ps:
input_unregister_device(data->input_dev_ps);
exit_free_dev_ps:
input_free_device(data->input_dev_ps);
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index d773ec5..1e62cde 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -745,8 +745,11 @@
union power_supply_propval pval = {0, };
if (!led->bms_psy) {
- pr_err("no bms psy found\n");
- return -EINVAL;
+ led->bms_psy = power_supply_get_by_name("bms");
+ if (!led->bms_psy) {
+ pr_err_ratelimited("Couldn't get bms_psy\n");
+ return -ENODEV;
+ }
}
rc = power_supply_get_property(led->bms_psy, prop, &pval);
@@ -1793,41 +1796,6 @@
__ATTR(enable, 0664, NULL, qpnp_flash_led_prepare_store),
};
-static int flash_led_psy_notifier_call(struct notifier_block *nb,
- unsigned long ev, void *v)
-{
- struct power_supply *psy = v;
- struct qpnp_flash_led *led =
- container_of(nb, struct qpnp_flash_led, nb);
-
- if (ev != PSY_EVENT_PROP_CHANGED)
- return NOTIFY_OK;
-
- if (!strcmp(psy->desc->name, "bms")) {
- led->bms_psy = power_supply_get_by_name("bms");
- if (!led->bms_psy)
- pr_err("Failed to get bms power_supply\n");
- else
- power_supply_unreg_notifier(&led->nb);
- }
-
- return NOTIFY_OK;
-}
-
-static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
-{
- int rc;
-
- led->nb.notifier_call = flash_led_psy_notifier_call;
- rc = power_supply_reg_notifier(&led->nb);
- if (rc < 0) {
- pr_err("Couldn't register psy notifier, rc = %d\n", rc);
- return rc;
- }
-
- return 0;
-}
-
/* irq handler */
static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
{
@@ -2821,15 +2789,6 @@
}
}
- led->bms_psy = power_supply_get_by_name("bms");
- if (!led->bms_psy) {
- rc = flash_led_psy_register_notifier(led);
- if (rc < 0) {
- pr_err("Couldn't register psy notifier, rc = %d\n", rc);
- goto error_switch_register;
- }
- }
-
rc = qpnp_flash_led_init_settings(led);
if (rc < 0) {
pr_err("Failed to initialize flash LED, rc=%d\n", rc);
diff --git a/drivers/media/platform/msm/Makefile b/drivers/media/platform/msm/Makefile
index 24c27cd..e19da45 100644
--- a/drivers/media/platform/msm/Makefile
+++ b/drivers/media/platform/msm/Makefile
@@ -9,3 +9,4 @@
obj-$(CONFIG_MSMB_CAMERA) += camera_v2/
obj-y += broadcast/
obj-$(CONFIG_DVB_MPQ) += dvb/
+obj-$(CONFIG_QCA402X) += qca402/
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 891b738..670349d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -56,7 +56,7 @@
}
if (!rc)
- cam_destroy_device_hdl(ctx_hdl);
+ rc = cam_destroy_device_hdl(ctx_hdl);
return rc;
}
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index fce7fc6..89aad8c 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -490,6 +490,7 @@
release.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release);
ctx->ctxt_to_hw_map = NULL;
+ ctx->dev_hdl = -1;
end:
return rc;
}
@@ -504,6 +505,7 @@
bool free_req;
CAM_DBG(CAM_CTXT, "[%s] E: NRT flush ctx", ctx->dev_name);
+ memset(&flush_args, 0, sizeof(flush_args));
/*
* flush pending requests, take the sync lock to synchronize with the
@@ -670,6 +672,7 @@
CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name);
+ memset(&flush_args, 0, sizeof(flush_args));
flush_args.num_req_pending = 0;
flush_args.num_req_active = 0;
mutex_lock(&ctx->sync_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index 0a9fabc..3f24c6d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -413,13 +413,16 @@
int cam_node_shutdown(struct cam_node *node)
{
int i = 0;
+ int rc = 0;
if (!node)
return -EINVAL;
for (i = 0; i < node->ctx_size; i++) {
- if (node->ctx_list[i].dev_hdl >= 0) {
- cam_context_shutdown(&(node->ctx_list[i]));
+ if (node->ctx_list[i].dev_hdl > 0) {
+ rc = cam_context_shutdown(&(node->ctx_list[i]));
+ if (rc)
+ continue;
cam_context_putref(&(node->ctx_list[i]));
}
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index d32d4b6..1733017 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -3841,19 +3841,15 @@
return -EINVAL;
}
- CAM_DBG(CAM_REQ, "ctx_id %d req %lld Flush type %d",
- ctx_data->ctx_id,
- *(int64_t *)flush_args->flush_req_pending[0],
- flush_args->flush_type);
+ CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d",
+ ctx_data->ctx_id, flush_args->flush_type);
switch (flush_args->flush_type) {
case CAM_FLUSH_TYPE_ALL:
mutex_lock(&hw_mgr->hw_mgr_mutex);
- if (!hw_mgr->recovery) {
- if (flush_args->num_req_active) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
- cam_icp_mgr_abort_handle(ctx_data);
- }
+ if (!hw_mgr->recovery && flush_args->num_req_active) {
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ cam_icp_mgr_abort_handle(ctx_data);
} else {
mutex_unlock(&hw_mgr->hw_mgr_mutex);
}
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index f5b1bb1..08ef0e9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -1395,12 +1395,56 @@
struct cam_context *ctx,
struct cam_req_mgr_flush_request *flush_req)
{
+ struct cam_isp_context *ctx_isp =
+ (struct cam_isp_context *) ctx->ctx_priv;
+ struct cam_isp_stop_args stop_isp;
+ struct cam_hw_stop_args stop_args;
+ struct cam_isp_start_args start_isp;
int rc = 0;
CAM_DBG(CAM_ISP, "try to flush pending list");
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
spin_unlock_bh(&ctx->lock);
+
+ if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+ /* if active and wait list are empty, return */
+ spin_lock_bh(&ctx->lock);
+ if ((list_empty(&ctx->wait_req_list)) &&
+ (list_empty(&ctx->active_req_list))) {
+ spin_unlock_bh(&ctx->lock);
+ CAM_DBG(CAM_ISP, "active and wait list are empty");
+ goto end;
+ }
+ spin_unlock_bh(&ctx->lock);
+
+ /* Stop hw first before active list flush */
+ stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
+ stop_isp.stop_only = true;
+ stop_args.args = (void *)&stop_isp;
+ ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
+ &stop_args);
+
+ spin_lock_bh(&ctx->lock);
+ CAM_DBG(CAM_ISP, "try to flush wait list");
+ rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,
+ flush_req);
+ CAM_DBG(CAM_ISP, "try to flush active list");
+ rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
+ flush_req);
+ spin_unlock_bh(&ctx->lock);
+
+ /* Start hw */
+ start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ start_isp.start_only = true;
+ start_isp.hw_config.priv = NULL;
+
+ rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
+ &start_isp);
+ }
+
+end:
CAM_DBG(CAM_ISP, "Flush request in top state %d",
ctx->state);
return rc;
@@ -1438,7 +1482,7 @@
spin_lock_bh(&ctx->lock);
rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
- /* if nothing is in pending req list, change state to acquire*/
+ /* if nothing is in pending req list, change state to acquire */
if (list_empty(&ctx->pending_req_list))
ctx->state = CAM_CTX_ACQUIRED;
spin_unlock_bh(&ctx->lock);
@@ -2366,7 +2410,7 @@
struct cam_start_stop_dev_cmd *cmd)
{
int rc = 0;
- struct cam_hw_config_args arg;
+ struct cam_isp_start_args start_isp;
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_isp_context *ctx_isp =
@@ -2395,12 +2439,13 @@
goto end;
}
- arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
- arg.request_id = req->request_id;
- arg.hw_update_entries = req_isp->cfg;
- arg.num_hw_update_entries = req_isp->num_cfg;
- arg.priv = &req_isp->hw_update_data;
- arg.init_packet = 1;
+ start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ start_isp.hw_config.request_id = req->request_id;
+ start_isp.hw_config.hw_update_entries = req_isp->cfg;
+ start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg;
+ start_isp.hw_config.priv = &req_isp->hw_update_data;
+ start_isp.hw_config.init_packet = 1;
+ start_isp.start_only = false;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
@@ -2417,7 +2462,8 @@
*/
ctx->state = CAM_CTX_ACTIVATED;
trace_cam_context_state("ISP", ctx);
- rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg);
+ rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
+ &start_isp);
if (rc) {
/* HW failure. user need to clean up the resource */
CAM_ERR(CAM_ISP, "Start HW failed");
@@ -2458,6 +2504,7 @@
struct cam_isp_ctx_req *req_isp;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *) ctx->ctx_priv;
+ struct cam_isp_stop_args stop_isp;
/* Mask off all the incoming hardware events */
spin_lock_bh(&ctx->lock);
@@ -2468,7 +2515,15 @@
/* stop hw first */
if (ctx_isp->hw_ctx) {
stop.ctxt_to_hw_map = ctx_isp->hw_ctx;
- stop.args = stop_cmd;
+
+ if (stop_cmd)
+ stop_isp.hw_stop_cmd =
+ CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
+ else
+ stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY;
+
+ stop_isp.stop_only = false;
+ stop.args = (void *) &stop_isp;
ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
&stop);
}
@@ -2489,6 +2544,22 @@
list_add_tail(&req->list, &ctx->free_req_list);
}
+ while (!list_empty(&ctx->wait_req_list)) {
+ req = list_first_entry(&ctx->wait_req_list,
+ struct cam_ctx_request, list);
+ list_del_init(&req->list);
+ req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+ CAM_DBG(CAM_ISP, "signal fence in wait list. fence num %d",
+ req_isp->num_fence_map_out);
+ for (i = 0; i < req_isp->num_fence_map_out; i++)
+ if (req_isp->fence_map_out[i].sync_id != -1) {
+ cam_sync_signal(
+ req_isp->fence_map_out[i].sync_id,
+ CAM_SYNC_STATE_SIGNALED_ERROR);
+ }
+ list_add_tail(&req->list, &ctx->free_req_list);
+ }
+
while (!list_empty(&ctx->active_req_list)) {
req = list_first_entry(&ctx->active_req_list,
struct cam_ctx_request, list);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 8d764b0..aab323e 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -283,6 +283,100 @@
}
}
+static int cam_ife_hw_mgr_init_hw(
+ struct cam_ife_hw_mgr_ctx *ctx)
+{
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ int rc = 0, i;
+
+ CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
+ ctx->ctx_index);
+ /* INIT IFE CID */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
+ rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
+ hw_mgr_res->res_id);
+ return rc;
+ }
+ }
+
+ CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
+ ctx->ctx_index);
+
+ /* INIT IFE csid */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+ rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
+ hw_mgr_res->res_id);
+ return rc;
+ }
+ }
+
+ /* INIT IFE SRC */
+ CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
+ ctx->ctx_index);
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
+ hw_mgr_res->res_id);
+ return rc;
+ }
+ }
+
+ /* INIT IFE OUT */
+ CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
+ ctx->ctx_index);
+
+ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
+ rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
+ ctx->res_list_ife_out[i].res_id);
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+static void cam_ife_hw_mgr_deinit_hw(
+ struct cam_ife_hw_mgr_ctx *ctx)
+{
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ int i = 0;
+
+ if (!ctx->init_done) {
+ CAM_WARN(CAM_ISP, "ctx is not in init state");
+ return;
+ }
+
+ /* Deinit IFE CID */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
+ CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
+ cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+ }
+
+ /* Deinit IFE CSID */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+ CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__);
+ cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+ }
+
+ /* Deint IFE MUX(SRC) */
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+ }
+
+ /* Deinit IFE OUT */
+ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
+ cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
+
+ ctx->init_done = false;
+}
+
static int cam_ife_hw_mgr_put_res(
struct list_head *src_list,
struct cam_ife_hw_mgr_res **res)
@@ -1833,6 +1927,7 @@
{
int rc = 0;
struct cam_hw_stop_args *stop_args = stop_hw_args;
+ struct cam_isp_stop_args *stop_isp;
struct cam_ife_hw_mgr_res *hw_mgr_res;
struct cam_ife_hw_mgr_ctx *ctx;
enum cam_ife_csid_halt_cmd csid_halt_type;
@@ -1842,6 +1937,7 @@
CAM_ERR(CAM_ISP, "Invalid arguments");
return -EINVAL;
}
+
ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map;
if (!ctx || !ctx->ctx_in_use) {
CAM_ERR(CAM_ISP, "Invalid context is used");
@@ -1849,12 +1945,20 @@
}
CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index);
+ stop_isp = (struct cam_isp_stop_args *)stop_args->args;
+
+ if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) &&
+ (stop_isp->stop_only)) {
+ CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d",
+ stop_isp->hw_stop_cmd, stop_isp->stop_only);
+ return -EPERM;
+ }
/* Set the csid halt command */
- if (!stop_args->args)
- csid_halt_type = CAM_CSID_HALT_IMMEDIATELY;
- else
+ if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY)
csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY;
+ else
+ csid_halt_type = CAM_CSID_HALT_IMMEDIATELY;
/* Note:stop resource will remove the irq mask from the hardware */
@@ -1930,30 +2034,15 @@
ctx->base[i].idx, csid_halt_type);
}
- /* Deinit IFE CID */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
- CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
- cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
- }
+ if (stop_isp->stop_only)
+ goto end;
- /* Deinit IFE CSID */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
- CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__);
- cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
- }
-
- /* Deint IFE MUX(SRC) */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
- cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
- }
-
- /* Deinit IFE OUT */
- for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
- cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
-
+ cam_ife_hw_mgr_deinit_hw(ctx);
CAM_DBG(CAM_ISP,
"Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc);
+end:
+
mutex_lock(&g_ife_hw_mgr.ctx_mutex);
if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) {
rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE);
@@ -2065,19 +2154,20 @@
static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
{
int rc = -1;
- struct cam_hw_config_args *start_args = start_hw_args;
+ struct cam_isp_start_args *start_isp = start_hw_args;
struct cam_hw_stop_args stop_args;
- struct cam_isp_stop_hw_method stop_hw_method;
+ struct cam_isp_stop_args stop_isp;
struct cam_ife_hw_mgr_ctx *ctx;
struct cam_ife_hw_mgr_res *hw_mgr_res;
uint32_t i;
- if (!hw_mgr_priv || !start_hw_args) {
+ if (!hw_mgr_priv || !start_isp) {
CAM_ERR(CAM_ISP, "Invalid arguments");
return -EINVAL;
}
- ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map;
+ ctx = (struct cam_ife_hw_mgr_ctx *)
+ start_isp->hw_config.ctxt_to_hw_map;
if (!ctx || !ctx->ctx_in_use) {
CAM_ERR(CAM_ISP, "Invalid context is used");
return -EPERM;
@@ -2090,6 +2180,9 @@
cam_tasklet_start(ctx->common.tasklet_info);
+ if (ctx->init_done && start_isp->start_only)
+ goto start_only;
+
/* set current csid debug information to CSID HW */
for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
if (g_ife_hw_mgr.csid_devices[i])
@@ -2100,58 +2193,13 @@
sizeof(g_ife_hw_mgr.debug_cfg.csid_debug));
}
- /* INIT IFE Root: do nothing */
-
- CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
- ctx->ctx_index);
- /* INIT IFE CID */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
- rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
- if (rc) {
- CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
- hw_mgr_res->res_id);
- goto err;
- }
+ rc = cam_ife_hw_mgr_init_hw(ctx);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Init failed");
+ goto err;
}
-
- CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
- ctx->ctx_index);
-
- /* INIT IFE csid */
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
- rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
- if (rc) {
- CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
- hw_mgr_res->res_id);
- goto err;
- }
- }
-
- /* INIT IFE SRC */
- CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
- ctx->ctx_index);
- list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
- rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
- if (rc) {
- CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
- hw_mgr_res->res_id);
- goto err;
- }
- }
-
- /* INIT IFE OUT */
- CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
- ctx->ctx_index);
-
- for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
- rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
- if (rc) {
- CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
- ctx->res_list_ife_out[i].res_id);
- goto err;
- }
- }
+start_only:
mutex_lock(&g_ife_hw_mgr.ctx_mutex);
if (!atomic_fetch_inc(&g_ife_hw_mgr.active_ctx_cnt)) {
@@ -2172,12 +2220,15 @@
goto err;
}
- /* Apply initial configuration */
- CAM_DBG(CAM_ISP, "Config HW");
- rc = cam_ife_mgr_config_hw(hw_mgr_priv, start_hw_args);
- if (rc) {
- CAM_ERR(CAM_ISP, "Config HW failed");
- goto err;
+ if (!start_isp->start_only) {
+ /* Apply initial configuration */
+ CAM_DBG(CAM_ISP, "Config HW");
+ rc = cam_ife_mgr_config_hw(hw_mgr_priv,
+ &start_isp->hw_config);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Config HW failed");
+ goto err;
+ }
}
CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d",
@@ -2229,13 +2280,18 @@
}
}
+ ctx->init_done = true;
/* Start IFE root node: do nothing */
CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index);
+
return 0;
+
err:
- stop_hw_method.hw_stop_cmd = CAM_CSID_HALT_IMMEDIATELY;
- stop_args.ctxt_to_hw_map = start_args->ctxt_to_hw_map;
- stop_args.args = (void *)(&stop_hw_method);
+ stop_isp.stop_only = false;
+ stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY;
+ stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map;
+ stop_args.args = (void *)(&stop_isp);
+
cam_ife_mgr_stop_hw(hw_mgr_priv, &stop_args);
CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc);
return rc;
@@ -2274,6 +2330,9 @@
CAM_DBG(CAM_ISP, "Enter...ctx id:%d",
ctx->ctx_index);
+ if (ctx->init_done)
+ cam_ife_hw_mgr_deinit_hw(ctx);
+
/* we should called the stop hw before this already */
cam_ife_hw_mgr_release_hw_for_ctx(ctx);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 0e678b4..0198f3d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -123,6 +123,7 @@
* context
* @is_rdi_only_context flag to specify the context has only rdi resource
* @config_done_complete indicator for configuration complete
+ * @init_done indicate whether init hw is done
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@@ -156,6 +157,7 @@
atomic_t overflow_pending;
uint32_t is_rdi_only_context;
struct completion config_done_complete;
+ bool init_done;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index 8f1911e..fd71c37 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -60,13 +60,29 @@
};
/**
- * struct cam_isp_stop_hw_method - hardware stop method
+ * struct cam_isp_stop_args - hardware stop arguments
*
* @hw_stop_cmd: Hardware stop command type information
+ * @stop_only Send stop only to hw drivers. No Deinit to be
+ * done.
*
*/
-struct cam_isp_stop_hw_method {
+struct cam_isp_stop_args {
enum cam_isp_hw_stop_cmd hw_stop_cmd;
+ bool stop_only;
+};
+
+/**
+ * struct cam_isp_start_args - isp hardware start arguments
+ *
+ * @config_args: Hardware configuration commands.
+ * @start_only Send start only to hw drivers. No init to
+ * be done.
+ *
+ */
+struct cam_isp_start_args {
+ struct cam_hw_config_args hw_config;
+ bool start_only;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 67b572e..206b3a3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -1131,6 +1131,9 @@
rsrc_data->common_data;
/* Disble WM */
+ cam_io_w_mb(0x0,
+ common_data->mem_base + rsrc_data->hw_regs->cfg);
+
/* Disable all register access, reply on global reset */
CAM_DBG(CAM_ISP, "WM res %d irq_enabled %d",
rsrc_data->index, rsrc_data->irq_enabled);
@@ -2291,9 +2294,10 @@
struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_client = NULL;
uint32_t *reg_val_pair;
- uint32_t i, j, size = 0;
+ uint32_t i, j, k, size = 0;
uint32_t frame_inc = 0, ubwc_bw_limit = 0, camera_hw_version, val;
int rc = 0;
+ uint32_t loop_size = 0;
bus_priv = (struct cam_vfe_bus_ver2_priv *) priv;
update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args;
@@ -2492,20 +2496,6 @@
}
}
- /* WM Image address */
- if (wm_data->en_ubwc)
- CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
- wm_data->hw_regs->image_addr,
- (update_buf->wm_update->image_buf[i] +
- io_cfg->planes[i].meta_size));
- else
- CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
- wm_data->hw_regs->image_addr,
- update_buf->wm_update->image_buf[i] +
- wm_data->offset);
- CAM_DBG(CAM_ISP, "WM %d image address 0x%x",
- wm_data->index, reg_val_pair[j-1]);
-
if (wm_data->en_ubwc) {
frame_inc = ALIGNUP(io_cfg->planes[i].plane_stride *
io_cfg->planes[i].slice_height, 4096);
@@ -2521,6 +2511,28 @@
io_cfg->planes[i].slice_height;
}
+ if (wm_data->index < 3)
+ loop_size = wm_data->irq_subsample_period + 1;
+ else
+ loop_size = 1;
+
+ /* WM Image address */
+ for (k = 0; k < loop_size; k++) {
+ if (wm_data->en_ubwc)
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ wm_data->hw_regs->image_addr,
+ update_buf->wm_update->image_buf[i] +
+ io_cfg->planes[i].meta_size +
+ k * frame_inc);
+ else
+ CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+ wm_data->hw_regs->image_addr,
+ update_buf->wm_update->image_buf[i] +
+ wm_data->offset + k * frame_inc);
+ CAM_DBG(CAM_ISP, "WM %d image address 0x%x",
+ wm_data->index, reg_val_pair[j-1]);
+ }
+
CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
wm_data->hw_regs->frame_inc, frame_inc);
CAM_DBG(CAM_ISP, "WM %d frame_inc %d",
@@ -2591,6 +2603,13 @@
wm_data = vfe_out_data->wm_res[i]->res_priv;
+ if (wm_data->index <= 2 && hfr_cfg->subsample_period > 3) {
+ CAM_ERR(CAM_ISP,
+ "RDI doesn't support irq subsample period %d",
+ hfr_cfg->subsample_period);
+ return -EINVAL;
+ }
+
if ((wm_data->framedrop_pattern !=
hfr_cfg->framedrop_pattern) ||
!wm_data->hfr_cfg_done) {
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index 346cd56..61fd7a8 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -1142,24 +1142,26 @@
}
/**
- * __cam_req_mgr_sof_freeze()
+ * __cam_req_mgr_process_sof_freeze()
*
* @brief : Apoptosis - Handles case when connected devices are not responding
- * @data : timer pointer
+ * @priv : link information
+ * @data : task data
*
*/
-static void __cam_req_mgr_sof_freeze(unsigned long data)
+static int __cam_req_mgr_process_sof_freeze(void *priv, void *data)
{
- struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
struct cam_req_mgr_core_link *link = NULL;
struct cam_req_mgr_core_session *session = NULL;
struct cam_req_mgr_message msg;
+ int rc = 0;
- if (!timer) {
- CAM_ERR(CAM_CRM, "NULL timer");
- return;
+ if (!data || !priv) {
+ CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
+ return -EINVAL;
}
- link = (struct cam_req_mgr_core_link *)timer->parent;
+
+ link = (struct cam_req_mgr_core_link *)priv;
session = (struct cam_req_mgr_core_session *)link->parent;
CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x",
@@ -1173,12 +1175,47 @@
msg.u.err_msg.request_id = 0;
msg.u.err_msg.link_hdl = link->link_hdl;
+ rc = cam_req_mgr_notify_message(&msg,
+ V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT);
- if (cam_req_mgr_notify_message(&msg,
- V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT))
+ if (rc)
CAM_ERR(CAM_CRM,
- "Error notifying SOF freeze for session %d link 0x%x",
- session->session_hdl, link->link_hdl);
+ "Error notifying SOF freeze for session %d link 0x%x rc %d",
+ session->session_hdl, link->link_hdl, rc);
+
+ return rc;
+}
+
+/**
+ * __cam_req_mgr_sof_freeze()
+ *
+ * @brief : Callback function for timer timeout indicating SOF freeze
+ * @data : timer pointer
+ *
+ */
+static void __cam_req_mgr_sof_freeze(unsigned long data)
+{
+ struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
+ struct crm_workq_task *task = NULL;
+ struct cam_req_mgr_core_link *link = NULL;
+ struct crm_task_payload *task_data;
+
+ if (!timer) {
+ CAM_ERR(CAM_CRM, "NULL timer");
+ return;
+ }
+
+ link = (struct cam_req_mgr_core_link *)timer->parent;
+ task = cam_req_mgr_workq_get_task(link->workq);
+ if (!task) {
+ CAM_ERR(CAM_CRM, "No empty task");
+ return;
+ }
+
+ task_data = (struct crm_task_payload *)task->payload;
+ task_data->type = CRM_WORKQ_TASK_NOTIFY_FREEZE;
+ task->process_cb = &__cam_req_mgr_process_sof_freeze;
+ cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
}
/**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 025c16a..68ec09b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -45,6 +45,7 @@
CRM_WORKQ_TASK_APPLY_REQ,
CRM_WORKQ_TASK_NOTIFY_SOF,
CRM_WORKQ_TASK_NOTIFY_ERR,
+ CRM_WORKQ_TASK_NOTIFY_FREEZE,
CRM_WORKQ_TASK_SCHED_REQ,
CRM_WORKQ_TASK_FLUSH_REQ,
CRM_WORKQ_TASK_INVALID,
diff --git a/drivers/media/platform/msm/qca402/Makefile b/drivers/media/platform/msm/qca402/Makefile
new file mode 100644
index 0000000..cffd2c4
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for MSM HTC driver.
+#
+obj-y += msm_qca402.o
diff --git a/drivers/media/platform/msm/qca402/msm_qca402.c b/drivers/media/platform/msm/qca402/msm_qca402.c
new file mode 100644
index 0000000..74b4929
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/msm_qca402.c
@@ -0,0 +1,1530 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/of_device.h>
+#include <uapi/media/msmb_qca.h>
+#include <linux/spinlock_types.h>
+#include "msm_qca402.h"
+
+#define DEVICE_NAME "msm_qca402char"
+#define DEVICE_CLASS "msm_qca402"
+#define MAX_DEVICE_NUM (1)
+#define QCA402_START_ENQ_BUFFS (8)
+#define QCA402_MAX_EVENTS_IN_MSG (16)
+#undef pr_fmt
+#define pr_fmt(fmt) "[qca402x]: %s: " fmt, __func__
+
+static int msm_qca402_major;
+static struct class *msm_qca402_class;
+struct msm_qca402_device_t {
+ struct msm_qca402_dev_data_t *dev;
+ struct task_struct *user_task;
+ struct task_struct *recv_task;
+};
+
+static struct msm_qca402_device_t msm_qca402_device[MAX_DEVICE_NUM];
+
+static const struct of_device_id msm_qca402_dt_match[] = {
+ {
+ .compatible = "qcom,qca402",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_qca402_dt_match);
+
+static int msm_qca402_open(struct inode *ip, struct file *fp)
+{
+ struct msm_qca402_dev_data_t *dev_data = container_of(ip->i_cdev,
+ struct msm_qca402_dev_data_t, cdev);
+ struct msm_qca402_file_data_t *file_data;
+ struct file_data_list_t *f_entry;
+
+ pr_debug("called for device %d\n", dev_data->dev_idx);
+
+ file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
+ if (!file_data)
+ return -EINVAL;
+ pr_debug("Out q %pK", &file_data->out_queue);
+ init_waitqueue_head(&file_data->out_queue);
+ /* initialize channel list here */
+ file_data->dev_data = dev_data;
+ INIT_LIST_HEAD(&file_data->evt_list);
+ INIT_LIST_HEAD(&file_data->ready_ch_list);
+ mutex_init(&file_data->file_mutex);
+ f_entry = kzalloc(sizeof(*f_entry), GFP_KERNEL);
+ if (!f_entry) {
+ mutex_destroy(&file_data->file_mutex);
+ kfree(file_data);
+ return -EINVAL;
+ }
+ f_entry->file_data = file_data;
+ list_add_tail(&f_entry->list, &dev_data->file_list);
+ fp->private_data = file_data;
+ return 0;
+}
+
+static void msm_qca402_free_file_data(struct msm_qca402_file_data_t *file_data)
+{
+ struct msm_qca402_evt_list_t *cur_evt, *next_evt;
+ struct msm_qca402_ready_list_t *cur_rch, *next_rch;
+
+ list_for_each_entry_safe(cur_evt, next_evt, &file_data->evt_list,
+ list) {
+ list_del_init(&cur_evt->list);
+ kfree(cur_evt);
+ break;
+ }
+ list_for_each_entry_safe(cur_rch, next_rch, &file_data->ready_ch_list,
+ list) {
+ list_del_init(&cur_rch->list);
+ kfree(cur_rch);
+ break;
+ }
+ mutex_destroy(&file_data->file_mutex);
+ kfree(file_data);
+}
+
+static void msm_qca402_release_file(struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_file_data_t *file_data)
+{
+ struct file_data_list_t *f_entry;
+ struct file_data_list_t *next;
+
+ list_for_each_entry_safe(f_entry, next, &dev_data->file_list, list) {
+ if (!file_data || f_entry->file_data == file_data) {
+ list_del_init(&f_entry->list);
+ msm_qca402_free_file_data(f_entry->file_data);
+ kfree(f_entry);
+ break;
+ }
+ }
+}
+
+static int msm_qca402_release(struct inode *ip, struct file *fp)
+{
+ struct msm_qca402_file_data_t *file_data =
+ (struct msm_qca402_file_data_t *)fp->private_data;
+ struct msm_qca402_dev_data_t *dev_data = container_of(ip->i_cdev,
+ struct msm_qca402_dev_data_t, cdev);
+
+ pr_debug("called\n");
+
+ msm_qca402_release_file(dev_data, file_data);
+
+ return 0;
+}
+
+static struct msm_qca402_channel_list_t *msm_qca402_init_channel(
+ struct msm_qca402_dev_data_t *dev_data,
+ __u32 channel_id)
+{
+ struct msm_qca402_channel_list_t *channel = NULL;
+ struct msm_qca402_channel_list_t *new_channel = NULL;
+
+ list_for_each_entry(channel, &dev_data->channel_list, list) {
+ if (channel->channel_id == channel_id) {
+ channel->ref_cnt++;
+ pr_debug("channel with %d exists\n", channel_id);
+ return channel;
+ }
+ }
+ new_channel = kzalloc(sizeof(*new_channel), GFP_KERNEL);
+ if (!new_channel)
+ return NULL;
+ new_channel->channel_id = channel_id;
+ INIT_LIST_HEAD(&new_channel->enqueued_list);
+ INIT_LIST_HEAD(&new_channel->ready_list);
+ INIT_LIST_HEAD(&new_channel->dequeued_list);
+ list_add_tail(&new_channel->list, &dev_data->channel_list);
+ new_channel->ref_cnt = 1;
+ return new_channel;
+}
+
+static void msm_qca402_free_buffer_list(struct msm_qca402_dev_data_t *dev_data,
+ struct list_head *buffer_list)
+{
+ struct msm_qca402_buffer_list_t *buffer;
+ struct msm_qca402_buffer_list_t *n_buffer;
+
+ list_for_each_entry_safe(buffer, n_buffer, buffer_list, list) {
+ if (buffer->ih)
+ ion_unmap_kernel(dev_data->ion_client, buffer->ih);
+ list_del_init(&buffer->list);
+ kfree(buffer);
+ }
+}
+
+static int msm_qca402_deinit_channel(
+ struct msm_qca402_dev_data_t *dev_data,
+ __u32 channel_id)
+{
+ struct msm_qca402_channel_list_t *channel;
+ struct msm_qca402_channel_list_t *c_channel = NULL;
+
+ list_for_each_entry(channel, &dev_data->channel_list, list) {
+ if (channel->channel_id == channel_id) {
+ c_channel = channel;
+ break;
+ }
+ }
+ if (!c_channel) {
+ pr_debug("No channel %d\n", channel_id);
+ return -EINVAL;
+ }
+ c_channel->ref_cnt--;
+ if (channel->ref_cnt)
+ return 0;
+ msm_qca402_free_buffer_list(dev_data, &channel->enqueued_list);
+ msm_qca402_free_buffer_list(dev_data, &channel->ready_list);
+ msm_qca402_free_buffer_list(dev_data, &channel->dequeued_list);
+ list_del_init(&channel->list);
+ kfree(channel);
+ return 0;
+}
+
+static void msm_qca402_unregister_events(
+ struct msm_qca402_file_data_t *file_data, int num_events,
+ struct msm_qca_event_type *evts)
+{
+ int i;
+ struct msm_qca402_evt_list_t *c_evt_entry;
+ struct msm_qca402_evt_list_t *next;
+
+ for (i = 0; i < num_events; i++) {
+ list_for_each_entry_safe(c_evt_entry, next,
+ &file_data->evt_list, list) {
+ if (c_evt_entry->channel_id == evts[i].channel_id &&
+ c_evt_entry->cmd == evts[i].cmd) {
+ pr_debug("%pK Unregistering %d %d\n", file_data,
+ c_evt_entry->channel_id,
+ c_evt_entry->cmd);
+ msm_qca402_deinit_channel(file_data->dev_data,
+ evts[i].channel_id);
+ list_del_init(&c_evt_entry->list);
+ kfree(c_evt_entry);
+ break;
+ }
+ }
+ }
+}
+
+static int msm_qca402_register_events(struct msm_qca402_file_data_t *file_data,
+ int num_events,
+ struct msm_qca_event_type *evts)
+{
+ int i;
+ int ret = 0;
+ struct msm_qca402_evt_list_t *c_evt_entry;
+
+ for (i = 0; i < num_events; i++) {
+ c_evt_entry = kzalloc(sizeof(*c_evt_entry), GFP_KERNEL);
+ if (!c_evt_entry) {
+ ret = -ENOMEM;
+ break;
+ }
+ c_evt_entry->channel_id = evts[i].channel_id;
+ c_evt_entry->cmd = evts[i].cmd;
+ pr_debug("%pK Registering %d %d\n", file_data,
+ c_evt_entry->channel_id, c_evt_entry->cmd);
+ list_add_tail(&c_evt_entry->list, &file_data->evt_list);
+ msm_qca402_init_channel(file_data->dev_data,
+ evts[i].channel_id);
+ }
+
+ if (ret)
+ msm_qca402_unregister_events(file_data, num_events, evts);
+
+ return ret;
+}
+
+static void msm_qca402_free_workbuffs(struct msm_qca402_dev_data_t *dev_data)
+{
+ struct msm_qca402_workbuff_list_t *wb;
+ struct msm_qca402_workbuff_list_t *next;
+
+ list_for_each_entry_safe(wb, next, &dev_data->work_list, list) {
+ list_del_init(&wb->list);
+ kfree(wb);
+ }
+}
+
+static int msm_qca402_alloc_add_workbuffs(
+ struct msm_qca402_dev_data_t *dev_data,
+ __u32 num_buffs)
+{
+ int ret = 0;
+ int i;
+ struct msm_qca402_workbuff_list_t *wb;
+
+ for (i = 0; i < num_buffs; i++) {
+ wb = kzalloc(sizeof(*wb), GFP_KERNEL);
+ if (!wb) {
+ ret = -ENOMEM;
+ msm_qca402_free_workbuffs(dev_data);
+ break;
+ }
+ list_add_tail(&wb->list, &dev_data->work_list);
+ }
+ return ret;
+}
+
+static struct msm_qca402_workbuff_list_t *msm_qca402_get_workbuff(
+ struct msm_qca402_dev_data_t *dev_data)
+{
+ int ret;
+ struct msm_qca402_workbuff_list_t *wb;
+
+ if (list_empty(&dev_data->work_list)) {
+ ret = msm_qca402_alloc_add_workbuffs(dev_data, 1);
+ if (ret)
+ return NULL;
+ }
+ wb = list_first_entry(&dev_data->work_list,
+ struct msm_qca402_workbuff_list_t, list);
+ list_del_init(&wb->list);
+ return wb;
+}
+
+static void msm_qca402_propagate_event(struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca_event_type *event,
+ struct msm_qca402_channel_list_t *channel)
+{
+ struct msm_qca402_file_data_t *file_data;
+ struct file_data_list_t *f_entry;
+ struct msm_qca402_evt_list_t *e_entry;
+ struct msm_qca402_ready_list_t *r_entry;
+
+ list_for_each_entry(f_entry, &dev_data->file_list, list) {
+ file_data = f_entry->file_data;
+ list_for_each_entry(e_entry, &file_data->evt_list, list) {
+ if (e_entry->channel_id == event->channel_id &&
+ e_entry->cmd == event->cmd) {
+ /**
+ * put event into queue
+ * unblock poll
+ */
+ pr_debug("%d %d\n", event->channel_id,
+ e_entry->cmd);
+ r_entry = kzalloc(sizeof(*r_entry), GFP_KERNEL);
+ if (!r_entry)
+ return;
+
+ channel->ref_cnt += 1;
+ r_entry->ch_data = channel;
+ r_entry->cmd = e_entry->cmd;
+ list_add_tail(&r_entry->list,
+ &file_data->ready_ch_list);
+ pr_debug("called\n");
+ wake_up_interruptible(&file_data->out_queue);
+ }
+ }
+ }
+}
+
+static int msm_qca402_copy_data(struct msm_qca402_htca_message_t *htca_msg,
+ struct msm_qca402_buffer_list_t *buffer,
+ __u32 size)
+{
+
+ __u32 c_payload_size = 0;
+ __u32 c_meta_size = 0;
+
+ if (size < (QCA_MSG_HEADER_SIZE + htca_msg->header.meta_size))
+ return -EINVAL;
+ c_payload_size = size - htca_msg->header.meta_size -
+ QCA_MSG_HEADER_SIZE;
+
+
+ switch (htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK) {
+ case LPCHTCA_FULL_PACKET:
+ case LPCHTCA_START_PACKET: {
+ if (buffer->valid_size > 0)
+ buffer->valid_size = 0;
+ if ((htca_msg->header.meta_size >
+ buffer->qca_msg.header_size) ||
+ (c_payload_size > buffer->qca_msg.data_size))
+ return -EINVAL;
+ c_meta_size = htca_msg->header.meta_size;
+ }
+ break;
+
+ case LPCHTCA_END_PACKET:
+ case LPCHTCA_MID_PACKET:
+ if (c_payload_size + buffer->valid_size >
+ buffer->qca_msg.data_size) {
+ /* indicate ERROR here */
+ return -EINVAL;
+ }
+ break;
+ case LPCHTCA_UNSPEC_PACKET:
+ if (c_payload_size + buffer->valid_size >
+ buffer->qca_msg.data_size) {
+ if (buffer->valid_size)
+ /* continue in next buffer */
+ return -ENOMEM;
+ else
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (c_meta_size)
+ if (copy_to_user((void __user *)
+ (uintptr_t)buffer->qca_msg.header,
+ htca_msg->payload,
+ c_meta_size))
+ return -EFAULT;
+
+ if (c_payload_size) {
+ __u8 *ptr;
+
+ if (buffer->vaddr) {
+ /* ion buffer */
+ ptr = (__u8 *)buffer->vaddr;
+ ptr += buffer->valid_size;
+ memcpy((void *)ptr,
+ &htca_msg->payload[htca_msg->header.meta_size],
+ c_payload_size);
+ } else {
+ ptr = (__u8 *)((uintptr_t)buffer->qca_msg.buff_addr);
+ ptr += buffer->valid_size;
+ if (copy_to_user((void __user *)ptr,
+ &htca_msg->payload[htca_msg->header.meta_size],
+ c_payload_size))
+ return -EFAULT;
+ }
+ buffer->valid_size += c_payload_size;
+ }
+
+ switch (htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK) {
+ case LPCHTCA_START_PACKET: {
+ buffer->qca_msg.header_size = c_meta_size;
+ }
+ break;
+
+ case LPCHTCA_FULL_PACKET: {
+ buffer->qca_msg.header_size = c_meta_size;
+ buffer->qca_msg.data_size = buffer->valid_size;
+ }
+ break;
+
+ case LPCHTCA_END_PACKET: {
+ buffer->qca_msg.data_size = buffer->valid_size;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msm_qca402_move_userbuff_to_(struct list_head *target_list,
+ struct msm_qca402_channel_list_t *ch_data)
+{
+ struct msm_qca402_buffer_list_t *c_entry;
+
+ c_entry = ch_data->current_entry;
+ if (c_entry) {
+ list_del_init(&c_entry->list);
+ list_add_tail(&c_entry->list, target_list);
+ }
+ ch_data->current_entry = NULL;
+ if (!list_empty(&ch_data->enqueued_list)) {
+ ch_data->current_entry = list_first_entry(
+ &ch_data->enqueued_list,
+ struct msm_qca402_buffer_list_t, list);
+ }
+ return 0;
+}
+
+static int msm_qca402_process_htca_message(
+ struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_workbuff_list_t *wb)
+{
+ int ret = 0;
+ int keep = 0;
+ __u8 pkt_flags;
+ struct msm_qca402_htca_message_t *htca_msg = &wb->htca_msg;
+ struct msm_qca402_channel_list_t *ch_data_cur;
+ struct msm_qca402_channel_list_t *ch_data = NULL;
+
+ pr_debug("wb %pK %d\n", htca_msg,
+ htca_msg->header.channel_id);
+ list_for_each_entry(ch_data_cur, &dev_data->channel_list, list) {
+ if (ch_data_cur->channel_id == htca_msg->header.channel_id) {
+ ch_data = ch_data_cur;
+ break;
+ }
+ }
+ if (!ch_data && !(htca_msg->header.msg_flags & LPCHTCA_ASYNC_MESSAGE)) {
+ /* No registered handler and not ASYNC message, drop packet */
+ goto return_wb;
+ } else if (!ch_data) {
+ /* if ASYNC message with no registered handler, add it */
+ ch_data = msm_qca402_init_channel(dev_data,
+ htca_msg->header.channel_id);
+ if (!ch_data)
+ return -EINVAL;
+ }
+ if (!ch_data->has_buff &&
+ !(htca_msg->header.msg_flags & LPCHTCA_FULL_PACKET)) {
+ /* data packet but no free enqueued buffers, drop packet */
+ /* indicate ERROR here */
+ goto return_wb;
+ } else if (ch_data->has_buff) {
+ if (!ch_data->current_entry) {
+ pr_debug("NO CURRENT ENTRY\n");
+ return -EINVAL;
+ }
+ /* data packet and there is enqueued buffer start filling it */
+ ret = msm_qca402_copy_data(htca_msg, ch_data->current_entry,
+ wb->size);
+ pkt_flags = htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK;
+ if ((pkt_flags == LPCHTCA_UNSPEC_PACKET && ret == -ENOMEM) ||
+ (pkt_flags == LPCHTCA_FULL_PACKET) ||
+ (pkt_flags == LPCHTCA_END_PACKET) ||
+ (htca_msg->header.msg_flags &
+ LPCHTCA_END_TRANSMISSON)) {
+ struct msm_qca_event_type event;
+
+ event.cmd = MSM_QCA_EVENT_ENQ_BUF;
+ event.channel_id = ch_data->channel_id;
+ msm_qca402_move_userbuff_to_(&ch_data->ready_list,
+ ch_data);
+ msm_qca402_propagate_event(dev_data, &event, ch_data);
+ }
+ if (ret == -ENOMEM) {
+ ret = msm_qca402_copy_data(htca_msg,
+ ch_data->current_entry, wb->size);
+ }
+ } else {
+ struct msm_qca_event_type event;
+
+ /* control message, save for future receiving */
+ keep = 1;
+ ch_data->wbout = wb;
+ event.cmd = MSM_QCA_EVENT_RECV_MSG;
+ event.channel_id = ch_data->channel_id;
+ msm_qca402_propagate_event(dev_data, &event, ch_data);
+ }
+
+return_wb:
+ if (!keep)
+ list_add_tail(&wb->list, &dev_data->work_list);
+ return ret;
+}
+
+static struct msm_qca402_channel_list_t *msm_qca402_find_channel(
+ struct msm_qca402_dev_data_t *dev_data,
+ __u32 channel_id)
+{
+ struct msm_qca402_channel_list_t *ch_data;
+
+ list_for_each_entry(ch_data, &dev_data->channel_list, list) {
+ if (ch_data->channel_id == channel_id)
+ return ch_data;
+ }
+
+ return NULL;
+}
+
+static int msm_qca402_copy_header(struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_buffer_list_t *buff,
+ struct msm_qca_message_type *data)
+{
+ buff->wbb = msm_qca402_get_workbuff(dev_data);
+ if (!buff->wbb)
+ return -ENOMEM;
+
+ if (data->header_size <= QCA_MSG_PAYLOAD_SIZE) {
+ if (copy_from_user(
+ (void *)&buff->wbb->htca_msg.payload[0],
+ (void __user *)(uintptr_t)data->header,
+ data->header_size))
+ return -EFAULT;
+ buff->wbb->htca_msg.header.meta_size =
+ data->header_size;
+ } else
+ return -EINVAL;
+ return 0;
+}
+
+static struct msm_qca402_buffer_list_t *msm_qca402_deq_map_buff(
+ struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_channel_list_t *ch_data,
+ struct msm_qca_message_type *data)
+{
+ int ret;
+ struct msm_qca402_buffer_list_t *buff;
+
+ list_for_each_entry(buff, &ch_data->dequeued_list, list) {
+ if (buff->qca_msg.fd == data->fd) {
+ list_del_init(&buff->list);
+ if (!ch_data->has_buff) {
+ ret = msm_qca402_copy_header(dev_data, buff,
+ data);
+ if (ret < 0)
+ return NULL;
+ }
+ buff->qca_msg = *data;
+ return buff;
+ }
+ }
+ buff = kzalloc(sizeof(*buff), GFP_KERNEL);
+ if (!buff)
+ return NULL;
+ if (!ch_data->has_buff) {
+ ret = msm_qca402_copy_header(dev_data, buff, data);
+ if (ret < 0)
+ return NULL;
+ }
+ buff->qca_msg = *data;
+ if (data->is_ion_data) {
+ buff->ih = ion_import_dma_buf_fd(dev_data->ion_client,
+ data->fd);
+ buff->vaddr = ion_map_kernel(dev_data->ion_client, buff->ih);
+ }
+
+ return buff;
+}
+
+static unsigned int msm_qca402_recv_message(
+ struct msm_qca402_file_data_t *file,
+ struct msm_qca_message_type *data)
+{
+ struct msm_qca402_channel_list_t *channel;
+ struct msm_qca402_ready_list_t *rq_entry;
+ struct msm_qca402_buffer_list_t *buffer;
+ int ret = 0;
+
+ if (list_empty(&file->ready_ch_list))
+ return -ENODATA;
+ rq_entry = list_first_entry(&file->ready_ch_list,
+ struct msm_qca402_ready_list_t, list);
+ channel = rq_entry->ch_data;
+ list_del_init(&rq_entry->list);
+ kfree(rq_entry);
+
+ if (!list_empty(&channel->ready_list)) {
+ buffer = list_first_entry(&channel->ready_list,
+ struct msm_qca402_buffer_list_t, list);
+ *data = buffer->qca_msg;
+ if (channel->has_buff)
+ data->cmd = MSM_QCA_EVENT_ENQ_BUF;
+ else
+ data->cmd = MSM_QCA_EVENT_SEND_MSG;
+ list_del_init(&buffer->list);
+ buffer->valid_size = 0;
+ channel->ref_cnt--;
+ list_add_tail(&buffer->list, &channel->dequeued_list);
+ } else if (channel->wbout) {
+ data->channel_id = channel->channel_id;
+ data->is_ion_data = 0;
+ data->data_size = 0;
+ if (data->header_size >=
+ channel->wbout->htca_msg.header.meta_size) {
+ data->header_size =
+ channel->wbout->htca_msg.header.meta_size;
+ data->cmd = MSM_QCA_EVENT_RECV_MSG;
+ if (copy_to_user((void __user *)(uintptr_t)data->header,
+ channel->wbout->htca_msg.payload,
+ channel->wbout->htca_msg.header.meta_size)) {
+ list_add_tail(&channel->wbout->list,
+ &file->dev_data->work_list);
+ return -EFAULT;
+ }
+ channel->ref_cnt--;
+ list_add_tail(&channel->wbout->list,
+ &file->dev_data->work_list);
+ } else {
+ ret = -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static __u8 msm_qca402_fill_wb(
+ struct msm_qca402_buffer_list_t *buff,
+ struct msm_qca402_workbuff_list_t *wb)
+{
+ __u32 total_size = buff->qca_msg.header_size +
+ buff->qca_msg.data_size;
+ __u32 write_size = 0;
+ __u8 *ptr;
+
+ wb->htca_msg.header.msg_flags = 0;
+
+ wb->htca_msg.header.channel_id = buff->qca_msg.channel_id;
+
+ pr_debug("valid size %d total %d\n", buff->valid_size, total_size);
+ if (buff->valid_size == 0) {
+ if (total_size <= QCA_MSG_PAYLOAD_SIZE)
+ wb->htca_msg.header.msg_flags = LPCHTCA_FULL_PACKET;
+ else
+ wb->htca_msg.header.msg_flags = LPCHTCA_START_PACKET;
+ write_size = min(QCA_MSG_PAYLOAD_SIZE -
+ wb->htca_msg.header.meta_size,
+ buff->qca_msg.data_size);
+ } else {
+ wb->htca_msg.header.meta_size = 0;
+ if (total_size - buff->valid_size <= QCA_MSG_PAYLOAD_SIZE)
+ wb->htca_msg.header.msg_flags = LPCHTCA_END_PACKET;
+ else
+ wb->htca_msg.header.msg_flags = LPCHTCA_MID_PACKET;
+ write_size = min(QCA_MSG_PAYLOAD_SIZE,
+ buff->qca_msg.data_size - buff->valid_size);
+ }
+ if (buff->vaddr) {
+ ptr = (__u8 *)buff->vaddr + buff->valid_size;
+ memcpy(&wb->htca_msg.payload[wb->htca_msg.header.meta_size],
+ (void *)ptr, write_size);
+ } else {
+ ptr = (__u8 *)((uintptr_t)buff->qca_msg.buff_addr) +
+ buff->valid_size;
+ if (copy_from_user(
+ &wb->htca_msg.payload[wb->htca_msg.header.meta_size],
+ (void __user *)ptr, write_size))
+ return -EFAULT;
+ }
+ buff->valid_size += write_size;
+ wb->size = QCA_MSG_HEADER_SIZE + wb->htca_msg.header.meta_size +
+ write_size;
+ if (buff->qca_msg.last_data &&
+ ((wb->htca_msg.header.msg_flags == LPCHTCA_FULL_PACKET) ||
+ (wb->htca_msg.header.msg_flags == LPCHTCA_END_PACKET)))
+ wb->htca_msg.header.msg_flags |= LPCHTCA_END_TRANSMISSON;
+
+ pr_debug("flags %x\n", wb->htca_msg.header.msg_flags);
+ return wb->htca_msg.header.msg_flags;
+}
+static unsigned int msm_qca402_process_wb(
+ struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_channel_list_t *ch_data,
+ struct msm_qca402_buffer_list_t *buff,
+ struct msm_qca402_workbuff_list_t **wb)
+{
+ __u8 flags;
+ struct msm_qca_event_type event;
+
+ if (!*wb)
+ *wb = msm_qca402_get_workbuff(dev_data);
+
+ flags = msm_qca402_fill_wb(buff, *wb);
+
+ if ((flags & LPCHTCA_PACKET_MASK) == LPCHTCA_FULL_PACKET ||
+ (flags & LPCHTCA_PACKET_MASK) == LPCHTCA_END_PACKET) {
+ msm_qca402_move_userbuff_to_(&ch_data->ready_list,
+ ch_data);
+ event.cmd = MSM_QCA_EVENT_SEND_MSG;
+ event.channel_id = ch_data->channel_id;
+ msm_qca402_propagate_event(dev_data, &event, ch_data);
+ return 1;
+ }
+
+ return 0;
+}
+
+static unsigned int msm_qca402_send_htca_message(
+ struct msm_qca402_dev_data_t *dev_data,
+ struct msm_qca402_channel_list_t *ch_data)
+{
+ int status;
+ int ret;
+ struct msm_qca402_buffer_list_t *buff = ch_data->current_entry;
+ struct msm_qca402_workbuff_list_t *wb = NULL;
+
+
+ wb = ch_data->wbin;
+ if (!wb) {
+ if (!buff)
+ return -EINVAL;
+ wb = buff->wbb;
+ if (!wb) {
+ pr_err("Incorrect header error\n");
+ return -EINVAL;
+ }
+ ret = msm_qca402_process_wb(dev_data, ch_data, buff,
+ &wb);
+ if (!wb)
+ return -EINVAL;
+ buff->wbb = NULL;
+ }
+
+ pr_debug("send %d\n", wb->size);
+ dev_data->sending++;
+ status = htca_buffer_send(dev_data->htca_target, 0,
+ (void *)&wb->htca_msg.header, wb->size, wb);
+ ch_data->wbin = NULL;
+ if (status)
+ return -EINVAL;
+ if (((wb->htca_msg.header.msg_flags & LPCHTCA_PACKET_MASK) ==
+ LPCHTCA_FULL_PACKET) ||
+ ((wb->htca_msg.header.msg_flags & LPCHTCA_PACKET_MASK) ==
+ LPCHTCA_END_PACKET)) {
+ return 0;
+ }
+
+ if (!buff)
+ return -EINVAL;
+ ret = msm_qca402_process_wb(dev_data, ch_data, buff, &ch_data->wbin);
+
+ return -EAGAIN;
+}
+
+
+static unsigned int msm_qca402_poll(struct file *fp, poll_table *wait)
+{
+ struct msm_qca402_file_data_t *file_data =
+ (struct msm_qca402_file_data_t *)fp->private_data;
+ unsigned int mask = 0;
+
+ pr_debug("called %pK\n", &file_data->out_queue);
+ poll_wait(fp, &file_data->out_queue, wait);
+ if (!list_empty(&file_data->ready_ch_list))
+ mask = POLLIN | POLLRDNORM;
+ return mask;
+}
+
+static struct msm_qca_event_type *msm_qca402_alloc_get_evts(
+ struct msm_qca_event_list_type *evt_list)
+{
+ int len = sizeof(struct msm_qca_event_type) *
+ evt_list->num_events;
+ struct msm_qca_event_type *evts;
+
+ if (evt_list->num_events > QCA402_MAX_EVENTS_IN_MSG)
+ return NULL;
+ evts = kzalloc(len, GFP_KERNEL);
+ if (!evts)
+ return NULL;
+ if (copy_from_user((void *)evts,
+ (void __user *)(uintptr_t)evt_list->events,
+ len)) {
+ kfree(evts);
+ return NULL;
+ }
+ return evts;
+}
+
+static int msm_qca402_abort(struct msm_qca402_file_data_t *file_data,
+ int num_events, struct msm_qca_event_type *evts) {
+ return 0;
+}
+
+static int msm_qca402_flush(struct msm_qca402_file_data_t *file_data,
+ int num_events, struct msm_qca_event_type *evts) {
+ return 0;
+}
+
+static long msm_qca402_ioctl(struct file *file, unsigned int cmd,
+ void *arg)
+{
+ struct msm_qca402_file_data_t *file_data =
+ (struct msm_qca402_file_data_t *)file->private_data;
+ long ret = 0;
+
+ switch (cmd) {
+ case MSM_QCA402X_ENQUEUE_BUFFER: {
+ struct msm_qca_message_type *data =
+ (struct msm_qca_message_type *)arg;
+ struct msm_qca402_buffer_list_t *buff;
+ struct msm_qca402_channel_list_t *ch_data;
+
+ pr_debug("MSM_QCA402X_ENQUEUE_BUFFER\n");
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ ch_data = msm_qca402_find_channel(file_data->dev_data,
+ data->channel_id);
+ if (!ch_data) {
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ return -EINVAL;
+ }
+ ch_data->has_buff = 1;
+ buff = msm_qca402_deq_map_buff(file_data->dev_data, ch_data,
+ data);
+ if (!buff) {
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ return -ENOMEM;
+ }
+ list_add_tail(&buff->list, &ch_data->enqueued_list);
+ if (!ch_data->current_entry)
+ ch_data->current_entry = list_first_entry(
+ &ch_data->enqueued_list,
+ struct msm_qca402_buffer_list_t, list);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ }
+ break;
+ case MSM_QCA402X_SEND_MESSAGE: {
+ struct msm_qca_message_type *data =
+ (struct msm_qca_message_type *)arg;
+ struct msm_qca402_buffer_list_t *buff;
+ struct msm_qca402_channel_list_t *ch_data;
+ struct msm_qca402_ready_list_t *r_entry;
+
+ pr_debug("MSM_QCA402X_SEND_MESSAGE\n");
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ ch_data = msm_qca402_find_channel(file_data->dev_data,
+ data->channel_id);
+ if (!ch_data) {
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ return -EINVAL;
+ }
+ ch_data->has_buff = 0;
+ buff = msm_qca402_deq_map_buff(file_data->dev_data, ch_data,
+ data);
+ if (!buff) {
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ return -ENOMEM;
+ }
+ r_entry = kzalloc(sizeof(*r_entry), GFP_KERNEL);
+ if (!r_entry) {
+ list_add_tail(&buff->list, &ch_data->dequeued_list);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ return -ENOMEM;
+ }
+ ch_data->ref_cnt += 1;
+ list_add_tail(&buff->list, &ch_data->enqueued_list);
+ r_entry->ch_data = ch_data;
+ list_add_tail(&r_entry->list, &file_data->dev_data->in_list);
+ if (!ch_data->current_entry)
+ ch_data->current_entry = list_first_entry(
+ &ch_data->enqueued_list,
+ struct msm_qca402_buffer_list_t, list);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+
+ wake_up_interruptible(&file_data->dev_data->in_queue);
+ }
+ break;
+ case MSM_QCA402X_RECEIVE_MESSAGE: {
+ struct msm_qca_message_type *data =
+ (struct msm_qca_message_type *)arg;
+ pr_debug("MSM_QCA402X_RECEIVE_MESSAGE\n");
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ ret = msm_qca402_recv_message(file_data, data);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ }
+ break;
+ case MSM_QCA402X_REGISTER_EVENT: {
+ struct msm_qca_event_list_type *evt_list =
+ (struct msm_qca_event_list_type *)arg;
+ struct msm_qca_event_type *evts;
+
+ pr_debug("MSM_QCA402X_REGISTER_EVENT\n");
+
+ evts = msm_qca402_alloc_get_evts(evt_list);
+ if (!evts)
+ return -ENOMEM;
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ ret = msm_qca402_register_events(file_data,
+ evt_list->num_events,
+ evts);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ kfree(evts);
+ }
+ break;
+ case MSM_QCA402X_UNREGISTER_EVENT: {
+ struct msm_qca_event_list_type *evt_list =
+ (struct msm_qca_event_list_type *)arg;
+ struct msm_qca_event_type *evts;
+
+ pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+ evts = msm_qca402_alloc_get_evts(evt_list);
+ if (!evts)
+ return -ENOMEM;
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ msm_qca402_unregister_events(file_data, evt_list->num_events,
+ evts);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ kfree(evts);
+ }
+ break;
+ case MSM_QCA402X_FLUSH_BUFFERS: {
+ struct msm_qca_event_list_type *evt_list =
+ (struct msm_qca_event_list_type *)arg;
+ struct msm_qca_event_type *evts;
+
+ pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+ evts = msm_qca402_alloc_get_evts(evt_list);
+ if (!evts)
+ return -ENOMEM;
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ msm_qca402_flush(file_data, evt_list->num_events, evts);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ kfree(evts);
+ }
+ break;
+
+ case MSM_QCA402X_ABORT_MESSAGE: {
+ struct msm_qca_event_list_type *evt_list =
+ (struct msm_qca_event_list_type *)arg;
+ struct msm_qca_event_type *evts;
+
+ pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+ evts = msm_qca402_alloc_get_evts(evt_list);
+ if (!evts)
+ return -ENOMEM;
+ mutex_lock(&file_data->dev_data->dev_mutex);
+ msm_qca402_abort(file_data, evt_list->num_events, evts);
+ mutex_unlock(&file_data->dev_data->dev_mutex);
+ kfree(evts);
+ }
+ break;
+ default:
+ pr_debug("unhandled ioctl command: %d\n", cmd);
+ }
+ return ret;
+}
+static long msm_qca402_unlocked_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+ __u32 len = 0;
+
+ switch (cmd) {
+ case MSM_QCA402X_ENQUEUE_BUFFER:
+ case MSM_QCA402X_SEND_MESSAGE:
+ case MSM_QCA402X_RECEIVE_MESSAGE: {
+ struct msm_qca_message_type data;
+
+ len = sizeof(struct msm_qca_message_type);
+ if (copy_from_user(&data, (void __user *)arg, len))
+ return -EFAULT;
+ ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+ if (copy_to_user((void __user *)arg, &data, len))
+ return -EFAULT;
+ }
+ break;
+ case MSM_QCA402X_FLUSH_BUFFERS:
+ case MSM_QCA402X_ABORT_MESSAGE:
+ case MSM_QCA402X_REGISTER_EVENT:
+ case MSM_QCA402X_UNREGISTER_EVENT: {
+ struct msm_qca_event_list_type data;
+
+ len = sizeof(struct msm_qca_event_list_type);
+ if (copy_from_user(&data, (void __user *)arg, len))
+ return -EFAULT;
+ ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+ if (copy_to_user((void __user *)arg, &data, len))
+ return -EFAULT;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+#ifdef CONFIG_COMPAT
+struct msm_qca_message_type_32 {
+ __u64 header;
+ __u64 buff_addr;
+ __u32 header_size;
+ __u32 data_size;
+ int fd;
+ __u8 cmd;
+ __u8 channel_id;
+ __u8 is_ion_data;
+ __u8 last_data;
+};
+
+struct msm_qca_event_list_type_32 {
+ __u64 events;
+ __u32 num_events;
+};
+
+#define MSM_QCA402X_ENQUEUE_BUFFER_COMPAT \
+ _IOWR(0xdd, 1, struct msm_qca_message_type_32)
+#define MSM_QCA402X_SEND_MESSAGE_COMPAT \
+ _IOWR(0xdd, 2, struct msm_qca_message_type_32)
+#define MSM_QCA402X_RECEIVE_MESSAGE_COMPAT \
+ _IOWR(0xdd, 3, struct msm_qca_message_type_32)
+#define MSM_QCA402X_FLUSH_BUFFERS_COMPAT \
+ _IOWR(0xdd, 4, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_ABORT_MESSAGE_COMPAT \
+ _IOWR(0xdd, 5, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_REGISTER_EVENT_COMPAT \
+ _IOWR(0xdd, 6, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_UNREGISTER_EVENT_COMPAT \
+ _IOWR(0xdd, 7, struct msm_qca_event_list_type_32)
+
+static long msm_qca402_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+
+ pr_debug("called\n");
+
+ switch (cmd) {
+ case MSM_QCA402X_ENQUEUE_BUFFER_COMPAT:
+ case MSM_QCA402X_SEND_MESSAGE_COMPAT:
+ case MSM_QCA402X_RECEIVE_MESSAGE_COMPAT: {
+ struct msm_qca_message_type_32 data32;
+ struct msm_qca_message_type data;
+ __u32 len = 0;
+
+ len = sizeof(struct msm_qca_message_type_32);
+ if (copy_from_user(&data32, (void __user *)arg, len))
+ return -EFAULT;
+ data.channel_id = data32.channel_id;
+ data.is_ion_data = data32.is_ion_data;
+ data.header_size = data32.header_size;
+ data.fd = data32.fd;
+ data.data_size = data32.data_size;
+ data.cmd = data32.cmd;
+ data.last_data = data32.last_data;
+ data.header = compat_ptr(data32.header);
+ data.buff_addr = compat_ptr(data32.buff_addr);
+
+ ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+
+ data32.header_size = data.header_size;
+ data32.fd = data.fd;
+ data32.data_size = data.data_size;
+ if (copy_to_user((void __user *)arg, (void *)&data32, len))
+ return -EFAULT;
+ }
+ break;
+ case MSM_QCA402X_FLUSH_BUFFERS_COMPAT:
+ case MSM_QCA402X_ABORT_MESSAGE_COMPAT:
+ case MSM_QCA402X_REGISTER_EVENT_COMPAT:
+ case MSM_QCA402X_UNREGISTER_EVENT_COMPAT: {
+ struct msm_qca_event_list_type_32 data32;
+ struct msm_qca_event_list_type data;
+ int i;
+
+ len = sizeof(struct msm_qca_event_list_type_32);
+ if (copy_from_user(&data32, (void __user *)arg, len))
+ return -EFAULT;
+ data.num_events = data32.num_events;
+ for (i = 0; i < data.num_events; i++)
+ data.events[i] = data32.events[i];
+ ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+#endif
+
+static void msm_qca402_send_msg_hndl(void *target, __u8 epid,
+ __u8 eventid, struct htca_event_info *event_info,
+ void *context)
+{
+ struct msm_qca402_dev_data_t *dev_data =
+ (struct msm_qca402_dev_data_t *)context;
+ struct msm_qca402_workbuff_list_t *wb;
+
+ wb = (struct msm_qca402_workbuff_list_t *)event_info->cookie;
+ if ((!wb) || (!dev_data))
+ return;
+
+ wake_up_interruptible(&dev_data->in_queue);
+
+ mutex_lock(&dev_data->dev_mutex);
+ dev_data->sending--;
+ list_add_tail(&wb->list, &dev_data->work_list);
+ mutex_unlock(&dev_data->dev_mutex);
+
+}
+
+static void msm_qca402_recv_msg_hndl(void *target, __u8 epid,
+ __u8 eventid, struct htca_event_info *event_info,
+ void *context)
+{
+ struct msm_qca402_dev_data_t *dev_data =
+ (struct msm_qca402_dev_data_t *)context;
+ struct msm_qca402_workbuff_list_t *wb;
+
+ wb = (struct msm_qca402_workbuff_list_t *)event_info->cookie;
+ if ((!wb) || (!dev_data))
+ return;
+
+ mutex_lock(&dev_data->dev_mutex);
+ dev_data->receiving--;
+ wb->size = event_info->actual_length;
+ list_add_tail(&wb->list, &dev_data->recv_list);
+ mutex_unlock(&dev_data->dev_mutex);
+ if (dev_data->sending < dev_data->receiving)
+ wake_up_interruptible(&dev_data->in_queue);
+ wake_up_interruptible(&dev_data->recv_queue);
+}
+
+static void msm_qca402_data_avl_hndl(void *target, __u8 epid,
+ __u8 eventid, struct htca_event_info *event_info,
+ void *context)
+{
+ pr_debug("started\n");
+}
+
+static int msm_qca402_htca_recv_thread(void *hdl)
+{
+
+ int wait;
+ struct msm_qca402_dev_data_t *dev_data =
+ (struct msm_qca402_dev_data_t *)hdl;
+ struct msm_qca402_workbuff_list_t *wb_prev, *wb_curr;
+ int status;
+
+ pr_debug("start waiting\n");
+
+ while (!kthread_should_stop()) {
+ wait = wait_event_interruptible(dev_data->recv_queue,
+ !list_empty(&dev_data->recv_list) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ pr_debug("rcvd\n");
+ mutex_lock(&dev_data->dev_mutex);
+ wb_prev = list_first_entry(&dev_data->recv_list,
+ struct msm_qca402_workbuff_list_t, list);
+ list_del_init(&wb_prev->list);
+
+ wb_curr = msm_qca402_get_workbuff(dev_data);
+ status = htca_buffer_receive(dev_data->htca_target, 0,
+ (void *)&wb_curr->htca_msg, HTCA_MAX_BUFF_SIZE,
+ wb_curr);
+ dev_data->receiving++;
+
+ if (status)
+ pr_err("Receive error\n");
+
+ msm_qca402_process_htca_message(dev_data, wb_prev);
+ mutex_unlock(&dev_data->dev_mutex);
+
+ }
+
+ return 0;
+}
+
+
+static int msm_qca402_htca_user_thread(void *hdl)
+{
+ int ret, wait, i;
+ struct msm_qca402_dev_data_t *dev_data =
+ (struct msm_qca402_dev_data_t *)hdl;
+ struct msm_qca402_ready_list_t *r_entry;
+ struct msm_qca402_channel_list_t *ch_data = NULL;
+ struct msm_qca402_workbuff_list_t *wb;
+ int status;
+
+ pr_debug("started EP\n");
+ ret = htca_start(dev_data->htca_target);
+ WARN_ON(ret);
+ htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_BUFFER_SENT,
+ msm_qca402_send_msg_hndl, dev_data);
+ htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_BUFFER_RECEIVED,
+ msm_qca402_recv_msg_hndl, dev_data);
+ htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_DATA_AVAILABLE,
+ msm_qca402_data_avl_hndl, dev_data);
+ pr_debug("start waiting\n");
+
+
+ for (i = 0; i < QCA402_START_ENQ_BUFFS; i++) {
+ wb = msm_qca402_get_workbuff(dev_data);
+ status = htca_buffer_receive(dev_data->htca_target, 0,
+ (void *)&wb->htca_msg, HTCA_MAX_BUFF_SIZE, wb);
+ }
+
+ dev_data->receiving += QCA402_START_ENQ_BUFFS;
+
+ while (!kthread_should_stop()) {
+ wait = wait_event_interruptible(dev_data->in_queue,
+ ((!list_empty(&dev_data->in_list) || ch_data) &&
+ (dev_data->sending < dev_data->receiving)) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ mutex_lock(&dev_data->dev_mutex);
+ if (!ch_data) {
+ r_entry = list_first_entry(&dev_data->in_list,
+ struct msm_qca402_ready_list_t, list);
+
+ ch_data = r_entry->ch_data;
+ list_del_init(&r_entry->list);
+ kfree(r_entry);
+ }
+ ret = msm_qca402_send_htca_message(dev_data, ch_data);
+ if (ret == -EINVAL) {
+ pr_err("Error during message send\n");
+ ch_data = NULL;
+ } else if (ret == 0) {
+ pr_debug("Message sent\n");
+ ch_data->ref_cnt--;
+ ch_data = NULL;
+ }
+ mutex_unlock(&dev_data->dev_mutex);
+ }
+
+ return 0;
+}
+
+static const struct file_operations msm_qca402_ops = {
+ .open = msm_qca402_open,
+ .poll = msm_qca402_poll,
+ .release = msm_qca402_release,
+ .unlocked_ioctl = msm_qca402_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = msm_qca402_compat_ioctl,
+#endif
+};
+
+static int msm_qca402_create_device(struct msm_qca402_dev_data_t **dv,
+ int minor)
+{
+ int ret;
+ char name[20];
+
+ *dv = kzalloc(sizeof(**dv), GFP_KERNEL);
+ if (!*dv)
+ return -ENOMEM;
+ snprintf(name, sizeof(name), "%s%d", DEVICE_NAME, minor);
+ pr_debug("called for device %s\n", name);
+ (*dv)->dev = device_create(msm_qca402_class, NULL,
+ MKDEV(msm_qca402_major, minor), NULL, name);
+ if (IS_ERR((*dv)->dev)) {
+ ret = PTR_ERR((*dv)->dev);
+ kfree(*dv);
+ *dv = NULL;
+ return ret;
+ }
+ cdev_init(&(*dv)->cdev, &msm_qca402_ops);
+ ret = cdev_add(&(*dv)->cdev, MKDEV(msm_qca402_major, minor), 1);
+ if (ret < 0) {
+ device_unregister((*dv)->dev);
+ kfree(*dv);
+ *dv = NULL;
+ }
+
+ return ret;
+}
+
+static void msm_qca402_destroy_device(struct msm_qca402_dev_data_t *dv)
+{
+ pr_debug("called\n");
+ cdev_del(&dv->cdev);
+ device_unregister(dv->dev);
+ kfree(dv);
+}
+
+static void msm_qca402_trgt_avail_hndl(void *target, __u8 epid,
+ __u8 eventid, struct htca_event_info *event_info,
+ void *context)
+{
+ struct msm_qca402_dev_data_t *dev_data;
+ dev_t devid;
+ int ret;
+ int i;
+
+ pr_debug("started\n");
+ /* get the actual number from dts */
+ ret = alloc_chrdev_region(&devid, 0, MAX_DEVICE_NUM, DEVICE_NAME);
+ if (ret < 0)
+ goto register_error;
+ msm_qca402_major = MAJOR(devid);
+ msm_qca402_class = class_create(THIS_MODULE, DEVICE_CLASS);
+ if (IS_ERR(msm_qca402_class)) {
+ ret = PTR_ERR(msm_qca402_class);
+ goto class_error;
+ }
+ for (i = 0; i < MAX_DEVICE_NUM; i++) {
+ ret = msm_qca402_create_device(&msm_qca402_device[i].dev,
+ i + MINOR(devid));
+ if (ret < 0)
+ goto device_error;
+ dev_data = msm_qca402_device[i].dev;
+ dev_data->dev_idx = i;
+ dev_data->ion_client =
+ msm_ion_client_create("qca_ion_client");
+ if (IS_ERR_OR_NULL(dev_data->ion_client)) {
+ msm_qca402_destroy_device(dev_data);
+ msm_qca402_device[i].dev = NULL;
+ goto device_error;
+ }
+
+ init_waitqueue_head(&dev_data->in_queue);
+ init_waitqueue_head(&dev_data->recv_queue);
+
+ pr_debug("ion done\n");
+ INIT_LIST_HEAD(&dev_data->file_list);
+ INIT_LIST_HEAD(&dev_data->channel_list);
+ INIT_LIST_HEAD(&dev_data->work_list);
+ INIT_LIST_HEAD(&dev_data->recv_list);
+ INIT_LIST_HEAD(&dev_data->in_list);
+ ret = msm_qca402_alloc_add_workbuffs(dev_data,
+ QCA402_MIN_NUM_WORKBUFS);
+ if (ret < 0)
+ goto device_error;
+ pr_debug("lists done\n");
+ mutex_init(&dev_data->dev_mutex);
+ spin_lock_init(&dev_data->lock);
+ pr_debug("device[%d] %pK\n", i, dev_data);
+ dev_data->htca_target = target;
+ }
+
+ for (i = 0; i < MAX_DEVICE_NUM; i++) {
+ msm_qca402_device[i].user_task = kthread_create(
+ msm_qca402_htca_user_thread, dev_data, "qca402_user");
+ msm_qca402_device[i].recv_task = kthread_create(
+ msm_qca402_htca_recv_thread, dev_data, "qca402_recv");
+ wake_up_process(msm_qca402_device[i].user_task);
+ wake_up_process(msm_qca402_device[i].recv_task);
+ }
+ return;
+
+device_error:
+ for (--i; i >= 0; i--) {
+ if (msm_qca402_device[i].dev) {
+ mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+ msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+ ion_client_destroy(
+ msm_qca402_device[i].dev->ion_client);
+ msm_qca402_destroy_device(msm_qca402_device[i].dev);
+ msm_qca402_device[i].dev = NULL;
+ }
+ }
+ class_destroy(msm_qca402_class);
+class_error:
+ unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+register_error:
+ pr_err("error: %d\n", ret);
+}
+
+static void msm_qca402_trgt_unavail_hndl(void *target, __u8 epid,
+ __u8 eventid, struct htca_event_info *event_info,
+ void *context)
+{
+ int i;
+
+ for (i = 0; i < MAX_DEVICE_NUM; i++) {
+ if (msm_qca402_device[i].dev) {
+ kthread_stop(msm_qca402_device[i].user_task);
+ kthread_stop(msm_qca402_device[i].recv_task);
+ htca_stop(msm_qca402_device[i].dev->htca_target);
+ mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+ msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+ ion_client_destroy(
+ msm_qca402_device[i].dev->ion_client);
+ msm_qca402_destroy_device(msm_qca402_device[i].dev);
+ msm_qca402_device[i].dev = NULL;
+ }
+ }
+ class_unregister(msm_qca402_class);
+ class_destroy(msm_qca402_class);
+ unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+}
+
+static int msm_qca402_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match_dev;
+ int status;
+
+ if (pdev->dev.of_node) {
+ pr_debug("device found\n");
+ match_dev = of_match_device(pdev->dev.driver->of_match_table,
+ &pdev->dev);
+ }
+
+ pr_debug("called\n");
+ if (htca_init())
+ return -EINVAL;
+
+ pr_debug("register\n");
+ status = htca_event_reg(NULL, 0, HTCA_EVENT_TARGET_AVAILABLE,
+ msm_qca402_trgt_avail_hndl, NULL);
+ if (status != HTCA_OK)
+ return -EINVAL;
+ status = htca_event_reg(NULL, 0, HTCA_EVENT_TARGET_UNAVAILABLE,
+ msm_qca402_trgt_unavail_hndl, NULL);
+ if (status != HTCA_OK)
+ return -EINVAL;
+ pr_debug("register_end\n");
+
+ return 0;
+}
+
+static int msm_qca402_remove(struct platform_device *pdev)
+{
+ int i, stop_flag = 0;
+
+ for (i = 0; i < MAX_DEVICE_NUM; i++) {
+ if (msm_qca402_device[i].dev) {
+ stop_flag = 1;
+ kthread_stop(msm_qca402_device[i].user_task);
+ kthread_stop(msm_qca402_device[i].recv_task);
+ htca_stop(msm_qca402_device[i].dev->htca_target);
+ mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+ msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+ ion_client_destroy(
+ msm_qca402_device[i].dev->ion_client);
+ msm_qca402_destroy_device(msm_qca402_device[i].dev);
+ msm_qca402_device[i].dev = NULL;
+ }
+ }
+ if (stop_flag) {
+ class_unregister(msm_qca402_class);
+ class_destroy(msm_qca402_class);
+ unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+ }
+ htca_shutdown();
+ return 0;
+}
+
+static struct platform_driver msm_qca402_driver = {
+ .probe = msm_qca402_probe,
+ .remove = msm_qca402_remove,
+ .driver = {
+ .name = "msm_qca402",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_qca402_dt_match,
+ },
+};
+
+static int __init msm_qca402_init(void)
+{
+ platform_driver_register(&msm_qca402_driver);
+ return 0;
+}
+
+static void __exit msm_qca402_exit(void)
+{
+}
+
+module_init(msm_qca402_init);
+module_exit(msm_qca402_exit);
+
+MODULE_DESCRIPTION("Driver for QCA402x HTCA High level communication");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/qca402/msm_qca402.h b/drivers/media/platform/msm/qca402/msm_qca402.h
new file mode 100644
index 0000000..518ded7
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/msm_qca402.h
@@ -0,0 +1,142 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef _QCA402_H_
+#define _QCA402_H_
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/msm_ion.h>
+#include "../drivers/net/wireless/qca402x/htca_mbox/htca.h"
+
+/* current htca buffer limitation */
+#define HTCA_MAX_BUFF_SIZE (2048)
+enum lpchtca_packet_type {
+ /* the below three types are for piece of data (i.e. frame) with
+ * known size
+ */
+ LPCHTCA_START_PACKET = 1,
+ LPCHTCA_MID_PACKET,
+ LPCHTCA_END_PACKET,
+
+ /* For piece of data (i.e. frame) with known size that fits in one
+ * packet
+ */
+ LPCHTCA_FULL_PACKET,
+
+ /* If data size is unknown/continuous - this case assumes no header or
+ * user space to take care of headers
+ */
+ LPCHTCA_UNSPEC_PACKET,
+
+};
+
+/* Message Flags */
+#define LPCHTCA_ASYNC_MESSAGE (1 << 7)
+/* this bit is added to one of the above to indicate the packet is last that
+ * will be received for this stream
+ */
+#define LPCHTCA_END_TRANSMISSON (1 << 6)
+#define LPCHTCA_PACKET_MASK ((1 << 6) - 1)
+#define QCA402_MIN_NUM_WORKBUFS (4)
+
+struct msm_qca402_file_data_t;
+
+struct __packed msm_qca402_htca_header_t {
+ __u8 channel_id;
+ __u8 msg_flags;
+ __u16 meta_size;
+};
+
+#define QCA_MSG_HEADER_SIZE (sizeof(struct msm_qca402_htca_header_t))
+#define QCA_MSG_PAYLOAD_SIZE (HTCA_MAX_BUFF_SIZE - QCA_MSG_HEADER_SIZE -\
+ HTCA_HEADER_LEN_MAX)
+
+struct __packed msm_qca402_htca_message_t {
+ __u8 htca_private[HTCA_HEADER_LEN_MAX];
+ struct msm_qca402_htca_header_t header;
+ __u8 payload[QCA_MSG_PAYLOAD_SIZE];
+};
+
+struct file_data_list_t {
+ struct msm_qca402_file_data_t *file_data;
+ struct list_head list;
+};
+
+struct msm_qca402_workbuff_list_t {
+ struct msm_qca402_htca_message_t htca_msg;
+ __u32 size;
+ struct list_head list;
+};
+
+struct msm_qca402_buffer_list_t {
+ struct msm_qca_message_type qca_msg;
+ struct msm_qca402_workbuff_list_t *wbb;
+ void *vaddr;
+ struct ion_handle *ih;
+ __u32 valid_size;
+ struct list_head list;
+};
+
+struct msm_qca402_evt_list_t {
+ __u8 channel_id;
+ __u8 cmd;
+ struct list_head list;
+};
+
+struct msm_qca402_channel_list_t {
+ struct msm_qca402_buffer_list_t *current_entry;
+ struct msm_qca402_workbuff_list_t *wbin;
+ struct msm_qca402_workbuff_list_t *wbout;
+ struct list_head enqueued_list;
+ struct list_head ready_list;
+ struct list_head dequeued_list;
+ __u32 ref_cnt;
+ __u8 channel_id;
+ __u8 has_buff;
+ struct list_head list;
+};
+
+struct msm_qca402_ready_list_t {
+ struct msm_qca402_channel_list_t *ch_data;
+ __u8 cmd;
+ struct list_head list;
+};
+
+struct msm_qca402_dev_data_t {
+ struct cdev cdev;
+ struct device *dev;
+ struct ion_client *ion_client;
+ __u8 endPointId;
+ void *htca_target;
+ struct list_head file_list;
+ struct list_head channel_list;
+ struct mutex dev_mutex;
+ struct list_head work_list;
+ wait_queue_head_t in_queue;
+ struct list_head in_list;
+ wait_queue_head_t recv_queue;
+ struct list_head recv_list;
+ spinlock_t lock;
+ __u8 dev_idx;
+ __u8 sending;
+ __u8 receiving;
+};
+
+struct msm_qca402_file_data_t {
+ struct msm_qca402_dev_data_t *dev_data;
+ wait_queue_head_t out_queue;
+ struct mutex file_mutex;
+ struct list_head evt_list;
+ struct list_head ready_ch_list;
+};
+
+#endif /* _QCA402_H_ */
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index f80d9b0..f975409 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -120,7 +120,7 @@
},
{
.key = "qcom,max-secure-instances",
- .value = 5,
+ .value = 2,
},
{
.key = "qcom,max-hw-load",
@@ -154,6 +154,10 @@
.key = "qcom,debug-timeout",
.value = 0,
},
+ {
+ .key = "qcom,enable-idle-indicator",
+ .value = 1,
+ },
};
static struct msm_vidc_common_data sdm670_common_data_v0[] = {
@@ -205,6 +209,10 @@
.key = "qcom,hw-resp-timeout",
.value = 1000,
},
+ {
+ .key = "qcom,enable-idle-indicator",
+ .value = 1,
+ },
};
static struct msm_vidc_common_data sdm670_common_data_v1[] = {
@@ -256,6 +264,10 @@
.key = "qcom,hw-resp-timeout",
.value = 1000,
},
+ {
+ .key = "qcom,enable-idle-indicator",
+ .value = 1,
+ },
};
static struct msm_vidc_efuse_data sdm670_efuse_data[] = {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 79ed798..6975c13 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2747,7 +2747,7 @@
{
int rc = 0;
u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
- int count = 0;
+ int pc_count = 0, idle_count = 0;
const int max_tries = 10;
struct venus_hfi_device *device = list_first_entry(
&hal_ctxt.dev_head, struct venus_hfi_device, list);
@@ -2796,8 +2796,16 @@
wfi_status);
goto skip_power_off;
}
- if (device->res->sys_idle_indicator &&
- !(idle_status & BIT(30))) {
+ while (device->res->sys_idle_indicator &&
+ idle_count < max_tries) {
+ if (idle_status & BIT(30))
+ break;
+ usleep_range(50, 100);
+ idle_status = __read_register(device,
+ VIDC_CPU_CS_SCIACMDARG0);
+ idle_count++;
+ }
+ if (idle_count == max_tries) {
dprintk(VIDC_WARN,
"Skipping PC as idle_status (%#x) bit not set\n",
idle_status);
@@ -2810,7 +2818,7 @@
goto skip_power_off;
}
- while (count < max_tries) {
+ while (pc_count < max_tries) {
wfi_status = __read_register(device,
VIDC_WRAPPER_CPU_STATUS);
pc_ready = __read_register(device,
@@ -2819,10 +2827,10 @@
VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY))
break;
usleep_range(150, 250);
- count++;
+ pc_count++;
}
- if (count == max_tries) {
+ if (pc_count == max_tries) {
dprintk(VIDC_ERR,
"Skip PC. Core is not in right state (%#x, %#x)\n",
wfi_status, pc_ready);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d0b5a0e..f9f2160 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1658,8 +1658,9 @@
int rc = 0;
uint32_t lstnr;
unsigned long flags;
- struct qseecom_client_listener_data_irsp send_data_rsp;
- struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
+ struct qseecom_client_listener_data_irsp send_data_rsp = {0};
+ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
+ = {0};
struct qseecom_registered_listener_list *ptr_svc = NULL;
sigset_t new_sigset;
sigset_t old_sigset;
@@ -1757,32 +1758,38 @@
}
err_resp:
qseecom.send_resp_flag = 0;
- ptr_svc->send_resp_flag = 0;
- table = ptr_svc->sglistinfo_ptr;
+ if (ptr_svc) {
+ ptr_svc->send_resp_flag = 0;
+ table = ptr_svc->sglistinfo_ptr;
+ }
if (qseecom.qsee_version < QSEE_VERSION_40) {
send_data_rsp.listener_id = lstnr;
send_data_rsp.status = status;
- send_data_rsp.sglistinfo_ptr =
- (uint32_t)virt_to_phys(table);
- send_data_rsp.sglistinfo_len =
- SGLISTINFO_TABLE_SIZE;
- dmac_flush_range((void *)table,
- (void *)table + SGLISTINFO_TABLE_SIZE);
+ if (table) {
+ send_data_rsp.sglistinfo_ptr =
+ (uint32_t)virt_to_phys(table);
+ send_data_rsp.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ }
cmd_buf = (void *)&send_data_rsp;
cmd_len = sizeof(send_data_rsp);
} else {
send_data_rsp_64bit.listener_id = lstnr;
send_data_rsp_64bit.status = status;
- send_data_rsp_64bit.sglistinfo_ptr =
- virt_to_phys(table);
- send_data_rsp_64bit.sglistinfo_len =
- SGLISTINFO_TABLE_SIZE;
- dmac_flush_range((void *)table,
- (void *)table + SGLISTINFO_TABLE_SIZE);
+ if (table) {
+ send_data_rsp_64bit.sglistinfo_ptr =
+ virt_to_phys(table);
+ send_data_rsp_64bit.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ }
cmd_buf = (void *)&send_data_rsp_64bit;
cmd_len = sizeof(send_data_rsp_64bit);
}
- if (qseecom.whitelist_support == false)
+ if (qseecom.whitelist_support == false || table == NULL)
*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
else
*(uint32_t *)cmd_buf =
@@ -1806,8 +1813,10 @@
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
cmd_buf, cmd_len, resp, sizeof(*resp));
- ptr_svc->listener_in_use = false;
- __qseecom_clean_listener_sglistinfo(ptr_svc);
+ if (ptr_svc) {
+ ptr_svc->listener_in_use = false;
+ __qseecom_clean_listener_sglistinfo(ptr_svc);
+ }
if (ret) {
pr_err("scm_call() failed with err: %d (app_id = %d)\n",
ret, data->client.app_id);
@@ -1960,8 +1969,9 @@
int rc = 0;
uint32_t lstnr;
unsigned long flags;
- struct qseecom_client_listener_data_irsp send_data_rsp;
- struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
+ struct qseecom_client_listener_data_irsp send_data_rsp = {0};
+ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
+ = {0};
struct qseecom_registered_listener_list *ptr_svc = NULL;
sigset_t new_sigset;
sigset_t old_sigset;
@@ -2052,30 +2062,36 @@
status = QSEOS_RESULT_SUCCESS;
}
err_resp:
- table = ptr_svc->sglistinfo_ptr;
+ if (ptr_svc)
+ table = ptr_svc->sglistinfo_ptr;
if (qseecom.qsee_version < QSEE_VERSION_40) {
send_data_rsp.listener_id = lstnr;
send_data_rsp.status = status;
- send_data_rsp.sglistinfo_ptr =
- (uint32_t)virt_to_phys(table);
- send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
- dmac_flush_range((void *)table,
- (void *)table + SGLISTINFO_TABLE_SIZE);
+ if (table) {
+ send_data_rsp.sglistinfo_ptr =
+ (uint32_t)virt_to_phys(table);
+ send_data_rsp.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ }
cmd_buf = (void *)&send_data_rsp;
cmd_len = sizeof(send_data_rsp);
} else {
send_data_rsp_64bit.listener_id = lstnr;
send_data_rsp_64bit.status = status;
- send_data_rsp_64bit.sglistinfo_ptr =
- virt_to_phys(table);
- send_data_rsp_64bit.sglistinfo_len =
- SGLISTINFO_TABLE_SIZE;
- dmac_flush_range((void *)table,
- (void *)table + SGLISTINFO_TABLE_SIZE);
+ if (table) {
+ send_data_rsp_64bit.sglistinfo_ptr =
+ virt_to_phys(table);
+ send_data_rsp_64bit.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ }
cmd_buf = (void *)&send_data_rsp_64bit;
cmd_len = sizeof(send_data_rsp_64bit);
}
- if (qseecom.whitelist_support == false)
+ if (qseecom.whitelist_support == false || table == NULL)
*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
else
*(uint32_t *)cmd_buf =
@@ -2098,9 +2114,11 @@
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
cmd_buf, cmd_len, resp, sizeof(*resp));
- ptr_svc->listener_in_use = false;
- __qseecom_clean_listener_sglistinfo(ptr_svc);
- wake_up_interruptible(&ptr_svc->listener_block_app_wq);
+ if (ptr_svc) {
+ ptr_svc->listener_in_use = false;
+ __qseecom_clean_listener_sglistinfo(ptr_svc);
+ wake_up_interruptible(&ptr_svc->listener_block_app_wq);
+ }
if (ret) {
pr_err("scm_call() failed with err: %d (app_id = %d)\n",
@@ -2644,6 +2662,7 @@
}
}
+unload_exit:
if (found_app) {
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
if (app_crash) {
@@ -2666,7 +2685,6 @@
spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
flags1);
}
-unload_exit:
qseecom_unmap_ion_allocated_memory(data);
data->released = true;
return ret;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 69465f8..6278377 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -507,28 +507,24 @@
pr_debug("%s: target freq = %lu (%s)\n", mmc_hostname(host),
*freq, current->comm);
- if ((clk_scaling->curr_freq == *freq) ||
- clk_scaling->skip_clk_scale_freq_update)
- goto out;
-
- /* No need to scale the clocks if they are gated */
- if (!host->ios.clock)
- goto out;
-
spin_lock_bh(&clk_scaling->lock);
- if (clk_scaling->clk_scaling_in_progress) {
- pr_debug("%s: clocks scaling is already in-progress by mmc thread\n",
- mmc_hostname(host));
+ if (clk_scaling->target_freq == *freq ||
+ clk_scaling->skip_clk_scale_freq_update) {
spin_unlock_bh(&clk_scaling->lock);
goto out;
}
+
clk_scaling->need_freq_change = true;
clk_scaling->target_freq = *freq;
clk_scaling->state = *freq < clk_scaling->curr_freq ?
MMC_LOAD_LOW : MMC_LOAD_HIGH;
spin_unlock_bh(&clk_scaling->lock);
- abort = __mmc_claim_host(host, &clk_scaling->devfreq_abort);
+ if (!clk_scaling->is_suspended && host->ios.clock)
+ abort = __mmc_claim_host(host, &clk_scaling->devfreq_abort);
+ else
+ goto out;
+
if (abort)
goto out;
@@ -572,6 +568,7 @@
{
unsigned long target_freq;
int err;
+ struct mmc_devfeq_clk_scaling clk_scaling;
if (!host->clk_scaling.enable)
return;
@@ -581,8 +578,7 @@
spin_lock_bh(&host->clk_scaling.lock);
- if (host->clk_scaling.clk_scaling_in_progress ||
- !(host->clk_scaling.need_freq_change)) {
+ if (!host->clk_scaling.need_freq_change) {
spin_unlock_bh(&host->clk_scaling.lock);
return;
}
@@ -590,7 +586,12 @@
atomic_inc(&host->clk_scaling.devfreq_abort);
target_freq = host->clk_scaling.target_freq;
- host->clk_scaling.clk_scaling_in_progress = true;
+ /*
+ * Store the clock scaling state while the lock is acquired so that
+ * if devfreq context modifies clk_scaling, it will get reflected only
+ * in the next deferred scaling check.
+ */
+ clk_scaling = host->clk_scaling;
host->clk_scaling.need_freq_change = false;
spin_unlock_bh(&host->clk_scaling.lock);
pr_debug("%s: doing deferred frequency change (%lu) (%s)\n",
@@ -598,7 +599,7 @@
target_freq, current->comm);
err = mmc_clk_update_freq(host, target_freq,
- host->clk_scaling.state);
+ clk_scaling.state);
if (err && err != -EAGAIN) {
pr_err("%s: failed on deferred scale clocks (%d)\n",
mmc_hostname(host), err);
@@ -608,7 +609,6 @@
mmc_hostname(host),
target_freq, current->comm);
}
- host->clk_scaling.clk_scaling_in_progress = false;
atomic_dec(&host->clk_scaling.devfreq_abort);
}
EXPORT_SYMBOL(mmc_deferred_scaling);
@@ -738,7 +738,6 @@
spin_lock_init(&host->clk_scaling.lock);
atomic_set(&host->clk_scaling.devfreq_abort, 0);
host->clk_scaling.curr_freq = host->ios.clock;
- host->clk_scaling.clk_scaling_in_progress = false;
host->clk_scaling.need_freq_change = false;
host->clk_scaling.is_busy_started = false;
@@ -809,7 +808,8 @@
return -EINVAL;
}
- if (!mmc_can_scale_clk(host) || !host->clk_scaling.enable)
+ if (!mmc_can_scale_clk(host) || !host->clk_scaling.enable ||
+ host->clk_scaling.is_suspended)
return 0;
if (!host->clk_scaling.devfreq) {
@@ -826,7 +826,7 @@
mmc_hostname(host), __func__);
return err;
}
- host->clk_scaling.enable = false;
+ host->clk_scaling.is_suspended = true;
host->clk_scaling.total_busy_time_us = 0;
@@ -880,15 +880,12 @@
if (host->ios.clock < host->clk_scaling.freq_table[max_clk_idx])
host->clk_scaling.curr_freq = devfreq_min_clk;
- host->clk_scaling.clk_scaling_in_progress = false;
- host->clk_scaling.need_freq_change = false;
-
err = devfreq_resume_device(host->clk_scaling.devfreq);
if (err) {
pr_err("%s: %s: failed to resume devfreq (%d)\n",
mmc_hostname(host), __func__, err);
} else {
- host->clk_scaling.enable = true;
+ host->clk_scaling.is_suspended = false;
pr_debug("%s: devfreq resumed\n", mmc_hostname(host));
}
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 45df01b..02dffe9 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -761,6 +761,7 @@
/* Suspend the clock scaling and mask host capability */
if (host->clk_scaling.enable)
mmc_suspend_clk_scaling(host);
+ host->clk_scaling.enable = false;
host->caps2 &= ~MMC_CAP2_CLK_SCALE;
host->clk_scaling.state = MMC_LOAD_HIGH;
/* Set to max. frequency when disabling */
@@ -769,8 +770,10 @@
} else if (value) {
/* Unmask host capability and resume scaling */
host->caps2 |= MMC_CAP2_CLK_SCALE;
- if (!host->clk_scaling.enable)
+ if (!host->clk_scaling.enable) {
+ host->clk_scaling.enable = true;
mmc_resume_clk_scaling(host);
+ }
}
mmc_put_card(host->card);
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index f86ce5b..42021af 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -244,8 +244,8 @@
}
static
-void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba,
- u32 slot, unsigned int bypass, short key_index)
+void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba, u32 slot,
+ unsigned int bypass, short key_index, u32 cdu_sz)
{
unsigned int ctrl_info_val = 0;
@@ -257,7 +257,7 @@
/* Configure data unit size of transfer request */
ctrl_info_val |=
- (SDHCI_MSM_ICE_TR_DATA_UNIT_512_B &
+ (cdu_sz &
MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU)
<< OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU;
@@ -335,8 +335,9 @@
struct sdhci_msm_host *msm_host = pltfm_host->priv;
int err = 0;
short key_index = 0;
- sector_t lba = 0;
+ u64 dun = 0;
unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
+ u32 cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_512_B;
struct request *req;
if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
@@ -349,8 +350,13 @@
if (!mrq)
return -EINVAL;
req = mrq->req;
- if (req) {
- lba = req->__sector;
+ if (req && req->bio) {
+ if (bio_dun(req->bio)) {
+ dun = bio_dun(req->bio);
+ cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_4_KB;
+ } else {
+ dun = req->__sector;
+ }
err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
if (err)
return err;
@@ -362,11 +368,12 @@
if (msm_host->ice_hci_support) {
/* For ICE HCI / ICE3.0 */
- sdhci_msm_ice_hci_update_noncq_cfg(host, lba, bypass,
+ sdhci_msm_ice_hci_update_noncq_cfg(host, dun, bypass,
key_index);
} else {
/* For ICE versions earlier to ICE3.0 */
- sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
+ sdhci_msm_ice_update_cfg(host, dun, slot, bypass, key_index,
+ cdu_sz);
}
return 0;
}
@@ -378,9 +385,10 @@
struct sdhci_msm_host *msm_host = pltfm_host->priv;
int err = 0;
short key_index = 0;
- sector_t lba = 0;
+ u64 dun = 0;
unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
struct request *req;
+ u32 cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_512_B;
if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
pr_err("%s: ice is in invalid state %d\n",
@@ -392,8 +400,13 @@
if (!mrq)
return -EINVAL;
req = mrq->req;
- if (req) {
- lba = req->__sector;
+ if (req && req->bio) {
+ if (bio_dun(req->bio)) {
+ dun = bio_dun(req->bio);
+ cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_4_KB;
+ } else {
+ dun = req->__sector;
+ }
err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
if (err)
return err;
@@ -405,11 +418,12 @@
if (msm_host->ice_hci_support) {
/* For ICE HCI / ICE3.0 */
- sdhci_msm_ice_hci_update_cmdq_cfg(lba, bypass, key_index,
+ sdhci_msm_ice_hci_update_cmdq_cfg(dun, bypass, key_index,
ice_ctx);
} else {
/* For ICE versions earlier to ICE3.0 */
- sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
+ sdhci_msm_ice_update_cfg(host, dun, slot, bypass, key_index,
+ cdu_sz);
}
return 0;
}
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index f51ab9e..15f3df9 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -975,6 +975,59 @@
}
}
+static bool is_gpio_tlmm_dc(struct irq_data *d, u32 type)
+{
+ const struct msm_pingroup *g;
+ unsigned long flags;
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct msm_pinctrl *pctrl;
+ bool ret = false;
+ unsigned int polarity = 0, offset, val;
+ int i;
+
+ if (!gc)
+ return false;
+
+ pctrl = gpiochip_get_data(gc);
+
+ for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
+ struct msm_dir_conn *dir_conn = (struct msm_dir_conn *)
+ &pctrl->soc->dir_conn[i];
+
+ if (dir_conn->gpio == d->hwirq && dir_conn->tlmm_dc) {
+ ret = true;
+ offset = pctrl->soc->dir_conn_irq_base -
+ dir_conn->hwirq;
+ break;
+ }
+ }
+
+ if (!ret)
+ return ret;
+
+ if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))
+ return ret;
+
+ /*
+ * Since the default polarity is set to 0, change it to 1 for
+ * Rising edge and active high interrupt type such that the line
+ * is not inverted.
+ */
+ polarity = 1;
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+ g = &pctrl->soc->groups[d->hwirq];
+
+ val = readl_relaxed(pctrl->regs + g->dir_conn_reg + (offset * 4));
+ val |= polarity << 8;
+
+ writel_relaxed(val, pctrl->regs + g->dir_conn_reg + (offset * 4));
+
+ spin_unlock_irqrestore(&pctrl->lock, flags);
+
+ return ret;
+}
+
static bool is_gpio_dual_edge(struct irq_data *d, irq_hw_number_t *dir_conn_irq)
{
struct irq_desc *desc = irq_data_to_desc(d);
@@ -1283,12 +1336,12 @@
if (!parent_data)
return 0;
- if (type == IRQ_TYPE_EDGE_BOTH) {
+ if (type == IRQ_TYPE_EDGE_BOTH)
add_dirconn_tlmm(d, irq);
- } else {
- if (is_gpio_dual_edge(d, &irq))
- remove_dirconn_tlmm(d, irq);
- }
+ else if (is_gpio_dual_edge(d, &irq))
+ remove_dirconn_tlmm(d, irq);
+ else if (is_gpio_tlmm_dc(d, type))
+ type = IRQ_TYPE_EDGE_RISING;
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
irq_set_handler_locked(d, handle_level_irq);
@@ -1366,9 +1419,28 @@
for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i];
+ struct irq_data *d;
request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
dirconn->hwirq, dirconn->gpio);
+
+ if (!dirconn->gpio)
+ continue;
+
+ if (!dirconn->tlmm_dc)
+ continue;
+
+ /*
+ * If the gpio is routed through TLMM direct connect interrupts,
+ * program the TLMM registers for this setup.
+ */
+ d = irq_get_irq_data(irq_find_mapping(pctrl->chip.irqdomain,
+ dirconn->gpio));
+ if (!d)
+ continue;
+
+ msm_dirconn_cfg_reg(d, pctrl->soc->dir_conn_irq_base
+ - (u32)dirconn->hwirq);
}
for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
@@ -1383,7 +1455,7 @@
* Statically choose the GPIOs for mapping to PDC. Dynamic mux mapping
* is very difficult.
*/
- for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+ for (i = 0; i < pctrl->soc->n_gpio_mux_in; i++) {
unsigned int irq;
struct irq_data *d;
struct msm_gpio_mux_input *gpio_in =
@@ -1403,6 +1475,12 @@
static int msm_gpiochip_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct irq_fwspec fwspec;
+ struct irq_domain *domain = chip->irqdomain;
+ int virq;
+
+ virq = irq_find_mapping(domain, offset);
+ if (virq)
+ return virq;
fwspec.fwnode = of_node_to_fwnode(chip->of_node);
fwspec.param[0] = offset;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index b8185ae..d0a0766 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -128,10 +128,12 @@
* struct msm_dir_conn - Direct GPIO connect configuration
* @gpio: GPIO pin number
* @hwirq: The GIC interrupt that the pin is connected to
+ * @tlmm_dc: indicates if the GPIO is routed to GIC directly
*/
struct msm_dir_conn {
unsigned int gpio;
irq_hw_number_t hwirq;
+ bool tlmm_dc;
};
/**
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index c5f1307..54d8f56 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -50,6 +50,7 @@
.intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
.intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
.intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .dir_conn_reg = REG_BASE + 0xab000,\
.mux_bit = 2, \
.pull_bit = 0, \
.drv_bit = 6, \
@@ -64,6 +65,7 @@
.intr_polarity_bit = 1, \
.intr_detection_bit = 2, \
.intr_detection_width = 2, \
+ .dir_conn_en_bit = 8, \
}
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
@@ -454,6 +456,7 @@
msm_mux_qdss_stm0,
msm_mux_dbg_out,
msm_mux_gcc_plltest,
+ msm_mux_emac_pps,
msm_mux_NA,
};
@@ -830,6 +833,10 @@
"gpio73", "gpio74",
};
+static const char * const emac_pps_groups[] = {
+ "gpio89",
+};
+
static const struct msm_function sdxpoorwills_functions[] = {
FUNCTION(uim2_data),
FUNCTION(gpio),
@@ -948,6 +955,7 @@
FUNCTION(qdss_stm0),
FUNCTION(dbg_out),
FUNCTION(gcc_plltest),
+ FUNCTION(emac_pps),
};
/* Every pin is maintained as a single group, and missing or non-existing pin
@@ -1085,7 +1093,8 @@
[86] = PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA),
[87] = PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA),
[88] = PINGROUP(88, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
- [89] = PINGROUP(89, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+ [89] = PINGROUP(89, qdss_cti, qdss_cti, emac_pps, NA, NA, NA, NA,
+ NA, NA),
[90] = PINGROUP(90, NA, NA, NA, NA, NA, NA, NA, NA, NA),
[91] = PINGROUP(91, NA, NA, NA, NA, NA, NA, NA, NA, NA),
[92] = PINGROUP(92, NA, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1151,7 +1160,7 @@
{42, 80},
{43, 82},
{44, 83},
- {45, 84},
+ {45, 84, 1},
{46, 86},
{47, 87},
{48, 88},
@@ -1196,6 +1205,17 @@
{0, 195},
};
+static struct msm_dir_conn sdxpoorwills_dir_conn[] = {
+ {0, 220},
+ {0, 219},
+ {0, 218},
+ {0, 217},
+ {0, 216},
+ {0, 215},
+ {0, 214},
+ {0, 213},
+};
+
static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
.pins = sdxpoorwills_pins,
.npins = ARRAY_SIZE(sdxpoorwills_pins),
@@ -1209,6 +1229,9 @@
.n_pdc_mux_out = ARRAY_SIZE(sdxpoorwills_mux_out),
.n_pdc_mux_offset = 20,
.ngpios = 100,
+ .dir_conn_irq_base = 220,
+ .dir_conn = sdxpoorwills_dir_conn,
+ .n_dir_conns = ARRAY_SIZE(sdxpoorwills_dir_conn),
};
static int sdxpoorwills_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index b4af0a09..5085d75 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -2146,6 +2146,15 @@
IPA_MHI_ERR("ipa_mhi_set_state failed %d\n", res);
return res;
}
+
+ res = ipa_mhi_suspend_dl(force);
+ if (res) {
+ IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res);
+ goto fail_suspend_dl_channel;
+ }
+
+ usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX);
+
res = ipa_mhi_suspend_ul(force, &empty, &force_clear);
if (res) {
IPA_MHI_ERR("ipa_mhi_suspend_ul failed %d\n", res);
@@ -2190,12 +2199,6 @@
#endif
usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX);
- res = ipa_mhi_suspend_dl(force);
- if (res) {
- IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res);
- goto fail_suspend_dl_channel;
- }
-
if (!empty)
ipa_set_tag_process_before_gating(false);
@@ -2209,7 +2212,6 @@
IPA_MHI_FUNC_EXIT();
return 0;
-fail_suspend_dl_channel:
fail_release_cons:
if (!ipa_pm_is_used())
ipa_mhi_request_prod();
@@ -2225,7 +2227,6 @@
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
fail_suspend_ul_channel:
ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->ul_channels);
- ipa_mhi_set_state(IPA_MHI_STATE_STARTED);
if (force_clear) {
if (
ipa_mhi_disable_force_clear(ipa_mhi_client_ctx->qmi_req_id)) {
@@ -2235,6 +2236,9 @@
IPA_MHI_DBG("force clear datapath disabled\n");
ipa_mhi_client_ctx->qmi_req_id++;
}
+fail_suspend_dl_channel:
+ ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->dl_channels);
+ ipa_mhi_set_state(IPA_MHI_STATE_STARTED);
return res;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 5bfb8e4..bc032d9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2536,6 +2536,9 @@
ipa3_q6_pipe_delay(true);
ipa3_q6_avoid_holb();
+ if (ipa3_ctx->ipa_config_is_mhi)
+ ipa3_set_reset_client_cons_pipe_sus_holb(true,
+ IPA_CLIENT_MHI_CONS);
if (ipa3_q6_clean_q6_tables()) {
IPAERR("Failed to clean Q6 tables\n");
BUG();
@@ -2548,8 +2551,11 @@
* on pipe reset procedure
*/
ipa3_q6_pipe_delay(false);
-
- ipa3_set_usb_prod_pipe_delay();
+ ipa3_set_reset_client_prod_pipe_delay(true,
+ IPA_CLIENT_USB_PROD);
+ if (ipa3_ctx->ipa_config_is_mhi)
+ ipa3_set_reset_client_prod_pipe_delay(true,
+ IPA_CLIENT_MHI_PROD);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
IPADBG_LOW("Exit with success\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index cfac126..bbc3a4f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -1331,27 +1331,32 @@
}
/*
- * Set USB PROD pipe delay for MBIM/RMNET config
+ * Set reset ep_delay for CLEINT PROD pipe
* Clocks, should be voted before calling this API
* locks should be taken before calling this API
*/
-void ipa3_set_usb_prod_pipe_delay(void)
+int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
+ enum ipa_client_type client)
{
- int result;
+ int result = 0;
int pipe_idx;
struct ipa3_ep_context *ep;
struct ipa_ep_cfg_ctrl ep_ctrl;
memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
- ep_ctrl.ipa_ep_delay = true;
+ ep_ctrl.ipa_ep_delay = set_reset;
+ if (IPA_CLIENT_IS_CONS(client)) {
+ IPAERR("client (%d) not PROD\n", client);
+ return -EINVAL;
+ }
- pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
+ pipe_idx = ipa3_get_ep_mapping(client);
if (pipe_idx == IPA_EP_NOT_ALLOCATED) {
- IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD);
- return;
+ IPAERR("client (%d) not valid\n", client);
+ return -EINVAL;
}
ep = &ipa3_ctx->ep[pipe_idx];
@@ -1368,6 +1373,59 @@
IPADBG("client (ep: %d) success\n", pipe_idx);
}
client_lock_unlock_cb(pipe_idx, false);
+ return result;
+}
+
+int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
+ enum ipa_client_type client)
+{
+ int pipe_idx;
+ struct ipa3_ep_context *ep;
+ struct ipa_ep_cfg_ctrl ep_suspend;
+ struct ipa_ep_cfg_holb ep_holb;
+
+ memset(&ep_suspend, 0, sizeof(ep_suspend));
+ memset(&ep_holb, 0, sizeof(ep_holb));
+
+ ep_suspend.ipa_ep_suspend = set_reset;
+ ep_holb.tmr_val = 0;
+ ep_holb.en = set_reset;
+
+ if (IPA_CLIENT_IS_PROD(client)) {
+ IPAERR("client (%d) not CONS\n", client);
+ return -EINVAL;
+ }
+
+ pipe_idx = ipa3_get_ep_mapping(client);
+
+ if (pipe_idx == IPA_EP_NOT_ALLOCATED) {
+ IPAERR("client (%d) not valid\n", client);
+ return -EINVAL;
+ }
+
+ ep = &ipa3_ctx->ep[pipe_idx];
+ /* Setting sus/holb on MHI_CONS with skip_ep_cfg */
+ client_lock_unlock_cb(pipe_idx, true);
+ if (ep->valid && ep->skip_ep_cfg) {
+ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_CTRL_n,
+ pipe_idx, &ep_suspend);
+ /*
+ * ipa3_cfg_ep_holb is not used here because we are
+ * setting HOLB on Q6 pipes, and from APPS perspective
+ * they are not valid, therefore, the above function
+ * will fail.
+ */
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
+ pipe_idx, &ep_holb);
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_HOL_BLOCK_EN_n,
+ pipe_idx, &ep_holb);
+ }
+ client_lock_unlock_cb(pipe_idx, false);
+ return 0;
}
void ipa3_xdci_ep_delay_rm(u32 clnt_hdl)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 43f4c74..6dc2905 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1922,7 +1922,10 @@
void ipa3_xdci_ep_delay_rm(u32 clnt_hdl);
void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx);
void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx);
-void ipa3_set_usb_prod_pipe_delay(void);
+int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
+ enum ipa_client_type client);
+int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
+ enum ipa_client_type client);
int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
bool should_force_clear, u32 qmi_req_id, bool is_dpl);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index dd97038..9075237 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -199,6 +199,7 @@
struct ipa3_ep_context *ep;
const struct ipa_gsi_ep_config *ep_cfg;
bool burst_mode_enabled = false;
+ struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
IPA_MHI_FUNC_ENTRY();
@@ -341,6 +342,20 @@
*params->mhi = ch_scratch.mhi;
+ if (IPA_CLIENT_IS_PROD(ep->client) && ep->skip_ep_cfg) {
+ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
+ ep_cfg_ctrl.ipa_ep_delay = true;
+ ep->ep_delay_set = true;
+ res = ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
+ if (res)
+ IPA_MHI_ERR("client (ep: %d) failed result=%d\n",
+ ipa_ep_idx, res);
+ else
+ IPA_MHI_DBG("client (ep: %d) success\n", ipa_ep_idx);
+ } else {
+ ep->ep_delay_set = false;
+ }
+
IPA_MHI_DBG("Starting channel\n");
res = gsi_start_channel(ep->gsi_chan_hdl);
if (res) {
@@ -524,6 +539,7 @@
{
struct ipa3_ep_context *ep;
int res;
+ struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
IPA_MHI_FUNC_ENTRY();
@@ -538,6 +554,21 @@
}
ep = &ipa3_ctx->ep[clnt_hdl];
+ if (ep->ep_delay_set == true) {
+ memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
+ ep_cfg_ctrl.ipa_ep_delay = false;
+ res = ipa3_cfg_ep_ctrl(clnt_hdl,
+ &ep_cfg_ctrl);
+ if (res) {
+ IPAERR
+ ("client(ep:%d) failed to remove delay res=%d\n",
+ clnt_hdl, res);
+ } else {
+ IPADBG("client (ep: %d) delay removed\n",
+ clnt_hdl);
+ ep->ep_delay_set = false;
+ }
+ }
res = gsi_dealloc_channel(ep->gsi_chan_hdl);
if (res) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 736c0fb..2212b00 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -908,6 +908,20 @@
return 0;
}
+static int __ipa_rt_validate_rule_id(u16 rule_id)
+{
+ if (!rule_id)
+ return 0;
+
+ if ((rule_id < ipahal_get_rule_id_hi_bit()) ||
+ (rule_id >= ((ipahal_get_rule_id_hi_bit()<<1)-1))) {
+ IPAERR_RL("Invalid rule_id provided 0x%x\n",
+ rule_id);
+ return -EPERM;
+ }
+
+ return 0;
+}
static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule,
struct ipa3_hdr_entry **hdr,
struct ipa3_hdr_proc_ctx_entry **proc_ctx)
@@ -1023,6 +1037,8 @@
if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx))
goto error;
+ if (__ipa_rt_validate_rule_id(rule_id))
+ goto error;
tbl = __ipa_add_rt_tbl(ip, name);
if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) {
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 0b8c212..37ae308 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -50,20 +50,23 @@
#define SCM_DLOAD_BOTHDUMPS (SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
static int restart_mode;
-static void __iomem *restart_reason, *dload_type_addr;
+static void *restart_reason;
static bool scm_pmic_arbiter_disable_supported;
static bool scm_deassert_ps_hold_supported;
/* Download mode master kill-switch */
static void __iomem *msm_ps_hold;
static phys_addr_t tcsr_boot_misc_detect;
+static void scm_disable_sdi(void);
+
+#ifdef CONFIG_QCOM_DLOAD_MODE
/* Runtime could be only changed value once.
* There is no API from TZ to re-enable the registers.
* So the SDI cannot be re-enabled when it already by-passed.
*/
static int download_mode = 1;
-static struct kobject dload_kobj;
-static void scm_disable_sdi(void);
-
+#else
+static const int download_mode;
+#endif
#ifdef CONFIG_QCOM_DLOAD_MODE
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
@@ -81,6 +84,8 @@
static void *kaslr_imem_addr;
#endif
static bool scm_dload_supported;
+static struct kobject dload_kobj;
+static void *dload_type_addr;
static int dload_set(const char *val, const struct kernel_param *kp);
/* interface for exporting attributes */
@@ -431,6 +436,7 @@
pr_err("Powering off has failed\n");
}
+#ifdef CONFIG_QCOM_DLOAD_MODE
static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
@@ -561,6 +567,7 @@
static struct attribute_group reset_attr_group = {
.attrs = reset_attrs,
};
+#endif
static int msm_restart_probe(struct platform_device *pdev)
{
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 36521a1..c596f54 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -573,14 +573,15 @@
return rc;
}
- *val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
+ *val = div_s64((int64_t)cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
return 0;
}
#define BATT_SOC_32BIT GENMASK(31, 0)
static int fg_get_charge_counter_shadow(struct fg_chip *chip, int *val)
{
- int rc, batt_soc;
+ int rc;
+ unsigned int batt_soc;
rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
if (rc < 0) {
@@ -588,13 +589,15 @@
return rc;
}
- *val = div_u64((u32)batt_soc * chip->cl.learned_cc_uah, BATT_SOC_32BIT);
+ *val = div_u64((uint64_t)batt_soc * chip->cl.learned_cc_uah,
+ BATT_SOC_32BIT);
return 0;
}
static int fg_get_charge_counter(struct fg_chip *chip, int *val)
{
- int rc, cc_soc;
+ int rc;
+ int cc_soc;
rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
if (rc < 0) {
@@ -602,7 +605,7 @@
return rc;
}
- *val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
+ *val = div_s64((int64_t)cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
return 0;
}
@@ -1296,7 +1299,7 @@
return true;
}
-static int fg_prime_cc_soc_sw(struct fg_chip *chip, int cc_soc_sw)
+static int fg_prime_cc_soc_sw(struct fg_chip *chip, unsigned int cc_soc_sw)
{
int rc;
@@ -1306,7 +1309,7 @@
if (rc < 0)
pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
else
- fg_dbg(chip, FG_STATUS, "cc_soc_sw: %x\n", cc_soc_sw);
+ fg_dbg(chip, FG_STATUS, "cc_soc_sw: %u\n", cc_soc_sw);
return rc;
}
@@ -1469,8 +1472,10 @@
static int fg_cap_learning_process_full_data(struct fg_chip *chip)
{
- int rc, cc_soc_sw, cc_soc_delta_pct;
+ int rc;
+ unsigned int cc_soc_sw;
int64_t delta_cc_uah;
+ unsigned int cc_soc_delta_pct;
rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
if (rc < 0) {
@@ -1488,31 +1493,32 @@
return -ERANGE;
}
- delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
+ delta_cc_uah = div64_u64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
100);
chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
- fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
+ fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%u total_cc_uah=%llu\n",
cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
return 0;
}
static int fg_cap_learning_begin(struct fg_chip *chip, u32 batt_soc)
{
- int rc, cc_soc_sw, batt_soc_msb;
+ int rc;
+ unsigned int batt_soc_msb, cc_soc_sw;
batt_soc_msb = batt_soc >> 24;
if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) >
chip->dt.cl_start_soc) {
- fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
+ fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %u is high!, not starting\n",
batt_soc_msb);
return -EINVAL;
}
- chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc_msb,
+ chip->cl.init_cc_uah = div64_u64(chip->cl.learned_cc_uah * batt_soc_msb,
FULL_SOC_RAW);
/* Prime cc_soc_sw with battery SOC when capacity learning begins */
- cc_soc_sw = div64_s64((int64_t)batt_soc * CC_SOC_30BIT,
+ cc_soc_sw = div64_u64((uint64_t)batt_soc * CC_SOC_30BIT,
BATT_SOC_32BIT);
rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
if (rc < 0) {
@@ -1529,7 +1535,8 @@
static int fg_cap_learning_done(struct fg_chip *chip)
{
- int rc, cc_soc_sw;
+ int rc;
+ unsigned int cc_soc_sw;
rc = fg_cap_learning_process_full_data(chip);
if (rc < 0) {
@@ -1553,7 +1560,8 @@
static void fg_cap_learning_update(struct fg_chip *chip)
{
- int rc, batt_soc, batt_soc_msb, cc_soc_sw;
+ int rc;
+ unsigned int batt_soc, batt_soc_msb, cc_soc_sw;
bool input_present = is_input_present(chip);
bool prime_cc = false;
@@ -1640,7 +1648,7 @@
if (chip->charge_done)
cc_soc_sw = CC_SOC_30BIT;
else
- cc_soc_sw = div_u64((u32)batt_soc *
+ cc_soc_sw = div_u64((uint64_t)batt_soc *
CC_SOC_30BIT, BATT_SOC_32BIT);
rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
diff --git a/drivers/power/supply/qcom/qpnp-linear-charger.c b/drivers/power/supply/qcom/qpnp-linear-charger.c
index aedc77a..7815eba 100644
--- a/drivers/power/supply/qcom/qpnp-linear-charger.c
+++ b/drivers/power/supply/qcom/qpnp-linear-charger.c
@@ -2877,7 +2877,8 @@
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 1);
REQUEST_IRQ(chip, USBIN_VALID, rc, usbin_valid, 1,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 1);
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_ONESHOT, 1);
REQUEST_IRQ(chip, USB_CHG_GONE, rc, chg_gone, 0,
IRQF_TRIGGER_RISING, 1);
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 56a09c6..e3e4f2b 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -985,6 +985,7 @@
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_QNOVO,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1076,6 +1077,10 @@
val->intval = get_client_vote(chg->fcc_votable,
BATT_PROFILE_VOTER);
break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ val->intval = get_client_vote(chg->fcc_votable,
+ FG_ESR_VOTER);
+ break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
@@ -1183,6 +1188,12 @@
chg->batt_profile_fcc_ua = val->intval;
vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ if (val->intval)
+ vote(chg->fcc_votable, FG_ESR_VOTER, true, val->intval);
+ else
+ vote(chg->fcc_votable, FG_ESR_VOTER, false, 0);
+ break;
case POWER_SUPPLY_PROP_SET_SHIP_MODE:
/* Not in ship mode as long as the device is active */
if (!val->intval)
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 71a4369..e56ecb0 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1260,6 +1260,52 @@
POWER_SUPPLY_PROP_CHARGE_FULL,
};
+#define ITERM_SCALING_FACTOR_PMI632 1525
+#define ITERM_SCALING_FACTOR_PM855B 3050
+static int smb5_get_prop_batt_iterm(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc, temp, scaling_factor;
+ u8 stat, buf[2];
+
+ /*
+ * Currently, only ADC comparator-based termination is supported,
+ * hence read only the threshold corresponding to ADC source.
+ * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
+ */
+ rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
+ if (rc < 0) {
+ pr_err("Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n", rc);
+ return rc;
+ }
+
+ if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
+ val->intval = -EINVAL;
+ return 0;
+ }
+
+ rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
+
+ if (rc < 0) {
+ pr_err("Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ temp = buf[1] | (buf[0] << 8);
+ temp = sign_extend32(temp, 15);
+
+ if (chg->smb_version == PMI632_SUBTYPE)
+ scaling_factor = ITERM_SCALING_FACTOR_PMI632;
+ else
+ scaling_factor = ITERM_SCALING_FACTOR_PM855B;
+
+ temp = div_s64(temp * scaling_factor, 10000);
+ val->intval = temp;
+
+ return rc;
+}
+
static int smb5_batt_get_prop(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -1322,7 +1368,7 @@
BATT_PROFILE_VOTER);
break;
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
- rc = smblib_get_prop_batt_iterm(chg, val);
+ rc = smb5_get_prop_batt_iterm(chg, val);
break;
case POWER_SUPPLY_PROP_TEMP:
rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_TEMP, val);
@@ -1772,30 +1818,42 @@
return 0;
}
+#define RAW_TERM_CURR(conv_factor, scaled_ma) \
+ div_s64((int64_t)scaled_ma * 10000, conv_factor)
+#define ITERM_LIMITS_PMI632_MA 5000
+#define ITERM_LIMITS_PM855B_MA 10000
static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
{
u8 *buf;
int rc = 0;
- s16 raw_hi_thresh, raw_lo_thresh;
+ int raw_hi_thresh, raw_lo_thresh, max_limit_ma, scaling_factor;
struct smb_charger *chg = &chip->chg;
- if (chip->dt.term_current_thresh_hi_ma < -10000 ||
- chip->dt.term_current_thresh_hi_ma > 10000 ||
- chip->dt.term_current_thresh_lo_ma < -10000 ||
- chip->dt.term_current_thresh_lo_ma > 10000) {
+ if (chip->chg.smb_version == PMI632_SUBTYPE) {
+ scaling_factor = ITERM_SCALING_FACTOR_PMI632;
+ max_limit_ma = ITERM_LIMITS_PMI632_MA;
+ } else {
+ scaling_factor = ITERM_SCALING_FACTOR_PM855B;
+ max_limit_ma = ITERM_LIMITS_PM855B_MA;
+ }
+
+ if (chip->dt.term_current_thresh_hi_ma < (-1 * max_limit_ma)
+ || chip->dt.term_current_thresh_hi_ma > max_limit_ma
+ || chip->dt.term_current_thresh_lo_ma < (-1 * max_limit_ma)
+ || chip->dt.term_current_thresh_lo_ma > max_limit_ma) {
dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
return -EINVAL;
}
/*
* Conversion:
- * raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000)
+ * raw (A) = (scaled_mA * (10000) / conv_factor)
* Note: raw needs to be converted to big-endian format.
*/
if (chip->dt.term_current_thresh_hi_ma) {
- raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma *
- ADC_CHG_TERM_MASK) / 10000);
+ raw_hi_thresh = RAW_TERM_CURR(scaling_factor,
+ chip->dt.term_current_thresh_hi_ma);
raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);
buf = (u8 *)&raw_hi_thresh;
raw_hi_thresh = buf[1] | (buf[0] << 8);
@@ -1810,8 +1868,8 @@
}
if (chip->dt.term_current_thresh_lo_ma) {
- raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma *
- ADC_CHG_TERM_MASK) / 10000);
+ raw_lo_thresh = RAW_TERM_CURR(scaling_factor,
+ chip->dt.term_current_thresh_lo_ma);
raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);
buf = (u8 *)&raw_lo_thresh;
raw_lo_thresh = buf[1] | (buf[0] << 8);
@@ -2438,6 +2496,7 @@
[TYPEC_ATTACH_DETACH_IRQ] = {
.name = "typec-attach-detach",
.handler = typec_attach_detach_irq_handler,
+ .wake = true,
},
[TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
.name = "typec-legacy-cable-detect",
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 5b94ff2..6b6bc9c 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3123,7 +3123,9 @@
return 0;
chg->cc2_detach_wa_active = false;
+ chg->in_chg_lock = true;
cancel_work_sync(&chg->rdstd_cc2_detach_work);
+ chg->in_chg_lock = false;
smblib_reg_block_restore(chg, cc2_detach_settings);
return 0;
}
@@ -4757,7 +4759,6 @@
{
int rc;
u8 stat4, stat5;
- bool lock = false;
struct smb_charger *chg = container_of(work, struct smb_charger,
rdstd_cc2_detach_work);
@@ -4826,22 +4827,15 @@
* during pd_hard_reset from the function smblib_cc2_sink_removal_exit
* which is called in the same lock context that we try to acquire in
* this work routine.
- * Check if this work is running during pd_hard_reset and use trylock
- * instead of mutex_lock to prevent any deadlock if mutext is already
- * held.
+ * Check if this work is running during pd_hard_reset and skip holding
+ * mutex if lock is already held.
*/
- if (chg->pd_hard_reset) {
- if (mutex_trylock(&chg->lock))
- lock = true;
- } else {
+ if (!chg->in_chg_lock)
mutex_lock(&chg->lock);
- lock = true;
- }
-
smblib_usb_typec_change(chg);
-
- if (lock)
+ if (!chg->in_chg_lock)
mutex_unlock(&chg->lock);
+
return;
rerun:
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 3b8bc1f..2457ed2 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -71,6 +71,7 @@
#define MOISTURE_VOTER "MOISTURE_VOTER"
#define HVDCP2_ICL_VOTER "HVDCP2_ICL_VOTER"
#define OV_VOTER "OV_VOTER"
+#define FG_ESR_VOTER "FG_ESR_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
@@ -354,6 +355,7 @@
bool otg_present;
bool is_audio_adapter;
bool disable_stat_sw_override;
+ bool in_chg_lock;
/* workaround flag */
u32 wa_flags;
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 054d153..f91d477 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1598,45 +1598,6 @@
return 0;
}
-int smblib_get_prop_batt_iterm(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- int rc, temp;
- u8 stat, buf[2];
-
- /*
- * Currently, only ADC comparator-based termination is supported,
- * hence read only the threshold corresponding to ADC source.
- * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
- */
- rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
- if (rc < 0) {
- smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n",
- rc);
- return rc;
- }
-
- if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
- val->intval = -EINVAL;
- return 0;
- }
-
- rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
-
- if (rc < 0) {
- smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
- rc);
- return rc;
- }
-
- temp = buf[1] | (buf[0] << 8);
- temp = sign_extend32(temp, 15);
- temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK);
- val->intval = temp;
-
- return rc;
-}
-
int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
union power_supply_propval *val)
{
@@ -1720,9 +1681,6 @@
return -EINVAL;
chg->system_temp_level = val->intval;
- /* disable parallel charge in case of system temp level */
- vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,
- chg->system_temp_level ? true : false, 0);
if (chg->system_temp_level == chg->thermal_levels)
return vote(chg->chg_disable_votable,
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index c252ef0..9afd7cd 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -84,7 +84,6 @@
#define TYPEC_DEFAULT_CURRENT_UA 900000
#define TYPEC_MEDIUM_CURRENT_UA 1500000
#define TYPEC_HIGH_CURRENT_UA 3000000
-#define ADC_CHG_TERM_MASK 32767
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -500,8 +499,6 @@
union power_supply_propval *val);
int smblib_get_prop_input_current_limited(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_get_prop_batt_iterm(struct smb_charger *chg,
- union power_supply_propval *val);
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 0ae6979..4dfd8d3 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -897,17 +897,16 @@
req = lrbp->cmd->request;
else
return 0;
- /*
- * Right now ICE do not support variable dun but can be
- * taken as future enhancement
- * if (bio_dun(req->bio)) {
- * dun @bio can be split, so we have to adjust offset
- * *dun = bio_dun(req->bio);
- * } else
- */
+
+ /* Use request LBA or given dun as the DUN value */
if (req->bio) {
- *dun = req->bio->bi_iter.bi_sector;
- *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+ if (bio_dun(req->bio)) {
+ /* dun @bio can be split, so we have to adjust offset */
+ *dun = bio_dun(req->bio);
+ } else {
+ *dun = req->bio->bi_iter.bi_sector;
+ *dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+ }
}
ret = ufs_qcom_ice_req_setup(host, lrbp->cmd, cc_index, enable);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 52d9f65..0e16501 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -195,6 +195,43 @@
Client driver for the WCNSS_CTRL SMD channel, used to download nv
firmware to a newly booted WCNSS chip.
+config SETUP_SSR_NOTIF_TIMEOUTS
+ bool "Set timeouts on SSR sysmon notifications and notifier callbacks"
+ help
+ Setup timers prior to initiating communication between
+ subsystems through sysmon, and prior to sending notifications
+ to drivers in the kernel that have registered callbacks with the
+ subsystem notifier framework for a particular subsystem. This
+ is a debugging feature.
+
+config SSR_SYSMON_NOTIF_TIMEOUT
+ depends on SETUP_SSR_NOTIF_TIMEOUTS
+ int "SSR Sysmon notifications timeout in ms"
+ default 10000
+ help
+ The amount of time, in milliseconds, that should elapse between
+ the start and end of sysmon SSR notifications, before a warning
+ is emitted.
+
+config SSR_SUBSYS_NOTIF_TIMEOUT
+ depends on SETUP_SSR_NOTIF_TIMEOUTS
+ int "SSR Subsystem notifier timeout in ms"
+ default 10000
+ help
+ The amount of time, in milliseconds, that should elapse between
+ the start and end of SSR notifications through the subsystem
+ notifier, before a warning is emitted.
+
+config PANIC_ON_SSR_NOTIF_TIMEOUT
+ bool "Trigger kernel panic when notification timeout expires"
+ depends on SETUP_SSR_NOTIF_TIMEOUTS
+ help
+ Trigger a kernel panic when communication between subsystems
+ through sysmon is taking too long. Also trigger a kernel panic
+ if invoking the callbacks registered with a particular subsystem's
+ notifications by the subsystem notifier framework is taking too long.
+ This is a debugging feature.
+
config MSM_BOOT_STATS
bool "Use MSM boot stats reporting"
help
diff --git a/drivers/soc/qcom/bam_dmux.c b/drivers/soc/qcom/bam_dmux.c
index 3b75e74..84e5193 100644
--- a/drivers/soc/qcom/bam_dmux.c
+++ b/drivers/soc/qcom/bam_dmux.c
@@ -1099,6 +1099,12 @@
kfree(hdr);
return -ENODEV;
}
+ if (in_global_reset) {
+ BAM_DMUX_LOG("%s: In SSR... ch_id[%d]\n", __func__, id);
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+ kfree(hdr);
+ return -ENODEV;
+ }
bam_ch[id].notify = notify;
bam_ch[id].priv = priv;
@@ -1177,6 +1183,12 @@
return 0;
}
+ if (in_global_reset) {
+ BAM_DMUX_LOG("%s: In SSR... ch_id[%d]\n", __func__, id);
+ read_unlock(&ul_wakeup_lock);
+ return 0;
+ }
+
hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_ATOMIC);
if (hdr == NULL) {
read_unlock(&ul_wakeup_lock);
diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c
index 446669f..d21e2e9 100644
--- a/drivers/soc/qcom/bgcom_spi.c
+++ b/drivers/soc/qcom/bgcom_spi.c
@@ -928,6 +928,8 @@
pr_debug("No callback registered\n");
return IRQ_HANDLED;
} else if (spi_state == BGCOM_SPI_BUSY) {
+ /* delay for SPI to be freed */
+ msleep(50);
return IRQ_HANDLED;
} else if (!bg_spi->irq_lock) {
bg_spi->irq_lock = 1;
diff --git a/drivers/soc/qcom/big_cluster_min_freq_adjust.c b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
index 979dd81..32feedc 100644
--- a/drivers/soc/qcom/big_cluster_min_freq_adjust.c
+++ b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
@@ -180,6 +180,11 @@
if (!p->min_freq_floor)
p->min_freq_floor = POLICY_MIN;
+ p->min_freq_state = RESET_MIN_FLOOR;
+ p->min_freq_request = RESET_MIN_FLOOR;
+ spin_lock_init(&p->lock);
+ p->big_min_freq_on = true;
+
ret = cpu_pm_register_notifier(&cpu_pm_nb);
if (ret) {
pr_err("Failed to register for PM notification\n");
@@ -193,11 +198,6 @@
return ret;
}
- p->min_freq_state = RESET_MIN_FLOOR;
- p->min_freq_request = RESET_MIN_FLOOR;
- spin_lock_init(&p->lock);
- p->big_min_freq_on = true;
-
/* If BIG cluster is active at this time and continue to be active
* forever, in that case min frequency of the cluster will never be
* set to floor value. This is to trigger the state machine and set
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index bef0757..3f4ad5d 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -39,8 +39,6 @@
#define dcc_readl(drvdata, off) \
__raw_readl(drvdata->base + off)
-#define dcc_sram_writel(drvdata, val, off) \
- __raw_writel((val), drvdata->ram_base + off)
#define dcc_sram_readl(drvdata, off) \
__raw_readl(drvdata->ram_base + off)
@@ -129,6 +127,16 @@
uint64_t xpu_addr;
uint32_t xpu_unlock_count;
};
+static int dcc_sram_writel(struct dcc_drvdata *drvdata,
+ uint32_t val, uint32_t off)
+{
+ if (unlikely(off > (drvdata->ram_size - 4)))
+ return -EINVAL;
+
+ __raw_writel((val), drvdata->ram_base + off);
+
+ return 0;
+}
static int dcc_cfg_xpu(struct dcc_drvdata *drvdata, bool enable)
{
@@ -277,12 +285,17 @@
if (!prev_addr || prev_addr != addr || prev_off > off) {
/* Check if we need to write link of prev entry */
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
/* Write address */
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata, addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Reset link and prev_off */
@@ -322,7 +335,9 @@
((entry->len << 8) & BM(8, 14))) << pos;
if (pos) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
link = 0;
}
@@ -332,12 +347,16 @@
}
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
/* Setting zero to indicate end of the list */
- dcc_sram_writel(drvdata, 0, sram_offset);
+ ret = dcc_sram_writel(drvdata, 0, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* check if the data will overstep */
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index ac50996..279461d 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -35,8 +35,6 @@
#define dcc_readl(drvdata, off) \
__raw_readl(drvdata->base + off)
-#define dcc_sram_writel(drvdata, val, off) \
- __raw_writel((val), drvdata->ram_base + off)
#define dcc_sram_readl(drvdata, off) \
__raw_readl(drvdata->ram_base + off)
@@ -153,6 +151,17 @@
uint8_t cti_trig;
};
+static int dcc_sram_writel(struct dcc_drvdata *drvdata,
+ uint32_t val, uint32_t off)
+{
+ if (unlikely(off > (drvdata->ram_size - 4)))
+ return -EINVAL;
+
+ __raw_writel((val), drvdata->ram_base + off);
+
+ return 0;
+}
+
static bool dcc_ready(struct dcc_drvdata *drvdata)
{
uint32_t val;
@@ -252,7 +261,10 @@
* processing the list
*/
link |= ((0x1 << 8) & BM(8, 14));
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Reset link and prev_off */
addr = 0x00;
@@ -262,13 +274,21 @@
}
addr = DCC_RD_MOD_WR_DESCRIPTOR;
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata, addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
- dcc_sram_writel(drvdata, entry->mask, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ entry->mask, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
- dcc_sram_writel(drvdata, entry->write_val, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ entry->write_val, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
addr = 0;
break;
@@ -278,7 +298,10 @@
{
/* Check if we need to write link of prev entry */
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
@@ -288,7 +311,10 @@
loop |= DCC_LOOP_DESCRIPTOR;
total_len += (total_len - loop_len) * loop_cnt;
- dcc_sram_writel(drvdata, loop, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ loop, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
loop_start = false;
@@ -317,7 +343,10 @@
* processing the list
*/
link |= ((0x1 << 8) & BM(8, 14));
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Reset link and prev_off */
addr = 0x00;
@@ -340,13 +369,20 @@
addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND
| DCC_AHB_IND;
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata, addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
- dcc_sram_writel(drvdata, entry->write_val, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ entry->write_val, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
addr = 0x00;
link = 0;
@@ -370,8 +406,10 @@
if (!prev_addr || prev_addr != addr || prev_off > off) {
/* Check if we need to write prev link entry */
if (link) {
- dcc_sram_writel(drvdata,
+ ret = dcc_sram_writel(drvdata,
link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
dev_dbg(drvdata->dev,
@@ -379,7 +417,10 @@
sram_offset);
/* Write address */
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Reset link and prev_off */
@@ -422,7 +463,10 @@
link |= DCC_LINK_DESCRIPTOR;
if (pos) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata,
+ link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
link = 0;
}
@@ -434,7 +478,9 @@
}
if (link) {
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
@@ -450,13 +496,17 @@
addr = (0xC105E) & BM(0, 27);
addr |= DCC_ADDR_DESCRIPTOR;
- dcc_sram_writel(drvdata, addr, sram_offset);
+ ret = dcc_sram_writel(drvdata, addr, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
}
/* Setting zero to indicate end of the list */
link = DCC_LINK_DESCRIPTOR;
- dcc_sram_writel(drvdata, link, sram_offset);
+ ret = dcc_sram_writel(drvdata, link, sram_offset);
+ if (ret)
+ goto overstep;
sram_offset += 4;
/* Update ram_cfg and check if the data will overstep */
diff --git a/drivers/soc/qcom/glink_bgcom_xprt.c b/drivers/soc/qcom/glink_bgcom_xprt.c
index 3c3923c..290d667 100644
--- a/drivers/soc/qcom/glink_bgcom_xprt.c
+++ b/drivers/soc/qcom/glink_bgcom_xprt.c
@@ -324,25 +324,22 @@
uint32_t size)
{
int ret;
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
mutex_lock(&einfo->write_lock);
+ add_wait_queue(&einfo->tx_blocked_queue, &wait);
while (glink_bgcom_get_tx_avail(einfo) < (size/WORD_SIZE)) {
send_tx_blocked_signal(einfo);
- prepare_to_wait(&einfo->tx_blocked_queue, &wait,
- TASK_UNINTERRUPTIBLE);
- if (glink_bgcom_get_tx_avail(einfo) < (size/WORD_SIZE)
- && !einfo->in_ssr) {
- mutex_unlock(&einfo->write_lock);
- schedule();
- mutex_lock(&einfo->write_lock);
- }
- finish_wait(&einfo->tx_blocked_queue, &wait);
if (einfo->in_ssr) {
+ remove_wait_queue(&einfo->tx_blocked_queue, &wait);
mutex_unlock(&einfo->write_lock);
return -EFAULT;
}
+ mutex_unlock(&einfo->write_lock);
+ wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+ mutex_lock(&einfo->write_lock);
}
+ remove_wait_queue(&einfo->tx_blocked_queue, &wait);
ret = glink_bgcom_xprt_tx_cmd_safe(einfo, src, size);
mutex_unlock(&einfo->write_lock);
return ret;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index b9572bd..7286f08 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2211,6 +2211,7 @@
err_setup_msa:
icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL);
+ clear_bit(ICNSS_MSA0_ASSIGNED, &penv->state);
err_power_on:
icnss_hw_power_off(penv);
fail:
@@ -3529,7 +3530,6 @@
goto out;
}
- WARN_ON(1);
icnss_pr_warn("Initiate PD restart at WLAN FW, state: 0x%lx\n",
priv->state);
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index 7a4ab97..aff0389 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -747,6 +747,7 @@
{
int ret;
char buf[MAX_ERR_BUFFER_SIZE] = {0};
+ uint32_t msg_id;
if (glink_enabled)
ret = msm_rpm_glink_rx_poll(glink_data->glink_handle);
@@ -773,24 +774,42 @@
* spinlock from being locked out.
*/
- if (!timeout) {
- pr_err("Timed out waiting for RPM ACK\n");
+ if (!timeout)
return -EAGAIN;
- }
ret = msm_rpm_read_smd_data(buf);
- if (!ret)
+ if (!ret) {
+ /* Mimic Glink behavior to ensure that the
+ * data is read and the msg is removed from
+ * the wait list. We should have gotten here
+ * only when there are no drivers waiting on
+ * ACKs. msm_rpm_get_entry_from_msg_id()
+ * return non-NULL only then.
+ */
+ msg_id = msm_rpm_get_msg_id_from_ack(buf);
+ msm_rpm_process_ack(msg_id, 0);
ret = smd_is_pkt_avail(msm_rpm_data.ch_info);
+ }
}
return ret;
}
+static void msm_rpm_flush_noack_messages(void)
+{
+ while (!list_empty(&msm_rpm_wait_list)) {
+ if (!msm_rpm_read_sleep_ack())
+ break;
+ }
+}
+
static int msm_rpm_flush_requests(bool print)
{
struct rb_node *t;
int ret;
int count = 0;
+ msm_rpm_flush_noack_messages();
+
for (t = rb_first(&tr_root); t; t = rb_next(t)) {
struct slp_buf *s = rb_entry(t, struct slp_buf, node);
@@ -827,8 +846,10 @@
if (ret >= 0)
count--;
- else
+ else {
+ pr_err("Timed out waiting for RPM ACK\n");
return ret;
+ }
}
}
return 0;
@@ -1057,14 +1078,18 @@
bool msm_rpm_waiting_for_ack(void)
{
- bool ret;
+ bool ret = false;
unsigned long flags;
+ struct msm_rpm_wait_data *elem = NULL;
spin_lock_irqsave(&msm_rpm_list_lock, flags);
- ret = list_empty(&msm_rpm_wait_list);
+ elem = list_first_entry_or_null(&msm_rpm_wait_list,
+ struct msm_rpm_wait_data, list);
+ if (elem)
+ ret = !elem->delete_on_ack;
spin_unlock_irqrestore(&msm_rpm_list_lock, flags);
- return !ret;
+ return ret;
}
static struct msm_rpm_wait_data *msm_rpm_get_entry_from_msg_id(uint32_t msg_id)
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index 110cdf7..f20eda2 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@
#include <trace/events/trace_msm_pil_event.h>
#include <asm/current.h>
+#include <linux/timer.h>
#include "peripheral-loader.h"
@@ -53,6 +54,35 @@
#define SHUTDOWN_ACK_MAX_LOOPS 100
#define SHUTDOWN_ACK_DELAY_MS 100
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+/* Timeout used for detection of notification hangs. In seconds.*/
+#define SYSMON_COMM_TIMEOUT CONFIG_SSR_SYSMON_NOTIF_TIMEOUT
+#define SUBSYS_NOTIF_TIMEOUT CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT
+
+#define setup_timeout(dest_ss, source_ss, comm_type) \
+ _setup_timeout(dest_ss, source_ss, comm_type)
+#define cancel_timeout(subsys) del_timer(&subsys->timeout_data.timer)
+#define init_subsys_timer(subsys) _init_subsys_timer(subsys)
+
+/* Timeout values */
+static unsigned long timeout_vals[NUM_SSR_COMMS] = {
+ [SUBSYS_TO_SUBSYS_SYSMON] = SYSMON_COMM_TIMEOUT,
+ [SUBSYS_TO_HLOS] = SUBSYS_NOTIF_TIMEOUT,
+ [HLOS_TO_SUBSYS_SYSMON_SHUTDOWN] = SYSMON_COMM_TIMEOUT,
+};
+
+#ifdef CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT
+#define SSR_NOTIF_TIMEOUT_WARN(fmt...) panic(fmt)
+#else /* CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT */
+#define SSR_NOTIF_TIMEOUT_WARN(fmt...) WARN(1, fmt)
+#endif /* CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT */
+
+#else /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+#define setup_timeout(dest_ss, source_ss, sysmon_comm)
+#define cancel_timeout(subsys)
+#define init_subsys_timer(subsys)
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+
/**
* enum p_subsys_state - state of a subsystem (private)
* @SUBSYS_NORMAL: subsystem is operating normally
@@ -470,15 +500,89 @@
return enable_ramdumps;
}
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+static void notif_timeout_handler(unsigned long data)
+{
+ char *sysmon_msg = "Sysmon communication from %s to %s taking too long";
+ char *subsys_notif_msg = "Subsys notifier chain for %s taking too long";
+ char *sysmon_shutdwn_msg = "sysmon_send_shutdown to %s taking too long";
+ char *unknown_err_msg = "Unknown communication occurred";
+ struct subsys_notif_timeout *timeout_data =
+ (struct subsys_notif_timeout *) data;
+ enum ssr_comm comm_type = timeout_data->comm_type;
+
+ switch (comm_type) {
+ case SUBSYS_TO_SUBSYS_SYSMON:
+ SSR_NOTIF_TIMEOUT_WARN(sysmon_msg, timeout_data->source_name,
+ timeout_data->dest_name);
+ break;
+ case SUBSYS_TO_HLOS:
+ SSR_NOTIF_TIMEOUT_WARN(subsys_notif_msg,
+ timeout_data->source_name);
+ break;
+ case HLOS_TO_SUBSYS_SYSMON_SHUTDOWN:
+ SSR_NOTIF_TIMEOUT_WARN(sysmon_shutdwn_msg,
+ timeout_data->dest_name);
+ break;
+ default:
+ SSR_NOTIF_TIMEOUT_WARN(unknown_err_msg);
+ }
+
+}
+
+static void _setup_timeout(struct subsys_desc *source_ss,
+ struct subsys_desc *dest_ss, enum ssr_comm comm_type)
+{
+ struct subsys_notif_timeout *timeout_data;
+ unsigned long timeout;
+
+ switch (comm_type) {
+ case SUBSYS_TO_SUBSYS_SYSMON:
+ timeout_data = &source_ss->timeout_data;
+ timeout_data->dest_name = dest_ss->name;
+ timeout_data->source_name = source_ss->name;
+ break;
+ case SUBSYS_TO_HLOS:
+ timeout_data = &source_ss->timeout_data;
+ timeout_data->dest_name = NULL;
+ timeout_data->source_name = source_ss->name;
+ break;
+ case HLOS_TO_SUBSYS_SYSMON_SHUTDOWN:
+ timeout_data = &dest_ss->timeout_data;
+ timeout_data->dest_name = dest_ss->name;
+ timeout_data->source_name = NULL;
+ break;
+ default:
+ return;
+ }
+
+ timeout_data->timer.data = (unsigned long) timeout_data;
+ timeout_data->comm_type = comm_type;
+ timeout = jiffies + msecs_to_jiffies(timeout_vals[comm_type]);
+ mod_timer(&timeout_data->timer, timeout);
+}
+
+static void _init_subsys_timer(struct subsys_desc *subsys)
+{
+ init_timer(&subsys->timeout_data.timer);
+ subsys->timeout_data.timer.function = notif_timeout_handler;
+}
+
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+
static void send_sysmon_notif(struct subsys_device *dev)
{
struct subsys_device *subsys;
mutex_lock(&subsys_list_lock);
list_for_each_entry(subsys, &subsys_list, list)
- if ((subsys->notif_state > 0) && (subsys != dev))
+ if ((subsys->notif_state > 0) && (subsys != dev)) {
+ setup_timeout(subsys->desc, dev->desc,
+ SUBSYS_TO_SUBSYS_SYSMON);
sysmon_send_event(dev->desc, subsys->desc,
subsys->notif_state);
+ cancel_timeout(subsys->desc);
+ }
mutex_unlock(&subsys_list_lock);
}
@@ -520,9 +624,13 @@
mutex_lock(&subsys_list_lock);
list_for_each_entry(subsys, &subsys_list, list)
if (dev != subsys &&
- subsys->track.state == SUBSYS_ONLINE)
+ subsys->track.state == SUBSYS_ONLINE) {
+ setup_timeout(dev->desc, subsys->desc,
+ SUBSYS_TO_SUBSYS_SYSMON);
sysmon_send_event(subsys->desc, dev->desc,
- notif);
+ notif);
+ cancel_timeout(dev->desc);
+ }
mutex_unlock(&subsys_list_lock);
if (notif == SUBSYS_AFTER_POWERUP &&
@@ -536,8 +644,10 @@
notif_data.pdev = pdev;
trace_pil_notif("before_send_notif", notif, dev->desc->fw_name);
+ setup_timeout(dev->desc, NULL, SUBSYS_TO_HLOS);
subsys_notif_queue_notification(dev->notify, notif,
¬if_data);
+ cancel_timeout(dev->desc);
trace_pil_notif("after_send_notif", notif, dev->desc->fw_name);
}
}
@@ -750,8 +860,11 @@
if (!of_property_read_bool(subsys->desc->dev->of_node,
"qcom,pil-force-shutdown")) {
subsys_set_state(subsys, SUBSYS_OFFLINING);
+ setup_timeout(NULL, subsys->desc,
+ HLOS_TO_SUBSYS_SYSMON_SHUTDOWN);
subsys->desc->sysmon_shutdown_ret =
sysmon_send_shutdown(subsys->desc);
+ cancel_timeout(subsys->desc);
if (subsys->desc->sysmon_shutdown_ret)
pr_debug("Graceful shutdown failed for %s\n", name);
}
@@ -1639,6 +1752,7 @@
INIT_WORK(&subsys->work, subsystem_restart_wq_func);
INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr);
spin_lock_init(&subsys->track.s_lock);
+ init_subsys_timer(desc);
subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
if (subsys->id < 0) {
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 32729c6..b5d9131 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -541,8 +541,14 @@
} else if (ret < 0 && ret != -ENOTSUPP) {
pr_err("Failed to wake function %s from suspend state. ret=%d.\n",
func->name ? func->name : "", ret);
+ } else {
+ /*
+ * Return -EAGAIN to queue the request from
+ * function driver wakeup function.
+ */
+ ret = -EAGAIN;
+ goto done;
}
- goto done;
}
if (!func->func_is_suspended)
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 0c4baf2..5222f79 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -96,6 +96,21 @@
return remote_wakeup_allowed;
}
+static void usb_gsi_check_pending_wakeup(struct usb_function *f)
+{
+ struct f_gsi *gsi = func_to_gsi(f);
+
+ /*
+ * If host suspended bus without receiving notification request then
+ * initiate remote-wakeup. As driver won't be able to do it later since
+ * notification request is already queued.
+ */
+ if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
+ mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
+ log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
+ }
+}
+
static void post_event(struct gsi_data_port *port, u8 event)
{
unsigned long flags;
@@ -1834,6 +1849,9 @@
gsi->c_port.notify_req_queued = false;
spin_unlock_irqrestore(&gsi->c_port.lock, flags);
+ log_event_dbg("%s: status:%d req_queued:%d",
+ __func__, status, gsi->c_port.notify_req_queued);
+
switch (status) {
case -ECONNRESET:
case -ESHUTDOWN:
@@ -2494,6 +2512,7 @@
*/
if (gsi->prot_id == USB_PROT_GPS_CTRL) {
log_event_dbg("%s: suspend done\n", __func__);
+ usb_gsi_check_pending_wakeup(f);
return;
}
@@ -2503,16 +2522,7 @@
post_event(&gsi->d_port, EVT_SUSPEND);
queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
log_event_dbg("gsi suspended");
-
- /*
- * If host suspended bus without receiving notification request then
- * initiate remote-wakeup. As driver won't be able to do it later since
- * notification request is already queued.
- */
- if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
- mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
- log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
- }
+ usb_gsi_check_pending_wakeup(f);
}
static void gsi_resume(struct usb_function *f)
diff --git a/drivers/video/fbdev/msm/mdss_dba_utils.c b/drivers/video/fbdev/msm/mdss_dba_utils.c
index 2758a5a..f904ace 100644
--- a/drivers/video/fbdev/msm/mdss_dba_utils.c
+++ b/drivers/video/fbdev/msm/mdss_dba_utils.c
@@ -734,7 +734,6 @@
struct mdss_dba_utils_data *udata = NULL;
struct msm_dba_reg_info info;
struct cec_abstract_init_data cec_abst_init_data;
- void *cec_abst_data;
int ret = 0;
if (!uid) {
@@ -823,7 +822,7 @@
udata->cec_abst_data = cec_abstract_init(&cec_abst_init_data);
if (IS_ERR_OR_NULL(udata->cec_abst_data)) {
pr_err("error initializing cec abstract module\n");
- ret = PTR_ERR(cec_abst_data);
+ ret = PTR_ERR(udata->cec_abst_data);
goto error;
}
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index a470656..25a2600 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1462,6 +1462,11 @@
(mipi->vc << 8) | DTYPE_DCS_LWRITE;
stream_total = pinfo->roi.h << 16 | pinfo->roi.w;
} else {
+ width = width + pdata->panel_info.lcdc.border_left +
+ pdata->panel_info.lcdc.border_right;
+ height = height + pdata->panel_info.lcdc.border_top +
+ pdata->panel_info.lcdc.border_bottom;
+ ystride = width * bpp + 1;
stream_ctrl = (ystride << 16) | (mipi->vc << 8) |
DTYPE_DCS_LWRITE;
stream_total = height << 16 | width;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 4683c71..bbffc06 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -960,7 +960,7 @@
{
u32 prefill_us = 0;
u32 prefill_amortized = 0;
- struct mdss_data_type *mdata;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_mixer *mixer;
struct mdss_panel_info *pinfo;
u32 fps, v_total;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3de3906..7c8a273 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1754,7 +1754,7 @@
int mdss_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
{
- struct mdss_rect l_roi, r_roi;
+ struct mdss_rect l_roi = {0}, r_roi = {0};
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_ctl *sctl;
diff --git a/fs/crypto/fscrypt_ice.h b/fs/crypto/fscrypt_ice.h
index c540506..d448eae 100644
--- a/fs/crypto/fscrypt_ice.h
+++ b/fs/crypto/fscrypt_ice.h
@@ -21,7 +21,7 @@
{
if (!inode->i_sb->s_cop)
return 0;
- if (!inode->i_sb->s_cop->is_encrypted((struct inode *)inode))
+ if (!IS_ENCRYPTED((struct inode *)inode))
return 0;
return fscrypt_using_hardware_encryption(inode);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 03ff3aa..6563f88 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -105,7 +105,8 @@
filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS)
return true;
- if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE)
+ if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE &&
+ filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
return true;
return false;
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index 737b6fc..1866733 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -267,7 +267,7 @@
static int fscrypt_data_encryption_mode(struct inode *inode)
{
- return fscrypt_should_be_processed_by_ice(inode) ?
+ return fscrypt_is_ice_capable(inode->i_sb) ?
FS_ENCRYPTION_MODE_PRIVATE : FS_ENCRYPTION_MODE_AES_256_XTS;
}
diff --git a/fs/direct-io.c b/fs/direct-io.c
index bf03a92..081e539 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -37,6 +37,8 @@
#include <linux/uio.h>
#include <linux/atomic.h>
#include <linux/prefetch.h>
+#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION)
+#include <linux/fscrypt.h>
/*
* How many user pages to map in one call to get_user_pages(). This determines
@@ -390,6 +392,21 @@
sdio->logical_offset_in_bio = sdio->cur_page_fs_offset;
}
+static bool is_inode_filesystem_type(const struct inode *inode,
+ const char *fs_type)
+{
+ if (!inode || !fs_type)
+ return false;
+
+ if (!inode->i_sb)
+ return false;
+
+ if (!inode->i_sb->s_type)
+ return false;
+
+ return (strcmp(inode->i_sb->s_type->name, fs_type) == 0);
+}
+
/*
* In the AIO read case we speculatively dirty the pages before starting IO.
* During IO completion, any of these pages which happen to have been written
@@ -412,6 +429,14 @@
bio_set_pages_dirty(bio);
bio->bi_dio_inode = dio->inode;
+
+/* iv sector for security/pfe/pfk_fscrypt.c and f2fs in fs/f2fs/f2fs.h.*/
+#define PG_DUN_NEW(i,p) \
+ (((((u64)(i)->i_ino) & 0xffffffff) << 32) | ((p) & 0xffffffff))
+
+ if (is_inode_filesystem_type(dio->inode, "f2fs"))
+ fscrypt_set_ice_dun(dio->inode, bio, PG_DUN_NEW(dio->inode,
+ (sdio->logical_offset_in_bio >> PAGE_SHIFT)));
dio->bio_bdev = bio->bi_bdev;
if (sdio->submit_io) {
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index fec1eaa..6941365 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1317,7 +1317,10 @@
ext4_itable_unused_count(sb, gdp)),
sbi->s_inodes_per_block);
- if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
+ if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) ||
+ ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) -
+ ext4_itable_unused_count(sb, gdp)) <
+ EXT4_FIRST_INO(sb)))) {
ext4_error(sb, "Something is wrong with group %u: "
"used itable blocks: %d; "
"itable unused count: %u",
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2436c76..ab72207 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1180,11 +1180,6 @@
EXT4_NAME_LEN;
}
-static inline bool ext4_is_encrypted(struct inode *inode)
-{
- return ext4_encrypted_inode(inode);
-}
-
static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:",
.get_context = ext4_get_context,
@@ -1192,7 +1187,6 @@
.dummy_context = ext4_dummy_context,
.empty_dir = ext4_empty_dir,
.max_namelen = ext4_max_namelen,
- .is_encrypted = ext4_is_encrypted,
};
#endif
@@ -3047,14 +3041,8 @@
if (!gdp)
continue;
- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
- continue;
- if (group != 0)
+ if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
break;
- ext4_error(sb, "Inode table for bg 0 marked as "
- "needing zeroing");
- if (sb->s_flags & MS_RDONLY)
- return ngroups;
}
return group;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9efe77e..25256ae 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -565,7 +565,8 @@
bio->bi_end_io = f2fs_read_end_io;
bio_set_op_attrs(bio, REQ_OP_READ, 0);
- if (f2fs_encrypted_file(inode))
+ if (f2fs_encrypted_file(inode) &&
+ !fscrypt_using_hardware_encryption(inode))
post_read_steps |= 1 << STEP_DECRYPT;
if (post_read_steps) {
ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
@@ -1548,9 +1549,9 @@
bio = NULL;
goto set_error_page;
}
+ if (bio_encrypted)
+ fscrypt_set_ice_dun(inode, bio, dun);
}
- if (bio_encrypted)
- fscrypt_set_ice_dun(inode, bio, dun);
if (bio_add_page(bio, page, blocksize, 0) < blocksize)
goto submit_and_realloc;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a7711d7..c850618 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1344,6 +1344,8 @@
seq_printf(seq, ",fsync_mode=%s", "posix");
else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT)
seq_printf(seq, ",fsync_mode=%s", "strict");
+ else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_NOBARRIER)
+ seq_printf(seq, ",fsync_mode=%s", "nobarrier");
return 0;
}
@@ -1940,11 +1942,6 @@
inode->i_sb->s_blocksize : F2FS_NAME_LEN;
}
-static inline bool f2fs_is_encrypted(struct inode *inode)
-{
- return f2fs_encrypted_file(inode);
-}
-
static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:",
.get_context = f2fs_get_context,
@@ -1952,7 +1949,6 @@
.dummy_context = f2fs_dummy_context,
.empty_dir = f2fs_empty_dir,
.max_namelen = f2fs_max_namelen,
- .is_encrypted = f2fs_is_encrypted,
};
#endif
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 211e80b..9f91d48 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -103,6 +103,7 @@
/* the following two fields are internal, NEVER access directly */
unsigned int __data_len; /* total data len */
sector_t __sector; /* sector cursor */
+ u64 __dun; /* dun for UFS */
struct bio *bio;
struct bio *biotail;
@@ -866,6 +867,11 @@
return rq->__sector;
}
+static inline sector_t blk_rq_dun(const struct request *rq)
+{
+ return rq->__dun;
+}
+
static inline unsigned int blk_rq_bytes(const struct request *rq)
{
return rq->__data_len;
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 8f4e90c..7a7fce9 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -19,12 +19,9 @@
struct fscrypt_ctx;
-/* iv sector for security/pfe/pfk_fscrypt.c and f2fs. sizeof is required
- * to accommodate 32 bit targets.
- */
+/* iv sector for security/pfe/pfk_fscrypt.c and f2fs */
#define PG_DUN(i, p) \
- ((((i)->i_ino & 0xffffffff) << (sizeof((i)->i_ino)/2)) | \
- ((p)->index & 0xffffffff))
+ (((((u64)(i)->i_ino) & 0xffffffff) << 32) | ((p)->index & 0xffffffff))
struct fscrypt_info;
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 32e2b6c..2f62d5b 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -29,7 +29,6 @@
bool (*dummy_context)(struct inode *);
bool (*empty_dir)(struct inode *);
unsigned (*max_namelen)(struct inode *);
- bool (*is_encrypted)(struct inode *);
};
struct fscrypt_ctx {
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
new file mode 100644
index 0000000..0380d89
--- /dev/null
+++ b/include/linux/irq_sim.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_IRQ_SIM_H
+#define _LINUX_IRQ_SIM_H
+/*
+ * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/irq_work.h>
+#include <linux/device.h>
+
+/*
+ * Provides a framework for allocating simulated interrupts which can be
+ * requested like normal irqs and enqueued from process context.
+ */
+
+struct irq_sim_work_ctx {
+ struct irq_work work;
+ int irq;
+};
+
+struct irq_sim_irq_ctx {
+ int irqnum;
+ bool enabled;
+};
+
+struct irq_sim {
+ struct irq_sim_work_ctx work_ctx;
+ int irq_base;
+ unsigned int irq_count;
+ struct irq_sim_irq_ctx *irqs;
+};
+
+int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs);
+int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
+ unsigned int num_irqs);
+void irq_sim_fini(struct irq_sim *sim);
+void irq_sim_fire(struct irq_sim *sim, unsigned int offset);
+int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset);
+
+#endif /* _LINUX_IRQ_SIM_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 149b718..4cbe862 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -350,9 +350,9 @@
* @upthreshold: up-threshold supplied to ondemand governor
* @downthreshold: down-threshold supplied to ondemand governor
* @need_freq_change: flag indicating if a frequency change is required
- * @clk_scaling_in_progress: flag indicating if there's ongoing frequency change
* @is_busy_started: flag indicating if a request is handled by the HW
* @enable: flag indicating if the clock scaling logic is enabled for this host
+ * @is_suspended: to make devfreq request queued when mmc is suspened
*/
struct mmc_devfeq_clk_scaling {
spinlock_t lock;
@@ -377,9 +377,9 @@
unsigned int lower_bus_speed_mode;
#define MMC_SCALING_LOWER_DDR52_MODE 1
bool need_freq_change;
- bool clk_scaling_in_progress;
bool is_busy_started;
bool enable;
+ bool is_suspended;
};
struct mmc_host {
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3fbfe96..6b20f91 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2986,6 +2986,8 @@
return __skb_grow(skb, len);
}
+#define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode)
+
#define skb_queue_walk(queue, skb) \
for (skb = (queue)->next; \
skb != (struct sk_buff *)(queue); \
diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h
index 9a0a53e..c1c1386 100644
--- a/include/soc/qcom/subsystem_restart.h
+++ b/include/soc/qcom/subsystem_restart.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,30 @@
struct device;
struct module;
+enum ssr_comm {
+ SUBSYS_TO_SUBSYS_SYSMON,
+ SUBSYS_TO_HLOS,
+ HLOS_TO_SUBSYS_SYSMON_SHUTDOWN,
+ NUM_SSR_COMMS,
+};
+
+/**
+ * struct subsys_notif_timeout - timeout data used by notification timeout hdlr
+ * @comm_type: Specifies if the type of communication being tracked is
+ * through sysmon between two subsystems, subsystem notifier call chain, or
+ * sysmon shutdown.
+ * @dest_name: subsystem to which sysmon notification is being sent to
+ * @source_name: subsystem which generated event that notification is being sent
+ * for
+ * @timer: timer for scheduling timeout
+ */
+struct subsys_notif_timeout {
+ enum ssr_comm comm_type;
+ const char *dest_name;
+ const char *source_name;
+ struct timer_list timer;
+};
+
/**
* struct subsys_desc - subsystem descriptor
* @name: name of subsystem
@@ -95,6 +119,9 @@
bool system_debug;
bool ignore_ssr_failure;
const char *edge;
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+ struct subsys_notif_timeout timeout_data;
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
};
/**
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index 34ecd82..bd9836c 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -586,6 +586,9 @@
* @IPA_HW_v3_5: IPA hardware version 3.5
* @IPA_HW_v3_5_1: IPA hardware version 3.5.1
* @IPA_HW_v4_0: IPA hardware version 4.0
+ * @IPA_HW_v4_1: IPA hardware version 4.1
+ * @IPA_HW_v4_2: IPA hardware version 4.2
+ * @IPA_HW_v4_5: IPA hardware version 4.5
*/
enum ipa_hw_type {
IPA_HW_None = 0,
@@ -601,10 +604,16 @@
IPA_HW_v3_5 = 12,
IPA_HW_v3_5_1 = 13,
IPA_HW_v4_0 = 14,
+ IPA_HW_v4_1 = 15,
+ IPA_HW_v4_2 = 16,
+ IPA_HW_v4_5 = 17,
};
-#define IPA_HW_MAX (IPA_HW_v4_0 + 1)
+#define IPA_HW_MAX (IPA_HW_v4_5 + 1)
#define IPA_HW_v4_0 IPA_HW_v4_0
+#define IPA_HW_v4_1 IPA_HW_v4_1
+#define IPA_HW_v4_2 IPA_HW_v4_2
+#define IPA_HW_v4_5 IPA_HW_v4_5
/**
* struct ipa_rule_attrib - attributes of a routing/filtering
diff --git a/include/uapi/media/msmb_qca.h b/include/uapi/media/msmb_qca.h
index 02a6b1f..22b1006 100644
--- a/include/uapi/media/msmb_qca.h
+++ b/include/uapi/media/msmb_qca.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2018, The Linux Foundation.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
#ifndef __UAPI_LINUX_MSMB_QCA402X_H
#define __UAPI_LINUX_MSMB_QCA402X_H
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 3bbfd6a..9b2d34f 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -59,6 +59,11 @@
config IRQ_DOMAIN
bool
+# Support for simulated interrupts
+config IRQ_SIM
+ bool
+ select IRQ_WORK
+
# Support for hierarchical irq domains
config IRQ_DOMAIN_HIERARCHY
bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 1d3ee31..2c0ba4e 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -3,6 +3,7 @@
obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
+obj-$(CONFIG_IRQ_SIM) += irq_sim.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
new file mode 100644
index 0000000..8569085
--- /dev/null
+++ b/kernel/irq/irq_sim.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/irq_sim.h>
+#include <linux/irq.h>
+
+struct irq_sim_devres {
+ struct irq_sim *sim;
+};
+
+static void irq_sim_irqmask(struct irq_data *data)
+{
+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+
+ irq_ctx->enabled = false;
+}
+
+static void irq_sim_irqunmask(struct irq_data *data)
+{
+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+
+ irq_ctx->enabled = true;
+}
+
+static struct irq_chip irq_sim_irqchip = {
+ .name = "irq_sim",
+ .irq_mask = irq_sim_irqmask,
+ .irq_unmask = irq_sim_irqunmask,
+};
+
+static void irq_sim_handle_irq(struct irq_work *work)
+{
+ struct irq_sim_work_ctx *work_ctx;
+
+ work_ctx = container_of(work, struct irq_sim_work_ctx, work);
+ handle_simple_irq(irq_to_desc(work_ctx->irq));
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator: allocate a range of
+ * dummy interrupts.
+ *
+ * @sim: The interrupt simulator object to initialize.
+ * @num_irqs: Number of interrupts to allocate
+ *
+ * On success: return the base of the allocated interrupt range.
+ * On failure: a negative errno.
+ */
+int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)
+{
+ int i;
+
+ sim->irqs = kmalloc_array(num_irqs, sizeof(*sim->irqs), GFP_KERNEL);
+ if (!sim->irqs)
+ return -ENOMEM;
+
+ sim->irq_base = irq_alloc_descs(-1, 0, num_irqs, 0);
+ if (sim->irq_base < 0) {
+ kfree(sim->irqs);
+ return sim->irq_base;
+ }
+
+ for (i = 0; i < num_irqs; i++) {
+ sim->irqs[i].irqnum = sim->irq_base + i;
+ sim->irqs[i].enabled = false;
+ irq_set_chip(sim->irq_base + i, &irq_sim_irqchip);
+ irq_set_chip_data(sim->irq_base + i, &sim->irqs[i]);
+ irq_set_handler(sim->irq_base + i, &handle_simple_irq);
+ irq_modify_status(sim->irq_base + i,
+ IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+ }
+
+ init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq);
+ sim->irq_count = num_irqs;
+
+ return sim->irq_base;
+}
+EXPORT_SYMBOL_GPL(irq_sim_init);
+
+/**
+ * irq_sim_fini - Deinitialize the interrupt simulator: free the interrupt
+ * descriptors and allocated memory.
+ *
+ * @sim: The interrupt simulator to tear down.
+ */
+void irq_sim_fini(struct irq_sim *sim)
+{
+ irq_work_sync(&sim->work_ctx.work);
+ irq_free_descs(sim->irq_base, sim->irq_count);
+ kfree(sim->irqs);
+}
+EXPORT_SYMBOL_GPL(irq_sim_fini);
+
+static void devm_irq_sim_release(struct device *dev, void *res)
+{
+ struct irq_sim_devres *this = res;
+
+ irq_sim_fini(this->sim);
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator for a managed device.
+ *
+ * @dev: Device to initialize the simulator object for.
+ * @sim: The interrupt simulator object to initialize.
+ * @num_irqs: Number of interrupts to allocate
+ *
+ * On success: return the base of the allocated interrupt range.
+ * On failure: a negative errno.
+ */
+int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
+ unsigned int num_irqs)
+{
+ struct irq_sim_devres *dr;
+ int rv;
+
+ dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ rv = irq_sim_init(sim, num_irqs);
+ if (rv < 0) {
+ devres_free(dr);
+ return rv;
+ }
+
+ dr->sim = sim;
+ devres_add(dev, dr);
+
+ return rv;
+}
+EXPORT_SYMBOL_GPL(devm_irq_sim_init);
+
+/**
+ * irq_sim_fire - Enqueue an interrupt.
+ *
+ * @sim: The interrupt simulator object.
+ * @offset: Offset of the simulated interrupt which should be fired.
+ */
+void irq_sim_fire(struct irq_sim *sim, unsigned int offset)
+{
+ if (sim->irqs[offset].enabled) {
+ sim->work_ctx.irq = irq_sim_irqnum(sim, offset);
+ irq_work_queue(&sim->work_ctx.work);
+ }
+}
+EXPORT_SYMBOL_GPL(irq_sim_fire);
+
+/**
+ * irq_sim_irqnum - Get the allocated number of a dummy interrupt.
+ *
+ * @sim: The interrupt simulator object.
+ * @offset: Offset of the simulated interrupt for which to retrieve
+ * the number.
+ */
+int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset)
+{
+ return sim->irqs[offset].irqnum;
+}
+EXPORT_SYMBOL_GPL(irq_sim_irqnum);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 91a909f..335b40e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10540,8 +10540,12 @@
rcu_read_lock();
sd = rcu_dereference_check_sched_domain(rq->sd);
if (sd) {
- cpumask_and(&cpumask, nohz.idle_cpus_mask,
- sched_domain_span(sd));
+ if (energy_aware() && rq->misfit_task)
+ cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
+ sched_domain_span(sd));
+ else
+ cpumask_and(&cpumask, nohz.idle_cpus_mask,
+ sched_domain_span(sd));
cpumask_andnot(&cpumask, &cpumask,
cpu_isolated_mask);
ilb = cpumask_first(&cpumask);
@@ -10552,7 +10556,7 @@
if (!energy_aware() ||
(capacity_orig_of(cpu) ==
cpu_rq(cpu)->rd->max_cpu_capacity.val ||
- cpu_overutilized(cpu))) {
+ (cpu_overutilized(cpu) && rq->nr_running > 1))) {
cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
cpu_isolated_mask);
ilb = cpumask_first(&cpumask);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 59c1581..340a3db 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -889,12 +889,9 @@
now = jiffies;
next = now + HZ;
- if (!(state & NUD_IN_TIMER)) {
- if (neigh_probe_enable && (state & NUD_STALE))
- neigh_dbg(2, "neigh %pK is still alive\n", neigh);
- else
- goto out;
- }
+ if (!(state & NUD_IN_TIMER))
+ goto out;
+
if (state & NUD_REACHABLE) {
if (time_before_eq(now,
neigh->confirmed + neigh->parms->reachable_time)) {
@@ -1185,10 +1182,7 @@
neigh_del_timer(neigh);
if (new & NUD_PROBE)
atomic_set(&neigh->probes, 0);
- if (new & NUD_IN_TIMER || (
- neigh_probe_enable &&
- (neigh->tbl->family == AF_INET6) &&
- (new & NUD_STALE)))
+ if (new & NUD_IN_TIMER)
neigh_add_timer(neigh, (jiffies +
((new & NUD_REACHABLE) ?
neigh->parms->reachable_time :
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index f0fc835..c244b72 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4909,6 +4909,7 @@
static void tcp_collapse_ofo_queue(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
+ u32 range_truesize, sum_tiny = 0;
struct sk_buff *skb, *head;
struct rb_node *p;
u32 start, end;
@@ -4927,6 +4928,7 @@
}
start = TCP_SKB_CB(skb)->seq;
end = TCP_SKB_CB(skb)->end_seq;
+ range_truesize = skb->truesize;
for (head = skb;;) {
skb = tcp_skb_next(skb, NULL);
@@ -4937,11 +4939,20 @@
if (!skb ||
after(TCP_SKB_CB(skb)->seq, end) ||
before(TCP_SKB_CB(skb)->end_seq, start)) {
- tcp_collapse(sk, NULL, &tp->out_of_order_queue,
- head, skb, start, end);
+ /* Do not attempt collapsing tiny skbs */
+ if (range_truesize != head->truesize ||
+ end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) {
+ tcp_collapse(sk, NULL, &tp->out_of_order_queue,
+ head, skb, start, end);
+ } else {
+ sum_tiny += range_truesize;
+ if (sum_tiny > sk->sk_rcvbuf >> 3)
+ return;
+ }
goto new_range;
}
+ range_truesize += skb->truesize;
if (unlikely(before(TCP_SKB_CB(skb)->seq, start)))
start = TCP_SKB_CB(skb)->seq;
if (after(TCP_SKB_CB(skb)->end_seq, end))
@@ -4956,6 +4967,7 @@
* 2) not add too big latencies if thousands of packets sit there.
* (But if application shrinks SO_RCVBUF, we could still end up
* freeing whole queue here)
+ * 3) Drop at least 12.5 % of sk_rcvbuf to avoid malicious attacks.
*
* Return true if queue has shrunk.
*/
@@ -4963,20 +4975,26 @@
{
struct tcp_sock *tp = tcp_sk(sk);
struct rb_node *node, *prev;
+ int goal;
if (RB_EMPTY_ROOT(&tp->out_of_order_queue))
return false;
NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED);
+ goal = sk->sk_rcvbuf >> 3;
node = &tp->ooo_last_skb->rbnode;
do {
prev = rb_prev(node);
rb_erase(node, &tp->out_of_order_queue);
+ goal -= rb_to_skb(node)->truesize;
tcp_drop(sk, rb_entry(node, struct sk_buff, rbnode));
- sk_mem_reclaim(sk);
- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
- !tcp_under_memory_pressure(sk))
- break;
+ if (!prev || goal <= 0) {
+ sk_mem_reclaim(sk);
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
+ !tcp_under_memory_pressure(sk))
+ break;
+ goal = sk->sk_rcvbuf >> 3;
+ }
node = prev;
} while (node);
tp->ooo_last_skb = rb_entry(prev, struct sk_buff, rbnode);
@@ -5011,6 +5029,9 @@
else if (tcp_under_memory_pressure(sk))
tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
+ return 0;
+
tcp_collapse_ofo_queue(sk);
if (!skb_queue_empty(&sk->sk_receive_queue))
tcp_collapse(sk, &sk->sk_receive_queue, NULL,
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 0fdd61a..38fbe09 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -1141,8 +1141,8 @@
country TT: DFS-FCC
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24)
- (5250 - 5330 @ 80), (24), DFS
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
# 60 gHz band channels 1-3, FCC
@@ -1216,7 +1216,7 @@
(5735 - 5875 @ 80), (14)
country VE: DFS-FCC
- (2402 - 2482 @ 40), (20)
+ (2402 - 2482 @ 40), (30)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f00e7d3..e086950 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -11438,6 +11438,7 @@
return -EOPNOTSUPP;
if (!info->attrs[NL80211_ATTR_MDID] ||
+ !info->attrs[NL80211_ATTR_IE] ||
!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 9195f23..e4f9816 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1688,7 +1688,9 @@
* as some drivers used this to restore its orig_* reg domain.
*/
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
- wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
+ wiphy->regulatory_flags & REGULATORY_CUSTOM_REG &&
+ !(wiphy->regulatory_flags &
+ REGULATORY_WIPHY_SELF_MANAGED))
reg_call_notifier(wiphy, lr);
return;
}
@@ -2157,26 +2159,6 @@
}
}
-static bool reg_only_self_managed_wiphys(void)
-{
- struct cfg80211_registered_device *rdev;
- struct wiphy *wiphy;
- bool self_managed_found = false;
-
- ASSERT_RTNL();
-
- list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
- wiphy = &rdev->wiphy;
- if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
- self_managed_found = true;
- else
- return false;
- }
-
- /* make sure at least one self-managed wiphy exists */
- return self_managed_found;
-}
-
/*
* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
* Regulatory hints come on a first come first serve basis and we
@@ -2209,10 +2191,6 @@
spin_unlock(®_requests_lock);
notify_self_managed_wiphys(reg_request);
- if (reg_only_self_managed_wiphys()) {
- reg_free_request(reg_request);
- return;
- }
reg_process_hint(reg_request);
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index 740da32..8ad25cc 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -220,11 +220,7 @@
if (!page_mapping(bio->bi_io_vec->bv_page))
return NULL;
- if (!bio->bi_io_vec->bv_page->mapping->host)
-
- return NULL;
-
- return bio->bi_io_vec->bv_page->mapping->host;
+ return page_mapping(bio->bi_io_vec->bv_page)->host;
}
/**