aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml172
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml84
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie.txt1
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt6
-rw-r--r--Documentation/devicetree/bindings/slimbus/slim-ngd-qcom-ctrl.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt57
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml73
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,wcd9335.txt20
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml145
-rw-r--r--Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml112
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/include/asm/local64.h1
-rw-r--r--arch/arc/include/asm/Kbuild1
-rw-r--r--arch/arm/include/asm/Kbuild1
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile1
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi49
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi56
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi32
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150l.dtsi20
-rw-r--r--arch/arm64/boot/dts/qcom/pm8994.dtsi9
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8994.dtsi28
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5.dts764
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-db845c.dts7
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi104
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-mtp.dts44
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi7
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-mtp.dts424
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts18
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi1128
-rw-r--r--arch/arm64/configs/defconfig69
-rw-r--r--arch/arm64/include/asm/Kbuild1
-rw-r--r--arch/csky/include/asm/Kbuild1
-rw-r--r--arch/h8300/include/asm/Kbuild1
-rw-r--r--arch/hexagon/include/asm/Kbuild1
-rw-r--r--arch/ia64/include/asm/local64.h1
-rw-r--r--arch/ia64/mm/init.c4
-rw-r--r--arch/m68k/include/asm/Kbuild1
-rw-r--r--arch/microblaze/include/asm/Kbuild1
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/nds32/include/asm/Kbuild1
-rw-r--r--arch/openrisc/include/asm/Kbuild1
-rw-r--r--arch/parisc/include/asm/Kbuild1
-rw-r--r--arch/powerpc/include/asm/Kbuild1
-rw-r--r--arch/riscv/include/asm/Kbuild1
-rw-r--r--arch/s390/Kconfig31
-rw-r--r--arch/s390/configs/debug_defconfig12
-rw-r--r--arch/s390/configs/defconfig11
-rw-r--r--arch/s390/configs/zfcpdump_defconfig2
-rw-r--r--arch/s390/include/asm/Kbuild1
-rw-r--r--arch/sh/include/asm/Kbuild1
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/x86/include/asm/local64.h1
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--block/blk-core.c13
-rw-r--r--block/blk-mq-debugfs.c2
-rw-r--r--block/blk-mq.c4
-rw-r--r--block/blk-pm.c15
-rw-r--r--block/blk-pm.h14
-rw-r--r--drivers/clk/qcom/clk-cpu-8996.c6
-rw-r--r--drivers/clk/qcom/dispcc-sm8250.c28
-rw-r--r--drivers/clk/qcom/gcc-sm8250.c6
-rw-r--r--drivers/cpufreq/intel_pstate.c1
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c55
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c41
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c38
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c73
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c1
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c7
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c27
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c16
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c3
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h3
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c10
-rw-r--r--drivers/ide/ide-atapi.c1
-rw-r--r--drivers/ide/ide-io.c7
-rw-r--r--drivers/ide/ide-pm.c2
-rw-r--r--drivers/idle/intel_idle.c41
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c89
-rw-r--r--drivers/iio/adc/qcom-vadc-common.c139
-rw-r--r--drivers/iio/adc/qcom-vadc-common.h15
-rw-r--r--drivers/leds/Kconfig9
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-qcom-lpg.c1244
-rw-r--r--drivers/md/dm-crypt.c7
-rw-r--r--drivers/mfd/Kconfig12
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/mfd-core.c7
-rw-r--r--drivers/mfd/qcom-qca639x.c162
-rw-r--r--drivers/mfd/wcd934x.c4
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_tx.c6
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.c5
-rw-r--r--drivers/net/wireless/ath/ath11k/wmi.h2
-rw-r--r--drivers/opp/core.c9
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c18
-rw-r--r--drivers/phy/qualcomm/Kconfig11
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp.c100
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c2
-rw-r--r--drivers/remoteproc/qcom_wcnss.c15
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/Kconfig1
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c2
-rw-r--r--drivers/scsi/scsi_lib.c27
-rw-r--r--drivers/scsi/scsi_transport_spi.c27
-rw-r--r--drivers/scsi/ufs/ufs-mediatek-trace.h2
-rw-r--r--drivers/scsi/ufs/ufs-mediatek.c21
-rw-r--r--drivers/scsi/ufs/ufs-mediatek.h1
-rw-r--r--drivers/scsi/ufs/ufs.h2
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c73
-rw-r--r--drivers/scsi/ufs/ufshcd.c45
-rw-r--r--drivers/scsi/ufs/ufshcd.h14
-rw-r--r--drivers/slimbus/qcom-ngd-ctrl.c3
-rw-r--r--drivers/soc/qcom/llcc-qcom.c40
-rw-r--r--drivers/soc/qcom/socinfo.c48
-rw-r--r--drivers/thermal/qcom/Kconfig11
-rw-r--r--drivers/thermal/qcom/Makefile1
-rw-r--r--drivers/thermal/qcom/qcom-spmi-adc-tm5.c567
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c126
-rw-r--r--drivers/usb/host/xhci-pci-renesas.c52
-rw-r--r--drivers/usb/typec/mux/Kconfig7
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/gpio_aux_switch.c91
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/ceph/mds_client.c53
-rw-r--r--fs/file.c2
-rw-r--r--fs/io_uring.c60
-rw-r--r--include/asm-generic/Kbuild1
-rw-r--r--include/linux/blk-mq.h4
-rw-r--r--include/linux/blkdev.h18
-rw-r--r--include/linux/build_bug.h5
-rw-r--r--include/linux/ceph/msgr.h4
-rw-r--r--include/linux/fixp-arith.h20
-rw-r--r--include/linux/kdev_t.h22
-rw-r--r--include/linux/mm.h12
-rw-r--r--include/linux/sizes.h3
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h4
-rw-r--r--kernel/cgroup/cgroup-v1.c2
-rw-r--r--kernel/cgroup/cgroup.c30
-rw-r--r--kernel/configs/debug.config13
-rw-r--r--kernel/configs/distro.config467
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/workqueue.c13
-rw-r--r--lib/genalloc.c25
-rw-r--r--lib/zlib_dfltcc/Makefile2
-rw-r--r--lib/zlib_dfltcc/dfltcc.c6
-rw-r--r--lib/zlib_dfltcc/dfltcc_deflate.c3
-rw-r--r--lib/zlib_dfltcc/dfltcc_inflate.c4
-rw-r--r--lib/zlib_dfltcc/dfltcc_syms.c17
-rw-r--r--mm/hugetlb.c22
-rw-r--r--mm/kasan/generic.c2
-rw-r--r--mm/memory.c8
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/page_alloc.c8
-rw-r--r--mm/slub.c5
-rw-r--r--net/ceph/messenger_v2.c15
-rwxr-xr-xscripts/checkpatch.pl6
-rwxr-xr-xscripts/depmod.sh2
-rw-r--r--sound/soc/codecs/wcd9335.c296
-rw-r--r--sound/soc/codecs/wcd934x.c10
-rw-r--r--sound/soc/qcom/apq8096.c48
-rw-r--r--tools/testing/selftests/vm/Makefile10
169 files changed, 7655 insertions, 563 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
new file mode 100644
index 000000000000..0474f1d998ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
@@ -0,0 +1,172 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Light Pulse Generator
+
+maintainers:
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: >
+ The Qualcomm Light Pulse Generator consists of three different hardware blocks;
+ a ramp generator with lookup table, the light pulse generator and a three
+ channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
+
+properties:
+ compatible:
+ enum:
+ - qcom,pm8150b-lpg
+ - qcom,pm8150l-lpg
+ - qcom,pm8916-pwm
+ - qcom,pm8941-lpg
+ - qcom,pm8994-lpg
+ - qcom,pmi8994-lpg
+ - qcom,pmi8998-lpg
+
+ "#pwm-cells":
+ const: 2
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ qcom,power-source:
+ $ref: /schemas/types.yaml#definitions/uint32
+ description: >
+ power-source used to drive the output, as defined in the datasheet.
+ Should be specified if the TRILED block is present
+ enum:
+ - 0
+ - 1
+ - 3
+
+ multi-led:
+ type: object
+ $ref: leds-class-multicolor.yaml#
+ properties:
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ "^led@[0-9a-f]$":
+ type: object
+ $ref: common.yaml#
+
+ properties:
+ "qcom,dtest":
+ $ref: /schemas/types.yaml#definitions/uint32-array
+ description: >
+ configures the output into an internal test line of the pmic. Specified
+ by a list of u32 pairs, one pair per channel, where each pair denotes the
+ test line to drive and the second configures how the value should be
+ outputed, as defined in the datasheet
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - reg
+
+patternProperties:
+ "^led@[0-9a-f]$":
+ type: object
+ $ref: common.yaml#
+ properties:
+ "qcom,dtest":
+ $ref: /schemas/types.yaml#definitions/uint32-array
+ description: >
+ configures the output into an internal test line of the pmic. Specified
+ by a list of u32 pairs, one pair per channel, where each pair denotes the
+ test line to drive and the second configures how the value should be
+ outputed, as defined in the datasheet
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - reg
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/leds/common.h>
+
+ lpg {
+ compatible = "qcom,pmi8994-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,power-source = <1>;
+
+ led@1 {
+ reg = <1>;
+ label = "green:user1";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "green:user0";
+ default-state = "on";
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "green:user2";
+ };
+
+ led@4 {
+ reg = <4>;
+ label = "green:user3";
+
+ qcom,dtest = <4 1>;
+ };
+ };
+ - |
+ #include <dt-bindings/leds/common.h>
+
+ lpg {
+ compatible = "qcom,pmi8994-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,power-source = <1>;
+
+ multi-led {
+ color = <LED_COLOR_ID_MULTI>;
+ label = "rgb:notification";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ color = <LED_COLOR_ID_RED>;
+ };
+
+ led@2 {
+ reg = <2>;
+ color = <LED_COLOR_ID_GREEN>;
+ };
+
+ led@3 {
+ reg = <3>;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+ };
+ - |
+ lpg {
+ compatible = "qcom,pm8916-pwm";
+ #pwm-cells = <2>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml b/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml
new file mode 100644
index 000000000000..d43c75da136f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/qcom,qca639x.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/mfd/qcom,qca639x.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm QCA639x WiFi + Bluetoot SoC bindings
+
+maintainers:
+ - Andy Gross <agross@kernel.org>
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: |
+ This binding describes thes Qualcomm QCA6390 or QCA6391 power supplies and
+ enablement pins.
+
+properties:
+ compatible:
+ const: qcom,qca639x
+
+ '#power-domain-cells':
+ const: 0
+
+ pinctrl-0: true
+ pinctrl-1: true
+
+ pinctrl-names:
+ items:
+ - const: default
+ - const: active
+
+ vddaon-supply:
+ description:
+ 0.95V always-on LDO power input
+
+ vddpmu-supply:
+ description:
+ 0.95V LDO power input to PMU
+
+ vddrfa1-supply:
+ description:
+ 0.95V LDO power input to RFA
+
+ vddrfa2-supply:
+ description:
+ 1.25V LDO power input to RFA
+
+ vddrfa3-supply:
+ description:
+ 2V LDO power input to RFA
+
+ vddpcie1-supply:
+ description:
+ 1.25V LDO power input to PCIe part
+
+ vddpcie2-supply:
+ description:
+ 2V LDO power input to PCIe part
+
+ vddio-supply:
+ description:
+ 1.8V VIO input
+
+additionalProperties: false
+
+examples:
+ - |
+ qca639x: qca639x {
+ compatible = "qcom,qca639x";
+ #power-domain-cells = <0>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s2f_0p95>;
+ vddrfa1-supply = <&vreg_s2f_0p95>;
+ vddrfa2-supply = <&vreg_s8c_1p3>;
+ vddrfa3-supply = <&vreg_s5a_1p9>;
+ vddpcie1-supply = <&vreg_s8c_1p3>;
+ vddpcie2-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+ pinctrl-names = "default", "active";
+ pinctrl-0 = <&wlan_default_state &bt_default_state>;
+ pinctrl-1 = <&wlan_active_state &bt_active_state>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
index 3b55310390a0..c87806f76a43 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
@@ -142,6 +142,7 @@
- "bus_slave" Slave AXI clock
- "slave_q2a" Slave Q2A clock
- "tbu" PCIe TBU clock
+ - "ddrss_sf_tbu" PCIe SF TBU clock, required on sm8250
- "pipe" PIPE clock
- resets:
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
index cc0b7fc1c29b..64e0a79e7934 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
@@ -34,6 +34,12 @@ on the Qualcomm WCNSS core.
Definition: should be "wdog", "fatal", optionally followed by "ready",
"handover", "stop-ack"
+- firmware-name:
+ Usage: optional
+ Value type: <string>
+ Definition: must list the relative firmware image path for the
+ WCNSS core.
+
- vddmx-supply: (deprecated for qcom,pronto-v1/2-pil)
- vddcx-supply: (deprecated for qcom,pronto-v1/2-pil)
- vddpx-supply:
diff --git a/Documentation/devicetree/bindings/slimbus/slim-ngd-qcom-ctrl.txt b/Documentation/devicetree/bindings/slimbus/slim-ngd-qcom-ctrl.txt
index e94a2ad3a710..1c615b622d07 100644
--- a/Documentation/devicetree/bindings/slimbus/slim-ngd-qcom-ctrl.txt
+++ b/Documentation/devicetree/bindings/slimbus/slim-ngd-qcom-ctrl.txt
@@ -14,6 +14,7 @@ Please refer to slimbus/bus.txt for details of the common SLIMBus bindings.
must be one of the following.
"qcom,slim-ngd-v1.5.0" for MSM8996
"qcom,slim-ngd-v2.1.0" for SDM845
+ "qcom,slim-ngd-v2.2.0" for SM8250
- reg:
Usage: required
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt
deleted file mode 100644
index 9326cdf6e1b1..000000000000
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Qualcomm Shared Memory Manager binding
-
-This binding describes the Qualcomm Shared Memory Manager, used to share data
-between various subsystems and OSes in Qualcomm platforms.
-
-- compatible:
- Usage: required
- Value type: <stringlist>
- Definition: must be:
- "qcom,smem"
-
-- memory-region:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: handle to memory reservation for main SMEM memory region.
-
-- qcom,rpm-msg-ram:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: handle to RPM message memory resource
-
-- hwlocks:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: reference to a hwspinlock used to protect allocations from
- the shared memory
-
-= EXAMPLE
-The following example shows the SMEM setup for MSM8974, with a main SMEM region
-at 0xfa00000 and the RPM message ram at 0xfc428000:
-
- reserved-memory {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- smem_region: smem@fa00000 {
- reg = <0xfa00000 0x200000>;
- no-map;
- };
- };
-
- smem@fa00000 {
- compatible = "qcom,smem";
-
- memory-region = <&smem_region>;
- qcom,rpm-msg-ram = <&rpm_msg_ram>;
-
- hwlocks = <&tcsr_mutex 3>;
- };
-
- soc {
- rpm_msg_ram: memory@fc428000 {
- compatible = "qcom,rpm-msg-ram";
- reg = <0xfc428000 0x4000>;
- };
- };
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml
new file mode 100644
index 000000000000..867640c09932
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smem.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/soc/qcom/qcom,smem.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm Shared Memory Manager binding
+
+maintainers:
+ - Andy Gross <agross@kernel.org>
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: |
+ This binding describes the Qualcomm Shared Memory Manager, used to share data
+ between various subsystems and OSes in Qualcomm platforms.
+
+properties:
+ compatible:
+ const: "qcom-smem"
+
+ memory-region:
+ maxItems: 1
+ description: handle to memory reservation for main SMEM memory region.
+
+ hwlocks:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: reference to a hwspinlock used to protect allocations from the shared memory
+
+ qcom,rpm-msg-ram:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: handle to RPM message memory resource
+
+required:
+ - compatible
+ - memory-region
+ - hwlocks
+
+additionalProperties: false
+
+examples:
+ - |
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ smem_region: smem@fa00000 {
+ reg = <0xfa00000 0x200000>;
+ no-map;
+ };
+ };
+
+ smem {
+ compatible = "qcom,smem";
+
+ memory-region = <&smem_region>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ rpm_msg_ram: memory@fc428000 {
+ compatible = "qcom,rpm-msg-ram";
+ reg = <0xfc428000 0x4000>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
index 5d6ea66a863f..4d56c3ca9fa8 100644
--- a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
+++ b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
@@ -55,6 +55,26 @@ Required properties with SLIMbus Interface:
Value type: <string>
Definition: Must contain "mclk", "mclk2" and "slimbus" strings.
+- qcom,mbhc-vthreshold:
+ Usage: Optional, only required if headset button support required.
+ Value type: <u32 array>
+ Definition: Must contain an array of 8 threshold voltages in mV for
+ 8 buttons detection on headset.
+
+- qcom,hphl-jack-type-normally-open:
+ Usage: Optional, only required if headset button support required.
+ Value type: <boolean>
+ Definition: present if hphl pin on jack is a NO (Normally Open).
+ If not specified, then its assumed that hphl pin on jack
+ is NC (Normally Closed).
+
+- qcom,gnd-jack-type-normally-open:
+ Usage: Optional, only required if headset button support required.
+ Value type: <boolean>
+ Definition: present if gnd pin on jack is NO (Normally Open).
+ If not specified, then its assumed that gnd pin on
+ jack is NC (Normally Closed).
+
- vdd-buck-supply:
Usage: required
Value type: <phandle>
diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml b/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
new file mode 100644
index 000000000000..0c8311d99da5
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
@@ -0,0 +1,145 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/qcom-spmi-adc-tm5.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm's SPMI PMIC ADC-TM
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+properties:
+ compatible:
+ const: qcom,spmi-adc-tm5
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ "#thermal-sensor-cells":
+ const: 1
+ description:
+ Number of cells required to uniquely identify the thermal sensors. Since
+ we have multiple sensors this is set to 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ io-channels:
+ description:
+ From common IIO binding. Used to pipe PMIC ADC channel to thermal monitor
+
+ io-channel-names:
+ description:
+ From common IIO binding. Names each of IIO channels. The name should
+ be equal to the sensor's subnode name.
+
+ qcom,avg-samples:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Number of samples to be used for measurement.
+ enum:
+ - 1
+ - 2
+ - 4
+ - 8
+ - 16
+ default: 1
+
+ qcom,decimation:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: This parameter is used to decrease ADC sampling rate.
+ enum:
+ - 250
+ - 420
+ - 840
+ default: 840
+
+patternProperties:
+ "^([-a-z0-9]*)@[0-9]+$":
+ type: object
+ description:
+ Represent one thermal sensor.
+
+ properties:
+ reg:
+ description: Specify the sensor channel.
+ maxItems: 1
+
+ qcom,adc-channel:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Corresponding ADC channel ID.
+
+ qcom,ratiometric:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Channel calibration type.
+ If this property is specified VADC will use the VDD reference
+ (1.875V) and GND for channel calibration. If property is not found,
+ channel will be calibrated with 0V and 1.25V reference channels,
+ also known as absolute calibration.
+
+ qcom,hw-settle-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Time between AMUX getting configured and the ADC starting conversion.
+
+ qcom,pre-scaling:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: Used for scaling the channel input signal before the signal is fed to VADC. See qcom,spi-vadc specification for the list of possible values.
+ minItems: 2
+ maxItems: 2
+
+ required:
+ - reg
+ - qcom,adc-channel
+
+ additionalProperties:
+ false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - "#address-cells"
+ - "#size-cells"
+ - "#thermal-sensor-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/iio/qcom,spmi-vadc.h>
+
+ pm8150b_adc: adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ /* Other propreties are omitted */
+ conn-therm@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+ };
+
+ pm8150b_adc_tm: adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x2 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ io-channels = <&pm8150b_adc ADC5_AMUX_THM3_100K_PU>;
+ io-channel-names = "conn-therm";
+
+ conn-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
new file mode 100644
index 000000000000..d5173f88d429
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm PMIC based USB type C Detection Driver
+
+maintainers:
+ - Wesley Cheng <wcheng@codeaurora.org>
+
+description: |
+ Qualcomm PMIC Type C Detect
+
+properties:
+ compatible:
+ enum:
+ - qcom,pm8150b-usb-typec
+
+ reg:
+ maxItems: 1
+ description: Type C base address
+
+ interrupts:
+ maxItems: 1
+ description: CC change interrupt from PMIC
+
+ connector:
+ description: Connector type for remote endpoints
+ type: object
+
+ properties:
+ compatible:
+ $ref: /connector/usb-connector.yaml#/properties/compatible
+ enum:
+ - usb-c-connector
+
+ power-role: true
+ data-role: true
+
+ ports:
+ description: Remote endpoint connections
+ type: object
+ $ref: /connector/usb-connector.yaml#/properties/ports
+
+ properties:
+ port@0:
+ description: Remote endpoints for the High Speed path
+ type: object
+
+ port@1:
+ description: Remote endpoints for the Super Speed path
+ type: object
+
+ properties:
+ endpoint@0:
+ description: Connection to USB type C mux node
+ type: object
+
+ endpoint@1:
+ description: Connection to role switch node
+ type: object
+
+ required:
+ - compatible
+
+required:
+ - compatible
+ - interrupts
+ - connector
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ pm8150b {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pm8150b_typec: typec@1500 {
+ compatible = "qcom,pm8150b-usb-typec";
+ reg = <0x1500>;
+ interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+
+ connector {
+ compatible = "usb-c-connector";
+ power-role = "dual";
+ data-role = "dual";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ usb3_data_ss: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&qmp_ss_mux>;
+ };
+ usb3_role: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dwc3_drd_switch>;
+ };
+ };
+ };
+ };
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 546aa66428c9..6eff4f720c72 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4588,7 +4588,7 @@ B: https://bugzilla.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
F: Documentation/admin-guide/pm/cpuidle.rst
F: Documentation/driver-api/pm/cpuidle.rst
-F: drivers/cpuidle/*
+F: drivers/cpuidle/
F: include/linux/cpuidle.h
CPU POWER MONITORING SUBSYSTEM
diff --git a/Makefile b/Makefile
index 3d328b7ab200..8b2c3f88ee5e 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 5
PATCHLEVEL = 11
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
NAME = Kleptomaniac Octopus
# *DOCUMENTATION*
diff --git a/arch/alpha/include/asm/local64.h b/arch/alpha/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/alpha/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 81f4edec0c2a..3c1afa524b9c 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += user.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 4a0848aef207..03657ff8fbe3 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -2,7 +2,6 @@
generic-y += early_ioremap.h
generic-y += extable.h
generic-y += flat.h
-generic-y += local64.h
generic-y += parport.h
generated-y += mach-types.h
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 5113fac80b7a..75acbd7efb20 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -49,3 +49,4 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8250-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8250-rb5-dvt.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
index 3a9538e1ec97..43677c529388 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
@@ -301,6 +301,11 @@
status = "okay";
};
+&mpss {
+ status = "okay";
+ firmware-name = "qcom/msm8916/mba.mbn", "qcom/msm8916/modem.mdt";
+};
+
&pm8916_resin {
status = "okay";
linux,code = <KEY_VOLUMEDOWN>;
@@ -308,6 +313,7 @@
&pronto {
status = "okay";
+ firmware-name = "qcom/msm8916/wcnss.mdt";
};
&sdhc_1 {
diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index defcbd15edf9..7e51677d256e 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -8,6 +8,7 @@
#include "pmi8994.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
@@ -682,6 +683,54 @@
};
};
+&pmi8994_mpps {
+ pmi8994_mpp2_userled4: mpp2-userled4 {
+ pins = "mpp2";
+ function = "sink";
+
+ output-low;
+ qcom,dtest = <4>;
+ };
+};
+
+&pmi8994_lpg {
+ qcom,power-source = <1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmi8994_mpp2_userled4>;
+
+ status = "okay";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ label = "green:user1";
+
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "green:user0";
+ default-state = "on";
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "green:user2";
+ };
+
+ led@4 {
+ reg = <4>;
+ label = "green:user3";
+
+ qcom,dtest = <4 1>;
+ };
+};
+
&pmi8994_spmi_regulators {
vdd_gfx: s2@1700 {
reg = <0x1700 0x100>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 7eef07e73e25..bc19fc80cdec 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -154,11 +154,6 @@
no-map;
};
- slpi_region: slpi@90b00000 {
- reg = <0x0 0x90b00000 0x0 0xa00000>;
- no-map;
- };
-
venus_region: venus@90400000 {
reg = <0x0 0x90400000 0x0 0x700000>;
no-map;
@@ -2121,6 +2116,55 @@
};
};
+ fastrpc {
+ compatible = "qcom,fastrpc";
+ qcom,smd-channels = "fastrpcsmd-apps-dsp";
+ /* DOMAIN_ADSP */
+ label = "adsp";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cb@8 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <8>;
+ iommus = <&lpass_q6_smmu 8>;
+ };
+ cb@9 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <9>;
+ iommus = <&lpass_q6_smmu 9>;
+ };
+ cb@10 {
+ compatible = "qcom,fastrpc-compute-cb";
+ reg = <10>;
+ iommus = <&lpass_q6_smmu 10>;
+ };
+ cb@11 {
+ reg = <11>;
+ compatible = "qcom,fastrpc-compute-cb";
+ iommus = <&lpass_q6_smmu 11>;
+ };
+ cb@12 {
+ reg = <12>;
+ compatible = "qcom,fastrpc-compute-cb";
+ iommus = <&lpass_q6_smmu 12>;
+ };
+ cb@5 {
+ reg = <5>;
+ compatible = "qcom,fastrpc-compute-cb";
+ iommus = <&lpass_q6_smmu 5>;
+ };
+ cb@6 {
+ reg = <6>;
+ compatible = "qcom,fastrpc-compute-cb";
+ iommus = <&lpass_q6_smmu 6>;
+ };
+ cb@7 {
+ reg = <7>;
+ compatible = "qcom,fastrpc-compute-cb";
+ iommus = <&lpass_q6_smmu 7>;
+ };
+ };
};
};
@@ -2455,3 +2499,5 @@
};
};
#include "msm8996-pins.dtsi"
+#include "pm8994.dtsi"
+#include "pmi8994.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/pm8150.dtsi b/arch/arm64/boot/dts/qcom/pm8150.dtsi
index a53eccf2b695..15e87153a194 100644
--- a/arch/arm64/boot/dts/qcom/pm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150.dtsi
@@ -97,6 +97,16 @@
};
};
+ pm8150_adc_tm: adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x0 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
pm8150_rtc: rtc@6000 {
compatible = "qcom,pm8941-rtc";
reg = <0x6000>;
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index e112e8876db6..30e7a5f19e5f 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,19 @@
status = "disabled";
};
+ pm8150b_vbus: dcdc@1100 {
+ compatible = "qcom,pm8150b-vbus-reg";
+ status = "disabled";
+ reg = <0x1100>;
+ };
+
+ pm8150b_typec: typec@1500 {
+ compatible = "qcom,pm8150b-usb-typec";
+ status = "disabled";
+ reg = <0x1500>;
+ interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+ };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
@@ -95,6 +108,16 @@
};
};
+ pm8150b_adc_tm: adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x2 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
pm8150b_gpios: gpio@c000 {
compatible = "qcom,pm8150b-gpio";
reg = <0xc000>;
@@ -110,5 +133,14 @@
reg = <0x3 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
+
+ pm8150b_lpg: lpg {
+ compatible = "qcom,pm8150b-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8150l.dtsi b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
index 62139538b7d9..e8926d6c32cb 100644
--- a/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -89,6 +89,16 @@
};
};
+ pm8150l_adc_tm: adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x4 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #thermal-sensor-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
pm8150l_gpios: gpio@c000 {
compatible = "qcom,pm8150l-gpio";
reg = <0xc000>;
@@ -104,5 +114,15 @@
reg = <0x5 SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
+
+ pm8150l_lpg: lpg {
+ compatible = "qcom,pm8150l-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
+
};
};
diff --git a/arch/arm64/boot/dts/qcom/pm8994.dtsi b/arch/arm64/boot/dts/qcom/pm8994.dtsi
index 5ffdf37d8e31..cd04baf293b3 100644
--- a/arch/arm64/boot/dts/qcom/pm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8994.dtsi
@@ -134,6 +134,15 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm8994_lpg: lpg {
+ compatible = "qcom,pm8994-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
+
pm8994_spmi_regulators: regulators {
compatible = "qcom,pm8994-regulators";
};
diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi
index e5ed28ab9b2d..ca709b8b5f04 100644
--- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi
@@ -19,6 +19,17 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ pmi8994_mpps: mpps@a000 {
+ compatible = "qcom,pm8994-mpp";
+ reg = <0xa000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
+ <0 0xa1 0 IRQ_TYPE_NONE>,
+ <0 0xa2 0 IRQ_TYPE_NONE>,
+ <0 0xa3 0 IRQ_TYPE_NONE>;
+ };
};
pmic@3 {
@@ -27,10 +38,27 @@
#address-cells = <1>;
#size-cells = <0>;
+ pmi8994_lpg: lpg@b100 {
+ compatible = "qcom,pmi8994-lpg";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+ };
+
pmi8994_spmi_regulators: regulators {
compatible = "qcom,pmi8994-regulators";
#address-cells = <1>;
#size-cells = <1>;
+
+ vreg_pmi8994_s2: s2@1700 {
+ reg = <0x1700 0x100>;
+ status = "ok";
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1015000>;
+ regulator-always-on;
+ };
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index ce22d4fa383e..70ba1f6806fd 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -7,6 +7,8 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
#include "sm8250.dtsi"
#include "pm8150.dtsi"
#include "pm8150b.dtsi"
@@ -17,6 +19,7 @@
compatible = "qcom,qrb5165-rb5", "qcom,sm8250";
aliases {
+ hsuart0 = &uart6;
serial0 = &uart12;
sdhc2 = &sdhc_2;
};
@@ -40,6 +43,17 @@
regulator-always-on;
};
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&lt9611_out>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -66,6 +80,108 @@
};
+ lt9611_1v2: lt9611-vdd12-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "LT9611_1V2";
+
+ vin-supply = <&vdc_3v3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+
+ /* not connected on the board
+ gpio = <&pm8150l_gpios 7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ */
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lt9611_3v3: lt9611-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "LT9611_3V3";
+
+ vin-supply = <&vdc_3v3>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+
+ // TODO: make it possible to drive same GPIO from two clients
+ // gpio = <&pm8150l_gpios 7 GPIO_ACTIVE_HIGH>;
+ // enable-active-high;
+ };
+
+ thermal-zones {
+ xo-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150_adc_tm 0>;
+ trips {
+ active-config0 {
+ temperature = <50000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ };
+ };
+
+ wifi-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150_adc_tm 1>;
+ trips {
+ active-config0 {
+ temperature = <52000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ };
+ };
+
+ conn-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150b_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ skin-msm-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150l_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <50000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pm8150l-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150l_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <50000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ };
+ };
+
+ };
+
vbat: vbat-regulator {
compatible = "regulator-fixed";
regulator-name = "VBAT";
@@ -87,7 +203,7 @@
vdc_3v3: vdc-3v3-regulator {
compatible = "regulator-fixed";
regulator-name = "VDC_3V3";
- vin-supply = <&dc12v>;
+ vin-supply = <&vreg_l11c_3p3>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
@@ -118,6 +234,30 @@
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
+
+ clk40M: can_clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <40000000>;
+ };
+
+ qca639x: qca639x {
+ compatible = "qcom,qca639x";
+ #power-domain-cells = <0>;
+
+ vddaon-supply = <&vreg_s6a_0p95>;
+ vddpmu-supply = <&vreg_s2f_0p95>;
+ vddrfa1-supply = <&vreg_s2f_0p95>;
+ vddrfa2-supply = <&vreg_s8c_1p3>;
+ vddrfa3-supply = <&vreg_s5a_1p9>;
+ vddpcie1-supply = <&vreg_s8c_1p3>;
+ vddpcie2-supply = <&vreg_s5a_1p9>;
+ vddio-supply = <&vreg_s4a_1p8>;
+ pinctrl-names = "default", "active";
+ pinctrl-0 = <&wlan_default_state &bt_default_state>;
+ pinctrl-1 = <&wlan_active_state &bt_active_state>;
+ };
+
};
&apps_rsc {
@@ -131,6 +271,13 @@
vdd-l5-l6-supply = <&vreg_bob>;
vdd-l7-supply = <&vreg_s4a_1p8>;
+ vreg_s2f_0p95: smps2 {
+ regulator-name = "vreg_s2f_0p95";
+ regulator-min-microvolt = <512000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+
vreg_l1f_1p1: ldo1 {
regulator-name = "vreg_l1f_1p1";
regulator-min-microvolt = <1104000>;
@@ -406,6 +553,187 @@
};
};
+&adsp {
+ status = "okay";
+ firmware-name = "qcom/sm8250/adsp.mbn";
+};
+
+&q6afedai {
+ qi2s@16 {
+ reg = <16>;
+ qcom,sd-lines = <0 1 2 3>;
+ };
+};
+
+/* TERT I2S Uses 1 I2S SD Lines for audio on LT9611 HDMI Bridge */
+&q6afedai {
+ qi2s@20 {
+ reg = <20>;
+ qcom,sd-lines = <0>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ };
+};
+
+&swr0 {
+
+ left_spkr: wsa8810-left{
+ compatible = "sdw10217211000";
+ reg = <0 3>;
+ powerdown-gpios = <&tlmm 130 GPIO_ACTIVE_HIGH>;
+ #thermal-sensor-cells = <0>;
+ sound-name-prefix = "SpkrLeft";
+ #sound-dai-cells = <0>;
+ };
+
+
+ right_spkr: wsa8810-right{
+ compatible = "sdw10217211000";
+ reg = <0 4>;
+ powerdown-gpios = <&tlmm 130 GPIO_ACTIVE_HIGH>;
+ #thermal-sensor-cells = <0>;
+ sound-name-prefix = "SpkrRight";
+ #sound-dai-cells = <0>;
+ };
+};
+
+&vamacro {
+ pinctrl-0 = <&cdc_dmic01_clk_active &cdc_dmic01_data_active>;
+ pinctrl-names = "default";
+ vdd-micb-supply = <&vreg_s4a_1p8>;
+};
+
+&sound {
+ compatible = "qcom,qrb5165-rb5-sndcard";
+ pinctrl-0 = <&tert_mi2s_sck_active
+ &tert_mi2s_sd0_active
+ &tert_mi2s_ws_active>;
+ pinctrl-names = "default";
+ model = "Qualcomm-RB5-WSA8815-Speakers-DMIC0";
+ audio-routing =
+ "SpkrLeft IN", "WSA_SPK1 OUT",
+ "SpkrRight IN", "WSA_SPK2 OUT",
+ "VA DMIC0", "vdd-micb",
+ "VA DMIC1", "vdd-micb",
+ "MM_DL1", "MultiMedia1 Playback",
+ "MM_DL2", "MultiMedia2 Playback",
+ "MultiMedia3 Capture", "MM_UL3";
+
+ mm1-dai-link {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ mm2-dai-link {
+ link-name = "MultiMedia2";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ mm3-dai-link {
+ link-name = "MultiMedia3";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ hdmi-dai-link {
+ link-name = "HDMI Playback";
+ cpu {
+ sound-dai = <&q6afedai TERTIARY_MI2S_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&lt9611_codec 0>;
+ };
+ };
+
+ dma-dai-link {
+ link-name = "WSA Playback";
+ cpu {
+ sound-dai = <&q6afedai WSA_CODEC_DMA_RX_0>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&left_spkr>, <&right_spkr>, <&swr0 0>, <&wsamacro>;
+ };
+ };
+
+ va-dai-link {
+ link-name = "VA Capture";
+ cpu {
+ sound-dai = <&q6afedai VA_CODEC_DMA_TX_0>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&vamacro 0>;
+ };
+ };
+};
+
+&cdsp {
+ status = "okay";
+ firmware-name = "qcom/sm8250/cdsp.mbn";
+};
+
+&dsi0 {
+ status = "okay";
+ vdda-supply = <&vreg_l9a_1p2>;
+
+#if 0
+ qcom,dual-dsi-mode;
+ qcom,master-dsi;
+#endif
+
+ ports {
+ port@1 {
+ endpoint {
+ remote-endpoint = <&lt9611_a>;
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+};
+
+&dsi0_phy {
+ status = "okay";
+ vdds-supply = <&vreg_l5a_0p88>;
+};
+
+&gpu {
+ zap-shader {
+ memory-region = <&gpu_mem>;
+ firmware-name = "qcom/sm8250/a650_zap.mbn";
+ };
+};
+
/* LS-I2C0 */
&i2c4 {
status = "okay";
@@ -413,6 +741,55 @@
&i2c5 {
status = "okay";
+ clock-frequency = <400000>;
+
+ lt9611_codec: hdmi-bridge@2b {
+ compatible = "lontium,lt9611uxc";
+ reg = <0x2b>;
+ #sound-dai-cells = <1>;
+
+ interrupts-extended = <&tlmm 63 IRQ_TYPE_EDGE_FALLING>;
+
+ reset-gpios = <&pm8150l_gpios 5 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&lt9611_1v2>;
+ vcc-supply = <&lt9611_3v3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&lt9611_irq_pin &lt9611_rst_pin>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ lt9611_a: endpoint {
+ remote-endpoint = <&dsi0_out>;
+ };
+ };
+
+#if 0
+ port@1 {
+ reg = <1>;
+
+ lt9611_b: endpoint {
+ remote-endpoint = <&dsi1_out>;
+ };
+ };
+#endif
+
+ port@2 {
+ reg = <2>;
+
+ lt9611_out: endpoint {
+ remote-endpoint = <&hdmi_con>;
+ };
+ };
+
+ };
+ };
};
/* LS-I2C1 */
@@ -420,6 +797,150 @@
status = "okay";
};
+&mdss {
+ status = "okay";
+};
+
+&mdss_mdp {
+ status = "okay";
+};
+
+&pcie0 {
+ status = "okay";
+ perst-gpio = <&tlmm 79 GPIO_ACTIVE_LOW>;
+ wake-gpio = <&tlmm 81 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_default_state>;
+};
+
+&pcie0_phy {
+ status = "okay";
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+
+ /* Power on QCA639x chip, otherwise PCIe bus timeouts */
+ power-domains = <&qca639x>;
+};
+
+&pcie1 {
+ status = "okay";
+ perst-gpio = <&tlmm 82 GPIO_ACTIVE_LOW>;
+ wake-gpio = <&tlmm 84 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_default_state>;
+};
+
+&pcie1_phy {
+ status = "okay";
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+};
+
+&pcie2 {
+ status = "okay";
+ perst-gpio = <&tlmm 85 GPIO_ACTIVE_LOW>;
+ wake-gpio = <&tlmm 87 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_default_state>;
+};
+
+&pcie2_phy {
+ status = "okay";
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+};
+
+&pm8150_adc {
+ xo-therm@4c {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ wifi-therm@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150b_adc {
+ conn-therm@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150l_adc {
+ skin-msm-therm@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pm8150l-therm@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150_adc ADC5_XO_THERM_100K_PU>,
+ <&pm8150_adc ADC5_AMUX_THM2_100K_PU>;
+ io-channel-names = "xo-therm", "wifi-therm";
+
+ xo-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ wifi-therm@1 {
+ reg = <1>;
+ qcom,adc-channel = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150b_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150b_adc ADC5_AMUX_THM3_100K_PU>;
+ io-channel-names = "conn-therm";
+
+ conn-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150l_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150l_adc ADC5_AMUX_THM2_100K_PU>,
+ <&pm8150l_adc ADC5_AMUX_THM3_100K_PU>;
+ io-channel-names = "skin-msm-therm", "pm8150l-therm";
+
+ skin-msm-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pm8150l-therm@1 {
+ reg = <1>;
+ qcom,adc-channel = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
&pm8150_gpios {
gpio-reserved-ranges = <1 1>, <3 2>, <7 1>;
gpio-line-names =
@@ -451,6 +972,35 @@
"NC";
};
+&pm8150b_typec {
+ status = "okay";
+ connector {
+ compatible = "usb-c-connector";
+ power-role = "dual";
+ data-role = "dual";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@1 {
+ reg = <1>;
+ usb3_data_ss: endpoint@0 {
+ remote-endpoint = <&qmp_ss_mux>;
+ };
+ };
+ };
+ };
+
+ port {
+ usb3_role: endpoint {
+ remote-endpoint = <&dwc3_drd_switch>;
+ };
+ };
+};
+
+&pm8150b_vbus {
+ status = "okay";
+};
+
&pm8150l_gpios {
gpio-line-names =
"NC",
@@ -465,12 +1015,64 @@
"PM_GPIO-B",
"NC",
"PM3003A_MODE";
+
+ lt9611_rst_pin: lt9611-rst-pin {
+ pins = "gpio5";
+ function = "normal";
+
+ output-high;
+ input-disable;
+ power-source = <0>;
+ };
+};
+
+&pm8150l_lpg {
+ status = "okay";
+
+ led@1 {
+ reg = <1>;
+ label = "green:user0";
+
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "green:user1";
+ default-state = "on";
+ };
+
+ led@3 {
+ reg = <3>;
+ label = "green:user2";
+ };
};
&pm8150_rtc {
status = "okay";
};
+&qup_uart6_default {
+ ctsrx {
+ pins = "gpio16", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rts {
+ pins = "gpio17";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tx {
+ pins = "gpio18";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
&qupv3_id_0 {
status = "okay";
};
@@ -491,12 +1093,15 @@
vqmmc-supply = <&vreg_l6c_2p96>;
cd-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>;
bus-width = <4>;
- /* there seem to be issues with HS400-1.8V mode, so disable it */
- no-1-8-v;
no-sdio;
no-emmc;
};
+&slpi {
+ /* status = "okay"; */
+ firmware-name = "qcom/sm8250/slpi.mbn";
+};
+
/* CAN */
&spi0 {
status = "okay";
@@ -696,6 +1301,109 @@
"HST_WLAN_UART_TX",
"HST_WLAN_UART_RX";
+ bt_default_state: bt-default-state {
+ bt-en {
+ pins = "gpio21";
+ function = "gpio";
+
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
+ };
+
+ bt_active_state: bt-active-state {
+ bt-en {
+ pins = "gpio21";
+ function = "gpio";
+
+ drive-strength = <16>;
+ output-high;
+ bias-pull-up;
+ };
+ };
+
+ lt9611_irq_pin: lt9611-irq {
+ pins = "gpio63";
+ function = "gpio";
+ bias-disable;
+ };
+
+ pcie0_default_state: pcie0-default {
+ clkreq {
+ pins = "gpio80";
+ function = "pci_e0";
+ bias-pull-up;
+ };
+
+ reset-n {
+ pins = "gpio79";
+ function = "gpio";
+
+ drive-strength = <2>;
+ output-low;
+ bias-pull-down;
+ };
+
+ wake-n {
+ pins = "gpio81";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie1_default_state: pcie1-default {
+ clkreq {
+ pins = "gpio83";
+ function = "pci_e1";
+ bias-pull-up;
+ };
+
+ reset-n {
+ pins = "gpio82";
+ function = "gpio";
+
+ drive-strength = <2>;
+ output-low;
+ bias-pull-down;
+ };
+
+ wake-n {
+ pins = "gpio84";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie2_default_state: pcie2-default {
+ clkreq {
+ pins = "gpio86";
+ function = "pci_e2";
+ bias-pull-up;
+ };
+
+ reset-n {
+ pins = "gpio85";
+ function = "gpio";
+
+ drive-strength = <2>;
+ output-low;
+ bias-pull-down;
+ };
+
+ wake-n {
+ pins = "gpio87";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
sdc2_default_state: sdc2-default {
clk {
pins = "sdc2_clk";
@@ -706,13 +1414,13 @@
cmd {
pins = "sdc2_cmd";
bias-pull-up;
- drive-strength = <16>;
+ drive-strength = <10>;
};
data {
pins = "sdc2_data";
bias-pull-up;
- drive-strength = <16>;
+ drive-strength = <10>;
};
};
@@ -721,6 +1429,37 @@
function = "gpio";
bias-pull-up;
};
+
+ wlan_default_state: wlan-default-state {
+ wlan-en {
+ pins = "gpio20";
+ function = "gpio";
+
+ drive-strength = <16>;
+ output-low;
+ bias-pull-up;
+ };
+ };
+
+ wlan_active_state: wlan-active-state {
+ wlan-en {
+ pins = "gpio20";
+ function = "gpio";
+
+ drive-strength = <16>;
+ output-high;
+ bias-pull-up;
+ };
+ };
+
+};
+
+&uart6 {
+ status = "okay";
+ bluetooth {
+ compatible = "qcom,qca6390-bt";
+ power-domains = <&qca639x>;
+ };
};
&uart12 {
@@ -749,10 +1488,17 @@
&usb_1 {
status = "okay";
+ usb-role-switch;
+ port {
+ dwc3_drd_switch: endpoint@0 {
+ remote-endpoint = <&usb3_role>;
+ };
+ };
};
&usb_1_dwc3 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ usb-role-switch;
};
&usb_1_hsphy {
@@ -768,6 +1514,12 @@
vdda-phy-supply = <&vreg_l9a_1p2>;
vdda-pll-supply = <&vreg_l18a_0p92>;
+ orientation-switch;
+ port {
+ qmp_ss_mux: endpoint@0 {
+ remote-endpoint = <&usb3_data_ss>;
+ };
+ };
};
&usb_2 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index 0653468f26ce..0cba7ad1d0eb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -491,6 +491,13 @@
status = "okay";
};
+&msm_dp {
+ status = "okay";
+ data-lanes = <0 1>;
+ vdda-1p2-supply = <&vreg_l26a_1p2>;
+ vdda-0p9-supply = <&vreg_l1a_0p875>;
+};
+
&mss_pil {
status = "okay";
firmware-name = "qcom/sdm845/mba.mbn", "qcom/sdm845/modem.mbn";
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index b0aeafdcdba2..603d4cd85431 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -3727,10 +3727,10 @@
};
usb_1_qmpphy: phy@88e9000 {
- compatible = "qcom,sdm845-qmp-usb3-phy";
+ compatible = "qcom,sdm845-qmp-usb3-dp-phy";
reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x10>;
- reg-names = "reg-base", "dp_com";
+ <0 0x088e8000 0 0x38>,
+ <0 0x088ea000 0 0x40>;
status = "disabled";
#clock-cells = <1>;
#address-cells = <2>;
@@ -3743,11 +3743,11 @@
<&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
clock-names = "aux", "cfg_ahb", "ref", "com_aux";
- resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
- <&gcc GCC_USB3_PHY_PRIM_BCR>;
+ resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+ <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: lanes@88e9200 {
+ usb_1_ssphy: usb3-phy@88e9200 {
reg = <0 0x088e9200 0 0x128>,
<0 0x088e9400 0 0x200>,
<0 0x088e9c00 0 0x218>,
@@ -3759,6 +3759,16 @@
clock-names = "pipe0";
clock-output-names = "usb3_phy_pipe_clk_src";
};
+
+ dp_phy: dp-phy@88ea200 {
+ reg = <0 0x088ea200 0 0x200>,
+ <0 0x088ea400 0 0x200>,
+ <0 0x088eaa00 0 0x200>,
+ <0 0x088ea600 0 0x200>,
+ <0 0x088ea800 0 0x200>;
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+ };
};
usb_2_qmpphy: phy@88eb000 {
@@ -4114,13 +4124,20 @@
port@0 {
reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&dp_in>;
};
};
port@1 {
reg = <1>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
@@ -4152,6 +4169,73 @@
};
};
+ msm_dp: displayport-controller@ae90000 {
+ status = "disabled";
+ compatible = "qcom,sc7180-dp";
+
+ reg = <0 0x0ae90000 0 0x1400>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface", "core_aux", "ctrl_link",
+ "ctrl_link_iface", "stream_pixel";
+ #clock-cells = <1>;
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+ phys = <&dp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SDM845_CX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dp_out: endpoint { };
+ };
+ };
+
+ dp_opp_table: dp-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
dsi0: dsi@ae94000 {
compatible = "qcom,mdss-dsi-ctrl";
reg = <0 0x0ae94000 0 0x400>;
@@ -4428,8 +4512,8 @@
<&dsi0_phy 1>,
<&dsi1_phy 0>,
<&dsi1_phy 1>,
- <0>,
- <0>;
+ <&dp_phy 0>,
+ <&dp_phy 1>;
clock-names = "bi_tcxo",
"gcc_disp_gpll0_clk_src",
"gcc_disp_gpll0_div_clk_src",
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
index 3774f8e63416..3202a92d815a 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -417,6 +417,35 @@
vdda-pll-max-microamp = <19000>;
};
+&pm8150b_vbus {
+ status = "okay";
+};
+
+&pm8150b_typec {
+ status = "okay";
+ connector {
+ compatible = "usb-c-connector";
+ power-role = "dual";
+ data-role = "dual";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@1 {
+ reg = <1>;
+ usb3_data_ss: endpoint@0 {
+ remote-endpoint = <&qmp_ss_mux>;
+ };
+ };
+ };
+ };
+
+ port {
+ usb3_role: endpoint {
+ remote-endpoint = <&dwc3_drd_switch>;
+ };
+ };
+};
+
&usb_1_hsphy {
status = "okay";
vdda-pll-supply = <&vdd_usb_hs_core>;
@@ -428,14 +457,27 @@
status = "okay";
vdda-phy-supply = <&vreg_l3c_1p2>;
vdda-pll-supply = <&vdda_usb_ss_dp_core_1>;
+ orientation-switch;
+ port {
+ qmp_ss_mux: endpoint@0 {
+ remote-endpoint = <&usb3_data_ss>;
+ };
+ };
};
&usb_1 {
status = "okay";
+ usb-role-switch;
+ port {
+ dwc3_drd_switch: endpoint@0 {
+ remote-endpoint = <&usb3_role>;
+ };
+ };
};
&usb_1_dwc3 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ usb-role-switch;
};
&wifi {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 5270bda7418f..0b6234ccdc3a 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -172,6 +172,13 @@
#hwlock-cells = <1>;
};
+ mmcx_reg: mmcx-reg {
+ compatible = "regulator-fixed-domain";
+ power-domains = <&rpmhpd SM8150_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ regulator-name = "MMCX";
+ };
+
memory@80000000 {
device_type = "memory";
/* We expect the bootloader to fill in the size */
diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
index dea00f19711d..5df2a399c526 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
@@ -6,6 +6,9 @@
/dts-v1/;
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/gpio/gpio.h>
#include "sm8250.dtsi"
#include "pm8150.dtsi"
#include "pm8150b.dtsi"
@@ -24,6 +27,104 @@
stdout-path = "serial0:115200n8";
};
+ thermal-zones {
+ xo-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150_adc_tm 0>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ skin-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150_adc_tm 1>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mmw-pa1 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ conn-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150b_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150l_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ skin-msm-therm {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150l_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mmw-pa2 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8150l_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+ };
+
vph_pwr: vph-pwr-regulator {
compatible = "regulator-fixed";
regulator-name = "vph_pwr";
@@ -53,6 +154,20 @@
regulator-always-on;
vin-supply = <&vph_pwr>;
};
+
+ display_panel_avdd: display_gpio_regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "display_panel_avdd";
+ regulator-min-microvolt = <5500000>;
+ regulator-max-microvolt = <5500000>;
+ regulator-enable-ramp-delay = <233>;
+ gpio = <&tlmm 61 0>;
+ enable-active-high;
+ regulator-boot-on;
+ pinctrl-names = "default";
+ pinctrl-0 = <&display_panel_avdd_default>;
+ };
+
};
&adsp {
@@ -186,6 +301,13 @@
regulator-max-microvolt = <3008000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+
+ vreg_l18a_0p9: ldo18 {
+ regulator-name = "vreg_l18a_0p9";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
};
pm8150l-rpmh-regulators {
@@ -358,6 +480,60 @@
firmware-name = "qcom/sm8250/cdsp.mbn";
};
+&dispcc {
+ dpu-disable-interfaces;
+};
+
+#if 0
+&dsi0 {
+ status = "okay";
+ vdda-supply = <&vreg_l9a_1p2>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ port@1 {
+ endpoint {
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+};
+
+&dsi0_phy {
+ status = "okay";
+ vdds-supply = <&vreg_l5a_0p875>;
+};
+#endif
+
+#if 0
+&dsi1 {
+ status = "okay";
+ vdda-supply = <&vreg_l9a_1p2>;
+
+ ports {
+ port@1 {
+ endpoint {
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+};
+
+&dsi1_phy {
+ status = "okay";
+ vdds-supply = <&vreg_l5a_0p875>;
+};
+#endif
+
+&gpu {
+ zap-shader {
+ memory-region = <&gpu_mem>;
+ firmware-name = "qcom/sm820/a650_zap.mbn";
+ };
+};
+
&i2c1 {
status = "okay";
clock-frequency = <1000000>;
@@ -378,6 +554,135 @@
/* rtc6226 @ 64 */
};
+#if 0
+&mdss {
+ status = "okay";
+};
+
+&mdss_mdp {
+ status = "okay";
+};
+#endif
+
+&pm8150_adc {
+ xo-therm@4c {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ skin-therm@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pa-therm1@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150b_adc {
+ conn-therm@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150l_adc {
+ camera-flash-therm@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ skin-msm-therm@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pa-therm2@4f {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150_adc ADC5_XO_THERM_100K_PU>,
+ <&pm8150_adc ADC5_AMUX_THM1_100K_PU>,
+ <&pm8150_adc ADC5_AMUX_THM2_100K_PU>;
+ io-channel-names = "xo-therm", "skin-therm", "pa-therm1";
+
+ xo-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ skin-therm@1 {
+ reg = <1>;
+ qcom,adc-channel = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pa-therm1@2 {
+ reg = <2>;
+ qcom,adc-channel = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150b_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150b_adc ADC5_AMUX_THM3_100K_PU>;
+ io-channel-names = "conn-therm";
+
+ conn-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
+&pm8150l_adc_tm {
+ status = "okay";
+ io-channels = <&pm8150l_adc ADC5_AMUX_THM1_100K_PU>,
+ <&pm8150l_adc ADC5_AMUX_THM2_100K_PU>,
+ <&pm8150l_adc ADC5_AMUX_THM3_100K_PU>;
+ io-channel-names = "camera-flash-therm", "skin-msm-therm", "pa-therm2";
+
+ camera-flash-therm@0 {
+ reg = <0>;
+ qcom,adc-channel = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ skin-msm-therm@1 {
+ reg = <1>;
+ qcom,adc-channel = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pa-therm2@2 {
+ reg = <2>;
+ qcom,adc-channel = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+};
+
&pm8150_rtc {
status = "okay";
};
@@ -401,6 +706,21 @@
&tlmm {
gpio-reserved-ranges = <28 4>, <40 4>;
+
+ display_panel_avdd_default: display_panel_avdd_default {
+ mux {
+ pins = "gpio61";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <8>;
+ bias-disable = <0>;
+ output-high;
+ };
+ };
+
};
&uart12 {
@@ -426,3 +746,107 @@
vdda-pll-supply = <&vreg_l9a_1p2>;
vdda-pll-max-microamp = <19000>;
};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l5a_0p875>;
+ vdda18-supply = <&vreg_l12a_1p8>;
+ vdda33-supply = <&vreg_l2a_3p1>;
+};
+
+&usb_1_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l9a_1p2>;
+ vdda-pll-supply = <&vreg_l18a_0p9>;
+};
+
+&usb_2 {
+ status = "okay";
+};
+
+&usb_2_dwc3 {
+ dr_mode = "host";
+};
+
+&usb_2_hsphy {
+ status = "okay";
+
+ vdda-pll-supply = <&vreg_l5a_0p875>;
+ vdda18-supply = <&vreg_l12a_1p8>;
+ vdda33-supply = <&vreg_l2a_3p1>;
+};
+
+&usb_2_qmpphy {
+ status = "okay";
+
+ vdda-phy-supply = <&vreg_l9a_1p2>;
+ vdda-pll-supply = <&vreg_l18a_0p9>;
+};
+
+&swr0 {
+ left_right: wsa8810-right{
+ compatible = "sdw10217211000";
+ reg = <0 2>;
+ powerdown-gpios = <&tlmm 127 GPIO_ACTIVE_HIGH>;
+ #thermal-sensor-cells = <0>;
+ sound-name-prefix = "SpkrRight";
+ #sound-dai-cells = <0>;
+ };
+
+ left_spkr: wsa8810-left{
+ compatible = "sdw10217211000";
+ reg = <0 1>;
+ powerdown-gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>;
+ #thermal-sensor-cells = <0>;
+ sound-name-prefix = "SpkrLeft";
+ #sound-dai-cells = <0>;
+ };
+};
+
+&q6asmdai {
+ dai@0 {
+ reg = <0>;
+ direction = <2>;
+ };
+};
+
+&sound {
+ compatible = "qcom,sm8250-sndcard";
+ model = "SM8250";
+ audio-routing =
+ "SpkrLeft IN", "WSA_SPK1 OUT",
+ "MM_DL1", "MultiMedia1 Playback";
+
+ mm1-dai-link {
+ link-name = "MultiMedia1";
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ dma-dai-link {
+ link-name = "WSA Playback";
+ cpu {
+ sound-dai = <&q6afedai WSA_CODEC_DMA_RX_0>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&left_spkr>, <&swr0 0>, <&wsamacro>;
+ };
+ };
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts b/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts
new file mode 100644
index 000000000000..47e14bb0f288
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8250-rb5-dvt.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020, Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include "qrb5165-rb5.dts"
+
+&left_spkr {
+ compatible = "sdw10217201000";
+ reg = <0 1>;
+};
+
+&right_spkr {
+ compatible = "sdw10217201000";
+ reg = <0 2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index 65acd1f381eb..3cb65b85f4a6 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -4,13 +4,19 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,dispcc-sm8250.h>
#include <dt-bindings/clock/qcom,gcc-sm8250.h>
#include <dt-bindings/clock/qcom,gpucc-sm8250.h>
+#include <dt-bindings/clock/qcom,sm8250-lpass-audiocc.h>
+#include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/interconnect/qcom,osm-l3.h>
+#include <dt-bindings/interconnect/qcom,sm8250.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/power/qcom-aoss-qmp.h>
#include <dt-bindings/power/qcom-rpmpd.h>
+#include <dt-bindings/soc/qcom,apr.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
#include <dt-bindings/thermal/thermal.h>
@@ -89,6 +95,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x0>;
enable-method = "psci";
+ cpu-idle-states = <&LITTLE_CPU_SLEEP_0
+ &LITTLE_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
next-level-cache = <&L2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
@@ -106,6 +117,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x100>;
enable-method = "psci";
+ cpu-idle-states = <&LITTLE_CPU_SLEEP_0
+ &LITTLE_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
next-level-cache = <&L2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
@@ -120,6 +136,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x200>;
enable-method = "psci";
+ cpu-idle-states = <&LITTLE_CPU_SLEEP_0
+ &LITTLE_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
next-level-cache = <&L2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
@@ -134,6 +155,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x300>;
enable-method = "psci";
+ cpu-idle-states = <&LITTLE_CPU_SLEEP_0
+ &LITTLE_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
next-level-cache = <&L2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
@@ -148,6 +174,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x400>;
enable-method = "psci";
+ cpu-idle-states = <&BIG_CPU_SLEEP_0
+ &BIG_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1894>;
+ dynamic-power-coefficient = <533>;
next-level-cache = <&L2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
@@ -162,6 +193,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x500>;
enable-method = "psci";
+ cpu-idle-states = <&BIG_CPU_SLEEP_0
+ &BIG_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1894>;
+ dynamic-power-coefficient = <533>;
next-level-cache = <&L2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
@@ -177,6 +213,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x600>;
enable-method = "psci";
+ cpu-idle-states = <&BIG_CPU_SLEEP_0
+ &BIG_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1894>;
+ dynamic-power-coefficient = <533>;
next-level-cache = <&L2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
@@ -191,6 +232,11 @@
compatible = "qcom,kryo485";
reg = <0x0 0x700>;
enable-method = "psci";
+ cpu-idle-states = <&BIG_CPU_SLEEP_0
+ &BIG_CPU_SLEEP_1
+ &CLUSTER_SLEEP_0>;
+ capacity-dmips-mhz = <1894>;
+ dynamic-power-coefficient = <642>;
next-level-cache = <&L2_700>;
qcom,freq-domain = <&cpufreq_hw 2>;
#cooling-cells = <2>;
@@ -199,6 +245,96 @@
next-level-cache = <&L3_0>;
};
};
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+
+ core4 {
+ cpu = <&CPU4>;
+ };
+
+ core5 {
+ cpu = <&CPU5>;
+ };
+
+ core6 {
+ cpu = <&CPU6>;
+ };
+
+ core7 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "little-power-down";
+ arm,psci-suspend-param = <0x40000003>;
+ entry-latency-us = <350>;
+ exit-latency-us = <461>;
+ min-residency-us = <1890>;
+ local-timer-stop;
+ };
+
+ LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
+ compatible = "arm,idle-state";
+ idle-state-name = "little-rail-power-down";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <360>;
+ exit-latency-us = <531>;
+ min-residency-us = <3934>;
+ local-timer-stop;
+ };
+
+ BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "big-power-down";
+ arm,psci-suspend-param = <0x40000003>;
+ entry-latency-us = <264>;
+ exit-latency-us = <621>;
+ min-residency-us = <952>;
+ local-timer-stop;
+ };
+
+ BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
+ compatible = "arm,idle-state";
+ idle-state-name = "big-rail-power-down";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <702>;
+ exit-latency-us = <1061>;
+ min-residency-us = <4488>;
+ local-timer-stop;
+ };
+
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "cluster-power-down";
+ arm,psci-suspend-param = <0x400000F4>;
+ entry-latency-us = <3263>;
+ exit-latency-us = <6562>;
+ min-residency-us = <9987>;
+ local-timer-stop;
+ };
+ };
};
firmware {
@@ -214,6 +350,13 @@
reg = <0x0 0x80000000 0x0 0x0>;
};
+ mmcx_reg: mmcx-reg {
+ compatible = "regulator-fixed-domain";
+ power-domains = <&rpmhpd SM8250_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ regulator-name = "MMCX";
+ };
+
pmu {
compatible = "arm,armv8-pmuv3";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
@@ -321,7 +464,7 @@
};
};
- smem: qcom,smem {
+ smem {
compatible = "qcom,smem";
memory-region = <&smem_mem>;
hwlocks = <&tcsr_mutex 3>;
@@ -1168,6 +1311,299 @@
qcom,bcm-voters = <&apps_bcm_voter>;
};
+ pcie0: pci@1c00000 {
+ compatible = "qcom,pcie-sm8250", "snps,dw-pcie";
+ reg = <0 0x01c00000 0 0x3000>,
+ <0 0x60000000 0 0xf1d>,
+ <0 0x60000f20 0 0xa8>,
+ <0 0x60001000 0 0x1000>,
+ <0 0x60100000 0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ ranges = <0x01000000 0x0 0x60200000 0 0x60200000 0x0 0x100000>,
+ <0x02000000 0x0 0x60300000 0 0x60300000 0x0 0x3d00000>;
+
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
+ <&gcc GCC_PCIE_0_AUX_CLK>,
+ <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>;
+ clock-names = "pipe",
+ "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "tbu",
+ "ddrss_sf_tbu";
+
+ iommus = <&apps_smmu 0x1c00 0x7f>;
+ iommu-map = <0x0 &apps_smmu 0x1c00 0x1>,
+ <0x100 &apps_smmu 0x1c01 0x1>;
+
+ resets = <&gcc GCC_PCIE_0_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_0_GDSC>;
+
+ phys = <&pcie0_lane>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie0_phy: phy@1c06000 {
+ compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy";
+ reg = <0 0x01c06000 0 0x1c0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
+ <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_WIFI_CLKREF_EN>,
+ <&gcc GCC_PCIE0_PHY_REFGEN_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "refgen";
+
+ resets = <&gcc GCC_PCIE_0_PHY_BCR>;
+ reset-names = "phy";
+
+ assigned-clocks = <&gcc GCC_PCIE0_PHY_REFGEN_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ status = "disabled";
+
+ pcie0_lane: lanes@1c06200 {
+ reg = <0 0x1c06200 0 0x170>, /* tx */
+ <0 0x1c06400 0 0x200>, /* rx */
+ <0 0x1c06800 0 0x1f0>, /* pcs */
+ <0 0x1c06c00 0 0xf4>; /* "pcs_lane" same as pcs_misc? */
+ clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
+ clock-names = "pipe0";
+
+ #phy-cells = <0>;
+ clock-output-names = "pcie_0_pipe_clk";
+ };
+ };
+
+ pcie1: pci@1c08000 {
+ compatible = "qcom,pcie-sm8250", "snps,dw-pcie";
+ reg = <0 0x01c08000 0 0x3000>,
+ <0 0x40000000 0 0xf1d>,
+ <0 0x40000f20 0 0xa8>,
+ <0 0x40001000 0 0x1000>,
+ <0 0x40100000 0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ device_type = "pci";
+ linux,pci-domain = <1>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <2>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+ interrupts = <GIC_SPI 306 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 434 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 435 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 438 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 439 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
+ <&gcc GCC_PCIE_1_AUX_CLK>,
+ <&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_1_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_PCIE_WIGIG_CLKREF_EN>,
+ <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>;
+ clock-names = "pipe",
+ "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ref",
+ "tbu",
+ "ddrss_sf_tbu";
+
+ assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ iommus = <&apps_smmu 0x1c80 0x7f>;
+ iommu-map = <0x0 &apps_smmu 0x1c80 0x1>,
+ <0x100 &apps_smmu 0x1c81 0x1>;
+
+ resets = <&gcc GCC_PCIE_1_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_1_GDSC>;
+
+ phys = <&pcie1_lane>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie1_phy: phy@1c0e000 {
+ compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy";
+ reg = <0 0x01c0e000 0 0x1c0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
+ <&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_WIGIG_CLKREF_EN>,
+ <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "refgen";
+
+ resets = <&gcc GCC_PCIE_1_PHY_BCR>;
+ reset-names = "phy";
+
+ assigned-clocks = <&gcc GCC_PCIE1_PHY_REFGEN_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ status = "disabled";
+
+ pcie1_lane: lanes@1c0e200 {
+ reg = <0 0x1c0e200 0 0x170>, /* tx0 */
+ <0 0x1c0e400 0 0x200>, /* rx0 */
+ <0 0x1c0ea00 0 0x1f0>, /* pcs */
+ <0 0x1c0e600 0 0x170>, /* tx1 */
+ <0 0x1c0e800 0 0x200>, /* rx1 */
+ <0 0x1c0ee00 0 0xf4>; /* "pcs_com" same as pcs_misc? */
+ clocks = <&gcc GCC_PCIE_1_PIPE_CLK>;
+ clock-names = "pipe0";
+
+ #phy-cells = <0>;
+ clock-output-names = "pcie_1_pipe_clk";
+ };
+ };
+
+ pcie2: pci@1c10000 {
+ compatible = "qcom,pcie-sm8250", "snps,dw-pcie";
+ reg = <0 0x01c10000 0 0x3000>,
+ <0 0x64000000 0 0xf1d>,
+ <0 0x64000f20 0 0xa8>,
+ <0 0x64001000 0 0x1000>,
+ <0 0x64100000 0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ device_type = "pci";
+ linux,pci-domain = <2>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <2>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ ranges = <0x01000000 0x0 0x64200000 0x0 0x64200000 0x0 0x100000>,
+ <0x02000000 0x0 0x64300000 0x0 0x64300000 0x0 0x3d00000>;
+
+ interrupts = <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 290 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 415 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 416 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 417 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ clocks = <&gcc GCC_PCIE_2_PIPE_CLK>,
+ <&gcc GCC_PCIE_2_AUX_CLK>,
+ <&gcc GCC_PCIE_2_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_2_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_2_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_2_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_PCIE_MDM_CLKREF_EN>,
+ <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>;
+ clock-names = "pipe",
+ "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ref",
+ "tbu",
+ "ddrss_sf_tbu";
+
+ assigned-clocks = <&gcc GCC_PCIE_2_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ iommus = <&apps_smmu 0x1d00 0x7f>;
+ iommu-map = <0x0 &apps_smmu 0x1d00 0x1>,
+ <0x100 &apps_smmu 0x1d01 0x1>;
+
+ resets = <&gcc GCC_PCIE_2_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_2_GDSC>;
+
+ phys = <&pcie2_lane>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie2_phy: phy@1c16000 {
+ compatible = "qcom,sm8250-qmp-modem-pcie-phy";
+ reg = <0 0x1c16000 0 0x1c0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clocks = <&gcc GCC_PCIE_PHY_AUX_CLK>,
+ <&gcc GCC_PCIE_2_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_MDM_CLKREF_EN>,
+ <&gcc GCC_PCIE2_PHY_REFGEN_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "refgen";
+
+ resets = <&gcc GCC_PCIE_2_PHY_BCR>;
+ reset-names = "phy";
+
+ assigned-clocks = <&gcc GCC_PCIE2_PHY_REFGEN_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ status = "disabled";
+
+ pcie2_lane: lanes@1c0e200 {
+ reg = <0 0x1c16200 0 0x170>, /* tx0 */
+ <0 0x1c16400 0 0x200>, /* rx0 */
+ <0 0x1c16a00 0 0x1f0>, /* pcs */
+ <0 0x1c16600 0 0x170>, /* tx1 */
+ <0 0x1c16800 0 0x200>, /* rx1 */
+ <0 0x1c16e00 0 0xf4>; /* "pcs_com" same as pcs_misc? */
+ clocks = <&gcc GCC_PCIE_2_PIPE_CLK>;
+ clock-names = "pipe0";
+
+ #phy-cells = <0>;
+ clock-output-names = "pcie_2_pipe_clk";
+ };
+ };
+
ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sm8250-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
@@ -1253,15 +1689,44 @@
#hwlock-cells = <1>;
};
+ slimbam: dma@3a84000 {
+ compatible = "qcom,bam-v1.7.0";
+ qcom,controlled-remotely;
+ reg = <0 0x3a84000 0 0x2a000>;
+ num-channels = <31>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ qcom,ee = <1>;
+ qcom,num-ees = <2>;
+ iommus = <&apps_smmu 0x1826 0x0>;
+ };
+
+ slim: slim@3ac0000 {
+ compatible = "qcom,slim-ngd-v2.2.0";
+ reg = <0 0x3ac0000 0 0x2c000>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+
+ qcom,apps-ch-pipes = <0x780000>;
+ qcom,ea-pc = <0x270>;
+ status = "okay";
+ dmas = <&slimbam 3>, <&slimbam 4>,
+ <&slimbam 5>, <&slimbam 6>;
+ dma-names = "rx", "tx", "tx2", "rx2";
+
+ iommus = <&apps_smmu 0x1826 0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ngd@1 {
+ reg = <1>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ };
+ };
+
gpu: gpu@3d00000 {
- /*
- * note: the amd,imageon compatible makes it possible
- * to use the drm/msm driver without the display node,
- * make sure to remove it when display node is added
- */
compatible = "qcom,adreno-650.2",
- "qcom,adreno",
- "amd,imageon";
+ "qcom,adreno";
#stream-id-cells = <16>;
reg = <0 0x03d00000 0 0x40000>;
@@ -1399,7 +1864,7 @@
compatible = "qcom,sm8250-slpi-pas";
reg = <0 0x05c00000 0 0x4000>;
- interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts-extended = <&pdc 9 IRQ_TYPE_EDGE_RISING>,
<&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
<&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
<&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
@@ -1465,7 +1930,7 @@
compatible = "qcom,sm8250-cdsp-pas";
reg = <0 0x08300000 0 0x10000>;
- interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
<&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
<&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
<&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
@@ -1557,6 +2022,9 @@
};
};
+ sound: sound {
+ };
+
usb_1_hsphy: phy@88e3000 {
compatible = "qcom,sm8250-usb-hs-phy",
"qcom,usb-snps-hs-7nm-phy";
@@ -1636,7 +2104,7 @@
<&gcc GCC_USB3_PHY_SEC_BCR>;
reset-names = "phy", "common";
- usb_2_ssphy: lane@88eb200 {
+ usb_2_ssphy: lanes@88eb200 {
reg = <0 0x088eb200 0 0x200>,
<0 0x088eb400 0 0x200>,
<0 0x088eb800 0 0x800>;
@@ -1657,7 +2125,7 @@
clocks = <&gcc GCC_SDCC2_AHB_CLK>,
<&gcc GCC_SDCC2_APPS_CLK>,
- <&xo_board>;
+ <&rpmhcc RPMH_CXO_CLK>;
clock-names = "iface", "core", "xo";
iommus = <&apps_smmu 0x4a0 0x0>;
qcom,dll-config = <0x0007642c>;
@@ -1758,6 +2226,12 @@
};
};
+ system-cache-controller@9200000 {
+ compatible = "qcom,sm8250-llcc";
+ reg = <0 0x09200000 0 0x1d0000>, <0 0x09600000 0 0x50000>;
+ reg-names = "llcc_base", "llcc_broadcast_base";
+ };
+
usb_2: usb@a8f8800 {
compatible = "qcom,sm8250-dwc3", "qcom,dwc3";
reg = <0 0x0a8f8800 0 0x400>;
@@ -1803,6 +2277,299 @@
};
};
+ mdss: mdss@ae00000 {
+ compatible = "qcom,sdm845-mdss";
+ reg = <0 0x0ae00000 0 0x1000>;
+ reg-names = "mdss";
+
+ interconnects = <&gem_noc MASTER_AMPSS_M0 &config_noc SLAVE_DISPLAY_CFG>,
+ <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>,
+ <&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>;
+ interconnect-names = "notused", "mdp0-mem", "mdp1-mem";
+
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&gcc GCC_DISP_SF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "nrt_bus", "core";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ assigned-clock-rates = <460000000>;
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x820 0x402>;
+
+ status = "disabled";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ mdss_mdp: mdp@ae01000 {
+ compatible = "qcom,sdm845-dpu";
+ reg = <0 0x0ae01000 0 0x8f000>,
+ <0 0x0aeb0000 0 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "core", "vsync";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ assigned-clock-rates = <460000000>,
+ <19200000>;
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: mdp-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-345000000 {
+ opp-hz = /bits/ 64 <345000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-460000000 {
+ opp-hz = /bits/ 64 <460000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
+ dsi0: dsi@ae94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0 0x0ae94000 0 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: dsi-phy@ae94400 {
+ compatible = "qcom,dsi-phy-7nm";
+ reg = <0 0x0ae94400 0 0x200>,
+ <0 0x0ae94600 0 0x280>,
+ <0 0x0ae94900 0 0x260>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+
+ dsi1: dsi@ae96000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0 0x0ae96000 0 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK1_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC1_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ phys = <&dsi1_phy>;
+ phy-names = "dsi";
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&dpu_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi1_phy: dsi-phy@ae96400 {
+ compatible = "qcom,dsi-phy-7nm";
+ reg = <0 0x0ae96400 0 0x200>,
+ <0 0x0ae96600 0 0x280>,
+ <0 0x0ae96900 0 0x260>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+
+ dsi_opp_table: dsi-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-358000000 {
+ opp-hz = /bits/ 64 <358000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
+ };
+
+ dispcc: clock-controller@af00000 {
+ compatible = "qcom,sm8250-dispcc";
+ reg = <0 0x0af00000 0 0x20000>;
+ mmcx-supply = <&mmcx_reg>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&dsi0_phy 0>,
+ <&dsi0_phy 1>,
+ <&dsi1_phy 0>,
+ <&dsi1_phy 1>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <0>,
+ <&sleep_clk>;
+ clock-names = "bi_tcxo",
+ "dsi0_phy_pll_out_byteclk",
+ "dsi0_phy_pll_out_dsiclk",
+ "dsi1_phy_pll_out_byteclk",
+ "dsi1_phy_pll_out_dsiclk",
+ "dp_link_clk_divsel_ten",
+ "dp_vco_divided_clk_src_mux",
+ "dptx1_phy_pll_link_clk",
+ "dptx1_phy_pll_vco_div_clk",
+ "dptx2_phy_pll_link_clk",
+ "dptx2_phy_pll_vco_div_clk",
+ "edp_phy_pll_link_clk",
+ "edp_phy_pll_vco_div_clk",
+ "sleep_clk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sm8250-pdc", "qcom,pdc";
reg = <0 0x0b220000 0 0x30000>, <0 0x17c000f0 0 0x60>;
@@ -1880,6 +2647,60 @@
gpio-ranges = <&tlmm 0 0 180>;
wakeup-parent = <&pdc>;
+ pri_mi2s_sck_active: pri-mi2s-sck-active {
+ mux {
+ pins = "gpio138";
+ function = "mi2s0_sck";
+ };
+
+ config {
+ pins = "gpio138";
+ drive-strength = <8>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ pri_mi2s_ws_active: pri-mi2s-ws-active {
+ mux {
+ pins = "gpio141";
+ function = "mi2s0_ws";
+ };
+
+ config {
+ pins = "gpio141";
+ drive-strength = <8>;
+ output-high;
+ };
+ };
+
+ pri_mi2s_sd0_active: pri-mi2s-sd0-active {
+ mux {
+ pins = "gpio139";
+ function = "mi2s0_data0";
+ };
+
+ config {
+ pins = "gpio139";
+ drive-strength = <8>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ pri_mi2s_sd1_active: pri-mi2s-sd1-active {
+ mux {
+ pins = "gpio140";
+ function = "mi2s0_data1";
+ };
+
+ config {
+ pins = "gpio140";
+ drive-strength = <8>;
+ output-high;
+ };
+ };
+
qup_i2c0_default: qup-i2c0-default {
mux {
pins = "gpio28", "gpio29";
@@ -2476,6 +3297,47 @@
function = "qup18";
};
};
+
+ tert_mi2s_sck_active: tert-mi2s-sck-active {
+ mux {
+ pins = "gpio133";
+ function = "mi2s2_sck";
+ };
+
+ config {
+ pins = "gpio133";
+ drive-strength = <8>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ tert_mi2s_sd0_active: tert-mi2s-sd0-active {
+ mux {
+ pins = "gpio134";
+ function = "mi2s2_data0";
+ };
+
+ config {
+ pins = "gpio134";
+ drive-strength = <8>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ tert_mi2s_ws_active: tert-mi2s-ws-active {
+ mux {
+ pins = "gpio135";
+ function = "mi2s2_ws";
+ };
+
+ config {
+ pins = "gpio135";
+ drive-strength = <8>;
+ output-high;
+ };
+ };
};
apps_smmu: iommu@15000000 {
@@ -2583,11 +3445,196 @@
<GIC_SPI 707 IRQ_TYPE_LEVEL_HIGH>;
};
+
+// lpass@2c00000 {
+// compatible = "qcom,sm8250-lpass";
+
+ lpass_tlmm: pinctrl@33c0000{
+ compatible = "qcom,sm8250-lpass-lpi-pinctrl";
+ reg = <0 0x33c0000 0x0 0x20000>,
+ <0 0x3550000 0x0 0x10000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_CLK_ID_WSA_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_CLK_ID_WSA_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "core", "audio","iface", "npl";
+
+
+ wsa_swr_clk_pin {
+ wsa_swr_clk_sleep: wsa_swr_clk_sleep {
+ mux {
+ pins = "gpio10";
+ function = "wsa_swr_clk";
+ drive-strength = <2>;
+ input-enable;
+ bias-pull-down;
+ };
+ };
+
+ wsa_swr_clk_active: wsa_swr_clk_active {
+ mux {
+ pins = "gpio10";
+ function = "wsa_swr_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+ };
+ };
+
+ wsa_swr_data_pin {
+ wsa_swr_data_sleep: wsa_swr_data_sleep {
+ mux {
+ pins = "gpio11";
+ function = "wsa_swr_data";
+ drive-strength = <2>;
+ input-enable;
+ bias-pull-down;
+ };
+ };
+
+ wsa_swr_data_active: wsa_swr_data_active {
+ mux {
+ pins = "gpio11";
+ function = "wsa_swr_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-bus-hold;
+ };
+ };
+ };
+
+ cdc_dmic01_data_active: dmic01_data_active {
+ mux {
+ pins = "gpio7";
+ function = "dmic1_data";
+ drive-strength = <8>;
+ input-enable;
+ };
+ };
+
+ cdc_dmic01_data_sleep: dmic01_data_sleep {
+ mux {
+ pins = "gpio7";
+ function = "dmic1_data";
+ drive-strength = <2>;
+ pull-down;
+ input-enable;
+ };
+ };
+
+ cdc_dmic01_clk_active: dmic01_clk_active {
+ mux {
+ pins = "gpio6";
+ function = "dmic1_clk";
+ drive-strength = <8>;
+ output-high;
+ };
+ };
+
+ cdc_dmic01_clk_sleep: dmic01_clk_sleep {
+ mux {
+ pins = "gpio6";
+ function = "dmic1_clk";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ };
+
+ audiocc: audiocc@3300000 {
+ compatible = "qcom,sm8250-lpass-audiocc";
+ reg = <0 0x03300000 0 0x30000>;
+ #clock-cells = <1>;
+ clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "core", "audio", "bus";
+ };
+
+ aoncc: aoncc@3380000 {
+ compatible = "qcom,sm8250-lpass-aoncc";
+ reg = <0 0x03380000 0 0x40000>;
+ #clock-cells = <1>;
+ clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_CLK_ID_TX_CORE_NPL_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "core", "audio", "bus";
+ };
+
+ wsamacro: lpass-wsa-macro@3240000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&wsa_swr_clk_active &wsa_swr_data_active>;
+
+ compatible = "qcom,sm8250-lpass-wsa-macro";
+ reg = <0 0x3240000 0 0x1000>;
+ clocks = <&audiocc LPASS_CDC_WSA_MCLK>,
+ <&audiocc LPASS_CDC_WSA_NPL>,
+ <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&aoncc LPASS_CDC_VA_MCLK>,
+ <&vamacro>;
+
+ clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen";
+
+ #clock-cells = <0>;
+ clock-frequency = <9600000>;
+ clock-output-names = "mclk";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ #sound-dai-cells = <0>;
+ ranges;
+ };
+
+ swr0: controller@3250000 {
+ reg = <0 0x3250000 0 0x2000>;
+ compatible = "qcom,soundwire-v1.5.1";
+ interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&wsamacro>;
+ clock-names = "iface";
+
+ qcom,din-ports = <2>;
+ qcom,dout-ports = <6>;
+
+ qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1F 0x3F 0x07 0x1F 0x3F 0x0F 0x0F>;
+ qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x06 0x12 0x0D 0x07 0x0A >;
+ qcom,ports-offset2 = /bits/ 8 <0xFF 0x00 0x1F 0xFF 0x00 0x1F 0x00 0x00>;
+ qcom,ports-block-pack-mode = /bits/ 8 <0x0 0x0 0x1 0x0 0x0 0x1 0x0 0x0>;
+
+ #sound-dai-cells = <1>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ };
+
+ vamacro: lpass-va-macro@3370000 {
+ compatible = "qcom,sm8250-lpass-va-macro";
+ reg = <0 0x3370000 0 0x1000>,
+ <0 0x3220000 0 0x1000>;
+ clocks = <&aoncc LPASS_CDC_VA_MCLK>,
+ <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+
+ clock-names = "mclk", "macro", "dcodec";
+
+ #clock-cells = <0>;
+ clock-frequency = <9600000>;
+ clock-output-names = "fsgen";
+ #sound-dai-cells = <1>;
+ qcom,vdd-micb-voltage = <1800000 1800000>;
+ qcom,vdd-micb-current = <11200>;
+ qcom,dmic-sample-rate = <600000>;
+ };
+ //};
adsp: remoteproc@17300000 {
compatible = "qcom,sm8250-adsp-pas";
reg = <0 0x17300000 0 0x100>;
- interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
<&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
<&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
<&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
@@ -2620,6 +3667,61 @@
label = "lpass";
qcom,remote-pid = <2>;
+ apr {
+ compatible = "qcom,apr-v2";
+ qcom,glink-channels = "apr_audio_svc";
+ qcom,apr-domain = <APR_DOMAIN_ADSP>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ qcom,intents = <512 20>;
+
+ apr-service@3 {
+ reg = <APR_SVC_ADSP_CORE>;
+ compatible = "qcom,q6core";
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ };
+
+ q6afe: apr-service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ q6afedai: dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ q6afecc: cc {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+ };
+
+ q6asm: apr-service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ q6asmdai: dais {
+ compatible = "qcom,q6asm-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ iommus = <&apps_smmu 0x1801 0x0>;
+ };
+ };
+
+ q6adm: apr-service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ q6routing: routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+ };
+
fastrpc {
compatible = "qcom,fastrpc";
qcom,glink-channels = "fastrpcglink-apps-dsp";
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 838301650a79..681cad0f2c8c 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -14,7 +14,6 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_NUMA_BALANCING=y
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
-CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
@@ -187,21 +186,33 @@ CONFIG_CAN=m
CONFIG_CAN_RCAR=m
CONFIG_CAN_RCAR_CANFD=m
CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_MCP251XFD=m
CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
# CONFIG_BT_HS is not set
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_CFG80211=m
+CONFIG_CFG80211_WEXT=y
CONFIG_MAC80211=m
CONFIG_MAC80211_LEDS=y
-CONFIG_RFKILL=m
+CONFIG_RFKILL=y
+CONFIG_WCN36XX=m
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_NFC=m
@@ -268,6 +279,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_VIRTIO_BLK=y
CONFIG_BLK_DEV_NVME=m
+CONFIG_QCOM_COINCELL=m
CONFIG_SRAM=y
CONFIG_PCI_ENDPOINT_TEST=m
CONFIG_EEPROM_AT24=m
@@ -282,7 +294,7 @@ CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_MPT3SAS=m
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
-CONFIG_SCSI_UFS_QCOM=m
+CONFIG_SCSI_UFS_QCOM=y
CONFIG_SCSI_UFS_HISI=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
@@ -374,6 +386,9 @@ CONFIG_USB_NET_MCS7830=m
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
CONFIG_ATH10K_SNOC=m
+CONFIG_ATH11K=m
+CONFIG_ATH11K_AHB=m
+CONFIG_ATH11K_PCI=m
CONFIG_BRCMFMAC=m
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_PCIE=m
@@ -449,7 +464,7 @@ CONFIG_I2C_OMAP=y
CONFIG_I2C_OWL=y
CONFIG_I2C_PXA=y
CONFIG_I2C_QCOM_CCI=m
-CONFIG_I2C_QCOM_GENI=m
+CONFIG_I2C_QCOM_GENI=y
CONFIG_I2C_QUP=y
CONFIG_I2C_RK3X=y
CONFIG_I2C_SH_MOBILE=y
@@ -474,7 +489,7 @@ CONFIG_SPI_ROCKCHIP=y
CONFIG_SPI_RPCIF=m
CONFIG_SPI_QCOM_QSPI=m
CONFIG_SPI_QUP=y
-CONFIG_SPI_QCOM_GENI=m
+CONFIG_SPI_QCOM_GENI=y
CONFIG_SPI_S3C64XX=y
CONFIG_SPI_SH_MSIOF=m
CONFIG_SPI_SUN6I=y
@@ -505,6 +520,7 @@ CONFIG_PINCTRL_SC7180=y
CONFIG_PINCTRL_SDM845=y
CONFIG_PINCTRL_SM8150=y
CONFIG_PINCTRL_SM8250=y
+CONFIG_PINCTRL_LPASS_LPI=y
CONFIG_GPIO_ALTERA=m
CONFIG_GPIO_DAVINCI=y
CONFIG_GPIO_DWAPB=y
@@ -561,6 +577,7 @@ CONFIG_EXYNOS_THERMAL=y
CONFIG_TEGRA_BPMP_THERMAL=m
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_TEMP_ALARM=m
+CONFIG_QCOM_SPMI_ADC_TM5=m
CONFIG_UNIPHIER_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SL28CPLD_WATCHDOG=m
@@ -608,6 +625,7 @@ CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_QCOM_RPMH=y
CONFIG_REGULATOR_QCOM_SMD_RPM=y
CONFIG_REGULATOR_QCOM_SPMI=y
+CONFIG_REGULATOR_QCOM_USB_VBUS=m
CONFIG_REGULATOR_RK808=y
CONFIG_REGULATOR_S2MPS11=y
CONFIG_REGULATOR_TPS65132=m
@@ -644,6 +662,7 @@ CONFIG_VIDEO_RCAR_DRIF=m
CONFIG_VIDEO_IMX219=m
CONFIG_VIDEO_OV5645=m
CONFIG_VIDEO_QCOM_CAMSS=m
+CONFIG_VIDEO_QCOM_VENUS=m
CONFIG_DRM=m
CONFIG_DRM_I2C_NXP_TDA998X=m
CONFIG_DRM_MALI_DISPLAY=m
@@ -683,11 +702,15 @@ CONFIG_DRM_SII902X=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
CONFIG_DRM_TI_SN65DSI86=m
+CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
+CONFIG_DRM_LONTIUM_LT9611=m
+CONFIG_DRM_LONTIUM_LT9611UXC=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
CONFIG_DRM_DW_HDMI_CEC=m
CONFIG_DRM_IMX_DCSS=m
+CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_VC4=m
CONFIG_DRM_ETNAVIV=m
CONFIG_DRM_HISI_HIBMC=m
@@ -702,6 +725,7 @@ CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
@@ -724,6 +748,7 @@ CONFIG_SND_SOC_QCOM=m
CONFIG_SND_SOC_APQ8016_SBC=m
CONFIG_SND_SOC_MSM8996=m
CONFIG_SND_SOC_SDM845=m
+CONFIG_SND_SOC_SM8250=m
CONFIG_SND_SOC_ROCKCHIP=m
CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
CONFIG_SND_SOC_ROCKCHIP_RT5645=m
@@ -747,14 +772,25 @@ CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SOC_WCD934X=m
CONFIG_SND_SOC_WM8904=m
CONFIG_SND_SOC_WSA881X=m
+CONFIG_SND_SOC_LPASS_WSA_MACRO=m
+CONFIG_SND_SOC_LPASS_VA_MACRO=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_SND_AUDIO_GRAPH_CARD=m
CONFIG_I2C_HID=m
+CONFIG_SND_SOC_QCOM=y
+CONFIG_SND_SOC_APQ8016_SBC=y
+CONFIG_SND_SOC_QDSP6=y
+CONFIG_SND_SOC_MSM8996=y
+CONFIG_SND_SOC_MSM8916_WCD_ANALOG=y
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=y
+CONFIG_USB=y
CONFIG_USB_CONN_GPIO=m
CONFIG_USB=y
CONFIG_USB_OTG=y
-CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_HCD=m
CONFIG_USB_XHCI_TEGRA=y
+CONFIG_USB_XHCI_PCI=m
+CONFIG_USB_XHCI_PCI_RENESAS=m
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EXYNOS=y
CONFIG_USB_EHCI_HCD_PLATFORM=y
@@ -793,11 +829,12 @@ CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
-CONFIG_TYPEC=m
+CONFIG_TYPEC=y
CONFIG_TYPEC_TCPM=m
CONFIG_TYPEC_FUSB302=m
CONFIG_TYPEC_HD3SS3220=m
CONFIG_TYPEC_TPS6598X=m
+CONFIG_TYPEC_QCOM_PMIC=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_ARMMMCI=y
@@ -828,8 +865,10 @@ CONFIG_MMC_OWL=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_LM3692X=m
+CONFIG_LEDS_CLASS_MULTICOLOR=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_PWM=y
+CONFIG_LEDS_QCOM_LPG=y
CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_DISK=y
@@ -931,8 +970,12 @@ CONFIG_SM_GCC_8150=y
CONFIG_SM_GCC_8250=y
CONFIG_SM_GPUCC_8150=y
CONFIG_SM_GPUCC_8250=y
+CONFIG_SM_DISPCC_8250=y
CONFIG_QCOM_HFPLL=y
+CONFIG_CLK_GFM_LPASS_SM8250=y
CONFIG_HWSPINLOCK=y
+CONFIG_SDM_GPUCC_845=y
+CONFIG_SDM_DISPCC_845=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_ARM_MHU=y
CONFIG_IMX_MBOX=y
@@ -949,6 +992,7 @@ CONFIG_REMOTEPROC=y
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
CONFIG_QCOM_SYSMON=m
+CONFIG_QCOM_WCNSS_PIL=m
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=m
CONFIG_RPMSG_QCOM_SMD=y
@@ -970,6 +1014,7 @@ CONFIG_QCOM_SMD_RPM=y
CONFIG_QCOM_SMP2P=y
CONFIG_QCOM_SMSM=y
CONFIG_QCOM_SOCINFO=m
+CONFIG_QCOM_WCNSS_CTRL=m
CONFIG_QCOM_APR=m
CONFIG_ARCH_R8A774A1=y
CONFIG_ARCH_R8A774B1=y
@@ -1034,9 +1079,13 @@ CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_HISTB_COMBPHY=y
CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
-CONFIG_PHY_QCOM_QMP=m
+CONFIG_PHY_QCOM_QMP=y
+CONFIG_PHY_QCOM_QMP_TYPEC=y
CONFIG_PHY_QCOM_QUSB2=m
+CONFIG_PHY_QCOM_UFS=y
CONFIG_PHY_QCOM_USB_HS=y
+CONFIG_PHY_QCOM_USB_HS_SNPS_28NM=y
+CONFIG_PHY_QCOM_USB_SS=y
CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
@@ -1078,6 +1127,7 @@ CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8916=m
CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+CONFIG_INTERCONNECT_QCOM_QCS404=m
CONFIG_INTERCONNECT_QCOM_SDM845=m
CONFIG_INTERCONNECT_QCOM_SM8150=m
CONFIG_INTERCONNECT_QCOM_SM8250=m
@@ -1108,6 +1158,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY=y
CONFIG_CRYPTO_ECHAINIV=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_DEV_SUN8I_CE=m
@@ -1119,6 +1170,7 @@ CONFIG_CRYPTO_DEV_HISI_SEC2=m
CONFIG_CRYPTO_DEV_HISI_ZIP=m
CONFIG_CRYPTO_DEV_HISI_HPRE=m
CONFIG_CRYPTO_DEV_HISI_TRNG=m
+CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
@@ -1129,3 +1181,4 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_MEMTEST=y
+CONFIG_QCOM_DUMMY=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index ff9cbb631212..07ac208edc89 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += early_ioremap.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
generic-y += qspinlock.h
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
index 93372255984d..cc24bb8e539f 100644
--- a/arch/csky/include/asm/Kbuild
+++ b/arch/csky/include/asm/Kbuild
@@ -2,7 +2,6 @@
generic-y += asm-offsets.h
generic-y += gpio.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += qrwlock.h
generic-y += user.h
generic-y += vmlinux.lds.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index ddf04f32b546..60ee7f0d60a8 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -2,7 +2,6 @@
generic-y += asm-offsets.h
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += spinlock.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 373964bb177e..3ece3c93fe08 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -2,5 +2,4 @@
generic-y += extable.h
generic-y += iomap.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
diff --git a/arch/ia64/include/asm/local64.h b/arch/ia64/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/ia64/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 9b5acf8fb092..e76386a3479e 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -536,7 +536,7 @@ virtual_memmap_init(u64 start, u64 end, void *arg)
if (map_start < map_end)
memmap_init_zone((unsigned long)(map_end - map_start),
- args->nid, args->zone, page_to_pfn(map_start),
+ args->nid, args->zone, page_to_pfn(map_start), page_to_pfn(map_end),
MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
return 0;
}
@@ -546,7 +546,7 @@ memmap_init (unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
if (!vmem_map) {
- memmap_init_zone(size, nid, zone, start_pfn,
+ memmap_init_zone(size, nid, zone, start_pfn, start_pfn + size,
MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
} else {
struct page *start;
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1bff55aa2d54..0dbf9c5c6fae 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -2,6 +2,5 @@
generated-y += syscall_table.h
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += spinlock.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 63bce836b9f1..29b0e557aa7c 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -2,7 +2,6 @@
generated-y += syscall_table.h
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += syscalls.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 198b3bafdac9..95b4fa7bd0d1 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -6,7 +6,6 @@ generated-y += syscall_table_64_n64.h
generated-y += syscall_table_64_o32.h
generic-y += export.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += parport.h
generic-y += qrwlock.h
diff --git a/arch/nds32/include/asm/Kbuild b/arch/nds32/include/asm/Kbuild
index ff1e94299317..82a4453c9c2d 100644
--- a/arch/nds32/include/asm/Kbuild
+++ b/arch/nds32/include/asm/Kbuild
@@ -4,6 +4,5 @@ generic-y += cmpxchg.h
generic-y += export.h
generic-y += gpio.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += parport.h
generic-y += user.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 442f3d3bcd90..ca5987e11053 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += qspinlock_types.h
generic-y += qspinlock.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f16c4db80116..4406475a2304 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -3,6 +3,5 @@ generated-y += syscall_table_32.h
generated-y += syscall_table_64.h
generated-y += syscall_table_c32.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += user.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 90cd5c53af66..e1f9b4ea1c53 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -5,7 +5,6 @@ generated-y += syscall_table_c32.h
generated-y += syscall_table_spu.h
generic-y += export.h
generic-y += kvm_types.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += qrwlock.h
generic-y += vtime.h
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 59dd7be55005..445ccc97305a 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -3,6 +3,5 @@ generic-y += early_ioremap.h
generic-y += extable.h
generic-y += flat.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += user.h
generic-y += vmlinux.lds.h
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index e84bdd15150b..c72874f09741 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -54,17 +54,23 @@ config KASAN_SHADOW_OFFSET
config S390
def_bool y
+ #
+ # Note: keep this list sorted alphabetically
+ #
+ imply IMA_SECURE_AND_OR_TRUSTED_BOOT
select ARCH_BINFMT_ELF_STATE
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
+ select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_SCALED_CPUTIME
select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_HAS_STRICT_MODULE_RWX
@@ -111,8 +117,10 @@ config S390
select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_TABLE_SORT
select CLONE_BACKWARDS2
+ select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
select DMA_OPS if PCI
select DYNAMIC_FTRACE if FUNCTION_TRACER
+ select GENERIC_ALLOCATOR
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_VULNERABILITIES
select GENERIC_FIND_FIRST_BIT
@@ -126,22 +134,21 @@ config S390
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_VMALLOC
- select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_SOFT_DIRTY
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
select HAVE_ARCH_VMAP_STACK
select HAVE_ASM_MODVERSIONS
- select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS
select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_REGS
- select HAVE_FAST_GUP
+ select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
select HAVE_EFFICIENT_UNALIGNED_ACCESS
+ select HAVE_FAST_GUP
select HAVE_FENTRY
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_ERROR_INJECTION
@@ -163,16 +170,15 @@ config S390
select HAVE_KRETPROBES
select HAVE_KVM
select HAVE_LIVEPATCH
- select HAVE_PERF_REGS
- select HAVE_PERF_USER_STACK_DUMP
select HAVE_MEMBLOCK_PHYS_MAP
- select MMU_GATHER_NO_GATHER
select HAVE_MOD_ARCH_SPECIFIC
+ select HAVE_NMI
select HAVE_NOP_MCOUNT
select HAVE_OPROFILE
select HAVE_PCI
select HAVE_PERF_EVENTS
- select MMU_GATHER_RCU_TABLE_FREE
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
select HAVE_RSEQ
@@ -181,6 +187,8 @@ config S390
select HAVE_VIRT_CPU_ACCOUNTING_IDLE
select IOMMU_HELPER if PCI
select IOMMU_SUPPORT if PCI
+ select MMU_GATHER_NO_GATHER
+ select MMU_GATHER_RCU_TABLE_FREE
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE if PCI
select NEED_SG_DMA_LENGTH if PCI
@@ -190,17 +198,12 @@ config S390
select PCI_MSI if PCI
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
select SPARSE_IRQ
+ select SWIOTLB
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
select TTY
select VIRT_CPU_ACCOUNTING
- select ARCH_HAS_SCALED_CPUTIME
- select HAVE_NMI
- select ARCH_HAS_FORCE_DMA_UNENCRYPTED
- select SWIOTLB
- select GENERIC_ALLOCATOR
- imply IMA_SECURE_AND_OR_TRUSTED_BOOT
-
+ # Note: keep the above list sorted alphabetically
config SCHED_OMIT_FRAME_POINTER
def_bool y
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 1be32fcf6f2e..c4f6ff98a612 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -61,7 +61,9 @@ CONFIG_OPROFILE=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
CONFIG_STATIC_KEYS_SELFTEST=y
+CONFIG_SECCOMP_CACHE_DEBUG=y
CONFIG_LOCK_EVENT_COUNTS=y
+# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
@@ -410,12 +412,12 @@ CONFIG_SCSI_ENCLOSURE=m
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
CONFIG_ISCSI_TCP=m
CONFIG_SCSI_DEBUG=m
-CONFIG_ZFCP=y
+CONFIG_ZFCP=m
CONFIG_SCSI_VIRTIO=m
CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
@@ -444,6 +446,7 @@ CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
CONFIG_DM_MULTIPATH_HST=m
+CONFIG_DM_MULTIPATH_IOA=m
CONFIG_DM_DELAY=m
CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
@@ -542,7 +545,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0
-CONFIG_NULL_TTY=m
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_RAW_DRIVER=m
@@ -574,6 +576,7 @@ CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=y
CONFIG_VHOST_NET=m
CONFIG_VHOST_VSOCK=m
+# CONFIG_SURFACE_PLATFORMS is not set
CONFIG_S390_CCW_IOMMU=y
CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
@@ -655,6 +658,7 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
# CONFIG_CIFS_DEBUG is not set
CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_SWN_UPCALL=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_850=m
@@ -826,6 +830,8 @@ CONFIG_FTRACE_SYSCALLS=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_HIST_TRIGGERS=y
+CONFIG_FTRACE_STARTUP_TEST=y
+# CONFIG_EVENT_TRACE_STARTUP_TEST is not set
CONFIG_DEBUG_USER_ASCE=y
CONFIG_NOTIFIER_ERROR_INJECTION=m
CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index e2171a008809..51135893cffe 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -58,6 +58,7 @@ CONFIG_S390_UNWIND_SELFTEST=m
CONFIG_OPROFILE=m
CONFIG_KPROBES=y
CONFIG_JUMP_LABEL=y
+# CONFIG_GCC_PLUGINS is not set
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
@@ -95,7 +96,6 @@ CONFIG_ZSMALLOC_STAT=y
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
CONFIG_IDLE_PAGE_TRACKING=y
CONFIG_PERCPU_STATS=y
-CONFIG_GUP_TEST=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=m
@@ -403,12 +403,12 @@ CONFIG_SCSI_ENCLOSURE=m
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=m
CONFIG_SCSI_SAS_LIBSAS=m
CONFIG_SCSI_SRP_ATTRS=m
CONFIG_ISCSI_TCP=m
CONFIG_SCSI_DEBUG=m
-CONFIG_ZFCP=y
+CONFIG_ZFCP=m
CONFIG_SCSI_VIRTIO=m
CONFIG_SCSI_DH=y
CONFIG_SCSI_DH_RDAC=m
@@ -437,6 +437,7 @@ CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
CONFIG_DM_MULTIPATH_HST=m
+CONFIG_DM_MULTIPATH_IOA=m
CONFIG_DM_DELAY=m
CONFIG_DM_UEVENT=y
CONFIG_DM_FLAKEY=m
@@ -536,7 +537,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_LEGACY_PTY_COUNT=0
-CONFIG_NULL_TTY=m
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_RAW_DRIVER=m
@@ -568,6 +568,7 @@ CONFIG_VIRTIO_BALLOON=m
CONFIG_VIRTIO_INPUT=y
CONFIG_VHOST_NET=m
CONFIG_VHOST_VSOCK=m
+# CONFIG_SURFACE_PLATFORMS is not set
CONFIG_S390_CCW_IOMMU=y
CONFIG_S390_AP_IOMMU=y
CONFIG_EXT4_FS=y
@@ -645,6 +646,7 @@ CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
# CONFIG_CIFS_DEBUG is not set
CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_SWN_UPCALL=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_850=m
@@ -778,6 +780,7 @@ CONFIG_FTRACE_SYSCALLS=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_HIST_TRIGGERS=y
+CONFIG_DEBUG_USER_ASCE=y
CONFIG_LKDTM=m
CONFIG_PERCPU_TEST=m
CONFIG_ATOMIC64_SELFTEST=y
diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig
index a302630341ef..1ef211dae77a 100644
--- a/arch/s390/configs/zfcpdump_defconfig
+++ b/arch/s390/configs/zfcpdump_defconfig
@@ -22,6 +22,7 @@ CONFIG_CRASH_DUMP=y
# CONFIG_VIRTUALIZATION is not set
# CONFIG_S390_GUEST is not set
# CONFIG_SECCOMP is not set
+# CONFIG_GCC_PLUGINS is not set
CONFIG_PARTITION_ADVANCED=y
CONFIG_IBM_PARTITION=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -58,6 +59,7 @@ CONFIG_RAW_DRIVER=y
# CONFIG_HID is not set
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
+# CONFIG_SURFACE_PLATFORMS is not set
# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 319efa0e6d02..1a18d7b82f86 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -7,5 +7,4 @@ generated-y += unistd_nr.h
generic-y += asm-offsets.h
generic-y += export.h
generic-y += kvm_types.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7435182ef846..fc44d9c88b41 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
generated-y += syscall_table.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += parport.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 5269a704801f..3688fdae50e4 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -6,5 +6,4 @@ generated-y += syscall_table_64.h
generated-y += syscall_table_c32.h
generic-y += export.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
diff --git a/arch/x86/include/asm/local64.h b/arch/x86/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/x86/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 9718e9593564..854c5e07e867 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -2,7 +2,6 @@
generated-y += syscall_table.h
generic-y += extable.h
generic-y += kvm_para.h
-generic-y += local64.h
generic-y += mcs_spinlock.h
generic-y += param.h
generic-y += qrwlock.h
diff --git a/block/blk-core.c b/block/blk-core.c
index 96e5fcd7f071..7663a9b94b80 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -18,6 +18,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/blk-mq.h>
+#include <linux/blk-pm.h>
#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
@@ -424,11 +425,11 @@ EXPORT_SYMBOL(blk_cleanup_queue);
/**
* blk_queue_enter() - try to increase q->q_usage_counter
* @q: request queue pointer
- * @flags: BLK_MQ_REQ_NOWAIT and/or BLK_MQ_REQ_PREEMPT
+ * @flags: BLK_MQ_REQ_NOWAIT and/or BLK_MQ_REQ_PM
*/
int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
{
- const bool pm = flags & BLK_MQ_REQ_PREEMPT;
+ const bool pm = flags & BLK_MQ_REQ_PM;
while (true) {
bool success = false;
@@ -440,7 +441,8 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
* responsible for ensuring that that counter is
* globally visible before the queue is unfrozen.
*/
- if (pm || !blk_queue_pm_only(q)) {
+ if ((pm && queue_rpm_status(q) != RPM_SUSPENDED) ||
+ !blk_queue_pm_only(q)) {
success = true;
} else {
percpu_ref_put(&q->q_usage_counter);
@@ -465,8 +467,7 @@ int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)
wait_event(q->mq_freeze_wq,
(!q->mq_freeze_depth &&
- (pm || (blk_pm_request_resume(q),
- !blk_queue_pm_only(q)))) ||
+ blk_pm_resume_queue(pm, q)) ||
blk_queue_dying(q));
if (blk_queue_dying(q))
return -ENODEV;
@@ -630,7 +631,7 @@ struct request *blk_get_request(struct request_queue *q, unsigned int op,
struct request *req;
WARN_ON_ONCE(op & REQ_NOWAIT);
- WARN_ON_ONCE(flags & ~(BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_PREEMPT));
+ WARN_ON_ONCE(flags & ~(BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_PM));
req = blk_mq_alloc_request(q, op, flags);
if (!IS_ERR(req) && q->mq_ops->initialize_rq_fn)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 3094542e12ae..4d6e83e5b442 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -129,6 +129,7 @@ static const char *const blk_queue_flag_name[] = {
QUEUE_FLAG_NAME(PCI_P2PDMA),
QUEUE_FLAG_NAME(ZONE_RESETALL),
QUEUE_FLAG_NAME(RQ_ALLOC_TIME),
+ QUEUE_FLAG_NAME(NOWAIT),
};
#undef QUEUE_FLAG_NAME
@@ -297,7 +298,6 @@ static const char *const rqf_name[] = {
RQF_NAME(MIXED_MERGE),
RQF_NAME(MQ_INFLIGHT),
RQF_NAME(DONTPREP),
- RQF_NAME(PREEMPT),
RQF_NAME(FAILED),
RQF_NAME(QUIET),
RQF_NAME(ELVPRIV),
diff --git a/block/blk-mq.c b/block/blk-mq.c
index c338c9bc5a2c..f285a9123a8b 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -294,8 +294,8 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
rq->mq_hctx = data->hctx;
rq->rq_flags = 0;
rq->cmd_flags = data->cmd_flags;
- if (data->flags & BLK_MQ_REQ_PREEMPT)
- rq->rq_flags |= RQF_PREEMPT;
+ if (data->flags & BLK_MQ_REQ_PM)
+ rq->rq_flags |= RQF_PM;
if (blk_queue_io_stat(data->q))
rq->rq_flags |= RQF_IO_STAT;
INIT_LIST_HEAD(&rq->queuelist);
diff --git a/block/blk-pm.c b/block/blk-pm.c
index b85234d758f7..17bd020268d4 100644
--- a/block/blk-pm.c
+++ b/block/blk-pm.c
@@ -67,6 +67,10 @@ int blk_pre_runtime_suspend(struct request_queue *q)
WARN_ON_ONCE(q->rpm_status != RPM_ACTIVE);
+ spin_lock_irq(&q->queue_lock);
+ q->rpm_status = RPM_SUSPENDING;
+ spin_unlock_irq(&q->queue_lock);
+
/*
* Increase the pm_only counter before checking whether any
* non-PM blk_queue_enter() calls are in progress to avoid that any
@@ -89,15 +93,14 @@ int blk_pre_runtime_suspend(struct request_queue *q)
/* Switch q_usage_counter back to per-cpu mode. */
blk_mq_unfreeze_queue(q);
- spin_lock_irq(&q->queue_lock);
- if (ret < 0)
+ if (ret < 0) {
+ spin_lock_irq(&q->queue_lock);
+ q->rpm_status = RPM_ACTIVE;
pm_runtime_mark_last_busy(q->dev);
- else
- q->rpm_status = RPM_SUSPENDING;
- spin_unlock_irq(&q->queue_lock);
+ spin_unlock_irq(&q->queue_lock);
- if (ret)
blk_clear_pm_only(q);
+ }
return ret;
}
diff --git a/block/blk-pm.h b/block/blk-pm.h
index ea5507d23e75..a2283cc9f716 100644
--- a/block/blk-pm.h
+++ b/block/blk-pm.h
@@ -6,11 +6,14 @@
#include <linux/pm_runtime.h>
#ifdef CONFIG_PM
-static inline void blk_pm_request_resume(struct request_queue *q)
+static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
{
- if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
- q->rpm_status == RPM_SUSPENDING))
- pm_request_resume(q->dev);
+ if (!q->dev || !blk_queue_pm_only(q))
+ return 1; /* Nothing to do */
+ if (pm && q->rpm_status != RPM_SUSPENDED)
+ return 1; /* Request allowed */
+ pm_request_resume(q->dev);
+ return 0;
}
static inline void blk_pm_mark_last_busy(struct request *rq)
@@ -44,8 +47,9 @@ static inline void blk_pm_put_request(struct request *rq)
--rq->q->nr_pending;
}
#else
-static inline void blk_pm_request_resume(struct request_queue *q)
+static inline int blk_pm_resume_queue(const bool pm, struct request_queue *q)
{
+ return 1;
}
static inline void blk_pm_mark_last_busy(struct request *rq)
diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c
index 4a4fde8dd12d..50683db99620 100644
--- a/drivers/clk/qcom/clk-cpu-8996.c
+++ b/drivers/clk/qcom/clk-cpu-8996.c
@@ -32,7 +32,9 @@
*
* The primary PLL is what drives the CPU clk, except for times
* when we are reprogramming the PLL itself (for rate changes) when
- * we temporarily switch to an alternate PLL.
+ * we temporarily switch to an alternate PLL. A subsequent patch adds
+ * support to switch between primary and alternate PLL during rate
+ * changes.
*
* The primary PLL operates on a single VCO range, between 600MHz
* and 3GHz. However the CPUs do support OPPs with frequencies
@@ -44,6 +46,7 @@
* Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk
* and for frequencies between 300MHz and 600MHz we follow
* Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk
+ * Support for this is added in a subsequent patch as well.
*
* ACD stands for Adaptive Clock Distribution and is used to
* detect voltage droops.
@@ -534,5 +537,6 @@ static struct platform_driver qcom_cpu_clk_msm8996_driver = {
};
module_platform_driver(qcom_cpu_clk_msm8996_driver);
+MODULE_ALIAS("platform:msm8996-apcc");
MODULE_DESCRIPTION("QCOM MSM8996 CPU Clock Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c
index 588575e1169d..6a05efaf8e10 100644
--- a/drivers/clk/qcom/dispcc-sm8250.c
+++ b/drivers/clk/qcom/dispcc-sm8250.c
@@ -1055,6 +1055,34 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev)
{
struct regmap *regmap;
+ if (of_property_read_bool(pdev->dev.of_node, "dpu-disable-interfaces")) {
+#define INTF_TIMING_ENGINE_EN 0x000
+#define INTF_MUX 0x25C
+ void *ptr;
+ u32 d;
+ int j, i;
+ phys_addr_t base[] = {
+ 0x6b000,
+ 0x6b800,
+ 0x6c000,
+ 0x6c800,
+ };
+ for (j = 0; j < ARRAY_SIZE(base); j++) {
+ pr_info("base %x\n", base[j]);
+ ptr = ioremap(0xae00000 + base[j], 0x800);
+ for (i = 0; i < 4; i++) {
+ pr_info("%d\n", i);
+ writel(0, ptr + INTF_TIMING_ENGINE_EN);
+ d = readl(ptr + INTF_MUX);
+ pr_info("%d: %x\n", i, d);
+ //writel(d | 0xf, ptr + INTF_MUX);
+ writel(0xf000f, ptr + INTF_MUX);
+ }
+ iounmap(ptr);
+ }
+ pr_err("DISABLED INTF!!!\n");
+ }
+
regmap = qcom_cc_map(pdev, &disp_cc_sm8250_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c
index 6cb6617b8d88..8e79d0077b55 100644
--- a/drivers/clk/qcom/gcc-sm8250.c
+++ b/drivers/clk/qcom/gcc-sm8250.c
@@ -188,6 +188,8 @@ static const struct clk_parent_data gcc_parent_data_5[] = {
static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
+ F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
{ }
};
@@ -722,7 +724,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
.name = "gcc_sdcc2_apps_clk_src",
.parent_data = gcc_parent_data_4,
.num_parents = 5,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
@@ -745,7 +747,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
.name = "gcc_sdcc4_apps_clk_src",
.parent_data = gcc_parent_data_0,
.num_parents = 3,
- .ops = &clk_rcg2_ops,
+ .ops = &clk_rcg2_floor_ops,
},
};
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6e23376548ce..1a660466dd75 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -3086,7 +3086,6 @@ static int __init intel_pstate_init(void)
intel_pstate.attr = hwp_cpufreq_attrs;
intel_cpufreq.attr = hwp_cpufreq_attrs;
intel_cpufreq.flags |= CPUFREQ_NEED_UPDATE_LIMITS;
- intel_cpufreq.fast_switch = NULL;
intel_cpufreq.adjust_perf = intel_cpufreq_adjust_perf;
if (!default_driver)
default_driver = &intel_pstate;
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 9ed5341dc515..dcc6546e2759 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -12,6 +12,7 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pm_opp.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#define LUT_MAX_ENTRIES 40U
@@ -32,6 +33,7 @@ struct qcom_cpufreq_soc_data {
struct qcom_cpufreq_data {
void __iomem *base;
+ struct regmap *regmap;
const struct qcom_cpufreq_soc_data *soc_data;
};
@@ -85,8 +87,11 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
struct qcom_cpufreq_data *data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
unsigned long freq = policy->freq_table[index].frequency;
+ int ret;
- writel_relaxed(index, data->base + soc_data->reg_perf_state);
+ ret = regmap_write(data->regmap, soc_data->reg_perf_state, index);
+ if (ret)
+ return ret;
if (icc_scaling_enabled)
qcom_cpufreq_set_bw(policy, freq);
@@ -100,6 +105,7 @@ static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
const struct qcom_cpufreq_soc_data *soc_data;
struct cpufreq_policy *policy;
unsigned int index;
+ int ret;
policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
@@ -108,7 +114,10 @@ static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
data = policy->driver_data;
soc_data = data->soc_data;
- index = readl_relaxed(data->base + soc_data->reg_perf_state);
+ ret = regmap_read(data->regmap, soc_data->reg_perf_state, &index);
+ if (ret)
+ return 0;
+
index = min(index, LUT_MAX_ENTRIES - 1);
return policy->freq_table[index].frequency;
@@ -120,9 +129,12 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
struct qcom_cpufreq_data *data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
unsigned int index;
+ int ret;
index = policy->cached_resolved_idx;
- writel_relaxed(index, data->base + soc_data->reg_perf_state);
+ ret = regmap_write(data->regmap, soc_data->reg_perf_state, index);
+ if (ret)
+ return 0;
return policy->freq_table[index].frequency;
}
@@ -164,14 +176,24 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
}
for (i = 0; i < LUT_MAX_ENTRIES; i++) {
- data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut +
- i * soc_data->lut_row_size);
+ ret = regmap_read(drv_data->regmap, soc_data->reg_freq_lut +
+ i * soc_data->lut_row_size, &data);
+ if (ret) {
+ kfree(table);
+ return ret;
+ }
+
src = FIELD_GET(LUT_SRC, data);
lval = FIELD_GET(LUT_L_VAL, data);
core_count = FIELD_GET(LUT_CORE_COUNT, data);
- data = readl_relaxed(drv_data->base + soc_data->reg_volt_lut +
- i * soc_data->lut_row_size);
+ ret = regmap_read(drv_data->regmap, soc_data->reg_volt_lut +
+ i * soc_data->lut_row_size, &data);
+ if (ret) {
+ kfree(table);
+ return ret;
+ }
+
volt = FIELD_GET(LUT_VOLT, data) * 1000;
if (src)
@@ -250,6 +272,13 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
}
}
+static struct regmap_config qcom_cpufreq_regmap = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+};
+
static const struct qcom_cpufreq_soc_data qcom_soc_data = {
.reg_enable = 0x0,
.reg_freq_lut = 0x110,
@@ -283,6 +312,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
void __iomem *base;
struct qcom_cpufreq_data *data;
int ret, index;
+ u32 val;
cpu_dev = get_cpu_device(policy->cpu);
if (!cpu_dev) {
@@ -315,9 +345,18 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
data->soc_data = of_device_get_match_data(&pdev->dev);
data->base = base;
+ data->regmap = devm_regmap_init_mmio(dev, base, &qcom_cpufreq_regmap);
+ if (IS_ERR(data->regmap)) {
+ ret = PTR_ERR(data->regmap);
+ goto error;
+ }
/* HW should be in enabled state to proceed */
- if (!(readl_relaxed(base + data->soc_data->reg_enable) & 0x1)) {
+ ret = regmap_read(data->regmap, data->soc_data->reg_enable, &val);
+ if (ret)
+ goto error;
+
+ if (!(val & 0x1)) {
dev_err(dev, "Domain-%d cpufreq hardware not enabled\n", index);
ret = -ENODEV;
goto error;
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 0c98d27f84ac..88630bc2921f 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -14,6 +14,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/wait.h>
+#include <linux/workqueue.h>
#include <sound/hdmi-codec.h>
@@ -36,6 +37,7 @@ struct lt9611uxc {
struct mutex ocm_lock;
struct wait_queue_head wq;
+ struct work_struct work;
struct device_node *dsi0_node;
struct device_node *dsi1_node;
@@ -52,6 +54,7 @@ struct lt9611uxc {
bool hpd_supported;
bool edid_read;
+ bool hdmi_connected;
uint8_t fw_version;
};
@@ -145,19 +148,32 @@ static irqreturn_t lt9611uxc_irq_thread_handler(int irq, void *dev_id)
lt9611uxc_unlock(lt9611uxc);
- if (irq_status & BIT(0))
+ if (irq_status & BIT(0)) {
lt9611uxc->edid_read = !!(hpd_status & BIT(0));
+ wake_up_all(&lt9611uxc->wq);
+ }
if (irq_status & BIT(1)) {
- if (lt9611uxc->connector.dev)
- drm_kms_helper_hotplug_event(lt9611uxc->connector.dev);
- else
- drm_bridge_hpd_notify(&lt9611uxc->bridge, !!(hpd_status & BIT(1)));
+ lt9611uxc->hdmi_connected = !!(hpd_status & BIT(1));
+ schedule_work(&lt9611uxc->work);
}
return IRQ_HANDLED;
}
+void lt9611uxc_hpd_work(struct work_struct *work)
+{
+ struct lt9611uxc *lt9611uxc = container_of(work, struct lt9611uxc, work);
+
+ if (lt9611uxc->connector.dev)
+ drm_kms_helper_hotplug_event(lt9611uxc->connector.dev);
+ else
+ drm_bridge_hpd_notify(&lt9611uxc->bridge,
+ lt9611uxc->hdmi_connected ?
+ connector_status_connected :
+ connector_status_disconnected);
+}
+
static void lt9611uxc_reset(struct lt9611uxc *lt9611uxc)
{
gpiod_set_value_cansleep(lt9611uxc->reset_gpio, 1);
@@ -445,7 +461,7 @@ static enum drm_connector_status lt9611uxc_bridge_detect(struct drm_bridge *brid
struct lt9611uxc *lt9611uxc = bridge_to_lt9611uxc(bridge);
unsigned int reg_val = 0;
int ret;
- int connected = 1;
+ bool connected = true;
if (lt9611uxc->hpd_supported) {
lt9611uxc_lock(lt9611uxc);
@@ -455,8 +471,9 @@ static enum drm_connector_status lt9611uxc_bridge_detect(struct drm_bridge *brid
if (ret)
dev_err(lt9611uxc->dev, "failed to read hpd status: %d\n", ret);
else
- connected = reg_val & BIT(1);
+ connected = !!(reg_val & BIT(1));
}
+ lt9611uxc->hdmi_connected = connected;
return connected ? connector_status_connected :
connector_status_disconnected;
@@ -465,7 +482,7 @@ static enum drm_connector_status lt9611uxc_bridge_detect(struct drm_bridge *brid
static int lt9611uxc_wait_for_edid(struct lt9611uxc *lt9611uxc)
{
return wait_event_interruptible_timeout(lt9611uxc->wq, lt9611uxc->edid_read,
- msecs_to_jiffies(100));
+ msecs_to_jiffies(500));
}
static int lt9611uxc_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
@@ -503,7 +520,10 @@ static struct edid *lt9611uxc_bridge_get_edid(struct drm_bridge *bridge,
ret = lt9611uxc_wait_for_edid(lt9611uxc);
if (ret < 0) {
dev_err(lt9611uxc->dev, "wait for EDID failed: %d\n", ret);
- return ERR_PTR(ret);
+ return NULL;
+ } else if (ret == 0) {
+ dev_err(lt9611uxc->dev, "wait for EDID timeout\n");
+ return NULL;
}
return drm_do_get_edid(connector, lt9611uxc_get_edid_block, lt9611uxc);
@@ -926,6 +946,8 @@ retry:
lt9611uxc->fw_version = ret;
init_waitqueue_head(&lt9611uxc->wq);
+ INIT_WORK(&lt9611uxc->work, lt9611uxc_hpd_work);
+
ret = devm_request_threaded_irq(dev, client->irq, NULL,
lt9611uxc_irq_thread_handler,
IRQF_ONESHOT, "lt9611uxc", lt9611uxc);
@@ -962,6 +984,7 @@ static int lt9611uxc_remove(struct i2c_client *client)
struct lt9611uxc *lt9611uxc = i2c_get_clientdata(client);
disable_irq(client->irq);
+ flush_scheduled_work();
lt9611uxc_audio_exit(lt9611uxc);
drm_bridge_remove(&lt9611uxc->bridge);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 90393fe9e59c..93c6184903b6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -21,6 +21,9 @@
#define VIG_SC7180_MASK \
(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED4))
+#define VIG_SM8250_MASK \
+ (VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3LITE))
+
#define DMA_SDM845_MASK \
(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) | BIT(DPU_SSPP_QOS_8LVL) |\
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
@@ -185,7 +188,7 @@ static const struct dpu_caps sm8150_dpu_caps = {
static const struct dpu_caps sm8250_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
- .qseed_type = DPU_SSPP_SCALER_QSEED3, /* TODO: qseed3 lite */
+ .qseed_type = DPU_SSPP_SCALER_QSEED3LITE,
.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
.ubwc_version = DPU_HW_UBWC_VER_40,
.has_src_split = true,
@@ -444,6 +447,34 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = {
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
+static const struct dpu_sspp_sub_blks sm8250_vig_sblk_0 =
+ _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE);
+static const struct dpu_sspp_sub_blks sm8250_vig_sblk_1 =
+ _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE);
+static const struct dpu_sspp_sub_blks sm8250_vig_sblk_2 =
+ _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE);
+static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 =
+ _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE);
+
+static const struct dpu_sspp_cfg sm8250_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK,
+ sm8250_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK,
+ sm8250_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
+ SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK,
+ sm8250_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
+ SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK,
+ sm8250_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+ SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,
+ sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
+ SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
+ SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
+};
+
/*************************************************************
* MIXER sub blocks config
*************************************************************/
@@ -969,9 +1000,8 @@ static void sm8250_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mdp = sm8250_mdp,
.ctl_count = ARRAY_SIZE(sm8150_ctl),
.ctl = sm8150_ctl,
- /* TODO: sspp qseed version differs from 845 */
- .sspp_count = ARRAY_SIZE(sdm845_sspp),
- .sspp = sdm845_sspp,
+ .sspp_count = ARRAY_SIZE(sm8250_sspp),
+ .sspp = sm8250_sspp,
.mixer_count = ARRAY_SIZE(sm8150_lm),
.mixer = sm8150_lm,
.dspp_count = ARRAY_SIZE(sm8150_dspp),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index eaef99db2d2f..ea4647d21a20 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -95,6 +95,7 @@ enum {
* @DPU_SSPP_SRC Src and fetch part of the pipes,
* @DPU_SSPP_SCALER_QSEED2, QSEED2 algorithm support
* @DPU_SSPP_SCALER_QSEED3, QSEED3 alogorithm support
+ * @DPU_SSPP_SCALER_QSEED3LITE, QSEED3 Lite alogorithm support
* @DPU_SSPP_SCALER_QSEED4, QSEED4 algorithm support
* @DPU_SSPP_SCALER_RGB, RGB Scaler, supported by RGB pipes
* @DPU_SSPP_CSC, Support of Color space converion
@@ -114,6 +115,7 @@ enum {
DPU_SSPP_SRC = 0x1,
DPU_SSPP_SCALER_QSEED2,
DPU_SSPP_SCALER_QSEED3,
+ DPU_SSPP_SCALER_QSEED3LITE,
DPU_SSPP_SCALER_QSEED4,
DPU_SSPP_SCALER_RGB,
DPU_SSPP_CSC,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 2c2ca5335aa8..34d81aa16041 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -673,6 +673,7 @@ static void _setup_layer_ops(struct dpu_hw_pipe *c,
c->ops.setup_multirect = dpu_hw_sspp_setup_multirect;
if (test_bit(DPU_SSPP_SCALER_QSEED3, &features) ||
+ test_bit(DPU_SSPP_SCALER_QSEED3LITE, &features) ||
test_bit(DPU_SSPP_SCALER_QSEED4, &features)) {
c->ops.setup_scaler = _dpu_hw_sspp_setup_scaler3;
c->ops.get_scaler_ver = _dpu_hw_sspp_get_scaler3_ver;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 85b018a9b03c..fdfd4b46e2c6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -28,6 +28,7 @@ struct dpu_hw_pipe;
#define DPU_SSPP_SCALER ((1UL << DPU_SSPP_SCALER_RGB) | \
(1UL << DPU_SSPP_SCALER_QSEED2) | \
(1UL << DPU_SSPP_SCALER_QSEED3) | \
+ (1UL << DPU_SSPP_SCALER_QSEED3LITE) | \
(1UL << DPU_SSPP_SCALER_QSEED4))
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
index 84e9875994a8..f94584c982cd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
@@ -59,6 +59,19 @@ static u32 dpu_hw_util_log_mask = DPU_DBG_MASK_NONE;
#define QSEED3_SEP_LUT_SIZE \
(QSEED3_LUT_SIZE * QSEED3_SEPARABLE_LUTS * sizeof(u32))
+/* DPU_SCALER_QSEED3LITE */
+#define QSEED3LITE_COEF_LUT_Y_SEP_BIT 4
+#define QSEED3LITE_COEF_LUT_UV_SEP_BIT 5
+#define QSEED3LITE_COEF_LUT_CTRL 0x4C
+#define QSEED3LITE_COEF_LUT_SWAP_BIT 0
+#define QSEED3LITE_DIR_FILTER_WEIGHT 0x60
+#define QSEED3LITE_FILTERS 2
+#define QSEED3LITE_SEPARABLE_LUTS 10
+#define QSEED3LITE_LUT_SIZE 33
+#define QSEED3LITE_SEP_LUT_SIZE \
+ (QSEED3LITE_LUT_SIZE * QSEED3LITE_SEPARABLE_LUTS * sizeof(u32))
+
+
void dpu_reg_write(struct dpu_hw_blk_reg_map *c,
u32 reg_off,
u32 val,
@@ -156,6 +169,57 @@ static void _dpu_hw_setup_scaler3_lut(struct dpu_hw_blk_reg_map *c,
}
+static void _dpu_hw_setup_scaler3lite_lut(struct dpu_hw_blk_reg_map *c,
+ struct dpu_hw_scaler3_cfg *scaler3_cfg, u32 offset)
+{
+ int j, filter;
+ int config_lut = 0x0;
+ unsigned long lut_flags;
+ u32 lut_addr, lut_offset;
+ u32 *lut[QSEED3LITE_FILTERS] = {NULL, NULL};
+ static const uint32_t off_tbl[QSEED3_FILTERS] = { 0x000, 0x200 };
+
+ DPU_REG_WRITE(c, QSEED3LITE_DIR_FILTER_WEIGHT + offset, scaler3_cfg->dir_weight);
+
+ if (!scaler3_cfg->sep_lut)
+ return;
+
+ lut_flags = (unsigned long) scaler3_cfg->lut_flag;
+ if (test_bit(QSEED3_COEF_LUT_Y_SEP_BIT, &lut_flags) &&
+ (scaler3_cfg->y_rgb_sep_lut_idx < QSEED3LITE_SEPARABLE_LUTS) &&
+ (scaler3_cfg->sep_len == QSEED3LITE_SEP_LUT_SIZE)) {
+ lut[0] = scaler3_cfg->sep_lut +
+ scaler3_cfg->y_rgb_sep_lut_idx * QSEED3LITE_LUT_SIZE;
+ config_lut = 1;
+ }
+ if (test_bit(QSEED3_COEF_LUT_UV_SEP_BIT, &lut_flags) &&
+ (scaler3_cfg->uv_sep_lut_idx < QSEED3LITE_SEPARABLE_LUTS) &&
+ (scaler3_cfg->sep_len == QSEED3LITE_SEP_LUT_SIZE)) {
+ lut[1] = scaler3_cfg->sep_lut +
+ scaler3_cfg->uv_sep_lut_idx * QSEED3LITE_LUT_SIZE;
+ config_lut = 1;
+ }
+
+ if (config_lut) {
+ for (filter = 0; filter < QSEED3LITE_FILTERS; filter++) {
+ if (!lut[filter])
+ continue;
+ lut_offset = 0;
+ lut_addr = QSEED3_COEF_LUT + offset + off_tbl[filter];
+ for (j = 0; j < QSEED3LITE_LUT_SIZE; j++) {
+ DPU_REG_WRITE(c,
+ lut_addr,
+ (lut[filter])[lut_offset++]);
+ lut_addr += 4;
+ }
+ }
+ }
+
+ if (test_bit(QSEED3_COEF_LUT_SWAP_BIT, &lut_flags))
+ DPU_REG_WRITE(c, QSEED3_COEF_LUT_CTRL + offset, BIT(0));
+
+}
+
static void _dpu_hw_setup_scaler3_de(struct dpu_hw_blk_reg_map *c,
struct dpu_hw_scaler3_de_cfg *de_cfg, u32 offset)
{
@@ -242,9 +306,12 @@ void dpu_hw_setup_scaler3(struct dpu_hw_blk_reg_map *c,
op_mode |= BIT(8);
}
- if (scaler3_cfg->lut_flag)
- _dpu_hw_setup_scaler3_lut(c, scaler3_cfg,
- scaler_offset);
+ if (scaler3_cfg->lut_flag) {
+ if (scaler_version < 0x2004)
+ _dpu_hw_setup_scaler3_lut(c, scaler3_cfg, scaler_offset);
+ else
+ _dpu_hw_setup_scaler3lite_lut(c, scaler3_cfg, scaler_offset);
+ }
if (scaler_version == 0x1002) {
phase_init =
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
index 234eb7d65753..ff3cffde84cd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
@@ -97,6 +97,7 @@ struct dpu_hw_scaler3_de_cfg {
* @ cir_lut: pointer to circular filter LUT
* @ sep_lut: pointer to separable filter LUT
* @ de: detail enhancer configuration
+ * @ dir_weight: Directional weight
*/
struct dpu_hw_scaler3_cfg {
u32 enable;
@@ -137,6 +138,8 @@ struct dpu_hw_scaler3_cfg {
* Detail enhancer settings
*/
struct dpu_hw_scaler3_de_cfg de;
+
+ u32 dir_weight;
};
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index bc0231a50132..f898a8f67b7f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1465,6 +1465,7 @@ static int _dpu_plane_init_debugfs(struct drm_plane *plane)
pdpu->debugfs_root, &pdpu->debugfs_src);
if (cfg->features & BIT(DPU_SSPP_SCALER_QSEED3) ||
+ cfg->features & BIT(DPU_SSPP_SCALER_QSEED3LITE) ||
cfg->features & BIT(DPU_SSPP_SCALER_QSEED2) ||
cfg->features & BIT(DPU_SSPP_SCALER_QSEED4)) {
dpu_debugfs_setup_regset32(&pdpu->debugfs_scaler,
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 627048851d99..22898f920a2c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -221,12 +221,7 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
goto fail;
}
- /*
- * check if the dsi encoder output is connected to a panel or an
- * external bridge. We create a connector only if we're connected to a
- * drm_panel device. When we're connected to an external bridge, we
- * assume that the drm_bridge driver will create the connector itself.
- */
+ /* Initialize the internal panel or external bridge */
ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host);
if (ext_bridge)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 1d28dfba2c9b..5bd1cfeb5fe2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*/
+#include <drm/drm_bridge_connector.h>
#include "msm_kms.h"
#include "dsi.h"
@@ -688,7 +689,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
bridge = &dsi_bridge->base;
bridge->funcs = &dsi_mgr_bridge_funcs;
- ret = drm_bridge_attach(encoder, bridge, NULL, 0);
+ ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
goto fail;
@@ -708,7 +709,6 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
struct drm_encoder *encoder;
struct drm_bridge *int_bridge, *ext_bridge;
struct drm_connector *connector;
- struct list_head *connector_list;
int_bridge = msm_dsi->bridge;
ext_bridge = msm_dsi->external_bridge =
@@ -716,22 +716,21 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
encoder = msm_dsi->encoder;
- /* link the internal dsi bridge to the external bridge */
- drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
-
- /*
- * we need the drm_connector created by the external bridge
- * driver (or someone else) to feed it to our driver's
- * priv->connector[] list, mainly for msm_fbdev_init()
+ /* link the internal dsi bridge to the external bridge and attach
+ * the connector, we are supporting DRM_BRIDGE_ATTACH_NO_CONNECTOR
+ * so always create connector
*/
- connector_list = &dev->mode_config.connector_list;
+ drm_bridge_attach(encoder, ext_bridge, int_bridge, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
- list_for_each_entry(connector, connector_list, head) {
- if (drm_connector_has_possible_encoder(connector, encoder))
- return connector;
+ connector = drm_bridge_connector_init(dev, encoder);
+ if (IS_ERR(connector)) {
+ DRM_DEV_ERROR(dev->dev, "drm_bridge_connector_init failed: %ld\n",
+ PTR_ERR(connector));
+ return ERR_PTR(-ENODEV);
}
- return ERR_PTR(-ENODEV);
+ drm_connector_attach_encoder(connector, msm_dsi->encoder);
+ return connector;
}
void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index e8c1a727179c..4eb1f121373f 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -723,6 +723,22 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
phy->pll = NULL;
}
+ /*
+ * As explained in msm_dsi_phy_enable, resetting the DSI PHY (as done
+ * in dsi_mgr_phy_enable) silently changes its PLL registers to power-on
+ * defaults, but the generic clock framework manages and caches several
+ * of the PLL registers. It initializes these caches at registration
+ * time via register read.
+ *
+ * As a result, we need to save DSI PLL registers once at probe in order
+ * for the first call to msm_dsi_phy_enable to successfully bring PLL
+ * registers back in line with what the generic clock framework expects.
+ *
+ * Subsequent PLL restores during msm_dsi_phy_enable will always be
+ * paired with PLL saves in msm_dsi_phy_disable.
+ */
+ msm_dsi_pll_save_state(phy->pll);
+
dsi_phy_disable_resource(phy);
platform_set_drvdata(pdev, phy);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 737453b6e596..bef6a698b1c4 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -28,6 +28,8 @@ void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
}
} else {
ctrl = HDMI_CTRL_HDMI;
+ if (hdmi->config->keep_ctrl_on)
+ ctrl |= HDMI_CTRL_ENABLE;
}
hdmi_write(hdmi, REG_HDMI_CTRL, ctrl);
@@ -407,6 +409,7 @@ static struct hdmi_platform_config hdmi_tx_8996_config = {
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
.hpd_freq = hpd_clk_freq_8x74,
+ .keep_ctrl_on = true,
};
static const struct {
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index d0b84f0abee1..2200dfffa13e 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -112,6 +112,9 @@ struct hdmi_platform_config {
/* gpio's: */
struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO];
+
+ /* caps, etc. */
+ bool keep_ctrl_on;
};
void msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index 58707a1f3878..7efef0eafed5 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -196,6 +196,13 @@ int msm_hdmi_hpd_enable(struct drm_connector *connector)
HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
spin_unlock_irqrestore(&hdmi->reg_lock, flags);
+ /*
+ * wait for a bit so that HPD is sensed if there is a cable already
+ * connected. Returning early will result in someone calling the
+ * connnector func's detect() callback too early
+ */
+ msleep(15);
+
return 0;
fail:
@@ -439,8 +446,7 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
hdmi->i2c);
drm_connector_helper_add(connector, &msm_hdmi_connector_helper_funcs);
- connector->polled = DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2162bc80f09e..013ad33fbbc8 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -223,7 +223,6 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
sense_rq->rq_disk = rq->rq_disk;
sense_rq->cmd_flags = REQ_OP_DRV_IN;
ide_req(sense_rq)->type = ATA_PRIV_SENSE;
- sense_rq->rq_flags |= RQF_PREEMPT;
req->cmd[0] = GPCMD_REQUEST_SENSE;
req->cmd[4] = cmd_len;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 1a53c7a75224..4867b67b60d6 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -515,15 +515,10 @@ repeat:
* above to return us whatever is in the queue. Since we call
* ide_do_request() ourselves, we end up taking requests while
* the queue is blocked...
- *
- * We let requests forced at head of queue with ide-preempt
- * though. I hope that doesn't happen too much, hopefully not
- * unless the subdriver triggers such a thing in its own PM
- * state machine.
*/
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
ata_pm_request(rq) == 0 &&
- (rq->rq_flags & RQF_PREEMPT) == 0) {
+ (rq->rq_flags & RQF_PM) == 0) {
/* there should be no pending command at this point */
ide_unlock_port(hwif);
goto plug_device;
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 192e6c65d34e..82ab308f1aaf 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -77,7 +77,7 @@ int generic_ide_resume(struct device *dev)
}
memset(&rqpm, 0, sizeof(rqpm));
- rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, BLK_MQ_REQ_PREEMPT);
+ rq = blk_get_request(drive->queue, REQ_OP_DRV_IN, BLK_MQ_REQ_PM);
ide_req(rq)->type = ATA_PRIV_PM_RESUME;
ide_req(rq)->special = &rqpm;
rqpm.pm_step = IDE_PM_START_RESUME;
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index d79335506ecd..28f93b9aa51b 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -963,6 +963,39 @@ static struct cpuidle_state dnv_cstates[] __initdata = {
.enter = NULL }
};
+/*
+ * Note, depending on HW and FW revision, SnowRidge SoC may or may not support
+ * C6, and this is indicated in the CPUID mwait leaf.
+ */
+static struct cpuidle_state snr_cstates[] __initdata = {
+ {
+ .name = "C1",
+ .desc = "MWAIT 0x00",
+ .flags = MWAIT2flg(0x00),
+ .exit_latency = 2,
+ .target_residency = 2,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .name = "C1E",
+ .desc = "MWAIT 0x01",
+ .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
+ .exit_latency = 15,
+ .target_residency = 25,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .name = "C6",
+ .desc = "MWAIT 0x20",
+ .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 130,
+ .target_residency = 500,
+ .enter = &intel_idle,
+ .enter_s2idle = intel_idle_s2idle, },
+ {
+ .enter = NULL }
+};
+
static const struct idle_cpu idle_cpu_nehalem __initconst = {
.state_table = nehalem_cstates,
.auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
@@ -1084,6 +1117,12 @@ static const struct idle_cpu idle_cpu_dnv __initconst = {
.use_acpi = true,
};
+static const struct idle_cpu idle_cpu_snr __initconst = {
+ .state_table = snr_cstates,
+ .disable_promotion_to_c1e = true,
+ .use_acpi = true,
+};
+
static const struct x86_cpu_id intel_idle_ids[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, &idle_cpu_nhx),
X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, &idle_cpu_nehalem),
@@ -1122,7 +1161,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &idle_cpu_bxt),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, &idle_cpu_bxt),
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_D, &idle_cpu_dnv),
- X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &idle_cpu_dnv),
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &idle_cpu_snr),
{}
};
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index c10aa28be70a..605b0c17d6ae 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -14,6 +14,7 @@
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -154,18 +155,6 @@ struct adc5_chip {
const struct adc5_data *data;
};
-static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
- {.num = 1, .den = 1},
- {.num = 1, .den = 3},
- {.num = 1, .den = 4},
- {.num = 1, .den = 6},
- {.num = 1, .den = 20},
- {.num = 1, .den = 8},
- {.num = 10, .den = 81},
- {.num = 1, .den = 10},
- {.num = 1, .den = 16}
-};
-
static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)
{
return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
@@ -181,55 +170,6 @@ static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val)
return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
}
-static int adc5_prescaling_from_dt(u32 num, u32 den)
-{
- unsigned int pre;
-
- for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++)
- if (adc5_prescale_ratios[pre].num == num &&
- adc5_prescale_ratios[pre].den == den)
- break;
-
- if (pre == ARRAY_SIZE(adc5_prescale_ratios))
- return -EINVAL;
-
- return pre;
-}
-
-static int adc5_hw_settle_time_from_dt(u32 value,
- const unsigned int *hw_settle)
-{
- unsigned int i;
-
- for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
- if (value == hw_settle[i])
- return i;
- }
-
- return -EINVAL;
-}
-
-static int adc5_avg_samples_from_dt(u32 value)
-{
- if (!is_power_of_2(value) || value > ADC5_AVG_SAMPLES_MAX)
- return -EINVAL;
-
- return __ffs(value);
-}
-
-static int adc5_decimation_from_dt(u32 value,
- const unsigned int *decimation)
-{
- unsigned int i;
-
- for (i = 0; i < ADC5_DECIMATION_SAMPLES_MAX; i++) {
- if (value == decimation[i])
- return i;
- }
-
- return -EINVAL;
-}
-
static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
{
int ret;
@@ -511,7 +451,7 @@ static int adc_read_raw_common(struct iio_dev *indio_dev,
return ret;
ret = qcom_adc5_hw_scale(prop->scale_fn_type,
- &adc5_prescale_ratios[prop->prescale],
+ prop->prescale,
adc->data,
adc_code_volt, val);
if (ret)
@@ -717,7 +657,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32(node, "qcom,decimation", &value);
if (!ret) {
- ret = adc5_decimation_from_dt(value, data->decimation);
+ ret = qcom_adc5_decimation_from_dt(value, data->decimation);
if (ret < 0) {
dev_err(dev, "%02x invalid decimation %d\n",
chan, value);
@@ -730,7 +670,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
if (!ret) {
- ret = adc5_prescaling_from_dt(varr[0], varr[1]);
+ ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]);
if (ret < 0) {
dev_err(dev, "%02x invalid pre-scaling <%d %d>\n",
chan, varr[0], varr[1]);
@@ -759,10 +699,10 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) ||
adc->data->info == &adc7_info)
- ret = adc5_hw_settle_time_from_dt(value,
+ ret = qcom_adc5_hw_settle_time_from_dt(value,
data->hw_settle_2);
else
- ret = adc5_hw_settle_time_from_dt(value,
+ ret = qcom_adc5_hw_settle_time_from_dt(value,
data->hw_settle_1);
if (ret < 0) {
@@ -777,7 +717,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32(node, "qcom,avg-samples", &value);
if (!ret) {
- ret = adc5_avg_samples_from_dt(value);
+ ret = qcom_adc5_avg_samples_from_dt(value);
if (ret < 0) {
dev_err(dev, "%02x invalid avg-samples %d\n",
chan, value);
@@ -870,8 +810,6 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
struct adc5_channel_prop prop, *chan_props;
struct device_node *child;
unsigned int index = 0;
- const struct of_device_id *id;
- const struct adc5_data *data;
int ret;
adc->nchannels = of_get_available_child_count(node);
@@ -890,24 +828,19 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
chan_props = adc->chan_props;
iio_chan = adc->iio_chans;
- id = of_match_node(adc5_match_table, node);
- if (id)
- data = id->data;
- else
- data = &adc5_data_pmic;
- adc->data = data;
+ adc->data = of_device_get_match_data(adc->dev);
for_each_available_child_of_node(node, child) {
- ret = adc5_get_dt_channel_data(adc, &prop, child, data);
+ ret = adc5_get_dt_channel_data(adc, &prop, child, adc->data);
if (ret) {
of_node_put(child);
return ret;
}
prop.scale_fn_type =
- data->adc_chans[prop.channel].scale_fn_type;
+ adc->data->adc_chans[prop.channel].scale_fn_type;
*chan_props = prop;
- adc_chan = &data->adc_chans[prop.channel];
+ adc_chan = &adc->data->adc_chans[prop.channel];
iio_chan->channel = prop.channel;
iio_chan->datasheet_name = prop.datasheet_name;
diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c
index 5113aaa6ba67..3d39e3406a7a 100644
--- a/drivers/iio/adc/qcom-vadc-common.c
+++ b/drivers/iio/adc/qcom-vadc-common.c
@@ -2,6 +2,7 @@
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
+#include <linux/fixp-arith.h>
#include <linux/math64.h>
#include <linux/log2.h>
#include <linux/err.h>
@@ -278,6 +279,18 @@ static const struct vadc_map_pt adcmap7_100k[] = {
{ 2420, 130048 }
};
+static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
+ {.num = 1, .den = 1},
+ {.num = 1, .den = 3},
+ {.num = 1, .den = 4},
+ {.num = 1, .den = 6},
+ {.num = 1, .den = 20},
+ {.num = 1, .den = 8},
+ {.num = 10, .den = 81},
+ {.num = 1, .den = 10},
+ {.num = 1, .den = 16}
+};
+
static int qcom_vadc_scale_hw_calib_volt(
const struct vadc_prescale_ratio *prescale,
const struct adc5_data *data,
@@ -356,15 +369,50 @@ static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
} else {
/* result is between search_index and search_index-1 */
/* interpolate linearly */
- *output = (((s32)((pts[i].y - pts[i - 1].y) *
- (input - pts[i - 1].x)) /
- (pts[i].x - pts[i - 1].x)) +
- pts[i - 1].y);
+ *output = fixp_linear_interpolate(pts[i - 1].x, pts[i - 1].y,
+ pts[i].x, pts[i].y, input);
}
return 0;
}
+static s32 qcom_vadc_map_temp_voltage(const struct vadc_map_pt *pts,
+ u32 tablesize, int input)
+{
+ bool descending = 1;
+ u32 i = 0;
+
+ /* Check if table is descending or ascending */
+ if (tablesize > 1) {
+ if (pts[0].y < pts[1].y)
+ descending = 0;
+ }
+
+ while (i < tablesize) {
+ if ((descending) && (pts[i].y < input)) {
+ /* table entry is less than measured*/
+ /* value and table is descending, stop */
+ break;
+ } else if ((!descending) &&
+ (pts[i].y > input)) {
+ /* table entry is greater than measured*/
+ /*value and table is ascending, stop */
+ break;
+ }
+ i++;
+ }
+
+ if (i == 0)
+ return pts[0].x;
+ if (i == tablesize)
+ return pts[tablesize - 1].x;
+
+ /* result is between search_index and search_index-1 */
+ /* interpolate linearly */
+ return fixp_linear_interpolate(pts[i - 1].y, pts[i - 1].x,
+ pts[i].y, pts[i].x, input);
+}
+
static void qcom_vadc_scale_calib(const struct vadc_linear_graph *calib_graph,
u16 adc_code,
bool absolute,
@@ -462,6 +510,19 @@ static int qcom_vadc_scale_chg_temp(const struct vadc_linear_graph *calib_graph,
return 0;
}
+static u16 qcom_vadc_scale_voltage_code(int voltage,
+ const struct vadc_prescale_ratio *prescale,
+ const u32 full_scale_code_volt,
+ unsigned int factor)
+{
+ s64 volt = voltage, adc_vdd_ref_mv = 1875;
+
+ volt *= prescale->num * factor * full_scale_code_volt;
+ volt = div64_s64(volt, (s64)prescale->den * adc_vdd_ref_mv * 1000);
+
+ return volt;
+}
+
static int qcom_vadc_scale_code_voltage_factor(u16 adc_code,
const struct vadc_prescale_ratio *prescale,
const struct adc5_data *data,
@@ -646,11 +707,26 @@ int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
}
EXPORT_SYMBOL(qcom_vadc_scale);
+u16 qcom_adc_tm5_temp_volt_scale(unsigned int prescale_ratio,
+ u32 full_scale_code_volt, int temp)
+{
+ const struct vadc_prescale_ratio *prescale = &adc5_prescale_ratios[prescale_ratio];
+ s32 voltage;
+
+ voltage = qcom_vadc_map_temp_voltage(adcmap_100k_104ef_104fb_1875_vref,
+ ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
+ temp);
+ return qcom_vadc_scale_voltage_code(voltage, prescale, full_scale_code_volt, 1000);
+}
+EXPORT_SYMBOL(qcom_adc_tm5_temp_volt_scale);
+
int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
- const struct vadc_prescale_ratio *prescale,
+ unsigned int prescale_ratio,
const struct adc5_data *data,
u16 adc_code, int *result)
{
+ const struct vadc_prescale_ratio *prescale = &adc5_prescale_ratios[prescale_ratio];
+
if (!(scaletype >= SCALE_HW_CALIB_DEFAULT &&
scaletype < SCALE_HW_CALIB_INVALID)) {
pr_err("Invalid scale type %d\n", scaletype);
@@ -662,6 +738,59 @@ int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
}
EXPORT_SYMBOL(qcom_adc5_hw_scale);
+int qcom_adc5_prescaling_from_dt(u32 num, u32 den)
+{
+ unsigned int pre;
+
+ for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++)
+ if (adc5_prescale_ratios[pre].num == num &&
+ adc5_prescale_ratios[pre].den == den)
+ break;
+
+ if (pre == ARRAY_SIZE(adc5_prescale_ratios))
+ return -EINVAL;
+
+ return pre;
+}
+EXPORT_SYMBOL(qcom_adc5_prescaling_from_dt);
+
+int qcom_adc5_hw_settle_time_from_dt(u32 value,
+ const unsigned int *hw_settle)
+{
+ unsigned int i;
+
+ for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
+ if (value == hw_settle[i])
+ return i;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(qcom_adc5_hw_settle_time_from_dt);
+
+int qcom_adc5_avg_samples_from_dt(u32 value)
+{
+ if (!is_power_of_2(value) || value > ADC5_AVG_SAMPLES_MAX)
+ return -EINVAL;
+
+ return __ffs(value);
+}
+EXPORT_SYMBOL(qcom_adc5_avg_samples_from_dt);
+
+int qcom_adc5_decimation_from_dt(u32 value,
+ const unsigned int *decimation)
+{
+ unsigned int i;
+
+ for (i = 0; i < ADC5_DECIMATION_SAMPLES_MAX; i++) {
+ if (value == decimation[i])
+ return i;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(qcom_adc5_decimation_from_dt);
+
int qcom_vadc_decimation_from_dt(u32 value)
{
if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||
diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h
index 17b2fc4d8bf2..aa3aef64d51e 100644
--- a/drivers/iio/adc/qcom-vadc-common.h
+++ b/drivers/iio/adc/qcom-vadc-common.h
@@ -168,10 +168,23 @@ struct qcom_adc5_scale_type {
};
int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
- const struct vadc_prescale_ratio *prescale,
+ unsigned int prescale_ratio,
const struct adc5_data *data,
u16 adc_code, int *result_mdec);
+u16 qcom_adc_tm5_temp_volt_scale(unsigned int prescale_ratio,
+ u32 full_scale_code_volt, int temp);
+
+int qcom_adc5_prescaling_from_dt(u32 num, u32 den);
+
+int qcom_adc5_hw_settle_time_from_dt(u32 value,
+ const unsigned int *hw_settle);
+
+int qcom_adc5_avg_samples_from_dt(u32 value);
+
+int qcom_adc5_decimation_from_dt(u32 value,
+ const unsigned int *decimation);
+
int qcom_vadc_decimation_from_dt(u32 value);
#endif /* QCOM_VADC_COMMON_H */
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 849d3c5f908e..d500648c586f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -803,6 +803,15 @@ config LEDS_POWERNV
To compile this driver as a module, choose 'm' here: the module
will be called leds-powernv.
+config LEDS_QCOM_LPG
+ tristate "LED support for Qualcomm LPG"
+ depends on LEDS_CLASS_MULTICOLOR
+ depends on OF
+ depends on SPMI
+ help
+ This option enables support for the Light Pulse Generator found in a
+ wide variety of Qualcomm PMICs.
+
config LEDS_SYSCON
bool "LED support for LEDs on system controllers"
depends on LEDS_CLASS=y
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 73e603e1727e..52d0ea26fc35 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o
obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o
obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o
obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
+obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o
obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o
diff --git a/drivers/leds/leds-qcom-lpg.c b/drivers/leds/leds-qcom-lpg.c
new file mode 100644
index 000000000000..4770fc46f312
--- /dev/null
+++ b/drivers/leds/leds-qcom-lpg.c
@@ -0,0 +1,1244 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2017-2020 Linaro Ltd
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ */
+#include <linux/bits.h>
+#include <linux/led-class-multicolor.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define LPG_PATTERN_CONFIG_REG 0x40
+#define LPG_SIZE_CLK_REG 0x41
+#define LPG_PREDIV_CLK_REG 0x42
+#define PWM_TYPE_CONFIG_REG 0x43
+#define PWM_VALUE_REG 0x44
+#define PWM_ENABLE_CONTROL_REG 0x46
+#define PWM_SYNC_REG 0x47
+#define LPG_RAMP_DURATION_REG 0x50
+#define LPG_HI_PAUSE_REG 0x52
+#define LPG_LO_PAUSE_REG 0x54
+#define LPG_HI_IDX_REG 0x56
+#define LPG_LO_IDX_REG 0x57
+#define PWM_SEC_ACCESS_REG 0xd0
+#define PWM_DTEST_REG(x) (0xe2 + (x) - 1)
+
+#define TRI_LED_SRC_SEL 0x45
+#define TRI_LED_EN_CTL 0x46
+#define TRI_LED_ATC_CTL 0x47
+
+#define LPG_LUT_REG(x) (0x40 + (x) * 2)
+#define RAMP_CONTROL_REG 0xc8
+
+struct lpg_channel;
+struct lpg_data;
+
+/**
+ * struct lpg - LPG device context
+ * @dev: struct device for LPG device
+ * @map: regmap for register access
+ * @pwm: PWM-chip object, if operating in PWM mode
+ * @lut_base: base address of the LUT block (optional)
+ * @lut_size: number of entries in the LUT block
+ * @lut_bitmap: allocation bitmap for LUT entries
+ * @triled_base: base address of the TRILED block (optional)
+ * @triled_src: power-source for the TRILED
+ * @triled_has_atc_ctl: true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel: true if there is TRI_LED_SRC_SEL register
+ * @channels: list of PWM channels
+ * @num_channels: number of @channels
+ */
+struct lpg {
+ struct device *dev;
+ struct regmap *map;
+
+ struct pwm_chip pwm;
+
+ const struct lpg_data *data;
+
+ u32 lut_base;
+ u32 lut_size;
+ unsigned long *lut_bitmap;
+
+ u32 triled_base;
+ u32 triled_src;
+ bool triled_has_atc_ctl;
+ bool triled_has_src_sel;
+
+ struct lpg_channel *channels;
+ unsigned int num_channels;
+};
+
+/**
+ * struct lpg_channel - per channel data
+ * @lpg: reference to parent lpg
+ * @base: base address of the PWM channel
+ * @triled_mask: mask in TRILED to enable this channel
+ * @lut_mask: mask in LUT to start pattern generator for this channel
+ * @in_use: channel is exposed to LED framework
+ * @color: color of the LED attached to this channel
+ * @dtest_line: DTEST line for output, or 0 if disabled
+ * @dtest_value: DTEST line configuration
+ * @pwm_value: duty (in microseconds) of the generated pulses, overridden by LUT
+ * @enabled: output enabled?
+ * @period_us: period (in microseconds) of the generated pulses
+ * @pwm_size: resolution of the @pwm_value, 6 or 9 bits
+ * @clk: base frequency of the clock generator
+ * @pre_div: divider of @clk
+ * @pre_div_exp: exponential divider of @clk
+ * @ramp_enabled: duty cycle is driven by iterating over lookup table
+ * @ramp_ping_pong: reverse through pattern, rather than wrapping to start
+ * @ramp_oneshot: perform only a single pass over the pattern
+ * @ramp_reverse: iterate over pattern backwards
+ * @ramp_duration_ms: length (in milliseconds) of one pattern run
+ * @ramp_lo_pause_ms: pause (in milliseconds) before iterating over pattern
+ * @ramp_hi_pause_ms: pause (in milliseconds) after iterating over pattern
+ * @pattern_lo_idx: start index of associated pattern
+ * @pattern_hi_idx: last index of associated pattern
+ */
+struct lpg_channel {
+ struct lpg *lpg;
+
+ u32 base;
+ unsigned int triled_mask;
+ unsigned int lut_mask;
+
+ bool in_use;
+
+ int color;
+
+ u32 dtest_line;
+ u32 dtest_value;
+
+ u16 pwm_value;
+ bool enabled;
+
+ unsigned int period_us;
+ unsigned int pwm_size;
+ unsigned int clk;
+ unsigned int pre_div;
+ unsigned int pre_div_exp;
+
+ bool ramp_enabled;
+ bool ramp_ping_pong;
+ bool ramp_oneshot;
+ bool ramp_reverse;
+ unsigned long ramp_duration_ms;
+ unsigned long ramp_lo_pause_ms;
+ unsigned long ramp_hi_pause_ms;
+
+ unsigned int pattern_lo_idx;
+ unsigned int pattern_hi_idx;
+};
+
+/**
+ * struct lpg_led - logical LED object
+ * @lpg: lpg context reference
+ * @cdev: LED class device
+ * @mcdev: Multicolor LED class device
+ * @num_channels: number of @channels
+ * @channels: list of channels associated with the LED
+ */
+struct lpg_led {
+ struct lpg *lpg;
+
+ struct led_classdev cdev;
+ struct led_classdev_mc mcdev;
+
+ unsigned int num_channels;
+ struct lpg_channel *channels[];
+};
+
+/**
+ * struct lpg_channel_data - per channel initialization data
+ * @base: base address for PWM channel registers
+ * @triled_mask: bitmask for controlling this channel in TRILED
+ */
+struct lpg_channel_data {
+ unsigned int base;
+ u8 triled_mask;
+};
+
+/**
+ * struct lpg_data - initialization data
+ * @lut_base: base address of LUT block
+ * @lut_size: number of entries in LUT
+ * @triled_base: base address of TRILED
+ * @triled_has_atc_ctl: true if there is TRI_LED_ATC_CTL register
+ * @triled_has_src_sel: true if there is TRI_LED_SRC_SEL register
+ * @pwm_9bit_mask: bitmask for switching from 6bit to 9bit pwm
+ * @num_channels: number of channels in LPG
+ * @channels: list of channel initialization data
+ */
+struct lpg_data {
+ unsigned int lut_base;
+ unsigned int lut_size;
+ unsigned int triled_base;
+ bool triled_has_atc_ctl;
+ bool triled_has_src_sel;
+ unsigned int pwm_9bit_mask;
+ int num_channels;
+ struct lpg_channel_data *channels;
+};
+
+static int triled_set(struct lpg *lpg, unsigned int mask, unsigned int enable)
+{
+ /* Skip if we don't have a triled block */
+ if (!lpg->triled_base)
+ return 0;
+
+ return regmap_update_bits(lpg->map, lpg->triled_base + TRI_LED_EN_CTL,
+ mask, enable);
+}
+
+static int lpg_lut_store(struct lpg *lpg, struct led_pattern *pattern,
+ size_t len, unsigned int *lo_idx, unsigned int *hi_idx)
+{
+ unsigned int idx;
+ __le16 val;
+ int i;
+
+ /* Hardware does not behave when LO_IDX == HI_IDX */
+ if (len == 1)
+ return -EINVAL;
+
+ idx = bitmap_find_next_zero_area(lpg->lut_bitmap, lpg->lut_size,
+ 0, len, 0);
+ if (idx >= lpg->lut_size)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ val = cpu_to_le16(pattern[i].brightness);
+
+ regmap_bulk_write(lpg->map, lpg->lut_base + LPG_LUT_REG(idx + i),
+ &val, sizeof(val));
+ }
+
+ bitmap_set(lpg->lut_bitmap, idx, len);
+
+ *lo_idx = idx;
+ *hi_idx = idx + len - 1;
+
+ return 0;
+}
+
+static void lpg_lut_free(struct lpg *lpg, unsigned int lo_idx, unsigned int hi_idx)
+{
+ int len;
+
+ if (lo_idx == hi_idx)
+ return;
+
+ len = hi_idx - lo_idx + 1;
+ bitmap_clear(lpg->lut_bitmap, lo_idx, len);
+}
+
+static int lpg_lut_sync(struct lpg *lpg, unsigned int mask)
+{
+ return regmap_write(lpg->map, lpg->lut_base + RAMP_CONTROL_REG, mask);
+}
+
+#define NUM_PWM_PREDIV 4
+#define NUM_PWM_CLK 3
+#define NUM_EXP 7
+
+static const unsigned int lpg_clk_table[NUM_PWM_PREDIV][NUM_PWM_CLK] = {
+ {
+ 1 * (NSEC_PER_SEC / 1024),
+ 1 * (NSEC_PER_SEC / 32768),
+ 1 * (NSEC_PER_SEC / 19200000),
+ },
+ {
+ 3 * (NSEC_PER_SEC / 1024),
+ 3 * (NSEC_PER_SEC / 32768),
+ 3 * (NSEC_PER_SEC / 19200000),
+ },
+ {
+ 5 * (NSEC_PER_SEC / 1024),
+ 5 * (NSEC_PER_SEC / 32768),
+ 5 * (NSEC_PER_SEC / 19200000),
+ },
+ {
+ 6 * (NSEC_PER_SEC / 1024),
+ 6 * (NSEC_PER_SEC / 32768),
+ 6 * (NSEC_PER_SEC / 19200000),
+ },
+};
+
+/*
+ * PWM Frequency = Clock Frequency / (N * T)
+ * or
+ * PWM Period = Clock Period * (N * T)
+ * where
+ * N = 2^9 or 2^6 for 9-bit or 6-bit PWM size
+ * T = Pre-divide * 2^m, where m = 0..7 (exponent)
+ *
+ * This is the formula to figure out m for the best pre-divide and clock:
+ * (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
+ */
+static void lpg_calc_freq(struct lpg_channel *chan, unsigned int period_us)
+{
+ int n, m, clk, div;
+ int best_m, best_div, best_clk;
+ unsigned int last_err, cur_err, min_err;
+ unsigned int tmp_p, period_n;
+
+ if (period_us == chan->period_us)
+ return;
+
+ /* PWM Period / N */
+ if (period_us < UINT_MAX / NSEC_PER_USEC)
+ n = 6;
+ else
+ n = 9;
+
+ period_n = ((u64)period_us * NSEC_PER_USEC) >> n;
+
+ min_err = UINT_MAX;
+ last_err = UINT_MAX;
+ best_m = 0;
+ best_clk = 0;
+ best_div = 0;
+ for (clk = 0; clk < NUM_PWM_CLK; clk++) {
+ for (div = 0; div < NUM_PWM_PREDIV; div++) {
+ /* period_n = (PWM Period / N) */
+ /* tmp_p = (Pre-divide * Clock Period) * 2^m */
+ tmp_p = lpg_clk_table[div][clk];
+ for (m = 0; m <= NUM_EXP; m++) {
+ cur_err = abs(period_n - tmp_p);
+ if (cur_err < min_err) {
+ min_err = cur_err;
+ best_m = m;
+ best_clk = clk;
+ best_div = div;
+ }
+
+ if (m && cur_err > last_err)
+ /* Break for bigger cur_err */
+ break;
+
+ last_err = cur_err;
+ tmp_p <<= 1;
+ }
+ }
+ }
+
+ /* Use higher resolution */
+ if (best_m >= 3 && n == 6) {
+ n += 3;
+ best_m -= 3;
+ }
+
+ chan->clk = best_clk;
+ chan->pre_div = best_div;
+ chan->pre_div_exp = best_m;
+ chan->pwm_size = n;
+
+ chan->period_us = period_us;
+}
+
+static void lpg_calc_duty(struct lpg_channel *chan, unsigned int duty_us)
+{
+ unsigned int max = (1 << chan->pwm_size) - 1;
+ unsigned int val = div_u64((u64)duty_us << chan->pwm_size, chan->period_us);
+
+ chan->pwm_value = min(val, max);
+}
+
+static void lpg_apply_freq(struct lpg_channel *chan)
+{
+ unsigned long val;
+ struct lpg *lpg = chan->lpg;
+
+ if (!chan->enabled)
+ return;
+
+ /* Clock register values are off-by-one from lpg_clk_table */
+ val = chan->clk + 1;
+
+ if (chan->pwm_size == 9)
+ val |= lpg->data->pwm_9bit_mask;
+
+ regmap_write(lpg->map, chan->base + LPG_SIZE_CLK_REG, val);
+
+ val = chan->pre_div << 5 | chan->pre_div_exp;
+ regmap_write(lpg->map, chan->base + LPG_PREDIV_CLK_REG, val);
+}
+
+#define LPG_ENABLE_GLITCH_REMOVAL BIT(5)
+
+static void lpg_enable_glitch(struct lpg_channel *chan)
+{
+ struct lpg *lpg = chan->lpg;
+
+ regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
+ LPG_ENABLE_GLITCH_REMOVAL, 0);
+}
+
+static void lpg_disable_glitch(struct lpg_channel *chan)
+{
+ struct lpg *lpg = chan->lpg;
+
+ regmap_update_bits(lpg->map, chan->base + PWM_TYPE_CONFIG_REG,
+ LPG_ENABLE_GLITCH_REMOVAL,
+ LPG_ENABLE_GLITCH_REMOVAL);
+}
+
+static void lpg_apply_pwm_value(struct lpg_channel *chan)
+{
+ __le16 val = cpu_to_le16(chan->pwm_value);
+ struct lpg *lpg = chan->lpg;
+
+ if (!chan->enabled)
+ return;
+
+ regmap_bulk_write(lpg->map, chan->base + PWM_VALUE_REG, &val, sizeof(val));
+}
+
+#define LPG_PATTERN_CONFIG_LO_TO_HI BIT(4)
+#define LPG_PATTERN_CONFIG_REPEAT BIT(3)
+#define LPG_PATTERN_CONFIG_TOGGLE BIT(2)
+#define LPG_PATTERN_CONFIG_PAUSE_HI BIT(1)
+#define LPG_PATTERN_CONFIG_PAUSE_LO BIT(0)
+
+static void lpg_apply_lut_control(struct lpg_channel *chan)
+{
+ struct lpg *lpg = chan->lpg;
+ unsigned int hi_pause;
+ unsigned int lo_pause;
+ unsigned int step;
+ unsigned int conf = 0;
+ unsigned int lo_idx = chan->pattern_lo_idx;
+ unsigned int hi_idx = chan->pattern_hi_idx;
+ int pattern_len;
+
+ if (!chan->ramp_enabled || chan->pattern_lo_idx == chan->pattern_hi_idx)
+ return;
+
+ pattern_len = hi_idx - lo_idx + 1;
+
+ step = DIV_ROUND_UP(chan->ramp_duration_ms, pattern_len);
+ hi_pause = DIV_ROUND_UP(chan->ramp_hi_pause_ms, step);
+ lo_pause = DIV_ROUND_UP(chan->ramp_lo_pause_ms, step);
+
+ if (!chan->ramp_reverse)
+ conf |= LPG_PATTERN_CONFIG_LO_TO_HI;
+ if (!chan->ramp_oneshot)
+ conf |= LPG_PATTERN_CONFIG_REPEAT;
+ if (chan->ramp_ping_pong)
+ conf |= LPG_PATTERN_CONFIG_TOGGLE;
+ if (chan->ramp_hi_pause_ms)
+ conf |= LPG_PATTERN_CONFIG_PAUSE_HI;
+ if (chan->ramp_lo_pause_ms)
+ conf |= LPG_PATTERN_CONFIG_PAUSE_LO;
+
+ regmap_write(lpg->map, chan->base + LPG_PATTERN_CONFIG_REG, conf);
+ regmap_write(lpg->map, chan->base + LPG_HI_IDX_REG, hi_idx);
+ regmap_write(lpg->map, chan->base + LPG_LO_IDX_REG, lo_idx);
+
+ regmap_write(lpg->map, chan->base + LPG_RAMP_DURATION_REG, step);
+ regmap_write(lpg->map, chan->base + LPG_HI_PAUSE_REG, hi_pause);
+ regmap_write(lpg->map, chan->base + LPG_LO_PAUSE_REG, lo_pause);
+}
+
+#define LPG_ENABLE_CONTROL_OUTPUT BIT(7)
+#define LPG_ENABLE_CONTROL_BUFFER_TRISTATE BIT(5)
+#define LPG_ENABLE_CONTROL_SRC_PWM BIT(2)
+#define LPG_ENABLE_CONTROL_RAMP_GEN BIT(1)
+
+static void lpg_apply_control(struct lpg_channel *chan)
+{
+ unsigned int ctrl;
+ struct lpg *lpg = chan->lpg;
+
+ ctrl = LPG_ENABLE_CONTROL_BUFFER_TRISTATE;
+
+ if (chan->enabled)
+ ctrl |= LPG_ENABLE_CONTROL_OUTPUT;
+
+ if (chan->pattern_lo_idx != chan->pattern_hi_idx)
+ ctrl |= LPG_ENABLE_CONTROL_RAMP_GEN;
+ else
+ ctrl |= LPG_ENABLE_CONTROL_SRC_PWM;
+
+ regmap_write(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, ctrl);
+
+ /*
+ * Due to LPG hardware bug, in the PWM mode, having enabled PWM,
+ * We have to write PWM values one more time.
+ */
+ if (chan->enabled)
+ lpg_apply_pwm_value(chan);
+}
+
+#define LPG_SYNC_PWM BIT(0)
+
+static void lpg_apply_sync(struct lpg_channel *chan)
+{
+ struct lpg *lpg = chan->lpg;
+
+ regmap_write(lpg->map, chan->base + PWM_SYNC_REG, LPG_SYNC_PWM);
+}
+
+static void lpg_apply_dtest(struct lpg_channel *chan)
+{
+ struct lpg *lpg = chan->lpg;
+
+ if (!chan->dtest_line)
+ return;
+
+ regmap_write(lpg->map, chan->base + PWM_SEC_ACCESS_REG, 0xa5);
+ regmap_write(lpg->map, chan->base + PWM_DTEST_REG(chan->dtest_line),
+ chan->dtest_value);
+}
+
+static void lpg_apply(struct lpg_channel *chan)
+{
+ lpg_disable_glitch(chan);
+ lpg_apply_freq(chan);
+ lpg_apply_pwm_value(chan);
+ lpg_apply_control(chan);
+ lpg_apply_sync(chan);
+ lpg_apply_lut_control(chan);
+ lpg_enable_glitch(chan);
+}
+
+static void lpg_brightness_set(struct lpg_led *led, struct led_classdev *cdev,
+ struct mc_subled *subleds)
+{
+ enum led_brightness brightness;
+ struct lpg_channel *chan;
+ unsigned int triled_enabled = 0;
+ unsigned int triled_mask = 0;
+ unsigned int lut_mask = 0;
+ unsigned int duty_us;
+ struct lpg *lpg = led->lpg;
+ int i;
+
+ for (i = 0; i < led->num_channels; i++) {
+ chan = led->channels[i];
+ brightness = subleds[i].brightness;
+
+ if (brightness == LED_OFF) {
+ chan->enabled = false;
+ chan->ramp_enabled = false;
+ } else if (chan->pattern_lo_idx != chan->pattern_hi_idx) {
+ lpg_calc_freq(chan, NSEC_PER_USEC);
+
+ chan->enabled = true;
+ chan->ramp_enabled = true;
+
+ lut_mask |= chan->lut_mask;
+ triled_enabled |= chan->triled_mask;
+ } else {
+ lpg_calc_freq(chan, NSEC_PER_USEC);
+
+ duty_us = brightness * chan->period_us / cdev->max_brightness;
+ lpg_calc_duty(chan, duty_us);
+ chan->enabled = true;
+ chan->ramp_enabled = false;
+
+ triled_enabled |= chan->triled_mask;
+ }
+
+ triled_mask |= chan->triled_mask;
+
+ lpg_apply(chan);
+ }
+
+ /* Toggle triled lines */
+ if (triled_mask)
+ triled_set(lpg, triled_mask, triled_enabled);
+
+ /* Trigger start of ramp generator(s) */
+ if (lut_mask)
+ lpg_lut_sync(lpg, lut_mask);
+}
+
+static void lpg_brightness_single_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+ struct mc_subled info;
+
+ info.brightness = value;
+ lpg_brightness_set(led, cdev, &info);
+}
+
+static void lpg_brightness_mc_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+ struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+ led_mc_calc_color_components(mc, value);
+ lpg_brightness_set(led, cdev, mc->subled_info);
+}
+
+static int lpg_blink_set(struct lpg_led *led,
+ unsigned long delay_on, unsigned long delay_off)
+{
+ struct lpg_channel *chan;
+ unsigned int period_us;
+ unsigned int duty_us;
+ int i;
+
+ if (!delay_on && !delay_off) {
+ delay_on = 500;
+ delay_off = 500;
+ }
+
+ duty_us = delay_on * USEC_PER_MSEC;
+ period_us = (delay_on + delay_off) * USEC_PER_MSEC;
+
+ for (i = 0; i < led->num_channels; i++) {
+ chan = led->channels[i];
+
+ lpg_calc_freq(chan, period_us);
+ lpg_calc_duty(chan, duty_us);
+
+ chan->enabled = true;
+ chan->ramp_enabled = false;
+
+ lpg_apply(chan);
+ }
+
+ return 0;
+}
+
+static int lpg_blink_single_set(struct led_classdev *cdev,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+
+ return lpg_blink_set(led, *delay_on, *delay_off);
+}
+
+static int lpg_blink_mc_set(struct led_classdev *cdev,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+ struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+ return lpg_blink_set(led, *delay_on, *delay_off);
+}
+
+static int lpg_pattern_set(struct lpg_led *led, struct led_pattern *pattern,
+ u32 len, int repeat)
+{
+ struct lpg_channel *chan;
+ struct lpg *lpg = led->lpg;
+ unsigned int hi_pause;
+ unsigned int lo_pause;
+ unsigned int lo_idx;
+ unsigned int hi_idx;
+ bool ping_pong = true;
+ int brightness_a;
+ int brightness_b;
+ int ret;
+ int i;
+
+ /* Only support oneshot or indefinite loops, due to limited pattern space */
+ if (repeat != -1 && repeat != 1)
+ return -EINVAL;
+
+ /*
+ * The LPG plays patterns with at a fixed pace, a "low pause" can be
+ * performed before the pattern and a "high pause" after. In order to
+ * save space the pattern can be played in "ping pong" mode, in which
+ * the pattern is first played forward, then "high pause" is applied,
+ * then the pattern is played backwards and finally the "low pause" is
+ * applied.
+ *
+ * The delta_t of the first entry is used to determine the pace of the
+ * pattern.
+ *
+ * If the specified pattern is a palindrome the ping pong mode is
+ * enabled. In this scenario the delta_t of the last entry determines
+ * the "low pause" time and the delta_t of the middle entry (i.e. the
+ * last in the programmed pattern) determines the "high pause". If the
+ * pattern consists of an odd number of values, no "high pause" is
+ * used.
+ *
+ * When ping pong mode is not selected, the delta_t of the last entry
+ * is used as "high pause". No "low pause" is used.
+ *
+ * delta_t of any other members of the pattern is ignored.
+ */
+
+ /* Detect palindromes and use "ping pong" to reduce LUT usage */
+ for (i = 0; i < len / 2; i++) {
+ brightness_a = pattern[i].brightness;
+ brightness_b = pattern[len - i - 1].brightness;
+
+ if (brightness_a != brightness_b) {
+ ping_pong = false;
+ break;
+ }
+ }
+
+ if (ping_pong) {
+ if (len % 2)
+ hi_pause = 0;
+ else
+ hi_pause = pattern[len + 1 / 2].delta_t;
+ lo_pause = pattern[len - 1].delta_t;
+
+ len = (len + 1) / 2;
+ } else {
+ hi_pause = pattern[len - 1].delta_t;
+ lo_pause = 0;
+ }
+
+ ret = lpg_lut_store(lpg, pattern, len, &lo_idx, &hi_idx);
+ if (ret < 0)
+ goto out;
+
+ for (i = 0; i < led->num_channels; i++) {
+ chan = led->channels[i];
+
+ chan->ramp_duration_ms = pattern[0].delta_t * len;
+ chan->ramp_ping_pong = ping_pong;
+ chan->ramp_oneshot = repeat != -1;
+
+ chan->ramp_lo_pause_ms = lo_pause;
+ chan->ramp_hi_pause_ms = hi_pause;
+
+ chan->pattern_lo_idx = lo_idx;
+ chan->pattern_hi_idx = hi_idx;
+ }
+
+out:
+ return ret;
+}
+
+static int lpg_pattern_single_set(struct led_classdev *cdev,
+ struct led_pattern *pattern, u32 len,
+ int repeat)
+{
+ struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+ int ret;
+
+ ret = lpg_pattern_set(led, pattern, len, repeat);
+ if (ret < 0)
+ return ret;
+
+ lpg_brightness_single_set(cdev, LED_FULL);
+
+ return 0;
+}
+
+static int lpg_pattern_mc_set(struct led_classdev *cdev,
+ struct led_pattern *pattern, u32 len,
+ int repeat)
+{
+ struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+ struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+ int ret;
+
+ ret = lpg_pattern_set(led, pattern, len, repeat);
+ if (ret < 0)
+ return ret;
+
+ led_mc_calc_color_components(mc, LED_FULL);
+ lpg_brightness_set(led, cdev, mc->subled_info);
+
+ return 0;
+}
+
+static int lpg_pattern_clear(struct lpg_led *led)
+{
+ struct lpg_channel *chan;
+ struct lpg *lpg = led->lpg;
+ int i;
+
+ chan = led->channels[0];
+ lpg_lut_free(lpg, chan->pattern_lo_idx, chan->pattern_hi_idx);
+
+ for (i = 0; i < led->num_channels; i++) {
+ chan = led->channels[i];
+ chan->pattern_lo_idx = 0;
+ chan->pattern_hi_idx = 0;
+ }
+
+ return 0;
+}
+
+static int lpg_pattern_single_clear(struct led_classdev *cdev)
+{
+ struct lpg_led *led = container_of(cdev, struct lpg_led, cdev);
+
+ return lpg_pattern_clear(led);
+}
+
+static int lpg_pattern_mc_clear(struct led_classdev *cdev)
+{
+ struct led_classdev_mc *mc = lcdev_to_mccdev(cdev);
+ struct lpg_led *led = container_of(mc, struct lpg_led, mcdev);
+
+ return lpg_pattern_clear(led);
+}
+
+static int lpg_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct lpg *lpg = container_of(chip, struct lpg, pwm);
+ struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
+
+ return chan->in_use ? -EBUSY : 0;
+}
+
+static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct lpg *lpg = container_of(chip, struct lpg, pwm);
+ struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
+
+ lpg_calc_freq(chan, div_u64(state->period, NSEC_PER_USEC));
+ lpg_calc_duty(chan, div_u64(state->duty_cycle, NSEC_PER_USEC));
+ chan->enabled = state->enabled;
+
+ lpg_apply(chan);
+
+ triled_set(lpg, chan->triled_mask, chan->enabled ? chan->triled_mask : 0);
+
+ return 0;
+}
+
+static const struct pwm_ops lpg_pwm_ops = {
+ .request = lpg_pwm_request,
+ .apply = lpg_pwm_apply,
+ .owner = THIS_MODULE,
+};
+
+static int lpg_add_pwm(struct lpg *lpg)
+{
+ int ret;
+
+ lpg->pwm.base = -1;
+ lpg->pwm.dev = lpg->dev;
+ lpg->pwm.npwm = lpg->num_channels;
+ lpg->pwm.ops = &lpg_pwm_ops;
+
+ ret = pwmchip_add(&lpg->pwm);
+ if (ret)
+ dev_err(lpg->dev, "failed to add PWM chip: ret %d\n", ret);
+
+ return ret;
+}
+
+static int lpg_parse_channel(struct lpg *lpg, struct device_node *np,
+ struct lpg_channel **channel)
+{
+ struct lpg_channel *chan;
+ u32 dtest[2];
+ u32 color = LED_COLOR_ID_GREEN;
+ u32 reg;
+ int ret;
+
+ ret = of_property_read_u32(np, "reg", &reg);
+ if (ret || !reg || reg > lpg->num_channels) {
+ dev_err(lpg->dev, "invalid reg of %pOFn\n", np);
+ return -EINVAL;
+ }
+
+ chan = &lpg->channels[reg - 1];
+ chan->in_use = true;
+
+ ret = of_property_read_u32(np, "color", &color);
+ if (ret < 0 && ret != -EINVAL)
+ return ret;
+
+ chan->color = color;
+
+ ret = of_property_read_u32_array(np, "qcom,dtest", dtest, 2);
+ if (ret < 0 && ret != -EINVAL) {
+ dev_err(lpg->dev, "malformed qcom,dtest of %pOFn\n", np);
+ return ret;
+ } else if (!ret) {
+ chan->dtest_line = dtest[0];
+ chan->dtest_value = dtest[1];
+ }
+
+ *channel = chan;
+
+ return 0;
+}
+
+static int lpg_add_led(struct lpg *lpg, struct device_node *np)
+{
+ struct led_classdev *cdev;
+ struct device_node *child;
+ struct mc_subled *info;
+ struct lpg_led *led;
+ const char *state;
+ int num_channels;
+ u32 color = 0;
+ int ret;
+ int i;
+
+ ret = of_property_read_u32(np, "color", &color);
+ if (ret < 0 && ret != -EINVAL)
+ return ret;
+
+ if (color == LED_COLOR_ID_MULTI)
+ num_channels = of_get_available_child_count(np);
+ else
+ num_channels = 1;
+
+ led = devm_kzalloc(lpg->dev, struct_size(led, channels, num_channels), GFP_KERNEL);
+ if (!led)
+ return -ENOMEM;
+
+ led->lpg = lpg;
+ led->num_channels = num_channels;
+
+ if (color == LED_COLOR_ID_MULTI) {
+ info = devm_kcalloc(lpg->dev, num_channels, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ i = 0;
+ for_each_available_child_of_node(np, child) {
+ ret = lpg_parse_channel(lpg, child, &led->channels[i]);
+ if (ret < 0)
+ return ret;
+
+ info[i].color_index = led->channels[i]->color;
+ info[i].intensity = LED_FULL;
+ i++;
+ }
+
+ led->mcdev.subled_info = info;
+ led->mcdev.num_colors = num_channels;
+
+ cdev = &led->mcdev.led_cdev;
+ cdev->brightness_set = lpg_brightness_mc_set;
+ cdev->blink_set = lpg_blink_mc_set;
+
+ /* Register pattern accessors only if we have a LUT block */
+ if (lpg->lut_base) {
+ cdev->pattern_set = lpg_pattern_mc_set;
+ cdev->pattern_clear = lpg_pattern_mc_clear;
+ }
+ } else {
+ ret = lpg_parse_channel(lpg, np, &led->channels[0]);
+ if (ret < 0)
+ return ret;
+
+ cdev = &led->cdev;
+ cdev->brightness_set = lpg_brightness_single_set;
+ cdev->blink_set = lpg_blink_single_set;
+
+ /* Register pattern accessors only if we have a LUT block */
+ if (lpg->lut_base) {
+ cdev->pattern_set = lpg_pattern_single_set;
+ cdev->pattern_clear = lpg_pattern_single_clear;
+ }
+ }
+
+ /* Use label else node name */
+ cdev->name = of_get_property(np, "label", NULL) ? : np->name;
+ cdev->default_trigger = of_get_property(np, "linux,default-trigger", NULL);
+ cdev->max_brightness = 255;
+
+ if (!of_property_read_string(np, "default-state", &state) &&
+ !strcmp(state, "on"))
+ cdev->brightness = LED_FULL;
+ else
+ cdev->brightness = LED_OFF;
+
+ cdev->brightness_set(cdev, cdev->brightness);
+
+ if (color == LED_COLOR_ID_MULTI)
+ ret = devm_led_classdev_multicolor_register(lpg->dev, &led->mcdev);
+ else
+ ret = devm_led_classdev_register(lpg->dev, &led->cdev);
+ if (ret)
+ dev_err(lpg->dev, "unable to register %s\n", cdev->name);
+
+ return ret;
+}
+
+static int lpg_init_channels(struct lpg *lpg)
+{
+ const struct lpg_data *data = lpg->data;
+ int i;
+
+ lpg->num_channels = data->num_channels;
+ lpg->channels = devm_kcalloc(lpg->dev, data->num_channels,
+ sizeof(struct lpg_channel), GFP_KERNEL);
+ if (!lpg->channels)
+ return -ENOMEM;
+
+ for (i = 0; i < data->num_channels; i++) {
+ lpg->channels[i].lpg = lpg;
+ lpg->channels[i].base = data->channels[i].base;
+ lpg->channels[i].triled_mask = data->channels[i].triled_mask;
+ lpg->channels[i].lut_mask = BIT(i);
+ }
+
+ return 0;
+}
+
+static int lpg_init_triled(struct lpg *lpg)
+{
+ struct device_node *np = lpg->dev->of_node;
+ int ret;
+
+ /* Skip initialization if we don't have a triled block */
+ if (!lpg->data->triled_base)
+ return 0;
+
+ lpg->triled_base = lpg->data->triled_base;
+ lpg->triled_has_atc_ctl = lpg->data->triled_has_atc_ctl;
+ lpg->triled_has_src_sel = lpg->data->triled_has_src_sel;
+
+ if (lpg->triled_has_src_sel) {
+ ret = of_property_read_u32(np, "qcom,power-source", &lpg->triled_src);
+ if (ret || lpg->triled_src == 2 || lpg->triled_src > 3) {
+ dev_err(lpg->dev, "invalid power source\n");
+ return -EINVAL;
+ }
+ }
+
+ /* Disable automatic trickle charge LED */
+ if (lpg->triled_has_atc_ctl)
+ regmap_write(lpg->map, lpg->triled_base + TRI_LED_ATC_CTL, 0);
+
+ /* Configure power source */
+ if (lpg->triled_has_src_sel)
+ regmap_write(lpg->map, lpg->triled_base + TRI_LED_SRC_SEL, lpg->triled_src);
+
+ /* Default all outputs to off */
+ regmap_write(lpg->map, lpg->triled_base + TRI_LED_EN_CTL, 0);
+
+ return 0;
+}
+
+static int lpg_init_lut(struct lpg *lpg)
+{
+ const struct lpg_data *data = lpg->data;
+ size_t bitmap_size;
+
+ if (!data->lut_base)
+ return 0;
+
+ lpg->lut_base = data->lut_base;
+ lpg->lut_size = data->lut_size;
+
+ bitmap_size = BITS_TO_LONGS(lpg->lut_size) * sizeof(unsigned long);
+ lpg->lut_bitmap = devm_kzalloc(lpg->dev, bitmap_size, GFP_KERNEL);
+
+ bitmap_clear(lpg->lut_bitmap, 0, lpg->lut_size);
+ return lpg->lut_bitmap ? 0 : -ENOMEM;
+}
+
+static int lpg_probe(struct platform_device *pdev)
+{
+ struct device_node *np;
+ struct lpg *lpg;
+ int ret;
+ int i;
+
+ lpg = devm_kzalloc(&pdev->dev, sizeof(*lpg), GFP_KERNEL);
+ if (!lpg)
+ return -ENOMEM;
+
+ lpg->data = of_device_get_match_data(&pdev->dev);
+ if (!lpg->data)
+ return -EINVAL;
+
+ lpg->dev = &pdev->dev;
+
+ lpg->map = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!lpg->map) {
+ dev_err(&pdev->dev, "parent regmap unavailable\n");
+ return -ENXIO;
+ }
+
+ ret = lpg_init_channels(lpg);
+ if (ret < 0)
+ return ret;
+
+ ret = lpg_init_triled(lpg);
+ if (ret < 0)
+ return ret;
+
+ ret = lpg_init_lut(lpg);
+ if (ret < 0)
+ return ret;
+
+ for_each_available_child_of_node(pdev->dev.of_node, np) {
+ ret = lpg_add_led(lpg, np);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < lpg->num_channels; i++)
+ lpg_apply_dtest(&lpg->channels[i]);
+
+ ret = lpg_add_pwm(lpg);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, lpg);
+
+ return 0;
+}
+
+static int lpg_remove(struct platform_device *pdev)
+{
+ struct lpg *lpg = platform_get_drvdata(pdev);
+
+ pwmchip_remove(&lpg->pwm);
+
+ return 0;
+}
+
+static const struct lpg_data pm8916_pwm_data = {
+ .pwm_9bit_mask = BIT(2),
+
+ .num_channels = 1,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xbc00 },
+ },
+};
+
+static const struct lpg_data pm8941_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 64,
+
+ .triled_base = 0xd000,
+ .triled_has_atc_ctl = true,
+ .triled_has_src_sel = true,
+
+ .pwm_9bit_mask = 3 << 4,
+
+ .num_channels = 8,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100 },
+ { .base = 0xb200 },
+ { .base = 0xb300 },
+ { .base = 0xb400 },
+ { .base = 0xb500, .triled_mask = BIT(5) },
+ { .base = 0xb600, .triled_mask = BIT(6) },
+ { .base = 0xb700, .triled_mask = BIT(7) },
+ { .base = 0xb800 },
+ },
+};
+
+static const struct lpg_data pm8994_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 64,
+
+ .pwm_9bit_mask = 3 << 4,
+
+ .num_channels = 6,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100 },
+ { .base = 0xb200 },
+ { .base = 0xb300 },
+ { .base = 0xb400 },
+ { .base = 0xb500 },
+ { .base = 0xb600 },
+ },
+};
+
+static const struct lpg_data pmi8994_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 24,
+
+ .triled_base = 0xd000,
+ .triled_has_atc_ctl = true,
+ .triled_has_src_sel = true,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 4,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100, .triled_mask = BIT(5) },
+ { .base = 0xb200, .triled_mask = BIT(6) },
+ { .base = 0xb300, .triled_mask = BIT(7) },
+ { .base = 0xb400 },
+ },
+};
+
+static const struct lpg_data pmi8998_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 49,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 6,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100 },
+ { .base = 0xb200 },
+ { .base = 0xb300, .triled_mask = BIT(5) },
+ { .base = 0xb400, .triled_mask = BIT(6) },
+ { .base = 0xb500, .triled_mask = BIT(7) },
+ { .base = 0xb600 },
+ },
+};
+
+static const struct lpg_data pm8150b_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 49,
+
+ .triled_base = 0xd000,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 2,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100, .triled_mask = BIT(7) },
+ { .base = 0xb200, .triled_mask = BIT(6) },
+ },
+};
+
+static const struct lpg_data pm8150l_lpg_data = {
+ .lut_base = 0xb000,
+ .lut_size = 49,
+
+ .triled_base = 0xd000,
+
+ .pwm_9bit_mask = BIT(4),
+
+ .num_channels = 5,
+ .channels = (struct lpg_channel_data[]) {
+ { .base = 0xb100, .triled_mask = BIT(7) },
+ { .base = 0xb200, .triled_mask = BIT(6) },
+ { .base = 0xb300, .triled_mask = BIT(5) },
+ { .base = 0xbc00 },
+ { .base = 0xbd00 },
+
+ },
+};
+
+static const struct of_device_id lpg_of_table[] = {
+ { .compatible = "qcom,pm8916-pwm", .data = &pm8916_pwm_data },
+ { .compatible = "qcom,pm8941-lpg", .data = &pm8941_lpg_data },
+ { .compatible = "qcom,pm8994-lpg", .data = &pm8994_lpg_data },
+ { .compatible = "qcom,pmi8994-lpg", .data = &pmi8994_lpg_data },
+ { .compatible = "qcom,pmi8998-lpg", .data = &pmi8998_lpg_data },
+ { .compatible = "qcom,pm8150b-lpg", .data = &pm8150b_lpg_data },
+ { .compatible = "qcom,pm8150l-lpg", .data = &pm8150l_lpg_data },
+ {}
+};
+MODULE_DEVICE_TABLE(of, lpg_of_table);
+
+static struct platform_driver lpg_driver = {
+ .probe = lpg_probe,
+ .remove = lpg_remove,
+ .driver = {
+ .name = "qcom-spmi-lpg",
+ .of_match_table = lpg_of_table,
+ },
+};
+module_platform_driver(lpg_driver);
+
+MODULE_DESCRIPTION("Qualcomm LPG LED driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 5f9f9b3a226d..53791138d78b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -3166,12 +3166,11 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
- cc->crypt_queue = alloc_workqueue("kcryptd-%s", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM,
+ cc->crypt_queue = alloc_workqueue("kcryptd/%s", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM,
1, devname);
else
- cc->crypt_queue = alloc_workqueue("kcryptd-%s",
- WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM |
- WQ_UNBOUND | WQ_SYSFS,
+ cc->crypt_queue = alloc_workqueue("kcryptd/%s",
+ WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND,
num_online_cpus(), devname);
if (!cc->crypt_queue) {
ti->error = "Couldn't create kcryptd queue";
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bdfce7b15621..2fd6b9770ad0 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1036,6 +1036,18 @@ config MFD_PM8XXX
Say M here if you want to include support for PM8xxx chips as a
module. This will build a module called "pm8xxx-core".
+config MFD_QCOM_QCA639X
+ tristate "Qualcomm QCA639x WiFi/Bluetooth module support"
+ depends on REGULATOR && PM_GENERIC_DOMAINS
+ help
+ If you say yes to this option, support will be included for Qualcomm
+ QCA639x family of WiFi and Bluetooth SoCs. Note, this driver supports
+ only power control for this SoC, you still have to enable individual
+ Bluetooth and WiFi drivers.
+
+ Say M here if you want to include support for QCA639x chips as a
+ module. This will build a module called "qcom-qca639x".
+
config MFD_QCOM_RPM
tristate "Qualcomm Resource Power Manager (RPM)"
depends on ARCH_QCOM && OF
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 14fdb188af02..da5747508faf 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -202,6 +202,7 @@ obj-$(CONFIG_MFD_SI476X_CORE) += si476x-core.o
obj-$(CONFIG_MFD_CS5535) += cs5535-mfd.o
obj-$(CONFIG_MFD_OMAP_USB_HOST) += omap-usb-host.o omap-usb-tll.o
obj-$(CONFIG_MFD_PM8XXX) += qcom-pm8xxx.o ssbi.o
+obj-$(CONFIG_MFD_QCOM_QCA639X) += qcom-qca639x.o
obj-$(CONFIG_MFD_QCOM_RPM) += qcom_rpm.o
obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index fc00aaccb5f7..3e845be895ac 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -359,6 +359,7 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
struct platform_device *pdev;
const struct mfd_cell *cell;
int *level = data;
+ struct mfd_of_node_entry *of_entry, *tmp;
if (dev->type != &mfd_dev_type)
return 0;
@@ -372,6 +373,12 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
cell->num_parent_supplies);
+ list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
+ if (of_entry->dev == &pdev->dev) {
+ list_del(&of_entry->list);
+ kfree(of_entry);
+ }
+
platform_device_unregister(pdev);
return 0;
}
diff --git a/drivers/mfd/qcom-qca639x.c b/drivers/mfd/qcom-qca639x.c
new file mode 100644
index 000000000000..b31e4b65bec5
--- /dev/null
+++ b/drivers/mfd/qcom-qca639x.c
@@ -0,0 +1,162 @@
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/devinfo.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#define MAX_NUM_REGULATORS 8
+
+static struct vreg {
+ const char *name;
+ unsigned int load_uA;
+} vregs [MAX_NUM_REGULATORS] = {
+ /* 2.0 V */
+ { "vddpcie2", 15000 },
+ { "vddrfa3", 400000 },
+
+ /* 0.95 V */
+ { "vddaon", 100000 },
+ { "vddpmu", 1250000 },
+ { "vddrfa1", 200000 },
+
+ /* 1.35 V */
+ { "vddrfa2", 400000 },
+ { "vddpcie1", 35000 },
+
+ /* 1.8 V */
+ { "vddio", 20000 },
+};
+
+struct qca639x_data {
+ struct regulator_bulk_data regulators[MAX_NUM_REGULATORS];
+ size_t num_vregs;
+ struct device *dev;
+ struct pinctrl_state *active_state;
+ struct generic_pm_domain pd;
+};
+
+#define domain_to_data(domain) container_of(domain, struct qca639x_data, pd)
+
+static int qca639x_power_on(struct generic_pm_domain *domain)
+{
+ struct qca639x_data *data = domain_to_data(domain);
+ int ret;
+
+ dev_warn(&domain->dev, "DUMMY POWER ON\n");
+
+ ret = regulator_bulk_enable(data->num_vregs, data->regulators);
+ if (ret) {
+ dev_err(data->dev, "Failed to enable regulators");
+ return ret;
+ }
+
+ /* Wait for 1ms before toggling enable pins. */
+ msleep(1);
+
+ ret = pinctrl_select_state(data->dev->pins->p, data->active_state);
+ if (ret) {
+ dev_err(data->dev, "Failed to select active state");
+ return ret;
+ }
+
+ /* Wait for all power levels to stabilize */
+ msleep(6);
+
+ return 0;
+}
+
+static int qca639x_power_off(struct generic_pm_domain *domain)
+{
+ struct qca639x_data *data = domain_to_data(domain);
+
+ dev_warn(&domain->dev, "DUMMY POWER OFF\n");
+
+ pinctrl_select_default_state(data->dev);
+ regulator_bulk_disable(data->num_vregs, data->regulators);
+
+ return 0;
+}
+
+static int qca639x_probe(struct platform_device *pdev)
+{
+ struct qca639x_data *data;
+ struct device *dev = &pdev->dev;
+ int i, ret;
+
+ if (!dev->pins || IS_ERR_OR_NULL(dev->pins->default_state))
+ return -EINVAL;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->dev = dev;
+ data->num_vregs = ARRAY_SIZE(vregs);
+
+ data->active_state = pinctrl_lookup_state(dev->pins->p, "active");
+ if (IS_ERR(data->active_state)) {
+ ret = PTR_ERR(data->active_state);
+ dev_err(dev, "Failed to get active_state: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < data->num_vregs; i++)
+ data->regulators[i].supply = vregs[i].name;
+ ret = devm_regulator_bulk_get(dev, data->num_vregs, data->regulators);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < data->num_vregs; i++) {
+ ret = regulator_set_load(data->regulators[i].consumer, vregs[i].load_uA);
+ if (ret)
+ return ret;
+ }
+
+ data->pd.name = dev_name(dev);
+ data->pd.power_on = qca639x_power_on;
+ data->pd.power_off = qca639x_power_off;
+
+ ret = pm_genpd_init(&data->pd, NULL, true);
+ if (ret < 0)
+ return ret;
+
+ ret = of_genpd_add_provider_simple(dev->of_node, &data->pd);
+ if (ret < 0) {
+ pm_genpd_remove(&data->pd);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int qca639x_remove(struct platform_device *pdev)
+{
+ struct qca639x_data *data = platform_get_drvdata(pdev);
+
+ pm_genpd_remove(&data->pd);
+
+ return 0;
+}
+
+static const struct of_device_id qca639x_of_match[] = {
+ { .compatible = "qcom,qca639x" },
+};
+
+static struct platform_driver qca639x_driver = {
+ .probe = qca639x_probe,
+ .remove = qca639x_remove,
+ .driver = {
+ .name = "qca639x",
+ .of_match_table = qca639x_of_match,
+ },
+};
+
+module_platform_driver(qca639x_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/wcd934x.c b/drivers/mfd/wcd934x.c
index c274d733b656..b5252053a624 100644
--- a/drivers/mfd/wcd934x.c
+++ b/drivers/mfd/wcd934x.c
@@ -194,10 +194,14 @@ static int wcd934x_slim_status_up(struct slim_device *sdev)
static int wcd934x_slim_status(struct slim_device *sdev,
enum slim_device_status status)
{
+ struct wcd934x_ddata *ddata;
+
switch (status) {
case SLIM_DEVICE_STATUS_UP:
return wcd934x_slim_status_up(sdev);
case SLIM_DEVICE_STATUS_DOWN:
+ ddata = dev_get_drvdata(&sdev->dev);
+ regcache_cache_only(ddata->regmap, true);
mfd_remove_devices(&sdev->dev);
break;
default:
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 205c0f1a40e9..24a36ba5317f 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -2293,7 +2293,6 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
struct ieee80211_rx_status *rx_status)
{
u8 channel_num;
- u32 center_freq;
rx_status->freq = 0;
rx_status->rate_idx = 0;
@@ -2304,11 +2303,8 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
channel_num = ath11k_dp_rx_h_msdu_start_freq(rx_desc);
- center_freq = ath11k_dp_rx_h_msdu_start_freq(rx_desc) >> 16;
- if (center_freq >= 5935 && center_freq <= 7105) {
- rx_status->band = NL80211_BAND_6GHZ;
- } else if (channel_num >= 1 && channel_num <= 14) {
+ if (channel_num >= 1 && channel_num <= 14) {
rx_status->band = NL80211_BAND_2GHZ;
} else if (channel_num >= 36 && channel_num <= 173) {
rx_status->band = NL80211_BAND_5GHZ;
diff --git a/drivers/net/wireless/ath/ath11k/dp_tx.c b/drivers/net/wireless/ath/ath11k/dp_tx.c
index 6a3fcea6c233..55bc83668669 100644
--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
@@ -922,6 +922,12 @@ int ath11k_dp_tx_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
enum htt_srng_ring_id htt_ring_id;
int ret;
+ /* HACK_KVALO: hack to workaround broken pktlog handling on
+ * QCA61390
+ */
+ if (!ab->hw_params.rxdma1_enable)
+ return 0;
+
skb = ath11k_htc_alloc_skb(ab, len);
if (!skb)
return -ENOMEM;
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 857647aa57c8..528cc040b358 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -889,12 +889,19 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
static int ath11k_pci_power_up(struct ath11k_base *ab)
{
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+ u8 aspm;
int ret;
ab_pci->register_window = 0;
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
ath11k_pci_sw_reset(ab_pci->ab, true);
+ pci_read_config_byte(ab_pci->pdev, 0x80, &aspm);
+ pci_write_config_byte(ab_pci->pdev, 0x80, aspm & 0xfd);
+
+ ath11k_info(ab, "aspm 0x%x changed to 0x%x\n",
+ aspm, aspm & 0xfd);
+
ret = ath11k_mhi_start(ab_pci);
if (ret) {
ath11k_err(ab, "failed to start mhi: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index da4b546b62cb..aa879917ff98 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -4494,7 +4494,6 @@ static int ath11k_pull_mgmt_rx_params_tlv(struct ath11k_base *ab,
}
hdr->pdev_id = ev->pdev_id;
- hdr->chan_freq = ev->chan_freq;
hdr->channel = ev->channel;
hdr->snr = ev->snr;
hdr->rate = ev->rate;
@@ -5914,9 +5913,7 @@ static void ath11k_mgmt_rx_event(struct ath11k_base *ab, struct sk_buff *skb)
if (rx_ev.status & WMI_RX_STATUS_ERR_MIC)
status->flag |= RX_FLAG_MMIC_ERROR;
- if (rx_ev.chan_freq >= ATH11K_MIN_6G_FREQ) {
- status->band = NL80211_BAND_6GHZ;
- } else if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {
+ if (rx_ev.channel >= 1 && rx_ev.channel <= 14) {
status->band = NL80211_BAND_2GHZ;
} else if (rx_ev.channel >= 36 && rx_ev.channel <= ATH11K_MAX_5G_CHAN) {
status->band = NL80211_BAND_5GHZ;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 993674228c9e..1c9a7bd66f78 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -4309,7 +4309,6 @@ struct wmi_pdev_temperature_event {
#define WLAN_MGMT_TXRX_HOST_MAX_ANTENNA 4
struct mgmt_rx_event_params {
- u32 chan_freq;
u32 channel;
u32 snr;
u8 rssi_ctl[WLAN_MGMT_TXRX_HOST_MAX_ANTENNA];
@@ -4339,7 +4338,6 @@ struct wmi_mgmt_rx_hdr {
u32 rx_tsf_l32;
u32 rx_tsf_u32;
u32 pdev_id;
- u32 chan_freq;
} __packed;
#define MAX_ANTENNA_EIGHT 8
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 4268eb359915..8c905aabacc0 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1092,7 +1092,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
if (IS_ERR(opp_table->clk)) {
ret = PTR_ERR(opp_table->clk);
if (ret == -EPROBE_DEFER)
- goto err;
+ goto remove_opp_dev;
dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__, ret);
}
@@ -1101,7 +1101,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
ret = dev_pm_opp_of_find_icc_paths(dev, opp_table);
if (ret) {
if (ret == -EPROBE_DEFER)
- goto err;
+ goto put_clk;
dev_warn(dev, "%s: Error finding interconnect paths: %d\n",
__func__, ret);
@@ -1113,6 +1113,11 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
return opp_table;
+put_clk:
+ if (!IS_ERR(opp_table->clk))
+ clk_put(opp_table->clk);
+remove_opp_dev:
+ _remove_opp_dev(opp_dev, opp_table);
err:
kfree(opp_table);
return ERR_PTR(ret);
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index affa2713bf80..f14ecff4fb61 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -159,8 +159,9 @@ struct qcom_pcie_resources_2_3_3 {
struct reset_control *rst[7];
};
+#define QCOM_PCIE_2_7_0_MAX_CLOCKS 6
struct qcom_pcie_resources_2_7_0 {
- struct clk_bulk_data clks[6];
+ struct clk_bulk_data clks[QCOM_PCIE_2_7_0_MAX_CLOCKS + 1]; /* + 1 for sf_tbu */
struct regulator_bulk_data supplies[2];
struct reset_control *pci_reset;
struct clk *pipe_clk;
@@ -1153,10 +1154,15 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
res->clks[4].id = "slave_q2a";
res->clks[5].id = "tbu";
- ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks);
+ ret = devm_clk_bulk_get(dev, QCOM_PCIE_2_7_0_MAX_CLOCKS, res->clks);
if (ret < 0)
return ret;
+ /* Optional clock for SM8250 */
+ res->clks[6].clk = devm_clk_get_optional(dev, "ddrss_sf_tbu");
+ if (IS_ERR(res->clks[6].clk))
+ return PTR_ERR(res->clks[6].clk);
+
res->pipe_clk = devm_clk_get(dev, "pipe");
return PTR_ERR_OR_ZERO(res->pipe_clk);
}
@@ -1552,6 +1558,13 @@ static void qcom_fixup_class(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_PCI << 8;
}
+
+static void qcom_fixup_nopm(struct pci_dev *dev)
+{
+ dev->pm_cap = 0;
+ dev_info(&dev->dev, "Disabling PCI power management\n");
+}
+
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0106, qcom_fixup_class);
@@ -1559,6 +1572,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0107, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_RENESAS, 0x0014, qcom_fixup_nopm);
static struct platform_driver qcom_pcie_driver = {
.probe = qcom_pcie_probe,
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 7f6fcb8ec5ba..7d5814c8f9cc 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -48,6 +48,17 @@ config PHY_QCOM_QMP
Enable this to support the QMP PHY transceiver that is used
with controllers such as PCIe, UFS, and USB on Qualcomm chips.
+if PHY_QCOM_QMP
+config PHY_QCOM_QMP_TYPEC
+ bool "Enable QCOM QMP PHY Type C Switch Support"
+ depends on PHY_QCOM_QMP=y && TYPEC=y || PHY_QCOM_QMP=m && TYPEC
+ help
+ Register a type C switch from the QMP PHY driver for type C
+ orientation support. This has dependencies with if the type C kernel
+ configuration is enabled or not. This support will not be present if
+ USB type C is disabled.
+endif
+
config PHY_QCOM_QUSB2
tristate "Qualcomm QUSB2 PHY Driver"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 0939a9e9d448..2668a9727bc5 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -19,6 +19,7 @@
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/slab.h>
+#include <linux/usb/typec_mux.h>
#include <dt-bindings/phy/phy.h>
@@ -66,6 +67,9 @@
/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
+#define SW_PORTSELECT_VAL BIT(0)
+#define SW_PORTSELECT_MUX BIT(1)
+
#define PHY_INIT_COMPLETE_TIMEOUT 10000
#define POWER_DOWN_DELAY_US_MIN 10
#define POWER_DOWN_DELAY_US_MAX 11
@@ -2112,6 +2116,8 @@ struct qmp_phy_dp_clks {
* @phy_mutex: mutex lock for PHY common block initialization
* @init_count: phy common block initialization count
* @ufs_reset: optional UFS PHY reset handle
+ * @sw: typec switch for receiving orientation changes
+ * @orientation: carries current CC orientation
*/
struct qcom_qmp {
struct device *dev;
@@ -2127,6 +2133,8 @@ struct qcom_qmp {
int init_count;
struct reset_control *ufs_reset;
+ struct typec_switch *sw;
+ enum typec_orientation orientation;
};
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -2579,6 +2587,11 @@ static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = {
.dp_cfg = &sc7180_dpphy_cfg,
};
+static const struct qmp_phy_combo_cfg sdm845_usb3dpphy_cfg = {
+ .usb_cfg = &qmp_v3_usb3phy_cfg,
+ .dp_cfg = &sc7180_dpphy_cfg,
+};
+
static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
.type = PHY_TYPE_USB3,
.nlanes = 1,
@@ -3042,25 +3055,17 @@ static int qcom_qmp_phy_configure_dp_phy(struct qmp_phy *qphy)
const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts;
u32 val, phy_vco_div, status;
unsigned long pixel_freq;
+ int lane_cnt = 2; /* FIXME: assume lane_cnt = 2 */
val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN |
DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN;
- /*
- * TODO: Assume orientation is CC1 for now and two lanes, need to
- * use type-c connector to understand orientation and lanes.
- *
- * Otherwise val changes to be like below if this code understood
- * the orientation of the type-c cable.
- *
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC2)
- * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
- * if (lane_cnt == 4 || orientation == ORIENTATION_CC1)
- * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
- * if (orientation == ORIENTATION_CC2)
- * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
- */
- val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+ if (lane_cnt == 4 || qphy->qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN;
+ if (lane_cnt == 4 || qphy->qmp->orientation == TYPEC_ORIENTATION_NORMAL)
+ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN;
+ if (qphy->qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
writel(val, qphy->pcs + QSERDES_V3_DP_PHY_PD_CTL);
writel(0x5c, qphy->pcs + QSERDES_V3_DP_PHY_MODE);
@@ -3155,6 +3160,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
void __iomem *pcs = qphy->pcs;
void __iomem *dp_com = qmp->dp_com;
int ret, i;
+ unsigned int val;
mutex_lock(&qmp->phy_mutex);
if (qmp->init_count++) {
@@ -3201,8 +3207,10 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
- /* Default type-c orientation, i.e CC1 */
- qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02);
+ val = SW_PORTSELECT_MUX;
+ if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= SW_PORTSELECT_VAL;
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, val);
qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL,
USB3_MODE | DP_MODE);
@@ -4141,6 +4149,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
.compatible = "qcom,sdm845-qmp-usb3-uni-phy",
.data = &qmp_v3_usb3_uniphy_cfg,
}, {
+ .compatible = "qcom,sdm845-qmp-usb3-dp-phy",
+ /* It's a combo phy */
+ }, {
.compatible = "qcom,sdm845-qmp-ufs-phy",
.data = &sdm845_ufsphy_cfg,
}, {
@@ -4183,6 +4194,10 @@ static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = {
.compatible = "qcom,sc7180-qmp-usb3-dp-phy",
.data = &sc7180_usb3dpphy_cfg,
},
+ {
+ .compatible = "qcom,sdm845-qmp-usb3-dp-phy",
+ .data = &sdm845_usb3dpphy_cfg,
+ },
{ }
};
@@ -4191,6 +4206,47 @@ static const struct dev_pm_ops qcom_qmp_phy_pm_ops = {
qcom_qmp_phy_runtime_resume, NULL)
};
+#if IS_ENABLED(CONFIG_PHY_QCOM_QMP_TYPEC)
+static int qcom_qmp_phy_typec_switch_set(struct typec_switch *sw,
+ enum typec_orientation orientation)
+{
+ struct qcom_qmp *qmp = typec_switch_get_drvdata(sw);
+ struct qmp_phy *qphy = qmp->phys[0];
+
+ qmp->orientation = orientation;
+ if (qmp->init_count) {
+ qcom_qmp_phy_disable(qphy->phy);
+ qcom_qmp_phy_enable(qphy->phy);
+ }
+
+ return 0;
+}
+
+static int qcom_qmp_phy_typec_switch_register(struct qcom_qmp *qmp, const struct qmp_phy_cfg *cfg)
+{
+ struct typec_switch_desc sw_desc;
+ struct device *dev = qmp->dev;
+
+ if (cfg->is_dual_lane_phy) {
+ sw_desc.drvdata = qmp;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = qcom_qmp_phy_typec_switch_set;
+ qmp->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(qmp->sw)) {
+ dev_err(dev, "Error registering typec switch: %ld\n",
+ PTR_ERR(qmp->sw));
+ }
+ }
+
+ return 0;
+}
+#else
+static int qcom_qmp_phy_typec_switch_register(struct qcom_qmp *qmp, const struct qmp_phy_cfg *cfg)
+{
+ return 0;
+}
+#endif
+
static int qcom_qmp_phy_probe(struct platform_device *pdev)
{
struct qcom_qmp *qmp;
@@ -4273,7 +4329,12 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
return ret;
}
- num = of_get_available_child_count(dev->of_node);
+ qcom_qmp_phy_typec_switch_register(qmp, cfg);
+ num = 0;
+ for_each_available_child_of_node(dev->of_node, child) {
+ if (strncmp("port", child->name, 4))
+ num++;
+ }
/* do we have a rogue child node ? */
if (num > expected_phys)
return -EINVAL;
@@ -4301,6 +4362,9 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
}
/* Create per-lane phy */
+ if (!strncmp("port", child->name, 4))
+ continue;
+
ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
index fe030ec4b7db..38d1251a0bd8 100644
--- a/drivers/regulator/qcom-rpmh-regulator.c
+++ b/drivers/regulator/qcom-rpmh-regulator.c
@@ -921,7 +921,7 @@ static const struct rpmh_vreg_init_data pm8350c_vreg_data[] = {
static const struct rpmh_vreg_init_data pm8009_vreg_data[] = {
RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"),
- RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps515, "vdd-s2"),
+ RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps510, "vdd-s2"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"),
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index f95854255c70..a443e3fec54e 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -92,6 +92,7 @@ struct qcom_wcnss {
struct completion start_done;
struct completion stop_done;
+ struct completion iris_assigned;
phys_addr_t mem_phys;
phys_addr_t mem_reloc;
@@ -150,6 +151,7 @@ void qcom_wcnss_assign_iris(struct qcom_wcnss *wcnss,
wcnss->iris = iris;
wcnss->use_48mhz_xo = use_48mhz_xo;
+ complete(&wcnss->iris_assigned);
mutex_unlock(&wcnss->iris_lock);
}
@@ -232,6 +234,10 @@ static int wcnss_start(struct rproc *rproc)
struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
int ret, i;
+ /* Grant some time for iris registration */
+ wait_for_completion_timeout(&wcnss->iris_assigned,
+ msecs_to_jiffies(5000));
+
mutex_lock(&wcnss->iris_lock);
if (!wcnss->iris) {
dev_err(wcnss->dev, "no iris registered\n");
@@ -530,6 +536,7 @@ static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
static int wcnss_probe(struct platform_device *pdev)
{
+ const char *fw_name = WCNSS_FIRMWARE_NAME;
const struct wcnss_data *data;
struct qcom_wcnss *wcnss;
struct resource *res;
@@ -547,8 +554,13 @@ static int wcnss_probe(struct platform_device *pdev)
return -ENXIO;
}
+ ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
+ &fw_name);
+ if (ret < 0 && ret != -EINVAL)
+ return ret;
+
rproc = rproc_alloc(&pdev->dev, pdev->name, &wcnss_ops,
- WCNSS_FIRMWARE_NAME, sizeof(*wcnss));
+ fw_name, sizeof(*wcnss));
if (!rproc) {
dev_err(&pdev->dev, "unable to allocate remoteproc\n");
return -ENOMEM;
@@ -562,6 +574,7 @@ static int wcnss_probe(struct platform_device *pdev)
init_completion(&wcnss->start_done);
init_completion(&wcnss->stop_done);
+ init_completion(&wcnss->iris_assigned);
mutex_init(&wcnss->iris_lock);
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index b206e266b4e7..8b0deece9758 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -4,6 +4,7 @@ config SCSI_CXGB4_ISCSI
depends on PCI && INET && (IPV6 || IPV6=n)
depends on THERMAL || !THERMAL
depends on ETHERNET
+ depends on TLS || TLS=n
select NET_VENDOR_CHELSIO
select CHELSIO_T4
select CHELSIO_LIB
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 969baf4cd3f5..6e23dc3209fe 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -5034,7 +5034,7 @@ _base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc)
static void
_base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc)
{
- u16 trigger_flags;
+ int trigger_flags;
/*
* Default setting of master trigger.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 4848ae3c7b56..b3f14f05340a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -249,7 +249,8 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
req = blk_get_request(sdev->request_queue,
data_direction == DMA_TO_DEVICE ?
- REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT);
+ REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
+ rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
if (IS_ERR(req))
return ret;
rq = scsi_req(req);
@@ -1206,6 +1207,8 @@ static blk_status_t
scsi_device_state_check(struct scsi_device *sdev, struct request *req)
{
switch (sdev->sdev_state) {
+ case SDEV_CREATED:
+ return BLK_STS_OK;
case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE:
/*
@@ -1232,18 +1235,18 @@ scsi_device_state_check(struct scsi_device *sdev, struct request *req)
return BLK_STS_RESOURCE;
case SDEV_QUIESCE:
/*
- * If the devices is blocked we defer normal commands.
+ * If the device is blocked we only accept power management
+ * commands.
*/
- if (req && !(req->rq_flags & RQF_PREEMPT))
+ if (req && WARN_ON_ONCE(!(req->rq_flags & RQF_PM)))
return BLK_STS_RESOURCE;
return BLK_STS_OK;
default:
/*
* For any other not fully online state we only allow
- * special commands. In particular any user initiated
- * command is not allowed.
+ * power management commands.
*/
- if (req && !(req->rq_flags & RQF_PREEMPT))
+ if (req && !(req->rq_flags & RQF_PM))
return BLK_STS_IOERR;
return BLK_STS_OK;
}
@@ -2516,15 +2519,13 @@ void sdev_evt_send_simple(struct scsi_device *sdev,
EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
/**
- * scsi_device_quiesce - Block user issued commands.
+ * scsi_device_quiesce - Block all commands except power management.
* @sdev: scsi device to quiesce.
*
* This works by trying to transition to the SDEV_QUIESCE state
* (which must be a legal transition). When the device is in this
- * state, only special requests will be accepted, all others will
- * be deferred. Since special requests may also be requeued requests,
- * a successful return doesn't guarantee the device will be
- * totally quiescent.
+ * state, only power management requests will be accepted, all others will
+ * be deferred.
*
* Must be called with user context, may sleep.
*
@@ -2586,12 +2587,12 @@ void scsi_device_resume(struct scsi_device *sdev)
* device deleted during suspend)
*/
mutex_lock(&sdev->state_mutex);
+ if (sdev->sdev_state == SDEV_QUIESCE)
+ scsi_device_set_state(sdev, SDEV_RUNNING);
if (sdev->quiesced_by) {
sdev->quiesced_by = NULL;
blk_clear_pm_only(sdev->request_queue);
}
- if (sdev->sdev_state == SDEV_QUIESCE)
- scsi_device_set_state(sdev, SDEV_RUNNING);
mutex_unlock(&sdev->state_mutex);
}
EXPORT_SYMBOL(scsi_device_resume);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index f3d5b1bbd5aa..c37dd15d16d2 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -117,12 +117,16 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
sshdr = &sshdr_tmp;
for(i = 0; i < DV_RETRIES; i++) {
+ /*
+ * The purpose of the RQF_PM flag below is to bypass the
+ * SDEV_QUIESCE state.
+ */
result = scsi_execute(sdev, cmd, dir, buffer, bufflen, sense,
sshdr, DV_TIMEOUT, /* retries */ 1,
REQ_FAILFAST_DEV |
REQ_FAILFAST_TRANSPORT |
REQ_FAILFAST_DRIVER,
- 0, NULL);
+ RQF_PM, NULL);
if (driver_byte(result) != DRIVER_SENSE ||
sshdr->sense_key != UNIT_ATTENTION)
break;
@@ -1005,23 +1009,26 @@ spi_dv_device(struct scsi_device *sdev)
*/
lock_system_sleep();
+ if (scsi_autopm_get_device(sdev))
+ goto unlock_system_sleep;
+
if (unlikely(spi_dv_in_progress(starget)))
- goto unlock;
+ goto put_autopm;
if (unlikely(scsi_device_get(sdev)))
- goto unlock;
+ goto put_autopm;
spi_dv_in_progress(starget) = 1;
buffer = kzalloc(len, GFP_KERNEL);
if (unlikely(!buffer))
- goto out_put;
+ goto put_sdev;
/* We need to verify that the actual device will quiesce; the
* later target quiesce is just a nice to have */
if (unlikely(scsi_device_quiesce(sdev)))
- goto out_free;
+ goto free_buffer;
scsi_target_quiesce(starget);
@@ -1041,12 +1048,16 @@ spi_dv_device(struct scsi_device *sdev)
spi_initial_dv(starget) = 1;
- out_free:
+free_buffer:
kfree(buffer);
- out_put:
+
+put_sdev:
spi_dv_in_progress(starget) = 0;
scsi_device_put(sdev);
-unlock:
+put_autopm:
+ scsi_autopm_put_device(sdev);
+
+unlock_system_sleep:
unlock_system_sleep();
}
EXPORT_SYMBOL(spi_dv_device);
diff --git a/drivers/scsi/ufs/ufs-mediatek-trace.h b/drivers/scsi/ufs/ufs-mediatek-trace.h
index fd6f84c1b4e2..895e82ea6ece 100644
--- a/drivers/scsi/ufs/ufs-mediatek-trace.h
+++ b/drivers/scsi/ufs/ufs-mediatek-trace.h
@@ -31,6 +31,6 @@ TRACE_EVENT(ufs_mtk_event,
#undef TRACE_INCLUDE_PATH
#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH ../../drivers/scsi/ufs/
#define TRACE_INCLUDE_FILE ufs-mediatek-trace
#include <trace/define_trace.h>
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index 3522458db3bb..80618af7c872 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -70,6 +70,13 @@ static bool ufs_mtk_is_va09_supported(struct ufs_hba *hba)
return !!(host->caps & UFS_MTK_CAP_VA09_PWR_CTRL);
}
+static bool ufs_mtk_is_broken_vcc(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ return !!(host->caps & UFS_MTK_CAP_BROKEN_VCC);
+}
+
static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable)
{
u32 tmp;
@@ -514,6 +521,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba)
if (of_property_read_bool(np, "mediatek,ufs-disable-ah8"))
host->caps |= UFS_MTK_CAP_DISABLE_AH8;
+ if (of_property_read_bool(np, "mediatek,ufs-broken-vcc"))
+ host->caps |= UFS_MTK_CAP_BROKEN_VCC;
+
dev_info(hba->dev, "caps: 0x%x", host->caps);
}
@@ -1003,6 +1013,17 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba)
static void ufs_mtk_fixup_dev_quirks(struct ufs_hba *hba)
{
ufshcd_fixup_dev_quirks(hba, ufs_mtk_dev_fixups);
+
+ if (ufs_mtk_is_broken_vcc(hba) && hba->vreg_info.vcc &&
+ (hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM)) {
+ hba->vreg_info.vcc->always_on = true;
+ /*
+ * VCC will be kept always-on thus we don't
+ * need any delay during regulator operations
+ */
+ hba->dev_quirks &= ~(UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_DELAY_AFTER_LPM);
+ }
}
static void ufs_mtk_event_notify(struct ufs_hba *hba,
diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h
index 93d35097dfb0..3f0d3bb769e8 100644
--- a/drivers/scsi/ufs/ufs-mediatek.h
+++ b/drivers/scsi/ufs/ufs-mediatek.h
@@ -81,6 +81,7 @@ enum ufs_mtk_host_caps {
UFS_MTK_CAP_BOOST_CRYPT_ENGINE = 1 << 0,
UFS_MTK_CAP_VA09_PWR_CTRL = 1 << 1,
UFS_MTK_CAP_DISABLE_AH8 = 1 << 2,
+ UFS_MTK_CAP_BROKEN_VCC = 1 << 3,
};
struct ufs_mtk_crypt_cfg {
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index d593edb48767..14dfda735adf 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -330,7 +330,6 @@ enum {
UFS_DEV_WRITE_BOOSTER_SUP = BIT(8),
};
-#define POWER_DESC_MAX_SIZE 0x62
#define POWER_DESC_MAX_ACTV_ICC_LVLS 16
/* Attribute bActiveICCLevel parameter bit masks definitions */
@@ -513,6 +512,7 @@ struct ufs_query_res {
struct ufs_vreg {
struct regulator *reg;
const char *name;
+ bool always_on;
bool enabled;
int min_uV;
int max_uV;
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index df3a564c3e33..fadd566025b8 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -148,6 +148,8 @@ static int ufs_intel_common_init(struct ufs_hba *hba)
{
struct intel_host *host;
+ hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
+
host = devm_kzalloc(hba->dev, sizeof(*host), GFP_KERNEL);
if (!host)
return -ENOMEM;
@@ -163,6 +165,41 @@ static void ufs_intel_common_exit(struct ufs_hba *hba)
intel_ltr_hide(hba->dev);
}
+static int ufs_intel_resume(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+ /*
+ * To support S4 (suspend-to-disk) with spm_lvl other than 5, the base
+ * address registers must be restored because the restore kernel can
+ * have used different addresses.
+ */
+ ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+ ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_H);
+
+ if (ufshcd_is_link_hibern8(hba)) {
+ int ret = ufshcd_uic_hibern8_exit(hba);
+
+ if (!ret) {
+ ufshcd_set_link_active(hba);
+ } else {
+ dev_err(hba->dev, "%s: hibern8 exit failed %d\n",
+ __func__, ret);
+ /*
+ * Force reset and restore. Any other actions can lead
+ * to an unrecoverable state.
+ */
+ ufshcd_set_link_off(hba);
+ }
+ }
+
+ return 0;
+}
+
static int ufs_intel_ehl_init(struct ufs_hba *hba)
{
hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8;
@@ -174,6 +211,7 @@ static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = {
.init = ufs_intel_common_init,
.exit = ufs_intel_common_exit,
.link_startup_notify = ufs_intel_link_startup_notify,
+ .resume = ufs_intel_resume,
};
static struct ufs_hba_variant_ops ufs_intel_ehl_hba_vops = {
@@ -181,6 +219,7 @@ static struct ufs_hba_variant_ops ufs_intel_ehl_hba_vops = {
.init = ufs_intel_ehl_init,
.exit = ufs_intel_common_exit,
.link_startup_notify = ufs_intel_link_startup_notify,
+ .resume = ufs_intel_resume,
};
#ifdef CONFIG_PM_SLEEP
@@ -207,6 +246,30 @@ static int ufshcd_pci_resume(struct device *dev)
{
return ufshcd_system_resume(dev_get_drvdata(dev));
}
+
+/**
+ * ufshcd_pci_poweroff - suspend-to-disk poweroff function
+ * @dev: pointer to PCI device handle
+ *
+ * Returns 0 if successful
+ * Returns non-zero otherwise
+ */
+static int ufshcd_pci_poweroff(struct device *dev)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ int spm_lvl = hba->spm_lvl;
+ int ret;
+
+ /*
+ * For poweroff we need to set the UFS device to PowerDown mode.
+ * Force spm_lvl to ensure that.
+ */
+ hba->spm_lvl = 5;
+ ret = ufshcd_system_suspend(hba);
+ hba->spm_lvl = spm_lvl;
+ return ret;
+}
+
#endif /* !CONFIG_PM_SLEEP */
#ifdef CONFIG_PM
@@ -302,8 +365,14 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
static const struct dev_pm_ops ufshcd_pci_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(ufshcd_pci_suspend,
- ufshcd_pci_resume)
+#ifdef CONFIG_PM_SLEEP
+ .suspend = ufshcd_pci_suspend,
+ .resume = ufshcd_pci_resume,
+ .freeze = ufshcd_pci_suspend,
+ .thaw = ufshcd_pci_resume,
+ .poweroff = ufshcd_pci_poweroff,
+ .restore = ufshcd_pci_resume,
+#endif
SET_RUNTIME_PM_OPS(ufshcd_pci_runtime_suspend,
ufshcd_pci_runtime_resume,
ufshcd_pci_runtime_idle)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9902b7e3aa4a..82ad31781bc9 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -225,6 +225,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba);
static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd);
static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
static void ufshcd_hba_exit(struct ufs_hba *hba);
+static int ufshcd_clear_ua_wluns(struct ufs_hba *hba);
static int ufshcd_probe_hba(struct ufs_hba *hba, bool async);
static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
@@ -580,6 +581,23 @@ static void ufshcd_print_pwr_info(struct ufs_hba *hba)
hba->pwr_info.hs_rate);
}
+static void ufshcd_device_reset(struct ufs_hba *hba)
+{
+ int err;
+
+ err = ufshcd_vops_device_reset(hba);
+
+ if (!err) {
+ ufshcd_set_ufs_dev_active(hba);
+ if (ufshcd_is_wb_allowed(hba)) {
+ hba->wb_enabled = false;
+ hba->wb_buf_flush_enabled = false;
+ }
+ }
+ if (err != -EOPNOTSUPP)
+ ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err);
+}
+
void ufshcd_delay_us(unsigned long us, unsigned long tolerance)
{
if (!us)
@@ -3665,7 +3683,7 @@ static int ufshcd_dme_enable(struct ufs_hba *hba)
ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
if (ret)
dev_err(hba->dev,
- "dme-reset: error code %d\n", ret);
+ "dme-enable: error code %d\n", ret);
return ret;
}
@@ -3964,7 +3982,7 @@ int ufshcd_link_recovery(struct ufs_hba *hba)
spin_unlock_irqrestore(hba->host->host_lock, flags);
/* Reset the attached device */
- ufshcd_vops_device_reset(hba);
+ ufshcd_device_reset(hba);
ret = ufshcd_host_reset_and_restore(hba);
@@ -6930,7 +6948,8 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
/* Establish the link again and restore the device */
err = ufshcd_probe_hba(hba, false);
-
+ if (!err)
+ ufshcd_clear_ua_wluns(hba);
out:
if (err)
dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err);
@@ -6968,7 +6987,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
do {
/* Reset the attached device */
- ufshcd_vops_device_reset(hba);
+ ufshcd_device_reset(hba);
err = ufshcd_host_reset_and_restore(hba);
} while (err && --retries);
@@ -8045,7 +8064,7 @@ static int ufshcd_disable_vreg(struct device *dev, struct ufs_vreg *vreg)
{
int ret = 0;
- if (!vreg || !vreg->enabled)
+ if (!vreg || !vreg->enabled || vreg->always_on)
goto out;
ret = regulator_disable(vreg->reg);
@@ -8414,13 +8433,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
* handling context.
*/
hba->host->eh_noresume = 1;
- if (hba->wlun_dev_clr_ua) {
- ret = ufshcd_send_request_sense(hba, sdp);
- if (ret)
- goto out;
- /* Unit attention condition is cleared now */
- hba->wlun_dev_clr_ua = false;
- }
+ ufshcd_clear_ua_wluns(hba);
cmd[4] = pwr_mode << 4;
@@ -8441,7 +8454,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
if (!ret)
hba->curr_dev_pwr_mode = pwr_mode;
-out:
+
scsi_device_put(sdp);
hba->host->eh_noresume = 0;
return ret;
@@ -8747,7 +8760,7 @@ set_link_active:
* further below.
*/
if (ufshcd_is_ufs_dev_deepsleep(hba)) {
- ufshcd_vops_device_reset(hba);
+ ufshcd_device_reset(hba);
WARN_ON(!ufshcd_is_link_off(hba));
}
if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
@@ -8757,7 +8770,7 @@ set_link_active:
set_dev_active:
/* Can also get here needing to exit DeepSleep */
if (ufshcd_is_ufs_dev_deepsleep(hba)) {
- ufshcd_vops_device_reset(hba);
+ ufshcd_device_reset(hba);
ufshcd_host_reset_and_restore(hba);
}
if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
@@ -9353,7 +9366,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
}
/* Reset the attached device */
- ufshcd_vops_device_reset(hba);
+ ufshcd_device_reset(hba);
ufshcd_init_crypto(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index f8c2467dc014..aa9ea3552323 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -1218,16 +1218,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
hba->vops->dbg_register_dump(hba);
}
-static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
+static inline int ufshcd_vops_device_reset(struct ufs_hba *hba)
{
- if (hba->vops && hba->vops->device_reset) {
- int err = hba->vops->device_reset(hba);
-
- if (!err)
- ufshcd_set_ufs_dev_active(hba);
- if (err != -EOPNOTSUPP)
- ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err);
- }
+ if (hba->vops && hba->vops->device_reset)
+ return hba->vops->device_reset(hba);
+
+ return -EOPNOTSUPP;
}
static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index c054e83ab636..871ed721dcfd 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -1351,6 +1351,9 @@ static const struct of_device_id qcom_slim_ngd_dt_match[] = {
},{
.compatible = "qcom,slim-ngd-v2.1.0",
.data = &ngd_v1_5_offset_info,
+ },{
+ .compatible = "qcom,slim-ngd-v2.2.0",
+ .data = &ngd_v1_5_offset_info,
},
{}
};
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 16b421608e9c..c129af62ae82 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -47,6 +47,7 @@
#define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00
#define LLCC_TRP_PCB_ACT 0x21f04
+#define LLCC_TRP_WRSC_EN 0x21f20
#define BANK_OFFSET_STRIDE 0x80000
@@ -73,6 +74,7 @@
* then the ways assigned to this client are not flushed on power
* collapse.
* @activate_on_init: Activate the slice immediately after it is programmed
+ * @write_scid_en: Bit enables write cache support for a given scid.
*/
struct llcc_slice_config {
u32 usecase_id;
@@ -87,12 +89,14 @@ struct llcc_slice_config {
bool dis_cap_alloc;
bool retain_on_pc;
bool activate_on_init;
+ bool write_scid_en;
};
struct qcom_llcc_config {
const struct llcc_slice_config *sct_data;
int size;
bool need_llcc_cfg;
+ bool need_write_scid;
};
static const struct llcc_slice_config sc7180_data[] = {
@@ -147,6 +151,25 @@ static const struct llcc_slice_config sm8150_data[] = {
{ LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 },
};
+static const struct llcc_slice_config sm8250_data[] = {
+ { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
+ { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
+ { LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
+ { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 },
+ { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
+ { LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+ { LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 },
+ { LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
+ { LLCC_CVPFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+};
+
static const struct qcom_llcc_config sc7180_cfg = {
.sct_data = sc7180_data,
.size = ARRAY_SIZE(sc7180_data),
@@ -164,6 +187,11 @@ static const struct qcom_llcc_config sm8150_cfg = {
.size = ARRAY_SIZE(sm8150_data),
};
+static const struct qcom_llcc_config sm8250_cfg = {
+ .sct_data = sm8250_data,
+ .size = ARRAY_SIZE(sm8250_data),
+};
+
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
/**
@@ -413,6 +441,16 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
return ret;
}
+ if (cfg->need_write_scid) {
+ u32 mask = BIT(config->write_scid_en);
+ u32 val = config->write_scid_en << config->slice_id;
+
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ LLCC_TRP_WRSC_EN, mask, val);
+ if (ret)
+ return ret;
+ }
+
if (config->activate_on_init) {
desc.slice_id = config->slice_id;
ret = llcc_slice_activate(&desc);
@@ -428,6 +466,7 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
u32 sz;
int ret = 0;
const struct llcc_slice_config *llcc_table;
+ u32 wren = 0;
sz = drv_data->cfg_size;
llcc_table = drv_data->cfg;
@@ -559,6 +598,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfg },
{ .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
{ .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
+ { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
{ }
};
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index d21530d24253..014d7a5a3751 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -15,6 +15,8 @@
#include <linux/sys_soc.h>
#include <linux/types.h>
+#include <asm/unaligned.h>
+
/*
* SoC version type with major number in the upper 16 bits and minor
* number in the lower 16 bits.
@@ -83,6 +85,11 @@ static const char *const pmic_models[] = {
[23] = "PM8038",
[24] = "PM8922",
[25] = "PM8917",
+ [30] = "PM8150",
+ [31] = "PM8150L",
+ [32] = "PM8150B",
+ [33] = "PMK8002",
+ [36] = "PM8009",
};
#endif /* CONFIG_DEBUG_FS */
@@ -234,6 +241,7 @@ static const struct soc_id soc_id[] = {
{ 356, "SM8250" },
{ 402, "IPQ6018" },
{ 425, "SC7180" },
+ { 455, "QRB5165" },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
@@ -294,6 +302,32 @@ static int qcom_show_pmic_model(struct seq_file *seq, void *p)
return 0;
}
+static int qcom_show_pmic_model_array(struct seq_file *seq, void *p)
+{
+ struct socinfo *socinfo = seq->private;
+ unsigned int num_pmics = le32_to_cpu(socinfo->num_pmics);
+ unsigned int pmic_array_offset = le32_to_cpu(socinfo->pmic_array_offset);
+ int i;
+ void *ptr = socinfo;
+
+ ptr += pmic_array_offset;
+
+ /* No need for bounds checking, it happened at socinfo_debugfs_init */
+ for (i = 0; i < num_pmics; i++) {
+ unsigned int model = SOCINFO_MINOR(get_unaligned_le32(ptr + 2 * i * sizeof(u32)));
+ unsigned int die_rev = get_unaligned_le32(ptr + (2 * i + 1) * sizeof(u32));
+
+ if (model <= ARRAY_SIZE(pmic_models) && pmic_models[model])
+ seq_printf(seq, "%s %u.%u\n", pmic_models[model],
+ SOCINFO_MAJOR(le32_to_cpu(die_rev)),
+ SOCINFO_MINOR(le32_to_cpu(die_rev)));
+ else
+ seq_printf(seq, "unknown (%d)\n", model);
+ }
+
+ return 0;
+}
+
static int qcom_show_pmic_die_revision(struct seq_file *seq, void *p)
{
struct socinfo *socinfo = seq->private;
@@ -316,6 +350,7 @@ static int qcom_show_chip_id(struct seq_file *seq, void *p)
QCOM_OPEN(build_id, qcom_show_build_id);
QCOM_OPEN(pmic_model, qcom_show_pmic_model);
+QCOM_OPEN(pmic_model_array, qcom_show_pmic_model_array);
QCOM_OPEN(pmic_die_rev, qcom_show_pmic_die_revision);
QCOM_OPEN(chip_id, qcom_show_chip_id);
@@ -344,12 +379,14 @@ DEFINE_IMAGE_OPS(variant);
DEFINE_IMAGE_OPS(oem);
static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
- struct socinfo *info)
+ struct socinfo *info, size_t info_size)
{
struct smem_image_version *versions;
struct dentry *dentry;
size_t size;
int i;
+ unsigned int num_pmics;
+ unsigned int pmic_array_offset;
qcom_socinfo->dbg_root = debugfs_create_dir("qcom_socinfo", NULL);
@@ -405,6 +442,11 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
&qcom_socinfo->info.raw_device_num);
fallthrough;
case SOCINFO_VERSION(0, 11):
+ num_pmics = le32_to_cpu(info->num_pmics);
+ pmic_array_offset = le32_to_cpu(info->pmic_array_offset);
+ if (pmic_array_offset + 2 * num_pmics * sizeof(u32) <= info_size)
+ DEBUGFS_ADD(info, pmic_model_array);
+ fallthrough;
case SOCINFO_VERSION(0, 10):
case SOCINFO_VERSION(0, 9):
qcom_socinfo->info.foundry_id = __le32_to_cpu(info->foundry_id);
@@ -482,7 +524,7 @@ static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo)
}
#else
static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo,
- struct socinfo *info)
+ struct socinfo *info, size_t info_size)
{
}
static void socinfo_debugfs_exit(struct qcom_socinfo *qcom_socinfo) { }
@@ -522,7 +564,7 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
if (IS_ERR(qs->soc_dev))
return PTR_ERR(qs->soc_dev);
- socinfo_debugfs_init(qs, info);
+ socinfo_debugfs_init(qs, info, item_size);
/* Feed the soc specific unique data into entropy pool */
add_device_randomness(info, item_size);
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
index aa9c1d80fae4..8d5ac2df26dc 100644
--- a/drivers/thermal/qcom/Kconfig
+++ b/drivers/thermal/qcom/Kconfig
@@ -10,6 +10,17 @@ config QCOM_TSENS
Also able to set threshold temperature for both hot and cold and update
when a threshold is reached.
+config QCOM_SPMI_ADC_TM5
+ tristate "Qualcomm SPMI PMIC Thermal Monitor ADC5"
+ depends on OF && SPMI && IIO
+ select REGMAP_SPMI
+ select QCOM_VADC_COMMON
+ help
+ This enables the thermal driver for the ADC thermal monitoring
+ device. It shows up as a thermal zone with multiple trip points.
+ Thermal client sets threshold temperature for both warm and cool and
+ gets updated when a threshold is reached.
+
config QCOM_SPMI_TEMP_ALARM
tristate "Qualcomm SPMI PMIC Temperature Alarm"
depends on OF && SPMI && IIO
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index ec86eef7f6a6..252ea7d9da0b 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o
qcom_tsens-y += tsens.o tsens-v2.o tsens-v1.o tsens-v0_1.o \
tsens-8960.o
+obj-$(CONFIG_QCOM_SPMI_ADC_TM5) += qcom-spmi-adc-tm5.o
obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
new file mode 100644
index 000000000000..124102e9c1fb
--- /dev/null
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020 Linaro Limited
+ */
+
+#include <linux/bitfield.h>
+#include <linux/iio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+
+#include "../../iio/adc/qcom-vadc-common.h"
+
+#define ADC5_MAX_CHANNEL 0xc0
+#define ADC_TM5_NUM_CHANNELS 8
+
+#define ADC_TM5_STATUS_LOW 0x0a
+
+#define ADC_TM5_STATUS_HIGH 0x0b
+
+#define ADC_TM5_NUM_BTM 0x0f
+
+#define ADC_TM5_ADC_DIG_PARAM 0x42
+
+#define ADC_TM5_FAST_AVG_CTL (ADC_TM5_ADC_DIG_PARAM + 1)
+#define ADC_TM5_FAST_AVG_EN BIT(7)
+
+#define ADC_TM5_MEAS_INTERVAL_CTL (ADC_TM5_ADC_DIG_PARAM + 2)
+#define ADC_TM5_TIMER1 3 /* 3.9ms */
+
+#define ADC_TM5_MEAS_INTERVAL_CTL2 (ADC_TM5_ADC_DIG_PARAM + 3)
+#define ADC_TM5_MEAS_INTERVAL_CTL2_MASK 0xf0
+#define ADC_TM5_TIMER2 10 /* 1 second */
+#define ADC_TM5_MEAS_INTERVAL_CTL3_MASK 0xf
+#define ADC_TM5_TIMER3 4 /* 4 second */
+
+#define ADC_TM5_M_CHAN_BASE 0x60
+
+#define ADC_TM5_M_ADC_CH_SEL_CTL(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 0)
+#define ADC_TM5_M_LOW_THR0(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 1)
+#define ADC_TM5_M_LOW_THR1(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 2)
+#define ADC_TM5_M_HIGH_THR0(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 3)
+#define ADC_TM5_M_HIGH_THR1(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 4)
+#define ADC_TM5_M_MEAS_INTERVAL_CTL(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 5)
+#define ADC_TM5_M_CTL(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 6)
+#define ADC_TM5_M_CTL_HW_SETTLE_DELAY_MASK 0xf
+#define ADC_TM5_M_CTL_CAL_SEL_MASK 0x30
+#define ADC_TM5_M_CTL_CAL_VAL 0x40
+#define ADC_TM5_M_EN(n) (ADC_TM5_M_CHAN_BASE + (n * 8) + 7)
+#define ADC_TM5_M_MEAS_EN BIT(7)
+#define ADC_TM5_M_HIGH_THR_INT_EN BIT(1)
+#define ADC_TM5_M_LOW_THR_INT_EN BIT(0)
+
+
+enum adc5_timer_select {
+ ADC5_TIMER_SEL_1 = 0,
+ ADC5_TIMER_SEL_2,
+ ADC5_TIMER_SEL_3,
+ ADC5_TIMER_SEL_NONE,
+};
+
+struct adc_tm5_data {
+ const u32 full_scale_code_volt;
+ unsigned int *decimation;
+ unsigned int *hw_settle;
+};
+
+enum adc_tm5_cal_method {
+ ADC_TM5_NO_CAL = 0,
+ ADC_TM5_RATIOMETRIC_CAL,
+ ADC_TM5_ABSOLUTE_CAL
+};
+
+struct adc_tm5_chip;
+
+struct adc_tm5_channel {
+ unsigned int channel;
+ unsigned int adc_channel;
+ enum adc_tm5_cal_method cal_method;
+ unsigned int prescale;
+ unsigned int hw_settle_time;
+ struct iio_channel *iio;
+ struct adc_tm5_chip *chip;
+ struct thermal_zone_device *tzd;
+};
+
+/**
+ * struct adc_tm5_chip - ADC Thermal Monitoring properties
+ * @nchannels: amount of channels defined/allocated
+ * @decimation: sampling rate supported for the channel.
+ * @avg_samples: ability to provide single result from the ADC
+ * that is an average of multiple measurements.
+ * @base: base address of TM registers.
+ */
+struct adc_tm5_chip {
+ struct regmap *regmap;
+ struct device *dev;
+ const struct adc_tm5_data *data;
+ struct adc_tm5_channel *channels;
+ unsigned int nchannels;
+ unsigned int decimation;
+ unsigned int avg_samples;
+ u16 base;
+};
+
+static const struct adc_tm5_data adc_tm5_data_pmic = {
+ .full_scale_code_volt = 0x70e4,
+ .decimation = (unsigned int []) {250, 420, 840},
+ .hw_settle = (unsigned int []) {15, 100, 200, 300, 400, 500, 600, 700,
+ 1, 2, 4, 8, 16, 32, 64, 128},
+};
+
+static int adc_tm5_read(struct adc_tm5_chip *adc_tm, u16 offset, u8 *data, int len)
+{
+ return regmap_bulk_read(adc_tm->regmap, adc_tm->base + offset, data, len);
+}
+
+static int adc_tm5_write(struct adc_tm5_chip *adc_tm, u16 offset, u8 *data, int len)
+{
+ return regmap_bulk_write(adc_tm->regmap, adc_tm->base + offset, data, len);
+}
+
+static int adc_tm5_reg_update(struct adc_tm5_chip *adc_tm, u16 offset, u8 mask, u8 val)
+{
+ return regmap_write_bits(adc_tm->regmap, adc_tm->base + offset, mask, val);
+}
+
+static irqreturn_t adc_tm5_isr(int irq, void *data)
+{
+ struct adc_tm5_chip *chip = data;
+ u8 status_low, status_high, ctl;
+ int ret = 0, i = 0;
+
+ ret = adc_tm5_read(chip, ADC_TM5_STATUS_LOW, &status_low, 1);
+ if (ret) {
+ dev_err(chip->dev, "read status low failed with %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ ret = adc_tm5_read(chip, ADC_TM5_STATUS_HIGH, &status_high, 1);
+ if (ret) {
+ dev_err(chip->dev, "read status high failed with %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ for (i = 0; i < chip->nchannels; i++) {
+ bool upper_set = false, lower_set = false;
+ unsigned int ch = chip->channels[i].channel;
+
+ if (!chip->channels[i].tzd) {
+ dev_err_once(chip->dev, "thermal device not found\n");
+ continue;
+ }
+
+ ret = adc_tm5_read(chip, ADC_TM5_M_EN(ch), &ctl, 1);
+
+ if (ret) {
+ dev_err(chip->dev, "ctl read failed with %d\n", ret);
+ continue;
+ }
+
+ lower_set = (status_low & BIT(ch)) &&
+ (ctl & ADC_TM5_M_MEAS_EN) &&
+ (ctl & ADC_TM5_M_LOW_THR_INT_EN);
+
+ upper_set = (status_high & BIT(ch)) &&
+ (ctl & ADC_TM5_M_MEAS_EN) &&
+ (ctl & ADC_TM5_M_HIGH_THR_INT_EN);
+
+ if (upper_set || lower_set)
+ thermal_zone_device_update(chip->channels[i].tzd,
+ THERMAL_EVENT_UNSPECIFIED);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int adc_tm5_get_temp(void *data, int *temp)
+{
+ struct adc_tm5_channel *channel = data;
+ int ret, milli_celsius;
+
+ if (!channel || !channel->iio)
+ return -EINVAL;
+
+ ret = iio_read_channel_processed(channel->iio, &milli_celsius);
+ if (ret < 0)
+ return ret;
+
+ *temp = milli_celsius;
+
+ return 0;
+}
+
+static int adc_tm5_disable_channel(struct adc_tm5_channel *channel)
+{
+ struct adc_tm5_chip *chip = channel->chip;
+ unsigned int reg = ADC_TM5_M_EN(channel->channel);
+
+ return adc_tm5_reg_update(chip, reg,
+ ADC_TM5_M_MEAS_EN | ADC_TM5_M_HIGH_THR_INT_EN | ADC_TM5_M_LOW_THR_INT_EN,
+ 0);
+}
+
+static int adc_tm5_configure(struct adc_tm5_channel *channel, int low_temp, int high_temp)
+{
+ struct adc_tm5_chip *chip = channel->chip;
+ u8 buf[8];
+ u16 reg = ADC_TM5_M_ADC_CH_SEL_CTL(channel->channel);
+ int ret = 0;
+
+ ret = adc_tm5_read(chip, reg, buf, 8);
+ if (ret) {
+ dev_err(chip->dev, "block read failed with %d\n", ret);
+ return ret;
+ }
+
+ /* Update ADC channel select */
+ buf[0] = channel->adc_channel;
+
+ /* Warm temperature corresponds to low voltage threshold */
+ if (high_temp != INT_MAX) {
+ u16 adc_code = qcom_adc_tm5_temp_volt_scale(channel->prescale,
+ chip->data->full_scale_code_volt, high_temp);
+
+ buf[1] = adc_code & 0xff;
+ buf[2] = adc_code >> 8;
+ buf[7] |= ADC_TM5_M_LOW_THR_INT_EN;
+ }
+
+ /* Cool temperature corresponds to high voltage threshold */
+ if (low_temp != -INT_MAX) {
+ u16 adc_code = qcom_adc_tm5_temp_volt_scale(channel->prescale,
+ chip->data->full_scale_code_volt, low_temp);
+
+ buf[3] = adc_code & 0xff;
+ buf[4] = adc_code >> 8;
+ buf[7] |= ADC_TM5_M_HIGH_THR_INT_EN;
+ }
+
+ /* Update timer select */
+ buf[5] = ADC5_TIMER_SEL_2;
+
+ /* Set calibration select, hw_settle delay */
+ buf[6] &= ~ADC_TM5_M_CTL_HW_SETTLE_DELAY_MASK;
+ buf[6] |= FIELD_PREP(ADC_TM5_M_CTL_HW_SETTLE_DELAY_MASK, channel->hw_settle_time);
+ buf[6] &= ~ADC_TM5_M_CTL_CAL_SEL_MASK;
+ buf[6] |= FIELD_PREP(ADC_TM5_M_CTL_CAL_SEL_MASK, channel->cal_method);
+
+ buf[7] |= ADC_TM5_M_MEAS_EN;
+
+ ret = adc_tm5_write(chip, reg, buf, 8);
+ if (ret)
+ dev_err(chip->dev, "buf write failed\n");
+
+ return ret;
+}
+
+static int adc_tm5_set_trips(void *data, int low_temp, int high_temp)
+{
+ struct adc_tm5_channel *channel = data;
+ struct adc_tm5_chip *chip;
+ int ret;
+
+ if (!channel)
+ return -EINVAL;
+
+ chip = channel->chip;
+ dev_dbg(chip->dev, "%d:low_temp(mdegC):%d, high_temp(mdegC):%d\n",
+ channel->channel, low_temp, high_temp);
+
+ if (high_temp == INT_MAX && low_temp <= -INT_MAX)
+ ret = adc_tm5_disable_channel(channel);
+ else
+ ret = adc_tm5_configure(channel, low_temp, high_temp);
+
+ return ret;
+}
+
+
+static struct thermal_zone_of_device_ops adc_tm5_ops = {
+ .get_temp = adc_tm5_get_temp,
+ .set_trips = adc_tm5_set_trips,
+};
+
+static int adc_tm5_register_tzd(struct adc_tm5_chip *adc_tm)
+{
+ unsigned int i;
+ struct thermal_zone_device *tzd;
+
+ for (i = 0; i < adc_tm->nchannels; i++) {
+ adc_tm->channels[i].chip = adc_tm;
+
+ tzd = devm_thermal_zone_of_sensor_register(
+ adc_tm->dev, adc_tm->channels[i].channel,
+ &adc_tm->channels[i], &adc_tm5_ops);
+ if (IS_ERR(tzd)) {
+ dev_err(adc_tm->dev, "Error registering TZ zone:%ld for channel:%d\n",
+ PTR_ERR(tzd), adc_tm->channels[i].channel);
+ continue;
+ }
+ adc_tm->channels[i].tzd = tzd;
+ }
+
+ return 0;
+}
+
+static int adc_tm5_init(struct adc_tm5_chip *chip)
+{
+ u8 buf[4], channels_available;
+ int ret;
+ unsigned int i;
+
+ ret = adc_tm5_read(chip, ADC_TM5_NUM_BTM, &channels_available, 1);
+ if (ret) {
+ dev_err(chip->dev, "read failed for BTM channels\n");
+ return ret;
+ }
+
+ ret = adc_tm5_read(chip, ADC_TM5_ADC_DIG_PARAM, buf, 4);
+ if (ret) {
+ dev_err(chip->dev, "block read failed with %d\n", ret);
+ return ret;
+ }
+
+ /* Select decimation */
+ buf[0] = chip->decimation;
+
+ /* Select number of samples in fast average mode */
+ buf[1] = chip->avg_samples | ADC_TM5_FAST_AVG_EN;
+
+ /* Select timer1 */
+ buf[2] = ADC_TM5_TIMER1;
+
+ /* Select timer2 and timer3 */
+ buf[3] = FIELD_PREP(ADC_TM5_MEAS_INTERVAL_CTL2_MASK, ADC_TM5_TIMER2) |
+ FIELD_PREP(ADC_TM5_MEAS_INTERVAL_CTL3_MASK, ADC_TM5_TIMER3);
+
+ ret = adc_tm5_write(chip, ADC_TM5_ADC_DIG_PARAM, buf, 4);
+ if (ret)
+ dev_err(chip->dev, "block write failed with %d\n", ret);
+
+ for (i = 0; i < chip->nchannels; i++) {
+ if (chip->channels[i].channel >= channels_available) {
+ dev_err(chip->dev, "Invalid channel %d\n", chip->channels[i].channel);
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+static int adc_tm5_get_dt_channel_data(struct adc_tm5_chip *adc_tm,
+ struct adc_tm5_channel *channel,
+ struct device_node *node)
+{
+ const char *name = node->name;
+ u32 chan, value, varr[2];
+ int ret;
+ struct device *dev = adc_tm->dev;
+
+ ret = of_property_read_u32(node, "reg", &chan);
+ if (ret) {
+ dev_err(dev, "invalid channel number %s\n", name);
+ return ret;
+ }
+
+ if (chan >= ADC_TM5_NUM_CHANNELS) {
+ dev_err(dev, "%s invalid channel number %d\n", name, chan);
+ return -EINVAL;
+ }
+
+ /* the channel has DT description */
+ channel->channel = chan;
+
+ ret = of_property_read_u32(node, "qcom,adc-channel", &chan);
+ if (ret) {
+ dev_err(dev, "invalid channel number %s\n", name);
+ return ret;
+ }
+ if (chan >= ADC5_MAX_CHANNEL) {
+ dev_err(dev, "%s invalid ADC channel number %d\n", name, chan);
+ return ret;
+ }
+ channel->adc_channel = chan;
+
+ channel->iio = devm_iio_channel_get(adc_tm->dev, name);
+ if (IS_ERR(channel->iio)) {
+ ret = PTR_ERR(channel->iio);
+ channel->iio = NULL;
+ dev_err(dev, "error getting channel %s: %d\n", name, ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
+ if (!ret) {
+ ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]);
+ if (ret < 0) {
+ dev_err(dev, "%02x invalid pre-scaling <%d %d>\n",
+ chan, varr[0], varr[1]);
+ return ret;
+ }
+ channel->prescale = ret;
+ } else {
+ /* 1:1 prescale is index 0 */
+ channel->prescale = 0;
+ }
+
+ ret = of_property_read_u32(node, "qcom,hw-settle-time", &value);
+ if (!ret) {
+ ret = qcom_adc5_hw_settle_time_from_dt(value, adc_tm->data->hw_settle);
+ if (ret < 0) {
+ dev_err(dev, "%02x invalid hw-settle-time %d us\n",
+ chan, value);
+ return ret;
+ }
+ channel->hw_settle_time = ret;
+ } else {
+ channel->hw_settle_time = VADC_DEF_HW_SETTLE_TIME;
+ }
+
+ if (of_property_read_bool(node, "qcom,ratiometric"))
+ channel->cal_method = ADC_TM5_RATIOMETRIC_CAL;
+ else
+ channel->cal_method = ADC_TM5_ABSOLUTE_CAL;
+
+ return 0;
+}
+
+static int adc_tm5_get_dt_data(struct adc_tm5_chip *adc_tm, struct device_node *node)
+{
+ struct adc_tm5_channel *channels;
+ struct device_node *child;
+ unsigned int index = 0;
+ u32 value;
+ int ret;
+ struct device *dev = adc_tm->dev;
+
+ adc_tm->nchannels = of_get_available_child_count(node);
+ if (!adc_tm->nchannels)
+ return -EINVAL;
+
+ adc_tm->channels = devm_kcalloc(dev, adc_tm->nchannels,
+ sizeof(*adc_tm->channels), GFP_KERNEL);
+ if (!adc_tm->channels)
+ return -ENOMEM;
+
+ channels = adc_tm->channels;
+
+ adc_tm->data = of_device_get_match_data(dev);
+
+ ret = of_property_read_u32(node, "qcom,decimation", &value);
+ if (!ret) {
+ ret = qcom_adc5_decimation_from_dt(value, adc_tm->data->decimation);
+ if (ret < 0) {
+ dev_err(dev, "invalid decimation %d\n", value);
+ return ret;
+ }
+ adc_tm->decimation = ret;
+ } else {
+ adc_tm->decimation = ADC5_DECIMATION_DEFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,avg-samples", &value);
+ if (!ret) {
+ ret = qcom_adc5_avg_samples_from_dt(value);
+ if (ret < 0) {
+ dev_err(dev, "invalid avg-samples %d\n", value);
+ return ret;
+ }
+ adc_tm->avg_samples = ret;
+ } else {
+ adc_tm->avg_samples = VADC_DEF_AVG_SAMPLES;
+ }
+
+ for_each_available_child_of_node(node, child) {
+ ret = adc_tm5_get_dt_channel_data(adc_tm, channels, child);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+
+ channels++;
+ index++;
+ }
+
+ return 0;
+}
+
+static int adc_tm5_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+ struct adc_tm5_chip *adc_tm;
+ struct regmap *regmap;
+ int ret, irq;
+ u32 reg;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
+ return -ENODEV;
+
+ ret = of_property_read_u32(node, "reg", &reg);
+ if (ret)
+ return ret;
+
+ adc_tm = devm_kzalloc(&pdev->dev, sizeof(*adc_tm), GFP_KERNEL);
+ if (!adc_tm)
+ return -ENOMEM;
+
+ adc_tm->regmap = regmap;
+ adc_tm->dev = dev;
+ adc_tm->base = reg;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "get_irq failed: %d\n", irq);
+ return irq;
+ }
+
+ ret = adc_tm5_get_dt_data(adc_tm, node);
+ if (ret) {
+ dev_err(dev, "get dt data failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = adc_tm5_init(adc_tm);
+ if (ret) {
+ dev_err(dev, "adc-tm init failed\n");
+ return ret;
+ }
+
+ ret = adc_tm5_register_tzd(adc_tm);
+ if (ret) {
+ dev_err(dev, "tzd register failed\n");
+ return ret;
+ }
+
+ return devm_request_irq(dev, irq, adc_tm5_isr, 0,
+ "pm-adc-tm5", adc_tm);
+}
+
+static const struct of_device_id adc_tm5_match_table[] = {
+ {
+ .compatible = "qcom,spmi-adc-tm5",
+ .data = &adc_tm5_data_pmic,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adc_tm5_match_table);
+
+static struct platform_driver adc_tm5_driver = {
+ .driver = {
+ .name = "spmi-adc-tm5",
+ .of_match_table = adc_tm5_match_table,
+ },
+ .probe = adc_tm5_probe,
+};
+module_platform_driver(adc_tm5_driver);
+
+MODULE_DESCRIPTION("SPMI PMIC Thermal Monitor ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index c703d552bbcf..654511c9905b 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -20,6 +20,8 @@
#include <linux/usb/of.h>
#include <linux/reset.h>
#include <linux/iopoll.h>
+#include <linux/fwnode.h>
+#include <linux/usb/role.h>
#include "core.h"
@@ -80,6 +82,9 @@ struct dwc3_qcom {
struct notifier_block vbus_nb;
struct notifier_block host_nb;
+ struct usb_role_switch *role_sw;
+ struct usb_role_switch *dwc3_drd_sw;
+
const struct dwc3_acpi_pdata *acpi_pdata;
enum usb_dr_mode mode;
@@ -113,7 +118,7 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
-static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool enable)
+static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
{
if (enable) {
dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
@@ -134,7 +139,7 @@ static int dwc3_qcom_vbus_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
/* enable vbus override for device mode */
- dwc3_qcom_vbus_overrride_enable(qcom, event);
+ dwc3_qcom_vbus_override_enable(qcom, event);
qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
return NOTIFY_DONE;
@@ -146,7 +151,7 @@ static int dwc3_qcom_host_notifier(struct notifier_block *nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
/* disable vbus override in host mode */
- dwc3_qcom_vbus_overrride_enable(qcom, !event);
+ dwc3_qcom_vbus_override_enable(qcom, !event);
qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
return NOTIFY_DONE;
@@ -291,6 +296,73 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
icc_put(qcom->icc_path_apps);
}
+static int dwc3_qcom_usb_role_switch_set(struct usb_role_switch *sw,
+ enum usb_role role)
+{
+ struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
+ struct fwnode_handle *child;
+ bool enable = false;
+
+ if (!qcom->dwc3_drd_sw) {
+ child = device_get_next_child_node(qcom->dev, NULL);
+ if (child) {
+ qcom->dwc3_drd_sw = usb_role_switch_find_by_fwnode(child);
+ fwnode_handle_put(child);
+ if (IS_ERR(qcom->dwc3_drd_sw)) {
+ qcom->dwc3_drd_sw = NULL;
+ return 0;
+ }
+ }
+ }
+
+ usb_role_switch_set_role(qcom->dwc3_drd_sw, role);
+
+ if (role == USB_ROLE_DEVICE)
+ enable = true;
+ else
+ enable = false;
+
+ qcom->mode = (role == USB_ROLE_HOST) ? USB_DR_MODE_HOST :
+ USB_DR_MODE_PERIPHERAL;
+ dwc3_qcom_vbus_override_enable(qcom, enable);
+ return 0;
+}
+
+static enum usb_role dwc3_qcom_usb_role_switch_get(struct usb_role_switch *sw)
+{
+ struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
+ enum usb_role role;
+
+ switch (qcom->mode) {
+ case USB_DR_MODE_HOST:
+ role = USB_ROLE_HOST;
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ role = USB_ROLE_DEVICE;
+ break;
+ default:
+ role = USB_ROLE_DEVICE;
+ break;
+ }
+
+ return role;
+}
+
+static int dwc3_qcom_setup_role_switch(struct dwc3_qcom *qcom)
+{
+ struct usb_role_switch_desc dwc3_role_switch = {NULL};
+
+ dwc3_role_switch.fwnode = dev_fwnode(qcom->dev);
+ dwc3_role_switch.set = dwc3_qcom_usb_role_switch_set;
+ dwc3_role_switch.get = dwc3_qcom_usb_role_switch_get;
+ dwc3_role_switch.driver_data = qcom;
+ qcom->role_sw = usb_role_switch_register(qcom->dev, &dwc3_role_switch);
+ if (IS_ERR(qcom->role_sw))
+ return PTR_ERR(qcom->role_sw);
+
+ return 0;
+}
+
static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
{
if (qcom->hs_phy_irq) {
@@ -651,6 +723,40 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)
return 0;
}
+static int dwc3_qcom_connector_check(struct fwnode_handle *fwnode)
+{
+ if (fwnode && (!fwnode_property_match_string(fwnode, "compatible",
+ "gpio-usb-b-connector") ||
+ !fwnode_property_match_string(fwnode, "compatible",
+ "usb-c-connector")))
+ return 1;
+
+ return 0;
+}
+
+static void *dwc3_qcom_find_usb_connector_match(struct fwnode_handle *fwnode,
+ const char *id, void *data)
+{
+ /* Check if the "connector" node is the parent of the remote endpoint */
+ if (dwc3_qcom_connector_check(fwnode))
+ return fwnode;
+
+ /* else, check if it is a child node */
+ fwnode = fwnode_get_named_child_node(fwnode, "connector");
+ if (dwc3_qcom_connector_check(fwnode))
+ return fwnode;
+
+ return 0;
+}
+
+static bool dwc3_qcom_find_usb_connector(struct platform_device *pdev)
+{
+ struct fwnode_handle *fwnode = pdev->dev.fwnode;
+
+ return fwnode_connection_find_match(fwnode, "connector", NULL,
+ dwc3_qcom_find_usb_connector_match);
+}
+
static int dwc3_qcom_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -757,10 +863,15 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
/* enable vbus override for device mode */
if (qcom->mode == USB_DR_MODE_PERIPHERAL)
- dwc3_qcom_vbus_overrride_enable(qcom, true);
+ dwc3_qcom_vbus_override_enable(qcom, true);
+
+ if (dwc3_qcom_find_usb_connector(pdev)) {
+ ret = dwc3_qcom_setup_role_switch(qcom);
+ } else {
+ /* register extcon to override sw_vbus on Vbus change later */
+ ret = dwc3_qcom_register_extcon(qcom);
+ }
- /* register extcon to override sw_vbus on Vbus change later */
- ret = dwc3_qcom_register_extcon(qcom);
if (ret)
goto interconnect_exit;
@@ -796,6 +907,9 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int i;
+ usb_role_switch_unregister(qcom->role_sw);
+ usb_role_switch_put(qcom->dwc3_drd_sw);
+
of_platform_depopulate(dev);
for (i = qcom->num_clocks - 1; i >= 0; i--) {
diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
index f97ac9f52bf4..f7a4d2dea439 100644
--- a/drivers/usb/host/xhci-pci-renesas.c
+++ b/drivers/usb/host/xhci-pci-renesas.c
@@ -2,6 +2,7 @@
/* Copyright (C) 2019-2020 Linaro Limited */
#include <linux/acpi.h>
+#include <linux/debugfs.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -50,6 +51,20 @@
#define RENESAS_RETRY 10000
#define RENESAS_DELAY 10
+#define ROM_VALID_01 0x2013
+#define ROM_VALID_02 0x2026
+
+static int renesas_verify_fw_version(struct pci_dev *pdev, u32 version)
+{
+ switch (version) {
+ case ROM_VALID_01:
+ case ROM_VALID_02:
+ return 0;
+ }
+ dev_err(&pdev->dev, "FW has invalid version :%d\n", version);
+ return -EINVAL;
+}
+
static int renesas_fw_download_image(struct pci_dev *dev,
const u32 *fw, size_t step, bool rom)
{
@@ -156,6 +171,8 @@ static int renesas_fw_verify(const void *fw_data,
return 0;
}
+static void debugfs_init(struct pci_dev *pdev);
+
static bool renesas_check_rom(struct pci_dev *pdev)
{
u16 rom_status;
@@ -169,6 +186,7 @@ static bool renesas_check_rom(struct pci_dev *pdev)
rom_status &= RENESAS_ROM_STATUS_ROM_EXISTS;
if (rom_status) {
dev_dbg(&pdev->dev, "External ROM exists\n");
+ debugfs_init(pdev);
return true; /* External ROM exists */
}
@@ -188,7 +206,10 @@ static int renesas_check_rom_state(struct pci_dev *pdev)
version &= RENESAS_FW_VERSION_FIELD;
version = version >> RENESAS_FW_VERSION_OFFSET;
- dev_dbg(&pdev->dev, "Found ROM version: %x\n", version);
+
+ err = renesas_verify_fw_version(pdev, version);
+ if (err)
+ return err;
/*
* Test if ROM is present and loaded, if so we can skip everything
@@ -432,6 +453,34 @@ static void renesas_rom_erase(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "ROM Erase... Done success\n");
}
+static int debugfs_rom_erase(void *data, u64 value)
+{
+ struct pci_dev *pdev = data;
+
+ if (value == 1) {
+ dev_dbg(&pdev->dev, "Userspace requested ROM erase\n");
+ renesas_rom_erase(pdev);
+ return 0;
+ }
+ return -EINVAL;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(rom_erase_ops, NULL, debugfs_rom_erase, "%llu\n");
+
+static struct dentry *debugfs_root;
+
+static void debugfs_init(struct pci_dev *pdev)
+{
+ debugfs_root = debugfs_create_dir("renesas_usb", NULL);
+
+ debugfs_create_file("rom_erase", 0200, debugfs_root,
+ pdev, &rom_erase_ops);
+}
+
+static void debugfs_exit(void)
+{
+ debugfs_remove_recursive(debugfs_root);
+}
+
static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
{
const u32 *fw_data = (const u32 *)fw->data;
@@ -622,6 +671,7 @@ EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw);
void renesas_xhci_pci_exit(struct pci_dev *dev)
{
+ debugfs_exit();
}
EXPORT_SYMBOL_GPL(renesas_xhci_pci_exit);
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index edead555835e..087981d59f9f 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -19,4 +19,11 @@ config TYPEC_MUX_INTEL_PMC
control the USB role switch and also the multiplexer/demultiplexer
switches used with USB Type-C Alternate Modes.
+config TYPEC_MUX_GPIO
+ tristate "GPIO DP aux switch"
+ depends on I2C
+ help
+ Driver for GPIO-controlled DP aux switch, to flip DP aux lanes
+ when orientation changes.
+
endmenu
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
index 280a6f553115..4aeebe4df61f 100644
--- a/drivers/usb/typec/mux/Makefile
+++ b/drivers/usb/typec/mux/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o
obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
+obj-$(CONFIG_TYPEC_MUX_GPIO) += gpio_aux_switch.o
diff --git a/drivers/usb/typec/mux/gpio_aux_switch.c b/drivers/usb/typec/mux/gpio_aux_switch.c
new file mode 100644
index 000000000000..6236b2a0b702
--- /dev/null
+++ b/drivers/usb/typec/mux/gpio_aux_switch.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for GPIO controlled aux switch
+ *
+ * Copyright (C) 2020 The Linux Foundation
+ */
+
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/pd.h>
+
+struct gpio_aux_switch {
+ struct typec_mux *typec_mux;
+ struct gpio_desc *gpio_en, *gpio_cc;
+};
+
+static int gpio_typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state)
+{
+ struct gpio_aux_switch *gas = typec_mux_get_drvdata(mux);
+ bool enable = false, reverse = false;
+
+ if (!state->alt)
+ return 0;
+
+ if (typec_altmode_get_orientation(state->alt) == TYPEC_ORIENTATION_REVERSE)
+ reverse = true;
+
+ if (state->alt->svid == USB_TYPEC_DP_SID && state->alt->active)
+ enable = true;
+
+ gpiod_set_value(gas->gpio_en, !enable);
+ gpiod_set_value(gas->gpio_cc, reverse);
+
+ return 0;
+}
+
+static int gpio_aux_switch_probe(struct platform_device *pdev)
+{
+ struct typec_mux_desc mux_desc = { };
+ struct device *dev = &pdev->dev;
+ struct gpio_aux_switch *gas;
+
+ gas = devm_kzalloc(dev, sizeof(*gas), GFP_KERNEL);
+ if (!gas)
+ return -ENOMEM;
+
+ gas->gpio_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
+ gas->gpio_cc = devm_gpiod_get(dev, "cc", GPIOD_OUT_LOW);
+
+ mux_desc.fwnode = dev->fwnode;
+ mux_desc.drvdata = gas;
+ mux_desc.set = gpio_typec_mux_set;
+ gas->typec_mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(gas->typec_mux))
+ return PTR_ERR(gas->typec_mux);
+
+ platform_set_drvdata(pdev, gas);
+
+ return 0;
+}
+
+static int gpio_aux_switch_remove(struct platform_device *pdev)
+{
+ struct gpio_aux_switch *gas = platform_get_drvdata(pdev);
+
+ typec_mux_unregister(gas->typec_mux);
+
+ return 0;
+}
+
+static const struct of_device_id gpio_aux_switch_dt_match[] = {
+ { .compatible = "gpio-aux-switch" },
+ { }
+};
+
+static struct platform_driver gpio_aux_switch_driver = {
+ .driver = {
+ .name = "gpio-aux-switch",
+ .of_match_table = gpio_aux_switch_dt_match,
+ },
+ .probe = gpio_aux_switch_probe,
+ .remove = gpio_aux_switch_remove,
+};
+
+module_platform_driver(gpio_aux_switch_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("GPIO AUX Switch driver");
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 9293045e128c..3e5b02f6606c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1055,7 +1055,6 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder)
/**
* bd_abort_claiming - abort claiming of a block device
* @bdev: block device of interest
- * @whole: whole block device
* @holder: holder that has claimed @bdev
*
* Abort claiming of a block device when the exclusive open failed. This can be
@@ -1828,6 +1827,7 @@ const struct file_operations def_blk_fops = {
/**
* lookup_bdev - lookup a struct block_device by name
* @pathname: special file representing the block device
+ * @dev: return value of the block device's dev_t
*
* Get a reference to the blockdevice at @pathname in the current
* namespace if possible and return it. Return ERR_PTR(error)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 98c15ff2e599..840587037b59 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2475,6 +2475,22 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
return r;
}
+static void encode_timestamp_and_gids(void **p,
+ const struct ceph_mds_request *req)
+{
+ struct ceph_timespec ts;
+ int i;
+
+ ceph_encode_timespec64(&ts, &req->r_stamp);
+ ceph_encode_copy(p, &ts, sizeof(ts));
+
+ /* gid_list */
+ ceph_encode_32(p, req->r_cred->group_info->ngroups);
+ for (i = 0; i < req->r_cred->group_info->ngroups; i++)
+ ceph_encode_64(p, from_kgid(&init_user_ns,
+ req->r_cred->group_info->gid[i]));
+}
+
/*
* called under mdsc->mutex
*/
@@ -2491,7 +2507,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
u64 ino1 = 0, ino2 = 0;
int pathlen1 = 0, pathlen2 = 0;
bool freepath1 = false, freepath2 = false;
- int len, i;
+ int len;
u16 releases;
void *p, *end;
int ret;
@@ -2517,17 +2533,10 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
goto out_free1;
}
- if (legacy) {
- /* Old style */
- len = sizeof(*head);
- } else {
- /* New style: add gid_list and any later fields */
- len = sizeof(struct ceph_mds_request_head) + sizeof(u32) +
- (sizeof(u64) * req->r_cred->group_info->ngroups);
- }
-
+ len = legacy ? sizeof(*head) : sizeof(struct ceph_mds_request_head);
len += pathlen1 + pathlen2 + 2*(1 + sizeof(u32) + sizeof(u64)) +
sizeof(struct ceph_timespec);
+ len += sizeof(u32) + (sizeof(u64) * req->r_cred->group_info->ngroups);
/* calculate (max) length for cap releases */
len += sizeof(struct ceph_mds_request_release) *
@@ -2548,7 +2557,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
msg->hdr.tid = cpu_to_le64(req->r_tid);
/*
- * The old ceph_mds_request_header didn't contain a version field, and
+ * The old ceph_mds_request_head didn't contain a version field, and
* one was added when we moved the message version from 3->4.
*/
if (legacy) {
@@ -2609,20 +2618,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
head->num_releases = cpu_to_le16(releases);
- /* time stamp */
- {
- struct ceph_timespec ts;
- ceph_encode_timespec64(&ts, &req->r_stamp);
- ceph_encode_copy(&p, &ts, sizeof(ts));
- }
-
- /* gid list */
- if (!legacy) {
- ceph_encode_32(&p, req->r_cred->group_info->ngroups);
- for (i = 0; i < req->r_cred->group_info->ngroups; i++)
- ceph_encode_64(&p, from_kgid(&init_user_ns,
- req->r_cred->group_info->gid[i]));
- }
+ encode_timestamp_and_gids(&p, req);
if (WARN_ON_ONCE(p > end)) {
ceph_msg_put(msg);
@@ -2730,13 +2726,8 @@ static int __prepare_send_request(struct ceph_mds_session *session,
/* remove cap/dentry releases from message */
rhead->num_releases = 0;
- /* time stamp */
p = msg->front.iov_base + req->r_request_release_offset;
- {
- struct ceph_timespec ts;
- ceph_encode_timespec64(&ts, &req->r_stamp);
- ceph_encode_copy(&p, &ts, sizeof(ts));
- }
+ encode_timestamp_and_gids(&p, req);
msg->front.iov_len = p - msg->front.iov_base;
msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
diff --git a/fs/file.c b/fs/file.c
index c0b60961c672..dab120b71e44 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -21,7 +21,6 @@
#include <linux/rcupdate.h>
#include <linux/close_range.h>
#include <net/sock.h>
-#include <linux/io_uring.h>
unsigned int sysctl_nr_open __read_mostly = 1024*1024;
unsigned int sysctl_nr_open_min = BITS_PER_LONG;
@@ -428,7 +427,6 @@ void exit_files(struct task_struct *tsk)
struct files_struct * files = tsk->files;
if (files) {
- io_uring_files_cancel(files);
task_lock(tsk);
tsk->files = NULL;
task_unlock(tsk);
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 7e35283fc0b1..ca46f314640b 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -992,6 +992,10 @@ enum io_mem_account {
ACCT_PINNED,
};
+static void destroy_fixed_file_ref_node(struct fixed_file_ref_node *ref_node);
+static struct fixed_file_ref_node *alloc_fixed_file_ref_node(
+ struct io_ring_ctx *ctx);
+
static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
struct io_comp_state *cs);
static void io_cqring_fill_event(struct io_kiocb *req, long res);
@@ -1501,6 +1505,13 @@ static bool io_grab_identity(struct io_kiocb *req)
spin_unlock_irq(&ctx->inflight_lock);
req->work.flags |= IO_WQ_WORK_FILES;
}
+ if (!(req->work.flags & IO_WQ_WORK_MM) &&
+ (def->work_flags & IO_WQ_WORK_MM)) {
+ if (id->mm != current->mm)
+ return false;
+ mmgrab(id->mm);
+ req->work.flags |= IO_WQ_WORK_MM;
+ }
return true;
}
@@ -1525,13 +1536,6 @@ static void io_prep_async_work(struct io_kiocb *req)
req->work.flags |= IO_WQ_WORK_UNBOUND;
}
- /* ->mm can never change on us */
- if (!(req->work.flags & IO_WQ_WORK_MM) &&
- (def->work_flags & IO_WQ_WORK_MM)) {
- mmgrab(id->mm);
- req->work.flags |= IO_WQ_WORK_MM;
- }
-
/* if we fail grabbing identity, we must COW, regrab, and retry */
if (io_grab_identity(req))
return;
@@ -7231,14 +7235,28 @@ static void io_file_ref_kill(struct percpu_ref *ref)
complete(&data->done);
}
+static void io_sqe_files_set_node(struct fixed_file_data *file_data,
+ struct fixed_file_ref_node *ref_node)
+{
+ spin_lock_bh(&file_data->lock);
+ file_data->node = ref_node;
+ list_add_tail(&ref_node->node, &file_data->ref_list);
+ spin_unlock_bh(&file_data->lock);
+ percpu_ref_get(&file_data->refs);
+}
+
static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
{
struct fixed_file_data *data = ctx->file_data;
- struct fixed_file_ref_node *ref_node = NULL;
+ struct fixed_file_ref_node *backup_node, *ref_node = NULL;
unsigned nr_tables, i;
+ int ret;
if (!data)
return -ENXIO;
+ backup_node = alloc_fixed_file_ref_node(ctx);
+ if (!backup_node)
+ return -ENOMEM;
spin_lock_bh(&data->lock);
ref_node = data->node;
@@ -7250,7 +7268,18 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
/* wait for all refs nodes to complete */
flush_delayed_work(&ctx->file_put_work);
- wait_for_completion(&data->done);
+ do {
+ ret = wait_for_completion_interruptible(&data->done);
+ if (!ret)
+ break;
+ ret = io_run_task_work_sig();
+ if (ret < 0) {
+ percpu_ref_resurrect(&data->refs);
+ reinit_completion(&data->done);
+ io_sqe_files_set_node(data, backup_node);
+ return ret;
+ }
+ } while (1);
__io_sqe_files_unregister(ctx);
nr_tables = DIV_ROUND_UP(ctx->nr_user_files, IORING_MAX_FILES_TABLE);
@@ -7261,6 +7290,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
kfree(data);
ctx->file_data = NULL;
ctx->nr_user_files = 0;
+ destroy_fixed_file_ref_node(backup_node);
return 0;
}
@@ -7758,11 +7788,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
return PTR_ERR(ref_node);
}
- file_data->node = ref_node;
- spin_lock_bh(&file_data->lock);
- list_add_tail(&ref_node->node, &file_data->ref_list);
- spin_unlock_bh(&file_data->lock);
- percpu_ref_get(&file_data->refs);
+ io_sqe_files_set_node(file_data, ref_node);
return ret;
out_fput:
for (i = 0; i < ctx->nr_user_files; i++) {
@@ -7918,11 +7944,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
if (needs_switch) {
percpu_ref_kill(&data->node->refs);
- spin_lock_bh(&data->lock);
- list_add_tail(&ref_node->node, &data->ref_list);
- data->node = ref_node;
- spin_unlock_bh(&data->lock);
- percpu_ref_get(&ctx->file_data->refs);
+ io_sqe_files_set_node(data, ref_node);
} else
destroy_fixed_file_ref_node(ref_node);
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index 4365b9aa3e3f..267f6dfb8960 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -34,6 +34,7 @@ mandatory-y += kmap_size.h
mandatory-y += kprobes.h
mandatory-y += linkage.h
mandatory-y += local.h
+mandatory-y += local64.h
mandatory-y += mm-arch-hooks.h
mandatory-y += mmiowb.h
mandatory-y += mmu.h
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 47b021952ac7..d705b174d346 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -447,8 +447,8 @@ enum {
BLK_MQ_REQ_NOWAIT = (__force blk_mq_req_flags_t)(1 << 0),
/* allocate from reserved pool */
BLK_MQ_REQ_RESERVED = (__force blk_mq_req_flags_t)(1 << 1),
- /* set RQF_PREEMPT */
- BLK_MQ_REQ_PREEMPT = (__force blk_mq_req_flags_t)(1 << 3),
+ /* set RQF_PM */
+ BLK_MQ_REQ_PM = (__force blk_mq_req_flags_t)(1 << 2),
};
struct request *blk_mq_alloc_request(struct request_queue *q, unsigned int op,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 070de09425ad..f94ee3089e01 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -79,9 +79,6 @@ typedef __u32 __bitwise req_flags_t;
#define RQF_MQ_INFLIGHT ((__force req_flags_t)(1 << 6))
/* don't call prep for this one */
#define RQF_DONTPREP ((__force req_flags_t)(1 << 7))
-/* set for "ide_preempt" requests and also for requests for which the SCSI
- "quiesce" state must be ignored. */
-#define RQF_PREEMPT ((__force req_flags_t)(1 << 8))
/* vaguely specified driver internal error. Ignored by the block layer */
#define RQF_FAILED ((__force req_flags_t)(1 << 10))
/* don't warn about errors */
@@ -430,8 +427,7 @@ struct request_queue {
unsigned long queue_flags;
/*
* Number of contexts that have called blk_set_pm_only(). If this
- * counter is above zero then only RQF_PM and RQF_PREEMPT requests are
- * processed.
+ * counter is above zero then only RQF_PM requests are processed.
*/
atomic_t pm_only;
@@ -696,6 +692,18 @@ static inline bool queue_is_mq(struct request_queue *q)
return q->mq_ops;
}
+#ifdef CONFIG_PM
+static inline enum rpm_status queue_rpm_status(struct request_queue *q)
+{
+ return q->rpm_status;
+}
+#else
+static inline enum rpm_status queue_rpm_status(struct request_queue *q)
+{
+ return RPM_ACTIVE;
+}
+#endif
+
static inline enum blk_zoned_model
blk_queue_zoned_model(struct request_queue *q)
{
diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h
index 7bb66e15b481..e3a0be2c90ad 100644
--- a/include/linux/build_bug.h
+++ b/include/linux/build_bug.h
@@ -77,9 +77,4 @@
#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
-#ifdef __GENKSYMS__
-/* genksyms gets confused by _Static_assert */
-#define _Static_assert(expr, ...)
-#endif
-
#endif /* _LINUX_BUILD_BUG_H */
diff --git a/include/linux/ceph/msgr.h b/include/linux/ceph/msgr.h
index f5e02f6c0655..3989dcb94d3d 100644
--- a/include/linux/ceph/msgr.h
+++ b/include/linux/ceph/msgr.h
@@ -33,8 +33,8 @@
#define CEPH_MSGR2_INCARNATION_1 (0ull)
#define DEFINE_MSGR2_FEATURE(bit, incarnation, name) \
- static const uint64_t CEPH_MSGR2_FEATURE_##name = (1ULL << bit); \
- static const uint64_t CEPH_MSGR2_FEATUREMASK_##name = \
+ static const uint64_t __maybe_unused CEPH_MSGR2_FEATURE_##name = (1ULL << bit); \
+ static const uint64_t __maybe_unused CEPH_MSGR2_FEATUREMASK_##name = \
(1ULL << bit | CEPH_MSGR2_INCARNATION_##incarnation);
#define HAVE_MSGR2_FEATURE(x, name) \
diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
index 8396013785ef..4c1f3528599d 100644
--- a/include/linux/fixp-arith.h
+++ b/include/linux/fixp-arith.h
@@ -141,4 +141,24 @@ static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
#define fixp_cos32_rad(rad, twopi) \
fixp_sin32_rad(rad + twopi / 4, twopi)
+
+/**
+ * fixp_linear_interpolate() - interpolates a value from two known points
+ *
+ * @x0: x value of point 0
+ * @y0: y value of point 0
+ * @x1: x value of point 1
+ * @y1: y value of point 1
+ * @x: the linear interpolant
+ */
+static inline int fixp_linear_interpolate(int x0, int y0, int x1, int y1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
#endif
diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h
index 85b5151911cf..4856706fbfeb 100644
--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -21,61 +21,61 @@
})
/* acceptable for old filesystems */
-static inline bool old_valid_dev(dev_t dev)
+static __always_inline bool old_valid_dev(dev_t dev)
{
return MAJOR(dev) < 256 && MINOR(dev) < 256;
}
-static inline u16 old_encode_dev(dev_t dev)
+static __always_inline u16 old_encode_dev(dev_t dev)
{
return (MAJOR(dev) << 8) | MINOR(dev);
}
-static inline dev_t old_decode_dev(u16 val)
+static __always_inline dev_t old_decode_dev(u16 val)
{
return MKDEV((val >> 8) & 255, val & 255);
}
-static inline u32 new_encode_dev(dev_t dev)
+static __always_inline u32 new_encode_dev(dev_t dev)
{
unsigned major = MAJOR(dev);
unsigned minor = MINOR(dev);
return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}
-static inline dev_t new_decode_dev(u32 dev)
+static __always_inline dev_t new_decode_dev(u32 dev)
{
unsigned major = (dev & 0xfff00) >> 8;
unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
return MKDEV(major, minor);
}
-static inline u64 huge_encode_dev(dev_t dev)
+static __always_inline u64 huge_encode_dev(dev_t dev)
{
return new_encode_dev(dev);
}
-static inline dev_t huge_decode_dev(u64 dev)
+static __always_inline dev_t huge_decode_dev(u64 dev)
{
return new_decode_dev(dev);
}
-static inline int sysv_valid_dev(dev_t dev)
+static __always_inline int sysv_valid_dev(dev_t dev)
{
return MAJOR(dev) < (1<<14) && MINOR(dev) < (1<<18);
}
-static inline u32 sysv_encode_dev(dev_t dev)
+static __always_inline u32 sysv_encode_dev(dev_t dev)
{
return MINOR(dev) | (MAJOR(dev) << 18);
}
-static inline unsigned sysv_major(u32 dev)
+static __always_inline unsigned sysv_major(u32 dev)
{
return (dev >> 18) & 0x3fff;
}
-static inline unsigned sysv_minor(u32 dev)
+static __always_inline unsigned sysv_minor(u32 dev)
{
return dev & 0x3ffff;
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5299b90a6c40..ecdf8a8cd6ae 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -216,6 +216,13 @@ int overcommit_kbytes_handler(struct ctl_table *, int, void *, size_t *,
loff_t *);
int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *,
loff_t *);
+/*
+ * Any attempt to mark this function as static leads to build failure
+ * when CONFIG_DEBUG_INFO_BTF is enabled because __add_to_page_cache_locked()
+ * is referred to by BPF code. This must be visible for error injection.
+ */
+int __add_to_page_cache_locked(struct page *page, struct address_space *mapping,
+ pgoff_t index, gfp_t gfp, void **shadowp);
#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
@@ -2432,8 +2439,9 @@ extern int __meminit early_pfn_to_nid(unsigned long pfn);
#endif
extern void set_dma_reserve(unsigned long new_dma_reserve);
-extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long,
- enum meminit_context, struct vmem_altmap *, int migratetype);
+extern void memmap_init_zone(unsigned long, int, unsigned long,
+ unsigned long, unsigned long, enum meminit_context,
+ struct vmem_altmap *, int migratetype);
extern void setup_per_zone_wmarks(void);
extern int __meminit init_per_zone_wmark_min(void);
extern void mem_init(void);
diff --git a/include/linux/sizes.h b/include/linux/sizes.h
index 9874f6f67537..1ac79bcee2bb 100644
--- a/include/linux/sizes.h
+++ b/include/linux/sizes.h
@@ -44,6 +44,9 @@
#define SZ_2G 0x80000000
#define SZ_4G _AC(0x100000000, ULL)
+#define SZ_8G _AC(0x200000000, ULL)
+#define SZ_16G _AC(0x400000000, ULL)
+#define SZ_32G _AC(0x800000000, ULL)
#define SZ_64T _AC(0x400000000000, ULL)
#endif /* __LINUX_SIZES_H__ */
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
index 3db6797ba6ff..61a18dba6eab 100644
--- a/include/linux/soc/qcom/llcc-qcom.h
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -29,9 +29,13 @@
#define LLCC_AUDHW 22
#define LLCC_NPU 23
#define LLCC_WLHW 24
+#define LLCC_PIMEM 25
+#define LLCC_DISPVG 27
+#define LLCC_CVP 28
#define LLCC_MODPE 29
#define LLCC_APTCM 30
#define LLCC_WRCACHE 31
+#define LLCC_CVPFW 32
/**
* llcc_slice_desc - Cache slice descriptor
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index 191c329e482a..32596fdbcd5b 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -908,6 +908,8 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param)
opt = fs_parse(fc, cgroup1_fs_parameters, param, &result);
if (opt == -ENOPARAM) {
if (strcmp(param->key, "source") == 0) {
+ if (fc->source)
+ return invalf(fc, "Multiple sources not supported");
fc->source = param->string;
param->string = NULL;
return 0;
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index fefa21981027..613845769103 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -244,7 +244,7 @@ bool cgroup_ssid_enabled(int ssid)
*
* The default hierarchy is the v2 interface of cgroup and this function
* can be used to test whether a cgroup is on the default hierarchy for
- * cases where a subsystem should behave differnetly depending on the
+ * cases where a subsystem should behave differently depending on the
* interface version.
*
* List of changed behaviors:
@@ -262,7 +262,7 @@ bool cgroup_ssid_enabled(int ssid)
* "cgroup.procs" instead.
*
* - "cgroup.procs" is not sorted. pids will be unique unless they got
- * recycled inbetween reads.
+ * recycled in-between reads.
*
* - "release_agent" and "notify_on_release" are removed. Replacement
* notification mechanism will be implemented.
@@ -342,7 +342,7 @@ static bool cgroup_is_mixable(struct cgroup *cgrp)
return !cgroup_parent(cgrp);
}
-/* can @cgrp become a thread root? should always be true for a thread root */
+/* can @cgrp become a thread root? Should always be true for a thread root */
static bool cgroup_can_be_thread_root(struct cgroup *cgrp)
{
/* mixables don't care */
@@ -527,7 +527,7 @@ static struct cgroup_subsys_state *cgroup_e_css_by_mask(struct cgroup *cgrp,
* the root css is returned, so this function always returns a valid css.
*
* The returned css is not guaranteed to be online, and therefore it is the
- * callers responsiblity to tryget a reference for it.
+ * callers responsibility to try get a reference for it.
*/
struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp,
struct cgroup_subsys *ss)
@@ -699,7 +699,7 @@ EXPORT_SYMBOL_GPL(of_css);
; \
else
-/* walk live descendants in preorder */
+/* walk live descendants in pre order */
#define cgroup_for_each_live_descendant_pre(dsct, d_css, cgrp) \
css_for_each_descendant_pre((d_css), cgroup_css((cgrp), NULL)) \
if (({ lockdep_assert_held(&cgroup_mutex); \
@@ -933,7 +933,7 @@ void put_css_set_locked(struct css_set *cset)
WARN_ON_ONCE(!list_empty(&cset->threaded_csets));
- /* This css_set is dead. unlink it and release cgroup and css refs */
+ /* This css_set is dead. Unlink it and release cgroup and css refs */
for_each_subsys(ss, ssid) {
list_del(&cset->e_cset_node[ssid]);
css_put(cset->subsys[ssid]);
@@ -1058,7 +1058,7 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset,
/*
* Build the set of subsystem state objects that we want to see in the
- * new css_set. while subsystems can change globally, the entries here
+ * new css_set. While subsystems can change globally, the entries here
* won't change, so no need for locking.
*/
for_each_subsys(ss, i) {
@@ -1148,7 +1148,7 @@ static void link_css_set(struct list_head *tmp_links, struct css_set *cset,
/*
* Always add links to the tail of the lists so that the lists are
- * in choronological order.
+ * in chronological order.
*/
list_move_tail(&link->cset_link, &cgrp->cset_links);
list_add_tail(&link->cgrp_link, &cset->cgrp_links);
@@ -3654,7 +3654,7 @@ static ssize_t cgroup_freeze_write(struct kernfs_open_file *of,
static int cgroup_file_open(struct kernfs_open_file *of)
{
- struct cftype *cft = of->kn->priv;
+ struct cftype *cft = of_cft(of);
if (cft->open)
return cft->open(of);
@@ -3663,7 +3663,7 @@ static int cgroup_file_open(struct kernfs_open_file *of)
static void cgroup_file_release(struct kernfs_open_file *of)
{
- struct cftype *cft = of->kn->priv;
+ struct cftype *cft = of_cft(of);
if (cft->release)
cft->release(of);
@@ -3674,7 +3674,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
{
struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
struct cgroup *cgrp = of->kn->parent->priv;
- struct cftype *cft = of->kn->priv;
+ struct cftype *cft = of_cft(of);
struct cgroup_subsys_state *css;
int ret;
@@ -3724,7 +3724,7 @@ static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf,
static __poll_t cgroup_file_poll(struct kernfs_open_file *of, poll_table *pt)
{
- struct cftype *cft = of->kn->priv;
+ struct cftype *cft = of_cft(of);
if (cft->poll)
return cft->poll(of, pt);
@@ -4134,7 +4134,7 @@ struct cgroup_subsys_state *css_next_child(struct cgroup_subsys_state *pos,
* implies that if we observe !CSS_RELEASED on @pos in this RCU
* critical section, the one pointed to by its next pointer is
* guaranteed to not have finished its RCU grace period even if we
- * have dropped rcu_read_lock() inbetween iterations.
+ * have dropped rcu_read_lock() in-between iterations.
*
* If @pos has CSS_RELEASED set, its next pointer can't be
* dereferenced; however, as each css is given a monotonically
@@ -4382,7 +4382,7 @@ static struct css_set *css_task_iter_next_css_set(struct css_task_iter *it)
}
/**
- * css_task_iter_advance_css_set - advance a task itererator to the next css_set
+ * css_task_iter_advance_css_set - advance a task iterator to the next css_set
* @it: the iterator to advance
*
* Advance @it to the next css_set to walk.
@@ -6308,7 +6308,7 @@ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss)
*
* Find the cgroup at @path on the default hierarchy, increment its
* reference count and return it. Returns pointer to the found cgroup on
- * success, ERR_PTR(-ENOENT) if @path doens't exist and ERR_PTR(-ENOTDIR)
+ * success, ERR_PTR(-ENOENT) if @path doesn't exist and ERR_PTR(-ENOTDIR)
* if @path points to a non-directory.
*/
struct cgroup *cgroup_get_from_path(const char *path)
diff --git a/kernel/configs/debug.config b/kernel/configs/debug.config
new file mode 100644
index 000000000000..451a71bb6bda
--- /dev/null
+++ b/kernel/configs/debug.config
@@ -0,0 +1,13 @@
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_PROVE_RCU=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_KASAN=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
diff --git a/kernel/configs/distro.config b/kernel/configs/distro.config
new file mode 100644
index 000000000000..0d1bcff1136c
--- /dev/null
+++ b/kernel/configs/distro.config
@@ -0,0 +1,467 @@
+# USB camera
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_DTCS033=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TOUPTEK=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_LAN78XX=m
+CONFIG_USB_PWC=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+
+# USB serial
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MXUPORT=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+
+# USB gadget
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_NEW_LEDS=y
+
+# USB Eth
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX88179_178A=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
+CONFIG_USB_NET_SR9700=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_MCS7830=m
+
+# USB device class
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+
+# LEDs
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEDS_TRIGGER_MTD=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_PANIC=y
+CONFIG_MAC80211_LEDS=y
+
+# systemd
+CONFIG_IPV6=y
+CONFIG_NAMESPACES=y
+CONFIG_NET_NS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_DEVTMPFS=y
+CONFIG_CGROUPS=y
+CONFIG_INOTIFY_USER=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EPOLL=y
+CONFIG_NET=y
+CONFIG_SYSFS=y
+CONFIG_PROC_FS=y
+CONFIG_FHANDLE=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_DEBUG=y
+
+# NFS server
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+
+# HID
+CONFIG_HID_APPLE=y
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_PLANTRONICS=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_HID_MULTITOUCH=m
+
+#misc
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_STACKTRACE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_GPIO_SYSFS=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_RFKILL=y
+CONFIG_BINFMT_MISC=m
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZRAM=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BBR=m
+
+# PPP
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+
+# input
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PM8941_PWRKEY=y
+CONFIG_INPUT_JOYDEV=m
+
+# Docker
+CONFIG_IPV6=y
+CONFIG_NET_NS=y
+CONFIG_IPC_NS=y
+CONFIG_UTS_NS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_VETH=m
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_NETFILTER_SYNPROXY=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_MATCH_CGROUP=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
+CONFIG_NF_TABLES_IPV4=m
+CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_TABLES_IPV6=m
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_LABELS=y
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_BROADCAST=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_USER_NS=y
+CONFIG_SECCOMP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_FQ=m
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_IP_VS=m
+CONFIG_VXLAN=m
+CONFIG_XFRM_ALGO=m
+CONFIG_XFRM_USER=m
+CONFIG_IPVLAN=m
+CONFIG_MACVLAN=m
+CONFIG_DUMMY=m
+CONFIG_BTRFS_FS=m
+CONFIG_OVERLAY_FS=m
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_POSIX_MQUEUE=y
+
+# Extended IPV6 support
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_MIP6=m
+CONFIG_IPV6_ILA=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_VTI=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NF_NAT_MASQUERADE_IPV6=m
+CONFIG_NF_DUP_IPV6=m
+CONFIG_NF_REJECT_IPV6=m
+CONFIG_NF_LOG_IPV6=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_NFT_CHAIN_NAT_IPV6=m
+CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+
+# 6LOWPAN
+CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_NHC=m
+CONFIG_6LOWPAN_NHC_DEST=m
+CONFIG_6LOWPAN_NHC_FRAGMENT=m
+CONFIG_6LOWPAN_NHC_HOP=m
+CONFIG_6LOWPAN_NHC_IPV6=m
+CONFIG_6LOWPAN_NHC_MOBILITY=m
+CONFIG_6LOWPAN_NHC_ROUTING=m
+CONFIG_6LOWPAN_NHC_UDP=m
+CONFIG_IEEE802154=m
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL=y
+CONFIG_IEEE802154_SOCKET=m
+CONFIG_IEEE802154_6LOWPAN=m
+CONFIG_IEEE802154_DRIVERS=m
+CONFIG_IEEE802154_FAKELB=m
+CONFIG_IEEE802154_AT86RF230=m
+CONFIG_IEEE802154_AT86RF230_DEBUGFS=y
+CONFIG_IEEE802154_MRF24J40=m
+CONFIG_IEEE802154_CC2520=m
+CONFIG_IEEE802154_ATUSB=m
+CONFIG_MAC802154=m
+
+# Extended BT support
+CONFIG_BT=m
+CONFIG_BT_BREDR=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
+CONFIG_BT_LE=y
+CONFIG_BT_LEDS=y
+CONFIG_BT_DEBUGFS=y
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_6LOWPAN=m
+
+# Extended WLAN support
+CONFIG_CFG80211_WEXT=y
+
+# Legacy instruction support for arm64
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+
+# Enable DM_CRYPT
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_RTC_DRV_PM8XXX=m
+CONFIG_RPMSG_CHAR=m
+
+# Disable Firmware fallback
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n
+
+# I2C Camera
+CONFIG_EXPERT=y
+CONFIG_VIDEO_OV5640=m
+CONFIG_VIDEO_OV5645=m
+CONFIG_VIDEO_OV7251=m
+CONFIG_VIDEO_OV8856=m \ No newline at end of file
diff --git a/kernel/exit.c b/kernel/exit.c
index 3594291a8542..04029e35e69a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -63,6 +63,7 @@
#include <linux/random.h>
#include <linux/rcuwait.h>
#include <linux/compat.h>
+#include <linux/io_uring.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
@@ -776,6 +777,7 @@ void __noreturn do_exit(long code)
schedule();
}
+ io_uring_files_cancel(tsk->files);
exit_signals(tsk); /* sets PF_EXITING */
/* sync mm's RSS info before statistics gathering */
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index b5295a0b0536..9880b6c0e272 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3731,17 +3731,24 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
* is updated and visible.
*/
if (!freezable || !workqueue_freezing) {
+ bool kick = false;
+
pwq->max_active = wq->saved_max_active;
while (!list_empty(&pwq->delayed_works) &&
- pwq->nr_active < pwq->max_active)
+ pwq->nr_active < pwq->max_active) {
pwq_activate_first_delayed(pwq);
+ kick = true;
+ }
/*
* Need to kick a worker after thawed or an unbound wq's
- * max_active is bumped. It's a slow path. Do it always.
+ * max_active is bumped. In realtime scenarios, always kicking a
+ * worker will cause interference on the isolated cpu cores, so
+ * let's kick iff work items were activated.
*/
- wake_up_worker(pwq->pool);
+ if (kick)
+ wake_up_worker(pwq->pool);
} else {
pwq->max_active = 0;
}
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 7f1244b5294a..dab97bb69df6 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -81,14 +81,14 @@ static int clear_bits_ll(unsigned long *addr, unsigned long mask_to_clear)
* users set the same bit, one user will return remain bits, otherwise
* return 0.
*/
-static int bitmap_set_ll(unsigned long *map, int start, int nr)
+static int bitmap_set_ll(unsigned long *map, unsigned long start, unsigned long nr)
{
unsigned long *p = map + BIT_WORD(start);
- const int size = start + nr;
+ const unsigned long size = start + nr;
int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
- while (nr - bits_to_set >= 0) {
+ while (nr >= bits_to_set) {
if (set_bits_ll(p, mask_to_set))
return nr;
nr -= bits_to_set;
@@ -116,14 +116,15 @@ static int bitmap_set_ll(unsigned long *map, int start, int nr)
* users clear the same bit, one user will return remain bits,
* otherwise return 0.
*/
-static int bitmap_clear_ll(unsigned long *map, int start, int nr)
+static unsigned long
+bitmap_clear_ll(unsigned long *map, unsigned long start, unsigned long nr)
{
unsigned long *p = map + BIT_WORD(start);
- const int size = start + nr;
+ const unsigned long size = start + nr;
int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
- while (nr - bits_to_clear >= 0) {
+ while (nr >= bits_to_clear) {
if (clear_bits_ll(p, mask_to_clear))
return nr;
nr -= bits_to_clear;
@@ -183,8 +184,8 @@ int gen_pool_add_owner(struct gen_pool *pool, unsigned long virt, phys_addr_t ph
size_t size, int nid, void *owner)
{
struct gen_pool_chunk *chunk;
- int nbits = size >> pool->min_alloc_order;
- int nbytes = sizeof(struct gen_pool_chunk) +
+ unsigned long nbits = size >> pool->min_alloc_order;
+ unsigned long nbytes = sizeof(struct gen_pool_chunk) +
BITS_TO_LONGS(nbits) * sizeof(long);
chunk = vzalloc_node(nbytes, nid);
@@ -242,7 +243,7 @@ void gen_pool_destroy(struct gen_pool *pool)
struct list_head *_chunk, *_next_chunk;
struct gen_pool_chunk *chunk;
int order = pool->min_alloc_order;
- int bit, end_bit;
+ unsigned long bit, end_bit;
list_for_each_safe(_chunk, _next_chunk, &pool->chunks) {
chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
@@ -278,7 +279,7 @@ unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size,
struct gen_pool_chunk *chunk;
unsigned long addr = 0;
int order = pool->min_alloc_order;
- int nbits, start_bit, end_bit, remain;
+ unsigned long nbits, start_bit, end_bit, remain;
#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
BUG_ON(in_nmi());
@@ -487,7 +488,7 @@ void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size,
{
struct gen_pool_chunk *chunk;
int order = pool->min_alloc_order;
- int start_bit, nbits, remain;
+ unsigned long start_bit, nbits, remain;
#ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
BUG_ON(in_nmi());
@@ -755,7 +756,7 @@ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size,
index = bitmap_find_next_zero_area(map, size, start, nr, 0);
while (index < size) {
- int next_bit = find_next_bit(map, size, index + nr);
+ unsigned long next_bit = find_next_bit(map, size, index + nr);
if ((next_bit - index) < len) {
len = next_bit - index;
start_bit = index;
diff --git a/lib/zlib_dfltcc/Makefile b/lib/zlib_dfltcc/Makefile
index 8e4d5afbbb10..66e1c96387c4 100644
--- a/lib/zlib_dfltcc/Makefile
+++ b/lib/zlib_dfltcc/Makefile
@@ -8,4 +8,4 @@
obj-$(CONFIG_ZLIB_DFLTCC) += zlib_dfltcc.o
-zlib_dfltcc-objs := dfltcc.o dfltcc_deflate.o dfltcc_inflate.o dfltcc_syms.o
+zlib_dfltcc-objs := dfltcc.o dfltcc_deflate.o dfltcc_inflate.o
diff --git a/lib/zlib_dfltcc/dfltcc.c b/lib/zlib_dfltcc/dfltcc.c
index c30de430b30c..782f76e9d4da 100644
--- a/lib/zlib_dfltcc/dfltcc.c
+++ b/lib/zlib_dfltcc/dfltcc.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: Zlib
/* dfltcc.c - SystemZ DEFLATE CONVERSION CALL support. */
-#include <linux/zutil.h>
+#include <linux/export.h>
+#include <linux/module.h>
#include "dfltcc_util.h"
#include "dfltcc.h"
@@ -53,3 +54,6 @@ void dfltcc_reset(
dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
dfltcc_state->param.ribm = DFLTCC_RIBM;
}
+EXPORT_SYMBOL(dfltcc_reset);
+
+MODULE_LICENSE("GPL");
diff --git a/lib/zlib_dfltcc/dfltcc_deflate.c b/lib/zlib_dfltcc/dfltcc_deflate.c
index 00c185101c6d..6c946e8532ee 100644
--- a/lib/zlib_dfltcc/dfltcc_deflate.c
+++ b/lib/zlib_dfltcc/dfltcc_deflate.c
@@ -4,6 +4,7 @@
#include "dfltcc_util.h"
#include "dfltcc.h"
#include <asm/setup.h>
+#include <linux/export.h>
#include <linux/zutil.h>
/*
@@ -34,6 +35,7 @@ int dfltcc_can_deflate(
return 1;
}
+EXPORT_SYMBOL(dfltcc_can_deflate);
static void dfltcc_gdht(
z_streamp strm
@@ -277,3 +279,4 @@ again:
goto again; /* deflate() must use all input or all output */
return 1;
}
+EXPORT_SYMBOL(dfltcc_deflate);
diff --git a/lib/zlib_dfltcc/dfltcc_inflate.c b/lib/zlib_dfltcc/dfltcc_inflate.c
index db107016d29b..fb60b5a6a1cb 100644
--- a/lib/zlib_dfltcc/dfltcc_inflate.c
+++ b/lib/zlib_dfltcc/dfltcc_inflate.c
@@ -125,7 +125,7 @@ dfltcc_inflate_action dfltcc_inflate(
param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1);
if (param->hl)
param->nt = 0; /* Honor history for the first block */
- param->cv = state->flags ? REVERSE(state->check) : state->check;
+ param->cv = state->check;
/* Inflate */
do {
@@ -138,7 +138,7 @@ dfltcc_inflate_action dfltcc_inflate(
state->bits = param->sbb;
state->whave = param->hl;
state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
- state->check = state->flags ? REVERSE(param->cv) : param->cv;
+ state->check = param->cv;
if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
/* Report an error if stream is corrupted */
state->mode = BAD;
diff --git a/lib/zlib_dfltcc/dfltcc_syms.c b/lib/zlib_dfltcc/dfltcc_syms.c
deleted file mode 100644
index 6f23481804c1..000000000000
--- a/lib/zlib_dfltcc/dfltcc_syms.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * linux/lib/zlib_dfltcc/dfltcc_syms.c
- *
- * Exported symbols for the s390 zlib dfltcc support.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/zlib.h>
-#include "dfltcc.h"
-
-EXPORT_SYMBOL(dfltcc_can_deflate);
-EXPORT_SYMBOL(dfltcc_deflate);
-EXPORT_SYMBOL(dfltcc_reset);
-MODULE_LICENSE("GPL");
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index cbf32d2824fd..a2602969873d 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -4105,10 +4105,30 @@ retry_avoidcopy:
* may get SIGKILLed if it later faults.
*/
if (outside_reserve) {
+ struct address_space *mapping = vma->vm_file->f_mapping;
+ pgoff_t idx;
+ u32 hash;
+
put_page(old_page);
BUG_ON(huge_pte_none(pte));
+ /*
+ * Drop hugetlb_fault_mutex and i_mmap_rwsem before
+ * unmapping. unmapping needs to hold i_mmap_rwsem
+ * in write mode. Dropping i_mmap_rwsem in read mode
+ * here is OK as COW mappings do not interact with
+ * PMD sharing.
+ *
+ * Reacquire both after unmap operation.
+ */
+ idx = vma_hugecache_offset(h, vma, haddr);
+ hash = hugetlb_fault_mutex_hash(mapping, idx);
+ mutex_unlock(&hugetlb_fault_mutex_table[hash]);
+ i_mmap_unlock_read(mapping);
+
unmap_ref_private(mm, vma, old_page, haddr);
- BUG_ON(huge_pte_none(pte));
+
+ i_mmap_lock_read(mapping);
+ mutex_lock(&hugetlb_fault_mutex_table[hash]);
spin_lock(ptl);
ptep = huge_pte_offset(mm, haddr, huge_page_size(h));
if (likely(ptep &&
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 1dd5a0f99372..5106b84b07d4 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -337,6 +337,8 @@ void kasan_record_aux_stack(void *addr)
cache = page->slab_cache;
object = nearest_obj(cache, page, addr);
alloc_meta = kasan_get_alloc_meta(cache, object);
+ if (!alloc_meta)
+ return;
alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0];
alloc_meta->aux_stack[0] = kasan_save_stack(GFP_NOWAIT);
diff --git a/mm/memory.c b/mm/memory.c
index 7d608765932b..feff48e1465a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2892,11 +2892,13 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
entry = mk_pte(new_page, vma->vm_page_prot);
entry = pte_sw_mkyoung(entry);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+
/*
* Clear the pte entry and flush it first, before updating the
- * pte with the new entry. This will avoid a race condition
- * seen in the presence of one thread doing SMC and another
- * thread doing COW.
+ * pte with the new entry, to keep TLBs on different CPUs in
+ * sync. This code used to set the new PTE then flush TLBs, but
+ * that left a window where the new PTE could be loaded into
+ * some TLBs while the old PTE remains in others.
*/
ptep_clear_flush_notify(vma, vmf->address, vmf->pte);
page_add_new_anon_rmap(new_page, vma, vmf->address, false);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index af41fb990820..f9d57b9be8c7 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -713,7 +713,7 @@ void __ref move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
* expects the zone spans the pfn range. All the pages in the range
* are reserved so nobody should be touching them so we should be safe
*/
- memmap_init_zone(nr_pages, nid, zone_idx(zone), start_pfn,
+ memmap_init_zone(nr_pages, nid, zone_idx(zone), start_pfn, 0,
MEMINIT_HOTPLUG, altmap, migratetype);
set_zone_contiguous(zone);
diff --git a/mm/mremap.c b/mm/mremap.c
index c5590afe7165..f554320281cc 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -358,7 +358,9 @@ static unsigned long get_extent(enum pgt_entry entry, unsigned long old_addr,
next = (old_addr + size) & mask;
/* even if next overflowed, extent below will be ok */
- extent = (next > old_end) ? old_end - old_addr : next - old_addr;
+ extent = next - old_addr;
+ if (extent > old_end - old_addr)
+ extent = old_end - old_addr;
next = (new_addr + size) & mask;
if (extent > next - new_addr)
extent = next - new_addr;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 7a2c89b21115..bdbec4c98173 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -423,6 +423,8 @@ defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
if (end_pfn < pgdat_end_pfn(NODE_DATA(nid)))
return false;
+ if (NODE_DATA(nid)->first_deferred_pfn != ULONG_MAX)
+ return true;
/*
* We start only with one section of pages, more pages are added as
* needed until the rest of deferred pages are initialized.
@@ -6116,7 +6118,7 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
* zone stats (e.g., nr_isolate_pageblock) are touched.
*/
void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
- unsigned long start_pfn,
+ unsigned long start_pfn, unsigned long zone_end_pfn,
enum meminit_context context,
struct vmem_altmap *altmap, int migratetype)
{
@@ -6152,7 +6154,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
if (context == MEMINIT_EARLY) {
if (overlap_memmap_init(zone, &pfn))
continue;
- if (defer_init(nid, pfn, end_pfn))
+ if (defer_init(nid, pfn, zone_end_pfn))
break;
}
@@ -6266,7 +6268,7 @@ void __meminit __weak memmap_init(unsigned long size, int nid,
if (end_pfn > start_pfn) {
size = end_pfn - start_pfn;
- memmap_init_zone(size, nid, zone, start_pfn,
+ memmap_init_zone(size, nid, zone, start_pfn, range_end_pfn,
MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
}
}
diff --git a/mm/slub.c b/mm/slub.c
index 0c8b43a5b3b0..dc5b42e700b8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1619,9 +1619,6 @@ static inline struct page *alloc_slab_page(struct kmem_cache *s,
else
page = __alloc_pages_node(node, flags, order);
- if (page)
- account_slab_page(page, order, s);
-
return page;
}
@@ -1774,6 +1771,8 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
page->objects = oo_objects(oo);
+ account_slab_page(page, oo_order(oo), s);
+
page->slab_cache = s;
__SetPageSlab(page);
if (page_is_pfmemalloc(page))
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index c1ebb2aa08b5..c38d8de93836 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -1333,7 +1333,8 @@ static int prepare_auth_signature(struct ceph_connection *con)
void *buf;
int ret;
- buf = alloc_conn_buf(con, head_onwire_len(SHA256_DIGEST_SIZE, false));
+ buf = alloc_conn_buf(con, head_onwire_len(SHA256_DIGEST_SIZE,
+ con_secure(con)));
if (!buf)
return -ENOMEM;
@@ -2032,10 +2033,18 @@ bad:
return -EINVAL;
}
+/*
+ * Align session_key and con_secret to avoid GFP_ATOMIC allocation
+ * inside crypto_shash_setkey() and crypto_aead_setkey() called from
+ * setup_crypto(). __aligned(16) isn't guaranteed to work for stack
+ * objects, so do it by hand.
+ */
static int process_auth_done(struct ceph_connection *con, void *p, void *end)
{
- u8 session_key[CEPH_KEY_LEN];
- u8 con_secret[CEPH_MAX_CON_SECRET_LEN];
+ u8 session_key_buf[CEPH_KEY_LEN + 16];
+ u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16];
+ u8 *session_key = PTR_ALIGN(&session_key_buf[0], 16);
+ u8 *con_secret = PTR_ALIGN(&con_secret_buf[0], 16);
int session_key_len, con_secret_len;
int payload_len;
u64 global_id;
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 00085308ed9d..92e888ed939f 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6646,6 +6646,12 @@ sub process {
# }
# }
+# strlcpy uses that should likely be strscpy
+ if ($line =~ /\bstrlcpy\s*\(/) {
+ WARN("STRLCPY",
+ "Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw\@mail.gmail.com/\n" . $herecurr);
+ }
+
# typecasts on min/max could be min_t/max_t
if ($perl_version_ok &&
defined $stat &&
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
index e083bcae343f..3643b4f896ed 100755
--- a/scripts/depmod.sh
+++ b/scripts/depmod.sh
@@ -15,6 +15,8 @@ if ! test -r System.map ; then
exit 0
fi
+# legacy behavior: "depmod" in /sbin, no /sbin in PATH
+PATH="$PATH:/sbin"
if [ -z $(command -v $DEPMOD) ]; then
echo "Warning: 'make modules_install' requires $DEPMOD. Please install it." >&2
echo "This is probably in the kmod package." >&2
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 9ddfed797b7e..8a5d8f812e95 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -11,6 +11,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <sound/jack.h>
#include <linux/kernel.h>
#include <linux/slimbus.h>
#include <sound/soc.h>
@@ -86,12 +87,18 @@
#define WCD9335_DEC_PWR_LVL_HP 0x04
#define WCD9335_DEC_PWR_LVL_DF 0x00
+#define WCD9335_MBHC_MAX_BUTTONS (8)
+
#define WCD9335_SLIM_RX_CH(p) \
{.port = p + WCD9335_RX_START, .shift = p,}
#define WCD9335_SLIM_TX_CH(p) \
{.port = p, .shift = p,}
+static int btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4;
+static int hs_jack_mask = SND_JACK_HEADPHONE | SND_JACK_HEADSET;
+
/* vout step value */
#define WCD9335_CALCULATE_VOUT_D(req_mv) (((req_mv - 650) * 10) / 25)
@@ -319,6 +326,16 @@ struct wcd9335_codec {
u32 num_rx_port;
u32 num_tx_port;
+ struct snd_soc_jack *jack;
+ bool hphl_jack_type_normally_open;
+ bool gnd_jack_type_normally_open;
+ bool mbhc_btn_enabled;
+ int mbhc_btn0_released;
+ bool detect_accessory_type;
+ int accessory_type;
+ /* Voltage threshold for button detection */
+ u32 vref_btn[WCD9335_MBHC_MAX_BUTTONS];
+
int sido_input_src;
enum wcd9335_sido_voltage sido_voltage;
@@ -2813,7 +2830,6 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
break;
case SND_SOC_DAPM_POST_PMU:
snd_soc_component_update_bits(comp, hpf_gate_reg, 0x01, 0x00);
-
if (decimator == 0) {
snd_soc_component_write(comp,
WCD9335_MBHC_ZDET_RAMP_CTL, 0x83);
@@ -2824,7 +2840,6 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
snd_soc_component_write(comp,
WCD9335_MBHC_ZDET_RAMP_CTL, 0x03);
}
-
snd_soc_component_update_bits(comp, hpf_gate_reg,
0x01, 0x01);
snd_soc_component_update_bits(comp, tx_vol_ctl_reg,
@@ -3962,6 +3977,131 @@ static int wcd9335_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
return 0;
}
+static irqreturn_t wcd9335_mbhc_sw_irq(int irq, void *data)
+{
+ struct wcd9335_codec *wcd = data;
+ struct snd_soc_component *component = wcd->component;
+ bool ins = false;
+
+ if (snd_soc_component_read32(component, WCD9335_ANA_MBHC_MECH) &
+ WCD9335_MBHC_MECH_DETECT_TYPE_MASK)
+ ins = true;
+
+ /* Set the detection type appropriately */
+ snd_soc_component_update_bits(component, WCD9335_ANA_MBHC_MECH,
+ WCD9335_MBHC_MECH_DETECT_TYPE_MASK,
+ (!ins << WCD9335_MBHC_MECH_DETECT_TYPE_SHIFT));
+
+ if (ins) { /* hs insertion */
+ u32 btndet_curr_src;
+
+ /*
+ * If no micbias is enabled, then enable 100uA internal
+ * current source for Button detection
+ */
+ if (snd_soc_component_read32(component, WCD9335_ANA_MICB2) &
+ WCD9335_ANA_MICB2_ENABLE)
+ btndet_curr_src = WCD9335_ANA_MBHC_BD_ISRC_OFF;
+ else
+ btndet_curr_src = WCD9335_ANA_MBHC_BD_ISRC_100UA;
+
+ snd_soc_component_update_bits(component,
+ WCD9335_ANA_MBHC_ELECT,
+ WCD9335_ANA_MBHC_BD_ISRC_CTL_MASK,
+ btndet_curr_src);
+
+ /*
+ * if only a btn0 press event is receive just before
+ * insert event then its a 3 pole headphone else if
+ * both press and release event received then its
+ * a headset.
+ */
+ if (wcd->mbhc_btn0_released) {
+ snd_soc_jack_report(wcd->jack,
+ SND_JACK_HEADSET, hs_jack_mask);
+ wcd->accessory_type = SND_JACK_HEADSET;
+ } else {
+ snd_soc_jack_report(wcd->jack,
+ SND_JACK_HEADPHONE, hs_jack_mask);
+ wcd->accessory_type = SND_JACK_HEADPHONE;
+ }
+
+ wcd->detect_accessory_type = false;
+
+ } else { /* removal */
+ snd_soc_jack_report(wcd->jack, 0, hs_jack_mask);
+ wcd->detect_accessory_type = true;
+ wcd->mbhc_btn0_released = false;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wcd9335_mbhc_btn_press_irq(int irq, void *data)
+{
+ struct wcd9335_codec *wcd = data;
+ struct snd_soc_component *comp = wcd->component;
+ u32 btn_result, result;
+
+ /* do not handle any button events for headset without buttons */
+ if (wcd->accessory_type == SND_JACK_HEADPHONE)
+ return IRQ_HANDLED;
+
+ result = snd_soc_component_read32(comp, WCD9335_ANA_MBHC_RESULT_3);
+ btn_result = result & WCD9335_MBHC_BTN_RESULT_MASK;
+
+ switch (btn_result) {
+ case 0xf:
+ snd_soc_jack_report(wcd->jack, SND_JACK_BTN_4, btn_mask);
+ break;
+ case 0x4:
+ snd_soc_jack_report(wcd->jack, SND_JACK_BTN_4, btn_mask);
+ break;
+ case 0x3:
+ snd_soc_jack_report(wcd->jack, SND_JACK_BTN_3, btn_mask);
+ break;
+ case 0x2:
+ snd_soc_jack_report(wcd->jack, SND_JACK_BTN_2, btn_mask);
+ break;
+ case 0x1:
+ snd_soc_jack_report(wcd->jack, SND_JACK_BTN_1, btn_mask);
+ break;
+ case 0x0:
+ /* handle BTN_0 specially for type detection */
+ if (!wcd->detect_accessory_type)
+ snd_soc_jack_report(wcd->jack,
+ SND_JACK_BTN_0, btn_mask);
+ break;
+ default:
+ dev_err(comp->dev,
+ "Unexpected button press result (%x)", btn_result);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wcd9335_mbhc_bt_rel_irq(int irq, void *data)
+{
+ struct wcd9335_codec *wcd = data;
+
+
+ if (wcd->detect_accessory_type) {
+ u32 result = snd_soc_component_read32(wcd->component,
+ WCD9335_ANA_MBHC_RESULT_3);
+
+ /* check if its BTN0 thats released */
+ if (!(result & WCD9335_MBHC_BTN_RESULT_MASK))
+ wcd->mbhc_btn0_released = true;
+
+ } else {
+ if (wcd->accessory_type != SND_JACK_HEADPHONE)
+ snd_soc_jack_report(wcd->jack, 0, btn_mask);
+ }
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
{
struct wcd9335_codec *wcd = data;
@@ -4036,11 +4176,95 @@ static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
return ret;
}
+static void wcd9335_program_btn_threshold(struct wcd9335_codec *wcd)
+{
+ int i, vth;
+
+ for (i = 0; i < WCD9335_MBHC_MAX_BUTTONS; i++) {
+ vth = ((wcd->vref_btn[i] * 2) / 25) & 0x3F;
+ snd_soc_component_update_bits(wcd->component,
+ WCD9335_ANA_MBHC_BTN0 + i,
+ 0xFC, vth << 2);
+ }
+}
+
+static void wcd9335_mbhc_initialise(struct wcd9335_codec *wcd)
+{
+ struct snd_soc_component *comp = wcd->component;
+ u32 plug_type = 0;
+
+ snd_soc_component_update_bits(comp, WCD9335_MBHC_PLUG_DETECT_CTL,
+ WCD9335_MBHC_HSDET_PULLUP_CTL_MASK,
+ WCD9335_MBHC_HSDET_PULLUP_CTL_1_2P0_UA);
+
+ if (wcd->hphl_jack_type_normally_open)
+ plug_type |= WCD9335_MBHC_HPHL_PLUG_TYPE_NO;
+
+ if (wcd->gnd_jack_type_normally_open)
+ plug_type |= WCD9335_MBHC_GND_PLUG_TYPE_NO;
+
+ snd_soc_component_write(wcd->component, WCD9335_ANA_MBHC_MECH,
+ plug_type |
+ WCD9335_MBHC_L_DET_EN |
+ WCD9335_MBHC_HSL_PULLUP_COMP_EN |
+ WCD9335_MBHC_HPHL_100K_TO_GND_EN);
+
+ /* Insertion debounce set to 96ms */
+ snd_soc_component_write(wcd->component,
+ WCD9335_MBHC_PLUG_DETECT_CTL,
+ WCD9335_MBHC_DBNC_TIMER_INSREM_DBNC_T_96_MS|
+ WCD9335_MBHC_HSDET_PULLUP_CTL_1_2P0_UA);
+ /* Button Debounce set to 16ms */
+ snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_1,
+ WCD9335_MBHC_BTN_DBNC_MASK,
+ WCD9335_MBHC_BTN_DBNC_T_16_MS);
+
+ /* enable bias distribution control */
+ snd_soc_component_update_bits(comp, WCD9335_ANA_MBHC_ELECT,
+ WCD9335_ANA_MBHC_BIAS_EN_MASK,
+ WCD9335_ANA_MBHC_BIAS_EN);
+
+ snd_soc_component_update_bits(wcd->component,
+ WCD9335_ANA_MBHC_ELECT,
+ WCD9335_ANA_MBHC_BD_ISRC_CTL_MASK,
+ WCD9335_ANA_MBHC_BD_ISRC_100UA);
+
+ /* enable MBHC clock */
+ snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_1,
+ WCD9335_MBHC_CTL_RCO_EN_MASK,
+ WCD9335_MBHC_CTL_RCO_EN);
+
+ snd_soc_component_update_bits(wcd->component, WCD9335_MBHC_CTL_2,
+ WCD9335_MBHC_HS_VREF_CTL_MASK,
+ WCD9335_MBHC_HS_VREF_1P5_V);
+
+ /* program HS_VREF value */
+ wcd9335_program_btn_threshold(wcd);
+ /* Start FSM */
+ snd_soc_component_update_bits(wcd->component, WCD9335_ANA_MBHC_ELECT,
+ BIT(7), BIT(7));
+
+ wcd->mbhc_btn0_released = false;
+ wcd->detect_accessory_type = true;
+}
+
static struct wcd9335_irq wcd9335_irqs[] = {
{
.irq = WCD9335_IRQ_SLIMBUS,
.handler = wcd9335_slimbus_irq,
.name = "SLIM Slave",
+ }, {
+ .irq = WCD9335_IRQ_MBHC_SW_DET,
+ .handler = wcd9335_mbhc_sw_irq,
+ .name = "Headset Mech Insert Removal",
+ }, {
+ .irq = WCD9335_IRQ_MBHC_BUTTON_PRESS_DET,
+ .handler = wcd9335_mbhc_btn_press_irq,
+ .name = "Headset Button Press",
+ }, {
+ .irq = WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET,
+ .handler = wcd9335_mbhc_bt_rel_irq,
+ .name = "Headset Button Release",
},
};
@@ -4839,6 +5063,7 @@ static void wcd9335_codec_init(struct snd_soc_component *component)
wcd9335_codec_reg_init[i].val);
wcd9335_enable_efuse_sensing(component);
+ wcd9335_mbhc_initialise(wcd);
}
static int wcd9335_codec_probe(struct snd_soc_component *component)
@@ -4894,10 +5119,21 @@ static int wcd9335_codec_set_sysclk(struct snd_soc_component *comp,
return clk_set_rate(wcd->mclk, freq);
}
+static int wcd9335_codec_set_jack(struct snd_soc_component *comp,
+ struct snd_soc_jack *jack, void *data)
+{
+ struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
+
+ wcd->jack = jack;
+
+ return 0;
+}
+
static const struct snd_soc_component_driver wcd9335_component_drv = {
.probe = wcd9335_codec_probe,
.remove = wcd9335_codec_remove,
.set_sysclk = wcd9335_codec_set_sysclk,
+ .set_jack = wcd9335_codec_set_jack,
.controls = wcd9335_snd_controls,
.num_controls = ARRAY_SIZE(wcd9335_snd_controls),
.dapm_widgets = wcd9335_dapm_widgets,
@@ -4906,10 +5142,39 @@ static const struct snd_soc_component_driver wcd9335_component_drv = {
.num_dapm_routes = ARRAY_SIZE(wcd9335_audio_map),
};
+static void of_parse_mbhc_data(struct device *dev, struct wcd9335_codec *wcd)
+{
+ int rval;
+
+ if (of_property_read_bool(dev->of_node,
+ "qcom,hphl-jack-type-normally-open"))
+ wcd->hphl_jack_type_normally_open = true;
+ else
+ wcd->hphl_jack_type_normally_open = false;
+
+ if (of_property_read_bool(dev->of_node,
+ "qcom,gnd-jack-type-normally-open"))
+ wcd->gnd_jack_type_normally_open = true;
+ else
+ wcd->gnd_jack_type_normally_open = false;
+
+ wcd->mbhc_btn_enabled = true;
+ rval = of_property_read_u32_array(dev->of_node,
+ "qcom,mbhc-vthreshold",
+ &wcd->vref_btn[0],
+ WCD9335_MBHC_MAX_BUTTONS);
+ if (rval < 0) {
+ wcd->mbhc_btn_enabled = false;
+ dev_err(dev, "MBHC btn detection disabled\n");
+ }
+}
+
static int wcd9335_probe(struct wcd9335_codec *wcd)
{
struct device *dev = wcd->dev;
+ of_parse_mbhc_data(dev, wcd);
+
memcpy(wcd->rx_chs, wcd9335_rx_chs, sizeof(wcd9335_rx_chs));
memcpy(wcd->tx_chs, wcd9335_tx_chs, sizeof(wcd9335_tx_chs));
@@ -4997,6 +5262,33 @@ static const struct regmap_irq wcd9335_codec_irqs[] = {
.type_reg_mask = BIT(0),
},
},
+ [WCD9335_IRQ_MBHC_SW_DET] = {
+ .reg_offset = 1,
+ .mask = BIT(0),
+ .type = {
+ .type_reg_offset = 1,
+ .types_supported = IRQ_TYPE_EDGE_BOTH,
+ .type_reg_mask = BIT(0),
+ },
+ },
+ [WCD9335_IRQ_MBHC_BUTTON_PRESS_DET] = {
+ .reg_offset = 1,
+ .mask = BIT(2),
+ .type = {
+ .type_reg_offset = 1,
+ .types_supported = IRQ_TYPE_EDGE_BOTH,
+ .type_reg_mask = BIT(2),
+ },
+ },
+ [WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET] = {
+ .reg_offset = 1,
+ .mask = BIT(3),
+ .type = {
+ .type_reg_offset = 1,
+ .types_supported = IRQ_TYPE_EDGE_BOTH,
+ .type_reg_mask = BIT(3),
+ },
+ }
};
static const struct regmap_irq_chip wcd9335_regmap_irq1_chip = {
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 40f682f5dab8..3197c701cdc5 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -2112,7 +2112,7 @@ static struct clk *wcd934x_register_mclk_output(struct wcd934x_codec *wcd)
wcd->hw.init = &init;
hw = &wcd->hw;
- ret = clk_hw_register(wcd->dev->parent, hw);
+ ret = devm_clk_hw_register(wcd->dev->parent, hw);
if (ret)
return ERR_PTR(ret);
@@ -5050,6 +5050,13 @@ static int wcd934x_codec_probe(struct platform_device *pdev)
wcd934x_slim_dais,
ARRAY_SIZE(wcd934x_slim_dais));
}
+static int wcd934x_codec_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+
+ return 0;
+}
+
static const struct platform_device_id wcd934x_driver_id[] = {
{
@@ -5061,6 +5068,7 @@ MODULE_DEVICE_TABLE(platform, wcd934x_driver_id);
static struct platform_driver wcd934x_codec_driver = {
.probe = &wcd934x_codec_probe,
+ .remove = wcd934x_codec_remove,
.id_table = wcd934x_driver_id,
.driver = {
.name = "wcd934x-codec",
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c
index 1a69baefc5ce..2426f5e0e10d 100644
--- a/sound/soc/qcom/apq8096.c
+++ b/sound/soc/qcom/apq8096.c
@@ -5,14 +5,21 @@
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <sound/soc.h>
+#include <sound/jack.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
+#include <uapi/linux/input-event-codes.h>
#include "common.h"
#define SLIM_MAX_TX_PORTS 16
#define SLIM_MAX_RX_PORTS 16
#define WCD9335_DEFAULT_MCLK_RATE 9600000
+struct apq8096_card_data {
+ struct snd_soc_jack jack;
+ bool jack_setup;
+};
+
static int apq8096_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -67,6 +74,7 @@ static struct snd_soc_ops apq8096_ops = {
static int apq8096_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
+ struct apq8096_card_data *data = snd_soc_card_get_drvdata(rtd->card);
/*
* Codec SLIMBUS configuration
@@ -79,6 +87,8 @@ static int apq8096_init(struct snd_soc_pcm_runtime *rtd)
unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139,
140, 141, 142, 143};
+ struct snd_soc_card *card = rtd->card;
+ int rval;
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
@@ -86,6 +96,38 @@ static int apq8096_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dai_set_sysclk(codec_dai, 0, WCD9335_DEFAULT_MCLK_RATE,
SNDRV_PCM_STREAM_PLAYBACK);
+ if (!data->jack_setup) {
+ struct snd_jack *jack;
+
+ rval = snd_soc_card_jack_new(card, "Headset Jack",
+ SND_JACK_HEADSET |
+ SND_JACK_HEADPHONE |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4,
+ &data->jack, NULL, 0);
+
+ if (rval < 0) {
+ dev_err(card->dev, "Unable to add Headphone Jack\n");
+ return rval;
+ }
+
+ jack = data->jack.jack;
+
+ snd_jack_set_key(jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+ data->jack_setup = true;
+ }
+
+ rval = snd_soc_component_set_jack(codec_dai->component,
+ &data->jack, NULL);
+ if (rval != 0 && rval != -ENOTSUPP) {
+ dev_warn(card->dev, "Failed to set jack: %d\n", rval);
+ return rval;
+ }
+
return 0;
}
@@ -105,6 +147,7 @@ static void apq8096_add_be_ops(struct snd_soc_card *card)
static int apq8096_platform_probe(struct platform_device *pdev)
{
+ struct apq8096_card_data *data;
struct snd_soc_card *card;
struct device *dev = &pdev->dev;
int ret;
@@ -113,9 +156,14 @@ static int apq8096_platform_probe(struct platform_device *pdev)
if (!card)
return -ENOMEM;
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
card->dev = dev;
card->owner = THIS_MODULE;
dev_set_drvdata(dev, card);
+ snd_soc_card_set_drvdata(card, data);
ret = qcom_snd_parse_of(card);
if (ret)
return ret;
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 9a25307f6115..d42115e4284d 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -4,7 +4,7 @@
include local_config.mk
uname_M := $(shell uname -m 2>/dev/null || echo not)
-MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/')
+MACHINE ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/ppc64/')
# Without this, failed build products remain, with up-to-date timestamps,
# thus tricking Make (and you!) into believing that All Is Well, in subsequent
@@ -43,7 +43,7 @@ TEST_GEN_FILES += thuge-gen
TEST_GEN_FILES += transhuge-stress
TEST_GEN_FILES += userfaultfd
-ifeq ($(ARCH),x86_64)
+ifeq ($(MACHINE),x86_64)
CAN_BUILD_I386 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_32bit_program.c -m32)
CAN_BUILD_X86_64 := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_64bit_program.c)
CAN_BUILD_WITH_NOPIE := $(shell ./../x86/check_cc.sh $(CC) ../x86/trivial_program.c -no-pie)
@@ -65,13 +65,13 @@ TEST_GEN_FILES += $(BINARIES_64)
endif
else
-ifneq (,$(findstring $(ARCH),powerpc))
+ifneq (,$(findstring $(MACHINE),ppc64))
TEST_GEN_FILES += protection_keys
endif
endif
-ifneq (,$(filter $(MACHINE),arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64))
+ifneq (,$(filter $(MACHINE),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sh64 sparc64 x86_64))
TEST_GEN_FILES += va_128TBswitch
TEST_GEN_FILES += virtual_address_range
TEST_GEN_FILES += write_to_hugetlbfs
@@ -84,7 +84,7 @@ TEST_FILES := test_vmalloc.sh
KSFT_KHDR_INSTALL := 1
include ../lib.mk
-ifeq ($(ARCH),x86_64)
+ifeq ($(MACHINE),x86_64)
BINARIES_32 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_32))
BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))