diff options
96 files changed, 2843 insertions, 886 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt index 8365762e520f..4808d1dda5c1 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt @@ -11,6 +11,8 @@ Main node: Required properties: - compatible : Should be "qcom,qpnp-flash-led-v2" - reg : Base address and size for flash LED modules +- qcom,pmic-revid : phandle of PMIC revid module. This is used to + identify the PMIC subtype. Optional properties: - interrupts : Specifies the interrupts associated with flash-led. @@ -32,6 +34,18 @@ Optional properties: - qcom,vph-droop-debounce-us : Integer property to specify VPH droop debounce time. It is only used if qcom,vph-droop-det is specified. Valid values are 0, 8, 16 and 26. Unit is uS. +- qcom,led1n2-iclamp-low-ma : Integer property to specify current clamp low + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led1n2-iclamp-mid-ma : Integer property to specify current clamp mid + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led3-iclamp-low-ma : Integer property to specify current clamp low + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. +- qcom,led3-iclamp-mid-ma : Integer property to specify current clamp mid + level for mitigation. Unit is mA. Allowed + values are same as under qcom,max-current. - qcom,vled-max-uv : Integer property for flash current predictive mitigation. Default value is 3500000 uV. - qcom,ibatt-ocp-threshold-ua : Integer property for flash current predictive mitigation. @@ -64,12 +78,47 @@ Optional properties: - qcom,thermal-derate-current : Array of currrent limits for thermal mitigation. Required if qcom,thermal-derate-en is specified. Unit is mA. Format is qcom,thermal-derate-current = <OTST1_LIMIT, OTST2_LIMIT, OTST3_LIMIT>. +- qcom,otst-ramp-back-up-dis : Boolean property to disable current ramp + backup after thermal derate trigger is + deasserted. +- qcom,thermal-derate-slow : Integer property to specify slow ramping + down thermal rate. Unit is in uS. Allowed + values are: 128, 256, 512, 1024, 2048, 4096, + 8192 and 314592. +- qcom,thermal-derate-fast : Integer property to specify fast ramping + down thermal rate. Unit is in uS. Allowed + values are: 32, 64, 96, 128, 256, 384 and + 512. +- qcom,thermal-debounce : Integer property to specify thermal debounce + time. It is only used if qcom,thermal-derate-en + is specified. Unit is in uS. Allowed values + are: 0, 16, 32, 64. +- qcom,thermal-hysteresis : Integer property to specify thermal derating + hysteresis. Unit is in deciDegC. It is only + used if qcom,thermal-derate-en is specified. + Allowed values are: + 0, 15, 30, 45 for pmicobalt. + 0, 20, 40, 60 for pm2falcon. +- qcom,thermal-thrsh1 : Integer property to specify OTST1 threshold + for thermal mitigation. Unit is in Celsius. + Accepted values are: + 85, 79, 73, 67, 109, 103, 97, 91. +- qcom,thermal-thrsh2 : Integer property to specify OTST2 threshold + for thermal mitigation. Unit is in Celsius. + Accepted values are: + 110, 104, 98, 92, 134, 128, 122, 116. +- qcom,thermal-thrsh3 : Integer property to specify OTST3 threshold + for thermal mitigation. Unit is in Celsius. + Accepted values are: + 125, 119, 113, 107, 149, 143, 137, 131. - qcom,hw-strobe-option : Integer type to specify hardware strobe option. Based on the specified value, additional GPIO configuration may be required to provide strobing support. Supported values are: 0: Flash strobe is used for LED1, LED2, LED3 1: Flash strobe is used for LED1, LED2 and GPIO10 is used for LED3 2: Flash strobe is used for LED1; GPIO9 is used for LED2; GPIO10 is used for LED3 +- switchX-supply : phandle of the regulator that needs to be used + as a supply for flash switch_X device. Child node: Contains settings for each individual LED. Each LED channel needs a flash node and torch node for itself, and an individual switch node to serve as an overall switch. @@ -126,15 +175,6 @@ Optional properties: be edge triggered. Otherwise, it is level triggered. - qcom,hw-strobe-active-low : Boolean property to select strobe signal polarity. If defined, hw-strobe signal polarity is set to active-low, else it is active-high. -- reg<n> : reg<n> (<n> represents number. e.g. 0,1,2,..) subnode is to add support for - multiple power sources. This subnode should only be specified for switch nodes. - Required property inside regulator node: - - regulator-name : Name of the regulator which has to be used for this - switch node. - Optional property inside regulator node: - - max-voltage-uv : This specifies max voltage of regulator. Some switch - or boost regulator does not need this property. - Example: qcom,leds@d300 { compatible = "qcom,qpnp-flash-led-v2"; @@ -160,6 +200,7 @@ Example: qcom,hdrm-auto-mode; qcom,isc-delay = <192>; + switch0-supply = <&pmicobalt_bob>; pmi8998_flash0: qcom,flash_0 { label = "flash"; @@ -254,10 +295,6 @@ Example: qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; pmi8998_switch1: qcom,led_switch_1 { @@ -266,10 +303,6 @@ Example: qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; }; diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt index ebbcfe5b2fd0..07f3fd274658 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt @@ -25,7 +25,11 @@ Optional properties for WLED: - linux,default-trigger : trigger for the backlight. default is NONE. - qcom,fdbk-output : string feedback current output for wled module. The accepted values are "wled1", "wled2", "wled3", "wled4" and "auto". default is "auto". -- qcom,vref-mv : maximum reference voltage in mv. default is 350. +- qcom,vref-uv : maximum reference voltage in uV. + For pmi8994/8952/8996, supported values are from 300000 to 675000 + with a step size of 25000, the default value is 350000. + For pmicobalt/pm2falcon, supported values are from 60000 to 397500 + with a step size of 22500, the default value is 127500. - qcom,switch-freq-khz : switch frequency in khz. default is 800. - qcom,ovp-mv : Over voltage protection threshold in mV. Default is 29500. Supported values are: @@ -94,7 +98,7 @@ Example: linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <350000>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29500>; qcom,ilim-ma = <980>; diff --git a/Documentation/devicetree/bindings/media/video/msm-cpp.txt b/Documentation/devicetree/bindings/media/video/msm-cpp.txt index 52abf409cb65..ade5fbe8cbd7 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cpp.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cpp.txt @@ -26,6 +26,8 @@ Required properties: and reset lines used by this controller. - reset-names: reset signal name strings sorted in the same order as the resets property. +- qcom,src-clock-rates = This is an array which holds clock rates for cpp src + clocks. The maximum size for the array is 10. Required properties of the child node: - qcom,stripe-base = Base offset of stripes in cpp payload. @@ -107,6 +109,8 @@ Example: <0x24 0x10000000>, <0x28 0x10000000>, <0x2C 0x10000000>; + qcom,src-clock-rates = <100000000 200000000 384000000 404000000 + 480000000 576000000 600000000>; qcom,cpp-fw-payload-info { qcom,stripe-base = <553>; qcom,plane-base = <481>; diff --git a/Documentation/devicetree/bindings/pci/msm_pcie.txt b/Documentation/devicetree/bindings/pci/msm_pcie.txt index 21b6d99424c0..a50e0c2b2c35 100644 --- a/Documentation/devicetree/bindings/pci/msm_pcie.txt +++ b/Documentation/devicetree/bindings/pci/msm_pcie.txt @@ -93,6 +93,8 @@ Optional Properties: and assign for each endpoint. - qcom,ep-latency: The time (unit: ms) to wait for the PCIe endpoint to become stable after power on, before de-assert the PERST to the endpoint. + - qcom,wr-halt-size: With base 2, this exponent determines the size of the + data that PCIe core will halt on for each write transaction. - qcom,cpl-timeout: Completion timeout value. This value specifies the time range which the root complex will send out a completion packet if there is no response from the endpoint. @@ -270,6 +272,7 @@ Example: qcom,smmu-exist; qcom,smmu-sid-base = <0x1480>; qcom,ep-latency = <100>; + qcom,wr-halt-size = <0xa>; /* 1KB */ qcom,cpl-timeout = <0x2>; iommus = <&anoc0_smmu>; diff --git a/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi b/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi index 76126c21c43a..8bf98d83d381 100644 --- a/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi +++ b/arch/arm/boot/dts/qcom/batterydata-qrd-skuk-4v4-3000mah.dtsi @@ -18,44 +18,44 @@ qcom,qrd_msmcobalt_skuk_3000mah { qcom,battery-type = "qrd_msmcobalt_skuk_300mah"; qcom,checksum = <0x0F19>; qcom,fg-profile-data = [ - 05 B2 1F 6F - FC A3 0A 6E - FD DB 1D 8C - 1D AE 12 C2 - 23 00 18 7E - 52 B4 45 8D - 00 00 00 55 - 00 00 00 0F - C5 92 00 00 - CA A0 CD 95 - 00 0C 00 1F - EC C3 F2 56 - F3 27 06 7B - 12 FF 01 02 - 3A 21 DA 1C - 40 40 09 1C - 00 05 00 07 - 05 B4 1F AC - FC EF 0A 57 - 00 2E 1D 6A - 14 BA 0B 12 - 22 DC 19 40 - 53 03 45 79 - 00 00 00 53 - 00 00 00 0E - CC 05 00 00 - CA 24 BB 3A - 00 00 00 1C - EC C3 F2 56 - F2 A2 06 A6 - 01 C7 06 96 - 1A CF EA 8B - 33 08 33 BA - 00 00 10 07 - 46 66 0C 3A - 00 19 00 1C - FA 0A 01 98 - 00 00 00 FF + 6F 1F B2 05 + 6E 0A A3 FC + 8C 1D DB FD + C2 12 AE 1D + 7E 18 00 23 + 8D 45 B4 52 + 55 00 00 00 + 0F 00 00 00 + 00 00 92 C5 + 95 CD A0 CA + 1F 00 0C 00 + 56 F2 C3 EC + 7B 06 27 F3 + 02 01 FF 12 + 1C DA 21 3A + 1C 09 40 40 + 07 00 05 00 + AC 1F B4 05 + 57 0A EF FC + 6A 1D 2E 00 + 12 0B BA 14 + 40 19 DC 22 + 79 45 03 53 + 53 00 00 00 + 0E 00 00 00 + 00 00 05 CC + 3A BB 24 CA + 1C 00 00 00 + 56 F2 C3 EC + A6 06 A2 F2 + 96 06 C7 01 + 8B EA CF 1A + BA 33 08 33 + 07 10 00 00 + 3A 0C 66 46 + 1C 00 19 00 + 98 01 0A FA + FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi index 41589d02f6fc..79883db10d06 100644 --- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -234,7 +234,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <127500>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29600>; qcom,ilim-ma = <970>; @@ -269,6 +269,7 @@ qcom,thermal-derate-en; qcom,thermal-derate-current = <200 500 1000>; qcom,isc-delay = <192>; + qcom,pmic-revid = <&pm2falcon_revid>; status = "disabled"; pm2falcon_flash0: qcom,flash_0 { @@ -357,10 +358,6 @@ qcom,led-name = "led:switch_0"; qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmfalcon_bob"; - max-voltage-uv = <3600000>; - }; }; pm2falcon_switch1: qcom,led_switch_1 { @@ -368,10 +365,6 @@ qcom,led-name = "led:switch_1"; qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmfalcon_bob"; - max-voltage-uv = <3600000>; - }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi index c46c0963ff56..c820d213165b 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi @@ -523,7 +523,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <350000>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29500>; qcom,ilim-ma = <980>; diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index b88b0e28c948..62db712e6979 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -598,7 +598,7 @@ linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; - qcom,vref-mv = <350>; + qcom,vref-uv = <127500>; qcom,switch-freq-khz = <800>; qcom,ovp-mv = <29600>; qcom,ilim-ma = <970>; @@ -657,6 +657,7 @@ qcom,thermal-derate-en; qcom,thermal-derate-current = <200 500 1000>; qcom,isc-delay = <192>; + qcom,pmic-revid = <&pmicobalt_revid>; pmicobalt_flash0: qcom,flash_0 { label = "flash"; @@ -744,10 +745,6 @@ qcom,led-name = "led:switch_0"; qcom,led-mask = <3>; qcom,default-led-trigger = "switch0_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; pmicobalt_switch1: qcom,led_switch_1 { @@ -755,10 +752,6 @@ qcom,led-name = "led:switch_1"; qcom,led-mask = <4>; qcom,default-led-trigger = "switch1_trigger"; - reg0 { - regulator-name = "pmicobalt_bob"; - max-voltage-uv = <3600000>; - }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi index 27e537c9c702..6a0061e206ca 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi @@ -422,6 +422,8 @@ qcom,msm-bus-vector-dyn-vote; resets = <&clock_mmss CAMSS_MICRO_BCR>; reset-names = "micro_iface_reset"; + qcom,src-clock-rates = <100000000 200000000 576000000 + 600000000>; qcom,cpp-fw-payload-info { qcom,stripe-base = <790>; qcom,plane-base = <715>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi index 32f616e1dc7a..ffb42576ffd3 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi @@ -3088,3 +3088,48 @@ #include "msmcobalt-mdss-pll.dtsi" #include "msmcobalt-blsp.dtsi" #include "msmcobalt-audio.dtsi" + + +/* GPU overrides */ +&msm_gpu { + qcom,initial-pwrlevel = <0>; + + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <332000000>; + qcom,bus-freq = <7>; + qcom,bus-min = <6>; + qcom,bus-max = <8>; + }; + + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <251000000>; + qcom,bus-freq = <4>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <171000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <1>; + qcom,bus-max = <4>; + }; + + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <27000000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi index 75de2d70028a..0cd6d0ab1f1d 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi @@ -269,7 +269,7 @@ batt_i@3 { reg = <3>; qcom,channel = <3>; - qcom,scale = <20000000>; + qcom,scale = <(-20000000)>; }; batt_v@4 { diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi index 1db1fc5cec46..15756d13d2e0 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi @@ -194,3 +194,19 @@ qcom,mdss-dsi-bl-max-level = <4095>; qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; + +/{ + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + + #include "batterydata-qrd-skuk-4v4-3000mah.dtsi" + }; +}; + +&pmicobalt_fg { + qcom,battery-data = <&qrd_batterydata>; +}; + +&pmicobalt_haptics { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi index 5b8585a33de6..71fd5cc1383f 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi @@ -128,3 +128,19 @@ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft"; }; }; + +/{ + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <15>; + + #include "batterydata-qrd-skuk-4v4-3000mah.dtsi" + }; +}; + +&pmicobalt_fg { + qcom,battery-data = <&qrd_batterydata>; +}; + +&pmicobalt_haptics { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi index 1ba5905bcc36..32cf1663cf43 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi @@ -1101,6 +1101,8 @@ qcom,cpr-aging-ref-corner = <6>; qcom,cpr-aging-ro-scaling-factor = <2950>; qcom,allow-aging-voltage-adjustment = <0>; + qcom,allow-aging-open-loop-voltage-adjustment = + <1>; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi index fcc4d6d8ee2d..a81287c36266 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-camera.dtsi @@ -116,5 +116,76 @@ 0 256000000 0>; status = "ok"; }; + + qcom,cpp@ca04000 { + cell-index = <0>; + compatible = "qcom,cpp"; + reg = <0xca04000 0x100>, + <0xca80000 0x3000>, + <0xca18000 0x3000>, + <0xc8c36d4 0x4>; + reg-names = "cpp", "cpp_vbif", "cpp_hw", "camss_cpp"; + interrupts = <0 294 0>; + interrupt-names = "cpp"; + smmu-vdd-supply = <&gdsc_bimc_smmu>; + camss-vdd-supply = <&gdsc_camss_top>; + vdd-supply = <&gdsc_cpp>; + qcom,vdd-names = "smmu-vdd", "camss-vdd", "vdd"; + clocks = <&clock_gcc clk_mmssnoc_axi_clk>, + <&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>, + <&clock_mmss clk_mmss_camss_micro_ahb_clk>, + <&clock_mmss clk_mmss_bimc_smmu_axi_clk>, + <&clock_mmss clk_mmss_camss_cpp_vbif_ahb_clk>; + 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 200000000 0 0 0 0 0>; + qcom,min-clock-rate = <200000000>; + qcom,bus-master = <1>; + qcom,vbif-qos-setting = <0x20 0x10000000>, + <0x24 0x10000000>, + <0x28 0x10000000>, + <0x2C 0x10000000>; + status = "ok"; + qcom,msm-bus,name = "msm_camera_cpp"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <106 512 0 0>, + <106 512 0 0>; + qcom,msm-bus-vector-dyn-vote; + resets = <&clock_mmss CAMSS_MICRO_BCR>; + reset-names = "micro_iface_reset"; + qcom,src-clock-rates = <100000000 200000000 384000000 404000000 + 480000000 576000000 600000000>; + qcom,cpp-fw-payload-info { + qcom,stripe-base = <790>; + qcom,plane-base = <715>; + qcom,stripe-size = <63>; + qcom,plane-size = <25>; + qcom,fe-ptr-off = <11>; + qcom,we-ptr-off = <23>; + qcom,ref-fe-ptr-off = <17>; + qcom,ref-we-ptr-off = <36>; + qcom,we-meta-ptr-off = <42>; + qcom,fe-mmu-pf-ptr-off = <7>; + qcom,ref-fe-mmu-pf-ptr-off = <10>; + qcom,we-mmu-pf-ptr-off = <13>; + qcom,dup-we-mmu-pf-ptr-off = <18>; + qcom,ref-we-mmu-pf-ptr-off = <23>; + qcom,set-group-buffer-len = <135>; + qcom,dup-frame-indicator-off = <70>; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi index 02cc86212301..46ed1f219970 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi @@ -750,7 +750,7 @@ &msm_gpu { /* Updated chip ID */ qcom,chipid = <0x05040001>; - qcom,initial-pwrlevel = <5>; + qcom,initial-pwrlevel = <0>; qcom,gpu-pwrlevels { #address-cells = <1>; @@ -760,61 +760,29 @@ qcom,gpu-pwrlevel@0 { reg = <0>; - qcom,gpu-freq = <670000000>; - qcom,bus-freq = <12>; - qcom,bus-min = <11>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@1 { - reg = <1>; - qcom,gpu-freq = <596000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@2 { - reg = <2>; - qcom,gpu-freq = <515000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - qcom,gpu-pwrlevel@3 { - reg = <3>; - qcom,gpu-freq = <414000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <8>; - qcom,bus-max = <11>; - }; - - qcom,gpu-pwrlevel@4 { - reg = <4>; qcom,gpu-freq = <342000000>; qcom,bus-freq = <8>; qcom,bus-min = <5>; qcom,bus-max = <9>; }; - qcom,gpu-pwrlevel@5 { - reg = <5>; + qcom,gpu-pwrlevel@1 { + reg = <1>; qcom,gpu-freq = <257000000>; qcom,bus-freq = <5>; qcom,bus-min = <3>; qcom,bus-max = <8>; }; - qcom,gpu-pwrlevel@6 { - reg = <6>; + qcom,gpu-pwrlevel@2 { + reg = <2>; qcom,gpu-freq = <180000000>; qcom,bus-freq = <3>; qcom,bus-min = <1>; qcom,bus-max = <5>; }; - qcom,gpu-pwrlevel@7 { - reg = <7>; + qcom,gpu-pwrlevel@3 { + reg = <3>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,bus-min = <0>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts index 78e810b816c9..581e9fef1aeb 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-qrd-skuk.dts @@ -19,5 +19,5 @@ / { model = "Qualcomm Technologies, Inc. MSM COBALT V2 SKUK"; compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd"; - qcom,board-id = <0x01000b 0x80>; + qcom,board-id = <0x01000b 0x10>; }; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts index 69a5419503ac..e5ad123f52a7 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts @@ -21,3 +21,194 @@ compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd"; qcom,board-id = <0x03000b 0x80>; }; + +&slim_aud { + tasha_codec { + /delete-property/cdc-vdd-buck-supply; + /delete-property/cdc-buck-sido-supply; + /delete-property/cdc-vdd-tx-h-supply; + /delete-property/cdc-vdd-rx-h-supply; + /delete-property/cdc-vddpx-1-supply; + }; + + tavil_codec { + /delete-property/cdc-vdd-buck-supply; + /delete-property/cdc-buck-sido-supply; + /delete-property/cdc-vdd-tx-h-supply; + /delete-property/cdc-vdd-rx-h-supply; + /delete-property/cdc-vddpx-1-supply; + }; +}; + +&clock_gcc { + /delete-property/vdd_dig-supply; + /delete-property/vdd_dig_ao-supply; +}; + +&clock_mmss { + /delete-property/vdd_dig-supply; + /delete-property/vdd_mmsscc_mx-supply; +}; + +&clock_gpu { + /delete-property/vdd_dig-supply; +}; + +&clock_gfx { + /delete-property/vdd_mx-supply; + /delete-property/vdd_gpu_mx-supply; +}; + +&pcie0 { + /delete-property/vreg-1.8-supply; + /delete-property/vreg-0.9-supply; + /delete-property/vreg-cx-supply; +}; + +&qusb_phy0 { + /delete-property/vdd-supply; + /delete-property/vdda18-supply; + /delete-property/vdda33-supply; +}; + +&ssphy { + /delete-property/vdd-supply; + /delete-property/core-supply; +}; + +&usb3 { + /delete-property/extcon; +}; + +&mdss_dsi { + /delete-property/vdda-1p2-supply; + /delete-property/vdda-0p9-supply; +}; + +&mdss_dsi0 { + /delete-property/wqhd-vddio-supply; + /delete-property/lab-supply; + /delete-property/ibb-supply; +}; + +&mdss_dsi1 { + /delete-property/wqhd-vddio-supply; + /delete-property/lab-supply; + /delete-property/ibb-supply; +}; + +&mdss_hdmi_pll { + /delete-property/vdda-pll-supply; + /delete-property/vdda-phy-supply; +}; + +&mdss_dp_ctrl { + /delete-property/vdda-1p2-supply; + /delete-property/vdda-0p9-supply; + /delete-property/qcom,dp-usbpd-detection; +}; + +&apc0_cpr { + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-hw-closed-loop; + /delete-property/qcom,cpr-aging-ref-voltage; +}; + +&apc0_pwrcl_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&apc1_cpr { + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-hw-closed-loop; + /delete-property/qcom,cpr-aging-ref-voltage; +}; + +&apc1_perfcl_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&gfx_cpr { + reg = <0x05061000 0x4000>, + <0x00784000 0x1000>; + reg-names = "cpr_ctrl", "fuse_base"; + + /* disable aging and closed-loop */ + /delete-property/vdd-supply; + /delete-property/qcom,cpr-enable; + /delete-property/qcom,cpr-aging-ref-voltage; + /delete-property/qcom,cpr-aging-allowed-reg-mask; + /delete-property/qcom,cpr-aging-allowed-reg-value; +}; + +&gfx_vreg { + /delete-property/qcom,cpr-aging-max-voltage-adjustment; + /delete-property/qcom,cpr-aging-ref-corner; + /delete-property/qcom,cpr-aging-ro-scaling-factor; + /delete-property/qcom,allow-aging-voltage-adjustment; + /delete-property/qcom,allow-aging-open-loop-voltage-adjustment; +}; + +&clock_audio { + /delete-property/qcom,audio-ref-clk-gpio; +}; + +&soc { + /delete-node/qcom,csid@ca30000; + /delete-node/qcom,csid@ca30400; + /delete-node/qcom,csid@ca30800; + /delete-node/qcom,csid@ca30c00; + + /delete-node/qcom,lpass@17300000; + /delete-node/qcom,mss@4080000; + /delete-node/qcom,spss@1d00000; + /delete-node/qcom,bcl; + /delete-node/qcom,msm-thermal; + /delete-node/qcom,ssc@5c00000; + /delete-node/qcom,icnss@18800000; + /delete-node/qcom,wil6210; + /delete-node/qcom,rpm-smd; + /delete-node/qcom,spmi@800f000; + + + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-glink"; + qcom,glink-edge = "rpm"; + rpm-channel-name = "rpm_requests"; + }; + + spmi_bus: qcom,spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x800f000 0x1000>, + <0x8400000 0x1000000>, + <0x9400000 0x1000000>, + <0xa400000 0x220000>, + <0x800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + }; +}; + +#include "msm-pmfalcon.dtsi" +#include "msm-pm2falcon.dtsi" +#include "msmfalcon-regulator.dtsi" diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi index fbb1e56b7090..b257281466a9 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi @@ -20,9 +20,6 @@ }; &ufsphy1 { - vdda-phy-supply = <&pmcobalt_l1>; - vdda-pll-supply = <&pmcobalt_l2>; - vddp-ref-clk-supply = <&pmcobalt_l26>; vdda-phy-max-microamp = <51400>; vdda-pll-max-microamp = <14600>; vddp-ref-clk-max-microamp = <100>; @@ -33,9 +30,6 @@ &ufs1 { vdd-hba-supply = <&gdsc_ufs>; vdd-hba-fixed-regulator; - vcc-supply = <&pmcobalt_l20>; - vccq-supply = <&pmcobalt_l26>; - vccq2-supply = <&pmcobalt_s4>; vcc-max-microamp = <750000>; vccq-max-microamp = <560000>; vccq2-max-microamp = <750000>; @@ -71,11 +65,9 @@ }; &sdhc_2 { - vdd-supply = <&pmcobalt_l21>; qcom,vdd-voltage-level = <2950000 2960000>; qcom,vdd-current-level = <200 800000>; - vdd-io-supply = <&pmcobalt_l13>; qcom,vdd-io-voltage-level = <1808000 2960000>; qcom,vdd-io-current-level = <200 22000>; @@ -91,15 +83,3 @@ status = "ok"; }; - -/{ - qrd_batterydata: qcom,battery-data { - qcom,batt-id-range-pct = <15>; - - #include "batterydata-qrd-skuk-4v4-3000mah.dtsi" - }; -}; - -&pmicobalt_fg { - qcom,battery-data = <&qrd_batterydata>; -}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi index f09f4d8b3adb..93b586df5640 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi @@ -205,6 +205,24 @@ }; }; +&devfreq_memlat_0 { + qcom,core-dev-table = + < 595200 3143 >, + < 1324800 4173 >, + < 1555200 5859 >, + < 1747200 5859 >, + < 1900800 7759 >; +}; + +&devfreq_memlat_4 { + qcom,core-dev-table = + < 576000 3143 >, + < 1132800 4173 >, + < 1344000 5859 >, + < 1728000 7759 >, + < 1958400 11863 >, + < 2208000 13763 >; +}; &clock_gcc { compatible = "qcom,gcc-cobalt-v2"; }; @@ -227,7 +245,8 @@ < 414000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >, < 515000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >, < 596000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >, - < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >; + < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >, + < 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >; qcom,gfxfreq-mx-speedbin0 = < 0 0 >, < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >, @@ -236,7 +255,8 @@ < 414000000 RPM_SMD_REGULATOR_LEVEL_SVS >, < 515000000 RPM_SMD_REGULATOR_LEVEL_NOM >, < 596000000 RPM_SMD_REGULATOR_LEVEL_NOM >, - < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >; + < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >, + < 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >; }; &mdss_mdp { @@ -438,43 +458,43 @@ qcom,cpr-open-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, /* Speed bin 1 */ - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <40000 24000 0 30000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>, - <25000 9000 (-15000) 15000>; + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <40000 24000 0 30000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>, + <25000 9000 (-15000) 15000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, /* Speed bin 1 */ - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <20000 26000 0 30000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>, - <5000 11000 (-15000) 15000>; + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + <20000 26000 0 30000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>, + < 5000 11000 (-15000) 15000>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; @@ -483,8 +503,8 @@ qcom,cpr-aging-ref-corner = <22 22>; qcom,cpr-aging-ro-scaling-factor = <1620>; qcom,allow-aging-voltage-adjustment = - <0 0 0 1 1 1 1 1>, - <0 0 0 1 1 1 1 1>; + <0 0 0 0 1 1 1 1>, + <0 0 0 0 1 1 1 1>; }; &apc1_cpr { @@ -601,19 +621,19 @@ qcom,cpr-open-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <(-7000) (-15000) (-15000) 37000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, <(-7000) (-15000) (-15000) 37000>, <(-7000) (-15000) (-15000) 37000>, <(-7000) (-15000) (-15000) 37000>, <(-7000) (-15000) (-15000) 37000>, /* Speed bin 1 */ - <8000 0 0 52000>, - <8000 0 0 52000>, - <8000 0 0 52000>, - <(-7000) (-15000) (-15000) 37000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, + < 8000 0 0 52000>, <(-7000) (-15000) (-15000) 37000>, <(-7000) (-15000) (-15000) 37000>, <(-7000) (-15000) (-15000) 37000>, @@ -621,19 +641,19 @@ qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <(-15000) (-15000) (-15000) 35000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, <(-15000) (-15000) (-15000) 35000>, <(-15000) (-15000) (-15000) 35000>, <(-15000) (-15000) (-15000) 35000>, <(-15000) (-15000) (-15000) 35000>, /* Speed bin 1 */ - <0 0 0 50000>, - <0 0 0 50000>, - <0 0 0 50000>, - <(-15000) (-15000) (-15000) 35000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, + < 0 0 0 50000>, <(-15000) (-15000) (-15000) 35000>, <(-15000) (-15000) (-15000) 35000>, <(-15000) (-15000) (-15000) 35000>, @@ -646,8 +666,8 @@ qcom,cpr-aging-ref-corner = <30 26>; qcom,cpr-aging-ro-scaling-factor = <1700>; qcom,allow-aging-voltage-adjustment = - <0 0 0 1 1 1 1 1>, - <0 0 0 1 1 1 1 1>; + <0 0 0 0 1 1 1 1>, + <0 0 0 0 1 1 1 1>; }; &pm8005_s1 { @@ -728,7 +748,7 @@ qcom,cpr-open-loop-voltage-fuse-adjustment = < 60000 0 0 0>, < 60000 0 0 0>, - < 45000 (-15000) (-15000) (-15000)>, + < 60000 0 0 0>, < 45000 (-15000) (-15000) (-15000)>, < 45000 (-15000) (-15000) (-15000)>, < 45000 (-15000) (-15000) (-15000)>, @@ -740,8 +760,8 @@ 0 29000 11000 0>, < 90000 38000 28000 8000 0 29000 11000 0>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, < 75000 23000 13000 (-7000) (-15000) 14000 (-4000) (-15000)>, < 75000 23000 13000 (-7000) @@ -765,7 +785,7 @@ qcom,cpr-aging-max-voltage-adjustment = <15000>; qcom,cpr-aging-ref-corner = <8>; qcom,cpr-aging-ro-scaling-factor = <1620>; - qcom,allow-aging-voltage-adjustment = <0 0 1 1 1 1 1 1>; + qcom,allow-aging-voltage-adjustment = <0 0 0 1 1 1 1 1>; }; &qusb_phy0 { @@ -909,13 +929,6 @@ qcom,gpu-pwrlevel@6 { reg = <6>; - qcom,gpu-freq = <180000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <1>; - qcom,bus-max = <5>; - }; - qcom,gpu-pwrlevel@7 { - reg = <7>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,bus-min = <0>; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi index f17be7570742..a8655c2e88a0 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi @@ -25,6 +25,7 @@ qcom,firmware-name = "venus"; qcom,never-unload-fw; qcom,sw-power-collapse; + qcom,max-secure-instances = <5>; qcom,debug-timeout; qcom,reg-presets = <0x80124 0x00000003>, diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 328ae458eb06..9b0d3f674032 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -611,7 +611,7 @@ < 13763 /* 1804 MHz */ >; }; - qcom,arm-memlat-mon-0 { + devfreq_memlat_0: qcom,arm-memlat-mon-0 { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>; qcom,target-dev = <&memlat_cpu0>; @@ -622,7 +622,7 @@ < 1881600 5859 >; }; - qcom,arm-memlat-mon-4 { + devfreq_memlat_4: qcom,arm-memlat-mon-4 { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>; qcom,target-dev = <&memlat_cpu4>; @@ -1568,6 +1568,10 @@ qcom,vreg-cx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_BINNING RPM_SMD_REGULATOR_LEVEL_SVS 0>; + qcom,l1-supported; + qcom,l1ss-supported; + qcom,aux-clk-sync; + qcom,ep-latency = <10>; qcom,ep-wakeirq; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi index 75cf4de97672..cfe968a7310a 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi @@ -142,6 +142,7 @@ }; rpm-regulator-ldoa2 { + status = "okay"; pmfalcon_l2: regulator-l2 { regulator-min-microvolt = <950000>; regulator-max-microvolt = <1010000>; @@ -150,6 +151,7 @@ }; rpm-regulator-ldoa3 { + status = "okay"; pmfalcon_l3: regulator-l3 { regulator-min-microvolt = <950000>; regulator-max-microvolt = <1010000>; @@ -159,6 +161,7 @@ /* TODO: remove if ADRASTEA CX/MX not voted from APPS */ rpm-regulator-ldoa5 { + status = "okay"; pmfalcon_l5: regulator-l5 { regulator-min-microvolt = <525000>; regulator-max-microvolt = <950000>; @@ -167,6 +170,7 @@ }; rpm-regulator-ldoa6 { + status = "okay"; pmfalcon_l6: regulator-l6 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1370000>; @@ -175,6 +179,7 @@ }; rpm-regulator-ldoa7 { + status = "okay"; pmfalcon_l7: regulator-l7 { regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; @@ -183,6 +188,7 @@ }; rpm-regulator-ldoa8 { + status = "okay"; pmfalcon_l8: regulator-l8 { regulator-min-microvolt = <1750000>; regulator-max-microvolt = <1900000>; @@ -191,6 +197,7 @@ }; rpm-regulator-ldoa9 { + status = "okay"; pmfalcon_l9: regulator-l9 { regulator-min-microvolt = <1750000>; regulator-max-microvolt = <1900000>; @@ -199,6 +206,7 @@ }; rpm-regulator-ldoa10 { + status = "okay"; pmfalcon_l10: regulator-l10 { regulator-min-microvolt = <1780000>; regulator-max-microvolt = <1950000>; @@ -207,6 +215,7 @@ }; rpm-regulator-ldoa11 { + status = "okay"; pmfalcon_l11: regulator-l11 { regulator-min-microvolt = <1780000>; regulator-max-microvolt = <1950000>; @@ -215,6 +224,7 @@ }; rpm-regulator-ldoa12 { + status = "okay"; pmfalcon_l12: regulator-l12 { regulator-min-microvolt = <1780000>; regulator-max-microvolt = <1950000>; @@ -223,6 +233,7 @@ }; rpm-regulator-ldoa13 { + status = "okay"; pmfalcon_l13: regulator-l13 { regulator-min-microvolt = <1780000>; regulator-max-microvolt = <1950000>; @@ -231,6 +242,7 @@ }; rpm-regulator-ldoa14 { + status = "okay"; pmfalcon_l14: regulator-l14 { regulator-min-microvolt = <1710000>; regulator-max-microvolt = <1900000>; @@ -239,6 +251,7 @@ }; rpm-regulator-ldoa15 { + status = "okay"; pmfalcon_l15: regulator-l15 { regulator-min-microvolt = <1650000>; regulator-max-microvolt = <2950000>; @@ -247,6 +260,7 @@ }; rpm-regulator-ldoa17 { + status = "okay"; pmfalcon_l17: regulator-l17 { regulator-min-microvolt = <1650000>; regulator-max-microvolt = <2950000>; @@ -255,6 +269,7 @@ }; rpm-regulator-ldoa19 { + status = "okay"; pmfalcon_l19: regulator-l19 { regulator-min-microvolt = <3200000>; regulator-max-microvolt = <3400000>; @@ -263,6 +278,7 @@ }; rpm-regulator-ldob1 { + status = "okay"; pm2falcon_l1: regulator-l1 { regulator-min-microvolt = <800000>; regulator-max-microvolt = <925000>; @@ -271,6 +287,7 @@ }; rpm-regulator-ldob2 { + status = "okay"; pm2falcon_l2: regulator-l2 { regulator-min-microvolt = <350000>; regulator-max-microvolt = <3100000>; @@ -279,6 +296,7 @@ }; rpm-regulator-ldob3 { + status = "okay"; pm2falcon_l3: regulator-l3 { regulator-min-microvolt = <1710000>; regulator-max-microvolt = <3600000>; @@ -287,6 +305,7 @@ }; rpm-regulator-ldob4 { + status = "okay"; pm2falcon_l4: regulator-l4 { regulator-min-microvolt = <1700000>; regulator-max-microvolt = <2950000>; @@ -295,6 +314,7 @@ }; rpm-regulator-ldob5 { + status = "okay"; pm2falcon_l5: regulator-l5 { regulator-min-microvolt = <1721000>; regulator-max-microvolt = <3600000>; @@ -303,6 +323,7 @@ }; rpm-regulator-ldob6 { + status = "okay"; pm2falcon_l6: regulator-l6 { regulator-min-microvolt = <1700000>; regulator-max-microvolt = <3300000>; @@ -311,6 +332,7 @@ }; rpm-regulator-ldob7 { + status = "okay"; pm2falcon_l7: regulator-l7 { regulator-min-microvolt = <2700000>; regulator-max-microvolt = <3125000>; @@ -319,6 +341,7 @@ }; rpm-regulator-ldob8 { + status = "okay"; pm2falcon_l8: regulator-l8 { regulator-min-microvolt = <3200000>; regulator-max-microvolt = <3400000>; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts index 9d76681bab2d..c94ba0df3e6e 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts @@ -57,3 +57,8 @@ status = "ok"; }; + +&clock_gcc { + compatible = "qcom,dummycc"; + clock-output-names = "gcc_clocks"; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index b035bc3c0f14..473270d6e87d 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -345,6 +345,31 @@ clock-names = "core", "iface"; }; + slim_aud: slim@151c0000 { + cell-index = <1>; + compatible = "qcom,slim-ngd"; + reg = <0x151c0000 0x2c000>, + <0x15180000 0x2e000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 163 0>, <0 164 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x7e0000>; + qcom,ea-pc = <0x260>; + status = "disabled"; + }; + + slim_qca: slim@15240000 { + cell-index = <3>; + compatible = "qcom,slim-ngd"; + reg = <0x15240000 0x2c000>, + <0x15200000 0x24000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 291 0>, <0 292 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x1800>; + status = "disabled"; + }; + timer@17920000 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts index d3c62dbf99f2..0317c35d1f44 100644 --- a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts @@ -27,3 +27,8 @@ pinctrl-names = "default"; pinctrl-0 = <&uart_console_active>; }; + +&clock_gcc { + compatible = "qcom,dummycc"; + clock-output-names = "gcc_clocks"; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index 49fa1ac7f192..06f296a49113 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -246,6 +246,32 @@ qcom,pipe-attr-ee; }; + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + tsens: tsens@10ad000 { compatible = "qcom,msmtriton-tsens"; reg = <0x10ad000 0x2000>; @@ -505,6 +531,13 @@ qcom,xprt = "smem"; }; + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-glink"; + qcom,glink-edge = "rpm"; + rpm-channel-name = "rpm_requests"; + rpm-standalone; + }; + qcom,ipc_router { compatible = "qcom,ipc_router"; qcom,node-id = <1>; diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index f843a98ee130..f8743e760054 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -27,6 +27,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 5f8b02904d49..520a60c46106 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -32,6 +32,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index c1c0ae9da001..6249b604466b 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -29,6 +29,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index df65a3db12f5..3990bece1dd1 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -35,6 +35,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 2f7dfa9216b1..15ca50859eca 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -34,6 +34,7 @@ CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_REGULAR=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y diff --git a/drivers/clk/msm/clock-gpu-cobalt.c b/drivers/clk/msm/clock-gpu-cobalt.c index 9d93351a083e..7cec9be1f42c 100644 --- a/drivers/clk/msm/clock-gpu-cobalt.c +++ b/drivers/clk/msm/clock-gpu-cobalt.c @@ -173,6 +173,7 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = { F_SLEW( 515000000, 1030000000, gpu_pll0_pll_out_even, 1, 0, 0), F_SLEW( 596000000, 1192000000, gpu_pll0_pll_out_even, 1, 0, 0), F_SLEW( 670000000, 1340000000, gpu_pll0_pll_out_even, 1, 0, 0), + F_SLEW( 710000000, 1420000000, gpu_pll0_pll_out_even, 1, 0, 0), F_END }; @@ -611,7 +612,7 @@ static void msm_gfxcc_hamster_fixup(void) static void msm_gfxcc_cobalt_v2_fixup(void) { - gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1340000500; + gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500; gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_v2; } diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c index f23f32f7e37a..93bbcf5d40f5 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-cobalt-util.c @@ -275,7 +275,7 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0); + QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x12); MDSS_PLL_REG_W(dp_res->pll_base, diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 1501c5da4a6c..085b9acfb9d5 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -221,8 +221,6 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, if (pll->flags & SUPPORTS_FSM_MODE) clk_alpha_set_fsm_mode(pll); - - pll->inited = true; } static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw) @@ -288,12 +286,6 @@ static int clk_alpha_pll_enable(struct clk_hw *hw) u32 val, mask, off; off = pll->offset; - - if (unlikely(!pll->inited)) { - clk_alpha_pll_configure(pll, pll->clkr.regmap, - pll->config); - } - mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL; ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val); if (ret) diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 425cf3afef9e..9b1d3ee61cac 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -39,7 +39,6 @@ struct pll_vco { struct clk_alpha_pll { u32 offset; struct pll_config *config; - bool inited; const struct pll_vco *vco_table; size_t num_vco; diff --git a/drivers/cpufreq/qcom-cpufreq.c b/drivers/cpufreq/qcom-cpufreq.c index 82861b1dbe46..2aa7b783f276 100644 --- a/drivers/cpufreq/qcom-cpufreq.c +++ b/drivers/cpufreq/qcom-cpufreq.c @@ -3,7 +3,7 @@ * MSM architecture cpufreq driver * * Copyright (C) 2007 Google, Inc. - * Copyright (c) 2007-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. * Author: Mike A. Chan <mikechan@google.com> * * This software is licensed under the terms of the GNU General Public @@ -320,7 +320,7 @@ static struct cpufreq_driver msm_cpufreq_driver = { static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, char *tbl_name, int cpu) { - int ret, nf, i; + int ret, nf, i, j; u32 *data; struct cpufreq_frequency_table *ftbl; @@ -344,6 +344,7 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, if (!ftbl) return ERR_PTR(-ENOMEM); + j = 0; for (i = 0; i < nf; i++) { unsigned long f; @@ -353,29 +354,20 @@ static struct cpufreq_frequency_table *cpufreq_parse_dt(struct device *dev, f /= 1000; /* - * Check if this is the last feasible frequency in the table. + * Don't repeat frequencies if they round up to the same clock + * frequency. * - * The table listing frequencies higher than what the HW can - * support is not an error since the table might be shared - * across CPUs in different speed bins. It's also not - * sufficient to check if the rounded rate is lower than the - * requested rate as it doesn't cover the following example: - * - * Table lists: 2.2 GHz and 2.5 GHz. - * Rounded rate returns: 2.2 GHz and 2.3 GHz. - * - * In this case, we can CPUfreq to use 2.2 GHz and 2.3 GHz - * instead of rejecting the 2.5 GHz table entry. */ - if (i > 0 && f <= ftbl[i-1].frequency) - break; + if (j > 0 && f <= ftbl[j - 1].frequency) + continue; - ftbl[i].driver_data = i; - ftbl[i].frequency = f; + ftbl[j].driver_data = j; + ftbl[j].frequency = f; + j++; } - ftbl[i].driver_data = i; - ftbl[i].frequency = CPUFREQ_TABLE_END; + ftbl[j].driver_data = j; + ftbl[j].frequency = CPUFREQ_TABLE_END; devm_kfree(dev, data); diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h index 436b6949c414..ef2861ca96dd 100644 --- a/drivers/gpu/msm/a5xx_reg.h +++ b/drivers/gpu/msm/a5xx_reg.h @@ -893,6 +893,11 @@ #define A5XX_GDPM_INT_MASK 0xB811 #define A5XX_GPMU_BEC_ENABLE 0xB9A0 +/* ISENSE registers */ +#define A5XX_GPU_CS_DECIMAL_ALIGN 0xC16A +#define A5XX_GPU_CS_SENSOR_PARAM_CORE_1 0xC126 +#define A5XX_GPU_CS_SENSOR_PARAM_CORE_2 0xC127 +#define A5XX_GPU_CS_SW_OV_FUSE_EN 0xC168 #define A5XX_GPU_CS_SENSOR_GENERAL_STATUS 0xC41A #define A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_0 0xC41D #define A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_2 0xC41F @@ -900,5 +905,6 @@ #define A5XX_GPU_CS_ENABLE_REG 0xC520 #define A5XX_GPU_CS_AMP_CALIBRATION_CONTROL1 0xC557 #define A5XX_GPU_CS_AMP_CALIBRATION_DONE 0xC565 +#define A5XX_GPU_CS_ENDPOINT_CALIBRATION_DONE 0xC556 #endif /* _A5XX_REG_H */ diff --git a/drivers/gpu/msm/adreno_a4xx_preempt.c b/drivers/gpu/msm/adreno_a4xx_preempt.c index 4087ac60c89e..ef837dc4b7ea 100644 --- a/drivers/gpu/msm/adreno_a4xx_preempt.c +++ b/drivers/gpu/msm/adreno_a4xx_preempt.c @@ -146,6 +146,8 @@ static int a4xx_submit_preempt_token(struct adreno_ringbuffer *rb, &ptname, PT_INFO_OFFSET(current_rb_ptname)); pt = kgsl_mmu_get_pt_from_ptname(&(device->mmu), ptname); + if (IS_ERR_OR_NULL(pt)) + return (pt == NULL) ? -ENOENT : PTR_ERR(pt); /* set the ringbuffer for incoming RB */ pt_switch_sizedwords = adreno_iommu_set_pt_generate_cmds(incoming_rb, diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index f652e955b07c..5dad7fd3bf4d 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -431,6 +431,43 @@ static int _poll_gdsc_status(struct adreno_device *adreno_dev, return 0; } +static void a5xx_restore_isense_regs(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + unsigned int reg, i, ramp = GPMU_ISENSE_SAVE; + static unsigned int isense_regs[6] = {0xFFFF}, isense_reg_addr[] = { + A5XX_GPU_CS_DECIMAL_ALIGN, + A5XX_GPU_CS_SENSOR_PARAM_CORE_1, + A5XX_GPU_CS_SENSOR_PARAM_CORE_2, + A5XX_GPU_CS_SW_OV_FUSE_EN, + A5XX_GPU_CS_ENDPOINT_CALIBRATION_DONE, + A5XX_GPMU_TEMP_SENSOR_CONFIG}; + + if (!adreno_is_a540(adreno_dev)) + return; + + /* read signature */ + kgsl_regread(device, ramp++, ®); + + if (reg == 0xBABEFACE) { + /* store memory locations in buffer */ + for (i = 0; i < ARRAY_SIZE(isense_regs); i++) + kgsl_regread(device, ramp + i, isense_regs + i); + + /* clear signature */ + kgsl_regwrite(device, GPMU_ISENSE_SAVE, 0x0); + } + + /* if we never stored memory locations - do nothing */ + if (isense_regs[0] == 0xFFFF) + return; + + /* restore registers from memory */ + for (i = 0; i < ARRAY_SIZE(isense_reg_addr); i++) + kgsl_regwrite(device, isense_reg_addr[i], isense_regs[i]); + +} + /* * a5xx_regulator_enable() - Enable any necessary HW regulators * @adreno_dev: The adreno device pointer @@ -480,6 +517,7 @@ static int a5xx_regulator_enable(struct adreno_device *adreno_dev) kgsl_regrmw(device, A5XX_GPMU_GPMU_SP_CLOCK_CONTROL, CNTL_IP_CLK_ENABLE, 1); + a5xx_restore_isense_regs(adreno_dev); return 0; } diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h index e424e7a9f228..08fd16a83f30 100644 --- a/drivers/gpu/msm/adreno_a5xx.h +++ b/drivers/gpu/msm/adreno_a5xx.h @@ -228,6 +228,7 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on); #define LM_SEQUENCE_ID 1 #define MAX_SEQUENCE_ID 3 +#define GPMU_ISENSE_SAVE (A5XX_GPMU_DATA_RAM_BASE + 200/4) /* LM defaults */ #define LM_DEFAULT_LIMIT 6000 #define A530_DEFAULT_LEAKAGE 0x004E001A diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 72895c18119f..618e9e9a33a3 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -574,12 +574,11 @@ int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset, void *addr = (memdesc->hostptr) ? memdesc->hostptr : (void *) memdesc->useraddr; - /* Make sure that size is non-zero */ - if (!size) + if (size == 0 || size > UINT_MAX) return -EINVAL; - /* Make sure that the offset + size isn't bigger than we can handle */ - if ((offset + size) > ULONG_MAX) + /* Make sure that the offset + size does not overflow */ + if ((offset + size < offset) || (offset + size < size)) return -ERANGE; /* Make sure the offset + size do not overflow the address */ diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index ebb49230d4d7..e08de7a808eb 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -165,7 +165,8 @@ #define FG_ADC_RR_CHG_THRESHOLD_SCALE 4 #define FG_ADC_RR_VOLT_INPUT_FACTOR 8 -#define FG_ADC_RR_CURR_INPUT_FACTOR 2 +#define FG_ADC_RR_CURR_INPUT_FACTOR 2000 +#define FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL 1886 #define FG_ADC_SCALE_MILLI_FACTOR 1000 #define FG_ADC_KELVINMIL_CELSIUSMIL 273150 @@ -323,12 +324,20 @@ static int rradc_post_process_curr(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 adc_code, int *result_ua) { - int64_t ua = 0; + int64_t ua = 0, scale = 0; - /* 0.5 V/A; 2.5V ADC full scale */ - ua = ((int64_t)adc_code * FG_ADC_RR_CURR_INPUT_FACTOR); + if (!prop) + return -EINVAL; + + if (prop->channel == RR_ADC_USBIN_I) + scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL; + else + scale = FG_ADC_RR_CURR_INPUT_FACTOR; + + /* scale * V/A; 2.5V ADC full scale */ + ua = ((int64_t)adc_code * scale); ua *= (FG_ADC_RR_FS_VOLTAGE_MV * FG_ADC_SCALE_MILLI_FACTOR); - ua = div64_s64(ua, FG_MAX_ADC_READINGS); + ua = div64_s64(ua, (FG_MAX_ADC_READINGS * 1000)); *result_ua = ua; return 0; diff --git a/drivers/iio/adc/qcom-tadc.c b/drivers/iio/adc/qcom-tadc.c index 3cc2694f9a03..4a56847a43e7 100644 --- a/drivers/iio/adc/qcom-tadc.c +++ b/drivers/iio/adc/qcom-tadc.c @@ -398,7 +398,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) } for (i = 0; i < TADC_NUM_CH; i++) - adc[i] = val[i * 2] | val[i * 2 + 1] << BITS_PER_BYTE; + adc[i] = (s16)(val[i * 2] | (u16)val[i * 2 + 1] << 8); return jiffies_to_msecs(timeout - timeleft); } diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fda10abae58a..eac6d07e6097 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -528,6 +528,8 @@ static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu); static bool arm_smmu_is_slave_side_secure(struct arm_smmu_domain *smmu_domain); static bool arm_smmu_has_secure_vmid(struct arm_smmu_domain *smmu_domain); +static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain); + static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom) { return container_of(dom, struct arm_smmu_domain, domain); @@ -1604,7 +1606,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, /* SCTLR */ reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_EAE_SBOP; - if (!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) || + if ((!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) && + !(smmu_domain->attributes & (1 << DOMAIN_ATTR_EARLY_MAP))) || !stage1) reg |= SCTLR_M; if (stage1) @@ -1651,7 +1654,7 @@ static void arm_smmu_secure_domain_unlock(struct arm_smmu_domain *smmu_domain) static unsigned long arm_smmu_pgtbl_lock(struct arm_smmu_domain *smmu_domain) { - unsigned long flags; + unsigned long flags = 0; if (arm_smmu_is_slave_side_secure(smmu_domain)) mutex_lock(&smmu_domain->pgtbl_mutex_lock); @@ -3043,6 +3046,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, ret = 0; break; } + case DOMAIN_ATTR_EARLY_MAP: + *((int *)data) = !!(smmu_domain->attributes + & (1 << DOMAIN_ATTR_EARLY_MAP)); + ret = 0; + break; default: ret = -ENODEV; break; @@ -3148,6 +3156,24 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST; ret = 0; break; + case DOMAIN_ATTR_EARLY_MAP: { + int early_map = *((int *)data); + + ret = 0; + if (early_map) { + smmu_domain->attributes |= + 1 << DOMAIN_ATTR_EARLY_MAP; + } else { + if (smmu_domain->smmu) + ret = arm_smmu_enable_s1_translations( + smmu_domain); + + if (!ret) + smmu_domain->attributes &= + ~(1 << DOMAIN_ATTR_EARLY_MAP); + } + break; + } default: ret = -ENODEV; break; @@ -3158,6 +3184,28 @@ out_unlock: return ret; } + +static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain) +{ + struct arm_smmu_cfg *cfg = &smmu_domain->cfg; + struct arm_smmu_device *smmu = smmu_domain->smmu; + void __iomem *cb_base; + u32 reg; + int ret; + + cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); + ret = arm_smmu_enable_clocks(smmu); + if (ret) + return ret; + + reg = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR); + reg |= SCTLR_M; + + writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR); + arm_smmu_disable_clocks(smmu); + return ret; +} + static int arm_smmu_dma_supported(struct iommu_domain *domain, struct device *dev, u64 mask) { diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index 3b54fd4a77e6..7b0c1ae5a48d 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -70,6 +70,8 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) return "DOMAIN_ATTR_S1_BYPASS"; case DOMAIN_ATTR_FAST: return "DOMAIN_ATTR_FAST"; + case DOMAIN_ATTR_EARLY_MAP: + return "DOMAIN_ATTR_EARLY_MAP"; default: return "Unknown attr!"; } diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 51fd79f101c8..674ca6161af9 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -10,6 +10,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "flashv2: %s: " fmt, __func__ + #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> @@ -27,6 +29,8 @@ #include <linux/regulator/consumer.h> #include <linux/leds-qpnp-flash.h> #include <linux/leds-qpnp-flash-v2.h> +#include <linux/qpnp/qpnp-revid.h> +#include <linux/log2.h> #include "leds.h" #define FLASH_LED_REG_LED_STATUS1(base) (base + 0x08) @@ -43,24 +47,28 @@ #define FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(base) (base + 0x50) #define FLASH_LED_REG_WARMUP_DELAY(base) (base + 0x51) #define FLASH_LED_REG_ISC_DELAY(base) (base + 0x52) +#define FLASH_LED_REG_THERMAL_RMP_DN_RATE(base) (base + 0x55) #define FLASH_LED_REG_THERMAL_THRSH1(base) (base + 0x56) #define FLASH_LED_REG_THERMAL_THRSH2(base) (base + 0x57) #define FLASH_LED_REG_THERMAL_THRSH3(base) (base + 0x58) +#define FLASH_LED_REG_THERMAL_HYSTERESIS(base) (base + 0x59) +#define FLASH_LED_REG_THERMAL_DEBOUNCE(base) (base + 0x5A) #define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61) #define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62) #define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67) +#define FLASH_LED_REG_LED1N2_ICLAMP_LOW(base) (base + 0x68) +#define FLASH_LED_REG_LED1N2_ICLAMP_MID(base) (base + 0x69) +#define FLASH_LED_REG_LED3_ICLAMP_LOW(base) (base + 0x6A) +#define FLASH_LED_REG_LED3_ICLAMP_MID(base) (base + 0x6B) #define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E) #define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F) #define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70) #define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76) -#define FLASH_LED_HDRM_MODE_PRGM_MASK GENMASK(7, 0) #define FLASH_LED_HDRM_VOL_MASK GENMASK(7, 4) #define FLASH_LED_CURRENT_MASK GENMASK(6, 0) #define FLASH_LED_ENABLE_MASK GENMASK(2, 0) #define FLASH_HW_STROBE_MASK GENMASK(2, 0) -#define FLASH_LED_SAFETY_TMR_MASK GENMASK(7, 0) -#define FLASH_LED_INT_RT_STS_MASK GENMASK(7, 0) #define FLASH_LED_ISC_WARMUP_DELAY_MASK GENMASK(1, 0) #define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0) #define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0) @@ -70,13 +78,19 @@ #define FLASH_LED_LMH_LEVEL_MASK GENMASK(1, 0) #define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4) #define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0) +#define FLASH_LED_THERMAL_HYSTERESIS_MASK GENMASK(1, 0) +#define FLASH_LED_THERMAL_DEBOUNCE_MASK GENMASK(1, 0) #define FLASH_LED_THERMAL_THRSH_MASK GENMASK(2, 0) -#define FLASH_LED_THERMAL_OTST_MASK GENMASK(2, 0) #define FLASH_LED_MOD_CTRL_MASK BIT(7) #define FLASH_LED_HW_SW_STROBE_SEL_BIT BIT(2) #define FLASH_LED_VPH_DROOP_FAULT_MASK BIT(4) #define FLASH_LED_LMH_MITIGATION_EN_MASK BIT(0) #define FLASH_LED_CHGR_MITIGATION_EN_MASK BIT(4) +#define THERMAL_OTST1_RAMP_CTRL_MASK BIT(7) +#define THERMAL_OTST1_RAMP_CTRL_SHIFT 7 +#define THERMAL_DERATE_SLOW_SHIFT 4 +#define THERMAL_DERATE_SLOW_MASK GENMASK(6, 4) +#define THERMAL_DERATE_FAST_MASK GENMASK(2, 0) #define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8) #define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25) @@ -85,17 +99,24 @@ #define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100) #define CURRENT_MA_TO_REG_VAL(curr_ma, ires_ua) ((curr_ma * 1000) / ires_ua - 1) #define SAFETY_TMR_TO_REG_VAL(duration_ms) ((duration_ms / 10) - 1) +#define THERMAL_HYST_TEMP_TO_VAL(val, divisor) (val / divisor) #define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6 #define FLASH_LED_WARMUP_DELAY_DEFAULT 2 #define FLASH_LED_ISC_DELAY_DEFAULT 3 #define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2 +#define FLASH_LED_VPH_DROOP_HYST_SHIFT 4 #define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2 #define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5 -#define FLASH_LED_VPH_DROOP_DEBOUNCE_MAX 3 -#define FLASH_LED_VPH_DROOP_HYST_MAX 3 +#define FLASH_LED_DEBOUNCE_MAX 3 +#define FLASH_LED_HYSTERESIS_MAX 3 #define FLASH_LED_VPH_DROOP_THRESH_MAX 7 +#define THERMAL_DERATE_SLOW_MAX 314592 +#define THERMAL_DERATE_FAST_MAX 512 +#define THERMAL_DEBOUNCE_TIME_MAX 64 +#define THERMAL_DERATE_HYSTERESIS_MAX 3 #define FLASH_LED_THERMAL_THRSH_MIN 3 +#define FLASH_LED_THERMAL_THRSH_MAX 7 #define FLASH_LED_THERMAL_OTST_LEVELS 3 #define FLASH_LED_VLED_MAX_DEFAULT_UV 3500000 #define FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA 4500000 @@ -173,18 +194,12 @@ struct flash_node_data { bool led_on; }; -struct flash_regulator_data { - struct regulator *vreg; - const char *reg_name; - u32 max_volt_uv; -}; struct flash_switch_data { struct platform_device *pdev; + struct regulator *vreg; struct led_classdev cdev; - struct flash_regulator_data *reg_data; int led_mask; - int num_regulators; bool regulator_on; bool enabled; }; @@ -193,28 +208,41 @@ struct flash_switch_data { * Flash LED configuration read from device tree */ struct flash_led_platform_data { - int *thermal_derate_current; - int all_ramp_up_done_irq; - int all_ramp_down_done_irq; - int led_fault_irq; - int ibatt_ocp_threshold_ua; - int vled_max_uv; - int rpara_uohm; - int lmh_rbatt_threshold_uohm; - int lmh_ocv_threshold_uv; - u8 isc_delay; - u8 warmup_delay; - u8 current_derate_en_cfg; - u8 vph_droop_threshold; - u8 vph_droop_hysteresis; - u8 vph_droop_debounce; - u8 lmh_mitigation_sel; - u8 chgr_mitigation_sel; - u8 lmh_level; - u8 iled_thrsh_val; - u8 hw_strobe_option; - bool hdrm_auto_mode_en; - bool thermal_derate_en; + struct pmic_revid_data *pmic_rev_id; + int *thermal_derate_current; + int all_ramp_up_done_irq; + int all_ramp_down_done_irq; + int led_fault_irq; + int ibatt_ocp_threshold_ua; + int vled_max_uv; + int rpara_uohm; + int lmh_rbatt_threshold_uohm; + int lmh_ocv_threshold_uv; + int thermal_derate_slow; + int thermal_derate_fast; + int thermal_hysteresis; + int thermal_debounce; + int thermal_thrsh1; + int thermal_thrsh2; + int thermal_thrsh3; + u32 led1n2_iclamp_low_ma; + u32 led1n2_iclamp_mid_ma; + u32 led3_iclamp_low_ma; + u32 led3_iclamp_mid_ma; + u8 isc_delay; + u8 warmup_delay; + u8 current_derate_en_cfg; + u8 vph_droop_threshold; + u8 vph_droop_hysteresis; + u8 vph_droop_debounce; + u8 lmh_mitigation_sel; + u8 chgr_mitigation_sel; + u8 lmh_level; + u8 iled_thrsh_val; + u8 hw_strobe_option; + bool hdrm_auto_mode_en; + bool thermal_derate_en; + bool otst_ramp_bkup_en; }; /* @@ -237,22 +265,54 @@ struct qpnp_flash_led { bool trigger_chgr; }; -static int -qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data) +static int thermal_derate_slow_table[] = { + 128, 256, 512, 1024, 2048, 4096, 8192, 314592, +}; + +static int thermal_derate_fast_table[] = { + 32, 64, 96, 128, 256, 384, 512, +}; + +static int otst1_threshold_table[] = { + 85, 79, 73, 67, 109, 103, 97, 91, +}; + +static int otst2_threshold_table[] = { + 110, 104, 98, 92, 134, 128, 122, 116, +}; + +static int otst3_threshold_table[] = { + 125, 119, 113, 107, 149, 143, 137, 131, +}; + +static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data) { int rc; uint val; rc = regmap_read(led->regmap, addr, &val); - if (rc < 0) - dev_err(&led->pdev->dev, "Unable to read from 0x%04X rc = %d\n", - addr, rc); - else - dev_dbg(&led->pdev->dev, "Read 0x%02X from addr 0x%04X\n", - val, addr); + if (rc < 0) { + pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc); + return rc; + } + pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr); *data = (u8)val; - return rc; + return 0; +} + +static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data) +{ + int rc; + + rc = regmap_write(led->regmap, addr, data); + if (rc < 0) { + pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc); + return rc; + } + + pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr); + return 0; } static int @@ -277,11 +337,10 @@ qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask, rc = regmap_update_bits(led->regmap, addr, mask, val); if (rc < 0) - dev_err(&led->pdev->dev, "Unable to update bits from 0x%04X, rc = %d\n", - addr, rc); + pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr, + rc); else - dev_dbg(&led->pdev->dev, "Wrote 0x%02X to addr 0x%04X\n", - val, addr); + pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr); return rc; } @@ -295,13 +354,12 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev) static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) { int rc, i, addr_offset; - u8 val = 0; + u8 val = 0, mask; for (i = 0; i < led->num_fnodes; i++) { addr_offset = led->fnode[i].id; - rc = qpnp_flash_led_masked_write(led, + rc = qpnp_flash_led_write(led, FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset), - FLASH_LED_HDRM_MODE_PRGM_MASK, led->fnode[i].hdrm_val); if (rc < 0) return rc; @@ -309,9 +367,9 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) val |= 0x1 << led->fnode[i].id; } - rc = qpnp_flash_led_masked_write(led, + rc = qpnp_flash_led_write(led, FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base), - FLASH_LED_HDRM_MODE_PRGM_MASK, val); + val); if (rc < 0) return rc; @@ -336,6 +394,70 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) if (rc < 0) return rc; + val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT); + mask = THERMAL_OTST1_RAMP_CTRL_MASK; + if (led->pdata->thermal_derate_slow >= 0) { + val |= (led->pdata->thermal_derate_slow << + THERMAL_DERATE_SLOW_SHIFT); + mask |= THERMAL_DERATE_SLOW_MASK; + } + + if (led->pdata->thermal_derate_fast >= 0) { + val |= led->pdata->thermal_derate_fast; + mask |= THERMAL_DERATE_FAST_MASK; + } + + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base), + mask, val); + if (rc < 0) + return rc; + + if (led->pdata->thermal_debounce >= 0) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_DEBOUNCE(led->base), + FLASH_LED_THERMAL_DEBOUNCE_MASK, + led->pdata->thermal_debounce); + if (rc < 0) + return rc; + } + + if (led->pdata->thermal_hysteresis >= 0) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_HYSTERESIS(led->base), + FLASH_LED_THERMAL_HYSTERESIS_MASK, + led->pdata->thermal_hysteresis); + if (rc < 0) + return rc; + } + + if (led->pdata->thermal_thrsh1 >= 0) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_THRSH1(led->base), + FLASH_LED_THERMAL_THRSH_MASK, + led->pdata->thermal_thrsh1); + if (rc < 0) + return rc; + } + + if (led->pdata->thermal_thrsh2 >= 0) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_THRSH2(led->base), + FLASH_LED_THERMAL_THRSH_MASK, + led->pdata->thermal_thrsh2); + if (rc < 0) + return rc; + } + + if (led->pdata->thermal_thrsh3 >= 0) { + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_THERMAL_THRSH3(led->base), + FLASH_LED_THERMAL_THRSH_MASK, + led->pdata->thermal_thrsh3); + if (rc < 0) + return rc; + } + rc = qpnp_flash_led_masked_write(led, FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base), FLASH_LED_VPH_DROOP_DEBOUNCE_MASK, @@ -385,6 +507,46 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) if (rc < 0) return rc; + if (led->pdata->led1n2_iclamp_low_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_low_ma, + led->fnode[0].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led1n2_iclamp_mid_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_mid_ma, + led->fnode[0].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led3_iclamp_low_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_low_ma, + led->fnode[3].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED3_ICLAMP_LOW(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + + if (led->pdata->led3_iclamp_mid_ma) { + val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_mid_ma, + led->fnode[3].ires_ua); + rc = qpnp_flash_led_masked_write(led, + FLASH_LED_REG_LED3_ICLAMP_MID(led->base), + FLASH_LED_CURRENT_MASK, val); + if (rc < 0) + return rc; + } + return 0; } @@ -414,8 +576,7 @@ static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode, on ? fnode->hw_strobe_state_active : fnode->hw_strobe_state_suspend); if (rc < 0) { - dev_err(&fnode->pdev->dev, - "failed to change hw strobe pin state\n"); + pr_err("failed to change hw strobe pin state\n"); return rc; } } @@ -426,34 +587,27 @@ static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode, static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led, struct flash_switch_data *snode, bool on) { - int i, rc = 0; + int rc = 0; + + if (!snode || !snode->vreg) + return 0; if (snode->regulator_on == on) return 0; - if (on == false) { - i = snode->num_regulators; - goto out; - } + if (on) + rc = regulator_enable(snode->vreg); + else + rc = regulator_disable(snode->vreg); - for (i = 0; i < snode->num_regulators; i++) { - rc = regulator_enable(snode->reg_data[i].vreg); - if (rc < 0) { - dev_err(&led->pdev->dev, - "regulator enable failed, rc=%d\n", rc); - goto out; - } + if (rc < 0) { + pr_err("regulator_%s failed, rc=%d\n", + on ? "enable" : "disable", rc); + return rc; } - snode->regulator_on = true; - - return rc; - -out: - while (i--) - regulator_disable(snode->reg_data[i].vreg); - snode->regulator_on = false; - return rc; + snode->regulator_on = on ? true : false; + return 0; } static int get_property_from_fg(struct qpnp_flash_led *led, @@ -463,14 +617,13 @@ static int get_property_from_fg(struct qpnp_flash_led *led, union power_supply_propval pval = {0, }; if (!led->bms_psy) { - dev_err(&led->pdev->dev, "no bms psy found\n"); + pr_err("no bms psy found\n"); return -EINVAL; } rc = power_supply_get_property(led->bms_psy, prop, &pval); if (rc) { - dev_err(&led->pdev->dev, - "bms psy doesn't support reading prop %d rc = %d\n", + pr_err("bms psy doesn't support reading prop %d rc = %d\n", prop, rc); return rc; } @@ -532,8 +685,7 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led) rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE, &rbatt_uohm); if (rc < 0) { - dev_err(&led->pdev->dev, "bms psy does not support resistance, rc=%d\n", - rc); + pr_err("bms psy does not support resistance, rc=%d\n", rc); return rc; } @@ -543,16 +695,14 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led) rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv); if (rc < 0) { - dev_err(&led->pdev->dev, "bms psy does not support OCV, rc=%d\n", - rc); + pr_err("bms psy does not support OCV, rc=%d\n", rc); return rc; } rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW, &ibat_now); if (rc < 0) { - dev_err(&led->pdev->dev, "bms psy does not support current, rc=%d\n", - rc); + pr_err("bms psy does not support current, rc=%d\n", rc); return rc; } @@ -571,8 +721,7 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led) FLASH_LED_LMH_MITIGATION_EN_MASK, FLASH_LED_LMH_MITIGATION_ENABLE); if (rc < 0) { - dev_err(&led->pdev->dev, "trigger lmh mitigation failed, rc=%d\n", - rc); + pr_err("trigger lmh mitigation failed, rc=%d\n", rc); return rc; } @@ -617,9 +766,8 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led) * before collapsing the battery. (available power/ flash input voltage) */ avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV); - dev_dbg(&led->pdev->dev, "avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n", - avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, - led->trigger_lmh); + pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n", + avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh); return min(FLASH_LED_MAX_TOTAL_CURRENT_MA, (int)(div64_s64(avail_flash_ua, MCONV))); } @@ -761,8 +909,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) FLASH_LED_LMH_MITIGATION_EN_MASK, FLASH_LED_LMH_MITIGATION_DISABLE); if (rc < 0) { - dev_err(&led->pdev->dev, "disable lmh mitigation failed, rc=%d\n", - rc); + pr_err("disable lmh mitigation failed, rc=%d\n", rc); return rc; } } @@ -773,8 +920,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) FLASH_LED_CHGR_MITIGATION_EN_MASK, FLASH_LED_CHGR_MITIGATION_DISABLE); if (rc < 0) { - dev_err(&led->pdev->dev, "disable chgr mitigation failed, rc=%d\n", - rc); + pr_err("disable chgr mitigation failed, rc=%d\n", rc); return rc; } } @@ -806,8 +952,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) rc = pinctrl_select_state(led->fnode[i].pinctrl, led->fnode[i].gpio_state_suspend); if (rc < 0) { - dev_err(&led->pdev->dev, - "failed to disable GPIO, rc=%d\n", rc); + pr_err("failed to disable GPIO, rc=%d\n", rc); return rc; } } @@ -816,8 +961,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode) rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i], led->pdata->hw_strobe_option, false); if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to disable hw strobe, rc=%d\n", + pr_err("Unable to disable hw strobe, rc=%d\n", rc); return rc; } @@ -835,8 +979,8 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) u8 val, mask; if (snode->enabled == on) { - dev_warn(&led->pdev->dev, "Switch node is already %s!\n", - on ? "enabled" : "disabled"); + pr_debug("Switch node is already %s!\n", + on ? "enabled" : "disabled"); return 0; } @@ -886,9 +1030,9 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) if (rc < 0) return rc; - rc = qpnp_flash_led_masked_write(led, + rc = qpnp_flash_led_write(led, FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset), - FLASH_LED_SAFETY_TMR_MASK, led->fnode[i].duration); + led->fnode[i].duration); if (rc < 0) return rc; @@ -898,8 +1042,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) rc = pinctrl_select_state(led->fnode[i].pinctrl, led->fnode[i].gpio_state_active); if (rc < 0) { - dev_err(&led->pdev->dev, - "failed to enable GPIO\n"); + pr_err("failed to enable GPIO rc=%d\n", rc); return rc; } } @@ -908,8 +1051,8 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i], led->pdata->hw_strobe_option, true); if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to enable hw strobe\n"); + pr_err("Unable to enable hw strobe rc=%d\n", + rc); return rc; } } @@ -930,8 +1073,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) FLASH_LED_LMH_MITIGATION_EN_MASK, FLASH_LED_LMH_MITIGATION_ENABLE); if (rc < 0) { - dev_err(&led->pdev->dev, "trigger lmh mitigation failed, rc=%d\n", - rc); + pr_err("trigger lmh mitigation failed, rc=%d\n", rc); return rc; } } @@ -942,8 +1084,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) FLASH_LED_CHGR_MITIGATION_EN_MASK, FLASH_LED_CHGR_MITIGATION_ENABLE); if (rc < 0) { - dev_err(&led->pdev->dev, "trigger chgr mitigation failed, rc=%d\n", - rc); + pr_err("trigger chgr mitigation failed, rc=%d\n", rc); return rc; } } @@ -975,15 +1116,14 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options, led = dev_get_drvdata(&snode->pdev->dev); if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) { - dev_err(&led->pdev->dev, "Invalid options %d\n", options); + pr_err("Invalid options %d\n", options); return -EINVAL; } if (options & ENABLE_REGULATOR) { rc = qpnp_flash_led_regulator_enable(led, snode, true); if (rc < 0) { - dev_err(&led->pdev->dev, - "enable regulator failed, rc=%d\n", rc); + pr_err("enable regulator failed, rc=%d\n", rc); return rc; } } @@ -991,8 +1131,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options, if (options & DISABLE_REGULATOR) { rc = qpnp_flash_led_regulator_enable(led, snode, false); if (rc < 0) { - dev_err(&led->pdev->dev, - "disable regulator failed, rc=%d\n", rc); + pr_err("disable regulator failed, rc=%d\n", rc); return rc; } } @@ -1000,8 +1139,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options, if (options & QUERY_MAX_CURRENT) { rc = qpnp_flash_led_get_max_avail_current(led); if (rc < 0) { - dev_err(&led->pdev->dev, - "query max current failed, rc=%d\n", rc); + pr_err("query max current failed, rc=%d\n", rc); return rc; } *max_current = rc; @@ -1041,8 +1179,7 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, if (snode) { rc = qpnp_flash_led_switch_set(snode, value > 0); if (rc < 0) - dev_err(&led->pdev->dev, - "Failed to set flash LED switch\n"); + pr_err("Failed to set flash LED switch rc=%d\n", rc); } else if (fnode) { qpnp_flash_led_node_set(fnode, value); } @@ -1050,6 +1187,31 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, spin_unlock(&led->lock); } +/* sysfs show function for flash_max_current */ +static ssize_t qpnp_flash_led_max_current_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int rc; + struct flash_switch_data *snode; + struct qpnp_flash_led *led; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + snode = container_of(led_cdev, struct flash_switch_data, cdev); + led = dev_get_drvdata(&snode->pdev->dev); + + rc = qpnp_flash_led_get_max_avail_current(led); + if (rc < 0) + pr_err("query max current failed, rc=%d\n", rc); + + return snprintf(buf, PAGE_SIZE, "%d\n", rc); +} + +/* sysfs attributes exported by flash_led */ +static struct device_attribute qpnp_flash_led_attrs[] = { + __ATTR(max_current, (S_IRUGO | S_IWUSR | S_IWGRP), + qpnp_flash_led_max_current_show, NULL), +}; + static int flash_led_psy_notifier_call(struct notifier_block *nb, unsigned long ev, void *v) { @@ -1063,7 +1225,7 @@ static int flash_led_psy_notifier_call(struct notifier_block *nb, if (!strcmp(psy->desc->name, "bms")) { led->bms_psy = power_supply_get_by_name("bms"); if (!led->bms_psy) - dev_err(&led->pdev->dev, "Failed to get bms power_supply\n"); + pr_err("Failed to get bms power_supply\n"); else power_supply_unreg_notifier(&led->nb); } @@ -1093,13 +1255,12 @@ static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led) int rc; u8 irq_status, led_status1, led_status2; - dev_dbg(&led->pdev->dev, "irq received, irq=%d\n", irq); + pr_debug("irq received, irq=%d\n", irq); rc = qpnp_flash_led_read(led, FLASH_LED_REG_INT_RT_STS(led->base), &irq_status); if (rc < 0) { - dev_err(&led->pdev->dev, "Failed to read interrupt status reg, rc=%d\n", - rc); + pr_err("Failed to read interrupt status reg, rc=%d\n", rc); goto exit; } @@ -1118,29 +1279,27 @@ static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led) rc = qpnp_flash_led_read(led, FLASH_LED_REG_LED_STATUS1(led->base), &led_status1); if (rc < 0) { - dev_err(&led->pdev->dev, "Failed to read led_status1 reg, rc=%d\n", - rc); + pr_err("Failed to read led_status1 reg, rc=%d\n", rc); goto exit; } rc = qpnp_flash_led_read(led, FLASH_LED_REG_LED_STATUS2(led->base), &led_status2); if (rc < 0) { - dev_err(&led->pdev->dev, "Failed to read led_status2 reg, rc=%d\n", - rc); + pr_err("Failed to read led_status2 reg, rc=%d\n", rc); goto exit; } if (led_status1) - dev_emerg(&led->pdev->dev, "led short/open fault detected! led_status1=%x\n", - led_status1); + pr_emerg("led short/open fault detected! led_status1=%x\n", + led_status1); if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK) - dev_emerg(&led->pdev->dev, "led vph_droop fault detected!\n"); + pr_emerg("led vph_droop fault detected!\n"); } - dev_dbg(&led->pdev->dev, "irq handled, irq_type=%x, irq_status=%x\n", - irq_type, irq_status); + pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type, + irq_status); exit: return IRQ_HANDLED; @@ -1156,104 +1315,6 @@ int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb) return atomic_notifier_chain_unregister(&irq_notifier_list, nb); } -static int qpnp_flash_led_regulator_setup(struct qpnp_flash_led *led, - struct flash_switch_data *snode, bool on) -{ - int i, rc = 0; - - if (on == false) { - i = snode->num_regulators; - goto out; - } - - for (i = 0; i < snode->num_regulators; i++) { - snode->reg_data[i].vreg = regulator_get(snode->cdev.dev, - snode->reg_data[i].reg_name); - if (IS_ERR(snode->reg_data[i].vreg)) { - rc = PTR_ERR(snode->reg_data[i].vreg); - dev_err(&led->pdev->dev, - "Failed to get regulator, rc=%d\n", rc); - goto out; - } - - if (regulator_count_voltages(snode->reg_data[i].vreg) > 0) { - rc = regulator_set_voltage(snode->reg_data[i].vreg, - snode->reg_data[i].max_volt_uv, - snode->reg_data[i].max_volt_uv); - if (rc < 0) { - dev_err(&led->pdev->dev, - "regulator set voltage failed, rc=%d\n", - rc); - regulator_put(snode->reg_data[i].vreg); - goto out; - } - } - } - - return rc; - -out: - while (i--) { - if (regulator_count_voltages(snode->reg_data[i].vreg) > 0) - regulator_set_voltage(snode->reg_data[i].vreg, 0, - snode->reg_data[i].max_volt_uv); - - regulator_put(snode->reg_data[i].vreg); - } - - return rc; -} - -static int qpnp_flash_led_regulator_parse_dt(struct qpnp_flash_led *led, - struct flash_switch_data *snode, - struct device_node *node) { - - int i = 0, rc = 0, num_regs = 0; - struct device_node *temp = NULL; - const char *temp_string; - u32 val; - - while ((temp = of_get_next_available_child(node, temp))) { - if (of_find_property(temp, "regulator-name", NULL)) - num_regs++; - } - snode->num_regulators = num_regs; - - if (snode->num_regulators == 0) - return 0; - - snode->reg_data = devm_kcalloc(&led->pdev->dev, snode->num_regulators, - sizeof(*snode->reg_data), - GFP_KERNEL); - if (!snode->reg_data) - return -ENOMEM; - - for_each_available_child_of_node(node, temp) { - rc = of_property_read_string(temp, "regulator-name", - &temp_string); - if (!rc) - snode->reg_data[i].reg_name = temp_string; - else { - dev_err(&led->pdev->dev, - "Unable to read regulator name, rc=%d\n", rc); - return rc; - } - - rc = of_property_read_u32(temp, "max-voltage-uv", &val); - if (!rc) { - snode->reg_data[i].max_volt_uv = val; - } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read max voltage, rc=%d\n", rc); - return rc; - } - - i++; - } - - return 0; -} - static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, struct flash_node_data *fnode, struct device_node *node) { @@ -1268,7 +1329,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name); if (rc < 0) { - dev_err(&led->pdev->dev, "Unable to read flash LED names\n"); + pr_err("Unable to read flash LED names\n"); return rc; } @@ -1279,11 +1340,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, } else if (!strcmp(temp_string, "torch")) { fnode->type = FLASH_LED_TYPE_TORCH; } else { - dev_err(&led->pdev->dev, "Wrong flash LED type\n"); + pr_err("Wrong flash LED type\n"); return rc; } } else { - dev_err(&led->pdev->dev, "Unable to read flash LED label\n"); + pr_err("Unable to read flash LED label\n"); return rc; } @@ -1291,14 +1352,14 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, if (!rc) { fnode->id = (u8)val; } else { - dev_err(&led->pdev->dev, "Unable to read flash LED ID\n"); + pr_err("Unable to read flash LED ID\n"); return rc; } rc = of_property_read_string(node, "qcom,default-led-trigger", &fnode->cdev.default_trigger); if (rc < 0) { - dev_err(&led->pdev->dev, "Unable to read trigger name\n"); + pr_err("Unable to read trigger name\n"); return rc; } @@ -1310,7 +1371,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->ires = FLASH_LED_IRES_BASE - (val - FLASH_LED_IRES_MIN_UA) / FLASH_LED_IRES_DIVISOR; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to read current resolution\n"); + pr_err("Unable to read current resolution rc=%d\n", rc); return rc; } @@ -1321,8 +1382,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->max_current = val; fnode->cdev.max_brightness = val; } else { - dev_err(&led->pdev->dev, - "Unable to read max current, rc=%d\n", rc); + pr_err("Unable to read max current, rc=%d\n", rc); return rc; } @@ -1330,8 +1390,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, if (!rc) { if (val < FLASH_LED_MIN_CURRENT_MA || val > fnode->max_current) - dev_warn(&led->pdev->dev, - "Invalid operational current specified, capping it\n"); + pr_warn("Invalid operational current specified, capping it\n"); if (val < FLASH_LED_MIN_CURRENT_MA) val = FLASH_LED_MIN_CURRENT_MA; if (val > fnode->max_current) @@ -1339,8 +1398,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->current_ma = val; fnode->cdev.brightness = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read operational current, rc=%d\n", rc); + pr_err("Unable to read operational current, rc=%d\n", rc); return rc; } @@ -1351,13 +1409,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, FLASH_LED_SAFETY_TMR_ENABLE); } else if (rc == -EINVAL) { if (fnode->type == FLASH_LED_TYPE_FLASH) { - dev_err(&led->pdev->dev, - "Timer duration is required for flash LED\n"); + pr_err("Timer duration is required for flash LED\n"); return rc; } } else { - dev_err(&led->pdev->dev, - "Unable to read timer duration\n"); + pr_err("Unable to read timer duration\n"); return rc; } @@ -1369,7 +1425,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) & FLASH_LED_HDRM_VOL_MASK; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to read headroom voltage\n"); + pr_err("Unable to read headroom voltage\n"); return rc; } @@ -1380,8 +1436,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, } else if (rc == -EINVAL) { fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV; } else { - dev_err(&led->pdev->dev, - "Unable to read hdrm hi-lo window voltage\n"); + pr_err("Unable to read hdrm hi-lo window voltage\n"); return rc; } @@ -1399,8 +1454,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->hw_strobe_gpio = of_get_named_gpio(node, "qcom,hw-strobe-gpio", 0); if (fnode->hw_strobe_gpio < 0) { - dev_err(&led->pdev->dev, - "Invalid gpio specified\n"); + pr_err("Invalid gpio specified\n"); return fnode->hw_strobe_gpio; } gpio_direction_output(fnode->hw_strobe_gpio, 0); @@ -1410,8 +1464,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, pinctrl_lookup_state(fnode->pinctrl, "strobe_enable"); if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) { - dev_err(&led->pdev->dev, - "No active pin for hardware strobe, rc=%ld\n", + pr_err("No active pin for hardware strobe, rc=%ld\n", PTR_ERR(fnode->hw_strobe_state_active)); fnode->hw_strobe_state_active = NULL; } @@ -1420,8 +1473,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, pinctrl_lookup_state(fnode->pinctrl, "strobe_disable"); if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) { - dev_err(&led->pdev->dev, - "No suspend pin for hardware strobe, rc=%ld\n", + pr_err("No suspend pin for hardware strobe, rc=%ld\n", PTR_ERR(fnode->hw_strobe_state_suspend) ); fnode->hw_strobe_state_suspend = NULL; @@ -1431,8 +1483,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, rc = led_classdev_register(&led->pdev->dev, &fnode->cdev); if (rc < 0) { - dev_err(&led->pdev->dev, "Unable to register led node %d\n", - fnode->id); + pr_err("Unable to register led node %d\n", fnode->id); return rc; } @@ -1440,14 +1491,13 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->pinctrl = devm_pinctrl_get(fnode->cdev.dev); if (IS_ERR_OR_NULL(fnode->pinctrl)) { - dev_warn(&led->pdev->dev, "No pinctrl defined\n"); + pr_debug("No pinctrl defined\n"); fnode->pinctrl = NULL; } else { fnode->gpio_state_active = pinctrl_lookup_state(fnode->pinctrl, "led_enable"); if (IS_ERR_OR_NULL(fnode->gpio_state_active)) { - dev_err(&led->pdev->dev, - "Cannot lookup LED active state\n"); + pr_err("Cannot lookup LED active state\n"); devm_pinctrl_put(fnode->pinctrl); fnode->pinctrl = NULL; return PTR_ERR(fnode->gpio_state_active); @@ -1456,8 +1506,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, fnode->gpio_state_suspend = pinctrl_lookup_state(fnode->pinctrl, "led_disable"); if (IS_ERR_OR_NULL(fnode->gpio_state_suspend)) { - dev_err(&led->pdev->dev, - "Cannot lookup LED disable state\n"); + pr_err("Cannot lookup LED disable state\n"); devm_pinctrl_put(fnode->pinctrl); fnode->pinctrl = NULL; return PTR_ERR(fnode->gpio_state_suspend); @@ -1471,46 +1520,48 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, struct flash_switch_data *snode, struct device_node *node) { - int rc = 0; + int rc = 0, num; + char reg_name[16], reg_sup_name[16]; rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name); if (rc < 0) { - dev_err(&led->pdev->dev, - "Failed to read switch node name, rc=%d\n", rc); + pr_err("Failed to read switch node name, rc=%d\n", rc); return rc; } + rc = sscanf(snode->cdev.name, "led:switch_%d", &num); + if (!rc) { + pr_err("No number for switch device?\n"); + return -EINVAL; + } + rc = of_property_read_string(node, "qcom,default-led-trigger", &snode->cdev.default_trigger); if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to read trigger name, rc=%d\n", rc); + pr_err("Unable to read trigger name, rc=%d\n", rc); return rc; } rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask); if (rc < 0) { - dev_err(&led->pdev->dev, "Unable to read led mask rc=%d\n", rc); + pr_err("Unable to read led mask rc=%d\n", rc); return rc; } if (snode->led_mask < 1 || snode->led_mask > 7) { - dev_err(&led->pdev->dev, "Invalid value for led-mask\n"); + pr_err("Invalid value for led-mask\n"); return -EINVAL; } - rc = qpnp_flash_led_regulator_parse_dt(led, snode, node); - if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to parse regulator data, rc=%d\n", rc); - return rc; - } - - if (snode->num_regulators) { - rc = qpnp_flash_led_regulator_setup(led, snode, true); - if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to setup regulator, rc=%d\n", rc); + scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num); + if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) { + scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num); + snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name); + if (IS_ERR_OR_NULL(snode->vreg)) { + rc = PTR_ERR(snode->vreg); + if (rc != -EPROBE_DEFER) + pr_err("Failed to get regulator, rc=%d\n", rc); + snode->vreg = NULL; return rc; } } @@ -1520,8 +1571,7 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, snode->cdev.brightness_get = qpnp_flash_led_brightness_get; rc = led_classdev_register(&led->pdev->dev, &snode->cdev); if (rc < 0) { - dev_err(&led->pdev->dev, - "Unable to register led switch node\n"); + pr_err("Unable to register led switch node\n"); return rc; } @@ -1529,13 +1579,53 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led, return 0; } +static int get_code_from_table(int *table, int len, int value) +{ + int i; + + for (i = 0; i < len; i++) { + if (value == table[i]) + break; + } + + if (i == len) { + pr_err("Couldn't find %d from table\n", value); + return -ENODATA; + } + + return i; +} + static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, struct device_node *node) { + struct device_node *revid_node; int rc; u32 val; bool short_circuit_det, open_circuit_det, vph_droop_det; + revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0); + if (!revid_node) { + pr_err("Missing qcom,pmic-revid property - driver failed\n"); + return -EINVAL; + } + + led->pdata->pmic_rev_id = get_revid_data(revid_node); + if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) { + pr_err("Unable to get pmic_revid rc=%ld\n", + PTR_ERR(led->pdata->pmic_rev_id)); + /* + * the revid peripheral must be registered, any failure + * here only indicates that the rev-id module has not + * probed yet. + */ + return -EPROBE_DEFER; + } + + pr_debug("PMIC subtype %d Digital major %d\n", + led->pdata->pmic_rev_id->pmic_subtype, + led->pdata->pmic_rev_id->rev4); + led->pdata->hdrm_auto_mode_en = of_property_read_bool(node, "qcom,hdrm-auto-mode"); @@ -1545,8 +1635,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->isc_delay = val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read ISC delay, rc=%d\n", rc); + pr_err("Unable to read ISC delay, rc=%d\n", rc); return rc; } @@ -1556,8 +1645,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->warmup_delay = val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read WARMUP delay, rc=%d\n", rc); + pr_err("Unable to read WARMUP delay, rc=%d\n", rc); return rc; } @@ -1584,26 +1672,128 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->thermal_derate_current, FLASH_LED_THERMAL_OTST_LEVELS); if (rc < 0) { - dev_err(&led->pdev->dev, "Unable to read thermal current limits, rc=%d\n", - rc); + pr_err("Unable to read thermal current limits, rc=%d\n", + rc); return rc; } } + led->pdata->otst_ramp_bkup_en = + !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis"); + + led->pdata->thermal_derate_slow = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val); + if (!rc) { + if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) { + pr_err("Invalid thermal_derate_slow %d\n", val); + return -EINVAL; + } + + led->pdata->thermal_derate_slow = + get_code_from_table(thermal_derate_slow_table, + ARRAY_SIZE(thermal_derate_slow_table), val); + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal derate slow, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_derate_fast = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val); + if (!rc) { + if (val < 0 || val > THERMAL_DERATE_FAST_MAX) { + pr_err("Invalid thermal_derate_fast %d\n", val); + return -EINVAL; + } + + led->pdata->thermal_derate_fast = + get_code_from_table(thermal_derate_fast_table, + ARRAY_SIZE(thermal_derate_fast_table), val); + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal derate fast, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_debounce = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-debounce", &val); + if (!rc) { + if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) { + pr_err("Invalid thermal_debounce %d\n", val); + return -EINVAL; + } + + if (val >= 0 && val < 16) + led->pdata->thermal_debounce = 0; + else + led->pdata->thermal_debounce = ilog2(val) - 3; + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal debounce, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_hysteresis = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val); + if (!rc) { + if (led->pdata->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) + val = THERMAL_HYST_TEMP_TO_VAL(val, 20); + else + val = THERMAL_HYST_TEMP_TO_VAL(val, 15); + + if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) { + pr_err("Invalid thermal_derate_hysteresis %d\n", val); + return -EINVAL; + } + + led->pdata->thermal_hysteresis = val; + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal hysteresis, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_thrsh1 = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val); + if (!rc) { + led->pdata->thermal_thrsh1 = + get_code_from_table(otst1_threshold_table, + ARRAY_SIZE(otst1_threshold_table), val); + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal thrsh1, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_thrsh2 = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val); + if (!rc) { + led->pdata->thermal_thrsh2 = + get_code_from_table(otst2_threshold_table, + ARRAY_SIZE(otst2_threshold_table), val); + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal thrsh2, rc=%d\n", rc); + return rc; + } + + led->pdata->thermal_thrsh3 = -EINVAL; + rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val); + if (!rc) { + led->pdata->thermal_thrsh3 = + get_code_from_table(otst3_threshold_table, + ARRAY_SIZE(otst3_threshold_table), val); + } else if (rc != -EINVAL) { + pr_err("Unable to read thermal thrsh3, rc=%d\n", rc); + return rc; + } + led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT; rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val); if (!rc) { led->pdata->vph_droop_debounce = VPH_DROOP_DEBOUNCE_US_TO_VAL(val); } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read VPH droop debounce, rc=%d\n", rc); + pr_err("Unable to read VPH droop debounce, rc=%d\n", rc); return rc; } - if (led->pdata->vph_droop_debounce > FLASH_LED_VPH_DROOP_DEBOUNCE_MAX) { - dev_err(&led->pdev->dev, - "Invalid VPH droop debounce specified"); + if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) { + pr_err("Invalid VPH droop debounce specified\n"); return -EINVAL; } @@ -1613,14 +1803,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->vph_droop_threshold = VPH_DROOP_THRESH_MV_TO_VAL(val); } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read VPH droop threshold, rc=%d\n", rc); + pr_err("Unable to read VPH droop threshold, rc=%d\n", rc); return rc; } if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) { - dev_err(&led->pdev->dev, - "Invalid VPH droop threshold specified"); + pr_err("Invalid VPH droop threshold specified\n"); return -EINVAL; } @@ -1631,23 +1819,54 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, led->pdata->vph_droop_hysteresis = VPH_DROOP_HYST_MV_TO_VAL(val); } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to read VPH droop hysteresis, rc=%d\n", rc); + pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc); return rc; } - if (led->pdata->vph_droop_hysteresis > FLASH_LED_VPH_DROOP_HYST_MAX) { - dev_err(&led->pdev->dev, - "Invalid VPH droop hysteresis specified"); + if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) { + pr_err("Invalid VPH droop hysteresis specified\n"); return -EINVAL; } + led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT; + rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val); if (!rc) { led->pdata->hw_strobe_option = (u8)val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, - "Unable to parse hw strobe option, rc=%d\n", rc); + pr_err("Unable to parse hw strobe option, rc=%d\n", rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val); + if (!rc) { + led->pdata->led1n2_iclamp_low_ma = val; + } else if (rc != -EINVAL) { + pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val); + if (!rc) { + led->pdata->led1n2_iclamp_mid_ma = val; + } else if (rc != -EINVAL) { + pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val); + if (!rc) { + led->pdata->led3_iclamp_low_ma = val; + } else if (rc != -EINVAL) { + pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc); + return rc; + } + + rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val); + if (!rc) { + led->pdata->led3_iclamp_mid_ma = val; + } else if (rc != -EINVAL) { + pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc); return rc; } @@ -1656,8 +1875,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->vled_max_uv = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse vled_max voltage, rc=%d\n", - rc); + pr_err("Unable to parse vled_max voltage, rc=%d\n", rc); return rc; } @@ -1667,8 +1885,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->ibatt_ocp_threshold_ua = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse ibatt_ocp threshold, rc=%d\n", - rc); + pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc); return rc; } @@ -1677,8 +1894,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->rpara_uohm = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse rparasitic, rc=%d\n", - rc); + pr_err("Unable to parse rparasitic, rc=%d\n", rc); return rc; } @@ -1688,8 +1904,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->lmh_ocv_threshold_uv = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse lmh ocv threshold, rc=%d\n", - rc); + pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc); return rc; } @@ -1699,8 +1914,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->lmh_rbatt_threshold_uohm = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse lmh rbatt threshold, rc=%d\n", - rc); + pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc); return rc; } @@ -1709,8 +1923,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->lmh_level = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse lmh_level, rc=%d\n", - rc); + pr_err("Unable to parse lmh_level, rc=%d\n", rc); return rc; } @@ -1719,13 +1932,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->lmh_mitigation_sel = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse lmh_mitigation_sel, rc=%d\n", - rc); + pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc); return rc; } if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) { - dev_err(&led->pdev->dev, "Invalid lmh_mitigation_sel specified\n"); + pr_err("Invalid lmh_mitigation_sel specified\n"); return -EINVAL; } @@ -1734,13 +1946,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->chgr_mitigation_sel = val; } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse chgr_mitigation_sel, rc=%d\n", - rc); + pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc); return rc; } if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) { - dev_err(&led->pdev->dev, "Invalid chgr_mitigation_sel specified\n"); + pr_err("Invalid chgr_mitigation_sel specified\n"); return -EINVAL; } @@ -1751,30 +1962,29 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led, if (!rc) { led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val); } else if (rc != -EINVAL) { - dev_err(&led->pdev->dev, "Unable to parse iled_thrsh_val, rc=%d\n", - rc); + pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc); return rc; } if (led->pdata->iled_thrsh_val > FLASH_LED_MITIGATION_THRSH_MAX) { - dev_err(&led->pdev->dev, "Invalid iled_thrsh_val specified\n"); + pr_err("Invalid iled_thrsh_val specified\n"); return -EINVAL; } led->pdata->all_ramp_up_done_irq = of_irq_get_byname(node, "all-ramp-up-done-irq"); if (led->pdata->all_ramp_up_done_irq < 0) - dev_dbg(&led->pdev->dev, "all-ramp-up-done-irq not used\n"); + pr_debug("all-ramp-up-done-irq not used\n"); led->pdata->all_ramp_down_done_irq = of_irq_get_byname(node, "all-ramp-down-done-irq"); if (led->pdata->all_ramp_down_done_irq < 0) - dev_dbg(&led->pdev->dev, "all-ramp-down-done-irq not used\n"); + pr_debug("all-ramp-down-done-irq not used\n"); led->pdata->led_fault_irq = of_irq_get_byname(node, "led-fault-irq"); if (led->pdata->led_fault_irq < 0) - dev_dbg(&led->pdev->dev, "led-fault-irq not used\n"); + pr_debug("led-fault-irq not used\n"); return 0; } @@ -1785,18 +1995,18 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) struct device_node *node, *temp; const char *temp_string; unsigned int base; - int rc, i = 0; + int rc, i = 0, j = 0; node = pdev->dev.of_node; if (!node) { - dev_info(&pdev->dev, "No flash LED nodes defined\n"); + pr_err("No flash LED nodes defined\n"); return -ENODEV; } rc = of_property_read_u32(node, "reg", &base); if (rc < 0) { - dev_err(&pdev->dev, "Couldn't find reg in node %s, rc = %d\n", - node->full_name, rc); + pr_err("Couldn't find reg in node %s, rc = %d\n", + node->full_name, rc); return rc; } @@ -1807,7 +2017,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) led->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!led->regmap) { - dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); + pr_err("Couldn't get parent's regmap\n"); return -EINVAL; } @@ -1820,16 +2030,14 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) rc = qpnp_flash_led_parse_common_dt(led, node); if (rc < 0) { - dev_err(&pdev->dev, - "Failed to parse common flash LED device tree\n"); + pr_err("Failed to parse common flash LED device tree\n"); return rc; } for_each_available_child_of_node(node, temp) { rc = of_property_read_string(temp, "label", &temp_string); if (rc < 0) { - dev_err(&pdev->dev, - "Failed to parse label, rc=%d\n", rc); + pr_err("Failed to parse label, rc=%d\n", rc); return rc; } @@ -1839,14 +2047,13 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) !strcmp("torch", temp_string)) { led->num_fnodes++; } else { - dev_err(&pdev->dev, - "Invalid label for led node\n"); + pr_err("Invalid label for led node\n"); return -EINVAL; } } if (!led->num_fnodes) { - dev_err(&pdev->dev, "No LED nodes defined\n"); + pr_err("No LED nodes defined\n"); return -ECHILD; } @@ -1863,26 +2070,34 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) return -ENOMEM; temp = NULL; - for (i = 0; i < led->num_fnodes; i++) { - temp = of_get_next_available_child(node, temp); - rc = qpnp_flash_led_parse_each_led_dt(led, - &led->fnode[i], temp); + i = 0; + j = 0; + for_each_available_child_of_node(node, temp) { + rc = of_property_read_string(temp, "label", &temp_string); if (rc < 0) { - dev_err(&pdev->dev, - "Unable to parse flash node %d rc=%d\n", i, rc); - goto error_led_register; + pr_err("Failed to parse label, rc=%d\n", rc); + return rc; } - } - for (i = 0; i < led->num_snodes; i++) { - temp = of_get_next_available_child(node, temp); - rc = qpnp_flash_led_parse_and_register_switch(led, - &led->snode[i], temp); - if (rc < 0) { - dev_err(&pdev->dev, - "Unable to parse and register switch node, rc=%d\n", - rc); - goto error_switch_register; + if (!strcmp("flash", temp_string) || + !strcmp("torch", temp_string)) { + rc = qpnp_flash_led_parse_each_led_dt(led, + &led->fnode[i++], temp); + if (rc < 0) { + pr_err("Unable to parse flash node %d rc=%d\n", + i, rc); + goto error_led_register; + } + } + + if (!strcmp("switch", temp_string)) { + rc = qpnp_flash_led_parse_and_register_switch(led, + &led->snode[j++], temp); + if (rc < 0) { + pr_err("Unable to parse and register switch node, rc=%d\n", + rc); + goto error_switch_register; + } } } @@ -1894,8 +2109,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) IRQF_ONESHOT, "qpnp_flash_led_all_ramp_up_done_irq", led); if (rc < 0) { - dev_err(&pdev->dev, - "Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n", + pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n", led->pdata->all_ramp_up_done_irq, rc); goto error_switch_register; } @@ -1908,8 +2122,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) IRQF_ONESHOT, "qpnp_flash_led_all_ramp_down_done_irq", led); if (rc < 0) { - dev_err(&pdev->dev, - "Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n", + pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n", led->pdata->all_ramp_down_done_irq, rc); goto error_switch_register; } @@ -1922,8 +2135,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) IRQF_ONESHOT, "qpnp_flash_led_fault_irq", led); if (rc < 0) { - dev_err(&pdev->dev, - "Unable to request led_fault(%d) IRQ(err:%d)\n", + pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n", led->pdata->led_fault_irq, rc); goto error_switch_register; } @@ -1933,25 +2145,46 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) if (!led->bms_psy) { rc = flash_led_psy_register_notifier(led); if (rc < 0) { - dev_err(&pdev->dev, "Couldn't register psy notifier, rc = %d\n", - rc); + pr_err("Couldn't register psy notifier, rc = %d\n", rc); goto error_switch_register; } } rc = qpnp_flash_led_init_settings(led); if (rc < 0) { - dev_err(&pdev->dev, - "Failed to initialize flash LED, rc=%d\n", rc); + pr_err("Failed to initialize flash LED, rc=%d\n", rc); goto unreg_notifier; } + for (i = 0; i < led->num_snodes; i++) { + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) { + rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + if (rc < 0) { + pr_err("sysfs creation failed, rc=%d\n", rc); + goto sysfs_fail; + } + } + } + spin_lock_init(&led->lock); dev_set_drvdata(&pdev->dev, led); return 0; +sysfs_fail: + for (--j; j >= 0; j--) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + + for (--i; i >= 0; i--) { + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + } + + i = led->num_snodes; unreg_notifier: power_supply_unreg_notifier(&led->nb); error_switch_register: @@ -1968,20 +2201,21 @@ error_led_register: static int qpnp_flash_led_remove(struct platform_device *pdev) { struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev); - int i; + int i, j; for (i = 0; i < led->num_snodes; i++) { - if (led->snode[i].num_regulators) { - if (led->snode[i].regulator_on) - qpnp_flash_led_regulator_enable(led, - &led->snode[i], false); - qpnp_flash_led_regulator_setup(led, + for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) + sysfs_remove_file(&led->snode[i].cdev.dev->kobj, + &qpnp_flash_led_attrs[j].attr); + + if (led->snode[i].regulator_on) + qpnp_flash_led_regulator_enable(led, &led->snode[i], false); - } } while (i > 0) led_classdev_unregister(&led->snode[--i].cdev); + i = led->num_fnodes; while (i > 0) led_classdev_unregister(&led->fnode[--i].cdev); diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 95b4c42a5adb..98dfa56add51 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -82,7 +82,6 @@ #define FLASH_LED_HDRM_SNS_ENABLE_MASK 0x81 #define FLASH_MASK_MODULE_CONTRL_MASK 0xE0 #define FLASH_FOLLOW_OTST2_RB_MASK 0x08 -#define FLASH_PREPARE_OPTIONS_MASK 0x08 #define FLASH_LED_TRIGGER_DEFAULT "none" #define FLASH_LED_HEADROOM_DEFAULT_MV 500 @@ -1172,7 +1171,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options, flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->pdev->dev); - if (!(options & FLASH_PREPARE_OPTIONS_MASK)) { + if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) { dev_err(&led->pdev->dev, "Invalid options %d\n", options); return -EINVAL; } diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c index 894c1d88b3ef..97cfa813f4ce 100644 --- a/drivers/leds/leds-qpnp-wled.c +++ b/drivers/leds/leds-qpnp-wled.c @@ -61,11 +61,7 @@ #define QPNP_WLED_EN_MASK 0x7F #define QPNP_WLED_EN_SHIFT 7 #define QPNP_WLED_FDBK_OP_MASK 0xF8 -#define QPNP_WLED_VREF_MASK 0xF0 -#define QPNP_WLED_VREF_STEP_MV 25 -#define QPNP_WLED_VREF_MIN_MV 300 -#define QPNP_WLED_VREF_MAX_MV 675 -#define QPNP_WLED_DFLT_VREF_MV 350 +#define QPNP_WLED_VREF_MASK GENMASK(3, 0) #define QPNP_WLED_VLOOP_COMP_RES_MASK 0xF0 #define QPNP_WLED_VLOOP_COMP_RES_OVERWRITE 0x80 @@ -275,6 +271,20 @@ static int qpnp_wled_ilim_settings_pmicobalt[NUM_SUPPORTED_ILIM_THRESHOLDS] = { 105, 280, 450, 620, 970, 1150, 1300, 1500, }; +struct wled_vref_setting { + u32 min_uv; + u32 max_uv; + u32 step_uv; + u32 default_uv; +}; + +static struct wled_vref_setting vref_setting_pmi8994 = { + 300000, 675000, 25000, 350000, +}; +static struct wled_vref_setting vref_setting_pmicobalt = { + 60000, 397500, 22500, 127500, +}; + /** * qpnp_wled - wed data structure * @ cdev - led class device @@ -294,7 +304,7 @@ static int qpnp_wled_ilim_settings_pmicobalt[NUM_SUPPORTED_ILIM_THRESHOLDS] = { * @ mod_freq_khz - modulator frequency in KHZ * @ hyb_thres - threshold for hybrid dimming * @ sync_dly_us - sync delay in us - * @ vref_mv - ref voltage in mv + * @ vref_uv - ref voltage in uv * @ vref_psm_mv - ref psm voltage in mv * @ loop_comp_res_kohm - control to select the compensation resistor * @ loop_ea_gm - control to select the gm for the gm stage in control loop @@ -337,7 +347,7 @@ struct qpnp_wled { u16 mod_freq_khz; u16 hyb_thres; u16 sync_dly_us; - u16 vref_mv; + u32 vref_uv; u16 vref_psm_mv; u16 loop_comp_res_kohm; u16 loop_ea_gm; @@ -1248,6 +1258,35 @@ static int qpnp_wled_ilim_config(struct qpnp_wled *wled) return rc; } +static int qpnp_wled_vref_config(struct qpnp_wled *wled) +{ + + struct wled_vref_setting vref_setting; + int rc; + u8 reg = 0; + + if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE || + wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) + vref_setting = vref_setting_pmicobalt; + else + vref_setting = vref_setting_pmi8994; + + if (wled->vref_uv < vref_setting.min_uv) + wled->vref_uv = vref_setting.min_uv; + else if (wled->vref_uv > vref_setting.max_uv) + wled->vref_uv = vref_setting.max_uv; + + reg |= DIV_ROUND_CLOSEST(wled->vref_uv - vref_setting.min_uv, + vref_setting.step_uv); + + rc = qpnp_wled_masked_write_reg(wled, QPNP_WLED_VREF_MASK, + ®, QPNP_WLED_VREF_REG(wled->ctrl_base)); + if (rc) + pr_err("Write VREF_REG failed, rc=%d\n", rc); + + return rc; +} + /* Configure WLED registers */ static int qpnp_wled_config(struct qpnp_wled *wled) { @@ -1272,22 +1311,11 @@ static int qpnp_wled_config(struct qpnp_wled *wled) return rc; /* Configure the VREF register */ - if (wled->vref_mv < QPNP_WLED_VREF_MIN_MV) - wled->vref_mv = QPNP_WLED_VREF_MIN_MV; - else if (wled->vref_mv > QPNP_WLED_VREF_MAX_MV) - wled->vref_mv = QPNP_WLED_VREF_MAX_MV; - - rc = qpnp_wled_read_reg(wled, ®, - QPNP_WLED_VREF_REG(wled->ctrl_base)); - if (rc < 0) - return rc; - reg &= QPNP_WLED_VREF_MASK; - temp = wled->vref_mv - QPNP_WLED_VREF_MIN_MV; - reg |= (temp / QPNP_WLED_VREF_STEP_MV); - rc = qpnp_wled_write_reg(wled, reg, - QPNP_WLED_VREF_REG(wled->ctrl_base)); - if (rc) + rc = qpnp_wled_vref_config(wled); + if (rc < 0) { + pr_err("Error in configuring wled vref, rc=%d\n", rc); return rc; + } /* Configure the ILIM register */ rc = qpnp_wled_ilim_config(wled); @@ -1714,11 +1742,15 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled) return rc; } - wled->vref_mv = QPNP_WLED_DFLT_VREF_MV; + if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE || + wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) + wled->vref_uv = vref_setting_pmicobalt.default_uv; + else + wled->vref_uv = vref_setting_pmi8994.default_uv; rc = of_property_read_u32(pdev->dev.of_node, - "qcom,vref-mv", &temp_val); + "qcom,vref-uv", &temp_val); if (!rc) { - wled->vref_mv = temp_val; + wled->vref_uv = temp_val; } else if (rc != -EINVAL) { dev_err(&pdev->dev, "Unable to read vref\n"); return rc; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c index 2c313016bc90..8213f736205a 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp_soc.c @@ -66,39 +66,72 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name) return -EINVAL; } -static int cpp_get_clk_freq_tbl(struct clk *clk, struct cpp_hw_info *hw_info, - uint32_t min_clk_rate) +static int cpp_get_clk_freq_tbl_dt(struct cpp_device *cpp_dev) { - uint32_t i; + uint32_t i, count, min_clk_rate; uint32_t idx = 0; - signed long freq_tbl_entry = 0; + struct device_node *of_node; + uint32_t *rates; + int32_t rc = 0; + struct cpp_hw_info *hw_info; - if ((clk == NULL) || (hw_info == NULL) || (clk->ops == NULL) || - (clk->ops->list_rate == NULL)) { + if (cpp_dev == NULL) { pr_err("Bad parameter\n"); - return -EINVAL; + rc = -EINVAL; + goto err; } - for (i = 0; i < MAX_FREQ_TBL; i++) { - freq_tbl_entry = clk->ops->list_rate(clk, i); - pr_debug("entry=%ld\n", freq_tbl_entry); - if (freq_tbl_entry >= 0) { - if (freq_tbl_entry >= min_clk_rate) { - hw_info->freq_tbl[idx++] = freq_tbl_entry; - pr_debug("tbl[%d]=%ld\n", idx-1, - freq_tbl_entry); + of_node = cpp_dev->pdev->dev.of_node; + min_clk_rate = cpp_dev->min_clk_rate; + hw_info = &cpp_dev->hw_info; + + if ((hw_info == NULL) || (of_node == NULL)) { + pr_err("Invalid hw_info %p or ofnode %p\n", hw_info, of_node); + rc = -EINVAL; + goto err; + + } + count = of_property_count_u32_elems(of_node, "qcom,src-clock-rates"); + if ((count == 0) || (count > MAX_FREQ_TBL)) { + pr_err("Clock count is invalid\n"); + rc = -EINVAL; + goto err; + } + + rates = devm_kcalloc(&cpp_dev->pdev->dev, count, sizeof(uint32_t), + GFP_KERNEL); + if (!rates) { + rc = -ENOMEM; + goto err; + } + + rc = of_property_read_u32_array(of_node, "qcom,src-clock-rates", + rates, count); + if (rc) { + rc = -EINVAL; + goto mem_free; + } + + for (i = 0; i < count; i++) { + pr_debug("entry=%d\n", rates[i]); + if (rates[i] >= 0) { + if (rates[i] >= min_clk_rate) { + hw_info->freq_tbl[idx++] = rates[i]; + pr_debug("tbl[%d]=%d\n", idx-1, rates[i]); } } else { - pr_debug("freq table returned invalid entry/end %ld\n", - freq_tbl_entry); + pr_debug("rate is invalid entry/end %d\n", rates[i]); break; } } - pr_debug("%s: idx %d", __func__, idx); + pr_debug("%s: idx %d\n", __func__, idx); hw_info->freq_tbl_count = idx; - return 0; +mem_free: + devm_kfree(&cpp_dev->pdev->dev, rates); +err: + return rc; } int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev) @@ -147,8 +180,7 @@ int msm_update_freq_tbl(struct cpp_device *cpp_dev) rc = msm_cpp_core_clk_idx; return rc; } - rc = cpp_get_clk_freq_tbl(cpp_dev->cpp_clk[msm_cpp_core_clk_idx], - &cpp_dev->hw_info, cpp_dev->min_clk_rate); + rc = cpp_get_clk_freq_tbl_dt(cpp_dev); if (rc < 0) { pr_err("%s: fail to get frequency table\n", __func__); return rc; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index 925b8497273a..4e86a3ff820d 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -1502,7 +1502,8 @@ static void sde_hw_rotator_free_rotctx(struct sde_hw_rotator *rot, ctx->q_id, ctx->timestamp, atomic_read(&ctx->hwres->num_active)); - rot->rotCtx[ctx->q_id][sde_hw_rotator_get_regdma_ctxidx(ctx)] = NULL; + /* Clear rotator context from lookup purpose */ + sde_hw_rotator_clr_ctx(ctx); devm_kfree(&rot->pdev->dev, ctx); } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h index 91ac3d0371fa..7aecc3cee210 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h @@ -345,10 +345,32 @@ static inline void sde_hw_rotator_put_ctx(struct sde_hw_rotator_context *ctx) { struct sde_hw_rotator *rot = ctx->rot; u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); + unsigned long flags; + spin_lock_irqsave(&rot->rotisr_lock, flags); rot->rotCtx[ctx->q_id][idx] = ctx; + spin_unlock_irqrestore(&rot->rotisr_lock, flags); + SDEROT_DBG("rotCtx[%d][%d] <== ctx:%p | session-id:%d\n", ctx->q_id, idx, ctx, ctx->session_id); } +/** + * sde_hw_rotator_clr_ctx(): Clearing rotator context according to its + * timestamp. + */ +static inline void sde_hw_rotator_clr_ctx(struct sde_hw_rotator_context *ctx) +{ + struct sde_hw_rotator *rot = ctx->rot; + u32 idx = sde_hw_rotator_get_regdma_ctxidx(ctx); + unsigned long flags; + + spin_lock_irqsave(&rot->rotisr_lock, flags); + rot->rotCtx[ctx->q_id][idx] = NULL; + spin_unlock_irqrestore(&rot->rotisr_lock, flags); + + SDEROT_DBG("rotCtx[%d][%d] <== null | session-id:%d\n", + ctx->q_id, idx, ctx->session_id); +} + #endif /*_SDE_ROTATOR_R3_INTERNAL_H */ diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c index 0b44896bf6b3..7388dab92c34 100644 --- a/drivers/media/platform/msm/vidc/hfi_packetization.c +++ b/drivers/media/platform/msm/vidc/hfi_packetization.c @@ -2153,6 +2153,33 @@ int create_pkt_cmd_session_set_property( pkt->size += sizeof(u32) + sizeof(*signal_info); break; } + case HAL_PARAM_VENC_IFRAMESIZE_TYPE: + { + enum hal_iframesize_type hal = + *(enum hal_iframesize_type *)pdata; + struct hfi_iframe_size *hfi = (struct hfi_iframe_size *) + &pkt->rg_property_data[1]; + + switch (hal) { + case HAL_IFRAMESIZE_TYPE_DEFAULT: + hfi->type = HFI_IFRAME_SIZE_DEFAULT; + break; + case HAL_IFRAMESIZE_TYPE_MEDIUM: + hfi->type = HFI_IFRAME_SIZE_MEDIUM; + break; + case HAL_IFRAMESIZE_TYPE_HUGE: + hfi->type = HFI_IFRAME_SIZE_HIGH; + break; + case HAL_IFRAMESIZE_TYPE_UNLIMITED: + hfi->type = HFI_IFRAME_SIZE_UNLIMITED; + break; + default: + return -ENOTSUPP; + } + pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_VENC_IFRAMESIZE; + pkt->size += sizeof(u32) + sizeof(struct hfi_iframe_size); + break; + } /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */ case HAL_CONFIG_BUFFER_REQUIREMENTS: case HAL_CONFIG_PRIORITY: diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c index 3633d1fb3cd1..fbdccea56f67 100644 --- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c @@ -36,7 +36,7 @@ struct msm_vidc_drv *vidc_driver; -uint32_t msm_vidc_pwr_collapse_delay = 2000; +uint32_t msm_vidc_pwr_collapse_delay = 3000; static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh) { @@ -138,12 +138,20 @@ int msm_v4l2_reqbufs(struct file *file, void *fh, { struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh); int rc = 0; - if (!b->count) + if (!b->count) { rc = msm_vidc_release_buffers(vidc_inst, b->type); - if (rc) - dprintk(VIDC_WARN, - "Failed in %s for release output buffers\n", __func__); - return msm_vidc_reqbufs((void *)vidc_inst, b); + if (rc) + dprintk(VIDC_WARN, + "Failed in %s for release output buffers\n", + __func__); + } else { + rc = msm_vidc_reqbufs((void *)vidc_inst, b); + if (rc) + dprintk(VIDC_WARN, + "Failed in %s for buffer requirements\n", + __func__); + } + return rc; } int msm_v4l2_prepare_buf(struct file *file, void *fh, diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 0931242a5ec4..4ec331d121d9 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -185,6 +185,13 @@ static const char *const timestamp_mode[] = { "Ignore", }; +static const char *const iframe_sizes[] = { + "Default", + "Medium", + "Huge", + "Unlimited" +}; + static struct msm_vidc_ctrl msm_venc_ctrls[] = { { .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD, @@ -1281,6 +1288,20 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .step = 1, .qmenu = NULL, }, + { + .id = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + .name = "Bounds of I-frame size", + .type = V4L2_CTRL_TYPE_MENU, + .minimum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .maximum = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, + .default_value = V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + .menu_skip_mask = ~( + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE) | + (1 << V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED)), + .qmenu = iframe_sizes, + }, }; @@ -2117,6 +2138,19 @@ static inline int venc_v4l2_to_hal(int id, int value) default: goto unknown_value; } + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + switch (value) { + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT: + return HAL_IFRAMESIZE_TYPE_DEFAULT; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM: + return HAL_IFRAMESIZE_TYPE_MEDIUM; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE: + return HAL_IFRAMESIZE_TYPE_HUGE; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED: + return HAL_IFRAMESIZE_TYPE_UNLIMITED; + default: + goto unknown_value; + } } unknown_value: @@ -2159,6 +2193,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) int frameqp = 0; int pic_order_cnt = 0; struct hal_video_signal_info signal_info = {0}; + enum hal_iframesize_type iframesize_type = HAL_IFRAMESIZE_TYPE_DEFAULT; if (!inst || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, "%s invalid parameters\n", __func__); @@ -3242,6 +3277,13 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } pdata = &enable; break; + case V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE: + property_id = HAL_PARAM_VENC_IFRAMESIZE_TYPE; + iframesize_type = venc_v4l2_to_hal( + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE, + ctrl->val); + pdata = &iframesize_type; + break; default: dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id); rc = -ENOTSUPP; diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 93e32ef4ac35..c4d06b658b30 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -652,10 +652,6 @@ int output_buffer_cache_invalidate(struct msm_vidc_inst *inst, return -EINVAL; } - if (binfo->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - return 0; - - for (i = 0; i < binfo->num_planes; i++) { if (binfo->handle[i]) { rc = msm_comm_smem_cache_operations(inst, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 011941c6d4eb..2e1df75cb248 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c @@ -24,7 +24,7 @@ EXPORT_SYMBOL(msm_vidc_debug_out); int msm_vidc_fw_debug = 0x18; int msm_vidc_fw_debug_mode = 1; int msm_vidc_fw_low_power_mode = 1; -int msm_vidc_hw_rsp_timeout = 1000; +int msm_vidc_hw_rsp_timeout = 2000; bool msm_vidc_fw_coverage = false; bool msm_vidc_vpe_csc_601_to_709 = false; bool msm_vidc_dec_dcvs_mode = true; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index c87b6fc585c7..787ee43ccbd2 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -3407,10 +3407,12 @@ static int __response_handler(struct venus_hfi_device *device) packets = device->response_pkt; - raw_packet = kzalloc(VIDC_IFACEQ_VAR_HUGE_PKT_SIZE, GFP_TEMPORARY); + raw_packet = device->raw_packet; + if (!raw_packet || !packets) { - dprintk(VIDC_ERR, "%s: Failed to allocate memory\n", __func__); - kfree(raw_packet); + dprintk(VIDC_ERR, + "%s: Invalid args : Res packet = %p, Raw packet = %p\n", + __func__, packets, raw_packet); return 0; } @@ -3566,7 +3568,6 @@ static int __response_handler(struct venus_hfi_device *device) exit: __flush_debug_queue(device, raw_packet); - kfree(raw_packet); return packet_count; } @@ -4553,6 +4554,13 @@ static struct venus_hfi_device *__add_device(u32 device_id, goto err_cleanup; } + hdevice->raw_packet = + kzalloc(VIDC_IFACEQ_VAR_HUGE_PKT_SIZE, GFP_TEMPORARY); + if (!hdevice->raw_packet) { + dprintk(VIDC_ERR, "failed to allocate raw packet\n"); + goto err_cleanup; + } + rc = __init_regs_and_interrupts(hdevice, res); if (rc) goto err_cleanup; @@ -4590,6 +4598,7 @@ err_cleanup: if (hdevice->vidc_workq) destroy_workqueue(hdevice->vidc_workq); kfree(hdevice->response_pkt); + kfree(hdevice->raw_packet); kfree(hdevice); exit: return NULL; @@ -4631,6 +4640,7 @@ void venus_hfi_delete_device(void *device) iounmap(dev->hal_data->register_base); kfree(close->hal_data); kfree(close->response_pkt); + kfree(close->raw_packet); kfree(close); break; } diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h index 7cc71a470c2e..1d2ca88a3c1d 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.h +++ b/drivers/media/platform/msm/vidc/venus_hfi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-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 @@ -247,6 +247,7 @@ struct venus_hfi_device { struct hfi_packetization_ops *pkt_ops; enum hfi_packetization_type packetization_type; struct msm_vidc_cb_info *response_pkt; + u8 *raw_packet; struct pm_qos_request qos; unsigned int skip_pc_count; struct msm_vidc_capability *sys_init_capabilities; diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index aa566159c393..116ce12c8dba 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -242,6 +242,7 @@ enum hal_property { HAL_PARAM_VENC_SESSION_QP_RANGE_PACKED, HAL_PARAM_VENC_H264_TRANSFORM_8x8, HAL_PARAM_VENC_VIDEO_SIGNAL_INFO, + HAL_PARAM_VENC_IFRAMESIZE_TYPE, }; enum hal_domain { @@ -1002,6 +1003,13 @@ struct hal_video_signal_info { bool full_range; }; +enum hal_iframesize_type { + HAL_IFRAMESIZE_TYPE_DEFAULT, + HAL_IFRAMESIZE_TYPE_MEDIUM, + HAL_IFRAMESIZE_TYPE_HUGE, + HAL_IFRAMESIZE_TYPE_UNLIMITED, +}; + enum vidc_resource_id { VIDC_RESOURCE_NONE, VIDC_RESOURCE_OCMEM, diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h index 5e5ef6abc303..bb9958b0a819 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h @@ -386,6 +386,8 @@ struct hfi_buffer_info { (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x031) #define HFI_PROPERTY_PARAM_VENC_VQZIP_SEI_TYPE \ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x033) +#define HFI_PROPERTY_PARAM_VENC_IFRAMESIZE \ + (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x034) #define HFI_PROPERTY_CONFIG_VENC_COMMON_START \ (HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000) @@ -888,6 +890,14 @@ struct hfi_aspect_ratio { u32 aspect_height; }; +#define HFI_IFRAME_SIZE_DEFAULT (HFI_COMMON_BASE + 0x1) +#define HFI_IFRAME_SIZE_MEDIUM (HFI_COMMON_BASE + 0x2) +#define HFI_IFRAME_SIZE_HIGH (HFI_COMMON_BASE + 0x3) +#define HFI_IFRAME_SIZE_UNLIMITED (HFI_COMMON_BASE + 0x4) +struct hfi_iframe_size { + u32 type; +}; + #define HFI_MVC_BUFFER_LAYOUT_TOP_BOTTOM (0) #define HFI_MVC_BUFFER_LAYOUT_SIDEBYSIDE (1) #define HFI_MVC_BUFFER_LAYOUT_SEQ (2) diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index ce0752d3b535..240bf2903308 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -619,6 +619,7 @@ struct msm_pcie_dev_t { bool ext_ref_clk; bool common_phy; uint32_t ep_latency; + uint32_t wr_halt_size; uint32_t cpl_timeout; uint32_t current_bdf; short current_short_bdf; @@ -1976,6 +1977,8 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev) dev->common_phy); PCIE_DBG_FS(dev, "ep_latency: %dms\n", dev->ep_latency); + PCIE_DBG_FS(dev, "wr_halt_size: 0x%x\n", + dev->wr_halt_size); PCIE_DBG_FS(dev, "cpl_timeout: 0x%x\n", dev->cpl_timeout); PCIE_DBG_FS(dev, "current_bdf: 0x%x\n", @@ -4495,8 +4498,19 @@ int msm_pcie_enable(struct msm_pcie_dev_t *dev, u32 options) if (dev->use_msi) { PCIE_DBG(dev, "RC%d: enable WR halt.\n", dev->rc_idx); - msm_pcie_write_mask(dev->parf + - PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, 0, BIT(31)); + val = dev->wr_halt_size ? dev->wr_halt_size : + readl_relaxed(dev->parf + + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); + + msm_pcie_write_reg(dev->parf, + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT, + BIT(31) | val); + + PCIE_DBG(dev, + "RC%d: PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT: 0x%x.\n", + dev->rc_idx, + readl_relaxed(dev->parf + + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT)); } mutex_lock(&com_phy_lock); @@ -5385,9 +5399,6 @@ static irqreturn_t handle_linkdown_irq(int irq, void *data) dev->link_status = MSM_PCIE_LINK_DISABLED; dev->shadow_en = false; - pcie_phy_dump(dev); - pcie_parf_dump(dev); - if (dev->linkdown_panic) panic("User has chosen to panic on linkdown\n"); @@ -5696,7 +5707,7 @@ static int arch_setup_msi_irq_qgic(struct pci_dev *pdev, irq_set_msi_desc(firstirq, desc); msg.address_hi = 0; msg.address_lo = dev->msi_gicm_addr; - msg.data = dev->msi_gicm_base; + msg.data = dev->msi_gicm_base + (firstirq - dev->msi[0].num); write_msi_msg(firstirq, &msg); return 0; @@ -6071,6 +6082,18 @@ static int msm_pcie_probe(struct platform_device *pdev) PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: ep-latency: 0x%x.\n", rc_idx, msm_pcie_dev[rc_idx].ep_latency); + msm_pcie_dev[rc_idx].wr_halt_size = 0; + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wr-halt-size", + &msm_pcie_dev[rc_idx].wr_halt_size); + if (ret) + PCIE_DBG(&msm_pcie_dev[rc_idx], + "RC%d: wr-halt-size not specified in dt. Use default value.\n", + rc_idx); + else + PCIE_DBG(&msm_pcie_dev[rc_idx], "RC%d: wr-halt-size: 0x%x.\n", + rc_idx, msm_pcie_dev[rc_idx].wr_halt_size); + msm_pcie_dev[rc_idx].cpl_timeout = 0; ret = of_property_read_u32((&pdev->dev)->of_node, "qcom,cpl-timeout", diff --git a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c index 45db409eb7c1..3678f952fe0f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c +++ b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c @@ -354,6 +354,8 @@ enum msmfalcon_functions { msm_mux_blsp_i2c2, msm_mux_phase_flag31, msm_mux_blsp_spi3, + msm_mux_blsp_spi3_cs1, + msm_mux_blsp_spi3_cs2, msm_mux_wlan1_adc1, msm_mux_atest_usb13, msm_mux_tgu_ch1, @@ -380,7 +382,10 @@ enum msmfalcon_functions { msm_mux_blsp_spi4, msm_mux_pri_mi2s, msm_mux_phase_flag26, - msm_mux_qdss_cti, + msm_mux_qdss_cti0_a, + msm_mux_qdss_cti0_b, + msm_mux_qdss_cti1_a, + msm_mux_qdss_cti1_b, msm_mux_DP_HOT, msm_mux_pri_mi2s_ws, msm_mux_phase_flag27, @@ -402,7 +407,8 @@ enum msmfalcon_functions { msm_mux_phase_flag13, msm_mux_vsense_mode, msm_mux_blsp_spi7, - msm_mux_BLSP_UART, + msm_mux_blsp_uart6_a, + msm_mux_blsp_uart6_b, msm_mux_sec_mi2s, msm_mux_sndwire_clk, msm_mux_phase_flag17, @@ -415,13 +421,15 @@ enum msmfalcon_functions { msm_mux_vfr_1, msm_mux_phase_flag20, msm_mux_NFC_INT, - msm_mux_blsp_spi, + msm_mux_blsp_spi8_cs1, + msm_mux_blsp_spi8_cs2, msm_mux_m_voc, msm_mux_phase_flag21, msm_mux_NFC_EN, msm_mux_phase_flag22, msm_mux_NFC_DWL, - msm_mux_BLSP_I2C, + msm_mux_blsp_i2c8_a, + msm_mux_blsp_i2c8_b, msm_mux_phase_flag23, msm_mux_NFC_ESE, msm_mux_pwr_modem, @@ -519,10 +527,15 @@ enum msmfalcon_functions { msm_mux_atest_char0, msm_mux_US_EURO, msm_mux_LCD_BACKLIGHT, - msm_mux_blsp_spi8, + msm_mux_blsp_spi8_a, + msm_mux_blsp_spi8_b, msm_mux_sp_cmu, - msm_mux_NAV_PPS, - msm_mux_GPS_TX, + msm_mux_nav_pps_a, + msm_mux_nav_pps_b, + msm_mux_nav_pps_c, + msm_mux_gps_tx_a, + msm_mux_gps_tx_b, + msm_mux_gps_tx_c, msm_mux_adsp_ext, msm_mux_TS_RESET, msm_mux_ssc_irq, @@ -560,16 +573,23 @@ static const char * const blsp_spi1_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio46", }; static const char * const gpio_groups[] = { - "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio6", "gpio7", "gpio8", - "gpio9", "gpio10", "gpio11", "gpio14", "gpio15", "gpio16", "gpio17", - "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", "gpio24", - "gpio25", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio37", - "gpio38", "gpio39", "gpio57", "gpio58", "gpio59", "gpio61", "gpio65", - "gpio81", "gpio82", "gpio83", "gpio84", "gpio85", "gpio86", "gpio87", - "gpio88", "gpio89", "gpio90", "gpio91", "gpio92", "gpio93", "gpio94", - "gpio95", "gpio96", "gpio97", "gpio98", "gpio99", "gpio100", "gpio101", - "gpio102", "gpio103", "gpio104", "gpio105", "gpio106", "gpio107", - "gpio108", "gpio109", "gpio110", "gpio111", "gpio112", "gpio113", + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", + "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14", + "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", + "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", + "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", + "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", + "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", }; static const char * const blsp_uim1_groups[] = { "gpio0", "gpio1", @@ -599,7 +619,13 @@ static const char * const phase_flag31_groups[] = { "gpio6", }; static const char * const blsp_spi3_groups[] = { - "gpio8", "gpio9", "gpio10", "gpio11", "gpio30", "gpio65", + "gpio8", "gpio9", "gpio10", "gpio11", +}; +static const char * const blsp_spi3_cs1_groups[] = { + "gpio30", +}; +static const char * const blsp_spi3_cs2_groups[] = { + "gpio65", }; static const char * const wlan1_adc1_groups[] = { "gpio8", @@ -679,9 +705,17 @@ static const char * const pri_mi2s_groups[] = { static const char * const phase_flag26_groups[] = { "gpio12", }; -static const char * const qdss_cti_groups[] = { - "gpio12", "gpio13", "gpio21", "gpio49", "gpio50", "gpio53", "gpio55", - "gpio66", +static const char * const qdss_cti0_a_groups[] = { + "gpio49", "gpio50", +}; +static const char * const qdss_cti0_b_groups[] = { + "gpio13", "gpio21", +}; +static const char * const qdss_cti1_a_groups[] = { + "gpio53", "gpio55", +}; +static const char * const qdss_cti1_b_groups[] = { + "gpio12", "gpio66", }; static const char * const DP_HOT_groups[] = { "gpio13", @@ -746,9 +780,11 @@ static const char * const vsense_mode_groups[] = { static const char * const blsp_spi7_groups[] = { "gpio24", "gpio25", "gpio26", "gpio27", }; -static const char * const BLSP_UART_groups[] = { - "gpio24", "gpio25", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", - "gpio31", +static const char * const blsp_uart6_a_groups[] = { + "gpio24", "gpio25", "gpio26", "gpio27", +}; +static const char * const blsp_uart6_b_groups[] = { + "gpio28", "gpio29", "gpio30", "gpio31", }; static const char * const sec_mi2s_groups[] = { "gpio24", "gpio25", "gpio26", "gpio27", "gpio62", @@ -786,9 +822,11 @@ static const char * const phase_flag20_groups[] = { static const char * const NFC_INT_groups[] = { "gpio28", }; -static const char * const blsp_spi_groups[] = { - "gpio28", "gpio29", "gpio30", "gpio31", "gpio40", "gpio41", "gpio44", - "gpio52", +static const char * const blsp_spi8_a_groups[] = { + "gpio28", "gpio29", "gpio30", "gpio31", +}; +static const char * const blsp_spi8_b_groups[] = { + "gpio40", "gpio41", "gpio44", "gpio52", }; static const char * const m_voc_groups[] = { "gpio28", @@ -805,8 +843,11 @@ static const char * const phase_flag22_groups[] = { static const char * const NFC_DWL_groups[] = { "gpio30", }; -static const char * const BLSP_I2C_groups[] = { - "gpio30", "gpio31", "gpio44", "gpio52", +static const char * const blsp_i2c8_a_groups[] = { + "gpio30", "gpio31", +}; +static const char * const blsp_i2c8_b_groups[] = { + "gpio44", "gpio52", }; static const char * const phase_flag23_groups[] = { "gpio30", @@ -1099,17 +1140,32 @@ static const char * const US_EURO_groups[] = { static const char * const LCD_BACKLIGHT_groups[] = { "gpio64", }; -static const char * const blsp_spi8_groups[] = { - "gpio64", "gpio76", +static const char * const blsp_spi8_cs1_groups[] = { + "gpio64", +}; +static const char * const blsp_spi8_cs2_groups[] = { + "gpio76", }; static const char * const sp_cmu_groups[] = { "gpio64", }; -static const char * const NAV_PPS_groups[] = { - "gpio65", "gpio65", "gpio80", "gpio80", "gpio98", "gpio98", +static const char * const nav_pps_a_groups[] = { + "gpio65", }; -static const char * const GPS_TX_groups[] = { - "gpio65", "gpio80", "gpio98", +static const char * const nav_pps_b_groups[] = { + "gpio98", +}; +static const char * const nav_pps_c_groups[] = { + "gpio80", +}; +static const char * const gps_tx_a_groups[] = { + "gpio65", +}; +static const char * const gps_tx_b_groups[] = { + "gpio98", +}; +static const char * const gps_tx_c_groups[] = { + "gpio80", }; static const char * const adsp_ext_groups[] = { "gpio65", @@ -1216,6 +1272,8 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(blsp_i2c2), FUNCTION(phase_flag31), FUNCTION(blsp_spi3), + FUNCTION(blsp_spi3_cs1), + FUNCTION(blsp_spi3_cs2), FUNCTION(wlan1_adc1), FUNCTION(atest_usb13), FUNCTION(tgu_ch1), @@ -1242,7 +1300,10 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(blsp_spi4), FUNCTION(pri_mi2s), FUNCTION(phase_flag26), - FUNCTION(qdss_cti), + FUNCTION(qdss_cti0_a), + FUNCTION(qdss_cti0_b), + FUNCTION(qdss_cti1_a), + FUNCTION(qdss_cti1_b), FUNCTION(DP_HOT), FUNCTION(pri_mi2s_ws), FUNCTION(phase_flag27), @@ -1264,7 +1325,8 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(phase_flag13), FUNCTION(vsense_mode), FUNCTION(blsp_spi7), - FUNCTION(BLSP_UART), + FUNCTION(blsp_uart6_a), + FUNCTION(blsp_uart6_b), FUNCTION(sec_mi2s), FUNCTION(sndwire_clk), FUNCTION(phase_flag17), @@ -1277,13 +1339,15 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(vfr_1), FUNCTION(phase_flag20), FUNCTION(NFC_INT), - FUNCTION(blsp_spi), + FUNCTION(blsp_spi8_cs1), + FUNCTION(blsp_spi8_cs2), FUNCTION(m_voc), FUNCTION(phase_flag21), FUNCTION(NFC_EN), FUNCTION(phase_flag22), FUNCTION(NFC_DWL), - FUNCTION(BLSP_I2C), + FUNCTION(blsp_i2c8_a), + FUNCTION(blsp_i2c8_b), FUNCTION(phase_flag23), FUNCTION(NFC_ESE), FUNCTION(pwr_modem), @@ -1381,10 +1445,15 @@ static const struct msm_function msmfalcon_functions[] = { FUNCTION(atest_char0), FUNCTION(US_EURO), FUNCTION(LCD_BACKLIGHT), - FUNCTION(blsp_spi8), + FUNCTION(blsp_spi8_a), + FUNCTION(blsp_spi8_b), FUNCTION(sp_cmu), - FUNCTION(NAV_PPS), - FUNCTION(GPS_TX), + FUNCTION(nav_pps_a), + FUNCTION(nav_pps_b), + FUNCTION(nav_pps_c), + FUNCTION(gps_tx_a), + FUNCTION(gps_tx_b), + FUNCTION(gps_tx_c), FUNCTION(adsp_ext), FUNCTION(TS_RESET), FUNCTION(ssc_irq), @@ -1441,10 +1510,10 @@ static const struct msm_pingroup msmfalcon_groups[] = { atest_usb11, bimc_dte1, NA), PINGROUP(11, NORTH, blsp_spi3, blsp_i2c3, NA, dbg_out, wlan2_adc0, atest_usb10, bimc_dte0, NA, NA), - PINGROUP(12, NORTH, blsp_spi4, pri_mi2s, NA, phase_flag26, qdss_cti, + PINGROUP(12, NORTH, blsp_spi4, pri_mi2s, NA, phase_flag26, qdss_cti1_b, NA, NA, NA, NA), PINGROUP(13, NORTH, blsp_spi4, DP_HOT, pri_mi2s_ws, NA, NA, - phase_flag27, qdss_cti, NA, NA), + phase_flag27, qdss_cti0_b, NA, NA), PINGROUP(14, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, phase_flag28, NA, NA, NA, NA), PINGROUP(15, NORTH, blsp_spi4, blsp_i2c4, pri_mi2s, NA, NA, NA, NA, NA, @@ -1460,27 +1529,27 @@ static const struct msm_pingroup msmfalcon_groups[] = { PINGROUP(20, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, NA, NA, NA, NA, NA), PINGROUP(21, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, phase_flag11, - qdss_cti, vsense_data0, NA, NA), + qdss_cti0_b, vsense_data0, NA, NA), PINGROUP(22, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA, phase_flag12, vsense_data1, NA, NA, NA), PINGROUP(23, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA, phase_flag13, vsense_mode, NA, NA, NA), - PINGROUP(24, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_clk, NA, + PINGROUP(24, NORTH, blsp_spi7, blsp_uart6_a, sec_mi2s, sndwire_clk, NA, NA, phase_flag17, vsense_clkout, NA), - PINGROUP(25, NORTH, blsp_spi7, BLSP_UART, sec_mi2s, sndwire_data, NA, + PINGROUP(25, NORTH, blsp_spi7, blsp_uart6_a, sec_mi2s, sndwire_data, NA, NA, phase_flag18, NA, NA), - PINGROUP(26, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, sec_mi2s, NA, + PINGROUP(26, NORTH, blsp_spi7, blsp_uart6_a, blsp_i2c7, sec_mi2s, NA, phase_flag19, NA, NA, NA), - PINGROUP(27, NORTH, blsp_spi7, BLSP_UART, blsp_i2c7, vfr_1, sec_mi2s, + PINGROUP(27, NORTH, blsp_spi7, blsp_uart6_a, blsp_i2c7, vfr_1, sec_mi2s, NA, phase_flag20, NA, NA), - PINGROUP(28, CENTER, blsp_spi, BLSP_UART, m_voc, NA, phase_flag21, NA, - NA, NA, NA), - PINGROUP(29, CENTER, blsp_spi, BLSP_UART, NA, NA, phase_flag22, NA, NA, - NA, NA), - PINGROUP(30, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, blsp_spi3, NA, - phase_flag23, NA, NA, NA), - PINGROUP(31, CENTER, blsp_spi, BLSP_UART, BLSP_I2C, pwr_modem, NA, - phase_flag24, qdss_gpio, NA, NA), + PINGROUP(28, CENTER, blsp_spi8_a, blsp_uart6_b, m_voc, NA, phase_flag21, + NA, NA, NA, NA), + PINGROUP(29, CENTER, blsp_spi8_a, blsp_uart6_b, NA, NA, phase_flag22, + NA, NA, NA, NA), + PINGROUP(30, CENTER, blsp_spi8_a, blsp_uart6_b, blsp_i2c8_a, + blsp_spi3_cs1, NA, phase_flag23, NA, NA, NA), + PINGROUP(31, CENTER, blsp_spi8_a, blsp_uart6_b, blsp_i2c8_a, pwr_modem, + NA, phase_flag24, qdss_gpio, NA, NA), PINGROUP(32, SOUTH, cam_mclk, pwr_nav, NA, NA, qdss_gpio0, NA, NA, NA, NA), PINGROUP(33, SOUTH, cam_mclk, qspi_data0, pwr_crypto, NA, NA, @@ -1495,30 +1564,35 @@ static const struct msm_pingroup msmfalcon_groups[] = { atest_usb23, NA, NA, NA), PINGROUP(38, SOUTH, cci_i2c, NA, NA, qdss_gpio6, NA, NA, NA, NA, NA), PINGROUP(39, SOUTH, cci_i2c, NA, NA, qdss_gpio7, NA, NA, NA, NA, NA), - PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi, NA, NA, NA, NA, NA, NA), - PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi, NA, NA, NA, NA, NA, NA), + PINGROUP(40, SOUTH, CCI_TIMER0, NA, blsp_spi8_b, NA, NA, NA, NA, NA, + NA), + PINGROUP(41, SOUTH, CCI_TIMER1, NA, blsp_spi8_b, NA, NA, NA, NA, NA, + NA), PINGROUP(42, SOUTH, mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3, NA, NA, qdss_gpio9, NA, NA), PINGROUP(43, SOUTH, CCI_TIMER3, CCI_ASYNC, qspi_cs, NA, NA, qdss_gpio10, NA, NA, NA), - PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi, BLSP_I2C, NA, NA, - qdss_gpio11, NA, NA), + PINGROUP(44, SOUTH, CCI_TIMER4, CCI_ASYNC, blsp_spi8_b, blsp_i2c8_b, NA, + NA, qdss_gpio11, NA, NA), PINGROUP(45, SOUTH, cci_async, NA, NA, qdss_gpio12, NA, NA, NA, NA, NA), PINGROUP(46, SOUTH, blsp_spi1, NA, NA, qdss_gpio13, NA, NA, NA, NA, NA), PINGROUP(47, SOUTH, qspi_clk, NA, phase_flag30, qdss_gpio14, NA, NA, NA, NA, NA), PINGROUP(48, SOUTH, NA, phase_flag1, qdss_gpio15, NA, NA, NA, NA, NA, NA), - PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti, NA, NA, NA, NA, NA, NA), - PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti, NA, NA, NA, NA, + PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti0_a, NA, NA, NA, NA, NA, NA), + PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti0_a, NA, NA, NA, + NA, NA), PINGROUP(51, SOUTH, qspi_data3, NA, phase_flag15, qdss_gpio8, NA, NA, NA, NA, NA), - PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi, BLSP_I2C, NA, phase_flag16, - qdss_gpio, NA, NA, NA), - PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti, NA, NA, NA, NA, NA, NA), + PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi8_b, blsp_i2c8_b, NA, + phase_flag16, qdss_gpio, NA, NA, NA), + PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti1_a, NA, NA, NA, NA, NA, + NA), PINGROUP(54, NORTH, NA, NA, phase_flag29, NA, NA, NA, NA, NA, NA), - PINGROUP(55, SOUTH, NA, phase_flag25, qdss_cti, NA, NA, NA, NA, NA, NA), + PINGROUP(55, SOUTH, NA, phase_flag25, qdss_cti1_a, NA, NA, NA, NA, NA, + NA), PINGROUP(56, SOUTH, NA, phase_flag10, qdss_gpio3, NA, atest_usb20, NA, NA, NA, NA), PINGROUP(57, SOUTH, gcc_gp1, NA, phase_flag4, atest_usb22, NA, NA, NA, @@ -1533,11 +1607,11 @@ static const struct msm_pingroup msmfalcon_groups[] = { PINGROUP(62, NORTH, sec_mi2s, audio_ref, MDP_VSYNC, cri_trng, NA, NA, atest_char0, NA, NA), PINGROUP(63, NORTH, NA, NA, NA, qdss_gpio1, NA, NA, NA, NA, NA), - PINGROUP(64, SOUTH, blsp_spi8, sp_cmu, NA, NA, qdss_gpio2, NA, NA, NA, - NA), - PINGROUP(65, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, blsp_spi3, adsp_ext, - NA, NA, NA), - PINGROUP(66, NORTH, NA, NA, qdss_cti, NA, NA, NA, NA, NA, NA), + PINGROUP(64, SOUTH, blsp_spi8_cs1, sp_cmu, NA, NA, qdss_gpio2, NA, NA, + NA, NA), + PINGROUP(65, SOUTH, NA, nav_pps_a, nav_pps_a, gps_tx_a, blsp_spi3_cs2, + adsp_ext, NA, NA, NA), + PINGROUP(66, NORTH, NA, NA, qdss_cti1_b, NA, NA, NA, NA, NA, NA), PINGROUP(67, NORTH, NA, NA, qdss_gpio0, NA, NA, NA, NA, NA, NA), PINGROUP(68, NORTH, isense_dbg, NA, phase_flag0, qdss_gpio, NA, NA, NA, NA, NA), @@ -1550,12 +1624,13 @@ static const struct msm_pingroup msmfalcon_groups[] = { PINGROUP(73, NORTH, NA, NA, qdss_gpio15, NA, NA, NA, NA, NA, NA), PINGROUP(74, NORTH, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(75, NORTH, NA, NA, qdss_gpio8, NA, NA, NA, NA, NA, NA), - PINGROUP(76, NORTH, blsp_spi8, NA, NA, NA, qdss_gpio9, NA, NA, NA, NA), + PINGROUP(76, NORTH, blsp_spi8_cs2, NA, NA, NA, qdss_gpio9, NA, NA, NA, + NA), PINGROUP(77, NORTH, NA, NA, qdss_gpio10, NA, NA, NA, NA, NA, NA), PINGROUP(78, NORTH, gcc_gp1, NA, qdss_gpio13, NA, NA, NA, NA, NA, NA), PINGROUP(79, SOUTH, NA, NA, qdss_gpio11, NA, NA, NA, NA, NA, NA), - PINGROUP(80, SOUTH, NAV_PPS, NAV_PPS, GPS_TX, NA, NA, qdss_gpio12, NA, - NA, NA), + PINGROUP(80, SOUTH, nav_pps_b, nav_pps_b, gps_tx_c, NA, NA, qdss_gpio12, + NA, NA, NA), PINGROUP(81, CENTER, mss_lte, gcc_gp2, NA, NA, NA, NA, NA, NA, NA), PINGROUP(82, CENTER, mss_lte, gcc_gp3, NA, NA, NA, NA, NA, NA, NA), PINGROUP(83, SOUTH, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA), @@ -1573,8 +1648,8 @@ static const struct msm_pingroup msmfalcon_groups[] = { PINGROUP(95, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(96, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(97, SOUTH, NA, ldo_en, NA, NA, NA, NA, NA, NA, NA), - PINGROUP(98, SOUTH, NA, NAV_PPS, NAV_PPS, GPS_TX, ldo_update, NA, NA, - NA, NA), + PINGROUP(98, SOUTH, NA, nav_pps_c, nav_pps_c, gps_tx_b, ldo_update, NA, + NA, NA, NA), PINGROUP(99, SOUTH, qlink_request, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(100, SOUTH, qlink_enable, NA, NA, NA, NA, NA, NA, NA, NA), PINGROUP(101, SOUTH, NA, NA, NA, NA, NA, NA, NA, NA, NA), diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 804c89dc9533..73add50cf224 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -4907,20 +4907,16 @@ int ipa_iommu_map(struct iommu_domain *domain, IPADBG("domain =0x%p iova 0x%lx\n", domain, iova); IPADBG("paddr =0x%pa size 0x%x\n", &paddr, (u32)size); - /* make sure no overlapping */ + /* Checking the address overlapping */ if (domain == ipa2_get_smmu_domain()) { if (iova >= ap_cb->va_start && iova < ap_cb->va_end) { IPAERR("iommu AP overlap addr 0x%lx\n", iova); - ipa_assert(); - return -EFAULT; } } else if (domain == ipa2_get_wlan_smmu_domain()) { /* wlan is one time map */ } else if (domain == ipa2_get_uc_smmu_domain()) { if (iova >= uc_cb->va_start && iova < uc_cb->va_end) { IPAERR("iommu uC overlap addr 0x%lx\n", iova); - ipa_assert(); - return -EFAULT; } } else { IPAERR("Unexpected domain 0x%p\n", domain); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c index cb47773e8a39..21ce28204069 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c @@ -585,7 +585,9 @@ send_cmd: if (ipa3_ctx->uc_ctx.uc_status != expected_status) { if (ipa3_ctx->uc_ctx.uc_status == - IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) { + IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE || + ipa3_ctx->uc_ctx.uc_status == + IPA_HW_CONS_DISABLE_CMD_GSI_STOP_FAILURE) { retries++; if (retries == IPA_GSI_CHANNEL_STOP_MAX_RETRY) { IPAERR("Failed after %d tries\n", retries); @@ -594,7 +596,9 @@ send_cmd: return -EFAULT; } IPA3_UC_UNLOCK(flags); - ipa3_inject_dma_task_for_gsi(); + if (ipa3_ctx->uc_ctx.uc_status == + IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE) + ipa3_inject_dma_task_for_gsi(); /* sleep for short period to flush IPA */ usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC, IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC); diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 3f67f49377b4..d612016b1b79 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -74,6 +74,7 @@ enum fg_debug_flag { FG_BUS_WRITE = BIT(5), /* Show REGMAP writes */ FG_BUS_READ = BIT(6), /* Show REGMAP reads */ FG_CAP_LEARN = BIT(7), /* Show capacity learning */ + FG_TTF = BIT(8), /* Show time to full */ }; /* SRAM access */ @@ -128,6 +129,7 @@ enum { */ enum fg_sram_param_id { FG_SRAM_BATT_SOC = 0, + FG_SRAM_FULL_SOC, FG_SRAM_VOLTAGE_PRED, FG_SRAM_OCV, FG_SRAM_RSLOW, @@ -250,6 +252,29 @@ struct fg_irq_info { int irq; }; +struct fg_circ_buf { + int arr[20]; + int size; + int head; +}; + +struct fg_pt { + s32 x; + s32 y; +}; + +static const struct fg_pt fg_ln_table[] = { + { 1000, 0 }, + { 2000, 693 }, + { 4000, 1386 }, + { 6000, 1792 }, + { 8000, 2079 }, + { 16000, 2773 }, + { 32000, 3466 }, + { 64000, 4159 }, + { 128000, 4852 }, +}; + struct fg_chip { struct device *dev; struct pmic_revid_data *pmic_rev_id; @@ -275,12 +300,15 @@ struct fg_chip { struct fg_cap_learning cl; struct mutex bus_lock; struct mutex sram_rw_lock; + struct mutex batt_avg_lock; u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; int batt_id_kohms; - int status; + int charge_status; + int prev_charge_status; int charge_done; + int charge_type; int last_soc; int last_batt_temp; int health; @@ -297,6 +325,9 @@ struct fg_chip { struct delayed_work profile_load_work; struct work_struct status_change_work; struct work_struct cycle_count_work; + struct delayed_work batt_avg_work; + struct fg_circ_buf ibatt_circ_buf; + struct fg_circ_buf vbatt_circ_buf; }; /* Debugfs data structures are below */ @@ -348,4 +379,8 @@ extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len); extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos); extern s64 fg_float_decode(u16 val); extern bool is_input_present(struct fg_chip *chip); +extern void fg_circ_buf_add(struct fg_circ_buf *, int); +extern void fg_circ_buf_clr(struct fg_circ_buf *); +extern int fg_circ_buf_avg(struct fg_circ_buf *, int *); +extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *); #endif diff --git a/drivers/power/qcom-charger/fg-util.c b/drivers/power/qcom-charger/fg-util.c index 0e3c7dbb5731..405d875ea7df 100644 --- a/drivers/power/qcom-charger/fg-util.c +++ b/drivers/power/qcom-charger/fg-util.c @@ -14,6 +14,82 @@ #include "fg-core.h" +void fg_circ_buf_add(struct fg_circ_buf *buf, int val) +{ + buf->arr[buf->head] = val; + buf->head = (buf->head + 1) % ARRAY_SIZE(buf->arr); + buf->size = min(++buf->size, (int)ARRAY_SIZE(buf->arr)); +} + +void fg_circ_buf_clr(struct fg_circ_buf *buf) +{ + memset(buf, 0, sizeof(*buf)); +} + +int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg) +{ + s64 result = 0; + int i; + + if (buf->size == 0) + return -ENODATA; + + for (i = 0; i < buf->size; i++) + result += buf->arr[i]; + + *avg = div_s64(result, buf->size); + return 0; +} + +int fg_lerp(const struct fg_pt *pts, size_t tablesize, s32 input, s32 *output) +{ + int i; + s64 temp; + + if (pts == NULL) { + pr_err("Table is NULL\n"); + return -EINVAL; + } + + if (tablesize < 1) { + pr_err("Table has no entries\n"); + return -ENOENT; + } + + if (tablesize == 1) { + *output = pts[0].y; + return 0; + } + + if (pts[0].x > pts[1].x) { + pr_err("Table is not in acending order\n"); + return -EINVAL; + } + + if (input <= pts[0].x) { + *output = pts[0].y; + return 0; + } + + if (input >= pts[tablesize - 1].x) { + *output = pts[tablesize - 1].y; + return 0; + } + + for (i = 1; i < tablesize; i++) { + if (input >= pts[i].x) + continue; + + temp = (s64)(pts[i].y - pts[i - 1].y) * + (s64)(input - pts[i - 1].x); + temp = div_s64(temp, pts[i].x - pts[i - 1].x); + *output = temp + pts[i - 1].y; + return 0; + } + + return -EINVAL; +} + static struct fg_dbgfs dbgfs_data = { .help_msg = { .data = diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index dfbf1adc5a38..100153280d9e 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -146,6 +146,8 @@ static void fg_encode_default(struct fg_sram_param *sp, static struct fg_sram_param pmicobalt_v1_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL, + fg_decode_default), PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141, 1000, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL, @@ -198,6 +200,8 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = { static struct fg_sram_param pmicobalt_v2_sram_params[] = { PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL, fg_decode_default), + PARAM(FULL_SOC, FULL_SOC_WORD, FULL_SOC_OFFSET, 2, 1, 1, 0, NULL, + fg_decode_default), PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141, 1000, 0, NULL, fg_decode_voltage_15b), PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL, @@ -1196,11 +1200,11 @@ static void fg_cap_learning_update(struct fg_chip *chip) batt_soc = (u32)batt_soc >> 24; fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n", - chip->status, chip->cl.active, batt_soc); + chip->charge_status, chip->cl.active, batt_soc); /* Initialize the starting point of learning capacity */ if (!chip->cl.active) { - if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { rc = fg_cap_learning_begin(chip, batt_soc); chip->cl.active = (rc == 0); } @@ -1216,7 +1220,7 @@ static void fg_cap_learning_update(struct fg_chip *chip) chip->cl.init_cc_uah = 0; } - if (chip->status == POWER_SUPPLY_STATUS_NOT_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", batt_soc); chip->cl.active = false; @@ -1246,7 +1250,7 @@ static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip) return rc; } - if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) { if (msoc < chip->dt.ki_coeff_soc[i]) { ki_coeff_med = chip->dt.ki_coeff_med_dischg[i]; @@ -1320,7 +1324,7 @@ static int fg_charge_full_update(struct fg_chip *chip) } fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc, - chip->health, chip->status); + chip->health, chip->charge_status); if (chip->charge_done) { if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) chip->charge_full = true; @@ -1438,10 +1442,11 @@ static int fg_esr_fcc_config(struct fg_chip *chip) parallel_en = prop.intval; } - fg_dbg(chip, FG_POWER_SUPPLY, "status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n", - chip->status, parallel_en, chip->esr_fcc_ctrl_en); + fg_dbg(chip, FG_POWER_SUPPLY, "charge_status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n", + chip->charge_status, parallel_en, chip->esr_fcc_ctrl_en); - if (chip->status == POWER_SUPPLY_STATUS_CHARGING && parallel_en) { + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING && + parallel_en) { if (chip->esr_fcc_ctrl_en) return 0; @@ -1487,6 +1492,21 @@ static int fg_esr_fcc_config(struct fg_chip *chip) return 0; } +static void fg_batt_avg_update(struct fg_chip *chip) +{ + if (chip->charge_status == chip->prev_charge_status) + return; + + cancel_delayed_work_sync(&chip->batt_avg_work); + fg_circ_buf_clr(&chip->ibatt_circ_buf); + fg_circ_buf_clr(&chip->vbatt_circ_buf); + + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING || + chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) + schedule_delayed_work(&chip->batt_avg_work, + msecs_to_jiffies(2000)); +} + static void status_change_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, @@ -1506,7 +1526,16 @@ static void status_change_work(struct work_struct *work) goto out; } - chip->status = prop.intval; + chip->prev_charge_status = chip->charge_status; + chip->charge_status = prop.intval; + rc = power_supply_get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_TYPE, &prop); + if (rc < 0) { + pr_err("Error in getting charge type, rc=%d\n", rc); + goto out; + } + + chip->charge_type = prop.intval; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_CHARGE_DONE, &prop); if (rc < 0) { @@ -1515,9 +1544,6 @@ static void status_change_work(struct work_struct *work) } chip->charge_done = prop.intval; - fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n", - chip->status, chip->charge_done); - if (chip->cyc_ctr.en) schedule_work(&chip->cycle_count_work); @@ -1538,7 +1564,12 @@ static void status_change_work(struct work_struct *work) rc = fg_esr_fcc_config(chip); if (rc < 0) pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc); + + fg_batt_avg_update(chip); + out: + fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n", + chip->charge_status, chip->charge_type, chip->charge_done); pm_relax(chip->dev); } @@ -1625,7 +1656,7 @@ static void cycle_count_work(struct work_struct *work) /* We need only the most significant byte here */ batt_soc = (u32)batt_soc >> 24; - if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) { /* Find out which bucket the SOC falls in */ bucket = batt_soc / BUCKET_SOC_PCT; pr_debug("batt_soc: %d bucket: %d\n", batt_soc, bucket); @@ -1942,6 +1973,229 @@ static struct kernel_param_ops fg_restart_ops = { module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); +#define BATT_AVG_POLL_PERIOD_MS 10000 +static void batt_avg_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + batt_avg_work.work); + int rc, ibatt_now, vbatt_now; + + mutex_lock(&chip->batt_avg_lock); + rc = fg_get_battery_current(chip, &ibatt_now); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + goto reschedule; + } + + rc = fg_get_battery_voltage(chip, &vbatt_now); + if (rc < 0) { + pr_err("failed to get battery voltage, rc=%d\n", rc); + goto reschedule; + } + + fg_circ_buf_add(&chip->ibatt_circ_buf, ibatt_now); + fg_circ_buf_add(&chip->vbatt_circ_buf, vbatt_now); + +reschedule: + mutex_unlock(&chip->batt_avg_lock); + schedule_delayed_work(&chip->batt_avg_work, + msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS)); +} + +#define DECI_TAU_SCALE 13 +#define HOURS_TO_SECONDS 3600 +#define OCV_SLOPE_UV 10869 +#define MILLI_UNIT 1000 +#define MICRO_UNIT 1000000 +static int fg_get_time_to_full(struct fg_chip *chip, int *val) +{ + int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc, + act_cap_uah; + s32 i_cc2cv, soc_cc2cv, ln_val; + s64 t_predicted_cc = 0, t_predicted_cv = 0; + + if (chip->bp.float_volt_uv <= 0) { + pr_err("battery profile is not loaded\n"); + return -ENODATA; + } + + if (!is_charger_available(chip)) { + fg_dbg(chip, FG_TTF, "charger is not available\n"); + return -ENODATA; + } + + if (chip->charge_status == POWER_SUPPLY_STATUS_FULL) { + *val = 0; + return 0; + } + + mutex_lock(&chip->batt_avg_lock); + rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg); + if (rc < 0) { + /* try to get instantaneous current */ + rc = fg_get_battery_current(chip, &ibatt_avg); + if (rc < 0) { + mutex_unlock(&chip->batt_avg_lock); + pr_err("failed to get battery current, rc=%d\n", rc); + return rc; + } + } + + rc = fg_circ_buf_avg(&chip->vbatt_circ_buf, &vbatt_avg); + if (rc < 0) { + /* try to get instantaneous voltage */ + rc = fg_get_battery_voltage(chip, &vbatt_avg); + if (rc < 0) { + mutex_unlock(&chip->batt_avg_lock); + pr_err("failed to get battery voltage, rc=%d\n", rc); + return rc; + } + } + + mutex_unlock(&chip->batt_avg_lock); + fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg); + + /* clamp ibatt_avg to -150mA */ + if (ibatt_avg > -150000) + ibatt_avg = -150000; + fg_dbg(chip, FG_TTF, "ibatt_avg=%d\n", ibatt_avg); + + /* reverse polarity to be consistent with unsigned current settings */ + ibatt_avg = abs(ibatt_avg); + + /* estimated battery current at the CC to CV transition */ + i_cc2cv = div_s64((s64)ibatt_avg * vbatt_avg, chip->bp.float_volt_uv); + fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv); + + rc = fg_get_battery_resistance(chip, &rbatt); + if (rc < 0) { + pr_err("failed to get battery resistance rc=%d\n", rc); + return rc; + } + + /* clamp rbatt to 50mOhms */ + if (rbatt < 50000) + rbatt = 50000; + + fg_dbg(chip, FG_TTF, "rbatt=%d\n", rbatt); + + rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah); + if (rc < 0) { + pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc); + return rc; + } + act_cap_uah *= MILLI_UNIT; + fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah); + + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("failed to get msoc rc=%d\n", rc); + return rc; + } + fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc); + + rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc); + if (rc < 0) { + pr_err("failed to get full soc rc=%d\n", rc); + return rc; + } + full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY, + FULL_SOC_RAW); + fg_dbg(chip, FG_TTF, "full_soc=%d\n", full_soc); + + /* if we are already in CV state then we can skip estimating CC */ + if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + goto skip_cc_estimate; + + /* if the charger is current limited then use power approximation */ + if (ibatt_avg > chip->bp.fastchg_curr_ma * MILLI_UNIT - 50000) + ocv_cc2cv = div_s64((s64)rbatt * ibatt_avg, MICRO_UNIT); + else + ocv_cc2cv = div_s64((s64)rbatt * i_cc2cv, MICRO_UNIT); + ocv_cc2cv = chip->bp.float_volt_uv - ocv_cc2cv; + fg_dbg(chip, FG_TTF, "ocv_cc2cv=%d\n", ocv_cc2cv); + + soc_cc2cv = div_s64(chip->bp.float_volt_uv - ocv_cc2cv, OCV_SLOPE_UV); + /* estimated SOC at the CC to CV transition */ + soc_cc2cv = 100 - soc_cc2cv; + fg_dbg(chip, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv); + + /* the esimated SOC may be lower than the current SOC */ + if (soc_cc2cv - msoc <= 0) + goto skip_cc_estimate; + + t_predicted_cc = div_s64((s64)full_soc * act_cap_uah, 100); + t_predicted_cc = div_s64(t_predicted_cc * (soc_cc2cv - msoc), 100); + t_predicted_cc *= HOURS_TO_SECONDS; + t_predicted_cc = div_s64(t_predicted_cc, (ibatt_avg + i_cc2cv) / 2); + +skip_cc_estimate: + fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc); + + /* CV estimate starts here */ + if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER) + ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma); + else + ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma); + + fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val); + rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val); + fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val); + t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT); + t_predicted_cv = div_s64(t_predicted_cv * DECI_TAU_SCALE, 10); + t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT); + t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT); + fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv); + *val = t_predicted_cc + t_predicted_cv; + return 0; +} + +#define CENTI_ICORRECT_C0 105 +#define CENTI_ICORRECT_C1 20 +static int fg_get_time_to_empty(struct fg_chip *chip, int *val) +{ + int rc, ibatt_avg, msoc, act_cap_uah; + s32 divisor; + s64 t_predicted; + + rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg); + if (rc < 0) { + /* try to get instantaneous current */ + rc = fg_get_battery_current(chip, &ibatt_avg); + if (rc < 0) { + pr_err("failed to get battery current, rc=%d\n", rc); + return rc; + } + } + + /* clamp ibatt_avg to 150mA */ + if (ibatt_avg < 150000) + ibatt_avg = 150000; + + rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah); + if (rc < 0) { + pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc); + return rc; + } + act_cap_uah *= MILLI_UNIT; + + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("Error in getting capacity, rc=%d\n", rc); + return rc; + } + + t_predicted = div_s64((s64)msoc * act_cap_uah, 100); + t_predicted *= HOURS_TO_SECONDS; + divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc; + divisor = div_s64((s64)divisor * ibatt_avg, 10000); + if (divisor > 0) + t_predicted = div_s64(t_predicted, divisor); + + *val = t_predicted; + return 0; +} + /* PSY CALLBACKS STAY HERE */ static int fg_psy_get_property(struct power_supply *psy, @@ -2003,11 +2257,22 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CHARGE_COUNTER: rc = fg_get_cc_soc_sw(chip, &pval->intval); break; + case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: + rc = fg_get_time_to_full(chip, &pval->intval); + break; + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: + rc = fg_get_time_to_empty(chip, &pval->intval); + break; default: + pr_err("unsupported property %d\n", psp); + rc = -EINVAL; break; } - return rc; + if (rc < 0) + return -ENODATA; + + return 0; } static int fg_psy_set_property(struct power_supply *psy, @@ -2090,6 +2355,8 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, + POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, }; static const struct power_supply_desc fg_psy_desc = { @@ -2964,6 +3231,8 @@ static int fg_gen3_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->debug_mask = &fg_gen3_debug_mask; chip->irqs = fg_irqs; + chip->charge_status = -EINVAL; + chip->prev_charge_status = -EINVAL; chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { dev_err(chip->dev, "Parent regmap is unavailable\n"); @@ -2988,11 +3257,13 @@ static int fg_gen3_probe(struct platform_device *pdev) mutex_init(&chip->sram_rw_lock); mutex_init(&chip->cyc_ctr.lock); mutex_init(&chip->cl.lock); + mutex_init(&chip->batt_avg_lock); init_completion(&chip->soc_update); init_completion(&chip->soc_ready); INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work); INIT_WORK(&chip->status_change_work, status_change_work); INIT_WORK(&chip->cycle_count_work, cycle_count_work); + INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work); rc = fg_memif_init(chip); if (rc < 0) { @@ -3085,6 +3356,7 @@ static int fg_gen3_suspend(struct device *dev) } } + cancel_delayed_work_sync(&chip->batt_avg_work); return 0; } @@ -3103,6 +3375,9 @@ static int fg_gen3_resume(struct device *dev) } } + fg_circ_buf_clr(&chip->ibatt_circ_buf); + fg_circ_buf_clr(&chip->vbatt_circ_buf); + schedule_delayed_work(&chip->batt_avg_work, 0); return 0; } diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c index a00ad8343a88..6968ab2ab11c 100644 --- a/drivers/power/qcom-charger/qpnp-smb2.c +++ b/drivers/power/qcom-charger/qpnp-smb2.c @@ -1049,6 +1049,7 @@ static int smb2_init_hw(struct smb2 *chip) { struct smb_charger *chg = &chip->chg; int rc; + u8 stat; if (chip->dt.no_battery) chg->fake_capacity = 50; @@ -1069,6 +1070,21 @@ static int smb2_init_hw(struct smb2 *chip) chg->otg_cl_ua = chip->dt.otg_cl_ua; + rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat); + if (rc < 0) { + pr_err("Couldn't read APSD_RESULT_STATUS rc=%d\n", rc); + return rc; + } + + /* clear the ICL override if it is set */ + if (stat & ICL_OVERRIDE_LATCH_BIT) { + rc = smblib_write(chg, CMD_APSD_REG, ICL_OVERRIDE_BIT); + if (rc < 0) { + pr_err("Couldn't disable ICL override rc=%d\n", rc); + return rc; + } + } + /* votes must be cast before configuring software control */ vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); @@ -1161,6 +1177,15 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } + /* increase VCONN softstart */ + rc = smblib_masked_write(chg, TYPE_C_CFG_2_REG, + VCONN_SOFTSTART_CFG_MASK, VCONN_SOFTSTART_CFG_MASK); + if (rc < 0) { + dev_err(chg->dev, "Couldn't increase VCONN softstart rc=%d\n", + rc); + return rc; + } + rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG, QNOVO_PT_ENABLE_CMD_BIT, QNOVO_PT_ENABLE_CMD_BIT); if (rc < 0) { @@ -1183,13 +1208,12 @@ static int smb2_init_hw(struct smb2 *chip) return rc; } - /* configure PMI stat output to enable and disable parallel charging */ + /* disable SW STAT override */ rc = smblib_masked_write(chg, STAT_CFG_REG, - STAT_PARALLEL_CFG_BIT | STAT_SW_OVERRIDE_CFG_BIT, - STAT_PARALLEL_CFG_BIT); + STAT_SW_OVERRIDE_CFG_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure signal for parallel rc=%d\n", rc); + dev_err(chg->dev, "Couldn't disable SW STAT override rc=%d\n", + rc); return rc; } @@ -1287,6 +1311,8 @@ static int smb2_setup_wa_flags(struct smb2 *chip) chip->chg.wa_flags |= BOOST_BACK_WA; if (pmic_rev_id->rev4 == PMICOBALT_V1P1_REV4) /* PMI rev 1.1 */ chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT; + if (pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4) /* PMI rev 2.0 */ + chg->wa_flags |= TYPEC_CC2_REMOVAL_WA_BIT; break; default: pr_err("PMIC subtype %d not supported\n", diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 144169ea4930..6aae7d49271f 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -1464,21 +1464,17 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg, int smblib_get_prop_dc_present(struct smb_charger *chg, union power_supply_propval *val) { - int rc = 0; + int rc; u8 stat; - rc = smblib_read(chg, DC_INT_RT_STS_REG, &stat); + rc = smblib_read(chg, DCIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { - smblib_err(chg, "Couldn't read DC_INT_RT_STS_REG rc=%d\n", - rc); + smblib_err(chg, "Couldn't read DCIN_RT_STS rc=%d\n", rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "DC_INT_RT_STS_REG = 0x%02x\n", - stat); val->intval = (bool)(stat & DCIN_PLUGIN_RT_STS_BIT); - - return rc; + return 0; } int smblib_get_prop_dc_online(struct smb_charger *chg, @@ -1534,20 +1530,17 @@ int smblib_set_prop_dc_current_max(struct smb_charger *chg, int smblib_get_prop_usb_present(struct smb_charger *chg, union power_supply_propval *val) { - int rc = 0; + int rc; u8 stat; - rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); + rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { - smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc); + smblib_err(chg, "Couldn't read USBIN_RT_STS rc=%d\n", rc); return rc; } - smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", - stat); - - val->intval = (bool)(stat & CC_ATTACHED_BIT); - return rc; + val->intval = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); + return 0; } int smblib_get_prop_usb_online(struct smb_charger *chg, @@ -2129,6 +2122,100 @@ int smblib_reg_block_restore(struct smb_charger *chg, return rc; } +static struct reg_info cc2_detach_settings[] = { + { + .reg = TYPE_C_CFG_2_REG, + .mask = TYPE_C_UFP_MODE_BIT | EN_TRY_SOURCE_MODE_BIT, + .val = TYPE_C_UFP_MODE_BIT, + .desc = "TYPE_C_CFG_2_REG", + }, + { + .reg = TYPE_C_CFG_3_REG, + .mask = EN_TRYSINK_MODE_BIT, + .val = 0, + .desc = "TYPE_C_CFG_3_REG", + }, + { + .reg = TAPER_TIMER_SEL_CFG_REG, + .mask = TYPEC_SPARE_CFG_BIT, + .val = TYPEC_SPARE_CFG_BIT, + .desc = "TAPER_TIMER_SEL_CFG_REG", + }, + { + .reg = TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + .mask = VCONN_EN_ORIENTATION_BIT, + .val = 0, + .desc = "TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG", + }, + { + .reg = MISC_CFG_REG, + .mask = TCC_DEBOUNCE_20MS_BIT, + .val = TCC_DEBOUNCE_20MS_BIT, + .desc = "Tccdebounce time" + }, + { + }, +}; + +static int smblib_cc2_sink_removal_enter(struct smb_charger *chg) +{ + int rc = 0; + union power_supply_propval cc2_val = {0, }; + + if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0) + return rc; + + if (chg->cc2_sink_detach_flag != CC2_SINK_NONE) + return rc; + + rc = smblib_get_prop_typec_cc_orientation(chg, &cc2_val); + if (rc < 0) { + smblib_err(chg, "Couldn't get cc orientation rc=%d\n", rc); + return rc; + } + if (cc2_val.intval == 1) + return rc; + + rc = smblib_get_prop_typec_mode(chg, &cc2_val); + if (rc < 0) { + smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc); + return rc; + } + + switch (cc2_val.intval) { + case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT: + smblib_reg_block_update(chg, cc2_detach_settings); + chg->cc2_sink_detach_flag = CC2_SINK_STD; + schedule_work(&chg->rdstd_cc2_detach_work); + break; + case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM: + case POWER_SUPPLY_TYPEC_SOURCE_HIGH: + chg->cc2_sink_detach_flag = CC2_SINK_MEDIUM_HIGH; + break; + default: + break; + } + + return rc; +} + +static int smblib_cc2_sink_removal_exit(struct smb_charger *chg) +{ + int rc = 0; + + if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0) + return rc; + + if (chg->cc2_sink_detach_flag == CC2_SINK_STD) { + cancel_work_sync(&chg->rdstd_cc2_detach_work); + smblib_reg_block_restore(chg, cc2_detach_settings); + } + + chg->cc2_sink_detach_flag = CC2_SINK_NONE; + + return rc; +} + int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, const union power_supply_propval *val) { @@ -2137,9 +2224,24 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg, 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); + if (rc < 0) { + smblib_err(chg, "Could not set EXIT_SNK_BASED_ON_CC rc=%d\n", + rc); + return rc; + } vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0); + if (val->intval) + rc = smblib_cc2_sink_removal_enter(chg); + else + rc = smblib_cc2_sink_removal_exit(chg); + + if (rc < 0) { + smblib_err(chg, "Could not detect cc2 removal rc=%d\n", rc); + return rc; + } + return rc; } @@ -2310,6 +2412,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) struct smb_charger *chg = irq_data->parent_data; int rc; u8 stat; + bool vbus_rising; rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat); if (rc < 0) { @@ -2317,9 +2420,9 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) return IRQ_HANDLED; } - chg->vbus_present = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); + vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT); smblib_set_opt_freq_buck(chg, - chg->vbus_present ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL); + vbus_rising ? FSW_600HZ_FOR_5V : FSW_1MHZ_FOR_REMOVAL); /* fetch the DPDM regulator */ if (!chg->dpdm_reg && of_get_property(chg->dev->of_node, @@ -2332,7 +2435,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) } } - if (chg->vbus_present) { + if (vbus_rising) { if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) { smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n"); rc = regulator_enable(chg->dpdm_reg); @@ -2359,7 +2462,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data) power_supply_changed(chg->usb_psy); smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n", - irq_data->name, chg->vbus_present ? "attached" : "detached"); + irq_data->name, vbus_rising ? "attached" : "detached"); return IRQ_HANDLED; } @@ -2726,6 +2829,24 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg, if (rc < 0) smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc); + /* + * HW BUG - after cable is removed, medium or high rd reading + * falls to std. Use it for signal of typec cc detachment in + * software WA. + */ + if (chg->cc2_sink_detach_flag == CC2_SINK_MEDIUM_HIGH + && pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) { + + chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE; + + rc = smblib_masked_write(chg, + TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + EXIT_SNK_BASED_ON_CC_BIT, 0); + if (rc < 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", smblib_typec_mode_name[pval.intval]); @@ -2739,6 +2860,10 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) u8 stat; bool debounce_done, sink_attached, legacy_cable; + /* WA - not when PD hard_reset WIP on cc2 in sink mode */ + if (chg->cc2_sink_detach_flag == CC2_SINK_STD) + return IRQ_HANDLED; + 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); @@ -2923,6 +3048,74 @@ static void clear_hdc_work(struct work_struct *work) chg->is_hdc = 0; } +static void rdstd_cc2_detach_work(struct work_struct *work) +{ + int rc; + u8 stat; + struct smb_irq_data irq_data = {NULL, "cc2-removal-workaround"}; + struct smb_charger *chg = container_of(work, struct smb_charger, + rdstd_cc2_detach_work); + + /* + * WA steps - + * 1. Enable both UFP and DFP, wait for 10ms. + * 2. Disable DFP, wait for 30ms. + * 3. Removal detected if both TYPEC_DEBOUNCE_DONE_STATUS + * and TIMER_STAGE bits are gone, otherwise repeat all by + * work rescheduling. + * Note, work will be cancelled when pd_hard_reset is 0. + */ + + rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc); + return; + } + + usleep_range(10000, 11000); + + rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + UFP_EN_CMD_BIT | DFP_EN_CMD_BIT, + UFP_EN_CMD_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't write TYPE_C_CTRL_REG rc=%d\n", rc); + return; + } + + usleep_range(30000, 31000); + + 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; + } + if (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT) + goto rerun; + + rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat); + if (rc < 0) { + smblib_err(chg, + "Couldn't read TYPE_C_STATUS_5_REG rc=%d\n", rc); + return; + } + if (stat & TIMER_STAGE_2_BIT) + goto rerun; + + /* Bingo, cc2 removal detected */ + smblib_reg_block_restore(chg, cc2_detach_settings); + chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE; + irq_data.parent_data = chg; + smblib_handle_usb_typec_change(0, &irq_data); + + return; + +rerun: + schedule_work(&chg->rdstd_cc2_detach_work); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; @@ -3105,6 +3298,7 @@ int smblib_init(struct smb_charger *chg) mutex_init(&chg->write_lock); INIT_WORK(&chg->bms_update_work, bms_update_work); INIT_WORK(&chg->pl_detect_work, smblib_pl_detect_work); + INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work); INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work); INIT_DELAYED_WORK(&chg->pl_taper_work, smblib_pl_taper_work); INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work); diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index 2809ddadbd90..a0237412ee8b 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -54,9 +54,17 @@ enum smb_mode { NUM_MODES, }; +enum cc2_sink_type { + CC2_SINK_NONE = 0, + CC2_SINK_STD, + CC2_SINK_MEDIUM_HIGH, + CC2_SINK_WA_DONE, +}; + enum { - QC_CHARGER_DETECTION_WA_BIT = BIT(0), - BOOST_BACK_WA = BIT(1), + QC_CHARGER_DETECTION_WA_BIT = BIT(0), + BOOST_BACK_WA = BIT(1), + TYPEC_CC2_REMOVAL_WA_BIT = BIT(2), }; struct smb_regulator { @@ -177,6 +185,7 @@ struct smb_charger { /* work */ struct work_struct bms_update_work; struct work_struct pl_detect_work; + struct work_struct rdstd_cc2_detach_work; struct delayed_work hvdcp_detect_work; struct delayed_work ps_change_timeout_work; struct delayed_work pl_taper_work; @@ -187,7 +196,6 @@ struct smb_charger { int voltage_min_uv; int voltage_max_uv; int pd_active; - bool vbus_present; bool system_suspend_supported; int system_temp_level; @@ -205,6 +213,7 @@ struct smb_charger { /* workaround flag */ u32 wa_flags; + enum cc2_sink_type cc2_sink_detach_flag; }; int smblib_read(struct smb_charger *chg, u16 addr, u8 *val); diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index 2aed4cf294a2..c2a2b0c86d73 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -705,9 +705,6 @@ enum { #define WIPWR_RANGE_STATUS_REG (DCIN_BASE + 0x08) #define WIPWR_RANGE_STATUS_MASK GENMASK(4, 0) -#define DC_INT_RT_STS_REG (DCIN_BASE + 0x10) -#define DCIN_PLUGIN_RT_STS_BIT BIT(4) - /* DCIN Interrupt Bits */ #define WIPWR_VOLTAGE_RANGE_RT_STS_BIT BIT(7) #define DCIN_ICL_CHANGE_RT_STS_BIT BIT(6) @@ -905,6 +902,7 @@ enum { #define MISC_CFG_REG (MISC_BASE + 0x52) #define GSM_PA_ON_ADJ_SEL_BIT BIT(0) +#define TCC_DEBOUNCE_20MS_BIT BIT(5) #define SNARL_BARK_BITE_WD_CFG_REG (MISC_BASE + 0x53) #define BITE_WDOG_DISABLE_CHARGING_CFG_BIT BIT(7) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 862d56e78086..19a8aacf98d0 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2633,6 +2633,65 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id) } /** + * ufshcd_get_write_lock - synchronize between shutdown, scaling & + * arrival of requests + * @hba: ufs host + * + * Lock is predominantly held by shutdown context thus, ensuring + * that no requests from any other context may sneak through. + */ +static void ufshcd_get_write_lock(struct ufs_hba *hba) +{ + down_write(&hba->lock); + hba->issuing_task = current; +} + +/** + * ufshcd_get_read_lock - synchronize between shutdown, scaling & + * arrival of requests + * @hba: ufs host + * + * Returns 1 if acquired, < 0 on contention + * + * After shutdown's initiated, allow requests only from shutdown + * context. The sync between scaling & issue is maintained + * as is and this restructuring syncs shutdown with these too. + */ +static int ufshcd_get_read_lock(struct ufs_hba *hba) +{ + int err = 0; + + err = down_read_trylock(&hba->lock); + if (err > 0) + goto out; + if (hba->issuing_task == current) + return 0; + else if (!ufshcd_is_shutdown_ongoing(hba)) + return -EAGAIN; + else + return -EPERM; + +out: + hba->issuing_task = current; + return err; +} + +/** + * ufshcd_put_read_lock - synchronize between shutdown, scaling & + * arrival of requests + * @hba: ufs host + * + * Returns none + */ +static inline void ufshcd_put_read_lock(struct ufs_hba *hba) +{ + if (!ufshcd_is_shutdown_ongoing(hba)) { + hba->issuing_task = NULL; + up_read(&hba->lock); + } +} + +/** * ufshcd_queuecommand - main entry point for SCSI requests * @cmd: command from SCSI Midlayer * @done: call back function @@ -2657,8 +2716,16 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) BUG(); } - if (!down_read_trylock(&hba->clk_scaling_lock)) - return SCSI_MLQUEUE_HOST_BUSY; + err = ufshcd_get_read_lock(hba); + if (unlikely(err < 0)) { + if (err == -EPERM) { + set_host_byte(cmd, DID_ERROR); + cmd->scsi_done(cmd); + return 0; + } + if (err == -EAGAIN) + return SCSI_MLQUEUE_HOST_BUSY; + } spin_lock_irqsave(hba->host->host_lock, flags); @@ -2798,7 +2865,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) out_unlock: spin_unlock_irqrestore(hba->host->host_lock, flags); out: - up_read(&hba->clk_scaling_lock); + ufshcd_put_read_lock(hba); return err; } @@ -2990,7 +3057,12 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, struct completion wait; unsigned long flags; - down_read(&hba->clk_scaling_lock); + /* + * May get invoked from shutdown and IOCTL contexts. + * In shutdown context, it comes in with lock acquired. + */ + if (!ufshcd_is_shutdown_ongoing(hba)) + down_read(&hba->lock); /* * Get free slot, sleep if slots are unavailable. @@ -3023,7 +3095,8 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, out_put_tag: ufshcd_put_dev_cmd_tag(hba, tag); wake_up(&hba->dev_cmd.tag_wq); - up_read(&hba->clk_scaling_lock); + if (!ufshcd_is_shutdown_ongoing(hba)) + up_read(&hba->lock); return err; } @@ -8654,11 +8727,37 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba) */ int ufshcd_shutdown(struct ufs_hba *hba) { - /* - * TODO: This function should send the power down notification to - * UFS device and then power off the UFS link. But we need to be sure - * that there will not be any new UFS requests issued after this. + int ret = 0; + + if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba)) + goto out; + + pm_runtime_get_sync(hba->dev); + ufshcd_hold_all(hba); + /** + * (1) Acquire the lock to stop any more requests + * (2) Set state to shutting down + * (3) Suspend clock scaling + * (4) Wait for all issued requests to complete */ + ufshcd_get_write_lock(hba); + ufshcd_mark_shutdown_ongoing(hba); + ufshcd_scsi_block_requests(hba); + ufshcd_suspend_clkscaling(hba); + ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX); + if (ret) + dev_err(hba->dev, "%s: waiting for DB clear: failed: %d\n", + __func__, ret); + /* Requests may have errored out above, let it be handled */ + flush_work(&hba->eh_work); + /* reqs issued from contexts other than shutdown will fail from now */ + ufshcd_scsi_unblock_requests(hba); + ufshcd_release_all(hba); + ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM); +out: + if (ret) + dev_err(hba->dev, "%s failed, err %d\n", __func__, ret); + /* allow force shutdown even in case of errors */ return 0; } EXPORT_SYMBOL(ufshcd_shutdown); @@ -8843,10 +8942,10 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba) * clock scaling is in progress */ ufshcd_scsi_block_requests(hba); - down_write(&hba->clk_scaling_lock); + down_write(&hba->lock); if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) { ret = -EBUSY; - up_write(&hba->clk_scaling_lock); + up_write(&hba->lock); ufshcd_scsi_unblock_requests(hba); } @@ -8855,7 +8954,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba) static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba) { - up_write(&hba->clk_scaling_lock); + up_write(&hba->lock); ufshcd_scsi_unblock_requests(hba); } @@ -9038,6 +9137,10 @@ static void ufshcd_clk_scaling_resume_work(struct work_struct *work) clk_scaling.resume_work); unsigned long irq_flags; + /* Let's not resume scaling if shutdown is ongoing */ + if (ufshcd_is_shutdown_ongoing(hba)) + return; + spin_lock_irqsave(hba->host->host_lock, irq_flags); if (!hba->clk_scaling.is_suspended) { spin_unlock_irqrestore(hba->host->host_lock, irq_flags); @@ -9250,7 +9353,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Initialize mutex for device management commands */ mutex_init(&hba->dev_cmd.lock); - init_rwsem(&hba->clk_scaling_lock); + init_rwsem(&hba->lock); /* Initialize device management tag acquire wait queue */ init_waitqueue_head(&hba->dev_cmd.tag_wq); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index c0714b7bea72..74fe46cf34fe 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -895,7 +895,10 @@ struct ufs_hba { enum bkops_status urgent_bkops_lvl; bool is_urgent_bkops_lvl_checked; - struct rw_semaphore clk_scaling_lock; + /* sync b/w diff contexts */ + struct rw_semaphore lock; + struct task_struct *issuing_task; + unsigned long shutdown_in_prog; struct reset_control *core_reset; /* If set, don't gate device ref_clk during clock gating */ @@ -904,6 +907,16 @@ struct ufs_hba { int scsi_block_reqs_cnt; }; +static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba) +{ + set_bit(0, &hba->shutdown_in_prog); +} + +static inline bool ufshcd_is_shutdown_ongoing(struct ufs_hba *hba) +{ + return !!(test_bit(0, &hba->shutdown_in_prog)); +} + /* Returns true if clocks can be gated. Otherwise false */ static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) { diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 9cfca014c8ad..382245eb90b6 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -3948,7 +3948,6 @@ int glink_core_register_transport(struct glink_transport_if *if_ptr, xprt_ptr->edge, xprt_ptr->name); if (IS_ERR_OR_NULL(xprt_ptr->tx_task)) { GLINK_ERR("%s: unable to run thread\n", __func__); - glink_core_deinit_xprt_qos_cfg(xprt_ptr); kfree(xprt_ptr); return -ENOMEM; } diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index feeed645fc47..6215636b0f46 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -45,6 +45,7 @@ #include <soc/qcom/service-locator.h> #include <soc/qcom/service-notifier.h> #include <soc/qcom/socinfo.h> +#include <soc/qcom/ramdump.h> #include "wlan_firmware_service_v01.h" @@ -439,6 +440,7 @@ static struct icnss_priv { struct wlfw_rf_board_info_s_v01 board_info; struct wlfw_soc_info_s_v01 soc_info; struct wlfw_fw_version_info_s_v01 fw_version_info; + char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; u32 pwr_pin_result; u32 phy_io_pin_result; u32 rf_pin_result; @@ -463,6 +465,7 @@ static struct icnss_priv { struct qpnp_vadc_chip *vadc_dev; uint64_t vph_pwr; atomic_t pm_count; + struct ramdump_device *msa0_dump_dev; } *penv; static void icnss_hw_write_reg(void *base, u32 offset, u32 val) @@ -1971,12 +1974,16 @@ static int wlfw_cap_send_sync_msg(void) penv->soc_info = resp.soc_info; if (resp.fw_version_info_valid) penv->fw_version_info = resp.fw_version_info; + if (resp.fw_build_id_valid) + strlcpy(penv->fw_build_id, resp.fw_build_id, + QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1); - icnss_pr_dbg("Capability, chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s", + icnss_pr_dbg("Capability, chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s, fw_build_id: %s", penv->chip_info.chip_id, penv->chip_info.chip_family, penv->board_info.board_id, penv->soc_info.soc_id, penv->fw_version_info.fw_version, - penv->fw_version_info.fw_build_timestamp); + penv->fw_version_info.fw_build_timestamp, + penv->fw_build_id); return 0; @@ -2657,8 +2664,6 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, out: ret = icnss_hw_power_off(priv); - icnss_remove_msa_permissions(priv); - kfree(data); return ret; @@ -2763,6 +2768,16 @@ static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this, return ret; } +static int icnss_msa0_ramdump(struct icnss_priv *priv) +{ + struct ramdump_segment segment; + + memset(&segment, 0, sizeof(segment)); + segment.v_address = priv->msa_va; + segment.size = priv->msa_mem_size; + return do_ramdump(priv->msa0_dump_dev, &segment, 1); +} + static struct notifier_block wlfw_clnt_nb = { .notifier_call = icnss_qmi_wlfw_clnt_svc_event_notify, }; @@ -2778,9 +2793,19 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, icnss_pr_dbg("Modem-Notify: event %lu\n", code); + if (code == SUBSYS_AFTER_SHUTDOWN) { + icnss_remove_msa_permissions(priv); + icnss_pr_info("Collecting msa0 segment dump\n"); + icnss_msa0_ramdump(priv); + return NOTIFY_OK; + } + if (code != SUBSYS_BEFORE_SHUTDOWN) return NOTIFY_OK; + if (test_bit(ICNSS_PDR_ENABLED, &priv->state)) + return NOTIFY_OK; + icnss_pr_info("Modem went down, state: %lx\n", priv->state); event_data = kzalloc(sizeof(*data), GFP_KERNEL); @@ -2936,8 +2961,6 @@ static int icnss_get_service_location_notify(struct notifier_block *nb, set_bit(ICNSS_PDR_ENABLED, &priv->state); - icnss_modem_ssr_unregister_notifier(priv); - icnss_pr_dbg("PD restart enabled, state: 0x%lx\n", priv->state); return NOTIFY_OK; @@ -3000,6 +3023,11 @@ static int icnss_enable_recovery(struct icnss_priv *priv) goto enable_pdr; } + priv->msa0_dump_dev = create_ramdump_device("wcss_msa0", + &priv->pdev->dev); + if (!priv->msa0_dump_dev) + return -ENOMEM; + icnss_modem_ssr_register_notifier(priv); if (test_bit(SSR_ONLY, &quirks)) { icnss_pr_dbg("PDR disabled through module parameter\n"); @@ -3929,6 +3957,8 @@ static int icnss_stats_show_capability(struct seq_file *s, priv->fw_version_info.fw_version); seq_printf(s, "Firmware Build Timestamp: %s\n", priv->fw_version_info.fw_build_timestamp); + seq_printf(s, "Firmware Build ID: %s\n", + priv->fw_build_id); } return 0; @@ -4511,6 +4541,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_modem_ssr_unregister_notifier(penv); + destroy_ramdump_device(penv->msa0_dump_dev); + icnss_pdr_unregister_notifier(penv); qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01, @@ -4522,6 +4554,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_hw_power_off(penv); + icnss_remove_msa_permissions(penv); + dev_set_drvdata(&pdev->dev, NULL); return 0; diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index afe6b2309e27..95d50fe01ee1 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -260,7 +260,7 @@ int hyp_assign_table(struct sg_table *table, int *dest_vmids, int *dest_perms, int dest_nelems) { - int ret; + int ret = 0; struct scm_desc desc = {0}; u32 *source_vm_copy; size_t source_vm_copy_size; diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.c b/drivers/soc/qcom/wlan_firmware_service_v01.c index f5f7ae8c9901..3e00d6c9d153 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.c +++ b/drivers/soc/qcom/wlan_firmware_service_v01.c @@ -766,6 +766,24 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = { .ei_array = wlfw_fw_version_info_s_v01_ei, }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id_valid), + }, + { + .data_type = QMI_STRING, + .elem_len = QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1, + .elem_size = sizeof(char), + .is_array = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + fw_build_id), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, .is_array = QMI_COMMON_TLV_TYPE, @@ -1588,3 +1606,47 @@ struct elem_info wlfw_vbatt_resp_msg_v01_ei[] = { .is_array = QMI_COMMON_TLV_TYPE, }, }; + +struct elem_info wlfw_mac_addr_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(uint8_t), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = QMI_WLFW_MAC_ADDR_SIZE_V01, + .elem_size = sizeof(uint8_t), + .is_array = STATIC_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_mac_addr_req_msg_v01, + mac_addr), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .is_array = QMI_COMMON_TLV_TYPE, + }, +}; + +struct elem_info wlfw_mac_addr_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, + .elem_size = sizeof(struct qmi_response_type_v01), + .is_array = NO_ARRAY, + .tlv_type = 0x02, + .offset = offsetof(struct wlfw_mac_addr_resp_msg_v01, + resp), + .ei_array = get_qmi_response_type_v01_ei(), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .is_array = QMI_COMMON_TLV_TYPE, + }, +}; diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.h b/drivers/soc/qcom/wlan_firmware_service_v01.h index 29bdfb23480a..47b315fce94c 100644 --- a/drivers/soc/qcom/wlan_firmware_service_v01.h +++ b/drivers/soc/qcom/wlan_firmware_service_v01.h @@ -24,6 +24,7 @@ #define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 #define QMI_WLFW_INI_RESP_V01 0x002F #define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 +#define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 #define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028 #define QMI_WLFW_MSA_READY_IND_V01 0x002B #define QMI_WLFW_ATHDIAG_WRITE_RESP_V01 0x0031 @@ -43,6 +44,7 @@ #define QMI_WLFW_CAP_RESP_V01 0x0024 #define QMI_WLFW_ATHDIAG_READ_RESP_V01 0x0030 #define QMI_WLFW_VBATT_REQ_V01 0x0032 +#define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033 #define QMI_WLFW_VBATT_RESP_V01 0x0032 #define QMI_WLFW_MSA_INFO_REQ_V01 0x002D #define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027 @@ -57,6 +59,8 @@ #define QMI_WLFW_MAX_TIMESTAMP_LEN_V01 32 #define QMI_WLFW_MAX_STR_LEN_V01 16 #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 +#define QMI_WLFW_MAC_ADDR_SIZE_V01 6 +#define QMI_WLFW_MAX_BUILD_ID_LEN_V01 128 #define QMI_WLFW_MAX_NUM_SVC_V01 24 enum wlfw_driver_mode_enum_v01 { @@ -99,6 +103,7 @@ enum wlfw_pipedir_enum_v01 { #define QMI_WLFW_ALREADY_REGISTERED_V01 ((uint64_t)0x01ULL) #define QMI_WLFW_FW_READY_V01 ((uint64_t)0x02ULL) +#define QMI_WLFW_MSA_READY_V01 ((uint64_t)0x04ULL) struct wlfw_ce_tgt_pipe_cfg_s_v01 { uint32_t pipe_num; @@ -243,8 +248,10 @@ struct wlfw_cap_resp_msg_v01 { struct wlfw_soc_info_s_v01 soc_info; uint8_t fw_version_info_valid; struct wlfw_fw_version_info_s_v01 fw_version_info; + uint8_t fw_build_id_valid; + char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1]; }; -#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 72 +#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 203 extern struct elem_info wlfw_cap_resp_msg_v01_ei[]; struct wlfw_bdf_download_req_msg_v01 { @@ -428,4 +435,17 @@ struct wlfw_vbatt_resp_msg_v01 { #define WLFW_VBATT_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct elem_info wlfw_vbatt_resp_msg_v01_ei[]; +struct wlfw_mac_addr_req_msg_v01 { + uint8_t mac_addr_valid; + uint8_t mac_addr[QMI_WLFW_MAC_ADDR_SIZE_V01]; +}; +#define WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN 9 +extern struct elem_info wlfw_mac_addr_req_msg_v01_ei[]; + +struct wlfw_mac_addr_resp_msg_v01 { + struct qmi_response_type_v01 resp; +}; +#define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7 +extern struct elem_info wlfw_mac_addr_resp_msg_v01_ei[]; + #endif diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index ea0f433f989c..33f7304eac84 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -43,6 +43,7 @@ #include "configfs.h" #define MTP_RX_BUFFER_INIT_SIZE 1048576 +#define MTP_TX_BUFFER_INIT_SIZE 1048576 #define MTP_BULK_BUFFER_SIZE 16384 #define INTR_BUFFER_SIZE 28 #define MAX_INST_NAME_LEN 40 @@ -81,7 +82,7 @@ unsigned int mtp_rx_req_len = MTP_RX_BUFFER_INIT_SIZE; module_param(mtp_rx_req_len, uint, S_IRUGO | S_IWUSR); -unsigned int mtp_tx_req_len = MTP_BULK_BUFFER_SIZE; +unsigned int mtp_tx_req_len = MTP_TX_BUFFER_INIT_SIZE; module_param(mtp_tx_req_len, uint, S_IRUGO | S_IWUSR); unsigned int mtp_tx_reqs = MTP_TX_REQ_MAX; @@ -551,9 +552,6 @@ static int mtp_create_bulk_endpoints(struct mtp_dev *dev, dev->ep_intr = ep; retry_tx_alloc: - if (mtp_tx_req_len > MTP_BULK_BUFFER_SIZE) - mtp_tx_reqs = 4; - /* now allocate requests for our endpoints */ for (i = 0; i < mtp_tx_reqs; i++) { req = mtp_request_new(dev->ep_in, mtp_tx_req_len); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 084dbbc81a6d..c025dccdd8f1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -332,7 +332,7 @@ static int xhci_plat_runtime_suspend(struct device *dev) dev_dbg(dev, "xhci-plat runtime suspend\n"); - return xhci_suspend(xhci, true); + return 0; } static int xhci_plat_runtime_resume(struct device *dev) @@ -346,7 +346,7 @@ static int xhci_plat_runtime_resume(struct device *dev) dev_dbg(dev, "xhci-plat runtime resume\n"); - ret = xhci_resume(xhci, false); + ret = 0; pm_runtime_mark_last_busy(dev); return ret; diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c index e396dfff60ef..b64518194926 100644 --- a/drivers/video/fbdev/msm/mdss_dp_aux.c +++ b/drivers/video/fbdev/msm/mdss_dp_aux.c @@ -514,7 +514,7 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt) { const u32 encoding_factx10 = 8; const u32 ln_to_link_ratio = 10; - u32 min_link_rate; + u32 min_link_rate, reminder = 0; char calc_link_rate = 0; pr_debug("clk_rate=%llu, bpp= %d, lane_cnt=%d\n", @@ -531,9 +531,15 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt) (lane_cnt * encoding_factx10)); min_link_rate /= ln_to_link_ratio; min_link_rate = (min_link_rate * pinfo->bpp); - min_link_rate = (u32)div_u64(min_link_rate * 10, - DP_LINK_RATE_MULTIPLIER); + min_link_rate = (u32)div_u64_rem(min_link_rate * 10, + DP_LINK_RATE_MULTIPLIER, &reminder); + /* + * To avoid any fractional values, + * increment the min_link_rate + */ + if (reminder) + min_link_rate += 1; pr_debug("min_link_rate = %d\n", min_link_rate); if (min_link_rate <= DP_LINK_RATE_162) diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index 20fcc26bb4bf..036e4e39efda 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -2470,16 +2470,20 @@ validate_exit: mutex_lock(&mdp5_data->list_lock); list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) { if (IS_ERR_VALUE(ret)) { - if ((pipe->ndx & rec_release_ndx[0]) || - (pipe->ndx & rec_release_ndx[1])) { + if (((pipe->ndx & rec_release_ndx[0]) && + (pipe->multirect.num == 0)) || + ((pipe->ndx & rec_release_ndx[1]) && + (pipe->multirect.num == 1))) { mdss_mdp_smp_unreserve(pipe); pipe->params_changed = 0; pipe->dirty = true; if (!list_empty(&pipe->list)) list_del_init(&pipe->list); mdss_mdp_pipe_destroy(pipe); - } else if ((pipe->ndx & rec_destroy_ndx[0]) || - (pipe->ndx & rec_destroy_ndx[1])) { + } else if (((pipe->ndx & rec_destroy_ndx[0]) && + (pipe->multirect.num == 0)) || + ((pipe->ndx & rec_destroy_ndx[1]) && + (pipe->multirect.num == 1))) { /* * cleanup/destroy list pipes should move back * to destroy list. Next/current kickoff cycle diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 664850a1a617..946e33033ab7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -2120,8 +2120,10 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) int ret = 0; int sd_in_pipe = 0; int sc_in_pipe = 0; + u64 pipes_flags = 0; list_for_each_entry(pipe, &mdp5_data->pipes_used, list) { + pipes_flags |= pipe->flags; if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) { sd_in_pipe = 1; pr_debug("Secure pipe: %u : %16llx\n", @@ -2133,34 +2135,54 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) } } - if ((!sd_in_pipe && !mdp5_data->sd_enabled) || - (sd_in_pipe && mdp5_data->sd_enabled) || - (!sc_in_pipe && !mdp5_data->sc_enabled) || + MDSS_XLOG(sd_in_pipe, sc_in_pipe, pipes_flags, + mdp5_data->sc_enabled, mdp5_data->sd_enabled); + pr_debug("sd:%d sd_in_pipe:%d sc:%d sc_in_pipe:%d flags:0x%llx\n", + mdp5_data->sd_enabled, sd_in_pipe, + mdp5_data->sc_enabled, sc_in_pipe, pipes_flags); + + /* + * Return early in only two conditions: + * 1. All the features are already disabled and state remains + * disabled for the pipes. + * 2. One of the features is already enabled and state remains + * enabled for the pipes. + */ + if (!sd_in_pipe && !mdp5_data->sd_enabled && + !sc_in_pipe && !mdp5_data->sc_enabled) + return ret; + else if ((sd_in_pipe && mdp5_data->sd_enabled) || (sc_in_pipe && mdp5_data->sc_enabled)) return ret; /* Secure Display */ if (!mdp5_data->sd_enabled && sd_in_pipe) { if (!mdss_get_sd_client_cnt()) { + MDSS_XLOG(0x11); /*wait for ping pong done */ if (ctl->ops.wait_pingpong) mdss_mdp_display_wait4pingpong(ctl, true); ret = mdss_mdp_secure_session_ctrl(1, MDP_SECURE_DISPLAY_OVERLAY_SESSION); - if (ret) + if (ret) { + pr_err("secure display enable fail:%d", ret); return ret; + } } mdp5_data->sd_enabled = 1; mdss_update_sd_client(mdp5_data->mdata, true); } else if (mdp5_data->sd_enabled && !sd_in_pipe) { /* disable the secure display on last client */ if (mdss_get_sd_client_cnt() == 1) { + MDSS_XLOG(0x22); if (ctl->ops.wait_pingpong) mdss_mdp_display_wait4pingpong(ctl, true); ret = mdss_mdp_secure_session_ctrl(0, MDP_SECURE_DISPLAY_OVERLAY_SESSION); - if (ret) + if (ret) { + pr_err("secure display disable fail:%d\n", ret); return ret; + } } mdss_update_sd_client(mdp5_data->mdata, false); mdp5_data->sd_enabled = 0; @@ -2169,29 +2191,36 @@ static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd) /* Secure Camera */ if (!mdp5_data->sc_enabled && sc_in_pipe) { if (!mdss_get_sc_client_cnt()) { + MDSS_XLOG(0x33); if (ctl->ops.wait_pingpong) mdss_mdp_display_wait4pingpong(ctl, true); ret = mdss_mdp_secure_session_ctrl(1, MDP_SECURE_CAMERA_OVERLAY_SESSION); - if (ret) + if (ret) { + pr_err("secure camera enable fail:%d\n", ret); return ret; + } } mdp5_data->sc_enabled = 1; mdss_update_sc_client(mdp5_data->mdata, true); } else if (mdp5_data->sc_enabled && !sc_in_pipe) { /* disable the secure camera on last client */ if (mdss_get_sc_client_cnt() == 1) { + MDSS_XLOG(0x44); if (ctl->ops.wait_pingpong) mdss_mdp_display_wait4pingpong(ctl, true); ret = mdss_mdp_secure_session_ctrl(0, MDP_SECURE_CAMERA_OVERLAY_SESSION); - if (ret) + if (ret) { + pr_err("secure camera disable fail:%d\n", ret); return ret; + } } mdss_update_sc_client(mdp5_data->mdata, false); mdp5_data->sc_enabled = 0; } + MDSS_XLOG(ret); return ret; } @@ -5430,6 +5459,7 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) mdss_mdp_overlay_kickoff(mfd, NULL); } +ctl_stop: /* * If retire fences are still active wait for a vsync time * for retire fence to be updated. @@ -5460,7 +5490,6 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd) flush_work(&mdp5_data->retire_work); } -ctl_stop: mutex_lock(&mdp5_data->ov_lock); /* set the correct pipe_mapped before ctl_stop */ mdss_mdp_mixer_update_pipe_map(mdp5_data->ctl, diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index e370a80ad998..bcf5309993b9 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1340,10 +1340,11 @@ static struct mdss_mdp_pipe *__pipe_lookup(struct mdss_mdp_pipe *pipe_list, bool (*cmp)(struct mdss_mdp_pipe *, void *), void *data) { struct mdss_mdp_pipe *pipe; - int i, j; + int i, j, max_rects; for (i = 0, pipe = pipe_list; i < count; i++) { - for (j = 0; j < pipe->multirect.max_rects; j++, pipe++) + max_rects = pipe->multirect.max_rects; + for (j = 0; j < max_rects; j++, pipe++) if ((rect_num == pipe->multirect.num) && cmp(pipe, data)) return pipe; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index c34a68ce901a..d33e10784b23 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -133,6 +133,7 @@ enum iommu_attr { DOMAIN_ATTR_S1_BYPASS, DOMAIN_ATTR_FAST, DOMAIN_ATTR_PGTBL_INFO, + DOMAIN_ATTR_EARLY_MAP, DOMAIN_ATTR_MAX, }; diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index ee8b2f5a8b5b..c2c49dd748de 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -32,7 +32,7 @@ #if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \ defined(CONFIG_MSM_QDSP6_APRV3_GLINK) #define APR_MAX_BUF 512 -#define APR_NUM_OF_TX_BUF 20 +#define APR_NUM_OF_TX_BUF 30 #else #define APR_MAX_BUF 8092 #endif diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 643c68f4c449..8fdf57504ab6 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1199,6 +1199,15 @@ enum v4l2_cid_mpeg_vidc_video_full_range { #define V4L2_CID_MPEG_VIDC_VIDEO_MATRIX_COEFFS \ (V4L2_CID_MPEG_MSM_VIDC_BASE + 97) +#define V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_TYPE \ + (V4L2_CID_MPEG_MSM_VIDC_BASE + 98) +enum v4l2_mpeg_vidc_video_venc_iframesize_type { + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_DEFAULT, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_MEDIUM, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_HUGE, + V4L2_CID_MPEG_VIDC_VIDEO_IFRAME_SIZE_UNLIMITED, +}; + /* Camera class control IDs */ #define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 862eb8fd3860..84563da000cf 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5537,8 +5537,8 @@ static void migrate_tasks(struct rq *dead_rq, bool migrate_pinned_tasks) * interferred since we don't stop all CPUs. Ignore warning for * this case. */ - if (WARN_ON((task_rq(next) != rq || !task_on_rq_queued(next)) && - migrate_pinned_tasks)) { + if (task_rq(next) != rq || !task_on_rq_queued(next)) { + WARN_ON(migrate_pinned_tasks); raw_spin_unlock(&next->pi_lock); continue; } diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c index ecf6c568f0b5..9b21a09ec4ba 100644 --- a/kernel/sched/core_ctl.c +++ b/kernel/sched/core_ctl.c @@ -687,6 +687,7 @@ int core_ctl_set_boost(bool boost) return ret; } +EXPORT_SYMBOL(core_ctl_set_boost); void core_ctl_check(u64 wallclock) { diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index dda332d821e4..456a1dff692d 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -460,9 +460,9 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) list_del(&info->timer->entry); del_timer_sync(&info->timer->timer); - cancel_work_sync(&info->timer->work); sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); unregister_pm_notifier(&info->timer->pm_nb); + cancel_work_sync(&info->timer->work); kfree(info->timer->attr.attr.name); kfree(info->timer); } else { diff --git a/net/rmnet_data/rmnet_data_vnd.c b/net/rmnet_data/rmnet_data_vnd.c index 4e3a205551e0..2999e2c15fdb 100644 --- a/net/rmnet_data/rmnet_data_vnd.c +++ b/net/rmnet_data/rmnet_data_vnd.c @@ -180,6 +180,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, rmnet_vnd_add_qos_header(skb, dev, dev_conf->qos_version); + skb_orphan(skb); rmnet_egress_handler(skb, &dev_conf->local_ep); } else { dev->stats.tx_dropped++; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 393b8b4b8084..06e00fdfe6a1 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -11820,7 +11820,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF1 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -11848,7 +11848,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF2 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -11876,7 +11876,7 @@ static struct snd_soc_dai_driver tasha_dai[] = { .capture = { .stream_name = "AIF3 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 48000, .rate_min = 8000, .channels_min = 1, @@ -11977,7 +11977,7 @@ static struct snd_soc_dai_driver tasha_i2s_dai[] = { .capture = { .stream_name = "AIF1 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, @@ -12005,7 +12005,7 @@ static struct snd_soc_dai_driver tasha_i2s_dai[] = { .capture = { .stream_name = "AIF2 Capture", .rates = WCD9335_RATES_MASK, - .formats = TASHA_FORMATS, + .formats = TASHA_FORMATS_S16_S24_LE, .rate_max = 192000, .rate_min = 8000, .channels_min = 1, diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 2874a334dfdd..22e14f431bb3 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -3015,7 +3015,8 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_circ; - int bytes_to_alloc, rc, len; + int bytes_to_alloc, rc; + size_t len; buf_circ = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL); @@ -3034,7 +3035,7 @@ int q6asm_set_shared_circ_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_circ->client, &buf_circ->handle, bytes_to_alloc, (ion_phys_addr_t *)&buf_circ->phys, - (size_t *)&len, &buf_circ->data); + &len, &buf_circ->data); if (rc) { pr_err("%s: Audio ION alloc is failed, rc = %d\n", __func__, @@ -3076,7 +3077,8 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, int dir) { struct audio_buffer *buf_pos = &ac->shared_pos_buf; - int len, rc; + int rc; + size_t len; int bytes_to_alloc = sizeof(struct asm_shared_position_buffer); mutex_lock(&ac->cmd_lock); @@ -3085,7 +3087,7 @@ int q6asm_set_shared_pos_buff(struct audio_client *ac, rc = msm_audio_ion_alloc("audio_client", &buf_pos->client, &buf_pos->handle, bytes_to_alloc, - (ion_phys_addr_t *)&buf_pos->phys, (size_t *)&len, + (ion_phys_addr_t *)&buf_pos->phys, &len, &buf_pos->data); if (rc) { @@ -5848,7 +5850,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, struct asm_buffer_node *buffer_node = NULL; int rc = 0; int i = 0; - int cmd_size = 0; + uint32_t cmd_size = 0; uint32_t bufcnt_t; uint32_t bufsz_t; @@ -5870,10 +5872,25 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir, bufsz_t = PAGE_ALIGN(bufsz_t); } + if (bufcnt_t > (UINT_MAX + - sizeof(struct avs_cmd_shared_mem_map_regions)) + / sizeof(struct avs_shared_map_region_payload)) { + pr_err("%s: Unsigned Integer Overflow. bufcnt_t = %u\n", + __func__, bufcnt_t); + return -EINVAL; + } + cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) + (sizeof(struct avs_shared_map_region_payload) * bufcnt_t); + + if (bufcnt > (UINT_MAX / sizeof(struct asm_buffer_node))) { + pr_err("%s: Unsigned Integer Overflow. bufcnt = %u\n", + __func__, bufcnt); + return -EINVAL; + } + buffer_node = kzalloc(sizeof(struct asm_buffer_node) * bufcnt, GFP_KERNEL); if (!buffer_node) { diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index 3b3e728f88f2..834fe7c05306 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -142,7 +142,7 @@ struct share_mem_buf { struct mem_map_table { dma_addr_t phys; void *data; - uint32_t size; /* size of buffer */ + size_t size; /* size of buffer */ struct ion_handle *handle; struct ion_client *client; }; diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index f4ceb5f5c678..eb894d073c07 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -68,7 +68,8 @@ out: static int soc_compr_open_fe(struct snd_compr_stream *cstream) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_dpcm *dpcm; struct snd_soc_dapm_widget_list *list; @@ -443,7 +444,8 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, struct snd_compr_params *params) { struct snd_soc_pcm_runtime *fe = cstream->private_data; - struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream; + struct snd_pcm_substream *fe_substream = + fe->pcm->streams[cstream->direction].substream; struct snd_soc_platform *platform = fe->platform; struct snd_soc_pcm_runtime *be_list[DPCM_MAX_BE_USERS]; struct snd_soc_dpcm *dpcm; |
