summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.txt3
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt20
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-falcon.dtsi204
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-falcon.dtsi409
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton-smp2p.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton.dtsi32
-rw-r--r--arch/arm/configs/msmfalcon_defconfig2
-rw-r--r--arch/arm64/configs/msmfalcon-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmfalcon_defconfig1
-rw-r--r--arch/arm64/include/asm/mmu_context.h7
-rw-r--r--drivers/clk/msm/clock-mmss-cobalt.c9
-rw-r--r--drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c122
-rw-r--r--drivers/clk/qcom/clk-smd-rpm.c55
-rw-r--r--drivers/clk/qcom/common.c31
-rw-r--r--drivers/clk/qcom/common.h2
-rw-r--r--drivers/clk/qcom/gcc-msmfalcon.c9
-rw-r--r--drivers/devfreq/governor_memlat.c24
-rw-r--r--drivers/gpu/msm/adreno_a5xx_snapshot.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c24
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h8
-rw-r--r--drivers/mmc/host/sdhci-msm.c727
-rw-r--r--drivers/mmc/host/sdhci-msm.h4
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_intf.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c26
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_intf.c4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_rt.c7
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c6
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c157
-rw-r--r--drivers/power/qcom-charger/smb-lib.c777
-rw-r--r--drivers/power/qcom-charger/smb-lib.h25
-rw-r--r--drivers/power/qcom-charger/smb-reg.h24
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c12
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c7
-rw-r--r--drivers/scsi/ufs/ufshcd.c16
-rw-r--r--drivers/scsi/ufs/ufshcd.h7
-rw-r--r--drivers/soc/qcom/service-notifier.c2
-rw-r--r--drivers/usb/gadget/function/f_midi.c1
-rw-r--r--drivers/usb/pd/policy_engine.c198
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c177
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h35
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c51
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c95
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h73
-rw-r--r--include/dt-bindings/clock/msm-clocks-cobalt.h8
-rw-r--r--include/linux/power_supply.h2
-rw-r--r--kernel/sched/fair.c2
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c132
-rw-r--r--sound/soc/msm/msmcobalt.c6
58 files changed, 2760 insertions, 857 deletions
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 3fc5d6cda7c9..0b46fd3d8ebf 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,6 +4,9 @@ Secure Digital Host Controller provides standard host interface to SD/MMC/SDIO c
Required properties:
- compatible : should be "qcom,sdhci-msm"
+ For SDCC version 5.0.0, MCI registers are removed from SDCC interface
+ and some registers are moved to HC. New compatible string is added to
+ support this change - "qcom,sdhci-msm-v5".
- reg : should contain SDHC, SD Core register map.
- reg-names : indicates various resources passed to driver (via reg proptery) by name.
Required "reg-names" are "hc_mem" and "core_mem"
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
index 12ac75a8608c..82386ba9b082 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
@@ -110,6 +110,25 @@ Charger specific properties:
will use io-channel-names to match IIO input names
with IIO specifiers.
+- qcom,float-option
+ Usage: optional
+ Value type: <u32>
+ Definition: Configures how the charger behaves when a float charger is
+ detected by APSD
+ 1 - Treat as a DCP
+ 2 - Treat as a SDP
+ 3 - Disable charging
+ 4 - Suspend USB input
+
+- qcom,hvdcp-disable
+ Usage: optional
+ Value type: <empty>
+ Definition: Specifies if hvdcp charging is to be enabled or not.
+ If this property is not specified hvdcp will be enabled.
+ If this property is specified, hvdcp 2.0 detection will still
+ happen but the adapter won't be asked to switch to a higher
+ voltage point.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
@@ -143,7 +162,6 @@ pmicobalt_charger: qcom,qpnp-smb2 {
io-channels = <&pmic_rradc 0>;
io-channel-names = "rradc_batt_id";
- qcom,suspend-input;
dpdm-supply = <&qusb_phy0>;
qcom,step-soc-thresholds = <60 70 80 90>;
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-falcon.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-falcon.dtsi
new file mode 100644
index 000000000000..e4824418409b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-falcon.dtsi
@@ -0,0 +1,204 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/clock/qcom,gcc-msmfalcon.h>
+#include <dt-bindings/clock/qcom,mmcc-msmfalcon.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&soc {
+ anoc2_smmu: arm,smmu-anoc2@16c0000 {
+ compatible = "qcom,smmu-v2";
+ reg = <0x16c0000 0x40000>;
+ #iommu-cells = <1>;
+ qcom,register-save;
+ qcom,skip-init;
+ #global-interrupts = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 374 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 375 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 376 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 377 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 378 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock_rpmcc RPM_AGGR2_NOC_CLK>;
+ clock-names = "smmu_aggr2_noc_clk";
+ #clock-cells = <1>;
+ };
+
+ lpass_q6_smmu: arm,smmu-lpass_q6@5100000 {
+ status = "disabled";
+ compatible = "qcom,smmu-v2";
+ reg = <0x5100000 0x40000>;
+ #iommu-cells = <1>;
+ qcom,register-save;
+ qcom,skip-init;
+ #global-interrupts = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
+ vdd-supply = <&gdsc_hlos1_vote_lpass_adsp>;
+ clocks = <&clock_gcc HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>;
+ clock-names = "lpass_q6_smmu_clk";
+ #clock-cells = <1>;
+ };
+
+ mmss_bimc_smmu: arm,smmu-mmss@cd00000 {
+ status = "disabled";
+ compatible = "qcom,smmu-v2";
+ reg = <0xcd00000 0x40000>;
+ #iommu-cells = <1>;
+ qcom,register-save;
+ qcom,skip-init;
+ #global-interrupts = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
+ vdd-supply = <&gdsc_bimc_smmu>;
+ clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>,
+ <&clock_gcc MMSSNOC_AXI_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
+ <&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>;
+ clock-names = "mmss_mnoc_ahb_clk",
+ "mmssnoc_axi_clk",
+ "mmss_bimc_smmu_ahb_clk",
+ "mmss_bimc_smmu_axi_clk";
+ #clock-cells = <1>;
+ qcom,bus-master-id = <MSM_BUS_MNOC_BIMC_MAS>;
+ };
+
+ kgsl_smmu: arm,smmu-kgsl@5040000 {
+ status = "disabled";
+ compatible = "qcom,smmu-v2";
+ reg = <0x5040000 0x10000>;
+ #iommu-cells = <1>;
+ qcom,dynamic;
+ qcom,register-save;
+ qcom,skip-init;
+ #global-interrupts = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>;
+ vdd-supply = <&gdsc_gpu_cx>;
+ clocks = <&clock_gcc GCC_GPU_CFG_AHB_CLK>,
+ <&clock_gcc GCC_BIMC_GFX_CLK>,
+ <&clock_gcc GCC_GPU_BIMC_GFX_CLK>;
+ clock-names = "gcc_gpu_cfg_ahb_clk",
+ "gcc_bimc_gfx_clk",
+ "gcc_gpu_bimc_gfx_clk";
+ #clock-cells = <1>;
+ };
+
+ turing_q6_smmu: arm,smmu-turing_q6@5180000 {
+ status = "disabled";
+ compatible = "qcom,smmu-v2";
+ reg = <0x5180000 0x40000>;
+ #iommu-cells = <1>;
+ qcom,register-save;
+ qcom,skip-init;
+ #global-interrupts = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 536 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 537 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 538 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 540 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 546 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 547 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 549 IRQ_TYPE_LEVEL_HIGH>;
+ vdd-supply = <&gdsc_hlos1_vote_turing_adsp>;
+ clocks = <&clock_gcc HLOS1_VOTE_TURING_ADSP_SMMU_CLK>;
+ clock-names = "turing_q6_smmu_clk";
+ #clock-cells = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-falcon.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-falcon.dtsi
new file mode 100644
index 000000000000..f060f2d7008c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-impl-defs-falcon.dtsi
@@ -0,0 +1,409 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&kgsl_smmu {
+ attach-impl-defs = <0x6000 0x2378>,
+ <0x6060 0x1055>,
+ <0x678c 0x8>,
+ <0x6794 0x28>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x204>,
+ <0x6928 0x11000>,
+ <0x6930 0x800>,
+ <0x6960 0xffffffff>,
+ <0x6b64 0x1a5551>,
+ <0x6b68 0x9a82a382>;
+};
+
+&lpass_q6_smmu {
+ attach-impl-defs = <0x6000 0x2378>,
+ <0x6060 0x1055>,
+ <0x6070 0xe0>,
+ <0x6074 0xe0>,
+ <0x6078 0xe0>,
+ <0x607c 0xe0>,
+ <0x60f0 0xc0>,
+ <0x60f4 0xc8>,
+ <0x60f8 0xd0>,
+ <0x60fc 0xd8>,
+ <0x6170 0x0>,
+ <0x6174 0x30>,
+ <0x6178 0x60>,
+ <0x617c 0x90>,
+ <0x6270 0x0>,
+ <0x6274 0x2>,
+ <0x6278 0x4>,
+ <0x627c 0x6>,
+ <0x62f0 0x8>,
+ <0x62f4 0xe>,
+ <0x62f8 0x14>,
+ <0x62fc 0x1a>,
+ <0x6370 0x20>,
+ <0x6374 0x40>,
+ <0x6378 0x60>,
+ <0x637c 0x80>,
+ <0x6784 0x0>,
+ <0x678c 0x10>,
+ <0x67a0 0x0>,
+ <0x67a4 0x0>,
+ <0x67a8 0x20>,
+ <0x67b0 0x0>,
+ <0x67b4 0x8>,
+ <0x67b8 0xc8>,
+ <0x67d0 0x4>,
+ <0x67dc 0x8>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x202>,
+ <0x6928 0x10a00>,
+ <0x6930 0x500>,
+ <0x6960 0xffffffff>,
+ <0x6b64 0x121151>,
+ <0x6b68 0xea800080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x1>,
+ <0x6c14 0x1>,
+ <0x6c18 0x1>,
+ <0x6c1c 0x1>,
+ <0x6c20 0x2>,
+ <0x6c24 0x2>,
+ <0x6c28 0x2>,
+ <0x6c2c 0x2>,
+ <0x6c30 0x3>,
+ <0x6c34 0x3>,
+ <0x6c38 0x3>,
+ <0x6c3c 0x3>;
+};
+
+&turing_q6_smmu {
+ attach-impl-defs = <0x6000 0x2378>,
+ <0x6060 0x1055>,
+ <0x6070 0xe0>,
+ <0x6074 0xe0>,
+ <0x6078 0xe0>,
+ <0x607c 0xe0>,
+ <0x60f0 0xc0>,
+ <0x60f4 0xc8>,
+ <0x60f8 0xd0>,
+ <0x60fc 0xd8>,
+ <0x6170 0x0>,
+ <0x6174 0x30>,
+ <0x6178 0x60>,
+ <0x617c 0x90>,
+ <0x6270 0x0>,
+ <0x6274 0x2>,
+ <0x6278 0x4>,
+ <0x627c 0x6>,
+ <0x62f0 0x8>,
+ <0x62f4 0xe>,
+ <0x62f8 0x14>,
+ <0x62fc 0x1a>,
+ <0x6370 0x20>,
+ <0x6374 0x40>,
+ <0x6378 0x60>,
+ <0x637c 0x80>,
+ <0x6784 0x0>,
+ <0x678c 0x10>,
+ <0x67a0 0x0>,
+ <0x67a4 0x0>,
+ <0x67a8 0x20>,
+ <0x67b0 0x0>,
+ <0x67b4 0x8>,
+ <0x67b8 0xc8>,
+ <0x67d0 0x4>,
+ <0x67dc 0x8>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x202>,
+ <0x6928 0x10a00>,
+ <0x6930 0x500>,
+ <0x6960 0xffffffff>,
+ <0x6b64 0x121151>,
+ <0x6b68 0xea800080>,
+ <0x6c00 0x0>,
+ <0x6c04 0x0>,
+ <0x6c08 0x0>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x1>,
+ <0x6c14 0x1>,
+ <0x6c18 0x1>,
+ <0x6c1c 0x1>,
+ <0x6c20 0x2>,
+ <0x6c24 0x2>,
+ <0x6c28 0x2>,
+ <0x6c2c 0x2>,
+ <0x6c30 0x3>,
+ <0x6c34 0x3>,
+ <0x6c38 0x3>,
+ <0x6c3c 0x3>;
+};
+
+&mmss_bimc_smmu {
+ attach-impl-defs = <0x6000 0x2378>,
+ <0x6060 0x1055>,
+ <0x678c 0x28>,
+ <0x6794 0xe0>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6924 0x204>,
+ <0x6928 0x11002>,
+ <0x6930 0x800>,
+ <0x6960 0xffffffff>,
+ <0x6964 0xffffffff>,
+ <0x6968 0xffffffff>,
+ <0x696c 0xffffffff>,
+ <0x6b48 0x330330>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x3333>,
+ <0x6b54 0x3333>,
+ <0x6b64 0x1a5555>,
+ <0x6b68 0xbaaa892a>,
+ <0x6b70 0x10100202>,
+ <0x6b74 0x10100202>,
+ <0x6b78 0x10100000>,
+ <0x6b80 0x20042004>,
+ <0x6b84 0x20042004>;
+};
+
+&anoc2_smmu {
+ attach-impl-defs = <0x6000 0x2378>,
+ <0x6060 0x1055>,
+ <0x6070 0xf>,
+ <0x6074 0x23>,
+ <0x6078 0x37>,
+ <0x607c 0x39>,
+ <0x6080 0x3f>,
+ <0x6084 0x6f>,
+ <0x6088 0x74>,
+ <0x608c 0x92>,
+ <0x6090 0xb0>,
+ <0x6094 0xf0>,
+ <0x6098 0xf0>,
+ <0x609c 0xf0>,
+ <0x60f0 0x0>,
+ <0x60f4 0x1>,
+ <0x60f8 0x3>,
+ <0x60fc 0x4>,
+ <0x6100 0x6>,
+ <0x6104 0x8>,
+ <0x6108 0x9>,
+ <0x610c 0xb>,
+ <0x6110 0xd>,
+ <0x6114 0xf>,
+ <0x6118 0xf>,
+ <0x611c 0xf>,
+ <0x6170 0x0>,
+ <0x6174 0x0>,
+ <0x6178 0x0>,
+ <0x617c 0x0>,
+ <0x6180 0x0>,
+ <0x6184 0x0>,
+ <0x6188 0x0>,
+ <0x618c 0x0>,
+ <0x6190 0x0>,
+ <0x6194 0x0>,
+ <0x6198 0x0>,
+ <0x619c 0x0>,
+ <0x6270 0x0>,
+ <0x6274 0x1>,
+ <0x6278 0x2>,
+ <0x627c 0x4>,
+ <0x6280 0x4>,
+ <0x6284 0x6>,
+ <0x6288 0x6>,
+ <0x628c 0xa>,
+ <0x6290 0xc>,
+ <0x6294 0xc>,
+ <0x6298 0xc>,
+ <0x629c 0xc>,
+ <0x62f0 0xc>,
+ <0x62f4 0x12>,
+ <0x62f8 0x18>,
+ <0x62fc 0x1a>,
+ <0x6300 0x1d>,
+ <0x6304 0x23>,
+ <0x6308 0x24>,
+ <0x630c 0x28>,
+ <0x6310 0x2c>,
+ <0x6314 0x30>,
+ <0x6318 0x30>,
+ <0x631c 0x30>,
+ <0x6370 0x30>,
+ <0x6374 0x35>,
+ <0x6378 0x3a>,
+ <0x637c 0x3e>,
+ <0x6380 0x46>,
+ <0x6384 0x50>,
+ <0x6388 0x55>,
+ <0x638c 0x5d>,
+ <0x6390 0x67>,
+ <0x6394 0x80>,
+ <0x6398 0x80>,
+ <0x639c 0x80>,
+ <0x678c 0x12>,
+ <0x6794 0x32>,
+ <0x67a0 0x0>,
+ <0x67a4 0xe1>,
+ <0x67a8 0xf0>,
+ <0x67b0 0x0>,
+ <0x67b4 0xc>,
+ <0x67b8 0x9c>,
+ <0x67d0 0x0>,
+ <0x67dc 0x4>,
+ <0x67e0 0x8>,
+ <0x6800 0x6>,
+ <0x6900 0x3ff>,
+ <0x6b48 0x330330>,
+ <0x6b4c 0x81>,
+ <0x6b50 0x1313>,
+ <0x6b64 0x121155>,
+ <0x6b68 0xcaa84920>,
+ <0x6b70 0xc0c0000>,
+ <0x6b74 0x8080000>,
+ <0x6b78 0x8080000>,
+ <0x6b80 0x20002000>,
+ <0x6b84 0x20002000>,
+ <0x6c00 0x5>,
+ <0x6c04 0x0>,
+ <0x6c08 0x5>,
+ <0x6c0c 0x0>,
+ <0x6c10 0x5>,
+ <0x6c14 0x0>,
+ <0x6c18 0x5>,
+ <0x6c1c 0x0>,
+ <0x6c20 0x5>,
+ <0x6c24 0x0>,
+ <0x6c28 0x0>,
+ <0x6c2c 0x0>,
+ <0x6c30 0x0>,
+ <0x6c34 0x0>,
+ <0x6c38 0x0>,
+ <0x6c3c 0x0>,
+ <0x6c40 0x0>,
+ <0x6c44 0x0>,
+ <0x6c48 0x0>,
+ <0x6c4c 0x0>,
+ <0x6c50 0x0>,
+ <0x6c54 0x0>,
+ <0x6c58 0x0>,
+ <0x6c5c 0x0>,
+ <0x6c60 0x0>,
+ <0x6c64 0x0>,
+ <0x6c68 0x0>,
+ <0x6c6c 0x0>,
+ <0x6c70 0x0>,
+ <0x6c74 0x0>,
+ <0x6c78 0x0>,
+ <0x6c7c 0x0>,
+ <0x6c80 0x0>,
+ <0x6c84 0x0>,
+ <0x6c88 0x0>,
+ <0x6c8c 0x0>,
+ <0x6c90 0x0>,
+ <0x6c94 0x0>,
+ <0x6c98 0x0>,
+ <0x6c9c 0x0>,
+ <0x6ca0 0x0>,
+ <0x6ca4 0x0>,
+ <0x6ca8 0x0>,
+ <0x6cac 0x0>,
+ <0x6cb0 0x0>,
+ <0x6cb4 0x0>,
+ <0x6cb8 0x0>,
+ <0x6cbc 0x0>,
+ <0x6cc0 0x0>,
+ <0x6cc4 0x0>,
+ <0x6cc8 0x0>,
+ <0x6ccc 0x0>,
+ <0x6cd0 0x0>,
+ <0x6cd4 0x0>,
+ <0x6cd8 0x0>,
+ <0x6cdc 0x0>,
+ <0x6ce0 0x0>,
+ <0x6ce4 0x0>,
+ <0x6ce8 0x0>,
+ <0x6cec 0x0>,
+ <0x6cf0 0x0>,
+ <0x6cf4 0x0>,
+ <0x6cf8 0x0>,
+ <0x6cfc 0x0>,
+ <0x6d00 0x3>,
+ <0x6d04 0x4>,
+ <0x6d08 0x4>,
+ <0x6d0c 0x0>,
+ <0x6d10 0x8>,
+ <0x6d14 0x8>,
+ <0x6d18 0x3>,
+ <0x6d1c 0x2>,
+ <0x6d20 0x4>,
+ <0x6d24 0x0>,
+ <0x6d28 0x4>,
+ <0x6d2c 0x0>,
+ <0x6d30 0x7>,
+ <0x6d34 0x0>,
+ <0x6d38 0x6>,
+ <0x6d3c 0x0>,
+ <0x6d40 0x0>,
+ <0x6d44 0x1>,
+ <0x6d48 0x4>,
+ <0x6d4c 0x0>,
+ <0x6d50 0x4>,
+ <0x6d54 0x0>,
+ <0x6d58 0x4>,
+ <0x6d5c 0x0>,
+ <0x6d60 0x0>,
+ <0x6d64 0x0>,
+ <0x6d68 0x0>,
+ <0x6d6c 0x0>,
+ <0x6d70 0x0>,
+ <0x6d74 0x0>,
+ <0x6d78 0x0>,
+ <0x6d7c 0x0>,
+ <0x6d80 0x0>,
+ <0x6d84 0x0>,
+ <0x6d88 0x0>,
+ <0x6d8c 0x0>,
+ <0x6d90 0x0>,
+ <0x6d94 0x0>,
+ <0x6d98 0x0>,
+ <0x6d9c 0x0>,
+ <0x6da0 0x0>,
+ <0x6da4 0x0>,
+ <0x6da8 0x0>,
+ <0x6dac 0x0>,
+ <0x6db0 0x0>,
+ <0x6db4 0x0>,
+ <0x6db8 0x0>,
+ <0x6dbc 0x0>,
+ <0x6dc0 0x0>,
+ <0x6dc4 0x0>,
+ <0x6dc8 0x0>,
+ <0x6dcc 0x0>,
+ <0x6dd0 0x0>,
+ <0x6dd4 0x0>,
+ <0x6dd8 0x0>,
+ <0x6ddc 0x0>,
+ <0x6de0 0x0>,
+ <0x6de4 0x0>,
+ <0x6de8 0x0>,
+ <0x6dec 0x0>,
+ <0x6df0 0x0>,
+ <0x6df4 0x0>,
+ <0x6df8 0x0>,
+ <0x6dfc 0x0>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
index a37fa26b1055..27e537c9c702 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
@@ -391,6 +391,7 @@
<&clock_mmss clk_mmss_mnoc_ahb_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
<&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ <&clock_mmss clk_cpp_clk_src>,
<&clock_mmss clk_mmss_camss_cpp_clk>,
<&clock_mmss clk_mmss_camss_cpp_ahb_clk>,
<&clock_mmss clk_mmss_camss_cpp_axi_clk>,
@@ -400,10 +401,11 @@
clock-names = "mmssnoc_axi_clk",
"mnoc_ahb_clk",
"camss_ahb_clk", "camss_top_ahb_clk",
+ "cpp_src_clk",
"cpp_core_clk", "camss_cpp_ahb_clk",
"camss_cpp_axi_clk", "micro_iface_clk",
"mmss_smmu_axi_clk", "cpp_vbif_ahb_clk";
- qcom,clock-rates = <0 0 0 0 200000000 0 0 0 0 0>;
+ qcom,clock-rates = <0 0 0 0 200000000 200000000 0 0 0 0 0>;
qcom,min-clock-rate = <200000000>;
qcom,bus-master = <1>;
qcom,vbif-qos-setting = <0x20 0x10000000>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
index f9bb6e512d33..7948dc3489cb 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
@@ -289,9 +289,11 @@
reg = <0x1000 0x700>;
io-channels = <&smb138x_tadc 2>,
- <&smb138x_tadc 12>;
+ <&smb138x_tadc 12>,
+ <&smb138x_tadc 3>;
io-channel-names = "charger_temp",
- "charger_temp_max";
+ "charger_temp_max",
+ "batt_i";
};
};
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
index c028ea0eeab3..f8069856f3d8 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
@@ -61,7 +61,7 @@
50000000 100000000 200000000>;
qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
- cd-gpios = <&tlmm 95 0x1>;
+ cd-gpios = <&tlmm 95 0x0>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 2b2a201db8bc..0cc8a1420f3f 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -792,3 +792,5 @@
#include "msm-pmfalcon.dtsi"
#include "msm-pm2falcon.dtsi"
+#include "msm-arm-smmu-falcon.dtsi"
+#include "msm-arm-smmu-impl-defs-falcon.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmtriton-smp2p.dtsi b/arch/arm/boot/dts/qcom/msmtriton-smp2p.dtsi
index 695a4f3b63c7..1a72414de094 100644
--- a/arch/arm/boot/dts/qcom/msmtriton-smp2p.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton-smp2p.dtsi
@@ -133,4 +133,27 @@
compatible = "qcom,smp2pgpio-sleepstate-out";
gpios = <&smp2pgpio_sleepstate_2_out 0 0>;
};
+
+ /* ssr - inbound entry from lpass */
+ smp2pgpio_ssr_smp2p_2_in: qcom,smp2pgpio-ssr-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to lpass */
+ smp2pgpio_ssr_smp2p_2_out: qcom,smp2pgpio-ssr-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi
index 09bb5f081602..0e58fc9ec2e9 100644
--- a/arch/arm/boot/dts/qcom/msmtriton.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi
@@ -541,6 +541,38 @@
<0 425 0>; /* CE11 */
qcom,wlan-msa-memory = <0x100000>;
};
+
+ qcom,lpass@15700000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0x15700000 0x00100>;
+ interrupts = <0 162 1>;
+
+ vdd_cx-supply = <&pmfalcon_s3b_level>;
+ qcom,proxy-reg-names = "vdd_cx";
+ qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+ clocks = <&clock_rpmcc CXO_PIL_LPASS_CLK>;
+ clock-names = "xo";
+ qcom,proxy-clock-names = "xo";
+
+ qcom,pas-id = <1>;
+ qcom,proxy-timeout-ms = <10000>;
+ qcom,smem-id = <423>;
+ qcom,sysmon-id = <1>;
+ qcom,ssctl-instance-id = <0x14>;
+ qcom,firmware-name = "adsp";
+ memory-region = <&adsp_fw_mem>;
+
+ /* GPIO inputs from lpass */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>;
+
+ /* GPIO output to lpass */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
+ status = "ok";
+ };
};
#include "msmtriton-ion.dtsi"
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 64da50bb55b2..41572d54afcb 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -420,7 +420,7 @@ CONFIG_IPA3=y
CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_USB_BAM=y
-CONFIG_MSM_MDSS_PLL=y
+CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
diff --git a/arch/arm64/configs/msmfalcon-perf_defconfig b/arch/arm64/configs/msmfalcon-perf_defconfig
index 1bc352704893..5d271cad0aad 100644
--- a/arch/arm64/configs/msmfalcon-perf_defconfig
+++ b/arch/arm64/configs/msmfalcon-perf_defconfig
@@ -473,6 +473,7 @@ CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
+CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_ARM_SMMU=y
diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig
index 348c34a94119..707bc68c825f 100644
--- a/arch/arm64/configs/msmfalcon_defconfig
+++ b/arch/arm64/configs/msmfalcon_defconfig
@@ -483,6 +483,7 @@ CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
+CONFIG_QCOM_CLK_SMD_RPM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index 24165784b803..32441df2270e 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -27,19 +27,24 @@
#include <asm-generic/mm_hooks.h>
#include <asm/cputype.h>
#include <asm/pgtable.h>
+#include <linux/msm_rtb.h>
#ifdef CONFIG_PID_IN_CONTEXTIDR
static inline void contextidr_thread_switch(struct task_struct *next)
{
+ pid_t pid = task_pid_nr(next);
asm(
" msr contextidr_el1, %0\n"
" isb"
:
- : "r" (task_pid_nr(next)));
+ : "r" (pid));
+ uncached_logk(LOGK_CTXID, (void *)(u64)pid);
+
}
#else
static inline void contextidr_thread_switch(struct task_struct *next)
{
+ uncached_logk(LOGK_CTXID, (void *)(u64)task_pid_nr(next));
}
#endif
diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c
index 873dd40d3a44..9c1cdf967fb1 100644
--- a/drivers/clk/msm/clock-mmss-cobalt.c
+++ b/drivers/clk/msm/clock-mmss-cobalt.c
@@ -399,6 +399,8 @@ static struct clk_freq_tbl ftbl_cpp_clk_src[] = {
static struct clk_freq_tbl ftbl_cpp_clk_src_vq[] = {
F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
+ F_MM( 384000000, mmpll4_pll_out, 2, 0, 0),
+ F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
F_MM( 600000000, mmsscc_gpll0, 1, 0, 0),
@@ -1112,8 +1114,8 @@ static struct rcg_clk dp_pixel_clk_src = {
.parent = &ext_dp_phy_pll_vco.c,
.ops = &clk_ops_rcg_dp,
.flags = CLKFLAG_NO_RATE_CACHE,
- VDD_DIG_FMAX_MAP3(LOWER, 148380, LOW, 296740,
- NOMINAL, 593470),
+ VDD_DIG_FMAX_MAP3(LOWER, 154000000, LOW, 337500000,
+ NOMINAL, 675000000),
CLK_INIT(dp_pixel_clk_src.c),
},
};
@@ -2703,7 +2705,6 @@ static void msm_mmsscc_hamster_fixup(void)
csi2phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
mdp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
- dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 154000000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW] = 312500000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW_L1] = 375000000;
rot_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
@@ -2736,8 +2737,6 @@ static void msm_mmsscc_v2_fixup(void)
csi1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 480000000;
csi2_clk_src.c.fmax[VDD_DIG_NOMINAL] = 480000000;
csi3_clk_src.c.fmax[VDD_DIG_NOMINAL] = 480000000;
-
- dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 148380000;
}
int msm_mmsscc_cobalt_probe(struct platform_device *pdev)
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c b/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c
index 1228d925761b..4b2d8bba0940 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-cobalt.c
@@ -1016,19 +1016,19 @@ static struct clk_mux_ops mdss_mux_ops = {
* | vco_clk |
* +-------+-------+
* |
- * +--------------------------------------+
- * | |
- * +-------v-------+ |
- * | bitclk_src | |
- * | DIV(1..15) | |
- * +-------+-------+ |
- * | |
- * +--------------------+ |
- * Shadow Path | | |
- * + +-------v-------+ +------v------+ +------v-------+
- * | | byteclk_src | |post_bit_div | |post_vco_div |
- * | | DIV(8) | |DIV(1,2) | |DIV(1,4) |
- * | +-------+-------+ +------+------+ +------+-------+
+ * +----------------------+------------------+
+ * | | |
+ * +-------v-------+ +-------v-------+ +-------v-------+
+ * | bitclk_src | | post_vco_div1 | | post_vco_div4 |
+ * | DIV(1..15) | +-------+-------+ +-------+-------+
+ * +-------+-------+ | |
+ * | +------------+ |
+ * +--------------------+ | |
+ * Shadow Path | | | |
+ * + +-------v-------+ +------v------+ +---v-----v------+
+ * | | byteclk_src | |post_bit_div | \ post_vco_mux /
+ * | | DIV(8) | |DIV(1,2) | \ /
+ * | +-------+-------+ +------+------+ +---+------+
* | | | |
* | | +------+ +----+
* | +--------+ | |
@@ -1085,19 +1085,51 @@ static struct div_clk dsi0pll_bitclk_src = {
}
};
-static struct div_clk dsi0pll_post_vco_div = {
+static struct div_clk dsi0pll_post_vco_div1 = {
.data = {
.div = 1,
.min_div = 1,
+ .max_div = 1,
+ },
+ .ops = &clk_post_vco_div_ops,
+ .c = {
+ .parent = &dsi0pll_vco_clk.c,
+ .dbg_name = "dsi0pll_post_vco_div1",
+ .ops = &clk_ops_post_vco_div_c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(dsi0pll_post_vco_div1.c),
+ }
+};
+
+static struct div_clk dsi0pll_post_vco_div4 = {
+ .data = {
+ .div = 4,
+ .min_div = 4,
.max_div = 4,
},
.ops = &clk_post_vco_div_ops,
.c = {
.parent = &dsi0pll_vco_clk.c,
- .dbg_name = "dsi0pll_post_vco_div",
+ .dbg_name = "dsi0pll_post_vco_div4",
.ops = &clk_ops_post_vco_div_c,
.flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi0pll_post_vco_div.c),
+ CLK_INIT(dsi0pll_post_vco_div4.c),
+ }
+};
+
+static struct mux_clk dsi0pll_post_vco_mux = {
+ .num_parents = 2,
+ .parents = (struct clk_src[]) {
+ {&dsi0pll_post_vco_div1.c, 0},
+ {&dsi0pll_post_vco_div4.c, 1},
+ },
+ .ops = &mdss_mux_ops,
+ .c = {
+ .parent = &dsi0pll_post_vco_div1.c,
+ .dbg_name = "dsi0pll_post_vco_mux",
+ .ops = &clk_ops_gen_mux,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(dsi0pll_post_vco_mux.c),
}
};
@@ -1121,7 +1153,7 @@ static struct mux_clk dsi0pll_pclk_src_mux = {
.num_parents = 2,
.parents = (struct clk_src[]) {
{&dsi0pll_post_bit_div.c, 0},
- {&dsi0pll_post_vco_div.c, 1},
+ {&dsi0pll_post_vco_mux.c, 1},
},
.ops = &mdss_mux_ops,
.c = {
@@ -1222,19 +1254,51 @@ static struct div_clk dsi1pll_bitclk_src = {
}
};
-static struct div_clk dsi1pll_post_vco_div = {
+static struct div_clk dsi1pll_post_vco_div1 = {
.data = {
.div = 1,
.min_div = 1,
+ .max_div = 1,
+ },
+ .ops = &clk_post_vco_div_ops,
+ .c = {
+ .parent = &dsi1pll_vco_clk.c,
+ .dbg_name = "dsi1pll_post_vco_div1",
+ .ops = &clk_ops_post_vco_div_c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(dsi1pll_post_vco_div1.c),
+ }
+};
+
+static struct div_clk dsi1pll_post_vco_div4 = {
+ .data = {
+ .div = 4,
+ .min_div = 4,
.max_div = 4,
},
.ops = &clk_post_vco_div_ops,
.c = {
.parent = &dsi1pll_vco_clk.c,
- .dbg_name = "dsi1pll_post_vco_div",
+ .dbg_name = "dsi1pll_post_vco_div4",
.ops = &clk_ops_post_vco_div_c,
.flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(dsi1pll_post_vco_div.c),
+ CLK_INIT(dsi1pll_post_vco_div4.c),
+ }
+};
+
+static struct mux_clk dsi1pll_post_vco_mux = {
+ .num_parents = 2,
+ .parents = (struct clk_src[]) {
+ {&dsi1pll_post_vco_div1.c, 0},
+ {&dsi1pll_post_vco_div4.c, 1},
+ },
+ .ops = &mdss_mux_ops,
+ .c = {
+ .parent = &dsi1pll_post_vco_div1.c,
+ .dbg_name = "dsi1pll_post_vco_mux",
+ .ops = &clk_ops_gen_mux,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(dsi1pll_post_vco_mux.c),
}
};
@@ -1258,7 +1322,7 @@ static struct mux_clk dsi1pll_pclk_src_mux = {
.num_parents = 2,
.parents = (struct clk_src[]) {
{&dsi1pll_post_bit_div.c, 0},
- {&dsi1pll_post_vco_div.c, 1},
+ {&dsi1pll_post_vco_mux.c, 1},
},
.ops = &mdss_mux_ops,
.c = {
@@ -1338,7 +1402,9 @@ static struct clk_lookup mdss_dsi_pll0cc_cobalt[] = {
CLK_LIST(dsi0pll_pclk_src),
CLK_LIST(dsi0pll_pclk_src_mux),
CLK_LIST(dsi0pll_post_bit_div),
- CLK_LIST(dsi0pll_post_vco_div),
+ CLK_LIST(dsi0pll_post_vco_mux),
+ CLK_LIST(dsi0pll_post_vco_div1),
+ CLK_LIST(dsi0pll_post_vco_div4),
CLK_LIST(dsi0pll_bitclk_src),
CLK_LIST(dsi0pll_vco_clk),
};
@@ -1349,7 +1415,9 @@ static struct clk_lookup mdss_dsi_pll1cc_cobalt[] = {
CLK_LIST(dsi1pll_pclk_src),
CLK_LIST(dsi1pll_pclk_src_mux),
CLK_LIST(dsi1pll_post_bit_div),
- CLK_LIST(dsi1pll_post_vco_div),
+ CLK_LIST(dsi1pll_post_vco_mux),
+ CLK_LIST(dsi1pll_post_vco_div1),
+ CLK_LIST(dsi1pll_post_vco_div4),
CLK_LIST(dsi1pll_bitclk_src),
CLK_LIST(dsi1pll_vco_clk),
};
@@ -1407,7 +1475,9 @@ int dsi_pll_clock_register_cobalt(struct platform_device *pdev,
dsi0pll_pclk_src.priv = pll_res;
dsi0pll_pclk_src_mux.priv = pll_res;
dsi0pll_post_bit_div.priv = pll_res;
- dsi0pll_post_vco_div.priv = pll_res;
+ dsi0pll_post_vco_mux.priv = pll_res;
+ dsi0pll_post_vco_div1.priv = pll_res;
+ dsi0pll_post_vco_div4.priv = pll_res;
dsi0pll_bitclk_src.priv = pll_res;
dsi0pll_vco_clk.priv = pll_res;
@@ -1421,7 +1491,9 @@ int dsi_pll_clock_register_cobalt(struct platform_device *pdev,
dsi1pll_pclk_src.priv = pll_res;
dsi1pll_pclk_src_mux.priv = pll_res;
dsi1pll_post_bit_div.priv = pll_res;
- dsi1pll_post_vco_div.priv = pll_res;
+ dsi1pll_post_vco_mux.priv = pll_res;
+ dsi1pll_post_vco_div1.priv = pll_res;
+ dsi1pll_post_vco_div4.priv = pll_res;
dsi1pll_bitclk_src.priv = pll_res;
dsi1pll_vco_clk.priv = pll_res;
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
index ac007ec667bb..612e7b37a8d0 100644
--- a/drivers/clk/qcom/clk-smd-rpm.c
+++ b/drivers/clk/qcom/clk-smd-rpm.c
@@ -29,6 +29,8 @@
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/mfd/qcom-rpm.h>
+#include "clk-voter.h"
+
#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
@@ -603,7 +605,7 @@ DEFINE_CLK_SMD_RPM(msmfalcon, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM(msmfalcon, cnoc_periph_clk, cnoc_periph_a_clk,
QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msmfalcon, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
-DEFINE_CLK_SMD_RPM(msmfalcon, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk,
+DEFINE_CLK_SMD_RPM(msmfalcon, mmssnoc_axi_clk, mmssnoc_axi_a_clk,
QCOM_SMD_RPM_MMAXI_CLK, 0);
DEFINE_CLK_SMD_RPM(msmfalcon, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
DEFINE_CLK_SMD_RPM(msmfalcon, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
@@ -624,6 +626,27 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msmfalcon, ln_bb_clk2_pin,
ln_bb_clk2_pin_ao, 0x2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msmfalcon, ln_bb_clk3_pin,
ln_bb_clk3_pin_ao, 0x3);
+/* Voter clocks */
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, bimc_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, bimc_a_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_clk, cnoc_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, cnoc_a_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, snoc_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, snoc_a_clk, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_periph_keepalive_a_clk, cnoc_periph_a_clk,
+ LONG_MAX);
+static DEFINE_CLK_VOTER(mcd_ce1_clk, ce1_clk, 85710000);
+static DEFINE_CLK_VOTER(qcedev_ce1_clk, ce1_clk, 85710000);
+static DEFINE_CLK_VOTER(qcrypto_ce1_clk, ce1_clk, 85710000);
+static DEFINE_CLK_VOTER(qseecom_ce1_clk, ce1_clk, 85710000);
+static DEFINE_CLK_VOTER(scm_ce1_clk, ce1_clk, 85710000);
+
+static DEFINE_CLK_BRANCH_VOTER(cxo_dwc3_clk, cxo);
+static DEFINE_CLK_BRANCH_VOTER(cxo_lpm_clk, cxo);
+static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, cxo);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_lpass_clk, cxo);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_cdsp_clk, cxo);
+
static struct clk_hw *msmfalcon_clks[] = {
[RPM_XO_CLK_SRC] = &msmfalcon_cxo.hw,
[RPM_XO_A_CLK_SRC] = &msmfalcon_cxo_a.hw,
@@ -639,8 +662,8 @@ static struct clk_hw *msmfalcon_clks[] = {
[RPM_AGGR2_NOC_A_CLK] = &msmfalcon_aggre2_noc_a_clk.hw,
[RPM_CNOC_CLK] = &msmfalcon_cnoc_clk.hw,
[RPM_CNOC_A_CLK] = &msmfalcon_cnoc_a_clk.hw,
- [RPM_MMAXI_CLK] = &msmfalcon_mmssnoc_axi_rpm_clk.hw,
- [RPM_MMAXI_A_CLK] = &msmfalcon_mmssnoc_axi_rpm_a_clk.hw,
+ [RPM_MMAXI_CLK] = &msmfalcon_mmssnoc_axi_clk.hw,
+ [RPM_MMAXI_A_CLK] = &msmfalcon_mmssnoc_axi_a_clk.hw,
[RPM_IPA_CLK] = &msmfalcon_ipa_clk.hw,
[RPM_IPA_A_CLK] = &msmfalcon_ipa_a_clk.hw,
[RPM_CE1_CLK] = &msmfalcon_ce1_clk.hw,
@@ -661,6 +684,25 @@ static struct clk_hw *msmfalcon_clks[] = {
[RPM_LN_BB_CLK3_PIN_AO] = &msmfalcon_ln_bb_clk3_pin_ao.hw,
[RPM_CNOC_PERIPH_CLK] = &msmfalcon_cnoc_periph_clk.hw,
[RPM_CNOC_PERIPH_A_CLK] = &msmfalcon_cnoc_periph_a_clk.hw,
+
+ /* Voter Clocks */
+ [BIMC_MSMBUS_CLK] = &bimc_msmbus_clk.hw,
+ [BIMC_MSMBUS_A_CLK] = &bimc_msmbus_a_clk.hw,
+ [CNOC_MSMBUS_CLK] = &cnoc_msmbus_clk.hw,
+ [CNOC_MSMBUS_A_CLK] = &cnoc_msmbus_a_clk.hw,
+ [MCD_CE1_CLK] = &mcd_ce1_clk.hw,
+ [QCEDEV_CE1_CLK] = &qcedev_ce1_clk.hw,
+ [QCRYPTO_CE1_CLK] = &qcrypto_ce1_clk.hw,
+ [QSEECOM_CE1_CLK] = &qseecom_ce1_clk.hw,
+ [SCM_CE1_CLK] = &scm_ce1_clk.hw,
+ [SNOC_MSMBUS_CLK] = &snoc_msmbus_clk.hw,
+ [SNOC_MSMBUS_A_CLK] = &snoc_msmbus_a_clk.hw,
+ [CXO_DWC3_CLK] = &cxo_dwc3_clk.hw,
+ [CXO_LPM_CLK] = &cxo_lpm_clk.hw,
+ [CXO_OTG_CLK] = &cxo_otg_clk.hw,
+ [CXO_PIL_LPASS_CLK] = &cxo_pil_lpass_clk.hw,
+ [CXO_PIL_CDSP_CLK] = &cxo_pil_cdsp_clk.hw,
+ [CNOC_PERIPH_KEEPALIVE_A_CLK] = &cnoc_periph_keepalive_a_clk.hw,
};
static const struct rpm_smd_clk_desc rpm_clk_msmfalcon = {
@@ -757,9 +799,14 @@ static int rpm_smd_clk_probe(struct platform_device *pdev)
/* Keep an active vote on CXO in case no other driver votes for it */
if (is_8996)
clk_prepare_enable(msm8996_cxo_a.hw.clk);
- else if (is_falcon)
+ else if (is_falcon) {
clk_prepare_enable(msmfalcon_cxo_a.hw.clk);
+ /* Hold an active set vote for the cnoc_periph resource */
+ clk_set_rate(cnoc_periph_keepalive_a_clk.hw.clk, 19200000);
+ clk_prepare_enable(cnoc_periph_keepalive_a_clk.hw.clk);
+ }
+
dev_info(&pdev->dev, "Registered RPM clocks\n");
return 0;
diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c
index f7c226ab4307..423e975dffee 100644
--- a/drivers/clk/qcom/common.c
+++ b/drivers/clk/qcom/common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
int qcom_cc_really_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc, struct regmap *regmap)
{
- int i, ret;
+ int i = 0, ret, j = 0;
struct device *dev = &pdev->dev;
struct clk *clk;
struct clk_onecell_data *data;
@@ -187,8 +187,10 @@ int qcom_cc_really_probe(struct platform_device *pdev,
struct gdsc_desc *scd;
size_t num_clks = desc->num_clks;
struct clk_regmap **rclks = desc->clks;
+ struct clk_hw **hw_clks = desc->hwclks;
- cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+ cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) *
+ (num_clks + desc->num_hwclks),
GFP_KERNEL);
if (!cc)
return -ENOMEM;
@@ -196,17 +198,32 @@ int qcom_cc_really_probe(struct platform_device *pdev,
clks = cc->clks;
data = &cc->data;
data->clks = clks;
- data->clk_num = num_clks;
+ data->clk_num = num_clks + desc->num_hwclks;
- for (i = 0; i < num_clks; i++) {
- if (!rclks[i]) {
+ for (i = 0; i < desc->num_hwclks; i++) {
+ if (!hw_clks[i]) {
clks[i] = ERR_PTR(-ENOENT);
continue;
}
- clk = devm_clk_register_regmap(dev, rclks[i]);
+ clk = devm_clk_register(dev, hw_clks[i]);
if (IS_ERR(clk))
return PTR_ERR(clk);
clks[i] = clk;
+ pr_debug("Index for hw_clocks %d added %s\n", i,
+ __clk_get_name(clk));
+ }
+
+ for (j = i; j < num_clks; j++) {
+ if (!rclks[j]) {
+ clks[j] = ERR_PTR(-ENOENT);
+ continue;
+ }
+ clk = devm_clk_register_regmap(dev, rclks[j]);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clks[j] = clk;
+ pr_debug("Index for Regmap clocks %d added %s\n", j,
+ __clk_get_name(clk));
}
ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h
index 10cabca921be..e3f450533470 100644
--- a/drivers/clk/qcom/common.h
+++ b/drivers/clk/qcom/common.h
@@ -25,7 +25,9 @@ struct parent_map;
struct qcom_cc_desc {
const struct regmap_config *config;
struct clk_regmap **clks;
+ struct clk_hw **hwclks;
size_t num_clks;
+ size_t num_hwclks;
const struct qcom_reset_map *resets;
size_t num_resets;
struct gdsc **gdscs;
diff --git a/drivers/clk/qcom/gcc-msmfalcon.c b/drivers/clk/qcom/gcc-msmfalcon.c
index 78858a3c6f1c..2cbc9dff047b 100644
--- a/drivers/clk/qcom/gcc-msmfalcon.c
+++ b/drivers/clk/qcom/gcc-msmfalcon.c
@@ -2739,6 +2739,8 @@ static const struct qcom_cc_desc gcc_falcon_desc = {
.config = &gcc_falcon_regmap_config,
.clks = gcc_falcon_clocks,
.num_clks = ARRAY_SIZE(gcc_falcon_clocks),
+ .hwclks = gcc_msmfalcon_hws,
+ .num_hwclks = ARRAY_SIZE(gcc_msmfalcon_hws),
.resets = gcc_falcon_resets,
.num_resets = ARRAY_SIZE(gcc_falcon_resets),
};
@@ -2765,13 +2767,6 @@ static int gcc_falcon_probe(struct platform_device *pdev)
*/
regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
- /* register hardware clocks */
- for (i = 0; i < ARRAY_SIZE(gcc_msmfalcon_hws); i++) {
- clk = devm_clk_register(&pdev->dev, gcc_msmfalcon_hws[i]);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
- }
-
vdd_dig.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_dig");
if (IS_ERR(vdd_dig.regulator[0])) {
if (!(PTR_ERR(vdd_dig.regulator[0]) == -EPROBE_DEFER))
diff --git a/drivers/devfreq/governor_memlat.c b/drivers/devfreq/governor_memlat.c
index 010f9defe33e..a3c826e152e1 100644
--- a/drivers/devfreq/governor_memlat.c
+++ b/drivers/devfreq/governor_memlat.c
@@ -81,6 +81,29 @@ show_attr(__attr) \
store_attr(__attr, min, max) \
static DEVICE_ATTR(__attr, 0644, show_##__attr, store_##__attr)
+static ssize_t show_map(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *df = to_devfreq(dev);
+ struct memlat_node *n = df->data;
+ struct core_dev_map *map = n->hw->freq_map;
+ unsigned int cnt = 0;
+
+ cnt += snprintf(buf, PAGE_SIZE, "Core freq (MHz)\tDevice BW\n");
+
+ while (map->core_mhz && cnt < PAGE_SIZE) {
+ cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%15u\t%9u\n",
+ map->core_mhz, map->target_freq);
+ map++;
+ }
+ if (cnt < PAGE_SIZE)
+ cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "\n");
+
+ return cnt;
+}
+
+static DEVICE_ATTR(freq_map, 0444, show_map, NULL);
+
static unsigned long core_to_dev_freq(struct memlat_node *node,
unsigned long coref)
{
@@ -247,6 +270,7 @@ gov_attr(ratio_ceil, 1U, 10000U);
static struct attribute *dev_attr[] = {
&dev_attr_ratio_ceil.attr,
+ &dev_attr_freq_map.attr,
NULL,
};
diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c
index aeffeab2f6dc..c09d2f8c1947 100644
--- a/drivers/gpu/msm/adreno_a5xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c
@@ -410,8 +410,6 @@ static const unsigned int a5xx_registers[] = {
0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2,
/* GPMU */
0xA800, 0xA8FF, 0xAC60, 0xAC60,
- /* DPM */
- 0xB000, 0xB97F, 0xB9A0, 0xB9BF,
};
struct a5xx_hlsq_sp_tp_regs {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 9a469abc56ca..f65963c964b3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -30,10 +30,13 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#define VFE47_8996V1_VERSION 0x70000000
+#define VFE48_SDM660_VERSION 0x80000003
#define VFE47_BURST_LEN 3
+#define VFE48_SDM660_BURST_LEN 4
#define VFE47_FETCH_BURST_LEN 3
#define VFE47_STATS_BURST_LEN 3
+#define VFE48_SDM660_STATS_BURST_LEN 4
#define VFE47_UB_SIZE_VFE0 2048
#define VFE47_UB_SIZE_VFE1 1536
#define VFE47_UB_STATS_SIZE 144
@@ -359,13 +362,13 @@ void msm_vfe47_release_hardware(struct vfe_device *vfe_dev)
else
id = CAM_AHB_CLIENT_VFE1;
+ vfe_dev->hw_info->vfe_ops.platform_ops.set_clk_rate(vfe_dev, &rate);
+
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SUSPEND_VOTE) < 0)
pr_err("%s: failed to vote for AHB\n", __func__);
vfe_dev->ahb_vote = CAM_AHB_SUSPEND_VOTE;
- vfe_dev->hw_info->vfe_ops.platform_ops.set_clk_rate(vfe_dev, &rate);
-
vfe_dev->hw_info->vfe_ops.platform_ops.enable_clks(
vfe_dev, 0);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators(vfe_dev, 0);
@@ -1504,7 +1507,7 @@ void msm_vfe47_axi_cfg_wm_reg(
{
uint32_t val;
int vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info);
- uint32_t wm_base;
+ uint32_t wm_base, burst_len;
wm_base = VFE47_WM_BASE(stream_info->wm[vfe_idx][plane_idx]);
val = msm_camera_io_r(vfe_dev->vfe_base + wm_base + 0x14);
@@ -1522,7 +1525,11 @@ void msm_vfe47_axi_cfg_wm_reg(
output_height - 1);
msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x1C);
/* WR_BUFFER_CFG */
- val = VFE47_BURST_LEN |
+ if (vfe_dev->vfe_hw_version == VFE48_SDM660_VERSION)
+ burst_len = VFE48_SDM660_BURST_LEN;
+ else
+ burst_len = VFE47_BURST_LEN;
+ val = burst_len |
(stream_info->plane_cfg[vfe_idx][plane_idx].
output_height - 1) <<
2 |
@@ -2089,7 +2096,7 @@ void msm_vfe47_stats_clear_wm_reg(
void msm_vfe47_stats_cfg_ub(struct vfe_device *vfe_dev)
{
int i;
- uint32_t ub_offset = 0;
+ uint32_t ub_offset = 0, stats_burst_len;
uint32_t ub_size[VFE47_NUM_STATS_TYPE] = {
16, /* MSM_ISP_STATS_HDR_BE */
16, /* MSM_ISP_STATS_BG */
@@ -2108,9 +2115,14 @@ void msm_vfe47_stats_cfg_ub(struct vfe_device *vfe_dev)
else
pr_err("%s: incorrect VFE device\n", __func__);
+ if (vfe_dev->vfe_hw_version == VFE48_SDM660_VERSION)
+ stats_burst_len = VFE48_SDM660_STATS_BURST_LEN;
+ else
+ stats_burst_len = VFE47_STATS_BURST_LEN;
+
for (i = 0; i < VFE47_NUM_STATS_TYPE; i++) {
ub_offset -= ub_size[i];
- msm_camera_io_w(VFE47_STATS_BURST_LEN << 30 |
+ msm_camera_io_w(stats_burst_len << 30 |
ub_offset << 16 | (ub_size[i] - 1),
vfe_dev->vfe_base + VFE47_STATS_BASE(i) + 0x14);
}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 258e08c1b34f..e0d6977b24a6 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -2748,14 +2748,14 @@ static int msm_cpp_validate_input(unsigned int cmd, void *arg,
break;
default: {
if (ioctl_ptr == NULL) {
- pr_err("Wrong ioctl_ptr %pK\n", ioctl_ptr);
+ pr_err("Wrong ioctl_ptr for cmd %u\n", cmd);
return -EINVAL;
}
*ioctl_ptr = arg;
if ((*ioctl_ptr == NULL) ||
- ((*ioctl_ptr)->ioctl_ptr == NULL)) {
- pr_err("Wrong arg %pK\n", arg);
+ (*ioctl_ptr)->ioctl_ptr == NULL) {
+ pr_err("Error invalid ioctl argument cmd %u", cmd);
return -EINVAL;
}
break;
@@ -2780,6 +2780,12 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
pr_err("cpp_dev is null\n");
return -EINVAL;
}
+
+ if (_IOC_DIR(cmd) == _IOC_NONE) {
+ pr_err("Invalid ioctl/subdev cmd %u", cmd);
+ return -EINVAL;
+ }
+
rc = msm_cpp_validate_input(cmd, arg, &ioctl_ptr);
if (rc != 0) {
pr_err("input validation failed\n");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h
index 79d7d94582c5..bba0b2bc9cdb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_5_0_1_hwreg.h
@@ -50,11 +50,11 @@ struct csiphy_reg_3ph_parms_t csiphy_v5_0_1_3ph = {
{0x148, 0xFE},
{0x14C, 0x1},
{0x154, 0x0},
- {0x15C, 0x23},
+ {0x15C, 0x63},
{0x160, ULPM_WAKE_UP_TIMER_MODE},
{0x164, 0x00},
- {0x168, 0xA0},
- {0x16C, 0x25},
+ {0x168, 0xAC},
+ {0x16C, 0xA5},
{0x170, 0x41},
{0x174, 0x41},
{0x178, 0x3E},
@@ -98,7 +98,7 @@ struct csiphy_reg_3ph_parms_t csiphy_v5_0_1_3ph = {
{0x0, 0x91},
{0x70C, 0xA5},
{0x38, 0xFE},
- {0x81c, 0x6},
+ {0x81c, 0x2},
};
struct csiphy_settings_t csiphy_combo_mode_v5_0_1 = {
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index be3ccf2536d9..203daf3bd5eb 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/gfp.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
@@ -48,11 +49,7 @@
#define CORE_SW_RST (1 << 7)
#define SDHCI_VER_100 0x2B
-#define CORE_MCI_DATA_CNT 0x30
-#define CORE_MCI_STATUS 0x34
-#define CORE_MCI_FIFO_CNT 0x44
-#define CORE_MCI_VERSION 0x050
#define CORE_VERSION_STEP_MASK 0x0000FFFF
#define CORE_VERSION_MINOR_MASK 0x0FFF0000
#define CORE_VERSION_MINOR_SHIFT 16
@@ -61,23 +58,12 @@
#define CORE_VERSION_TARGET_MASK 0x000000FF
#define SDHCI_MSM_VER_420 0x49
-#define CORE_GENERICS 0x70
#define SWITCHABLE_SIGNALLING_VOL (1 << 29)
#define CORE_HC_MODE 0x78
#define HC_MODE_EN 0x1
#define FF_CLK_SW_RST_DIS (1 << 13)
-#define CORE_TESTBUS_CONFIG 0x0CC
-#define CORE_TESTBUS_SEL2_BIT 4
-#define CORE_TESTBUS_ENA (1 << 3)
-#define CORE_TESTBUS_SEL2 (1 << CORE_TESTBUS_SEL2_BIT)
-
-#define CORE_PWRCTL_STATUS 0xDC
-#define CORE_PWRCTL_MASK 0xE0
-#define CORE_PWRCTL_CLEAR 0xE4
-#define CORE_PWRCTL_CTL 0xE8
-
#define CORE_PWRCTL_BUS_OFF 0x01
#define CORE_PWRCTL_BUS_ON (1 << 1)
#define CORE_PWRCTL_IO_LOW (1 << 2)
@@ -91,7 +77,6 @@
#define INT_MASK 0xF
#define MAX_PHASES 16
-#define CORE_DLL_CONFIG 0x100
#define CORE_CMD_DAT_TRACK_SEL (1 << 0)
#define CORE_DLL_EN (1 << 16)
#define CORE_CDR_EN (1 << 17)
@@ -100,11 +85,9 @@
#define CORE_DLL_PDN (1 << 29)
#define CORE_DLL_RST (1 << 30)
-#define CORE_DLL_STATUS 0x108
#define CORE_DLL_LOCK (1 << 7)
#define CORE_DDR_DLL_LOCK (1 << 11)
-#define CORE_VENDOR_SPEC 0x10C
#define CORE_CLK_PWRSAVE (1 << 1)
#define CORE_HC_MCLK_SEL_DFLT (2 << 8)
#define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -117,23 +100,16 @@
#define CORE_HC_SELECT_IN_MASK (7 << 19)
#define CORE_VENDOR_SPEC_POR_VAL 0xA1C
-#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR0 0x114
-#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 0x118
-
-#define CORE_VENDOR_SPEC_FUNC2 0x110
#define HC_SW_RST_WAIT_IDLE_DIS (1 << 20)
#define HC_SW_RST_REQ (1 << 21)
#define CORE_ONE_MID_EN (1 << 25)
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11C
#define CORE_8_BIT_SUPPORT (1 << 18)
#define CORE_3_3V_SUPPORT (1 << 24)
#define CORE_3_0V_SUPPORT (1 << 25)
#define CORE_1_8V_SUPPORT (1 << 26)
#define CORE_SYS_BUS_SUPPORT_64_BIT BIT(28)
-#define CORE_SDCC_DEBUG_REG 0x124
-
#define CORE_CSR_CDC_CTLR_CFG0 0x130
#define CORE_SW_TRIG_FULL_CALIB (1 << 16)
#define CORE_HW_AUTOCAL_ENA (1 << 17)
@@ -161,25 +137,20 @@
#define CORE_CDC_SWITCH_BYPASS_OFF (1 << 0)
#define CORE_CDC_SWITCH_RC_EN (1 << 1)
-#define CORE_DDR_200_CFG 0x184
#define CORE_CDC_T4_DLY_SEL (1 << 0)
#define CORE_CMDIN_RCLK_EN (1 << 1)
#define CORE_START_CDC_TRAFFIC (1 << 6)
-#define CORE_VENDOR_SPEC3 0x1B0
#define CORE_PWRSAVE_DLL (1 << 3)
#define CORE_CMDEN_HS400_INPUT_MASK_CNT (1 << 13)
-#define CORE_DLL_CONFIG_2 0x1B4
#define CORE_DDR_CAL_EN (1 << 0)
#define CORE_FLL_CYCLE_CNT (1 << 18)
#define CORE_DLL_CLOCK_DISABLE (1 << 21)
-#define CORE_DDR_CONFIG 0x1B8
#define DDR_CONFIG_POR_VAL 0x80040853
#define DDR_CONFIG_PRG_RCLK_DLY_MASK 0x1FF
#define DDR_CONFIG_PRG_RCLK_DLY 115
-#define CORE_DDR_CONFIG_2 0x1BC
#define DDR_CONFIG_2_POR_VAL 0x80040873
/* 512 descriptors */
@@ -196,6 +167,149 @@
#define MAX_DRV_TYPES_SUPPORTED_HS200 4
#define MSM_AUTOSUSPEND_DELAY_MS 100
+struct sdhci_msm_offset {
+ u32 CORE_MCI_DATA_CNT;
+ u32 CORE_MCI_STATUS;
+ u32 CORE_MCI_FIFO_CNT;
+ u32 CORE_MCI_VERSION;
+ u32 CORE_GENERICS;
+ u32 CORE_TESTBUS_CONFIG;
+ u32 CORE_TESTBUS_SEL2_BIT;
+ u32 CORE_TESTBUS_ENA;
+ u32 CORE_TESTBUS_SEL2;
+ u32 CORE_PWRCTL_STATUS;
+ u32 CORE_PWRCTL_MASK;
+ u32 CORE_PWRCTL_CLEAR;
+ u32 CORE_PWRCTL_CTL;
+ u32 CORE_SDCC_DEBUG_REG;
+ u32 CORE_DLL_CONFIG;
+ u32 CORE_DLL_STATUS;
+ u32 CORE_VENDOR_SPEC;
+ u32 CORE_VENDOR_SPEC_ADMA_ERR_ADDR0;
+ u32 CORE_VENDOR_SPEC_ADMA_ERR_ADDR1;
+ u32 CORE_VENDOR_SPEC_FUNC2;
+ u32 CORE_VENDOR_SPEC_CAPABILITIES0;
+ u32 CORE_DDR_200_CFG;
+ u32 CORE_VENDOR_SPEC3;
+ u32 CORE_DLL_CONFIG_2;
+ u32 CORE_DDR_CONFIG;
+ u32 CORE_DDR_CONFIG_2;
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
+ .CORE_MCI_DATA_CNT = 0x35C,
+ .CORE_MCI_STATUS = 0x324,
+ .CORE_MCI_FIFO_CNT = 0x308,
+ .CORE_MCI_VERSION = 0x318,
+ .CORE_GENERICS = 0x320,
+ .CORE_TESTBUS_CONFIG = 0x32C,
+ .CORE_TESTBUS_SEL2_BIT = 3,
+ .CORE_TESTBUS_ENA = (1 << 31),
+ .CORE_TESTBUS_SEL2 = (1 << 3),
+ .CORE_PWRCTL_STATUS = 0x240,
+ .CORE_PWRCTL_MASK = 0x244,
+ .CORE_PWRCTL_CLEAR = 0x248,
+ .CORE_PWRCTL_CTL = 0x24C,
+ .CORE_SDCC_DEBUG_REG = 0x358,
+ .CORE_DLL_CONFIG = 0x200,
+ .CORE_DLL_STATUS = 0x208,
+ .CORE_VENDOR_SPEC = 0x20C,
+ .CORE_VENDOR_SPEC_ADMA_ERR_ADDR0 = 0x214,
+ .CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 = 0x218,
+ .CORE_VENDOR_SPEC_FUNC2 = 0x210,
+ .CORE_VENDOR_SPEC_CAPABILITIES0 = 0x21C,
+ .CORE_DDR_200_CFG = 0x224,
+ .CORE_VENDOR_SPEC3 = 0x250,
+ .CORE_DLL_CONFIG_2 = 0x254,
+ .CORE_DDR_CONFIG = 0x258,
+ .CORE_DDR_CONFIG_2 = 0x25C,
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
+ .CORE_MCI_DATA_CNT = 0x30,
+ .CORE_MCI_STATUS = 0x34,
+ .CORE_MCI_FIFO_CNT = 0x44,
+ .CORE_MCI_VERSION = 0x050,
+ .CORE_GENERICS = 0x70,
+ .CORE_TESTBUS_CONFIG = 0x0CC,
+ .CORE_TESTBUS_SEL2_BIT = 4,
+ .CORE_TESTBUS_ENA = (1 << 3),
+ .CORE_TESTBUS_SEL2 = (1 << 4),
+ .CORE_PWRCTL_STATUS = 0xDC,
+ .CORE_PWRCTL_MASK = 0xE0,
+ .CORE_PWRCTL_CLEAR = 0xE4,
+ .CORE_PWRCTL_CTL = 0xE8,
+ .CORE_SDCC_DEBUG_REG = 0x124,
+ .CORE_DLL_CONFIG = 0x100,
+ .CORE_DLL_STATUS = 0x108,
+ .CORE_VENDOR_SPEC = 0x10C,
+ .CORE_VENDOR_SPEC_ADMA_ERR_ADDR0 = 0x114,
+ .CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 = 0x118,
+ .CORE_VENDOR_SPEC_FUNC2 = 0x110,
+ .CORE_VENDOR_SPEC_CAPABILITIES0 = 0x11C,
+ .CORE_DDR_200_CFG = 0x184,
+ .CORE_VENDOR_SPEC3 = 0x1B0,
+ .CORE_DLL_CONFIG_2 = 0x1B4,
+ .CORE_DDR_CONFIG = 0x1B8,
+ .CORE_DDR_CONFIG_2 = 0x1BC,
+};
+
+u8 sdhci_msm_readb_relaxed(struct sdhci_host *host, u32 offset)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ void __iomem *base_addr;
+
+ if (msm_host->mci_removed)
+ base_addr = host->ioaddr;
+ else
+ base_addr = msm_host->core_mem;
+
+ return readb_relaxed(base_addr + offset);
+}
+
+u32 sdhci_msm_readl_relaxed(struct sdhci_host *host, u32 offset)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ void __iomem *base_addr;
+
+ if (msm_host->mci_removed)
+ base_addr = host->ioaddr;
+ else
+ base_addr = msm_host->core_mem;
+
+ return readl_relaxed(base_addr + offset);
+}
+
+void sdhci_msm_writeb_relaxed(u8 val, struct sdhci_host *host, u32 offset)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ void __iomem *base_addr;
+
+ if (msm_host->mci_removed)
+ base_addr = host->ioaddr;
+ else
+ base_addr = msm_host->core_mem;
+
+ writeb_relaxed(val, base_addr + offset);
+}
+
+void sdhci_msm_writel_relaxed(u32 val, struct sdhci_host *host, u32 offset)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ void __iomem *base_addr;
+
+ if (msm_host->mci_removed)
+ base_addr = host->ioaddr;
+ else
+ base_addr = msm_host->core_mem;
+
+ writel_relaxed(val, base_addr + offset);
+}
+
static const u32 tuning_block_64[] = {
0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
@@ -241,10 +355,14 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host,
u32 wait_cnt = 50;
u8 ck_out_en = 0;
struct mmc_host *mmc = host->mmc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
/* poll for CK_OUT_EN bit. max. poll time = 50us */
- ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
- CORE_CK_OUT_EN);
+ ck_out_en = !!(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) & CORE_CK_OUT_EN);
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -256,7 +374,7 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host,
udelay(1);
ck_out_en = !!(readl_relaxed(host->ioaddr +
- CORE_DLL_CONFIG) & CORE_CK_OUT_EN);
+ msm_host_offset->CORE_DLL_CONFIG) & CORE_CK_OUT_EN);
}
out:
return rc;
@@ -270,18 +388,25 @@ static int msm_enable_cdr_cm_sdc4_dll(struct sdhci_host *host)
{
int rc = 0;
u32 config;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
- config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
config |= CORE_CDR_EN;
config &= ~(CORE_CDR_EXT_EN | CORE_CK_OUT_EN);
- writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
rc = msm_dll_poll_ck_out_en(host, 0);
if (rc)
goto err;
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) |
- CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) | CORE_CK_OUT_EN),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
rc = msm_dll_poll_ck_out_en(host, 1);
if (rc)
@@ -328,6 +453,8 @@ static int sdhci_msm_config_auto_tuning_cmd(struct sdhci_host *host,
int rc = 0;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
u32 val = 0;
if (!msm_host->en_auto_cmd21)
@@ -340,11 +467,13 @@ static int sdhci_msm_config_auto_tuning_cmd(struct sdhci_host *host,
if (enable) {
rc = msm_enable_cdr_cm_sdc4_dll(host);
- writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
- val, host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) | val,
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC);
} else {
- writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
- ~val, host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) & ~val,
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC);
}
return rc;
}
@@ -352,6 +481,10 @@ static int sdhci_msm_config_auto_tuning_cmd(struct sdhci_host *host,
static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
{
int rc = 0;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
u8 grey_coded_phase_table[] = {0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
0xC, 0xD, 0xF, 0xE, 0xA, 0xB, 0x9,
0x8};
@@ -362,10 +495,12 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
spin_lock_irqsave(&host->lock, flags);
- config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
- writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
rc = msm_dll_poll_ck_out_en(host, 0);
@@ -376,24 +511,28 @@ static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
* Write the selected DLL clock output phase (0 ... 15)
* to CDR_SELEXT bit field of DLL_CONFIG register.
*/
- writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+ writel_relaxed(((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
& ~(0xF << 20))
| (grey_coded_phase_table[phase] << 20)),
- host->ioaddr + CORE_DLL_CONFIG);
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) | CORE_CK_OUT_EN),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
rc = msm_dll_poll_ck_out_en(host, 1);
if (rc)
goto err_out;
- config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ config = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
config |= CORE_CDR_EN;
config &= ~CORE_CDR_EXT_EN;
- writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
goto out;
err_out:
@@ -522,6 +661,10 @@ static int msm_find_most_appropriate_phase(struct sdhci_host *host,
static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
{
u32 mclk_freq = 0;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
/* Program the MCLK value to MCLK_FREQ bit field */
if (host->clock <= 112000000)
@@ -541,9 +684,10 @@ static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
else if (host->clock <= 200000000)
mclk_freq = 7;
- writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+ writel_relaxed(((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
& ~(7 << 24)) | (mclk_freq << 24)),
- host->ioaddr + CORE_DLL_CONFIG);
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
}
/* Initialize the DLL (Programmable Delay Line ) */
@@ -551,6 +695,8 @@ static int msm_init_cm_dll(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
struct mmc_host *mmc = host->mmc;
int rc = 0;
unsigned long flags;
@@ -559,8 +705,8 @@ static int msm_init_cm_dll(struct sdhci_host *host)
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
spin_lock_irqsave(&host->lock, flags);
- prev_pwrsave = !!(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
- CORE_CLK_PWRSAVE);
+ prev_pwrsave = !!(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) & CORE_CLK_PWRSAVE);
curr_pwrsave = prev_pwrsave;
/*
* Make sure that clock is always enabled when DLL
@@ -569,76 +715,89 @@ static int msm_init_cm_dll(struct sdhci_host *host)
* here and re-enable it once tuning is completed.
*/
if (prev_pwrsave) {
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE),
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
+ & ~CORE_CLK_PWRSAVE), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
curr_pwrsave = false;
}
if (msm_host->use_updated_dll_reset) {
/* Disable the DLL clock */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_CK_OUT_EN),
- host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
+ & ~CORE_CK_OUT_EN), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
- | CORE_DLL_CLOCK_DISABLE),
- host->ioaddr + CORE_DLL_CONFIG_2);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2)
+ | CORE_DLL_CLOCK_DISABLE), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2);
}
/* Write 1 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) | CORE_DLL_RST),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) | CORE_DLL_PDN),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
msm_cm_dll_set_freq(host);
if (msm_host->use_updated_dll_reset) {
u32 mclk_freq = 0;
- if ((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
+ if ((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2)
& CORE_FLL_CYCLE_CNT))
mclk_freq = (u32) ((host->clock / TCXO_FREQ) * 8);
else
mclk_freq = (u32) ((host->clock / TCXO_FREQ) * 4);
- writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
- & ~(0xFF << 10)) | (mclk_freq << 10)),
- host->ioaddr + CORE_DLL_CONFIG_2);
+ writel_relaxed(((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2)
+ & ~(0xFF << 10)) | (mclk_freq << 10)),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_2);
/* wait for 5us before enabling DLL clock */
udelay(5);
}
/* Write 0 to DLL_RST bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) & ~CORE_DLL_RST),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) & ~CORE_DLL_PDN),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
if (msm_host->use_updated_dll_reset) {
msm_cm_dll_set_freq(host);
/* Enable the DLL clock */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
- & ~CORE_DLL_CLOCK_DISABLE),
- host->ioaddr + CORE_DLL_CONFIG_2);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2)
+ & ~CORE_DLL_CLOCK_DISABLE), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2);
}
/* Set DLL_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG) | CORE_DLL_EN),
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG);
/* Set CK_OUT_EN bit to 1. */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
+ | CORE_CK_OUT_EN), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
wait_cnt = 50;
/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
- while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
- CORE_DLL_LOCK)) {
+ while (!(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_STATUS) & CORE_DLL_LOCK)) {
/* max. wait for 50us sec for LOCK bit to be set */
if (--wait_cnt == 0) {
pr_err("%s: %s: DLL failed to LOCK\n",
@@ -653,14 +812,16 @@ static int msm_init_cm_dll(struct sdhci_host *host)
out:
/* Restore the correct PWRSAVE state */
if (prev_pwrsave ^ curr_pwrsave) {
- u32 reg = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+ u32 reg = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
if (prev_pwrsave)
reg |= CORE_CLK_PWRSAVE;
else
reg &= ~CORE_CLK_PWRSAVE;
- writel_relaxed(reg, host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(reg, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -673,13 +834,18 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
u32 calib_done;
int ret = 0;
int cdc_err = 0;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
pr_debug("%s: Enter %s\n", mmc_hostname(host->mmc), __func__);
/* Write 0 to CDC_T4_DLY_SEL field in VENDOR_SPEC_DDR200_CFG */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DDR_200_CFG)
& ~CORE_CDC_T4_DLY_SEL),
- host->ioaddr + CORE_DDR_200_CFG);
+ host->ioaddr + msm_host_offset->CORE_DDR_200_CFG);
/* Write 0 to CDC_SWITCH_BYPASS_OFF field in CORE_CSR_CDC_GEN_CFG */
writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG)
@@ -692,9 +858,10 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
host->ioaddr + CORE_CSR_CDC_GEN_CFG);
/* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DDR_200_CFG)
& ~CORE_START_CDC_TRAFFIC),
- host->ioaddr + CORE_DDR_200_CFG);
+ host->ioaddr + msm_host_offset->CORE_DDR_200_CFG);
/*
* Perform CDC Register Initialization Sequence
@@ -765,9 +932,10 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
}
/* Write 1 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DDR_200_CFG)
| CORE_START_CDC_TRAFFIC),
- host->ioaddr + CORE_DDR_200_CFG);
+ host->ioaddr + msm_host_offset->CORE_DDR_200_CFG);
out:
pr_debug("%s: Exit %s, ret:%d\n", mmc_hostname(host->mmc),
__func__, ret);
@@ -778,6 +946,8 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
u32 dll_status, ddr_config;
int ret = 0;
@@ -788,27 +958,31 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
* bootloaders.
*/
if (msm_host->rclk_delay_fix) {
- writel_relaxed(DDR_CONFIG_2_POR_VAL,
- host->ioaddr + CORE_DDR_CONFIG_2);
+ writel_relaxed(DDR_CONFIG_2_POR_VAL, host->ioaddr +
+ msm_host_offset->CORE_DDR_CONFIG_2);
} else {
ddr_config = DDR_CONFIG_POR_VAL &
~DDR_CONFIG_PRG_RCLK_DLY_MASK;
ddr_config |= DDR_CONFIG_PRG_RCLK_DLY;
- writel_relaxed(ddr_config, host->ioaddr + CORE_DDR_CONFIG);
+ writel_relaxed(ddr_config, host->ioaddr +
+ msm_host_offset->CORE_DDR_CONFIG);
}
if (msm_host->enhanced_strobe && mmc_card_strobe(msm_host->mmc->card))
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
- | CORE_CMDIN_RCLK_EN),
- host->ioaddr + CORE_DDR_200_CFG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DDR_200_CFG)
+ | CORE_CMDIN_RCLK_EN), host->ioaddr +
+ msm_host_offset->CORE_DDR_200_CFG);
/* Write 1 to DDR_CAL_EN field in CORE_DLL_CONFIG_2 */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2)
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG_2)
| CORE_DDR_CAL_EN),
- host->ioaddr + CORE_DLL_CONFIG_2);
+ host->ioaddr + msm_host_offset->CORE_DLL_CONFIG_2);
/* Poll on DDR_DLL_LOCK bit in CORE_DLL_STATUS to be set */
- ret = readl_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
+ ret = readl_poll_timeout(host->ioaddr +
+ msm_host_offset->CORE_DLL_STATUS,
dll_status, (dll_status & CORE_DDR_DLL_LOCK), 10, 1000);
if (ret == -ETIMEDOUT) {
@@ -826,9 +1000,10 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
* turned on for host controllers using this DLL.
*/
if (!msm_host->use_14lpp_dll)
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3)
- | CORE_PWRSAVE_DLL),
- host->ioaddr + CORE_VENDOR_SPEC3);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3)
+ | CORE_PWRSAVE_DLL), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3);
mb();
out:
pr_debug("%s: Exit %s, ret:%d\n", mmc_hostname(host->mmc),
@@ -877,6 +1052,8 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
int ret = 0;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
pr_debug("%s: Enter %s\n", mmc_hostname(host->mmc), __func__);
@@ -894,9 +1071,10 @@ static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
goto out;
/* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_CMD_DAT_TRACK_SEL),
- host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
+ | CORE_CMD_DAT_TRACK_SEL), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
if (msm_host->use_cdclp533)
/* Calibrate CDCLP533 DLL HW */
@@ -2321,12 +2499,17 @@ void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x\n",
mmc_hostname(host->mmc),
- readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS),
- readl_relaxed(msm_host->core_mem + CORE_PWRCTL_MASK),
- readl_relaxed(msm_host->core_mem + CORE_PWRCTL_CTL));
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_STATUS),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_MASK),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_CTL));
}
static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
@@ -2334,6 +2517,8 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
struct sdhci_host *host = (struct sdhci_host *)data;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
u8 irq_status = 0;
u8 irq_ack = 0;
int ret = 0;
@@ -2341,12 +2526,16 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
unsigned long flags;
int retry = 10;
- irq_status = readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
+ irq_status = sdhci_msm_readb_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_STATUS);
+
pr_debug("%s: Received IRQ(%d), status=0x%x\n",
mmc_hostname(msm_host->mmc), irq, irq_status);
/* Clear the interrupt */
- writeb_relaxed(irq_status, (msm_host->core_mem + CORE_PWRCTL_CLEAR));
+ sdhci_msm_writeb_relaxed(irq_status, host,
+ msm_host_offset->CORE_PWRCTL_CLEAR);
+
/*
* SDHC has core_mem and hc_mem device memory and these memory
* addresses do not fall within 1KB region. Hence, any update to
@@ -2361,16 +2550,16 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
* sure status register is cleared. Otherwise, this will result in
* a spurious power IRQ resulting in system instability.
*/
- while (irq_status &
- readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS)) {
+ while (irq_status & sdhci_msm_readb_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_STATUS)) {
if (retry == 0) {
pr_err("%s: Timedout clearing (0x%x) pwrctl status register\n",
mmc_hostname(host->mmc), irq_status);
sdhci_msm_dump_pwr_ctrl_regs(host);
BUG_ON(1);
}
- writeb_relaxed(irq_status,
- (msm_host->core_mem + CORE_PWRCTL_CLEAR));
+ sdhci_msm_writeb_relaxed(irq_status, host,
+ msm_host_offset->CORE_PWRCTL_CLEAR);
retry--;
udelay(10);
}
@@ -2432,7 +2621,8 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
}
/* ACK status to the core */
- writeb_relaxed(irq_ack, (msm_host->core_mem + CORE_PWRCTL_CTL));
+ sdhci_msm_writeb_relaxed(irq_ack, host,
+ msm_host_offset->CORE_PWRCTL_CTL);
/*
* SDHC has core_mem and hc_mem device memory and these memory
* addresses do not fall within 1KB region. Hence, any update to
@@ -2442,14 +2632,16 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
mb();
if ((io_level & REQ_IO_HIGH) && (msm_host->caps_0 & CORE_3_0V_SUPPORT))
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
- ~CORE_IO_PAD_PWR_SWITCH),
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) &
+ ~CORE_IO_PAD_PWR_SWITCH), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
else if ((io_level & REQ_IO_LOW) ||
(msm_host->caps_0 & CORE_1_8V_SUPPORT))
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
- CORE_IO_PAD_PWR_SWITCH),
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) |
+ CORE_IO_PAD_PWR_SWITCH), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
mb();
pr_debug("%s: Handled IRQ(%d), ret=%d, ack=0x%x\n",
@@ -2534,6 +2726,8 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
unsigned long flags;
bool done = false;
u32 io_sig_sts;
@@ -2542,7 +2736,9 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
mmc_hostname(host->mmc), __func__, req_type,
msm_host->curr_pwr_state, msm_host->curr_io_level);
- io_sig_sts = readl_relaxed(msm_host->core_mem + CORE_GENERICS);
+ io_sig_sts = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_GENERICS);
+
/*
* The IRQ for request type IO High/Low will be generated when -
* 1. SWITCHABLE_SIGNALLING_VOL is enabled in HW.
@@ -2589,16 +2785,23 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
static void sdhci_msm_toggle_cdr(struct sdhci_host *host, bool enable)
{
- u32 config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
+ u32 config = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
if (enable) {
config |= CORE_CDR_EN;
config &= ~CORE_CDR_EXT_EN;
- writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
} else {
config &= ~CORE_CDR_EN;
config |= CORE_CDR_EXT_EN;
- writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed(config, host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
}
}
@@ -2809,6 +3012,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
int rc;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
struct mmc_card *card = host->mmc->card;
struct mmc_ios curr_ios = host->mmc->ios;
u32 sup_clock, ddr_clock, dll_lock;
@@ -2819,8 +3024,10 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
* disable pwrsave to ensure clock is not auto-gated until
* the rate is >400KHz (initialization complete).
*/
- writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
- ~CORE_CLK_PWRSAVE, host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) &
+ ~CORE_CLK_PWRSAVE, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
sdhci_msm_prepare_clocks(host, false);
host->clock = clock;
goto out;
@@ -2830,21 +3037,23 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
if (rc)
goto out;
- curr_pwrsave = !!(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
- CORE_CLK_PWRSAVE);
+ curr_pwrsave = !!(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) & CORE_CLK_PWRSAVE);
if ((clock > 400000) &&
!curr_pwrsave && card && mmc_host_may_gate_card(card))
- writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- | CORE_CLK_PWRSAVE,
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
+ | CORE_CLK_PWRSAVE, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
/*
* Disable pwrsave for a newly added card if doesn't allow clock
* gating.
*/
else if (curr_pwrsave && card && !mmc_host_may_gate_card(card))
- writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_CLK_PWRSAVE,
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
+ & ~CORE_CLK_PWRSAVE, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
sup_clock = sdhci_msm_get_sup_clk_rate(host, clock);
if ((curr_ios.timing == MMC_TIMING_UHS_DDR50) ||
@@ -2880,10 +3089,11 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
*/
if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
/* Select the divided clock (free running MCLK/2) */
- writel_relaxed(((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
- & ~CORE_HC_MCLK_SEL_MASK)
- | CORE_HC_MCLK_SEL_HS400),
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed(((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
+ & ~CORE_HC_MCLK_SEL_MASK)
+ | CORE_HC_MCLK_SEL_HS400), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
/*
* Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
* register
@@ -2897,10 +3107,10 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
* field in VENDOR_SPEC_FUNC
*/
writel_relaxed((readl_relaxed(host->ioaddr + \
- CORE_VENDOR_SPEC)
+ msm_host_offset->CORE_VENDOR_SPEC)
| CORE_HC_SELECT_IN_HS400
- | CORE_HC_SELECT_IN_EN),
- host->ioaddr + CORE_VENDOR_SPEC);
+ | CORE_HC_SELECT_IN_EN), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
}
if (!host->mmc->ios.old_rate && !msm_host->use_cdclp533) {
/*
@@ -2908,7 +3118,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
* CORE_DLL_STATUS to be set. This should get set
* with in 15 us at 200 MHz.
*/
- rc = readl_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
+ rc = readl_poll_timeout(host->ioaddr +
+ msm_host_offset->CORE_DLL_STATUS,
dll_lock, (dll_lock & (CORE_DLL_LOCK |
CORE_DDR_DLL_LOCK)), 10, 1000);
if (rc == -ETIMEDOUT)
@@ -2920,14 +3131,16 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
if (!msm_host->use_cdclp533)
/* set CORE_PWRSAVE_DLL bit in CORE_VENDOR_SPEC3 */
writel_relaxed((readl_relaxed(host->ioaddr +
- CORE_VENDOR_SPEC3) & ~CORE_PWRSAVE_DLL),
- host->ioaddr + CORE_VENDOR_SPEC3);
+ msm_host_offset->CORE_VENDOR_SPEC3)
+ & ~CORE_PWRSAVE_DLL), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3);
/* Select the default clock (free running MCLK) */
- writel_relaxed(((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ writel_relaxed(((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
& ~CORE_HC_MCLK_SEL_MASK)
- | CORE_HC_MCLK_SEL_DFLT),
- host->ioaddr + CORE_VENDOR_SPEC);
+ | CORE_HC_MCLK_SEL_DFLT), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
/*
* Disable HC_SELECT_IN to be able to use the UHS mode select
@@ -2937,10 +3150,11 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
* Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
* in VENDOR_SPEC_FUNC
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC)
& ~CORE_HC_SELECT_IN_EN
- & ~CORE_HC_SELECT_IN_MASK),
- host->ioaddr + CORE_VENDOR_SPEC);
+ & ~CORE_HC_SELECT_IN_MASK), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
}
mb();
@@ -2971,6 +3185,8 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
u16 ctrl_2;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -3006,14 +3222,16 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
*
* Write 1 to DLL_RST bit of DLL_CONFIG register
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_RST),
- host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
+ | CORE_DLL_RST), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
- | CORE_DLL_PDN),
- host->ioaddr + CORE_DLL_CONFIG);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG)
+ | CORE_DLL_PDN), host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG);
mb();
/*
@@ -3033,12 +3251,15 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
#define DRV_NAME "cmdq-host"
static void sdhci_msm_cmdq_dump_debug_ram(struct sdhci_host *host)
{
+ int i = 0;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
- int i = 0;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
struct cmdq_host *cq_host = host->cq_host;
- u32 version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
+ u32 version = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_VERSION);
u16 minor = version & CORE_VERSION_TARGET_MASK;
/* registers offset changed starting from 4.2.0 */
int offset = minor >= SDHCI_MSM_VER_420 ? 0 : 0x48;
@@ -3060,6 +3281,8 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
int tbsel, tbsel2;
int i, index = 0;
u32 test_bus_val = 0;
@@ -3071,19 +3294,29 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
sdhci_msm_cmdq_dump_debug_ram(host);
pr_info("Data cnt: 0x%08x | Fifo cnt: 0x%08x | Int sts: 0x%08x\n",
- readl_relaxed(msm_host->core_mem + CORE_MCI_DATA_CNT),
- readl_relaxed(msm_host->core_mem + CORE_MCI_FIFO_CNT),
- readl_relaxed(msm_host->core_mem + CORE_MCI_STATUS));
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_DATA_CNT),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_FIFO_CNT),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_STATUS));
pr_info("DLL cfg: 0x%08x | DLL sts: 0x%08x | SDCC ver: 0x%08x\n",
- readl_relaxed(host->ioaddr + CORE_DLL_CONFIG),
- readl_relaxed(host->ioaddr + CORE_DLL_STATUS),
- readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION));
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_CONFIG),
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_DLL_STATUS),
+ sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_VERSION));
pr_info("Vndr func: 0x%08x | Vndr adma err : addr0: 0x%08x addr1: 0x%08x\n",
- readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC),
- readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_ADMA_ERR_ADDR0),
- readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_ADMA_ERR_ADDR1));
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC),
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR0),
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_ADMA_ERR_ADDR1));
pr_info("Vndr func2: 0x%08x\n",
- readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2));
+ readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2));
/*
* tbsel indicates [2:0] bits and tbsel2 indicates [7:4] bits
@@ -3098,12 +3331,13 @@ void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
for (tbsel = 0; tbsel < 8; tbsel++) {
if (index >= MAX_TEST_BUS)
break;
- test_bus_val = (tbsel2 << CORE_TESTBUS_SEL2_BIT) |
- tbsel | CORE_TESTBUS_ENA;
- writel_relaxed(test_bus_val,
- msm_host->core_mem + CORE_TESTBUS_CONFIG);
- debug_reg[index++] = readl_relaxed(msm_host->core_mem +
- CORE_SDCC_DEBUG_REG);
+ test_bus_val =
+ (tbsel2 << msm_host_offset->CORE_TESTBUS_SEL2_BIT) |
+ tbsel | msm_host_offset->CORE_TESTBUS_ENA;
+ sdhci_msm_writel_relaxed(test_bus_val, host,
+ msm_host_offset->CORE_TESTBUS_CONFIG);
+ debug_reg[index++] = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_SDCC_DEBUG_REG);
}
}
for (i = 0; i < MAX_TEST_BUS; i = i + 4)
@@ -3140,6 +3374,8 @@ static void sdhci_msm_enhanced_strobe_mask(struct sdhci_host *host, bool set)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
if (!msm_host->enhanced_strobe ||
!mmc_card_strobe(msm_host->mmc->card)) {
@@ -3149,13 +3385,15 @@ static void sdhci_msm_enhanced_strobe_mask(struct sdhci_host *host, bool set)
}
if (set) {
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3)
- | CORE_CMDEN_HS400_INPUT_MASK_CNT),
- host->ioaddr + CORE_VENDOR_SPEC3);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3)
+ | CORE_CMDEN_HS400_INPUT_MASK_CNT),
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC3);
} else {
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3)
- & ~CORE_CMDEN_HS400_INPUT_MASK_CNT),
- host->ioaddr + CORE_VENDOR_SPEC3);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC3)
+ & ~CORE_CMDEN_HS400_INPUT_MASK_CNT),
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC3);
}
}
@@ -3163,15 +3401,19 @@ static void sdhci_msm_clear_set_dumpregs(struct sdhci_host *host, bool set)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
if (set) {
- writel_relaxed(CORE_TESTBUS_ENA,
- msm_host->core_mem + CORE_TESTBUS_CONFIG);
+ sdhci_msm_writel_relaxed(msm_host_offset->CORE_TESTBUS_ENA,
+ host, msm_host_offset->CORE_TESTBUS_CONFIG);
} else {
u32 value;
- value = readl_relaxed(msm_host->core_mem + CORE_TESTBUS_CONFIG);
- value &= ~CORE_TESTBUS_ENA;
- writel_relaxed(value, msm_host->core_mem + CORE_TESTBUS_CONFIG);
+ value = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_TESTBUS_CONFIG);
+ value &= ~(msm_host_offset->CORE_TESTBUS_ENA);
+ sdhci_msm_writel_relaxed(value, host,
+ msm_host_offset->CORE_TESTBUS_CONFIG);
}
}
@@ -3205,15 +3447,20 @@ void sdhci_msm_reset_workaround(struct sdhci_host *host, u32 enable)
{
u32 vendor_func2;
unsigned long timeout;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
- vendor_func2 = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2);
+ vendor_func2 = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
if (enable) {
writel_relaxed(vendor_func2 | HC_SW_RST_REQ, host->ioaddr +
- CORE_VENDOR_SPEC_FUNC2);
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
timeout = 10000;
- while (readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2) &
- HC_SW_RST_REQ) {
+ while (readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2) & HC_SW_RST_REQ) {
if (timeout == 0) {
pr_info("%s: Applying wait idle disable workaround\n",
mmc_hostname(host->mmc));
@@ -3225,10 +3472,10 @@ void sdhci_msm_reset_workaround(struct sdhci_host *host, u32 enable)
* AXI bus.
*/
vendor_func2 = readl_relaxed(host->ioaddr +
- CORE_VENDOR_SPEC_FUNC2);
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
writel_relaxed(vendor_func2 |
- HC_SW_RST_WAIT_IDLE_DIS,
- host->ioaddr + CORE_VENDOR_SPEC_FUNC2);
+ HC_SW_RST_WAIT_IDLE_DIS, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
host->reset_wa_t = ktime_get();
return;
}
@@ -3239,7 +3486,7 @@ void sdhci_msm_reset_workaround(struct sdhci_host *host, u32 enable)
mmc_hostname(host->mmc));
} else {
writel_relaxed(vendor_func2 & ~HC_SW_RST_WAIT_IDLE_DIS,
- host->ioaddr + CORE_VENDOR_SPEC_FUNC2);
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
}
}
@@ -3755,8 +4002,11 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
u16 minor;
u8 major;
u32 val;
+ const struct sdhci_msm_offset *msm_host_offset =
+ msm_host->offset;
- version = readl_relaxed(msm_host->core_mem + CORE_MCI_VERSION);
+ version = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_MCI_VERSION);
major = (version & CORE_VERSION_MAJOR_MASK) >>
CORE_VERSION_MAJOR_SHIFT;
minor = version & CORE_VERSION_TARGET_MASK;
@@ -3789,9 +4039,10 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
*/
if (major == 1 && (minor == 0x2e || minor == 0x3e)) {
host->quirks2 |= SDHCI_QUIRK2_USE_RESET_WORKAROUND;
- val = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2);
+ val = readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
writel_relaxed((val | CORE_ONE_MID_EN),
- host->ioaddr + CORE_VENDOR_SPEC_FUNC2);
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC_FUNC2);
}
/*
* SDCC 5 controller with major version 1, minor version 0x34 and later
@@ -3825,9 +4076,9 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
/* Fake 3.0V support for SDIO devices which requires such voltage */
if (msm_host->pdata->core_3_0v_support) {
caps |= CORE_3_0V_SUPPORT;
- writel_relaxed(
- (readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES) |
- caps), host->ioaddr + CORE_VENDOR_SPEC_CAPABILITIES0);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ SDHCI_CAPABILITIES) | caps), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_CAPABILITIES0);
}
if ((major == 1) && (minor >= 0x49))
@@ -3839,7 +4090,8 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
if (!msm_host->pdata->largeaddressbus)
caps &= ~CORE_SYS_BUS_SUPPORT_64_BIT;
- writel_relaxed(caps, host->ioaddr + CORE_VENDOR_SPEC_CAPABILITIES0);
+ writel_relaxed(caps, host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC_CAPABILITIES0);
/* keep track of the value in SDHCI_CAPABILITIES */
msm_host->caps_0 = caps;
}
@@ -3892,6 +4144,7 @@ static bool sdhci_msm_is_bootdevice(struct device *dev)
static int sdhci_msm_probe(struct platform_device *pdev)
{
+ const struct sdhci_msm_offset *msm_host_offset;
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_msm_host *msm_host;
@@ -3911,6 +4164,14 @@ static int sdhci_msm_probe(struct platform_device *pdev)
goto out;
}
+ if (of_find_compatible_node(NULL, NULL, "qcom,sdhci-msm-v5")) {
+ msm_host->mci_removed = true;
+ msm_host->offset = &sdhci_msm_offset_mci_removed;
+ } else {
+ msm_host->mci_removed = false;
+ msm_host->offset = &sdhci_msm_offset_mci_present;
+ }
+ msm_host_offset = msm_host->offset;
msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops;
host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0);
if (IS_ERR(host)) {
@@ -4086,17 +4347,19 @@ static int sdhci_msm_probe(struct platform_device *pdev)
/* Reset the core and Enable SDHC mode */
core_memres = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "core_mem");
- if (!core_memres) {
- dev_err(&pdev->dev, "Failed to get iomem resource\n");
- goto vreg_deinit;
- }
- msm_host->core_mem = devm_ioremap(&pdev->dev, core_memres->start,
- resource_size(core_memres));
+ if (!msm_host->mci_removed) {
+ if (!core_memres) {
+ dev_err(&pdev->dev, "Failed to get iomem resource\n");
+ goto vreg_deinit;
+ }
+ msm_host->core_mem = devm_ioremap(&pdev->dev,
+ core_memres->start, resource_size(core_memres));
- if (!msm_host->core_mem) {
- dev_err(&pdev->dev, "Failed to remap registers\n");
- ret = -ENOMEM;
- goto vreg_deinit;
+ if (!msm_host->core_mem) {
+ dev_err(&pdev->dev, "Failed to remap registers\n");
+ ret = -ENOMEM;
+ goto vreg_deinit;
+ }
}
tlmm_memres = platform_get_resource_byname(pdev,
@@ -4119,24 +4382,27 @@ static int sdhci_msm_probe(struct platform_device *pdev)
* Reset the vendor spec register to power on reset state.
*/
writel_relaxed(CORE_VENDOR_SPEC_POR_VAL,
- host->ioaddr + CORE_VENDOR_SPEC);
-
- /* Set HC_MODE_EN bit in HC_MODE register */
- writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+ host->ioaddr + msm_host_offset->CORE_VENDOR_SPEC);
- /* Set FF_CLK_SW_RST_DIS bit in HC_MODE register */
- writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_HC_MODE) |
- FF_CLK_SW_RST_DIS, msm_host->core_mem + CORE_HC_MODE);
+ if (!msm_host->mci_removed) {
+ /* Set HC_MODE_EN bit in HC_MODE register */
+ writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+ /* Set FF_CLK_SW_RST_DIS bit in HC_MODE register */
+ writel_relaxed(readl_relaxed(msm_host->core_mem +
+ CORE_HC_MODE) | FF_CLK_SW_RST_DIS,
+ msm_host->core_mem + CORE_HC_MODE);
+ }
sdhci_set_default_hw_caps(msm_host, host);
/*
* Set the PAD_PWR_SWTICH_EN bit so that the PAD_PWR_SWITCH bit can
* be used as required later on.
*/
- writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
- CORE_IO_PAD_PWR_SWITCH_EN),
- host->ioaddr + CORE_VENDOR_SPEC);
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC) |
+ CORE_IO_PAD_PWR_SWITCH_EN), host->ioaddr +
+ msm_host_offset->CORE_VENDOR_SPEC);
/*
* CORE_SW_RST above may trigger power irq if previous status of PWRCTL
* was either BUS_ON or IO_HIGH_V. So before we enable the power irq
@@ -4144,14 +4410,19 @@ static int sdhci_msm_probe(struct platform_device *pdev)
* ensure that any pending power irq interrupt status is acknowledged
* otherwise power irq interrupt handler would be fired prematurely.
*/
- irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
- writel_relaxed(irq_status, (msm_host->core_mem + CORE_PWRCTL_CLEAR));
- irq_ctl = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_CTL);
+ irq_status = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_STATUS);
+ sdhci_msm_writel_relaxed(irq_status, host,
+ msm_host_offset->CORE_PWRCTL_CLEAR);
+ irq_ctl = sdhci_msm_readl_relaxed(host,
+ msm_host_offset->CORE_PWRCTL_CTL);
+
if (irq_status & (CORE_PWRCTL_BUS_ON | CORE_PWRCTL_BUS_OFF))
irq_ctl |= CORE_PWRCTL_BUS_SUCCESS;
if (irq_status & (CORE_PWRCTL_IO_HIGH | CORE_PWRCTL_IO_LOW))
irq_ctl |= CORE_PWRCTL_IO_SUCCESS;
- writel_relaxed(irq_ctl, (msm_host->core_mem + CORE_PWRCTL_CTL));
+ sdhci_msm_writel_relaxed(irq_ctl, host,
+ msm_host_offset->CORE_PWRCTL_CTL);
/*
* Ensure that above writes are propogated before interrupt enablement
@@ -4215,7 +4486,8 @@ static int sdhci_msm_probe(struct platform_device *pdev)
}
/* Enable pwr irq interrupts */
- writel_relaxed(INT_MASK, (msm_host->core_mem + CORE_PWRCTL_MASK));
+ sdhci_msm_writel_relaxed(INT_MASK, host,
+ msm_host_offset->CORE_PWRCTL_MASK);
#ifdef CONFIG_MMC_CLKGATE
/* Set clock gating delay to be used when CONFIG_MMC_CLKGATE is set */
@@ -4653,6 +4925,7 @@ static const struct dev_pm_ops sdhci_msm_pmops = {
#endif
static const struct of_device_id sdhci_msm_dt_match[] = {
{.compatible = "qcom,sdhci-msm"},
+ {.compatible = "qcom,sdhci-msm-v5"},
{},
};
MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index e47a5083e8a6..6f96ea97bddc 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -214,6 +214,8 @@ struct sdhci_msm_host {
bool pm_qos_group_enable;
struct sdhci_msm_pm_qos_irq pm_qos_irq;
bool tuning_in_progress;
+ bool mci_removed;
+ const struct sdhci_msm_offset *offset;
};
extern char *saved_command_line;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index 249de808ec5c..f5afb4b0141c 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -523,10 +523,9 @@ ssize_t ipa_read(struct file *filp, char __user *buf, size_t count,
start = buf;
while (1) {
- prepare_to_wait(&ipa_ctx->msg_waitq, &wait, TASK_INTERRUPTIBLE);
-
mutex_lock(&ipa_ctx->msg_lock);
locked = 1;
+ prepare_to_wait(&ipa_ctx->msg_waitq, &wait, TASK_INTERRUPTIBLE);
if (!list_empty(&ipa_ctx->msg_list)) {
msg = list_first_entry(&ipa_ctx->msg_list,
struct ipa_push_msg, link);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 11da023c9d6a..93fa1492cfd5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -326,7 +326,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
int needed_len;
int mem_size;
- IPADBG_LOW("processing type %d hdr_hdl %d\n",
+ IPADBG_LOW("Add processing type %d hdr_hdl %d\n",
proc_ctx->type, proc_ctx->hdr_hdl);
if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) {
@@ -335,10 +335,17 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
}
hdr_entry = ipa3_id_find(proc_ctx->hdr_hdl);
- if (!hdr_entry || (hdr_entry->cookie != IPA_COOKIE)) {
+ if (!hdr_entry) {
IPAERR("hdr_hdl is invalid\n");
return -EINVAL;
}
+ if (hdr_entry->cookie != IPA_COOKIE) {
+ IPAERR("Invalid header cookie %u\n", hdr_entry->cookie);
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ IPADBG("Associated header is name=%s is_hdr_proc_ctx=%d\n",
+ hdr_entry->name, hdr_entry->is_hdr_proc_ctx);
entry = kmem_cache_zalloc(ipa3_ctx->hdr_proc_ctx_cache, GFP_KERNEL);
if (!entry) {
@@ -403,7 +410,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
entry->offset_entry = offset;
list_add(&entry->link, &htbl->head_proc_ctx_entry_list);
htbl->proc_ctx_cnt++;
- IPADBG_LOW("add proc ctx of sz=%d cnt=%d ofst=%d\n", needed_len,
+ IPADBG("add proc ctx of sz=%d cnt=%d ofst=%d\n", needed_len,
htbl->proc_ctx_cnt, offset->offset);
id = ipa3_id_alloc(entry);
@@ -520,12 +527,12 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr)
list_add(&entry->link, &htbl->head_hdr_entry_list);
htbl->hdr_cnt++;
if (entry->is_hdr_proc_ctx)
- IPADBG_LOW("add hdr of sz=%d hdr_cnt=%d phys_base=%pa\n",
+ IPADBG("add hdr of sz=%d hdr_cnt=%d phys_base=%pa\n",
hdr->hdr_len,
htbl->hdr_cnt,
&entry->phys_base);
else
- IPADBG_LOW("add hdr of sz=%d hdr_cnt=%d ofst=%d\n",
+ IPADBG("add hdr of sz=%d hdr_cnt=%d ofst=%d\n",
hdr->hdr_len,
htbl->hdr_cnt,
entry->offset_entry->offset);
@@ -580,7 +587,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, bool release_hdr)
return -EINVAL;
}
- IPADBG("del ctx proc cnt=%d ofst=%d\n",
+ IPADBG("del proc ctx cnt=%d ofst=%d\n",
htbl->proc_ctx_cnt, entry->offset_entry->offset);
if (--entry->ref_cnt) {
@@ -624,11 +631,12 @@ int __ipa3_del_hdr(u32 hdr_hdl)
}
if (entry->is_hdr_proc_ctx)
- IPADBG("del hdr of sz=%d hdr_cnt=%d phys_base=%pa\n",
+ IPADBG("del hdr of len=%d hdr_cnt=%d phys_base=%pa\n",
entry->hdr_len, htbl->hdr_cnt, &entry->phys_base);
else
- IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
- htbl->hdr_cnt, entry->offset_entry->offset);
+ IPADBG("del hdr of len=%d hdr_cnt=%d ofst=%d\n",
+ entry->hdr_len, htbl->hdr_cnt,
+ entry->offset_entry->offset);
if (--entry->ref_cnt) {
IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index 22756c1fb168..b9f57552533e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -528,12 +528,12 @@ ssize_t ipa3_read(struct file *filp, char __user *buf, size_t count,
start = buf;
while (1) {
+ mutex_lock(&ipa3_ctx->msg_lock);
+ locked = 1;
prepare_to_wait(&ipa3_ctx->msg_waitq,
&wait,
TASK_INTERRUPTIBLE);
- mutex_lock(&ipa3_ctx->msg_lock);
- locked = 1;
if (!list_empty(&ipa3_ctx->msg_list)) {
msg = list_first_entry(&ipa3_ctx->msg_list,
struct ipa3_push_msg, link);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 6c7bf500e760..ac7e57f10062 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -1210,8 +1210,9 @@ int __ipa3_del_rt_rule(u32 rule_hdl)
__ipa3_release_hdr_proc_ctx(entry->proc_ctx->id);
list_del(&entry->link);
entry->tbl->rule_cnt--;
- IPADBG("del rt rule tbl_idx=%d rule_cnt=%d rule_id=%d\n",
- entry->tbl->idx, entry->tbl->rule_cnt, entry->rule_id);
+ IPADBG("del rt rule tbl_idx=%d rule_cnt=%d rule_id=%d\n ref_cnt=%u",
+ entry->tbl->idx, entry->tbl->rule_cnt,
+ entry->rule_id, entry->tbl->ref_cnt);
idr_remove(&entry->tbl->rule_ids, entry->rule_id);
if (entry->tbl->rule_cnt == 0 && entry->tbl->ref_cnt == 0) {
if (__ipa_del_rt_tbl(entry->tbl))
@@ -1488,6 +1489,8 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl)
entry->ref_cnt--;
if (entry->ref_cnt == 0 && entry->rule_cnt == 0) {
+ IPADBG("zero ref_cnt, delete rt tbl (idx=%u)\n",
+ entry->idx);
if (__ipa_del_rt_tbl(entry))
IPAERR("fail to del RT tbl\n");
/* commit for put */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index bcd2cb3bfd7a..2bc179d5a33c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -1222,9 +1222,9 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
if (!base ||
!hdr_len ||
- (!phys_base && !hdr_base_addr) ||
- !hdr_base_addr ||
- ((is_hdr_proc_ctx == false) && !offset_entry)) {
+ (is_hdr_proc_ctx && !phys_base) ||
+ (!is_hdr_proc_ctx && !offset_entry) ||
+ (!is_hdr_proc_ctx && !hdr_base_addr)) {
IPAHAL_ERR(
"invalid input: hdr_len:%u phys_base:%pad hdr_base_addr:%u is_hdr_proc_ctx:%d offset_entry:%pK\n"
, hdr_len, &phys_base, hdr_base_addr
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 0619b314b7de..ea2694c8c58d 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -249,6 +249,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(flash_current_max),
POWER_SUPPLY_ATTR(update_now),
POWER_SUPPLY_ATTR(esr_count),
+ POWER_SUPPLY_ATTR(buck_freq),
POWER_SUPPLY_ATTR(safety_timer_enabled),
POWER_SUPPLY_ATTR(charge_done),
POWER_SUPPLY_ATTR(flash_active),
@@ -273,6 +274,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(charger_temp),
POWER_SUPPLY_ATTR(charger_temp_max),
POWER_SUPPLY_ATTR(parallel_disable),
+ POWER_SUPPLY_ATTR(parallel_percent),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 8aaeb095db3c..954a03f042f7 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -216,12 +217,15 @@ struct smb_dt_props {
u32 step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
struct device_node *revid_dev_node;
+ int float_option;
+ bool hvdcp_disable;
};
struct smb2 {
- struct smb_charger chg;
- struct smb_dt_props dt;
- bool bad_part;
+ struct smb_charger chg;
+ struct dentry *dfs_root;
+ struct smb_dt_props dt;
+ bool bad_part;
};
static int __debug_mask;
@@ -320,6 +324,15 @@ static int smb2_parse_dt(struct smb2 *chip)
}
}
+ of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option);
+ if (chip->dt.float_option < 0 || chip->dt.float_option > 4) {
+ pr_err("qcom,float-option is out of range [0, 4]\n");
+ return -EINVAL;
+ }
+
+ chip->dt.hvdcp_disable = of_property_read_bool(node,
+ "qcom,hvdcp-disable");
+
return 0;
}
@@ -333,6 +346,7 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_TYPEC_MODE,
@@ -372,6 +386,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = smblib_get_prop_usb_voltage_now(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+ rc = smblib_get_prop_pd_current_max(chg, val);
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_get_prop_usb_current_max(chg, val);
break;
@@ -409,6 +426,12 @@ static int smb2_usb_get_prop(struct power_supply *psy,
val->intval = get_client_vote(chg->pl_disable_votable,
USER_VOTER);
break;
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_get_prop_pd_in_hard_reset(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
+ val->intval = chg->system_suspend_supported;
+ break;
default:
pr_err("get prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -436,17 +459,12 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_set_prop_usb_voltage_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+ rc = smblib_set_prop_pd_current_max(chg, val);
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_prop_usb_current_max(chg, val);
break;
- case POWER_SUPPLY_PROP_TYPE:
- if (chg->pd_active && val->intval == POWER_SUPPLY_TYPE_USB_PD) {
- chg->usb_psy_desc.type = val->intval;
- } else {
- pr_err("set type %d not allowed\n", val->intval);
- rc = -EINVAL;
- }
- break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
rc = smblib_set_prop_typec_power_role(chg, val);
break;
@@ -456,6 +474,12 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
break;
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_set_prop_pd_in_hard_reset(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
+ chg->system_suspend_supported = val->intval;
+ break;
default:
pr_err("set prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -1022,6 +1046,14 @@ static int smb2_init_hw(struct smb2 *chip)
DEFAULT_VOTER, true, chip->dt.usb_icl_ua);
vote(chg->dc_icl_votable,
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
+ vote(chg->hvdcp_disable_votable, DEFAULT_VOTER,
+ chip->dt.hvdcp_disable, 0);
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER,
+ true, 0);
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
+ true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ true, 0);
/* Configure charge enable for software control; active high */
rc = smblib_masked_write(chg, CHGR_CFG2_REG,
@@ -1119,6 +1151,35 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ /* configure float charger options */
+ switch (chip->dt.float_option) {
+ case 1:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, 0);
+ break;
+ case 2:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
+ break;
+ case 3:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
+ break;
+ case 4:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
+ rc);
+ return rc;
+ }
+
return rc;
}
@@ -1438,9 +1499,74 @@ static int smb2_request_interrupts(struct smb2 *chip)
return rc;
}
-/*********
- * PROBE *
- *********/
+#if defined(CONFIG_DEBUG_FS)
+
+static int force_batt_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->batt_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
+ force_batt_psy_update_write, "0x%02llx\n");
+
+static int force_usb_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->usb_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
+ force_usb_psy_update_write, "0x%02llx\n");
+
+static int force_dc_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->dc_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
+ force_dc_psy_update_write, "0x%02llx\n");
+
+static void smb2_create_debugfs(struct smb2 *chip)
+{
+ struct dentry *file;
+
+ chip->dfs_root = debugfs_create_dir("charger", NULL);
+ if (IS_ERR_OR_NULL(chip->dfs_root)) {
+ pr_err("Couldn't create charger debugfs rc=%ld\n",
+ (long)chip->dfs_root);
+ return;
+ }
+
+ file = debugfs_create_file("force_batt_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_batt_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
+ (long)file);
+
+ file = debugfs_create_file("force_usb_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_usb_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
+ (long)file);
+
+ file = debugfs_create_file("force_dc_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_dc_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
+ (long)file);
+}
+
+#else
+
+static void smb2_create_debugfs(struct smb2 *chip)
+{}
+
+#endif
static int smb2_probe(struct platform_device *pdev)
{
@@ -1458,6 +1584,7 @@ static int smb2_probe(struct platform_device *pdev)
chg->param = v1_params;
chg->debug_mask = &__debug_mask;
chg->mode = PARALLEL_MASTER;
+ chg->name = "PMI";
chg->pl.master_percent = &__pl_master_percent;
chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
@@ -1552,6 +1679,8 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
+ smb2_create_debugfs(chip);
+
pr_info("QPNP SMB2 probed successfully\n");
return rc;
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index ce76260be6f6..c719773fae30 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -22,12 +22,18 @@
#include "storm-watch.h"
#include "pmic-voter.h"
+#define smblib_err(chg, fmt, ...) \
+ pr_err("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__) \
+
#define smblib_dbg(chg, reason, fmt, ...) \
do { \
if (*chg->debug_mask & (reason)) \
- dev_info(chg->dev, fmt, ##__VA_ARGS__); \
+ pr_info("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__); \
else \
- dev_dbg(chg->dev, fmt, ##__VA_ARGS__); \
+ pr_debug("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__); \
} while (0)
static bool is_secure(struct smb_charger *chg, int addr)
@@ -99,7 +105,7 @@ static int smblib_get_step_charging_adjustment(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -136,7 +142,7 @@ static void smblib_fcc_split_ua(struct smb_charger *chg, int total_fcc,
&chg->param.jeita_cc_comp,
&cc_reduction_ua);
if (rc < 0) {
- dev_err(chg->dev, "Could not get jeita comp, rc=%d\n",
+ smblib_err(chg, "Could not get jeita comp, rc=%d\n",
rc);
cc_reduction_ua = 0;
}
@@ -172,7 +178,7 @@ int smblib_get_charge_param(struct smb_charger *chg,
rc = smblib_read(chg, param->reg, &val_raw);
if (rc < 0) {
- dev_err(chg->dev, "%s: Couldn't read from 0x%04x rc=%d\n",
+ smblib_err(chg, "%s: Couldn't read from 0x%04x rc=%d\n",
param->name, param->reg, rc);
return rc;
}
@@ -194,7 +200,7 @@ int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend)
rc = smblib_read(chg, USBIN_CMD_IL_REG, &temp);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read USBIN_CMD_IL rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read USBIN_CMD_IL rc=%d\n", rc);
return rc;
}
*suspend = temp & USBIN_SUSPEND_BIT;
@@ -208,47 +214,97 @@ struct apsd_result {
const enum power_supply_type pst;
};
+enum {
+ UNKNOWN,
+ SDP,
+ CDP,
+ DCP,
+ OCP,
+ FLOAT,
+ HVDCP2,
+ HVDCP3,
+ MAX_TYPES
+};
+
static const struct apsd_result const smblib_apsd_results[] = {
- {"UNKNOWN", 0, POWER_SUPPLY_TYPE_UNKNOWN},
- {"SDP", SDP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB},
- {"CDP", CDP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_CDP},
- {"DCP", DCP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"OCP", OCP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"FLOAT", FLOAT_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"HVDCP2", DCP_CHARGER_BIT | QC_2P0_BIT, POWER_SUPPLY_TYPE_USB_HVDCP},
- {"HVDCP3", DCP_CHARGER_BIT | QC_3P0_BIT, POWER_SUPPLY_TYPE_USB_HVDCP_3},
+ [UNKNOWN] = {
+ .name = "UNKNOWN",
+ .bit = 0,
+ .pst = POWER_SUPPLY_TYPE_UNKNOWN
+ },
+ [SDP] = {
+ .name = "SDP",
+ .bit = SDP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB
+ },
+ [CDP] = {
+ .name = "CDP",
+ .bit = CDP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_CDP
+ },
+ [DCP] = {
+ .name = "DCP",
+ .bit = DCP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [OCP] = {
+ .name = "OCP",
+ .bit = OCP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [FLOAT] = {
+ .name = "FLOAT",
+ .bit = FLOAT_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [HVDCP2] = {
+ .name = "HVDCP2",
+ .bit = DCP_CHARGER_BIT | QC_2P0_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_HVDCP
+ },
+ [HVDCP3] = {
+ .name = "HVDCP3",
+ .bit = DCP_CHARGER_BIT | QC_3P0_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_HVDCP_3,
+ },
};
static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg)
{
int rc, i;
- u8 stat;
+ u8 apsd_stat, stat;
+ const struct apsd_result *result = &smblib_apsd_results[UNKNOWN];
- rc = smblib_read(chg, APSD_STATUS_REG, &stat);
+ rc = smblib_read(chg, APSD_STATUS_REG, &apsd_stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_STATUS rc=%d\n", rc);
- return &smblib_apsd_results[0];
+ smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
+ return result;
}
- smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
+ smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", apsd_stat);
- if (!(stat & APSD_DTC_STATUS_DONE_BIT))
- return &smblib_apsd_results[0];
+ if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT))
+ return result;
rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_RESULT_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read APSD_RESULT_STATUS rc=%d\n",
rc);
- return &smblib_apsd_results[0];
+ return result;
}
stat &= APSD_RESULT_STATUS_MASK;
for (i = 0; i < ARRAY_SIZE(smblib_apsd_results); i++) {
if (smblib_apsd_results[i].bit == stat)
- return &smblib_apsd_results[i];
+ result = &smblib_apsd_results[i];
+ }
+
+ if (apsd_stat & QC_CHARGER_BIT) {
+ /* since its a qc_charger, either return HVDCP3 or HVDCP2 */
+ if (result != &smblib_apsd_results[HVDCP3])
+ result = &smblib_apsd_results[HVDCP2];
}
- dev_err(chg->dev, "Couldn't find an APSD result for 0x%02x\n", stat);
- return &smblib_apsd_results[0];
+ return result;
}
@@ -268,7 +324,7 @@ int smblib_set_charge_param(struct smb_charger *chg,
return -EINVAL;
} else {
if (val_u > param->max_u || val_u < param->min_u) {
- dev_err(chg->dev, "%s: %d is out of range [%d, %d]\n",
+ smblib_err(chg, "%s: %d is out of range [%d, %d]\n",
param->name, val_u, param->min_u, param->max_u);
return -EINVAL;
}
@@ -278,7 +334,7 @@ int smblib_set_charge_param(struct smb_charger *chg,
rc = smblib_write(chg, param->reg, val_raw);
if (rc < 0) {
- dev_err(chg->dev, "%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
+ smblib_err(chg, "%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
param->name, val_raw, param->reg, rc);
return rc;
}
@@ -295,14 +351,14 @@ static int step_charge_soc_update(struct smb_charger *chg, int capacity)
rc = smblib_set_charge_param(chg, &chg->param.step_soc, capacity);
if (rc < 0) {
- dev_err(chg->dev, "Error in updating soc, rc=%d\n", rc);
+ smblib_err(chg, "Error in updating soc, rc=%d\n", rc);
return rc;
}
rc = smblib_write(chg, STEP_CHG_SOC_VBATT_V_UPDATE_REG,
STEP_CHG_SOC_VBATT_V_UPDATE_BIT);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't set STEP_CHG_SOC_VBATT_V_UPDATE_REG rc=%d\n",
rc);
return rc;
@@ -318,7 +374,7 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend)
rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
suspend ? USBIN_SUSPEND_BIT : 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
+ smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
@@ -331,7 +387,7 @@ int smblib_set_dc_suspend(struct smb_charger *chg, bool suspend)
rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_SUSPEND_BIT,
suspend ? DCIN_SUSPEND_BIT : 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't write %s to DCIN_SUSPEND_BIT rc=%d\n",
+ smblib_err(chg, "Couldn't write %s to DCIN_SUSPEND_BIT rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
@@ -359,14 +415,14 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
} else if (min_allowed_uv < MICRO_12V && max_allowed_uv <= MICRO_12V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_9V_TO_12V;
} else {
- dev_err(chg->dev, "invalid allowed voltage [%d, %d]\n",
+ smblib_err(chg, "invalid allowed voltage [%d, %d]\n",
min_allowed_uv, max_allowed_uv);
return -EINVAL;
}
rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG, allowed_voltage);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't write 0x%02x to USBIN_ADAPTER_ALLOW_CFG rc=%d\n",
+ smblib_err(chg, "Couldn't write 0x%02x to USBIN_ADAPTER_ALLOW_CFG rc=%d\n",
allowed_voltage, rc);
return rc;
}
@@ -378,49 +434,44 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
* HELPER FUNCTIONS *
********************/
-static int smblib_update_usb_type(struct smb_charger *chg)
+static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
{
- int rc = 0;
const struct apsd_result *apsd_result;
- /* if PD is active, APSD is disabled so won't have a valid result */
- if (chg->pd_active)
- return rc;
-
- apsd_result = smblib_get_apsd_result(chg);
- chg->usb_psy_desc.type = apsd_result->pst;
- return rc;
+ /*
+ * PD_INACTIVE_VOTER on hvdcp_disable_votable indicates whether
+ * apsd rerun was tried earlier
+ */
+ if (get_client_vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER)) {
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER, false, 0);
+ /* ensure hvdcp is enabled */
+ if (!get_effective_result(chg->hvdcp_disable_votable)) {
+ apsd_result = smblib_get_apsd_result(chg);
+ if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ /* rerun APSD */
+ smblib_dbg(chg, PR_MISC, "rerun APSD\n");
+ smblib_masked_write(chg, CMD_APSD_REG,
+ APSD_RERUN_BIT,
+ APSD_RERUN_BIT);
+ }
+ }
+ }
+ return 0;
}
-static int smblib_detach_usb(struct smb_charger *chg)
+static int smblib_update_usb_type(struct smb_charger *chg)
{
- int rc;
-
- cancel_delayed_work_sync(&chg->hvdcp_detect_work);
- chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
-
- /* reconfigure allowed voltage for HVDCP */
- rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG,
- USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
- rc);
- return rc;
- }
-
- chg->voltage_min_uv = MICRO_5V;
- chg->voltage_max_uv = MICRO_5V;
+ int rc = 0;
+ const struct apsd_result *apsd_result;
- /* clear USB ICL vote for PD_VOTER */
- rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote for USB ICL rc=%d\n",
- rc);
- return rc;
+ /* if PD is active, APSD is disabled so won't have a valid result */
+ if (chg->pd_active) {
+ chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
+ return 0;
}
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, false, 0);
-
+ apsd_result = smblib_get_apsd_result(chg);
+ chg->usb_psy_desc.type = apsd_result->pst;
return rc;
}
@@ -452,7 +503,7 @@ static int smblib_register_notifier(struct smb_charger *chg)
chg->nb.notifier_call = smblib_notifier_call;
rc = power_supply_reg_notifier(&chg->nb);
if (rc < 0) {
- pr_err("Couldn't register psy notifier rc = %d\n", rc);
+ smblib_err(chg, "Couldn't register psy notifier rc = %d\n", rc);
return rc;
}
@@ -550,7 +601,7 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Could not set parallel fcc, rc=%d\n",
+ smblib_err(chg, "Could not set parallel fcc, rc=%d\n",
rc);
return rc;
}
@@ -560,7 +611,7 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
rc = smblib_set_charge_param(chg, &chg->param.fcc, master_ua);
if (rc < 0) {
- dev_err(chg->dev, "Error in setting fcc, rc=%d\n", rc);
+ smblib_err(chg, "Error in setting fcc, rc=%d\n", rc);
return rc;
}
@@ -582,8 +633,7 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
rc = smblib_set_charge_param(chg, &chg->param.fv, fv_uv);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't set floating voltage rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set floating voltage rc=%d\n", rc);
return rc;
}
@@ -592,7 +642,7 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't set float on parallel rc=%d\n", rc);
return rc;
}
@@ -601,41 +651,67 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
return 0;
}
-#define USBIN_25MA 25000
-#define USBIN_100MA 100000
+#define USBIN_25MA 25000
+#define USBIN_100MA 100000
+#define USBIN_150MA 150000
+#define USBIN_500MA 500000
+#define USBIN_900MA 900000
static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
int icl_ua, const char *client)
{
struct smb_charger *chg = data;
int rc = 0;
- bool suspend;
+ bool suspend = (icl_ua < USBIN_25MA);
+ u8 icl_options = 0;
- if (icl_ua < 0) {
- smblib_dbg(chg, PR_MISC, "No Voter hence suspending\n");
- icl_ua = 0;
- }
-
- suspend = (icl_ua < USBIN_25MA);
if (suspend)
- goto suspend;
+ goto out;
- if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
- rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USB51_MODE_BIT,
- (icl_ua > USBIN_100MA) ? USB51_MODE_BIT : 0);
- else
+ if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) {
rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
+ return rc;
+ }
+ goto out;
+ }
+
+ /* power source is SDP */
+ switch (icl_ua) {
+ case USBIN_100MA:
+ /* USB 2.0 100mA */
+ icl_options = 0;
+ break;
+ case USBIN_150MA:
+ /* USB 3.0 150mA */
+ icl_options = CFG_USB3P0_SEL_BIT;
+ break;
+ case USBIN_500MA:
+ /* USB 2.0 500mA */
+ icl_options = USB51_MODE_BIT;
+ break;
+ case USBIN_900MA:
+ /* USB 3.0 900mA */
+ icl_options = CFG_USB3P0_SEL_BIT | USB51_MODE_BIT;
+ break;
+ default:
+ smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua);
+ icl_options = 0;
+ break;
+ }
+
+out:
+ rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
+ CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't set USB input current limit rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc);
return rc;
}
-suspend:
rc = vote(chg->usb_suspend_votable, PD_VOTER, suspend, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s input rc=%d\n",
+ smblib_err(chg, "Couldn't %s input rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
}
@@ -650,8 +726,7 @@ static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua)
rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_cl_ua);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set otg current limit rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't set otg current limit rc=%d\n", rc);
return rc;
}
@@ -660,7 +735,7 @@ static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua)
ENG_SSUPPLY_CFG_SKIP_TH_V0P2_BIT,
otg_cl_ua > MICRO_250MA ? 1 : 0);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't write DC_ENG_SSUPPLY_CFG3_REG rc=%d\n", rc);
return rc;
}
@@ -686,7 +761,7 @@ static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
rc = smblib_set_charge_param(chg, &chg->param.dc_icl, icl_ua);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set DC input current limit rc=%d\n",
+ smblib_err(chg, "Couldn't set DC input current limit rc=%d\n",
rc);
return rc;
}
@@ -694,13 +769,25 @@ static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
suspend:
rc = vote(chg->dc_suspend_votable, USER_VOTER, suspend, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s DC rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
}
return rc;
}
+static int smblib_pd_disallowed_votable_indirect_callback(
+ struct votable *votable, void *data, int disallowed, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
+ !disallowed, 0);
+
+ return rc;
+}
+
static int smblib_awake_vote_callback(struct votable *votable, void *data,
int awake, const char *client)
{
@@ -732,7 +819,7 @@ static int smblib_pl_disable_vote_callback(struct votable *votable, void *data,
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't change slave suspend state rc=%d\n", rc);
return rc;
}
@@ -750,7 +837,7 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
CHARGING_ENABLE_CMD_BIT,
chg_disable ? 0 : CHARGING_ENABLE_CMD_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s charging rc=%d\n",
+ smblib_err(chg, "Couldn't %s charging rc=%d\n",
chg_disable ? "disable" : "enable", rc);
return rc;
}
@@ -768,6 +855,55 @@ static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
return 0;
}
+static int smblib_hvdcp_disable_vote_callback(struct votable *votable,
+ void *data,
+ int hvdcp_disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+ u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT
+ | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT | HVDCP_EN_BIT;
+
+ /*
+ * Disable the autonomous bit and auth bit for disabling hvdcp.
+ * This ensures only qc 2.0 detection runs but no vbus
+ * negotiation happens.
+ */
+ if (hvdcp_disable)
+ val = HVDCP_EN_BIT;
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_EN_BIT
+ | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT
+ | HVDCP_AUTH_ALG_EN_CFG_BIT,
+ val);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
+ hvdcp_disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int smblib_apsd_disable_vote_callback(struct votable *votable,
+ void *data,
+ int apsd_disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ AUTO_SRC_DETECT_BIT,
+ apsd_disable ? 0 : AUTO_SRC_DETECT_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't %s APSD rc=%d\n",
+ apsd_disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return 0;
+}
/*****************
* OTG REGULATOR *
*****************/
@@ -783,21 +919,21 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
ENG_BUCKBOOST_HALT1_8_MODE_BIT,
ENG_BUCKBOOST_HALT1_8_MODE_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
+ smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
rc);
return rc;
}
rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't enable OTG regulator rc=%d\n", rc);
+ smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc);
return rc;
}
msleep(OTG_SOFT_START_DELAY_MS);
rc = smblib_read(chg, OTG_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read OTG_STATUS_REG rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", rc);
return rc;
}
if (stat & BOOST_SOFTSTART_DONE_BIT)
@@ -813,7 +949,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
rc = smblib_write(chg, CMD_OTG_REG, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't disable OTG regulator rc=%d\n", rc);
+ smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc);
return rc;
}
@@ -822,7 +958,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
+ smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
rc);
return rc;
}
@@ -839,7 +975,7 @@ int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev)
rc = smblib_read(chg, CMD_OTG_REG, &cmd);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read CMD_OTG rc=%d", rc);
+ smblib_err(chg, "Couldn't read CMD_OTG rc=%d", rc);
return rc;
}
@@ -862,7 +998,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
*/
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
stat = stat & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
@@ -870,7 +1006,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
VCONN_EN_VALUE_BIT | stat);
if (rc < 0)
- dev_err(chg->dev, "Couldn't enable vconn setting rc=%d\n", rc);
+ smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
return rc;
}
@@ -883,7 +1019,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev)
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
VCONN_EN_VALUE_BIT, 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't disable vconn regulator rc=%d\n",
+ smblib_err(chg, "Couldn't disable vconn regulator rc=%d\n",
rc);
return rc;
@@ -897,7 +1033,7 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev)
rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &cmd);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
rc);
return rc;
}
@@ -925,8 +1061,7 @@ int smblib_get_prop_batt_present(struct smb_charger *chg,
rc = smblib_read(chg, BATIF_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATIF_INT_RT_STS rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read BATIF_INT_RT_STS rc=%d\n", rc);
return rc;
}
@@ -962,7 +1097,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_get_prop_usb_online(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get usb online property rc=%d\n",
+ smblib_err(chg, "Couldn't get usb online property rc=%d\n",
rc);
return rc;
}
@@ -970,7 +1105,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_get_prop_dc_online(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get dc online property rc=%d\n",
+ smblib_err(chg, "Couldn't get dc online property rc=%d\n",
rc);
return rc;
}
@@ -983,7 +1118,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1020,7 +1155,7 @@ int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1052,7 +1187,7 @@ int smblib_get_prop_batt_health(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
rc);
return rc;
}
@@ -1060,7 +1195,7 @@ int smblib_get_prop_batt_health(struct smb_charger *chg,
stat);
if (stat & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
- dev_err(chg->dev, "battery over-voltage\n");
+ smblib_err(chg, "battery over-voltage\n");
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
goto done;
}
@@ -1095,7 +1230,7 @@ int smblib_get_prop_input_current_limited(struct smb_charger *chg,
rc = smblib_read(chg, AICL_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read AICL_STATUS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc);
return rc;
}
val->intval = (stat & SOFT_ILIMIT_BIT) || chg->is_hdc;
@@ -1154,7 +1289,7 @@ int smblib_get_prop_step_chg_step(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1173,7 +1308,7 @@ int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1194,14 +1329,14 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg,
rc = vote(chg->usb_suspend_votable, USER_VOTER, (bool)val->intval, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s USB rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s USB rc=%d\n",
(bool)val->intval ? "suspend" : "resume", rc);
return rc;
}
rc = vote(chg->dc_suspend_votable, USER_VOTER, (bool)val->intval, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s DC rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
(bool)val->intval ? "suspend" : "resume", rc);
return rc;
}
@@ -1258,7 +1393,7 @@ int smblib_get_prop_dc_present(struct smb_charger *chg,
rc = smblib_read(chg, DC_INT_RT_STS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read DC_INT_RT_STS_REG rc=%d\n",
+ smblib_err(chg, "Couldn't read DC_INT_RT_STS_REG rc=%d\n",
rc);
return rc;
}
@@ -1283,7 +1418,7 @@ int smblib_get_prop_dc_online(struct smb_charger *chg,
rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
rc);
return rc;
}
@@ -1328,8 +1463,7 @@ int smblib_get_prop_usb_present(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
@@ -1353,7 +1487,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
rc);
return rc;
}
@@ -1384,10 +1518,18 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval);
}
+int smblib_get_prop_pd_current_max(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
+ return 0;
+}
+
int smblib_get_prop_usb_current_max(struct smb_charger *chg,
union power_supply_propval *val)
{
- val->intval = get_effective_result_locked(chg->usb_icl_votable);
+ val->intval = get_client_vote_locked(chg->usb_icl_votable,
+ USB_PSY_VOTER);
return 0;
}
@@ -1452,8 +1594,7 @@ int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
@@ -1487,7 +1628,7 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
return POWER_SUPPLY_TYPEC_NONE;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat);
@@ -1515,7 +1656,7 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
return POWER_SUPPLY_TYPEC_NONE;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat);
@@ -1546,7 +1687,7 @@ int smblib_get_prop_typec_mode(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
val->intval = POWER_SUPPLY_TYPEC_NONE;
return rc;
}
@@ -1573,7 +1714,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
rc);
return rc;
}
@@ -1597,7 +1738,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
break;
default:
val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
- dev_err(chg->dev, "unsupported power role 0x%02lx\n",
+ smblib_err(chg, "unsupported power role 0x%02lx\n",
ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT));
return -EINVAL;
}
@@ -1618,16 +1759,55 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval);
}
+int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc;
+ u8 ctrl;
+
+ rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ val->intval = ctrl & EXIT_SNK_BASED_ON_CC_BIT;
+ return 0;
+}
+
/*******************
* USB PSY SETTERS *
* *****************/
+int smblib_set_prop_pd_current_max(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc;
+
+ if (chg->pd_active)
+ rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
+ else
+ rc = -EPERM;
+
+ return rc;
+}
+
int smblib_set_prop_usb_current_max(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc;
- rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
+ if (!chg->pd_active) {
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ true, val->intval);
+ } else if (chg->system_suspend_supported) {
+ if (val->intval <= USBIN_25MA)
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ true, val->intval);
+ else
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ false, 0);
+ }
return rc;
}
@@ -1651,14 +1831,14 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
power_role = DFP_EN_CMD_BIT;
break;
default:
- dev_err(chg->dev, "power role %d not supported\n", val->intval);
+ smblib_err(chg, "power role %d not supported\n", val->intval);
return -EINVAL;
}
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
TYPEC_POWER_ROLE_CMD_MASK, power_role);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
power_role, rc);
return rc;
}
@@ -1675,7 +1855,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
rc = smblib_set_usb_pd_allowed_voltage(chg, min_uv,
chg->voltage_max_uv);
if (rc < 0) {
- dev_err(chg->dev, "invalid max voltage %duV rc=%d\n",
+ smblib_err(chg, "invalid max voltage %duV rc=%d\n",
val->intval, rc);
return rc;
}
@@ -1697,7 +1877,7 @@ int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
rc = smblib_set_usb_pd_allowed_voltage(chg, chg->voltage_min_uv,
max_uv);
if (rc < 0) {
- dev_err(chg->dev, "invalid min voltage %duV rc=%d\n",
+ smblib_err(chg, "invalid min voltage %duV rc=%d\n",
val->intval, rc);
return rc;
}
@@ -1710,60 +1890,75 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc;
- u8 stat;
+ u8 stat = 0;
+ bool cc_debounced;
+ bool orientation;
+ bool pd_active = val->intval;
if (!get_effective_result(chg->pd_allowed_votable)) {
- dev_err(chg->dev, "PD is not allowed\n");
+ smblib_err(chg, "PD is not allowed\n");
return -EINVAL;
}
- rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
- AUTO_SRC_DETECT_BIT,
- val->intval ? 0 : AUTO_SRC_DETECT_BIT);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s APSD rc=%d\n",
- val->intval ? "disable" : "enable", rc);
- return rc;
- }
-
- vote(chg->pd_allowed_votable, PD_VOTER, val->intval, 0);
+ vote(chg->apsd_disable_votable, PD_VOTER, pd_active, 0);
+ vote(chg->pd_allowed_votable, PD_VOTER, pd_active, 0);
/*
* VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2 line
* when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override) is set
* or when VCONN_EN_VALUE_BIT is set.
*/
- if (val->intval) {
- rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
- if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
- return rc;
- }
+ rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ return rc;
+ }
- stat &= CC_ORIENTATION_BIT;
+ if (pd_active) {
+ orientation = stat & CC_ORIENTATION_BIT;
rc = smblib_masked_write(chg,
- TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- VCONN_EN_ORIENTATION_BIT,
- stat ? 0 : VCONN_EN_ORIENTATION_BIT);
- if (rc < 0)
- dev_err(chg->dev,
+ TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ VCONN_EN_ORIENTATION_BIT,
+ orientation ? 0 : VCONN_EN_ORIENTATION_BIT);
+ if (rc < 0) {
+ smblib_err(chg,
"Couldn't enable vconn on CC line rc=%d\n", rc);
+ return rc;
+ }
}
/* CC pin selection s/w override in PD session; h/w otherwise. */
rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
TYPEC_SPARE_CFG_BIT,
- val->intval ? TYPEC_SPARE_CFG_BIT : 0);
+ pd_active ? TYPEC_SPARE_CFG_BIT : 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't change cc_out ctrl to %s rc=%d\n",
- val->intval ? "SW" : "HW", rc);
+ smblib_err(chg, "Couldn't change cc_out ctrl to %s rc=%d\n",
+ pd_active ? "SW" : "HW", rc);
return rc;
}
- chg->pd_active = (bool)val->intval;
+ cc_debounced = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+ if (!pd_active && cc_debounced)
+ try_rerun_apsd_for_hvdcp(chg);
+
+ chg->pd_active = pd_active;
smblib_update_usb_type(chg);
+ power_supply_changed(chg->usb_psy);
+
+ return rc;
+}
+
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc;
+
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ EXIT_SNK_BASED_ON_CC_BIT,
+ (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
+
+ vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0);
+
return rc;
}
@@ -1836,7 +2031,7 @@ irqreturn_t smblib_handle_chg_state_change(int irq, void *data)
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return IRQ_HANDLED;
}
@@ -1891,7 +2086,7 @@ irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data)
rc = smblib_get_prop_batt_capacity(chg, &pval);
if (rc < 0)
- dev_err(chg->dev, "Couldn't get batt capacity rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
else
step_charge_soc_update(chg, pval.intval);
@@ -1940,7 +2135,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
"dpdm-supply", NULL)) {
chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
if (IS_ERR(chg->dpdm_reg)) {
- dev_err(chg->dev, "Couldn't get dpdm regulator rc=%ld\n",
+ smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
PTR_ERR(chg->dpdm_reg));
chg->dpdm_reg = NULL;
}
@@ -1951,7 +2146,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
return IRQ_HANDLED;
}
@@ -1962,7 +2157,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
rc = regulator_enable(chg->dpdm_reg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't enable dpdm regulator rc=%d\n",
+ smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
rc);
}
} else {
@@ -1970,7 +2165,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
rc = regulator_disable(chg->dpdm_reg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't disable dpdm regulator rc=%d\n",
+ smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
rc);
}
}
@@ -1992,7 +2187,7 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data)
rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ma);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get ICL status rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
return IRQ_HANDLED;
}
@@ -2047,9 +2242,13 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
bool rising, bool qc_charger)
{
- if (rising && !qc_charger) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
- power_supply_changed(chg->usb_psy);
+ /* Hold off PD only until hvdcp 2.0 detection timeout */
+ if (rising) {
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+ if (get_effective_result(chg->pd_disallowed_votable_indirect))
+ /* could be a legacy cable, try doing hvdcp */
+ try_rerun_apsd_for_hvdcp(chg);
}
smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
@@ -2084,7 +2283,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
case CDP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ /* if not DCP then no hvdcp timeout happens. Enable pd here */
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
break;
case DCP_CHARGER_BIT:
if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
@@ -2097,7 +2298,7 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
rc = smblib_update_usb_type(chg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't update usb type rc=%d\n", rc);
+ smblib_err(chg, "Couldn't update usb type rc=%d\n", rc);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
apsd_result->name);
@@ -2112,7 +2313,7 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
rc = smblib_read(chg, APSD_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_STATUS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
return IRQ_HANDLED;
}
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
@@ -2144,48 +2345,124 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
return IRQ_HANDLED;
}
-static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached)
+static void typec_source_removal(struct smb_charger *chg)
{
int rc;
- if (!attached) {
- rc = smblib_detach_usb(chg);
- if (rc < 0)
- dev_err(chg->dev, "Couldn't detach USB rc=%d\n", rc);
+ vote(chg->pl_disable_votable, TYPEC_SRC_VOTER, true, 0);
+ /* reset both usbin current and voltage votes */
+ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+ vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
+ /* reset taper_end voter here */
+ vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
+
+ cancel_delayed_work_sync(&chg->hvdcp_detect_work);
+
+ /* reconfigure allowed voltage for HVDCP */
+ rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG,
+ USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
+ rc);
+
+ chg->voltage_min_uv = MICRO_5V;
+ chg->voltage_max_uv = MICRO_5V;
+
+ /* clear USB ICL vote for PD_VOTER */
+ rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+
+ /* clear USB ICL vote for USB_PSY_VOTER */
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+}
+
+static void typec_source_insertion(struct smb_charger *chg)
+{
+ vote(chg->pl_disable_votable, TYPEC_SRC_VOTER, false, 0);
+}
+
+static void typec_sink_insertion(struct smb_charger *chg)
+{
+ /* when a sink is inserted we should not wait on hvdcp timeout to
+ * enable pd
+ */
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+}
+
+static void smblib_handle_typec_removal(struct smb_charger *chg)
+{
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
+
+ /* reset votes from vbus_cc_short */
+ vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, true, 0);
+
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER, true, 0);
+
+ /*
+ * cable could be removed during hard reset, remove its vote to
+ * disable apsd
+ */
+ vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
+
+ typec_source_removal(chg);
+
+ smblib_update_usb_type(chg);
+}
+
+static void smblib_handle_typec_insertion(struct smb_charger *chg,
+ bool sink_attached, bool legacy_cable)
+{
+ int rp;
+ bool vbus_cc_short = false;
+
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
+
+ if (sink_attached) {
+ typec_source_removal(chg);
+ typec_sink_insertion(chg);
+ } else {
+ typec_source_insertion(chg);
}
- smblib_dbg(chg, PR_INTERRUPT, "IRQ: CC %s\n",
- attached ? "attached" : "detached");
+ vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER,
+ legacy_cable, 0);
+
+ if (legacy_cable) {
+ rp = smblib_get_prop_ufp_mode(chg);
+ if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH
+ || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) {
+ vbus_cc_short = true;
+ smblib_err(chg, "Disabling PD and HVDCP, VBUS-CC shorted, rp = %d found\n",
+ rp);
+ }
+ }
+
+ vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, vbus_cc_short, 0);
+ vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER,
+ vbus_cc_short, 0);
}
static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
- bool rising, bool sink_attached)
+ bool rising, bool sink_attached, bool legacy_cable)
{
int rc;
union power_supply_propval pval = {0, };
- /* allow PD for attached sinks */
- if (rising && sink_attached)
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ if (rising)
+ smblib_handle_typec_insertion(chg, sink_attached, legacy_cable);
+ else
+ smblib_handle_typec_removal(chg);
rc = smblib_get_prop_typec_mode(chg, &pval);
if (rc < 0)
- dev_err(chg->dev, "Couldn't get prop typec mode rc=%d\n", rc);
-
- /*
- * vote to enable parallel charging if a source is attached, and disable
- * otherwise
- */
- vote(chg->pl_disable_votable, TYPEC_SRC_VOTER,
- !rising || sink_attached, 0);
-
- if (!rising || sink_attached) {
- /* reset both usbin current and voltage votes */
- vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
- vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
- /* reset taper_end voter here */
- vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
- }
+ smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
rising ? "rising" : "falling",
@@ -2198,20 +2475,27 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
struct smb_charger *chg = irq_data->parent_data;
int rc;
u8 stat;
+ bool debounce_done, sink_attached, legacy_cable;
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return IRQ_HANDLED;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
+ debounce_done = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+ sink_attached = (bool)(stat & UFP_DFP_MODE_STATUS_BIT);
+
+ rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat);
+ legacy_cable = (bool)(stat & TYPEC_LEGACY_CABLE_STATUS_BIT);
- smblib_handle_typec_cc(chg,
- (bool)(stat & CC_ATTACHED_BIT));
smblib_handle_typec_debounce_done(chg,
- (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT),
- (bool)(stat & UFP_DFP_MODE_STATUS_BIT));
+ debounce_done, sink_attached, legacy_cable);
power_supply_changed(chg->usb_psy);
@@ -2241,14 +2525,15 @@ static void smblib_hvdcp_detect_work(struct work_struct *work)
{
struct smb_charger *chg = container_of(work, struct smb_charger,
hvdcp_detect_work.work);
- const struct apsd_result *apsd_result;
- apsd_result = smblib_get_apsd_result(chg);
- if (apsd_result->bit &&
- !(apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT))) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+ if (get_effective_result(chg->pd_disallowed_votable_indirect))
+ /* pd is still disabled, try hvdcp */
+ try_rerun_apsd_for_hvdcp(chg);
+ else
+ /* notify pd now that pd is allowed */
power_supply_changed(chg->usb_psy);
- }
}
static void bms_update_work(struct work_struct *work)
@@ -2267,7 +2552,7 @@ static void step_soc_req_work(struct work_struct *work)
rc = smblib_get_prop_batt_capacity(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get batt capacity rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
return;
}
@@ -2299,7 +2584,7 @@ static void smblib_pl_taper_work(struct work_struct *work)
rc = smblib_get_prop_batt_charge_type(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get batt charge type rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt charge type rc=%d\n", rc);
goto done;
}
@@ -2389,8 +2674,16 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
- chg->pd_allowed_votable = create_votable("PD_ALLOWED", VOTE_SET_ANY,
- NULL, NULL);
+ chg->pd_disallowed_votable_indirect
+ = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
+ smblib_pd_disallowed_votable_indirect_callback, chg);
+ if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
+ rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
+ return rc;
+ }
+
+ chg->pd_allowed_votable = create_votable("PD_ALLOWED",
+ VOTE_SET_ANY, NULL, NULL);
if (IS_ERR(chg->pd_allowed_votable)) {
rc = PTR_ERR(chg->pd_allowed_votable);
return rc;
@@ -2429,6 +2722,24 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
+ chg->hvdcp_disable_votable = create_votable("HVDCP_DISABLE",
+ VOTE_SET_ANY,
+ smblib_hvdcp_disable_vote_callback,
+ chg);
+ if (IS_ERR(chg->hvdcp_disable_votable)) {
+ rc = PTR_ERR(chg->hvdcp_disable_votable);
+ return rc;
+ }
+
+ chg->apsd_disable_votable = create_votable("APSD_DISABLE",
+ VOTE_SET_ANY,
+ smblib_apsd_disable_vote_callback,
+ chg);
+ if (IS_ERR(chg->apsd_disable_votable)) {
+ rc = PTR_ERR(chg->apsd_disable_votable);
+ return rc;
+ }
+
return rc;
}
@@ -2448,6 +2759,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->usb_icl_votable);
if (chg->dc_icl_votable)
destroy_votable(chg->dc_icl_votable);
+ if (chg->pd_disallowed_votable_indirect)
+ destroy_votable(chg->pd_disallowed_votable_indirect);
if (chg->pd_allowed_votable)
destroy_votable(chg->pd_allowed_votable);
if (chg->awake_votable)
@@ -2458,6 +2771,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->chg_disable_votable);
if (chg->pl_enable_votable_indirect)
destroy_votable(chg->pl_enable_votable_indirect);
+ if (chg->apsd_disable_votable)
+ destroy_votable(chg->apsd_disable_votable);
}
static void smblib_iio_deinit(struct smb_charger *chg)
@@ -2491,14 +2806,14 @@ int smblib_init(struct smb_charger *chg)
case PARALLEL_MASTER:
rc = smblib_create_votables(chg);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't create votables rc=%d\n",
+ smblib_err(chg, "Couldn't create votables rc=%d\n",
rc);
return rc;
}
rc = smblib_register_notifier(chg);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't register notifier rc=%d\n", rc);
return rc;
}
@@ -2513,7 +2828,7 @@ int smblib_init(struct smb_charger *chg)
case PARALLEL_SLAVE:
break;
default:
- dev_err(chg->dev, "Unsupported mode %d\n", chg->mode);
+ smblib_err(chg, "Unsupported mode %d\n", chg->mode);
return -EINVAL;
}
@@ -2530,7 +2845,7 @@ int smblib_deinit(struct smb_charger *chg)
case PARALLEL_SLAVE:
break;
default:
- dev_err(chg->dev, "Unsupported mode %d\n", chg->mode);
+ smblib_err(chg, "Unsupported mode %d\n", chg->mode);
return -EINVAL;
}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index 00975e6c1285..b6913fa12f1a 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -27,6 +27,7 @@ enum print_reason {
#define DEFAULT_VOTER "DEFAULT_VOTER"
#define USER_VOTER "USER_VOTER"
#define PD_VOTER "PD_VOTER"
+#define USB_PSY_VOTER "USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
@@ -37,6 +38,13 @@ enum print_reason {
#define TAPER_END_VOTER "TAPER_END_VOTER"
#define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER"
#define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER"
+#define CC_DETACHED_VOTER "CC_DETACHED_VOTER"
+#define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER"
+#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER"
+#define PD_HARD_RESET_VOTER "PD_HARD_RESET_VOTER"
+#define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER"
+#define LEGACY_CABLE_VOTER "LEGACY_CABLE_VOTER"
+#define PD_INACTIVE_VOTER "PD_INACTIVE_VOTER"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -89,6 +97,7 @@ struct smb_params {
struct smb_chg_param step_soc_threshold[4];
struct smb_chg_param step_soc;
struct smb_chg_param step_cc_delta[5];
+ struct smb_chg_param freq_buck;
};
struct parallel_params {
@@ -108,6 +117,7 @@ struct smb_iio {
struct smb_charger {
struct device *dev;
+ char *name;
struct regmap *regmap;
struct smb_params param;
struct smb_iio iio;
@@ -144,11 +154,14 @@ struct smb_charger {
struct votable *fv_votable;
struct votable *usb_icl_votable;
struct votable *dc_icl_votable;
+ struct votable *pd_disallowed_votable_indirect;
struct votable *pd_allowed_votable;
struct votable *awake_votable;
struct votable *pl_disable_votable;
struct votable *chg_disable_votable;
struct votable *pl_enable_votable_indirect;
+ struct votable *hvdcp_disable_votable;
+ struct votable *apsd_disable_votable;
/* work */
struct work_struct bms_update_work;
@@ -162,8 +175,9 @@ struct smb_charger {
/* cached status */
int voltage_min_uv;
int voltage_max_uv;
- bool pd_active;
+ int pd_active;
bool vbus_present;
+ bool system_suspend_supported;
int system_temp_level;
int thermal_levels;
@@ -275,6 +289,8 @@ int smblib_get_prop_usb_suspend(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_pd_current_max(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_usb_current_max(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
@@ -289,10 +305,14 @@ int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_set_prop_pd_current_max(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_set_prop_usb_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
@@ -303,6 +323,8 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val);
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_get_prop_slave_current_now(struct smb_charger *chg,
union power_supply_propval *val);
@@ -310,4 +332,3 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg,
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
-
diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h
index 8a49a8fb38ba..c2941f61f4a2 100644
--- a/drivers/power/qcom-charger/smb-reg.h
+++ b/drivers/power/qcom-charger/smb-reg.h
@@ -506,6 +506,15 @@ enum {
#define CC_ORIENTATION_BIT BIT(1)
#define CC_ATTACHED_BIT BIT(0)
+#define TYPE_C_STATUS_5_REG (USBIN_BASE + 0x0F)
+#define TRY_SOURCE_FAILED_BIT BIT(6)
+#define TRY_SINK_FAILED_BIT BIT(5)
+#define TIMER_STAGE_2_BIT BIT(4)
+#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(3)
+#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(2)
+#define TYPEC_TRYSOURCE_DETECT_STATUS_BIT BIT(1)
+#define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0)
+
/* USBIN Interrupt Bits */
#define TYPE_C_CHANGE_RT_STS_BIT BIT(7)
#define USBIN_ICL_CHANGE_RT_STS_BIT BIT(6)
@@ -555,6 +564,16 @@ enum {
#define TYPE_C_UFP_MODE_BIT BIT(1)
#define EN_80UA_180UA_CUR_SOURCE_BIT BIT(0)
+#define TYPE_C_CFG_3_REG (USBIN_BASE + 0x5A)
+#define TVBUS_DEBOUNCE_BIT BIT(7)
+#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(6)
+#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT BIT(5)
+#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(4)
+#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(3)
+#define EN_TRYSINK_MODE_BIT BIT(2)
+#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1)
+#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0)
+
#define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60)
#define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0)
enum {
@@ -585,6 +604,7 @@ enum {
#define DCD_TIMEOUT_SEL_BIT BIT(5)
#define OCD_CURRENT_SEL_BIT BIT(4)
#define SLOW_PLUGIN_TIMER_EN_CFG_BIT BIT(3)
+#define FLOAT_OPTIONS_MASK GENMASK(2, 0)
#define FLOAT_DIS_CHGING_CFG_BIT BIT(2)
#define SUSPEND_FLOAT_CFG_BIT BIT(1)
#define FORCE_FLOAT_SDP_CFG_BIT BIT(0)
@@ -612,7 +632,7 @@ enum {
#define TYPEC_VBUS_ASSERT_INT_EN_BIT BIT(0)
#define TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG (USBIN_BASE + 0x68)
-#define EXIT_SNK_BASED_ON_CC BIT(7)
+#define EXIT_SNK_BASED_ON_CC_BIT BIT(7)
#define VCONN_EN_ORIENTATION_BIT BIT(6)
#define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5)
#define VCONN_EN_SRC_BIT BIT(4)
@@ -975,4 +995,6 @@ enum {
#define SYSOK_POL_BIT BIT(3)
#define SYSOK_OPTIONS_MASK GENMASK(2, 0)
+#define CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG (MISC_BASE + 0xA0)
+
#endif /* __SMB2_CHARGER_REG_H */
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index e8ec2f49f7eb..3db295b3e6e8 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -72,6 +72,13 @@ static struct smb_params v1_params = {
.max_u = 6000000,
.step_u = 25000,
},
+ .freq_buck = {
+ .name = "buck switching frequency",
+ .reg = CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
+ .min_u = 500,
+ .max_u = 2000,
+ .step_u = 100,
+ },
};
struct smb_dt_props {
@@ -471,6 +478,10 @@ static int smb138x_parallel_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
break;
+ case POWER_SUPPLY_PROP_BUCK_FREQ:
+ rc = smblib_set_charge_param(chg, &chg->param.freq_buck,
+ val->intval);
+ break;
default:
pr_err("parallel power supply set prop %d not supported\n",
prop);
@@ -1172,6 +1183,7 @@ static int smb138x_probe(struct platform_device *pdev)
chip->chg.dev = &pdev->dev;
chip->chg.debug_mask = &__debug_mask;
+ chip->chg.name = "SMB";
chip->chg.regmap = dev_get_regmap(chip->chg.dev->parent, NULL);
if (!chip->chg.regmap) {
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1a1dd804ffb3..873b4615d4a9 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2567,16 +2567,19 @@ static void ufs_qcom_print_unipro_testbus(struct ufs_hba *hba)
kfree(testbus);
}
-static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba, bool no_sleep)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
"HCI Vendor Specific Registers ");
+ ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
+
+ if (no_sleep)
+ return;
/* sleep a bit intermittently as we are dumping too much data */
- ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
usleep_range(1000, 1100);
ufs_qcom_testbus_read(hba);
usleep_range(1000, 1100);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 53fed74eaefc..862d56e78086 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -539,7 +539,7 @@ static void ufshcd_print_uic_err_hist(struct ufs_hba *hba,
}
}
-static void ufshcd_print_host_regs(struct ufs_hba *hba)
+static inline void __ufshcd_print_host_regs(struct ufs_hba *hba, bool no_sleep)
{
if (!(hba->ufshcd_dbg_print & UFSHCD_DBG_PRINT_HOST_REGS_EN))
return;
@@ -571,7 +571,12 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba)
ufshcd_print_clk_freqs(hba);
- ufshcd_vops_dbg_register_dump(hba);
+ ufshcd_vops_dbg_register_dump(hba, no_sleep);
+}
+
+static void ufshcd_print_host_regs(struct ufs_hba *hba)
+{
+ __ufshcd_print_host_regs(hba, false);
}
static
@@ -5055,7 +5060,12 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
dev_err(hba->dev,
"OCS error from controller = %x for tag %d\n",
ocs, lrbp->task_tag);
- ufshcd_print_host_regs(hba);
+ /*
+ * This is called in interrupt context, hence avoid sleep
+ * while printing debug registers. Also print only the minimum
+ * debug registers needed to debug OCS failure.
+ */
+ __ufshcd_print_host_regs(hba, true);
ufshcd_print_host_state(hba);
break;
} /* end of switch */
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index cd15d67cf8d5..c0714b7bea72 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -335,7 +335,7 @@ struct ufs_hba_variant_ops {
int (*suspend)(struct ufs_hba *, enum ufs_pm_op);
int (*resume)(struct ufs_hba *, enum ufs_pm_op);
int (*full_reset)(struct ufs_hba *);
- void (*dbg_register_dump)(struct ufs_hba *hba);
+ void (*dbg_register_dump)(struct ufs_hba *hba, bool no_sleep);
int (*update_sec_cfg)(struct ufs_hba *hba, bool restore_sec_cfg);
u32 (*get_scale_down_gear)(struct ufs_hba *);
int (*set_bus_vote)(struct ufs_hba *, bool);
@@ -1244,10 +1244,11 @@ static inline int ufshcd_vops_full_reset(struct ufs_hba *hba)
}
-static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
+static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba,
+ bool no_sleep)
{
if (hba->var && hba->var->vops && hba->var->vops->dbg_register_dump)
- hba->var->vops->dbg_register_dump(hba);
+ hba->var->vops->dbg_register_dump(hba, no_sleep);
}
static inline int ufshcd_vops_update_sec_cfg(struct ufs_hba *hba,
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 504a3263253c..ab00eac7f633 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -605,8 +605,8 @@ void *service_notif_register_notifier(const char *service_path, int instance_id,
if (!service_path || !instance_id || !nb)
return ERR_PTR(-EINVAL);
- service_notif = _find_service_info(service_path);
mutex_lock(&notif_add_lock);
+ service_notif = _find_service_info(service_path);
if (!service_notif) {
service_notif = (struct service_notif_info *)add_service_notif(
service_path,
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 0121bf7ca4ac..98d5908c1e2f 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -1139,6 +1139,7 @@ static void f_midi_free(struct usb_function *f)
mutex_lock(&opts->lock);
for (i = opts->in_ports - 1; i >= 0; --i)
kfree(midi->in_port[i]);
+ opts->func_inst.f = NULL;
kfree(midi);
--opts->refcnt;
mutex_unlock(&opts->lock);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 7a1174b32a38..26c91e0ce163 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -299,6 +299,7 @@ struct usbpd {
enum power_supply_typec_mode typec_mode;
enum power_supply_type psy_type;
bool vbus_present;
+ bool pd_allowed;
enum data_role current_dr;
enum power_role current_pr;
@@ -459,6 +460,7 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos)
static int pd_eval_src_caps(struct usbpd *pd, const u32 *src_caps)
{
+ union power_supply_propval val;
u32 first_pdo = src_caps[0];
/* save the PDOs so userspace can further evaluate */
@@ -474,6 +476,10 @@ static int pd_eval_src_caps(struct usbpd *pd, const u32 *src_caps)
pd->peer_pr_swap = PD_SRC_PDO_FIXED_PR_SWAP(first_pdo);
pd->peer_dr_swap = PD_SRC_PDO_FIXED_DR_SWAP(first_pdo);
+ val.intval = PD_SRC_PDO_FIXED_USB_SUSP(first_pdo);
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED, &val);
+
/* Select the first PDO (vSafe5V) immediately. */
pd_select_pdo(pd, 1);
@@ -625,7 +631,10 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
case PE_SRC_STARTUP:
if (pd->current_dr == DR_NONE) {
pd->current_dr = DR_DFP;
- /* Defer starting USB host mode until after PD */
+ /*
+ * Defer starting USB host mode until PE_SRC_READY or
+ * when PE_SRC_SEND_CAPABILITIES fails
+ */
}
/* Set CC back to DRP toggle for the next disconnect */
@@ -660,7 +669,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
pd->current_state = PE_SRC_SEND_CAPABILITIES;
if (pd->in_pr_swap) {
- pd->in_pr_swap = false;
kick_sm(pd, SWAP_SOURCE_START_TIME);
break;
}
@@ -820,6 +828,9 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
}
}
+ if (!pd->pd_allowed)
+ break;
+
/* Reset protocol layer */
pd->tx_msgid = 0;
pd->rx_msgid = -1;
@@ -847,7 +858,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
pd->pd_phy_opened = true;
}
- pd->in_pr_swap = false;
pd->current_voltage = 5000000;
pd->current_state = PE_SNK_WAIT_FOR_CAPABILITIES;
@@ -1373,11 +1383,11 @@ static void usbpd_sm(struct work_struct *w)
ctrl_recvd = pd->rx_msg_type;
/* Disconnect? */
- if (pd->typec_mode == POWER_SUPPLY_TYPEC_NONE) {
+ if (pd->typec_mode == POWER_SUPPLY_TYPEC_NONE && !pd->in_pr_swap) {
if (pd->current_state == PE_UNKNOWN)
goto sm_done;
- usbpd_info(&pd->dev, "USB PD disconnect\n");
+ usbpd_info(&pd->dev, "USB Type-C disconnect\n");
if (pd->pd_phy_opened) {
pd_phy_close();
@@ -1400,6 +1410,10 @@ static void usbpd_sm(struct work_struct *w)
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED,
+ &val);
+
+ power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
if (pd->current_pr == PR_SRC)
@@ -1484,6 +1498,10 @@ static void usbpd_sm(struct work_struct *w)
}
break;
+ case PE_SRC_STARTUP:
+ usbpd_set_state(pd, PE_SRC_STARTUP);
+ break;
+
case PE_SRC_SEND_CAPABILITIES:
ret = pd_send_msg(pd, MSG_SOURCE_CAPABILITIES, default_src_caps,
ARRAY_SIZE(default_src_caps), SOP_MSG);
@@ -1621,6 +1639,10 @@ static void usbpd_sm(struct work_struct *w)
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
break;
+ case PE_SNK_STARTUP:
+ usbpd_set_state(pd, PE_SNK_STARTUP);
+ break;
+
case PE_SNK_WAIT_FOR_CAPABILITIES:
if (data_recvd == MSG_SOURCE_CAPABILITIES) {
val.intval = 0;
@@ -1668,9 +1690,14 @@ static void usbpd_sm(struct work_struct *w)
POWER_SUPPLY_PROP_VOLTAGE_MIN,
&val);
- val.intval = 0; /* suspend charging */
+ /*
+ * disable charging; technically we are allowed to
+ * charge up to pSnkStdby (2.5 W) during this
+ * transition, but disable it just for simplicity.
+ */
+ val.intval = 0;
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
pd->selected_pdo = pd->requested_pdo;
usbpd_set_state(pd, PE_SNK_TRANSITION_SINK);
@@ -1701,7 +1728,7 @@ static void usbpd_sm(struct work_struct *w)
/* resume charging */
val.intval = pd->requested_current * 1000; /* mA->uA */
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
usbpd_set_state(pd, PE_SNK_READY);
} else {
@@ -1853,7 +1880,7 @@ static void usbpd_sm(struct work_struct *w)
if (pd->requested_current) {
val.intval = pd->requested_current = 0;
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
}
val.intval = pd->requested_voltage;
@@ -2008,9 +2035,8 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
{
struct usbpd *pd = container_of(nb, struct usbpd, psy_nb);
union power_supply_propval val;
- bool pd_allowed;
enum power_supply_typec_mode typec_mode;
- enum power_supply_type psy_type;
+ bool do_work = false;
int ret;
if (ptr != pd->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
@@ -2024,7 +2050,9 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
return ret;
}
- pd_allowed = val.intval;
+ if (pd->pd_allowed != val.intval)
+ do_work = true;
+ pd->pd_allowed = val.intval;
ret = power_supply_get_property(pd->usb_psy,
POWER_SUPPLY_PROP_PRESENT, &val);
@@ -2044,38 +2072,6 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
typec_mode = val.intval;
- /*
- * Don't proceed if cable is connected but PD_ALLOWED is false.
- * It means the PMIC may still be in the middle of performing
- * charger type detection.
- */
- if (!pd_allowed && typec_mode != POWER_SUPPLY_TYPEC_NONE)
- return 0;
-
- /*
- * Workaround for PMIC HW bug.
- *
- * During hard reset or PR swap (sink to source) when VBUS goes to 0
- * the CC logic will report this as a disconnection. In those cases it
- * can be ignored, however the downside is that pd->hard_reset can be
- * momentarily true even when a non-PD capable source is attached, and
- * can't be distinguished from a physical disconnect. In that case,
- * allow for the common case of disconnecting from an SDP.
- *
- * The less common case is a PD-capable SDP which will result in a
- * hard reset getting treated like a disconnect. We can live with this
- * until the HW bug is fixed: in which disconnection won't be reported
- * on VBUS loss alone unless pullup is also removed from CC.
- */
- if (typec_mode == POWER_SUPPLY_TYPEC_NONE &&
- (pd->in_pr_swap ||
- (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
- pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT))) {
- usbpd_dbg(&pd->dev, "Ignoring disconnect due to %s\n",
- pd->in_pr_swap ? "PR swap" : "hard reset");
- return 0;
- }
-
ret = power_supply_get_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPE, &val);
if (ret) {
@@ -2083,61 +2079,91 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
return ret;
}
- psy_type = val.intval;
+ if (pd->psy_type != val.intval)
+ do_work = true;
+ pd->psy_type = val.intval;
usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
- typec_mode, pd->vbus_present, psy_type,
+ typec_mode, pd->vbus_present, pd->psy_type,
usbpd_get_plug_orientation(pd));
- /* any change? */
- if (pd->typec_mode == typec_mode && pd->psy_type == psy_type)
- return 0;
+ if (pd->typec_mode != typec_mode) {
+ pd->typec_mode = typec_mode;
+ do_work = true;
- pd->typec_mode = typec_mode;
- pd->psy_type = psy_type;
+ switch (typec_mode) {
+ /* Disconnect */
+ case POWER_SUPPLY_TYPEC_NONE:
+ if (pd->in_pr_swap) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
+ do_work = false;
+ }
- switch (typec_mode) {
- /* Disconnect */
- case POWER_SUPPLY_TYPEC_NONE:
- kick_sm(pd, 0);
- break;
+ /*
+ * Workaround for PMIC HW bug.
+ *
+ * During hard reset when VBUS goes to 0 the CC logic
+ * will report this as a disconnection. In those cases
+ * it can be ignored, however the downside is that
+ * pd->hard_reset can be momentarily true even when a
+ * non-PD capable source is attached, and can't be
+ * distinguished from a physical disconnect. In that
+ * case, allow for the common case of disconnecting
+ * from an SDP.
+ *
+ * The less common case is a PD-capable SDP which will
+ * result in a hard reset getting treated like a
+ * disconnect. We can live with this until the HW bug
+ * is fixed: in which disconnection won't be reported
+ * on VBUS loss alone unless pullup is also removed
+ * from CC.
+ */
+ if (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
+ pd->current_state ==
+ PE_SNK_TRANSITION_TO_DEFAULT) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
+ do_work = false;
+ }
- /* Sink states */
- case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
- case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
- case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
- usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
- src_current(typec_mode));
- if (pd->current_pr != PR_SINK ||
- pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT) {
+ break;
+
+ /* Sink states */
+ case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+ case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+ case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+ usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
+ src_current(typec_mode));
pd->current_pr = PR_SINK;
- kick_sm(pd, 0);
- }
- break;
+ pd->in_pr_swap = false;
+ break;
- /* Source states */
- case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
- case POWER_SUPPLY_TYPEC_SINK:
- usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
- typec_mode == POWER_SUPPLY_TYPEC_SINK ?
- "" : " (powered)");
- if (pd->current_pr != PR_SRC) {
+ /* Source states */
+ case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
+ case POWER_SUPPLY_TYPEC_SINK:
+ usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
+ typec_mode == POWER_SUPPLY_TYPEC_SINK ?
+ "" : " (powered)");
pd->current_pr = PR_SRC;
- kick_sm(pd, 0);
- }
- break;
+ pd->in_pr_swap = false;
+ break;
- case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
- usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
- break;
- case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
- usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
- break;
- default:
- usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n", typec_mode);
- break;
+ case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
+ usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
+ break;
+ case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
+ usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
+ break;
+ default:
+ usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n",
+ typec_mode);
+ break;
+ }
}
+ /* only queue state machine if CC state or PD_ALLOWED changes */
+ if (do_work)
+ kick_sm(pd, 0);
+
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 55918d47a21a..1e93a5b2e9ba 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -460,6 +460,7 @@ struct mdss_data_type {
u32 nmax_concurrent_ad_hw;
struct workqueue_struct *ad_calc_wq;
u32 ad_debugen;
+ bool mem_retain;
struct mdss_intr hist_intr;
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 4e68952d33a9..b246204f3181 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -1157,23 +1157,46 @@ exit:
return ret;
}
-int mdss_dp_off(struct mdss_panel_data *pdata)
+static void mdss_dp_mainlink_off(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
+ const int idle_pattern_completion_timeout_ms = 3 * HZ / 100;
dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
panel_data);
if (!dp_drv) {
pr_err("Invalid input data\n");
- return -EINVAL;
+ return;
}
- pr_debug("Entered++, cont_splash=%d\n", dp_drv->cont_splash);
+ pr_debug("Entered++\n");
/* wait until link training is completed */
mutex_lock(&dp_drv->train_mutex);
reinit_completion(&dp_drv->idle_comp);
mdss_dp_state_ctrl(&dp_drv->ctrl_io, ST_PUSH_IDLE);
+ if (!wait_for_completion_timeout(&dp_drv->idle_comp,
+ idle_pattern_completion_timeout_ms))
+ pr_warn("PUSH_IDLE pattern timedout\n");
+
+ mutex_unlock(&dp_drv->train_mutex);
+ pr_debug("mainlink off done\n");
+}
+
+int mdss_dp_off(struct mdss_panel_data *pdata)
+{
+ struct mdss_dp_drv_pdata *dp_drv = NULL;
+
+ dp_drv = container_of(pdata, struct mdss_dp_drv_pdata,
+ panel_data);
+ if (!dp_drv) {
+ pr_err("Invalid input data\n");
+ return -EINVAL;
+ }
+ pr_debug("Entered++, cont_splash=%d\n", dp_drv->cont_splash);
+
+ /* wait until link training is completed */
+ mutex_lock(&dp_drv->train_mutex);
if (dp_drv->link_clks_on)
mdss_dp_mainlink_ctrl(&dp_drv->ctrl_io, false);
@@ -1187,6 +1210,13 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
mdss_dp_config_gpios(dp_drv, false);
mdss_dp_pinctrl_set_state(dp_drv, false);
+ /*
+ * The global reset will need DP link ralated clocks to be
+ * running. Add the global reset just before disabling the
+ * link clocks and core clocks.
+ */
+ mdss_dp_ctrl_reset(&dp_drv->ctrl_io);
+
/* Make sure DP is disabled before clk disable */
wmb();
mdss_dp_clk_ctrl(dp_drv, DP_CTRL_PM, false);
@@ -1360,6 +1390,7 @@ edid_error:
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
clk_error:
mdss_dp_regulator_ctrl(dp_drv, false);
+ mdss_dp_config_gpios(dp_drv, false);
vreg_error:
return ret;
}
@@ -1616,7 +1647,7 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
return -EINVAL;
}
- pr_debug("event=%d\n", event);
+ pr_debug("event=%s\n", mdss_panel_intf_event_to_string(event));
dp = container_of(pdata, struct mdss_dp_drv_pdata,
panel_data);
@@ -1639,6 +1670,7 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
case MDSS_EVENT_BLANK:
if (ops && ops->off)
ops->off(dp->hdcp_data);
+ mdss_dp_mainlink_off(pdata);
break;
case MDSS_EVENT_FB_REGISTERED:
fbi = (struct fb_info *)arg;
@@ -1803,7 +1835,7 @@ static void mdss_dp_event_work(struct work_struct *work)
dp->current_event = 0;
spin_unlock_irqrestore(&dp->event_lock, flag);
- pr_debug("todo=%x\n", todo);
+ pr_debug("todo=%s\n", mdss_dp_ev_event_to_string(todo));
switch (todo) {
case EV_EDID_READ:
@@ -1964,10 +1996,50 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
pr_debug("cable disconnected\n");
mutex_lock(&dp_drv->pd_msg_mutex);
dp_drv->cable_connected = false;
+ dp_drv->alt_mode.current_state = UNKNOWN_STATE;
mutex_unlock(&dp_drv->pd_msg_mutex);
mdss_dp_notify_clients(dp_drv, false);
}
+static int mdss_dp_validate_callback(u8 cmd,
+ enum usbpd_svdm_cmd_type cmd_type, int num_vdos)
+{
+ int ret = 0;
+
+ if (cmd_type == SVDM_CMD_TYPE_RESP_NAK) {
+ pr_err("error: NACK\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (cmd_type == SVDM_CMD_TYPE_RESP_BUSY) {
+ pr_err("error: BUSY\n");
+ ret = -EBUSY;
+ goto end;
+ }
+
+ if (cmd == USBPD_SVDM_ATTENTION) {
+ if (cmd_type != SVDM_CMD_TYPE_INITIATOR) {
+ pr_err("error: invalid cmd type for attention\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (!num_vdos) {
+ pr_err("error: no vdo provided\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ } else {
+ if (cmd_type != SVDM_CMD_TYPE_RESP_ACK) {
+ pr_err("error: invalid cmd type\n");
+ ret = -EINVAL;
+ }
+ }
+end:
+ return ret;
+}
+
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type,
const u32 *vdos, int num_vdos)
@@ -1983,80 +2055,51 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
pr_debug("callback -> cmd: 0x%x, *vdos = 0x%x, num_vdos = %d\n",
cmd, *vdos, num_vdos);
+ if (mdss_dp_validate_callback(cmd, cmd_type, num_vdos))
+ return;
+
switch (cmd) {
case USBPD_SVDM_DISCOVER_MODES:
- if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
- dp_drv->alt_mode.dp_cap.response = *vdos;
- mdss_dp_usbpd_ext_capabilities
- (&dp_drv->alt_mode.dp_cap);
- dp_drv->alt_mode.current_state = DISCOVER_MODES_DONE;
- dp_send_events(dp_drv, EV_USBPD_ENTER_MODE);
- } else {
- pr_err("unknown response: %d for Discover_modes\n",
- cmd_type);
- }
+ dp_drv->alt_mode.dp_cap.response = *vdos;
+ mdss_dp_usbpd_ext_capabilities(&dp_drv->alt_mode.dp_cap);
+ dp_drv->alt_mode.current_state |= DISCOVER_MODES_DONE;
+ dp_send_events(dp_drv, EV_USBPD_ENTER_MODE);
break;
case USBPD_SVDM_ENTER_MODE:
- if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
- dp_drv->alt_mode.current_state = ENTER_MODE_DONE;
- dp_send_events(dp_drv, EV_USBPD_DP_STATUS);
- } else {
- pr_err("unknown response: %d for Enter_mode\n",
- cmd_type);
- }
+ dp_drv->alt_mode.current_state |= ENTER_MODE_DONE;
+ dp_send_events(dp_drv, EV_USBPD_DP_STATUS);
break;
case USBPD_SVDM_ATTENTION:
- if (cmd_type == SVDM_CMD_TYPE_INITIATOR) {
- pr_debug("Attention. cmd_type=%d\n",
- cmd_type);
- if (!(dp_drv->alt_mode.current_state
- == ENTER_MODE_DONE)) {
- pr_debug("sending discover_mode\n");
- dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES);
- break;
- }
- if (num_vdos == 1) {
- dp_drv->alt_mode.dp_status.response = *vdos;
- mdss_dp_usbpd_ext_dp_status
- (&dp_drv->alt_mode.dp_status);
- if (dp_drv->alt_mode.dp_status.hpd_high) {
- pr_debug("HPD high\n");
- dp_drv->alt_mode.current_state =
- DP_STATUS_DONE;
- dp_send_events
- (dp_drv, EV_USBPD_DP_CONFIGURE);
- }
- }
- } else {
- pr_debug("unknown response: %d for Attention\n",
- cmd_type);
- }
+ dp_drv->alt_mode.dp_status.response = *vdos;
+ mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status);
+
+ if (!dp_drv->alt_mode.dp_status.hpd_high)
+ return;
+
+ pr_debug("HPD high\n");
+
+ dp_drv->alt_mode.current_state |= DP_STATUS_DONE;
+
+ if (dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE)
+ mdss_dp_host_init(&dp_drv->panel_data);
+ else
+ dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
break;
case DP_VDM_STATUS:
- if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
- dp_drv->alt_mode.dp_status.response = *vdos;
- mdss_dp_usbpd_ext_dp_status
- (&dp_drv->alt_mode.dp_status);
- if (dp_drv->alt_mode.dp_status.hpd_high) {
- pr_debug("HDP high\n");
- dp_drv->alt_mode.current_state =
- DP_STATUS_DONE;
- dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
- }
- } else {
- pr_err("unknown response: %d for DP_Status\n",
- cmd_type);
+ dp_drv->alt_mode.dp_status.response = *vdos;
+ mdss_dp_usbpd_ext_dp_status(&dp_drv->alt_mode.dp_status);
+
+ if (!(dp_drv->alt_mode.current_state & DP_CONFIGURE_DONE)) {
+ dp_drv->alt_mode.current_state |= DP_STATUS_DONE;
+ dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
}
break;
case DP_VDM_CONFIGURE:
- if (cmd_type == SVDM_CMD_TYPE_RESP_ACK) {
- dp_drv->alt_mode.current_state = DP_CONFIGURE_DONE;
- pr_debug("config USBPD to DP done\n");
+ dp_drv->alt_mode.current_state |= DP_CONFIGURE_DONE;
+ pr_debug("config USBPD to DP done\n");
+
+ if (dp_drv->alt_mode.dp_status.hpd_high)
mdss_dp_host_init(&dp_drv->panel_data);
- } else {
- pr_err("unknown response: %d for DP_Configure\n",
- cmd_type);
- }
break;
default:
pr_err("unknown cmd: %d\n", cmd);
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 6c391f6f7de0..8d5af4dc5bf3 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -105,6 +105,7 @@
EDP_INTR_FRAME_END | EDP_INTR_CRC_UPDATED)
#define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2)
+#define EV_EVENT_STR(x) #x
struct edp_buf {
char *start; /* buffer start addr */
@@ -170,12 +171,12 @@ struct usbpd_dp_status {
};
enum dp_alt_mode_state {
- ALT_MODE_INIT_STATE = 0,
- DISCOVER_MODES_DONE,
- ENTER_MODE_DONE,
- DP_STATUS_DONE,
- DP_CONFIGURE_DONE,
- UNKNOWN_STATE,
+ UNKNOWN_STATE = 0,
+ ALT_MODE_INIT_STATE = BIT(0),
+ DISCOVER_MODES_DONE = BIT(1),
+ ENTER_MODE_DONE = BIT(2),
+ DP_STATUS_DONE = BIT(3),
+ DP_CONFIGURE_DONE = BIT(4),
};
struct dp_alt_mode {
@@ -465,6 +466,28 @@ static inline const char *__mdss_dp_pm_supply_node_name(
}
}
+static inline char *mdss_dp_ev_event_to_string(int event)
+{
+ switch (event) {
+ case EV_EDP_AUX_SETUP:
+ return EV_EVENT_STR(EV_EDP_AUX_SETUP);
+ case EV_EDID_READ:
+ return EV_EVENT_STR(EV_EDID_READ);
+ case EV_DPCD_CAP_READ:
+ return EV_EVENT_STR(EV_DPCD_CAP_READ);
+ case EV_DPCD_STATUS_READ:
+ return EV_EVENT_STR(EV_DPCD_STATUS_READ);
+ case EV_LINK_TRAIN:
+ return EV_EVENT_STR(EV_LINK_TRAIN);
+ case EV_IDLE_PATTERNS_SENT:
+ return EV_EVENT_STR(EV_IDLE_PATTERNS_SENT);
+ case EV_VIDEO_READY:
+ return EV_EVENT_STR(EV_VIDEO_READY);
+ default:
+ return "unknown";
+ }
+}
+
void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index 119e2a2b05cf..3c525b0dac4f 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -1174,8 +1174,9 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
pr_debug("Entered++");
dp_host_train_set(ep, 0x01); /* train_1 */
- dp_voltage_pre_emphasise_set(ep);
+ dp_cap_lane_rate_set(ep);
dp_train_pattern_set_write(ep, 0x21); /* train_1 */
+ dp_voltage_pre_emphasise_set(ep);
tries = 0;
old_v_level = ep->v_level;
@@ -1336,7 +1337,6 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
train_start:
dp->v_level = 0; /* start from default level */
dp->p_level = 0;
- dp_cap_lane_rate_set(dp);
mdss_dp_config_ctrl(dp);
mdss_dp_state_ctrl(&dp->ctrl_io, 0);
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c
index 92acb910e0c3..b1eb8e0c9579 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.c
+++ b/drivers/video/fbdev/msm/mdss_dp_util.c
@@ -495,6 +495,14 @@ void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status)
dp_status->hpd_irq =
(buf & BIT(8)) ? true : false;
+ pr_debug("low_pow_st = %d, adaptor_dp_en = %d, multi_func = %d\n",
+ dp_status->low_pow_st, dp_status->adaptor_dp_en,
+ dp_status->multi_func);
+ pr_debug("switch_to_usb_config = %d, exit_dp_mode = %d, hpd_high =%d\n",
+ dp_status->switch_to_usb_config,
+ dp_status->exit_dp_mode, dp_status->hpd_high);
+ pr_debug("hpd_irq = %d\n", dp_status->hpd_irq);
+
mdss_dp_initialize_s_port(&dp_status->c_port, port);
}
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index ace796163fa4..94cc2f2dc370 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -3566,54 +3566,6 @@ static int hdmi_tx_hdcp_off(struct hdmi_tx_ctrl *hdmi_ctrl)
return rc;
}
-static char *hdmi_tx_get_event_name(int event)
-{
- switch (event) {
- case MDSS_EVENT_RESET:
- return HDMI_TX_EVT_STR(MDSS_EVENT_RESET);
- case MDSS_EVENT_LINK_READY:
- return HDMI_TX_EVT_STR(MDSS_EVENT_LINK_READY);
- case MDSS_EVENT_UNBLANK:
- return HDMI_TX_EVT_STR(MDSS_EVENT_UNBLANK);
- case MDSS_EVENT_PANEL_ON:
- return HDMI_TX_EVT_STR(MDSS_EVENT_PANEL_ON);
- case MDSS_EVENT_BLANK:
- return HDMI_TX_EVT_STR(MDSS_EVENT_BLANK);
- case MDSS_EVENT_PANEL_OFF:
- return HDMI_TX_EVT_STR(MDSS_EVENT_PANEL_OFF);
- case MDSS_EVENT_CLOSE:
- return HDMI_TX_EVT_STR(MDSS_EVENT_CLOSE);
- case MDSS_EVENT_SUSPEND:
- return HDMI_TX_EVT_STR(MDSS_EVENT_SUSPEND);
- case MDSS_EVENT_RESUME:
- return HDMI_TX_EVT_STR(MDSS_EVENT_RESUME);
- case MDSS_EVENT_CHECK_PARAMS:
- return HDMI_TX_EVT_STR(MDSS_EVENT_CHECK_PARAMS);
- case MDSS_EVENT_CONT_SPLASH_BEGIN:
- return HDMI_TX_EVT_STR(MDSS_EVENT_CONT_SPLASH_BEGIN);
- case MDSS_EVENT_CONT_SPLASH_FINISH:
- return HDMI_TX_EVT_STR(MDSS_EVENT_CONT_SPLASH_FINISH);
- case MDSS_EVENT_PANEL_UPDATE_FPS:
- return HDMI_TX_EVT_STR(MDSS_EVENT_PANEL_UPDATE_FPS);
- case MDSS_EVENT_FB_REGISTERED:
- return HDMI_TX_EVT_STR(MDSS_EVENT_FB_REGISTERED);
- case MDSS_EVENT_PANEL_CLK_CTRL:
- return HDMI_TX_EVT_STR(MDSS_EVENT_PANEL_CLK_CTRL);
- case MDSS_EVENT_DSI_CMDLIST_KOFF:
- return HDMI_TX_EVT_STR(MDSS_EVENT_DSI_CMDLIST_KOFF);
- case MDSS_EVENT_ENABLE_PARTIAL_ROI:
- return HDMI_TX_EVT_STR(MDSS_EVENT_ENABLE_PARTIAL_ROI);
- case MDSS_EVENT_DSI_STREAM_SIZE:
- return HDMI_TX_EVT_STR(MDSS_EVENT_DSI_STREAM_SIZE);
- case MDSS_EVENT_DSI_DYNAMIC_SWITCH:
- return HDMI_TX_EVT_STR(MDSS_EVENT_DSI_DYNAMIC_SWITCH);
- case MDSS_EVENT_REGISTER_RECOVERY_HANDLER:
- return HDMI_TX_EVT_STR(MDSS_EVENT_REGISTER_RECOVERY_HANDLER);
- default:
- return "unknown";
- }
-}
-
static void hdmi_tx_update_fps(struct hdmi_tx_ctrl *hdmi_ctrl)
{
void *pdata = pdata = hdmi_tx_get_fd(HDMI_TX_FEAT_PANEL);
@@ -3918,7 +3870,8 @@ static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data,
hdmi_ctrl->evt_arg = arg;
DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__,
- hdmi_tx_get_event_name(event), hdmi_ctrl->panel_suspend,
+ mdss_panel_intf_event_to_string(event),
+ hdmi_ctrl->panel_suspend,
hdmi_ctrl->hpd_feature_on);
handler = hdmi_ctrl->evt_handler[event];
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 6845b386807b..a0637109c7b3 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1345,7 +1345,12 @@ int mdss_iommu_ctrl(int enable)
return mdata->iommu_ref_cnt;
}
-static void mdss_mdp_memory_retention_enter(void)
+#define MEM_RETAIN_ON 1
+#define MEM_RETAIN_OFF 0
+#define PERIPH_RETAIN_ON 1
+#define PERIPH_RETAIN_OFF 0
+
+static void mdss_mdp_memory_retention_ctrl(bool mem_ctrl, bool periph_ctrl)
{
struct clk *mdss_mdp_clk = NULL;
struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE);
@@ -1366,49 +1371,35 @@ static void mdss_mdp_memory_retention_enter(void)
__mdss_mdp_reg_access_clk_enable(mdata, true);
if (mdss_mdp_clk) {
- clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM);
- clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET);
- clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH);
- }
-
- if (mdss_mdp_lut_clk) {
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM);
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET);
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_PERIPH);
- }
- __mdss_mdp_reg_access_clk_enable(mdata, false);
-}
-
-static void mdss_mdp_memory_retention_exit(void)
-{
- struct clk *mdss_mdp_clk = NULL;
- struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE);
- struct clk *mdss_mdp_lut_clk = NULL;
- struct clk *mdp_lut_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_LUT);
- struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ if (mem_ctrl)
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_MEM);
- if (mdp_vote_clk) {
- if (test_bit(MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED,
- mdata->mdss_caps_map)) {
- mdss_mdp_clk = mdp_vote_clk;
- mdss_mdp_lut_clk = mdp_lut_vote_clk;
+ if (periph_ctrl) {
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH);
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_CLEAR);
} else {
- mdss_mdp_clk = clk_get_parent(mdp_vote_clk);
- mdss_mdp_lut_clk = clk_get_parent(mdp_lut_vote_clk);
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET);
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH);
}
}
- __mdss_mdp_reg_access_clk_enable(mdata, true);
- if (mdss_mdp_clk) {
- clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM);
- clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH);
- clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_CLEAR);
- }
-
if (mdss_mdp_lut_clk) {
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM);
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH);
- clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_CLEAR);
+ if (mem_ctrl)
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_MEM);
+
+ if (periph_ctrl) {
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH);
+ clk_set_flags(mdss_mdp_lut_clk,
+ CLKFLAG_PERIPH_OFF_CLEAR);
+ } else {
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET);
+ clk_set_flags(mdss_mdp_lut_clk,
+ CLKFLAG_NORETAIN_PERIPH);
+ }
}
__mdss_mdp_reg_access_clk_enable(mdata, false);
}
@@ -1441,17 +1432,21 @@ static int mdss_mdp_idle_pc_restore(void)
mdss_hw_init(mdata);
mdss_iommu_ctrl(0);
- /**
- * sleep 10 microseconds to make sure AD auto-reinitialization
- * is done
- */
- udelay(10);
- mdss_mdp_memory_retention_exit();
-
mdss_mdp_ctl_restore(true);
mdata->idle_pc = false;
end:
+ if (mdata->mem_retain) {
+ /**
+ * sleep 10 microseconds to make sure AD auto-reinitialization
+ * is done
+ */
+ udelay(10);
+ mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON,
+ PERIPH_RETAIN_ON);
+ mdata->mem_retain = false;
+ }
+
mutex_unlock(&mdp_fs_idle_pc_lock);
return rc;
}
@@ -1980,7 +1975,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
case MDSS_MDP_HW_REV_300:
case MDSS_MDP_HW_REV_301:
mdata->max_target_zorder = 7; /* excluding base layer */
- mdata->max_cursor_size = 384;
+ mdata->max_cursor_size = 512;
mdata->per_pipe_ib_factor.numer = 8;
mdata->per_pipe_ib_factor.denom = 5;
mdata->apply_post_scale_bytes = false;
@@ -4912,10 +4907,12 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
* Turning off GDSC while overlays are still
* active.
*/
+
+ mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON,
+ PERIPH_RETAIN_OFF);
mdata->idle_pc = true;
pr_debug("idle pc. active overlays=%d\n",
active_cnt);
- mdss_mdp_memory_retention_enter();
} else {
/*
* Advise RPM to turn MMSS GDSC off during
@@ -4927,7 +4924,11 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
mdss_mdp_cx_ctrl(mdata, false);
mdss_mdp_batfet_ctrl(mdata, false);
+ mdss_mdp_memory_retention_ctrl(
+ MEM_RETAIN_OFF,
+ PERIPH_RETAIN_OFF);
}
+ mdata->mem_retain = true;
if (mdata->en_svs_high)
mdss_mdp_config_cx_voltage(mdata, false);
regulator_disable(mdata->fs);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 0f0df2256f74..e26b3843d7b0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -1618,8 +1618,8 @@ static bool __multirect_validate_rects(struct mdp_input_layer **layers,
/* resolution related validation */
if (mdss_rect_overlap_check(&dst[0], &dst[1])) {
pr_err("multirect dst overlap is not allowed. input: %d,%d,%d,%d paired %d,%d,%d,%d\n",
- dst[0].x, dst[0].y, dst[0].w, dst[0].y,
- dst[1].x, dst[1].y, dst[1].w, dst[1].y);
+ dst[0].x, dst[0].y, dst[0].w, dst[0].h,
+ dst[1].x, dst[1].y, dst[1].w, dst[1].h);
return false;
}
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 463d26643dde..be0491195263 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -54,6 +54,7 @@ struct panel_id {
#define DP_PANEL 12 /* LVDS */
#define DSC_PPS_LEN 128
+#define INTF_EVENT_STR(x) #x
static inline const char *mdss_panel2str(u32 panel)
{
@@ -270,6 +271,78 @@ enum mdss_intf_events {
MDSS_EVENT_MAX,
};
+/**
+ * mdss_panel_intf_event_to_string() - converts interface event enum to string
+ * @event: interface event to be converted to string representation
+ */
+static inline char *mdss_panel_intf_event_to_string(int event)
+{
+ switch (event) {
+ case MDSS_EVENT_RESET:
+ return INTF_EVENT_STR(MDSS_EVENT_RESET);
+ case MDSS_EVENT_LINK_READY:
+ return INTF_EVENT_STR(MDSS_EVENT_LINK_READY);
+ case MDSS_EVENT_UNBLANK:
+ return INTF_EVENT_STR(MDSS_EVENT_UNBLANK);
+ case MDSS_EVENT_PANEL_ON:
+ return INTF_EVENT_STR(MDSS_EVENT_PANEL_ON);
+ case MDSS_EVENT_POST_PANEL_ON:
+ return INTF_EVENT_STR(MDSS_EVENT_POST_PANEL_ON);
+ case MDSS_EVENT_BLANK:
+ return INTF_EVENT_STR(MDSS_EVENT_BLANK);
+ case MDSS_EVENT_PANEL_OFF:
+ return INTF_EVENT_STR(MDSS_EVENT_PANEL_OFF);
+ case MDSS_EVENT_CLOSE:
+ return INTF_EVENT_STR(MDSS_EVENT_CLOSE);
+ case MDSS_EVENT_SUSPEND:
+ return INTF_EVENT_STR(MDSS_EVENT_SUSPEND);
+ case MDSS_EVENT_RESUME:
+ return INTF_EVENT_STR(MDSS_EVENT_RESUME);
+ case MDSS_EVENT_CHECK_PARAMS:
+ return INTF_EVENT_STR(MDSS_EVENT_CHECK_PARAMS);
+ case MDSS_EVENT_CONT_SPLASH_BEGIN:
+ return INTF_EVENT_STR(MDSS_EVENT_CONT_SPLASH_BEGIN);
+ case MDSS_EVENT_CONT_SPLASH_FINISH:
+ return INTF_EVENT_STR(MDSS_EVENT_CONT_SPLASH_FINISH);
+ case MDSS_EVENT_PANEL_UPDATE_FPS:
+ return INTF_EVENT_STR(MDSS_EVENT_PANEL_UPDATE_FPS);
+ case MDSS_EVENT_FB_REGISTERED:
+ return INTF_EVENT_STR(MDSS_EVENT_FB_REGISTERED);
+ case MDSS_EVENT_PANEL_CLK_CTRL:
+ return INTF_EVENT_STR(MDSS_EVENT_PANEL_CLK_CTRL);
+ case MDSS_EVENT_DSI_CMDLIST_KOFF:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_CMDLIST_KOFF);
+ case MDSS_EVENT_ENABLE_PARTIAL_ROI:
+ return INTF_EVENT_STR(MDSS_EVENT_ENABLE_PARTIAL_ROI);
+ case MDSS_EVENT_DSC_PPS_SEND:
+ return INTF_EVENT_STR(MDSS_EVENT_DSC_PPS_SEND);
+ case MDSS_EVENT_DSI_STREAM_SIZE:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_STREAM_SIZE);
+ case MDSS_EVENT_DSI_UPDATE_PANEL_DATA:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_UPDATE_PANEL_DATA);
+ case MDSS_EVENT_REGISTER_RECOVERY_HANDLER:
+ return INTF_EVENT_STR(MDSS_EVENT_REGISTER_RECOVERY_HANDLER);
+ case MDSS_EVENT_REGISTER_MDP_CALLBACK:
+ return INTF_EVENT_STR(MDSS_EVENT_REGISTER_MDP_CALLBACK);
+ case MDSS_EVENT_DSI_PANEL_STATUS:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_PANEL_STATUS);
+ case MDSS_EVENT_DSI_DYNAMIC_SWITCH:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_DYNAMIC_SWITCH);
+ case MDSS_EVENT_DSI_RECONFIG_CMD:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_RECONFIG_CMD);
+ case MDSS_EVENT_DSI_RESET_WRITE_PTR:
+ return INTF_EVENT_STR(MDSS_EVENT_DSI_RESET_WRITE_PTR);
+ case MDSS_EVENT_PANEL_TIMING_SWITCH:
+ return INTF_EVENT_STR(MDSS_EVENT_PANEL_TIMING_SWITCH);
+ case MDSS_EVENT_DEEP_COLOR:
+ return INTF_EVENT_STR(MDSS_EVENT_DEEP_COLOR);
+ case MDSS_EVENT_DISABLE_PANEL:
+ return INTF_EVENT_STR(MDSS_EVENT_DISABLE_PANEL);
+ default:
+ return "unknown";
+ }
+}
+
struct lcd_panel_info {
u32 h_back_porch;
u32 h_front_porch;
diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h
index b80ea0c31597..251b7e314238 100644
--- a/include/dt-bindings/clock/msm-clocks-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-cobalt.h
@@ -447,7 +447,9 @@
#define clk_dsi0pll_pclk_src 0x5efd85d4
#define clk_dsi0pll_pclk_src_mux 0x84b14663
#define clk_dsi0pll_post_bit_div 0xf46dcf27
-#define clk_dsi0pll_post_vco_div 0x8ee956ff
+#define clk_dsi0pll_post_vco_mux 0xfaf9bd1f
+#define clk_dsi0pll_post_vco_div1 0xabb50b2a
+#define clk_dsi0pll_post_vco_div4 0xbe51c091
#define clk_dsi0pll_bitclk_src 0x36c3c437
#define clk_dsi0pll_vco_clk 0x15940d40
@@ -457,7 +459,9 @@
#define clk_dsi1pll_pclk_src 0xeddcd80e
#define clk_dsi1pll_pclk_src_mux 0x3651feb3
#define clk_dsi1pll_post_bit_div 0x712f0260
-#define clk_dsi1pll_post_vco_div 0x623e04de
+#define clk_dsi1pll_post_vco_mux 0xc6a90d20
+#define clk_dsi1pll_post_vco_div1 0x6f47ca7d
+#define clk_dsi1pll_post_vco_div4 0x90628974
#define clk_dsi1pll_bitclk_src 0x13ab045b
#define clk_dsi1pll_vco_clk 0x99797b50
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 218cd875ee5a..a8ccecf5799a 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -198,6 +198,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_FLASH_CURRENT_MAX,
POWER_SUPPLY_PROP_UPDATE_NOW,
POWER_SUPPLY_PROP_ESR_COUNT,
+ POWER_SUPPLY_PROP_BUCK_FREQ,
POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE,
POWER_SUPPLY_PROP_CHARGE_DONE,
POWER_SUPPLY_PROP_FLASH_ACTIVE,
@@ -222,6 +223,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_CHARGER_TEMP,
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
POWER_SUPPLY_PROP_PARALLEL_DISABLE,
+ POWER_SUPPLY_PROP_PARALLEL_PERCENT,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6362b864e2b1..98ae45174a40 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3189,8 +3189,8 @@ retry:
}
}
p->last_cpu_selected_ts = sched_ktime_clock();
- sbc_flag |= env.sbc_best_cluster_flag;
out:
+ sbc_flag |= env.sbc_best_cluster_flag;
rcu_read_unlock();
trace_sched_task_load(p, sched_boost(), env.reason, env.sync,
env.need_idle, sbc_flag, target);
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index c0996e24e3d6..30c23df444d6 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -358,6 +358,15 @@ enum {
ASRC_MAX,
};
+enum {
+ CONV_88P2K_TO_384K,
+ CONV_96K_TO_352P8K,
+ CONV_352P8K_TO_384K,
+ CONV_384K_TO_352P8K,
+ CONV_384K_TO_384K,
+ CONV_96K_TO_384K,
+};
+
static struct afe_param_slimbus_slave_port_cfg tavil_slimbus_slave_port_cfg = {
.minor_version = 1,
.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
@@ -577,7 +586,7 @@ struct tavil_priv {
/* num of slim ports required */
struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
/* Port values for Rx and Tx codec_dai */
- unsigned int rx_port_value;
+ unsigned int rx_port_value[WCD934X_RX_MAX];
unsigned int tx_port_value;
struct wcd9xxx_resmgr_v2 *resmgr;
@@ -616,6 +625,7 @@ struct tavil_priv {
int native_clk_users;
/* ASRC users count */
int asrc_users[ASRC_MAX];
+ int asrc_output_mode[ASRC_MAX];
/* Main path clock users count */
int main_clk_users[WCD934X_NUM_INTERPOLATORS];
struct tavil_dsd_config *dsd_config;
@@ -1298,7 +1308,8 @@ static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
- ucontrol->value.enumerated.item[0] = tavil_p->rx_port_value;
+ ucontrol->value.enumerated.item[0] =
+ tavil_p->rx_port_value[widget->shift];
return 0;
}
@@ -1313,17 +1324,20 @@ static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct snd_soc_dapm_update *update = NULL;
+ unsigned int rx_port_value;
u32 port_id = widget->shift;
+ tavil_p->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
+ rx_port_value = tavil_p->rx_port_value[port_id];
+
mutex_lock(&tavil_p->codec_mutex);
- tavil_p->rx_port_value = ucontrol->value.enumerated.item[0];
dev_dbg(codec->dev, "%s: wname %s cname %s value %u shift %d item %ld\n",
__func__, widget->name, ucontrol->id.name,
- tavil_p->rx_port_value, widget->shift,
+ rx_port_value, widget->shift,
ucontrol->value.integer.value[0]);
/* value need to match the Virtual port and AIF number */
- switch (tavil_p->rx_port_value) {
+ switch (rx_port_value) {
case 0:
list_del_init(&core->rx_chs[port_id].list);
break;
@@ -1372,13 +1386,13 @@ static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
&tavil_p->dai[AIF4_PB].wcd9xxx_ch_list);
break;
default:
- dev_err(codec->dev, "Unknown AIF %d\n", tavil_p->rx_port_value);
+ dev_err(codec->dev, "Unknown AIF %d\n", rx_port_value);
goto err;
}
rtn:
mutex_unlock(&tavil_p->codec_mutex);
snd_soc_dapm_mux_update_power(widget->dapm, kcontrol,
- tavil_p->rx_port_value, e, update);
+ rx_port_value, e, update);
return 0;
err:
@@ -2592,6 +2606,45 @@ done:
return rc;
}
+static int tavil_get_asrc_mode(struct tavil_priv *tavil, int asrc,
+ u8 main_sr, u8 mix_sr)
+{
+ u8 asrc_output_mode;
+ int asrc_mode = CONV_88P2K_TO_384K;
+
+ if ((asrc < 0) || (asrc >= ASRC_MAX))
+ return 0;
+
+ asrc_output_mode = tavil->asrc_output_mode[asrc];
+
+ if (asrc_output_mode) {
+ /*
+ * If Mix sample rate is < 96KHz, use 96K to 352.8K
+ * conversion, or else use 384K to 352.8K conversion
+ */
+ if (mix_sr < 5)
+ asrc_mode = CONV_96K_TO_352P8K;
+ else
+ asrc_mode = CONV_384K_TO_352P8K;
+ } else {
+ /* Integer main and Fractional mix path */
+ if (main_sr < 8 && mix_sr > 9) {
+ asrc_mode = CONV_352P8K_TO_384K;
+ } else if (main_sr > 8 && mix_sr < 8) {
+ /* Fractional main and Integer mix path */
+ if (mix_sr < 5)
+ asrc_mode = CONV_96K_TO_352P8K;
+ else
+ asrc_mode = CONV_384K_TO_352P8K;
+ } else if (main_sr < 8 && mix_sr < 8) {
+ /* Integer main and Integer mix path */
+ asrc_mode = CONV_96K_TO_384K;
+ }
+ }
+
+ return asrc_mode;
+}
+
static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
int asrc_in, int event)
{
@@ -2658,19 +2711,8 @@ static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
main_sr = snd_soc_read(codec, ctl_reg) & 0x0F;
mix_ctl_reg = ctl_reg + 5;
mix_sr = snd_soc_read(codec, mix_ctl_reg) & 0x0F;
- /* Integer main and Fractional mix path */
- if (main_sr < 8 && mix_sr > 9) {
- asrc_mode = 2;
- } else if (main_sr > 8 && mix_sr < 8) {
- /* Fractional main and Integer mix path */
- if (mix_sr < 5)
- asrc_mode = 1;
- else
- asrc_mode = 3;
- } else if (main_sr < 8 && mix_sr < 8) {
- /* Integer main and Integer mix path */
- asrc_mode = 5;
- }
+ asrc_mode = tavil_get_asrc_mode(tavil, asrc,
+ main_sr, mix_sr);
dev_dbg(codec->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
__func__, main_sr, mix_sr, asrc_mode);
snd_soc_update_bits(codec, asrc_ctl, 0x07, asrc_mode);
@@ -4752,6 +4794,46 @@ static int tavil_compander_put(struct snd_kcontrol *kcontrol,
return 0;
}
+static int tavil_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ int index = -EINVAL;
+
+ if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
+ index = ASRC0;
+ if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
+ index = ASRC1;
+
+ if (tavil && (index >= 0) && (index < ASRC_MAX))
+ tavil->asrc_output_mode[index] =
+ ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
+static int tavil_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ int val = 0;
+ int index = -EINVAL;
+
+ if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
+ index = ASRC0;
+ if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
+ index = ASRC1;
+
+ if (tavil && (index >= 0) && (index < ASRC_MAX))
+ val = tavil->asrc_output_mode[index];
+
+ ucontrol->value.integer.value[0] = val;
+
+ return 0;
+}
+
static int tavil_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -5146,6 +5228,10 @@ static const char * const hph_idle_detect_text[] = {
"OFF", "ON"
};
+static const char * const asrc_mode_text[] = {
+ "INT", "FRAC"
+};
+
static const char * const tavil_ear_pa_gain_text[] = {
"G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
"G_0_DB", "G_M2P5_DB", "UNDEFINED", "G_M12_DB"
@@ -5161,6 +5247,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_spkr_pa_gain_enum,
tavil_ear_spkr_pa_gain_text);
static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
+static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, WCD934X_CDC_TX0_TX_PATH_CFG0, 5,
cf_text);
static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, WCD934X_CDC_TX1_TX_PATH_CFG0, 5,
@@ -5395,6 +5482,11 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = {
SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
tavil_compander_get, tavil_compander_put),
+ SOC_ENUM_EXT("ASRC0 Output Mode", asrc_mode_enum,
+ tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
+ SOC_ENUM_EXT("ASRC1 Output Mode", asrc_mode_enum,
+ tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
+
SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
tavil_hph_idle_detect_get, tavil_hph_idle_detect_put),
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index a2bd3be62175..524f737360d8 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -3180,8 +3180,10 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
* Send speaker configuration only for WSA8810.
* Defalut configuration is for WSA8815.
*/
+ pr_debug("%s: Number of aux devices: %d\n",
+ __func__, rtd->card->num_aux_devs);
if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
- if (rtd_aux && rtd_aux->component)
+ if (rtd->card->num_aux_devs && rtd_aux && rtd_aux->component)
if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
!strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1);
@@ -3200,7 +3202,7 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
pdata->codec_root = entry;
tavil_codec_info_create_codec_entry(pdata->codec_root, codec);
} else {
- if (rtd_aux && rtd_aux->component)
+ if (rtd->card->num_aux_devs && rtd_aux && rtd_aux->component)
if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
!strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);