summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-04-05 18:16:21 -0700
committerLinux Build Service Account <lnxbuild@localhost>2016-04-05 18:16:22 -0700
commitd31ca55280c228f9e8833b7ebdfad1247e3ac7de (patch)
treea9320836ea8bde11d162fb660e1da94b2e28b5e4
parent1ee82d8d00dafea331698b8d70722286d45038f6 (diff)
parent41dd57df41626b75145c56f958e93fe2904303a9 (diff)
Promotion of kernel.lnx.4.4-160404.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 991549 I98dbc4cef7c08fa7452a6912e4f98270c72dc6d2 msm: ipa3: Add SSR support for IPA3.1 990963 Iebe8cb4034721e76fa5ea63e33304b9dc0243797 usb: qmp: phy: Make sure QMP PHY reset write is complete 992982 Ie2a78394b388b0357459f1778bb7b2d821abde1c clk: msm: clock-osm: refactor OSM FSM initialization 987787 I82b7f78bac7379e9a647b5c8e68c356cd1d5c863 clk: msm: clock-osm: support trace packet config through 999611 I755eb9d30f50e30e55382c52aa3471f272fdb4e7 ARM: dts: msm: remove phy_clk_scheme usage with QUSB_PHY 981231 I03e6f189ab0ab6af406a338bd667fb40240d89b3 clk: msm: clock-osm: add support for mem-acc level progr 980623 I5d6a8b8b18de44b0ae512a4610d9f55f538d0fdb msm: ipa3: Move IPA Status Packet parsing to IPAHAL 978217 Ie0fa374b720ebbffd1d1fd5b9289b2aa816a822a icnss: Update WLFW QMI messages 994739 I64059e1c440736884c7fea1a0096351b8b49f976 ARM: dts: msm: remove always on for sdhc reg on msmcobal 988270 I7f3527ef45cf68c3f5c41e04bfdd3ede55bbaa4d clk: msm: alpha-pll: Add support for dynamic programming 992982 I69fa6fd84c1e89bb6b698b865dcb9ce1bfc35e98 ARM: dts: msm: Enable all OSM FSMs for msmcobalt 992231 I2a861c6a0d34d75aaad508b182c4007b6b448c2e ARM: dts: msm: Increase USB QMP PHY register address spa 992982 Iadcbba42eeae1f4e8b4a43e0bf833eaa7e96afd5 ARM: dts: msm: disable OSM secure programming for msmcob 999611 If3cc9573debc65018b896f64b1fc85d6a8682168 clk: msm: clock-gcc-cobalt: Keep the hmss clocks enabled 988270 I48a40f879b07469a954065d568c12e4a75925292 clk: msm: clock-mmss-8996: Add dynamic_update support fo 999611 I5bc5976ec2c0bfb33358614f834db8a7dc7b9e55 ARM: dts: msm: Enable u1u2 low power mode functionality 999611 If1f264e155a4411df5e037f9f28bc590e9465ac9 usb: phy: qusb: Use phy_clk_scheme with ref_clk_base_add 999611 I958e8a2e61c5b4f906d6896ac9696cbb88cd5a69 ARM: dts: msm: Remove efuse base address with QUSB PHY o 994012 If787e92dbd59b9147d44a53fa3d35d3b3bcfc3d9 clk: msm: clock-mmss-cobalt: Update clock frequencies 994175 I0193663d72e05d8227f9814268ec293cfb94bbe3 clk: msm: clock-osm: call of_platform_populate() during 992753 I49ac2aefb645a4463cb1873072cd3a1f9a136dad clk: msm: clock-gcc-cobalt: Add cxo as bimc_clk parent 981231 I2f37dc87b3380a1d84b3f2aa1763a47c4ec9b034 ARM: dts: msm: move RUMI clock_cpu overrides to msmcobal 999611 I77d9d2a127a2a763b93b968f1d8ccf68a649493e dwc3: msm: Add sysfs entry to manually set mode 994161 Id18261d76edd859ef078f4510dd82b8a6c1ca4bd usb: gadget: f_fs: Update driver to handle compat id des 999611 I920c73ddd2f30c7ab5dd29d3641888fb0f6be61b defconfig: arm64: msm: Increase the log buf size 992982 I961bde48822adcbfbbb28130f2872104de5c11ce clk: msm: clock-osm: add scm_io_write calls to program s 999611 Id0ac493420a4d076f99b9f0d31b479a50f6eafd2 phy: qcom-ufs: update new phy offsets and calibration da 999611 Ifc23fee9ccecaee738998b957ad5d3fc85094bf6 ARM: dts: msm: Fix USB QMP PHY register offset on msmcob 987747 I749ebd54144e9bd8080d4153da5375f40a9f2209 defconfig: msmcortex: Enable ICNSS platform driver Change-Id: I899b8d9f967e8133232af82ce1e0e8c190bd6473 CRs-Fixed: 992982, 991549, 994175, 978217, 980623, 992231, 994012, 994161, 990963, 999611, 987747, 992753, 988270, 987787, 981231, 994739
-rw-r--r--Documentation/devicetree/bindings/arm/msm/qcom,osm.txt151
-rw-r--r--Documentation/devicetree/bindings/cnss/icnss.txt2
-rw-r--r--Documentation/devicetree/bindings/usb/msm-phy.txt2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-rumi.dts63
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-rumi.dtsi65
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-sim.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi274
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig8
-rw-r--r--arch/arm64/configs/msmcortex_defconfig8
-rw-r--r--drivers/clk/msm/clock-alpha-pll.c77
-rw-r--r--drivers/clk/msm/clock-gcc-cobalt.c4
-rw-r--r--drivers/clk/msm/clock-mmss-8996.c4
-rw-r--r--drivers/clk/msm/clock-mmss-cobalt.c13
-rw-r--r--drivers/clk/msm/clock-osm.c610
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-v3.h11
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa.c172
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c121
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c195
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h80
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h68
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc.c107
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c292
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h208
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h93
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c12
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c87
-rw-r--r--drivers/soc/qcom/icnss.c358
-rw-r--r--drivers/soc/qcom/wlan_firmware_service_v01.c406
-rw-r--r--drivers/soc/qcom/wlan_firmware_service_v01.h142
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c40
-rw-r--r--drivers/usb/gadget/function/f_fs.c10
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c60
-rw-r--r--drivers/usb/phy/phy-msm-ssusb-qmp.c5
-rw-r--r--include/soc/qcom/clock-alpha-pll.h8
-rw-r--r--include/soc/qcom/icnss.h10
37 files changed, 2830 insertions, 946 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
index 01abce9fd859..2c5b03e72598 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
@@ -52,15 +52,15 @@ Properties:
Usage: required
Value type: <prop-encoded-array>
Definition: Array which defines the frequency in Hertz, frequency,
- and PLL override data used by the OSM hardware for
- each supported DCVS setpoint of the Power cluster.
+ PLL override data, and ACC level used by the OSM hardware
+ for each supported DCVS setpoint of the Power cluster.
- qcom,perfcl-speedbinX-v0
Usage: required
Value type: <prop-encoded-array>
Definition: Array which defines the frequency in Hertz, frequency,
- and PLL override data used by the OSM hardware for
- each supported DCVS setpoint of the Performance cluster.
+ PLL override data, and ACC level used by the OSM hardware
+ for each supported DCVS setpoint of the Performance cluster.
- qcom,osm-no-tz
Usage: optional
@@ -195,6 +195,38 @@ Properties:
controller status register for each of the two clusters
managed by the OSM controller.
+- qcom,pwrcl-apcs-mem-acc-cfg
+ Usage: required if qcom,osm-no-tz is specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the addresses of the mem-acc
+ configuration registers for the Power cluster.
+ The array must contain exactly three elements.
+
+- qcom,perfcl-apcs-mem-acc-cfg
+ Usage: required if qcom,osm-no-tz is specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the addresses of the mem-acc
+ configuration registers for the Performance cluster.
+ The array must contain exactly three elements.
+
+- qcom,pwrcl-apcs-mem-acc-val
+ Usage: required if qcom,osm-no-tz is specified
+ Value type: <prop-encoded-array>
+ Definition: List of integer tuples which define the mem-acc values
+ for each performance mode of the Power cluster. Each tuple
+ is of length 3 corresponding to the mem-acc values per
+ performance mode with a total of 4 tuples corresponding
+ to each supported performance mode.
+
+- qcom,perfcl-apcs-mem-acc-val
+ Usage: required if qcom,osm-no-tz is specified
+ Value type: <prop-encoded-array>
+ Definition: List of integer tuples which define the mem-acc values
+ for each performance mode of the Performance cluster.
+ Each tuple is of length 3 corresponding to the mem-acc
+ values per performance mode with a total of 4 tuples
+ corresponding to each supported performance mode.
+
- qcom,red-fsm-en
Usage: optional
Value type: <empty>
@@ -263,57 +295,55 @@ Example:
interrupt-names = "pwrcl-irq", "perfcl-irq";
qcom,pwrcl-speedbin0-v0 =
- < 300000000 0x4000f 0x31e001e >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 499200000 0x504001a 0x5200020 >,
- < 576000000 0x504001e 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 806400000 0x404002a 0x8220022 >,
- < 883200000 0x404002e 0x9250025 >,
- < 960000000 0x4040032 0xa280028 >,
- < 1036800000 0x4040036 0xb2b002b >,
- < 1113600000 0x404003a 0xc2e002e >,
- < 1190400000 0x404003e 0xc320032 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3a003a >,
- < 1478400000 0x404004d 0x103e003e >,
- < 1497600000 0x404004e 0x103e003e >,
- < 1574400000 0x4040052 0x10420042 >,
- < 1651200000 0x4040056 0x11450045 >,
- < 1728000000 0x404005a 0x12480048 >,
- < 1804800000 0x404005e 0x134b004b >,
- < 1881600000 0x4040062 0x144e004e >;
+ < 300000000 0x0004000f 0x031e001e 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 499200000 0x0504001a 0x05200020 0x1>,
+ < 576000000 0x0504001e 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 806400000 0x0404002a 0x08220022 0x2>,
+ < 883200000 0x0404002e 0x09250025 0x2>,
+ < 960000000 0x04040032 0x0a280028 0x2>,
+ < 1036800000 0x04040036 0x0b2b002b 0x3>,
+ < 1113600000 0x0404003a 0x0c2e002e 0x3>,
+ < 1190400000 0x0404003e 0x0c320032 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3a003a 0x3>,
+ < 1478400000 0x0404004d 0x103e003e 0x3>,
+ < 1574400000 0x04040052 0x10420042 0x4>,
+ < 1651200000 0x04040056 0x11450045 0x4>,
+ < 1728000000 0x0404005a 0x12480048 0x4>,
+ < 1804800000 0x0404005e 0x134b004b 0x4>,
+ < 1881600000 0x04040062 0x144e004e 0x4>;
qcom,perfcl-speedbin0-v0 =
- < 300000000 0x4000f 0x3200020 >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 480000000 0x5040019 0x5200020 >,
- < 556800000 0x504001d 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 787200000 0x4040029 0x8210021 >,
- < 844800000 0x404002c 0x9240024 >,
- < 902400000 0x404002f 0x9260026 >,
- < 979200000 0x4040033 0xa290029 >,
- < 1056000000 0x4040037 0xb2c002c >,
- < 1094400000 0x4040039 0xb2e002e >,
- < 1171200000 0x404003d 0xc300030 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3b003b >,
- < 1478400000 0x404004d 0xf3e003e >,
- < 1536000000 0x4040050 0x10400040 >,
- < 1632000000 0x4040055 0x11440044 >,
- < 1708800000 0x4040059 0x12480048 >,
- < 1785600000 0x404005d 0x134a004a >,
- < 1862400000 0x4040061 0x134e004e >,
- < 1939200000 0x4040065 0x14510051 >,
- < 2016000000 0x4040069 0x15540054 >,
- < 2092800000 0x404006d 0x16570057 >;
+ < 300000000 0x0004000f 0x03200020 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 480000000 0x05040019 0x05200020 0x1>,
+ < 556800000 0x0504001d 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 787200000 0x04040029 0x08210021 0x1>,
+ < 844800000 0x0404002c 0x09240024 0x2>,
+ < 902400000 0x0404002f 0x09260026 0x2>,
+ < 979200000 0x04040033 0x0a290029 0x2>,
+ < 1056000000 0x04040037 0x0b2c002c 0x2>,
+ < 1171200000 0x0404003d 0x0c300030 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3b003b 0x3>,
+ < 1478400000 0x0404004d 0x0f3e003e 0x3>,
+ < 1536000000 0x04040050 0x10400040 0x3>,
+ < 1632000000 0x04040055 0x11440044 0x4>,
+ < 1708800000 0x04040059 0x12480048 0x4>,
+ < 1785600000 0x0404005d 0x134a004a 0x4>,
+ < 1862400000 0x04040061 0x134e004e 0x4>,
+ < 1939200000 0x04040065 0x14510051 0x4>,
+ < 2016000000 0x04040069 0x15540054 0x4>,
+ < 2092800000 0x0404006d 0x16570057 0x4>;
qcom,osm-no-tz;
qcom,osm-pll-setup;
@@ -352,6 +382,21 @@ Example:
qcom,apm-ctrl-status =
<0x179d000c 0x179d0018>;
+ qcom,pwrcl-apcs-mem-acc-cfg =
+ <0x179d1360 0x179d1364 0x179d1364>;
+ qcom,perfcl-apcs-mem-acc-cfg =
+ <0x179d1368 0x179d136C 0x179d1370>;
+ qcom,pwrcl-apcs-mem-acc-val =
+ <0x00000000 0x10000000 0x10000000>,
+ <0x00000000 0x10000000 0x10000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000001 0x00000001>;
+ qcom,perfcl-apcs-mem-acc-val =
+ <0x00000000 0x00000000 0x10000000>,
+ <0x00000000 0x00000000 0x10000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000000 0x00000001>;
+
clock-names = "aux_clk";
clocks = <&clock_gcc clk_gpll0_ao>;
#clock-cells = <1>;
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index 252e3075f8e2..f07a2beafbb3 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -11,6 +11,7 @@ Required properties:
- reg: Memory regions defined as starting address and size
- reg-names: Names of the memory regions defined in reg entry
- interrupts: Copy engine interrupt table
+ - qcom,wlan-msa-memory: MSA memory size
Optional properties:
@@ -33,4 +34,5 @@ Example:
<0 139 0 /* CE9 */ >,
<0 140 0 /* CE10 */ >,
<0 141 0 /* CE11 */ >;
+ qcom,wlan-msa-memory = <0x200000>;
};
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index c77f35c448e6..048d00057ea9 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -154,7 +154,6 @@ Required properties:
- clock-names: Names of the clocks in 1-1 correspondence with the "clocks"
property. Required clocks are "cfg_ahb_clk" and "phy_reset".
- phy_type: Should be one of "ulpi" or "utmi". ChipIdea core uses "ulpi" mode.
- - qcom,phy-clk-scheme: Should be one of "cml" or "cmos".
Optional properties:
- reg: Address and length register set to control QUSB2 PHY
@@ -175,6 +174,7 @@ Optional properties:
- qcom,tune2-efuse-num-bits: Number of bits based value to use for TUNE2 high nibble
- qcom,emulation: Indicates that we are running on emulation platform.
- qcom,hold-reset: Indicates that hold QUSB PHY into reset state.
+ - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided.
Example:
qusb_phy: qusb@f9b39000 {
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index d62862ebb96a..3672d6f313cd 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -2133,7 +2133,7 @@
ssphy: ssphy@7410000 {
compatible = "qcom,usb-ssphy-qmp-v2";
- reg = <0x7410000 0x45c>,
+ reg = <0x7410000 0x7a8>,
<0x007ab244 0x4>;
reg-names = "qmp_phy_base",
"vls_clamp_reg";
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-rumi.dts b/arch/arm/boot/dts/qcom/msmcobalt-rumi.dts
index 3500e36ceeeb..30a3700c4e70 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-rumi.dts
+++ b/arch/arm/boot/dts/qcom/msmcobalt-rumi.dts
@@ -34,69 +34,6 @@
status = "disabled";
};
-&clock_cpu {
- qcom,cc-factor = <10>;
- qcom,osm-clk-rate = <2000000>;
- qcom,xo-clk-rate = <333333>;
-
- qcom,pwrcl-speedbin0-v0 =
- < 300000000 0x4000f 0x31e001e >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 499200000 0x504001a 0x5200020 >,
- < 576000000 0x504001e 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 748800000 0x4030027 0x7200020 >,
- < 768000000 0x4020028 0x7200020 >,
- < 787200000 0x4010029 0x7200020 >,
- < 806400000 0x404002a 0x8220022 >,
- < 883200000 0x404002e 0x9250025 >,
- < 960000000 0x4040032 0xa280028 >,
- < 1036800000 0x4040036 0xb2b002b >,
- < 1113600000 0x404003a 0xc2e002e >,
- < 1190400000 0x404003e 0xc320032 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3a003a >,
- < 1478400000 0x404004d 0x103e003e >,
- < 1574400000 0x4040052 0x10420042 >,
- < 1651200000 0x4040056 0x11450045 >,
- < 1728000000 0x404005a 0x12480048 >,
- < 1804800000 0x404005e 0x134b004b >,
- < 1881600000 0x4040062 0x144e004e >;
-
- qcom,perfcl-speedbin0-v0 =
- < 300000000 0x4000f 0x3200020 >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 480000000 0x5040019 0x5200020 >,
- < 556800000 0x504001d 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 652800000 0x4030022 0x7200020 >,
- < 672000000 0x4020023 0x7200020 >,
- < 691200000 0x4010024 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 787200000 0x4040029 0x8210021 >,
- < 844800000 0x404002c 0x9240024 >,
- < 902400000 0x404002f 0x9260026 >,
- < 979200000 0x4040033 0xa290029 >,
- < 1056000000 0x4040037 0xb2c002c >,
- < 1171200000 0x404003d 0xc300030 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3b003b >,
- < 1478400000 0x404004d 0xf3e003e >,
- < 1536000000 0x4040050 0x10400040 >,
- < 1632000000 0x4040055 0x11440044 >,
- < 1708800000 0x4040059 0x12480048 >,
- < 1785600000 0x404005d 0x134a004a >,
- < 1862400000 0x4040061 0x134e004e >,
- < 1939200000 0x4040065 0x14510051 >,
- < 2016000000 0x4040069 0x15540054 >,
- < 2092800000 0x404006d 0x16570057 >;
-};
-
&apc0_cpr {
qcom,cpr-initial-temp-band = <3>;
qcom,cpr-temp-point-map = <0 25 85>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-rumi.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-rumi.dtsi
index 34a6e179d259..26e229ae6a2c 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-rumi.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-rumi.dtsi
@@ -48,7 +48,7 @@
qcom,vdd-current-level = <200 800000>;
vdd-io-supply = <&pmcobalt_l13>;
- qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
qcom,vdd-io-current-level = <200 22000>;
qcom,clk-rates = <400000 20000000 25000000
@@ -58,6 +58,69 @@
status = "ok";
};
+&clock_cpu {
+ qcom,cc-factor = <10>;
+ qcom,osm-clk-rate = <2000000>;
+ qcom,xo-clk-rate = <333333>;
+
+ qcom,pwrcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x031e001e 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 499200000 0x0504001a 0x05200020 0x1>,
+ < 576000000 0x0504001e 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 748800000 0x04030027 0x07200020 0x1>,
+ < 768000000 0x04020028 0x07200020 0x1>,
+ < 787200000 0x04010029 0x07200020 0x1>,
+ < 806400000 0x0404002a 0x08220022 0x2>,
+ < 883200000 0x0404002e 0x09250025 0x2>,
+ < 960000000 0x04040032 0x0a280028 0x2>,
+ < 1036800000 0x04040036 0x0b2b002b 0x3>,
+ < 1113600000 0x0404003a 0x0c2e002e 0x3>,
+ < 1190400000 0x0404003e 0x0c320032 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3a003a 0x3>,
+ < 1478400000 0x0404004d 0x103e003e 0x3>,
+ < 1574400000 0x04040052 0x10420042 0x4>,
+ < 1651200000 0x04040056 0x11450045 0x4>,
+ < 1728000000 0x0404005a 0x12480048 0x4>,
+ < 1804800000 0x0404005e 0x134b004b 0x4>,
+ < 1881600000 0x04040062 0x144e004e 0x4>;
+
+ qcom,perfcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x03200020 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 480000000 0x05040019 0x05200020 0x1>,
+ < 556800000 0x0504001d 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 652800000 0x04030022 0x07200020 0x1>,
+ < 672000000 0x04020023 0x07200020 0x1>,
+ < 691200000 0x04010024 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 787200000 0x04040029 0x08210021 0x1>,
+ < 844800000 0x0404002c 0x09240024 0x2>,
+ < 902400000 0x0404002f 0x09260026 0x2>,
+ < 979200000 0x04040033 0x0a290029 0x2>,
+ < 1056000000 0x04040037 0x0b2c002c 0x2>,
+ < 1171200000 0x0404003d 0x0c300030 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3b003b 0x3>,
+ < 1478400000 0x0404004d 0x0f3e003e 0x3>,
+ < 1536000000 0x04040050 0x10400040 0x3>,
+ < 1632000000 0x04040055 0x11440044 0x4>,
+ < 1708800000 0x04040059 0x12480048 0x4>,
+ < 1785600000 0x0404005d 0x134a004a 0x4>,
+ < 1862400000 0x04040061 0x134e004e 0x4>,
+ < 1939200000 0x04040065 0x14510051 0x4>,
+ < 2016000000 0x04040069 0x15540054 0x4>,
+ < 2092800000 0x0404006d 0x16570057 0x4>;
+};
+
&soc {
qcom,icnss@18800000 {
compatible = "qcom,icnss";
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-sim.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-sim.dtsi
index 938d5d8c40d1..64291b3b2abc 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-sim.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-sim.dtsi
@@ -20,13 +20,11 @@
&sdhc_2 {
vdd-supply = <&pmcobalt_l21>;
- qcom,vdd-always-on;
qcom,vdd-voltage-level = <2950000 2960000>;
qcom,vdd-current-level = <200 800000>;
vdd-io-supply = <&pmcobalt_l13>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-voltage-level = <1808000 2950000>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
qcom,vdd-io-current-level = <200 22000>;
qcom,clk-rates = <400000 20000000 25000000
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 3b7a362a786a..c157f544e5ba 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -653,57 +653,56 @@
interrupt-names = "pwrcl-irq", "perfcl-irq";
qcom,pwrcl-speedbin0-v0 =
- < 300000000 0x4000f 0x31e001e >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 499200000 0x504001a 0x5200020 >,
- < 576000000 0x504001e 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 806400000 0x404002a 0x8220022 >,
- < 883200000 0x404002e 0x9250025 >,
- < 960000000 0x4040032 0xa280028 >,
- < 1036800000 0x4040036 0xb2b002b >,
- < 1113600000 0x404003a 0xc2e002e >,
- < 1190400000 0x404003e 0xc320032 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3a003a >,
- < 1478400000 0x404004d 0x103e003e >,
- < 1574400000 0x4040052 0x10420042 >,
- < 1651200000 0x4040056 0x11450045 >,
- < 1728000000 0x404005a 0x12480048 >,
- < 1804800000 0x404005e 0x134b004b >,
- < 1881600000 0x4040062 0x144e004e >;
+ < 300000000 0x0004000f 0x031e001e 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 499200000 0x0504001a 0x05200020 0x1>,
+ < 576000000 0x0504001e 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 806400000 0x0404002a 0x08220022 0x2>,
+ < 883200000 0x0404002e 0x09250025 0x2>,
+ < 960000000 0x04040032 0x0a280028 0x2>,
+ < 1036800000 0x04040036 0x0b2b002b 0x3>,
+ < 1113600000 0x0404003a 0x0c2e002e 0x3>,
+ < 1190400000 0x0404003e 0x0c320032 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3a003a 0x3>,
+ < 1478400000 0x0404004d 0x103e003e 0x3>,
+ < 1574400000 0x04040052 0x10420042 0x4>,
+ < 1651200000 0x04040056 0x11450045 0x4>,
+ < 1728000000 0x0404005a 0x12480048 0x4>,
+ < 1804800000 0x0404005e 0x134b004b 0x4>,
+ < 1881600000 0x04040062 0x144e004e 0x4>;
qcom,perfcl-speedbin0-v0 =
- < 300000000 0x4000f 0x3200020 >,
- < 345600000 0x5040012 0x4200020 >,
- < 422400000 0x5040016 0x4200020 >,
- < 480000000 0x5040019 0x5200020 >,
- < 556800000 0x504001d 0x6200020 >,
- < 633600000 0x4040021 0x7200020 >,
- < 710400000 0x4040025 0x7200020 >,
- < 787200000 0x4040029 0x8210021 >,
- < 844800000 0x404002c 0x9240024 >,
- < 902400000 0x404002f 0x9260026 >,
- < 979200000 0x4040033 0xa290029 >,
- < 1056000000 0x4040037 0xb2c002c >,
- < 1171200000 0x404003d 0xc300030 >,
- < 1248000000 0x4040041 0xd340034 >,
- < 1324800000 0x4040045 0xe370037 >,
- < 1401600000 0x4040049 0xf3b003b >,
- < 1478400000 0x404004d 0xf3e003e >,
- < 1536000000 0x4040050 0x10400040 >,
- < 1632000000 0x4040055 0x11440044 >,
- < 1708800000 0x4040059 0x12480048 >,
- < 1785600000 0x404005d 0x134a004a >,
- < 1862400000 0x4040061 0x134e004e >,
- < 1939200000 0x4040065 0x14510051 >,
- < 2016000000 0x4040069 0x15540054 >,
- < 2092800000 0x404006d 0x16570057 >;
-
- qcom,osm-no-tz;
+ < 300000000 0x0004000f 0x03200020 0x1>,
+ < 345600000 0x05040012 0x04200020 0x1>,
+ < 422400000 0x05040016 0x04200020 0x1>,
+ < 480000000 0x05040019 0x05200020 0x1>,
+ < 556800000 0x0504001d 0x06200020 0x1>,
+ < 633600000 0x04040021 0x07200020 0x1>,
+ < 710400000 0x04040025 0x07200020 0x1>,
+ < 787200000 0x04040029 0x08210021 0x1>,
+ < 844800000 0x0404002c 0x09240024 0x2>,
+ < 902400000 0x0404002f 0x09260026 0x2>,
+ < 979200000 0x04040033 0x0a290029 0x2>,
+ < 1056000000 0x04040037 0x0b2c002c 0x2>,
+ < 1171200000 0x0404003d 0x0c300030 0x3>,
+ < 1248000000 0x04040041 0x0d340034 0x3>,
+ < 1324800000 0x04040045 0x0e370037 0x3>,
+ < 1401600000 0x04040049 0x0f3b003b 0x3>,
+ < 1478400000 0x0404004d 0x0f3e003e 0x3>,
+ < 1536000000 0x04040050 0x10400040 0x3>,
+ < 1632000000 0x04040055 0x11440044 0x4>,
+ < 1708800000 0x04040059 0x12480048 0x4>,
+ < 1785600000 0x0404005d 0x134a004a 0x4>,
+ < 1862400000 0x04040061 0x134e004e 0x4>,
+ < 1939200000 0x04040065 0x14510051 0x4>,
+ < 2016000000 0x04040069 0x15540054 0x4>,
+ < 2092800000 0x0404006d 0x16570057 0x4>;
+
qcom,osm-pll-setup;
qcom,up-timer =
@@ -746,6 +745,25 @@
qcom,red-fsm-en;
qcom,boost-fsm-en;
qcom,safe-fsm-en;
+ qcom,ps-fsm-en;
+ qcom,droop-fsm-en;
+ qcom,wfx-fsm-en;
+ qcom,pc-fsm-en;
+
+ qcom,pwrcl-apcs-mem-acc-cfg =
+ <0x179d1360 0x179d1364 0x179d1364>;
+ qcom,perfcl-apcs-mem-acc-cfg =
+ <0x179d1368 0x179d136C 0x179d1370>;
+ qcom,pwrcl-apcs-mem-acc-val =
+ <0x00000000 0x10000000 0x10000000>,
+ <0x00000000 0x10000000 0x10000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000001 0x00000001>;
+ qcom,perfcl-apcs-mem-acc-val =
+ <0x00000000 0x00000000 0x10000000>,
+ <0x00000000 0x00000000 0x10000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000000 0x00000001>;
clock-names = "aux_clk", "xo_ao";
clocks = <&clock_gcc clk_hmss_gpll0_clk_src>,
@@ -1270,7 +1288,6 @@
interrupts = <0 131 0>;
usb-phy = <&qusb_phy0>, <&ssphy>;
tx-fifo-resize;
- snps,usb3-u1u2-disable;
snps,nominal-elastic-buffer;
snps,hird_thresh = <0x10>;
};
@@ -1311,11 +1328,9 @@
qusb_phy0: qusb@c012000 {
compatible = "qcom,qusb2phy";
reg = <0x0c012000 0x2a8>,
- <0x0a8f8800 0x400>,
- <0x0078024c 0x4>;
+ <0x0a8f8800 0x400>;
reg-names = "qusb_phy_base",
- "qscratch_base",
- "tune2_efuse_addr";
+ "qscratch_base";
vdd-supply = <&pmcobalt_l1>;
vdda18-supply = <&pmcobalt_l12>;
vdda33-supply = <&pmcobalt_l24>;
@@ -1328,7 +1343,6 @@
0x0a 0x84
0x00 0x40>;
phy_type= "utmi";
- qcom,phy-clk-scheme = "cml";
clocks = <&clock_gcc clk_ln_bb_clk1>,
<&clock_gcc clk_gcc_rx1_usb2_clkref_clk>,
@@ -1386,81 +1400,81 @@
0x18 0x00 0x00
0x24 0x7e 0x00
0x28 0x15 0x00
- 0x30 0x0b 0x00 /* RX Settings */
- 0xd4 0x0a 0x00
- 0xd8 0x43 0x00
- 0xdc 0x18 0x00
- 0xf8 0x07 0x00
- 0xfc 0x80 0x00
- 0x104 0x03 0x00
- 0x10c 0x16 0x00
- 0x34 0x75 0x00
- 0x3c 0x00 0x00
- 0x40 0x00 0x00
- 0x44 0x80 0x00
- 0x08 0x0a 0x00
- 0x14 0x06 0x00
- 0x100 0x00 0x00
- 0x30 0x0b 0x00
- 0xd4 0x0a 0x00
- 0xd8 0x4e 0x00
- 0xdc 0x18 0x00
- 0xf8 0x07 0x00
- 0xfc 0x80 0x00
- 0x104 0x03 0x00
- 0x10c 0x16 0x00
- 0x34 0x75 0x00
- 0x3c 0x00 0x00
- 0x40 0x00 0x00
- 0x44 0x80 0x00
- 0x08 0x0a 0x00
- 0x14 0x06 0x00
- 0x100 0x00 0x00
- 0x60 0x10 0x00 /* TX Settings */
- 0xa4 0x12 0x00
- 0x8c 0xc6 0x00
- 0x44 0x00 0x00
- 0x60 0x10 0x00
- 0xa4 0x12 0x00
- 0x8c 0xc6 0x00
- 0x44 0x00 0x00
- 0xc8 0x83 0x00 /* FLL Config */
- 0xcc 0x09 0x00
- 0xd0 0xa2 0x00
- 0xd4 0x40 0x01
- 0x80 0xd1 0x00 /* Lock Detect */
- 0x84 0x1f 0x00
- 0x88 0x47 0x00
- 0x64 0x1b 0x00 /* PCS Power State */
- 0x0c 0x9f 0x00 /* PCS Settings */
- 0x10 0x9e 0x00
- 0x14 0xb0 0x00
- 0x18 0x57 0x00
- 0x1c 0x69 0x00
- 0x20 0x69 0x00
- 0x24 0x17 0x00
- 0x28 0x0f 0x00
- 0x2c 0x16 0x00
- 0x30 0x0f 0x00
- 0x34 0x11 0x00
- 0x38 0x0c 0x00
- 0x3c 0x19 0x00
- 0x40 0x11 0x00
- 0x44 0x10 0x00
- 0x48 0x0b 0x00
- 0x4c 0x10 0x00
- 0x50 0x0b 0x00
- 0x5c 0x02 0x00
- 0xa0 0x04 0x00
- 0x8c 0x44 0x00
- 0x70 0xe7 0x00
- 0x74 0x03 0x00
- 0x78 0x40 0x00
- 0x7c 0x00 0x00
- 0x1d7 0x88 0x00
- 0xb8 0x75 0x00 /* USB3 RX EQ */
- 0xb0 0x86 0x00
- 0xbc 0x13 0x00
+ 0x430 0x0b 0x00 /* RX Settings */
+ 0x4d4 0x0a 0x00
+ 0x4d8 0x4e 0x00
+ 0x4dc 0x18 0x00
+ 0x4f8 0x07 0x00
+ 0x4fc 0x80 0x00
+ 0x50c 0x16 0x00
+ 0x434 0x75 0x00
+ 0x43c 0x00 0x00
+ 0x440 0x00 0x00
+ 0x444 0x80 0x00
+ 0x408 0x0a 0x00
+ 0x414 0x06 0x00
+ 0x500 0x00 0x00
+ 0x830 0x0b 0x00
+ 0x8d4 0x0a 0x00
+ 0x8d8 0x4e 0x00
+ 0x8dc 0x18 0x00
+ 0x8f8 0x07 0x00
+ 0x8fc 0x80 0x00
+ 0x904 0x03 0x00
+ 0x90c 0x16 0x00
+ 0x834 0x75 0x00
+ 0x83c 0x00 0x00
+ 0x840 0x00 0x00
+ 0x844 0x80 0x00
+ 0x808 0x0a 0x00
+ 0x814 0x06 0x00
+ 0x900 0x00 0x00
+ 0x260 0x10 0x00 /* TX Settings */
+ 0x2a4 0x12 0x00
+ 0x28c 0xc6 0x00
+ 0x244 0x00 0x00
+ 0x660 0x10 0x00
+ 0x6a4 0x12 0x00
+ 0x68c 0xc6 0x00
+ 0x644 0x00 0x00
+ 0xcc8 0x83 0x00 /* FLL Config */
+ 0xccc 0x09 0x00
+ 0xcd0 0xa2 0x00
+ 0xcd4 0x40 0x00
+ 0xcc4 0x01 0x00
+ 0xc80 0xd1 0x00 /* Lock Detect */
+ 0xc84 0x1f 0x00
+ 0xc88 0x47 0x00
+ 0xc64 0x1b 0x00 /* PCS Power State */
+ 0xc0c 0x9f 0x00 /* PCS Settings */
+ 0xc10 0x9e 0x00
+ 0xc14 0xb0 0x00
+ 0xc18 0x57 0x00
+ 0xc1c 0x69 0x00
+ 0xc20 0x69 0x00
+ 0xc24 0x17 0x00
+ 0xc28 0x0f 0x00
+ 0xc2c 0x16 0x00
+ 0xc30 0x0f 0x00
+ 0xc34 0x11 0x00
+ 0xc38 0x0c 0x00
+ 0xc3c 0x19 0x00
+ 0xc40 0x11 0x00
+ 0xc44 0x10 0x00
+ 0xc48 0x0b 0x00
+ 0xc4c 0x10 0x00
+ 0xc50 0x0b 0x00
+ 0xc5c 0x02 0x00
+ 0xca0 0x04 0x00
+ 0xc8c 0x44 0x00
+ 0xc70 0xe7 0x00
+ 0xc74 0x03 0x00
+ 0xc78 0x40 0x00
+ 0xc7c 0x00 0x00
+ 0xdd8 0x88 0x00
+ 0xcb8 0x75 0x00 /* USB3 RX EQ */
+ 0xcb0 0x86 0x00
+ 0xcbc 0x13 0x00
0xffffffff 0xffffffff 0x00>;
qcom,qmp-phy-reg-offset =
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 5d62b423e2b9..3f44a31d4dc4 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -14,7 +14,7 @@ CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
@@ -211,7 +211,7 @@ CONFIG_BPF_JIT=y
CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
-# CONFIG_WIRELESS is not set
+CONFIG_CFG80211=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
@@ -259,7 +259,8 @@ CONFIG_PPP_MPPE=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_USB_USBNET=y
-# CONFIG_WLAN is not set
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_INPUT_MISC=y
@@ -410,6 +411,7 @@ CONFIG_QCOM_SCM=y
CONFIG_QCOM_SCM_XPU=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_ICNSS=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 2327ccb45221..c358c2a1cc56 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -13,7 +13,7 @@ CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
@@ -210,7 +210,7 @@ CONFIG_BPF_JIT=y
CONFIG_SOCKEV_NLMCAST=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
-# CONFIG_WIRELESS is not set
+CONFIG_CFG80211=y
CONFIG_RFKILL=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
@@ -258,7 +258,8 @@ CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
-# CONFIG_WLAN is not set
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
# CONFIG_INPUT_MOUSE is not set
@@ -435,6 +436,7 @@ CONFIG_QCOM_SCM=y
CONFIG_QCOM_SCM_XPU=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_ICNSS=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_MSM_CORE_HANG_DETECT=y
CONFIG_MSM_BOOT_STATS=y
diff --git a/drivers/clk/msm/clock-alpha-pll.c b/drivers/clk/msm/clock-alpha-pll.c
index 89ec52fa8fbc..a0dc22216364 100644
--- a/drivers/clk/msm/clock-alpha-pll.c
+++ b/drivers/clk/msm/clock-alpha-pll.c
@@ -60,8 +60,8 @@
#define FABIA_PLL_RUN 0x1
#define FABIA_PLL_OUT_MAIN 0x7
#define FABIA_RATE_MARGIN 500
-#define FABIA_PLL_ACK_LATCH BIT(29)
-#define FABIA_PLL_HW_UPDATE_LOGIC_BYPASS BIT(23)
+#define ALPHA_PLL_ACK_LATCH BIT(29)
+#define ALPHA_PLL_HW_UPDATE_LOGIC_BYPASS BIT(23)
/*
* Even though 40 bits are present, use only 32 for ease of calculation.
@@ -562,6 +562,34 @@ static int __calibrate_alpha_pll(struct alpha_pll_clk *pll)
return 0;
}
+static int alpha_pll_dynamic_update(struct alpha_pll_clk *pll)
+{
+ u32 regval;
+
+ /* Latch the input to the PLL */
+ regval = readl_relaxed(MODE_REG(pll));
+ regval |= pll->masks->update_mask;
+ writel_relaxed(regval, MODE_REG(pll));
+
+ /* Wait for 2 reference cycle before checking ACK bit */
+ udelay(1);
+ if (!(readl_relaxed(MODE_REG(pll)) & ALPHA_PLL_ACK_LATCH)) {
+ WARN(1, "%s: PLL latch failed. Output may be unstable!\n",
+ pll->c.dbg_name);
+ return -EINVAL;
+ }
+
+ /* Return latch input to 0 */
+ regval = readl_relaxed(MODE_REG(pll));
+ regval &= ~pll->masks->update_mask;
+ writel_relaxed(regval, MODE_REG(pll));
+
+ /* Wait for PLL output to stabilize */
+ udelay(100);
+
+ return 0;
+}
+
static int alpha_pll_set_rate(struct clk *c, unsigned long rate)
{
struct alpha_pll_clk *pll = to_alpha_pll_clk(c);
@@ -584,12 +612,13 @@ static int alpha_pll_set_rate(struct clk *c, unsigned long rate)
}
/*
- * Ensure PLL is off before changing rate. For optimization reasons,
- * assume no downstream clock is actively using it. No support
- * for dynamic update at the moment.
+ * For PLLs that do not support dynamic programming (dynamic_update
+ * is not set), ensure PLL is off before changing rate. For
+ * optimization reasons, assume no downstream clock is actively
+ * using it.
*/
spin_lock_irqsave(&c->lock, flags);
- if (c->count)
+ if (c->count && !pll->dynamic_update)
c->ops->disable(c);
a_val = a_val << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
@@ -608,7 +637,10 @@ static int alpha_pll_set_rate(struct clk *c, unsigned long rate)
regval |= masks->alpha_en_mask;
writel_relaxed(regval, ALPHA_EN_REG(pll));
- if (c->count)
+ if (c->count && pll->dynamic_update)
+ alpha_pll_dynamic_update(pll);
+
+ if (c->count && !pll->dynamic_update)
c->ops->enable(c);
spin_unlock_irqrestore(&c->lock, flags);
@@ -754,7 +786,14 @@ static enum handoff alpha_pll_handoff(struct clk *c)
struct alpha_pll_clk *pll = to_alpha_pll_clk(c);
struct alpha_pll_masks *masks = pll->masks;
u64 a_val;
- u32 alpha_en, l_val;
+ u32 alpha_en, l_val, regval;
+
+ /* Set the PLL_HW_UPDATE_LOGIC_BYPASS bit before continuing */
+ if (pll->dynamic_update) {
+ regval = readl_relaxed(MODE_REG(pll));
+ regval |= ALPHA_PLL_HW_UPDATE_LOGIC_BYPASS;
+ writel_relaxed(regval, MODE_REG(pll));
+ }
update_vco_tbl(pll);
@@ -911,7 +950,7 @@ static int fabia_alpha_pll_set_rate(struct clk *c, unsigned long rate)
{
struct alpha_pll_clk *pll = to_alpha_pll_clk(c);
unsigned long flags, freq_hz;
- u32 regval, l_val;
+ u32 l_val;
u64 a_val;
freq_hz = round_rate_up(pll, rate, &l_val, &a_val);
@@ -926,24 +965,8 @@ static int fabia_alpha_pll_set_rate(struct clk *c, unsigned long rate)
writel_relaxed(l_val, FABIA_L_REG(pll));
writel_relaxed(a_val, FABIA_FRAC_REG(pll));
- /* Latch the input to the PLL */
- regval = readl_relaxed(MODE_REG(pll));
- regval |= pll->masks->update_mask;
- writel_relaxed(regval, MODE_REG(pll));
-
- /* Wait for 2 reference cycle before checking ACK bit */
- udelay(1);
- if (!(readl_relaxed(MODE_REG(pll)) & FABIA_PLL_ACK_LATCH)) {
- pr_err("%s: PLL latch failed. Leaving PLL disabled\n",
- c->dbg_name);
- goto ret;
- }
+ alpha_pll_dynamic_update(pll);
- /* Return latch input to 0 */
- regval = readl_relaxed(MODE_REG(pll));
- regval &= ~pll->masks->update_mask;
- writel_relaxed(regval, MODE_REG(pll));
-ret:
spin_unlock_irqrestore(&c->lock, flags);
return 0;
}
@@ -1005,7 +1028,7 @@ static enum handoff fabia_alpha_pll_handoff(struct clk *c)
/* Set the PLL_HW_UPDATE_LOGIC_BYPASS bit before continuing */
regval = readl_relaxed(MODE_REG(pll));
- regval |= FABIA_PLL_HW_UPDATE_LOGIC_BYPASS;
+ regval |= ALPHA_PLL_HW_UPDATE_LOGIC_BYPASS;
writel_relaxed(regval, MODE_REG(pll));
if (!is_locked(pll)) {
diff --git a/drivers/clk/msm/clock-gcc-cobalt.c b/drivers/clk/msm/clock-gcc-cobalt.c
index 70198d93787f..0c32332d155f 100644
--- a/drivers/clk/msm/clock-gcc-cobalt.c
+++ b/drivers/clk/msm/clock-gcc-cobalt.c
@@ -1725,6 +1725,7 @@ static struct local_vote_clk gcc_bimc_hmss_axi_clk = {
.base = &virt_base,
.c = {
.dbg_name = "gcc_bimc_hmss_axi_clk",
+ .always_on = true,
.ops = &clk_ops_vote,
CLK_INIT(gcc_bimc_hmss_axi_clk.c),
},
@@ -1737,6 +1738,7 @@ static struct local_vote_clk gcc_hmss_ahb_clk = {
.base = &virt_base,
.c = {
.dbg_name = "gcc_hmss_ahb_clk",
+ .always_on = true,
.parent = &hmss_ahb_clk_src.c,
.ops = &clk_ops_vote,
CLK_INIT(gcc_hmss_ahb_clk.c),
@@ -1749,6 +1751,7 @@ static struct branch_clk gcc_hmss_dvm_bus_clk = {
.base = &virt_base,
.c = {
.dbg_name = "gcc_hmss_dvm_bus_clk",
+ .always_on = true,
.ops = &clk_ops_branch,
CLK_INIT(gcc_hmss_dvm_bus_clk.c),
},
@@ -2695,6 +2698,7 @@ static int msm_gcc_cobalt_probe(struct platform_device *pdev)
return PTR_ERR(vdd_dig.regulator[0]);
}
+ bimc_clk.c.parent = &cxo_clk_src.c;
ret = of_msm_clock_register(pdev->dev.of_node, msm_clocks_rpm_cobalt,
ARRAY_SIZE(msm_clocks_rpm_cobalt));
if (ret)
diff --git a/drivers/clk/msm/clock-mmss-8996.c b/drivers/clk/msm/clock-mmss-8996.c
index c73563d459f4..2b8a2d2edcbc 100644
--- a/drivers/clk/msm/clock-mmss-8996.c
+++ b/drivers/clk/msm/clock-mmss-8996.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -121,6 +121,7 @@ static struct alpha_pll_masks pll_masks_b = {
.alpha_en_mask = BIT(24),
.output_mask = 0xf,
.post_div_mask = BM(11, 8),
+ .update_mask = BIT(22),
};
static struct alpha_pll_vco_tbl mmpll_t_vco[] = {
@@ -315,6 +316,7 @@ static struct alpha_pll_clk mmpll9 = {
.num_vco = ARRAY_SIZE(mmpll_t_vco),
.post_div_config = 0x100,
.enable_config = 0x1,
+ .dynamic_update = true,
.c = {
.parent = &mmsscc_xo.c,
.rate = 960000000,
diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c
index 5a18473023d9..ba9196b7abc9 100644
--- a/drivers/clk/msm/clock-mmss-cobalt.c
+++ b/drivers/clk/msm/clock-mmss-cobalt.c
@@ -226,7 +226,8 @@ static struct rcg_clk ahb_clk_src = {
.c = {
.dbg_name = "ahb_clk_src",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOWER, 40000000, NOMINAL, 80800000),
+ VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 40000000,
+ NOMINAL, 80800000),
CLK_INIT(ahb_clk_src.c),
},
};
@@ -392,13 +393,8 @@ static struct rcg_clk jpeg0_clk_src = {
};
static struct clk_freq_tbl ftbl_rot_clk_src[] = {
- F_MM( 85714286, mmsscc_gpll0, 7, 0, 0),
- F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
F_MM( 171428571, mmsscc_gpll0, 3.5, 0, 0),
- F_MM( 150000000, mmsscc_gpll0, 4, 0, 0),
- F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
F_MM( 275000000, mmpll5_pll_out, 3, 0, 0),
- F_MM( 300000000, mmsscc_gpll0, 2, 0, 0),
F_MM( 330000000, mmpll5_pll_out, 2.5, 0, 0),
F_MM( 412500000, mmpll5_pll_out, 2, 0, 0),
F_END
@@ -885,7 +881,7 @@ static struct rcg_clk dp_gtc_clk_src = {
.c = {
.dbg_name = "dp_gtc_clk_src",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOWER, 40000000, NOMINAL, 300000000),
+ VDD_DIG_FMAX_MAP2(LOWER, 40000000, LOW, 300000000),
CLK_INIT(dp_gtc_clk_src.c),
},
};
@@ -940,7 +936,8 @@ static struct rcg_clk extpclk_clk_src = {
.dbg_name = "extpclk_clk_src",
.parent = &ext_extpclk_clk_src.c,
.ops = &clk_ops_byte,
- VDD_DIG_FMAX_MAP2(LOWER, 150000000, NOMINAL, 600000000),
+ VDD_DIG_FMAX_MAP3(LOWER, 150000000, LOW, 300000000,
+ NOMINAL, 600000000),
CLK_INIT(extpclk_clk_src.c),
},
};
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 875f8ecd3df1..173f9214d7f7 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -32,7 +32,9 @@
#include <linux/pm_qos.h>
#include <linux/interrupt.h>
#include <linux/regulator/driver.h>
+#include <linux/uaccess.h>
+#include <soc/qcom/scm.h>
#include <soc/qcom/clock-pll.h>
#include <soc/qcom/clock-local2.h>
#include <soc/qcom/clock-alpha-pll.h>
@@ -51,10 +53,28 @@ enum clk_osm_lut_data {
FREQ,
FREQ_DATA,
PLL_OVERRIDES,
+ SPARE_DATA,
NUM_FIELDS,
};
-#define SEQ_REG(n) (0x300 + n*4)
+enum clk_osm_trace_method {
+ XOR_PACKET,
+ PERIODIC_PACKET,
+};
+
+enum clk_osm_trace_packet_id {
+ TRACE_PACKET0,
+ TRACE_PACKET1,
+ TRACE_PACKET2,
+ TRACE_PACKET3,
+};
+
+#define SEQ_REG(n) (0x300 + (n) * 4)
+#define MEM_ACC_SEQ_REG_CFG_START(n) (SEQ_REG(12 + (n)))
+#define MEM_ACC_SEQ_CONST(n) (n)
+#define MEM_ACC_INSTR_COMP(n) (0x67 + ((n) * 0x40))
+#define MEM_ACC_SEQ_REG_VAL_START(n) \
+ ((n) < 8 ? SEQ_REG(4 + (n)) : SEQ_REG(60 + (n) - 8))
#define OSM_TABLE_SIZE 40
#define MAX_CLUSTER_CNT 2
@@ -65,6 +85,7 @@ enum clk_osm_lut_data {
#define FREQ_REG 0x1154
#define VOLT_REG 0x1158
#define OVERRIDE_REG 0x115C
+#define SPARE_REG 0x1164
#define OSM_CYCLE_COUNTER_CTRL_REG 0x1F00
#define OSM_CYCLE_COUNTER_STATUS_REG 0x1F04
@@ -153,45 +174,71 @@ enum clk_osm_lut_data {
#define MAX_INSTRUCTIONS 256
#define MAX_BR_INSTRUCTIONS 49
+#define MAX_MEM_ACC_LEVELS 4
+#define MAX_MEM_ACC_VAL_PER_LEVEL 3
+#define MAX_MEM_ACC_VALUES (MAX_MEM_ACC_LEVELS * \
+ MAX_MEM_ACC_VAL_PER_LEVEL)
+#define MEM_ACC_READ_MASK 0x7
+
+#define TRACE_CTRL 0x1F38
+#define TRACE_CTRL_EN_MASK BIT(0)
+#define TRACE_CTRL_ENABLE 1
+#define TRACE_CTRL_DISABLE 0
+#define TRACE_CTRL_PACKET_TYPE_MASK BVAL(2, 1, 3)
+#define TRACE_CTRL_PACKET_TYPE_SHIFT 1
+#define TRACE_CTRL_PERIODIC_TRACE_EN_MASK BIT(3)
+#define TRACE_CTRL_PERIODIC_TRACE_ENABLE BIT(3)
+#define PERIODIC_TRACE_TIMER_CTRL 0x1F3C
+#define PERIODIC_TRACE_MIN_US 1
+#define PERIODIC_TRACE_MAX_US 20000000
+#define PERIODIC_TRACE_DEFAULT_US 1000
+
static u32 seq_instr[] = {
0xc2005000, 0x2c9e3b21, 0xc0ab2cdc, 0xc2882525, 0x359dc491,
0x700a500b, 0x70005001, 0x390938c8, 0xcb44c833, 0xce56cd54,
0x341336e0, 0xadba0000, 0x10004000, 0x70005001, 0x1000500c,
0xc792c5a1, 0x501625e1, 0x3da335a2, 0x50170006, 0x50150006,
- 0x1000c633, 0x1000acb3, 0xc422acb4, 0xaefc1000, 0x700a500b,
- 0x70005001, 0x5010aefd, 0x5012700b, 0xad41700c, 0x0000adb9,
- 0x500c181b, 0x5011500f, 0x181b3413, 0x853984b9, 0x0003bd80,
- 0xa0012ba4, 0x71050006, 0x500e1000, 0x500c1000, 0x38801c0a,
- 0x1c063b18, 0x1c073b43, 0x1c061000, 0x1c073983, 0x3840500c,
- 0x00001c0a, 0x50021000, 0x00007001, 0x81031000, 0x70025003,
- 0x70035004, 0x3b441000, 0x81043985, 0x70025003, 0x50054003,
- 0xa1467009, 0x0003b1c0, 0x4005238b, 0x83081000, 0x850c848b,
- 0x830d1000, 0x850c848e, 0x38811000, 0xa7183842, 0xa79aa759,
- 0x0000a7db, 0x8c101000, 0x8d128c91, 0x00008d93, 0x8c141000,
- 0x8d168c95, 0x00008d97, 0x50061000, 0x39cd3a4c, 0x3ad03a8f,
- 0x10004006, 0x70065007, 0xa00f2c12, 0x00064007, 0x700d7105,
- 0xa9641000, 0x40071c1a, 0x1000700d, 0x70065007, 0x50101c16,
- 0x24115012, 0x700d4007, 0x10004007, 0xa821a00f, 0x71050006,
- 0x700d4007, 0x91ad500c, 0x500f1c15, 0x00005011, 0x2bd41000,
- 0xa00f500c, 0x71050006, 0xa00f1000, 0x0006a821, 0x500c7005,
- 0x1c1591ad, 0x5011500f, 0x2bce1000, 0x50101c16, 0xa0225012,
- 0x0006a82a, 0x91a67105, 0x500f1c15, 0x500c5011, 0xa00f5014,
- 0x71050006, 0x10000000, 0x501391a4, 0xa9632217, 0x10001c1a,
- 0xa9632217, 0x10001c1a, 0x70075008, 0xa9634008, 0x50091c1a,
- 0x40097008, 0x848e1000, 0xb1c0850c, 0x2b990003, 0x1000400d,
- 0x1000500d, 0x84b0abaf, 0xbb808531, 0x10000003, 0x0006a037,
- 0x10007105,
+ 0xafb9c633, 0xacb31000, 0xacb41000, 0x1000c422, 0x500baefc,
+ 0x5001700a, 0xaefd7000, 0x700b5010, 0x700c5012, 0xadb9ad41,
+ 0x181b0000, 0x500f500c, 0x34135011, 0x84b9181b, 0xbd808539,
+ 0x2ba40003, 0x0006a001, 0x10007105, 0x1000500e, 0x1c0a500c,
+ 0x3b181c01, 0x3b431c06, 0x10001c07, 0x39831c06, 0x500c1c07,
+ 0x1c0a1c02, 0x10000000, 0x70015002, 0x10000000, 0x50038103,
+ 0x50047002, 0x10007003, 0x39853b44, 0x50038104, 0x40037002,
+ 0x70095005, 0xb1c0a146, 0x238b0003, 0x10004005, 0x848b8308,
+ 0x1000850c, 0x848e830d, 0x1000850c, 0x3a4c5006, 0x3a8f39cd,
+ 0x40063ad0, 0x50071000, 0x2c127006, 0x4007a00f, 0x71050006,
+ 0x1000700d, 0x1c1aa964, 0x700d4007, 0x50071000, 0x1c167006,
+ 0x50125010, 0x40072411, 0x4007700d, 0xa00f1000, 0x0006a821,
+ 0x40077105, 0x500c700d, 0x1c1591ad, 0x5011500f, 0x10000000,
+ 0x500c2bd4, 0x0006a00f, 0x10007105, 0xa821a00f, 0x70050006,
+ 0x91ad500c, 0x500f1c15, 0x10005011, 0x1c162bce, 0x50125010,
+ 0xa82aa022, 0x71050006, 0x1c1591a6, 0x5011500f, 0x5014500c,
+ 0x0006a00f, 0x00007105, 0x91a41000, 0x22175013, 0x1c1aa963,
+ 0x22171000, 0x1c1aa963, 0x50081000, 0x40087007, 0x1c1aa963,
+ 0x70085009, 0x10004009, 0x850c848e, 0x0003b1c0, 0x400d2b99,
+ 0x500d1000, 0xabaf1000, 0x853184b0, 0x0003bb80, 0xa0371000,
+ 0x71050006, 0x85481000, 0xbf8084c3, 0x2ba80003, 0xbf8084c2,
+ 0x2ba70003, 0xbf8084c1, 0x2ba60003, 0x8ec71000, 0xc6dd8dc3,
+ 0x8c1625ec, 0x8d498c97, 0x8ec61c00, 0xc6dd8dc2, 0x8c1325ec,
+ 0x8d158c94, 0x8ec51c00, 0xc6dd8dc1, 0x8c1025ec, 0x8d128c91,
+ 0x8dc01c00, 0x182cc633, 0x84c08548, 0x0003bf80, 0x84c12ba9,
+ 0x0003bf80, 0x84c22baa, 0x0003bf80, 0x10002bab, 0x8dc08ec4,
+ 0x25ecc6dd, 0x8c948c13, 0x1c008d15, 0x8dc18ec5, 0x25ecc6dd,
+ 0x8c978c16, 0x1c008d49, 0x8dc28ec6, 0x25ecc6dd, 0x8ccb8c4a,
+ 0x1c008d4c, 0xc6338dc3, 0x1000af9b, 0xa759a79a, 0x1000a718,
};
static u32 seq_br_instr[] = {
- 0xfa, 0x10a, 0x116, 0xce, 0xea,
- 0xf2, 0xba, 0xc2, 0x9a, 0xaa,
- 0x122, 0xe0, 0x17a, 0x19a, 0x1a2,
- 0x130, 0x14c, 0x160, 0x142, 0x96,
- 0x186, 0x1cc, 0x1c0, 0x1d4, 0x1e6,
- 0x1f4, 0x1f8, 0x30, 0x5e, 0x84,
- 0x7a, 0x1fe, 0x34, 0x3c, 0x54,
- 0x58, 0x204, 0x2e,
+ 0x28c, 0x1e6, 0x238, 0xd0, 0xec,
+ 0xf4, 0xbc, 0xc4, 0x9c, 0xac,
+ 0xfc, 0xe2, 0x154, 0x174, 0x17c,
+ 0x10a, 0x126, 0x13a, 0x11c, 0x98,
+ 0x160, 0x1a6, 0x19a, 0x1ae, 0x1c0,
+ 0x1ce, 0x1d2, 0x30, 0x60, 0x86,
+ 0x7c, 0x1d8, 0x34, 0x3c, 0x56,
+ 0x5a, 0x1de, 0x2e, 0x222, 0x212,
+ 0x202, 0x254, 0x264, 0x274, 0x288,
};
DEFINE_EXT_CLK(xo_ao, NULL);
@@ -202,6 +249,7 @@ struct osm_entry {
u16 open_loop_volt;
u32 freq_data;
u32 override_data;
+ u32 spare_data;
long frequency;
};
@@ -230,10 +278,13 @@ struct clk_osm {
u32 apcs_cfg_rcgr;
u32 apcs_cmd_rcgr;
u32 apcs_pll_user_ctl;
+ u32 apcs_mem_acc_cfg[MAX_MEM_ACC_VAL_PER_LEVEL];
+ u32 apcs_mem_acc_val[MAX_MEM_ACC_VALUES];
u32 apm_mode_ctl;
u32 apm_ctrl_status;
u32 osm_clk_rate;
u32 xo_clk_rate;
+ bool secure_init;
bool red_fsm_en;
bool boost_fsm_en;
bool safe_fsm_en;
@@ -241,18 +292,34 @@ struct clk_osm {
bool droop_fsm_en;
bool wfx_fsm_en;
bool pc_fsm_en;
+
+ enum clk_osm_trace_method trace_method;
+ enum clk_osm_trace_packet_id trace_id;
+ u32 trace_periodic_timer;
+ bool trace_en;
};
-static void clk_osm_write_reg(struct clk_osm *c, int val, u32 offset)
+static inline void clk_osm_masked_write_reg(struct clk_osm *c, u32 val,
+ u32 offset, u32 mask)
{
- writel_relaxed(val , (char *)c->vbases[OSM_BASE] + offset
- + c->cluster_num * OSM_CORE_TABLE_SIZE);
+ u32 val2, orig_val;
+
+ val2 = orig_val = readl_relaxed((char *)c->vbases[OSM_BASE] + offset);
+ val2 &= ~mask;
+ val2 |= val & mask;
+
+ if (val2 != orig_val)
+ writel_relaxed(val2, (char *)c->vbases[OSM_BASE] + offset);
}
-static int clk_osm_read_reg(struct clk_osm *c, u32 offset)
+static inline void clk_osm_write_reg(struct clk_osm *c, u32 val, u32 offset)
{
- return readl_relaxed((char *)c->vbases[OSM_BASE] + offset +
- c->cluster_num * OSM_CORE_TABLE_SIZE);
+ writel_relaxed(val, (char *)c->vbases[OSM_BASE] + offset);
+}
+
+static inline int clk_osm_read_reg(struct clk_osm *c, u32 offset)
+{
+ return readl_relaxed((char *)c->vbases[OSM_BASE] + offset);
}
static inline int clk_osm_count_us(struct clk_osm *c, u32 usec)
@@ -396,20 +463,21 @@ static void clk_osm_print_osm_table(struct clk_osm *c)
struct osm_entry *table = c->osm_table;
u32 pll_src, pll_div, lval;
- pr_debug("Index, Frequency, VC, OLV (mv), PLLSrc, PLLDivVal, LVal\n");
+ pr_debug("Index, Frequency, VC, OLV (mv), PLL Src, PLL Div, L-Val, ACC Level\n");
for (i = 0; i < c->num_entries; i++) {
pll_src = (table[i].freq_data & GENMASK(27, 26)) >> 26;
pll_div = (table[i].freq_data & GENMASK(25, 24)) >> 24;
lval = table[i].freq_data & GENMASK(7, 0);
- pr_debug("%3d, %11lu, %2u, %5u, %6u, %8u, %7u\n",
+ pr_debug("%3d, %11lu, %2u, %5u, %6u, %8u, %7u, %5u\n",
i,
table[i].frequency,
table[i].virtual_corner,
table[i].open_loop_volt,
pll_src,
pll_div,
- lval);
+ lval,
+ table[i].spare_data);
}
pr_debug("APM crossover corner: %d\n",
c->apm_crossover_vc);
@@ -466,10 +534,12 @@ static int clk_osm_get_lut(struct platform_device *pdev,
c->osm_table[j].frequency = array[i + FREQ];
c->osm_table[j].freq_data = array[i + FREQ_DATA];
c->osm_table[j].override_data = array[i + PLL_OVERRIDES];
- pr_debug("index=%d freq=%ld freq_data=0x%x override_data=0x%x\n",
+ c->osm_table[j].spare_data = array[i + SPARE_DATA];
+ pr_debug("index=%d freq=%ld freq_data=0x%x override_data=0x%x spare_data=0x%x\n",
j, c->osm_table[j].frequency,
c->osm_table[j].freq_data,
- c->osm_table[j].override_data);
+ c->osm_table[j].override_data,
+ c->osm_table[j].spare_data);
data = (array[i + FREQ_DATA] & GENMASK(18, 16)) >> 16;
if (!last_entry && data == MAX_CONFIG) {
@@ -641,6 +711,49 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev)
of_property_read_bool(of, "qcom,pc-fsm-en");
devm_kfree(&pdev->dev, array);
+
+ perfcl_clk.secure_init = pwrcl_clk.secure_init =
+ of_property_read_bool(pdev->dev.of_node, "qcom,osm-no-tz");
+
+ if (!pwrcl_clk.secure_init)
+ return rc;
+
+ rc = of_property_read_u32_array(of, "qcom,pwrcl-apcs-mem-acc-cfg",
+ pwrcl_clk.apcs_mem_acc_cfg,
+ MAX_MEM_ACC_VAL_PER_LEVEL);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,pwrcl-apcs-mem-acc-cfg property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ of_property_read_u32_array(of, "qcom,perfcl-apcs-mem-acc-cfg",
+ perfcl_clk.apcs_mem_acc_cfg,
+ MAX_MEM_ACC_VAL_PER_LEVEL);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,perfcl-apcs-mem-acc-cfg property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(of, "qcom,pwrcl-apcs-mem-acc-val",
+ pwrcl_clk.apcs_mem_acc_val,
+ MAX_MEM_ACC_VALUES);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,pwrcl-apcs-mem-acc-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(of, "qcom,perfcl-apcs-mem-acc-val",
+ perfcl_clk.apcs_mem_acc_val,
+ MAX_MEM_ACC_VALUES);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,perfcl-apcs-mem-acc-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
return rc;
}
@@ -668,8 +781,10 @@ static int clk_osm_resources_init(struct platform_device *pdev)
return -ENOMEM;
}
- perfcl_clk.pbases[OSM_BASE] = pwrcl_clk.pbases[OSM_BASE];
- perfcl_clk.vbases[OSM_BASE] = pwrcl_clk.vbases[OSM_BASE];
+ perfcl_clk.pbases[OSM_BASE] = pwrcl_clk.pbases[OSM_BASE] +
+ perfcl_clk.cluster_num * OSM_CORE_TABLE_SIZE;
+ perfcl_clk.vbases[OSM_BASE] = pwrcl_clk.vbases[OSM_BASE] +
+ perfcl_clk.cluster_num * OSM_CORE_TABLE_SIZE;
for (i = 0; i < MAX_CLUSTER_CNT; i++) {
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -793,12 +908,12 @@ static void clk_osm_setup_cluster_pll(struct clk_osm *c)
writel_relaxed(0x7, c->vbases[PLL_BASE] + PLL_MODE);
}
-static void clk_osm_setup_hw_table(struct clk_osm *c)
+static int clk_osm_setup_hw_table(struct clk_osm *c)
{
struct osm_entry *entry = c->osm_table;
int i;
- u32 freq_val, volt_val, override_val;
- u32 table_entry_offset;
+ u32 freq_val, volt_val, override_val, spare_val;
+ u32 table_entry_offset, last_spare, last_virtual_corner = 0;
for (i = 0; i < OSM_TABLE_SIZE; i++) {
if (i < c->num_entries) {
@@ -806,17 +921,34 @@ static void clk_osm_setup_hw_table(struct clk_osm *c)
volt_val = BVAL(21, 16, entry[i].virtual_corner)
| BVAL(11, 0, entry[i].open_loop_volt);
override_val = entry[i].override_data;
+ spare_val = entry[i].spare_data;
+
+ if (last_virtual_corner && last_virtual_corner ==
+ entry[i].virtual_corner && last_spare !=
+ entry[i].spare_data) {
+ pr_err("invalid LUT entry at row=%d virtual_corner=%d, spare_data=%d\n",
+ i, entry[i].virtual_corner,
+ entry[i].spare_data);
+ return -EINVAL;
+ }
+ last_virtual_corner = entry[i].virtual_corner;
+ last_spare = entry[i].spare_data;
}
+
table_entry_offset = i * OSM_REG_SIZE;
clk_osm_write_reg(c, i, INDEX_REG + table_entry_offset);
clk_osm_write_reg(c, freq_val, FREQ_REG + table_entry_offset);
clk_osm_write_reg(c, volt_val, VOLT_REG + table_entry_offset);
clk_osm_write_reg(c, override_val, OVERRIDE_REG +
table_entry_offset);
+ clk_osm_write_reg(c, spare_val, SPARE_REG +
+ table_entry_offset);
}
/* Make sure all writes go through */
mb();
+
+ return 0;
}
static int clk_osm_resolve_open_loop_voltages(struct clk_osm *c)
@@ -1207,6 +1339,35 @@ static void clk_osm_program_apm_regs(struct clk_osm *c)
clk_osm_write_reg(c, APM_APC_MODE_VAL, SEQ_REG(26));
}
+static void clk_osm_program_mem_acc_regs(struct clk_osm *c)
+{
+ int i;
+
+ if (!c->secure_init)
+ return;
+
+ clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(50),
+ SEQ_REG(49));
+ clk_osm_write_reg(c, MEM_ACC_SEQ_CONST(1), SEQ_REG(50));
+ clk_osm_write_reg(c, MEM_ACC_SEQ_CONST(1), SEQ_REG(51));
+ clk_osm_write_reg(c, MEM_ACC_SEQ_CONST(2), SEQ_REG(52));
+ clk_osm_write_reg(c, MEM_ACC_SEQ_CONST(3), SEQ_REG(53));
+ clk_osm_write_reg(c, MEM_ACC_SEQ_CONST(4), SEQ_REG(54));
+ clk_osm_write_reg(c, MEM_ACC_INSTR_COMP(0), SEQ_REG(55));
+ clk_osm_write_reg(c, MEM_ACC_INSTR_COMP(1), SEQ_REG(56));
+ clk_osm_write_reg(c, MEM_ACC_INSTR_COMP(2), SEQ_REG(57));
+ clk_osm_write_reg(c, MEM_ACC_INSTR_COMP(3), SEQ_REG(58));
+ clk_osm_write_reg(c, MEM_ACC_READ_MASK, SEQ_REG(59));
+
+ for (i = 0; i < MAX_MEM_ACC_VALUES; i++)
+ clk_osm_write_reg(c, c->apcs_mem_acc_val[i],
+ MEM_ACC_SEQ_REG_VAL_START(i));
+
+ for (i = 0; i < MAX_MEM_ACC_VAL_PER_LEVEL; i++)
+ clk_osm_write_reg(c, c->apcs_mem_acc_cfg[i],
+ MEM_ACC_SEQ_REG_CFG_START(i));
+}
+
void clk_osm_setup_sequencer(struct clk_osm *c)
{
u32 i;
@@ -1243,60 +1404,33 @@ static void clk_osm_setup_osm_was(struct clk_osm *c)
{
u32 val;
- clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(42) +
- c->cluster_num *
- OSM_CORE_TABLE_SIZE, SEQ_REG(40));
- clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(43) +
- c->cluster_num *
- OSM_CORE_TABLE_SIZE, SEQ_REG(41));
- clk_osm_write_reg(c, 0x1, SEQ_REG(44));
- clk_osm_write_reg(c, 0x0, SEQ_REG(45));
- clk_osm_write_reg(c, c->pbases[OSM_BASE] + PDN_FSM_CTRL_REG +
- c->cluster_num *
- OSM_CORE_TABLE_SIZE, SEQ_REG(46));
-
val = clk_osm_read_reg(c, PDN_FSM_CTRL_REG);
val |= IGNORE_PLL_LOCK_MASK;
- clk_osm_write_reg(c, val, SEQ_REG(47));
- val &= ~IGNORE_PLL_LOCK_MASK;
- clk_osm_write_reg(c, val, SEQ_REG(48));
+
+ if (c->secure_init) {
+ clk_osm_write_reg(c, val, SEQ_REG(47));
+ val &= ~IGNORE_PLL_LOCK_MASK;
+ clk_osm_write_reg(c, val, SEQ_REG(48));
+
+ clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(42),
+ SEQ_REG(40));
+ clk_osm_write_reg(c, c->pbases[OSM_BASE] + SEQ_REG(43),
+ SEQ_REG(41));
+ clk_osm_write_reg(c, 0x1, SEQ_REG(44));
+ clk_osm_write_reg(c, 0x0, SEQ_REG(45));
+ clk_osm_write_reg(c, c->pbases[OSM_BASE] + PDN_FSM_CTRL_REG,
+ SEQ_REG(46));
+ } else {
+ scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(47), val);
+ val &= ~IGNORE_PLL_LOCK_MASK;
+ scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(48), val);
+ }
}
-static void clk_osm_do_additional_setup(struct clk_osm *c,
- struct platform_device *pdev)
+static void clk_osm_setup_fsms(struct clk_osm *c)
{
u32 val;
- if (!of_property_read_bool(pdev->dev.of_node, "qcom,osm-no-tz"))
- return;
-
- dev_info(&pdev->dev, "Performing additional OSM setup due to lack of TZ for cluster=%d\n",
- c->cluster_num);
-
- clk_osm_write_reg(c, BVAL(23, 16, 0xF), SPM_CC_CTRL);
-
- /* PLL LVAL programming */
- clk_osm_write_reg(c, c->l_val_base, SEQ_REG(0));
- clk_osm_write_reg(c, PLL_MIN_LVAL, SEQ_REG(21));
-
- /* PLL post-div programming */
- clk_osm_write_reg(c, c->apcs_pll_user_ctl, SEQ_REG(18));
- clk_osm_write_reg(c, PLL_POST_DIV2, SEQ_REG(19));
- clk_osm_write_reg(c, PLL_POST_DIV1, SEQ_REG(29));
-
- /* APM Programming */
- clk_osm_program_apm_regs(c);
-
- /* GFMUX Programming */
- clk_osm_write_reg(c, c->apcs_cfg_rcgr, SEQ_REG(16));
- clk_osm_write_reg(c, GPLL_SEL, SEQ_REG(17));
- clk_osm_write_reg(c, PLL_EARLY_SEL, SEQ_REG(20));
- clk_osm_write_reg(c, PLL_MAIN_SEL, SEQ_REG(32));
- clk_osm_write_reg(c, c->apcs_cmd_rcgr, SEQ_REG(33));
- clk_osm_write_reg(c, RCG_UPDATE, SEQ_REG(34));
- clk_osm_write_reg(c, RCG_UPDATE_SUCCESS, SEQ_REG(35));
- clk_osm_write_reg(c, RCG_UPDATE, SEQ_REG(36));
-
/* Reduction FSM */
if (c->red_fsm_en) {
val = clk_osm_read_reg(c, VMIN_REDUC_ENABLE_REG) | BIT(0);
@@ -1404,6 +1538,43 @@ static void clk_osm_do_additional_setup(struct clk_osm *c,
BVAL(22, 16, 0x2);
clk_osm_write_reg(c, val, DROOP_CTRL_REG);
}
+}
+
+static void clk_osm_do_additional_setup(struct clk_osm *c,
+ struct platform_device *pdev)
+{
+ if (!c->secure_init)
+ return;
+
+ dev_info(&pdev->dev, "Performing additional OSM setup due to lack of TZ for cluster=%d\n",
+ c->cluster_num);
+
+ clk_osm_write_reg(c, BVAL(23, 16, 0xF), SPM_CC_CTRL);
+
+ /* PLL LVAL programming */
+ clk_osm_write_reg(c, c->l_val_base, SEQ_REG(0));
+ clk_osm_write_reg(c, PLL_MIN_LVAL, SEQ_REG(21));
+
+ /* PLL post-div programming */
+ clk_osm_write_reg(c, c->apcs_pll_user_ctl, SEQ_REG(18));
+ clk_osm_write_reg(c, PLL_POST_DIV2, SEQ_REG(19));
+ clk_osm_write_reg(c, PLL_POST_DIV1, SEQ_REG(29));
+
+ /* APM Programming */
+ clk_osm_program_apm_regs(c);
+
+ /* MEM-ACC Programming */
+ clk_osm_program_mem_acc_regs(c);
+
+ /* GFMUX Programming */
+ clk_osm_write_reg(c, c->apcs_cfg_rcgr, SEQ_REG(16));
+ clk_osm_write_reg(c, GPLL_SEL, SEQ_REG(17));
+ clk_osm_write_reg(c, PLL_EARLY_SEL, SEQ_REG(20));
+ clk_osm_write_reg(c, PLL_MAIN_SEL, SEQ_REG(32));
+ clk_osm_write_reg(c, c->apcs_cmd_rcgr, SEQ_REG(33));
+ clk_osm_write_reg(c, RCG_UPDATE, SEQ_REG(34));
+ clk_osm_write_reg(c, RCG_UPDATE_SUCCESS, SEQ_REG(35));
+ clk_osm_write_reg(c, RCG_UPDATE, SEQ_REG(36));
pr_debug("seq_size: %lu, seqbr_size: %lu\n", ARRAY_SIZE(seq_instr),
ARRAY_SIZE(seq_br_instr));
@@ -1417,10 +1588,15 @@ static void clk_osm_apm_vc_setup(struct clk_osm *c)
* APM crossover virtual corner at which the switch
* from APC to MX and vice-versa should take place.
*/
- clk_osm_write_reg(c, c->apm_crossover_vc, SEQ_REG(1));
+ if (c->secure_init) {
+ clk_osm_write_reg(c, c->apm_crossover_vc, SEQ_REG(1));
- /* Ensure writes complete before delaying */
- mb();
+ /* Ensure writes complete before returning */
+ mb();
+ } else {
+ scm_io_write(c->pbases[OSM_BASE] + SEQ_REG(1),
+ c->apm_crossover_vc);
+ }
}
static irqreturn_t clk_osm_debug_irq_cb(int irq, void *data)
@@ -1600,6 +1776,189 @@ static void populate_opp_table(struct platform_device *pdev)
}
}
+static int debugfs_get_trace_enable(void *data, u64 *val)
+{
+ struct clk_osm *c = data;
+
+ *val = c->trace_en;
+ return 0;
+}
+
+static int debugfs_set_trace_enable(void *data, u64 val)
+{
+ struct clk_osm *c = data;
+
+ clk_osm_masked_write_reg(c, val ? TRACE_CTRL_ENABLE :
+ TRACE_CTRL_DISABLE,
+ TRACE_CTRL, TRACE_CTRL_EN_MASK);
+ c->trace_en = val ? true : false;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debugfs_trace_enable_fops,
+ debugfs_get_trace_enable,
+ debugfs_set_trace_enable,
+ "%llu\n");
+
+#define MAX_DEBUG_BUF_LEN 15
+
+static DEFINE_MUTEX(debug_buf_mutex);
+static char debug_buf[MAX_DEBUG_BUF_LEN];
+
+static ssize_t debugfs_trace_method_set(struct file *file,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct clk_osm *c = file->private_data;
+ u32 val;
+
+ if (IS_ERR(file) || file == NULL) {
+ pr_err("input error %ld\n", PTR_ERR(file));
+ return -EINVAL;
+ }
+
+ if (!c) {
+ pr_err("invalid clk_osm handle\n");
+ return -EINVAL;
+ }
+
+ if (count < MAX_DEBUG_BUF_LEN) {
+ mutex_lock(&debug_buf_mutex);
+
+ if (copy_from_user(debug_buf, (void __user *) buf, count)) {
+ mutex_unlock(&debug_buf_mutex);
+ return -EFAULT;
+ }
+ debug_buf[count] = '\0';
+ mutex_unlock(&debug_buf_mutex);
+
+ /* check that user entered a supported packet type */
+ if (strcmp(debug_buf, "periodic\n") == 0) {
+ clk_osm_write_reg(c, clk_osm_count_us(c,
+ PERIODIC_TRACE_DEFAULT_US),
+ PERIODIC_TRACE_TIMER_CTRL);
+ clk_osm_masked_write_reg(c,
+ TRACE_CTRL_PERIODIC_TRACE_ENABLE,
+ TRACE_CTRL, TRACE_CTRL_PERIODIC_TRACE_EN_MASK);
+ c->trace_method = PERIODIC_PACKET;
+ c->trace_periodic_timer = PERIODIC_TRACE_DEFAULT_US;
+ return count;
+ } else if (strcmp(debug_buf, "xor\n") == 0) {
+ val = clk_osm_read_reg(c, TRACE_CTRL);
+ val &= ~TRACE_CTRL_PERIODIC_TRACE_ENABLE;
+ clk_osm_write_reg(c, val, TRACE_CTRL);
+ c->trace_method = XOR_PACKET;
+ return count;
+ }
+ }
+
+ pr_err("error, supported trace mode types: 'periodic' or 'xor'\n");
+ return -EINVAL;
+}
+
+static ssize_t debugfs_trace_method_get(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct clk_osm *c = file->private_data;
+ int len, rc;
+
+ if (IS_ERR(file) || file == NULL) {
+ pr_err("input error %ld\n", PTR_ERR(file));
+ return -EINVAL;
+ }
+
+ if (!c) {
+ pr_err("invalid clk_osm handle\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&debug_buf_mutex);
+
+ if (c->trace_method == PERIODIC_PACKET)
+ len = snprintf(debug_buf, sizeof(debug_buf), "periodic\n");
+ else if (c->trace_method == XOR_PACKET)
+ len = snprintf(debug_buf, sizeof(debug_buf), "xor\n");
+
+ rc = simple_read_from_buffer((void __user *) buf, len, ppos,
+ (void *) debug_buf, len);
+
+ mutex_unlock(&debug_buf_mutex);
+
+ return rc;
+}
+
+static int debugfs_trace_method_open(struct inode *inode, struct file *file)
+{
+ if (IS_ERR(file) || file == NULL) {
+ pr_err("input error %ld\n", PTR_ERR(file));
+ return -EINVAL;
+ }
+
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static const struct file_operations debugfs_trace_method_fops = {
+ .write = debugfs_trace_method_set,
+ .open = debugfs_trace_method_open,
+ .read = debugfs_trace_method_get,
+};
+
+static int debugfs_get_trace_packet_id(void *data, u64 *val)
+{
+ struct clk_osm *c = data;
+
+ *val = c->trace_id;
+ return 0;
+}
+
+static int debugfs_set_trace_packet_id(void *data, u64 val)
+{
+ struct clk_osm *c = data;
+
+ if (val < TRACE_PACKET0 || val > TRACE_PACKET3) {
+ pr_err("supported trace IDs=%d-%d\n",
+ TRACE_PACKET0, TRACE_PACKET3);
+ return 0;
+ }
+
+ clk_osm_masked_write_reg(c, val << TRACE_CTRL_PACKET_TYPE_SHIFT,
+ TRACE_CTRL, TRACE_CTRL_PACKET_TYPE_MASK);
+ c->trace_id = val;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debugfs_trace_packet_id_fops,
+ debugfs_get_trace_packet_id,
+ debugfs_set_trace_packet_id,
+ "%llu\n");
+
+static int debugfs_get_trace_periodic_timer(void *data, u64 *val)
+{
+ struct clk_osm *c = data;
+
+ *val = c->trace_periodic_timer;
+ return 0;
+}
+
+static int debugfs_set_trace_periodic_timer(void *data, u64 val)
+{
+ struct clk_osm *c = data;
+
+ if (val < PERIODIC_TRACE_MIN_US || val > PERIODIC_TRACE_MAX_US) {
+ pr_err("supported periodic trace periods=%d-%d\n",
+ PERIODIC_TRACE_MIN_US, PERIODIC_TRACE_MAX_US);
+ return 0;
+ }
+
+ clk_osm_write_reg(c, clk_osm_count_us(c, val),
+ PERIODIC_TRACE_TIMER_CTRL);
+ c->trace_periodic_timer = val;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debugfs_trace_periodic_timer_fops,
+ debugfs_get_trace_periodic_timer,
+ debugfs_set_trace_periodic_timer,
+ "%llu\n");
+
static int debugfs_get_perf_state_met_irq(void *data, u64 *val)
{
struct clk_osm *c = data;
@@ -1711,6 +2070,42 @@ static void populate_debugfs_dir(struct clk_osm *c)
goto exit;
}
+ temp = debugfs_create_file("trace_enable",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_trace_enable_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_trace_enable_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
+ temp = debugfs_create_file("trace_method",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_trace_method_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_trace_method_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
+ temp = debugfs_create_file("trace_packet_id",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_trace_packet_id_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_trace_packet_id_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
+ temp = debugfs_create_file("trace_periodic_timer",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_trace_periodic_timer_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_trace_periodic_timer_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
exit:
if (IS_ERR_OR_NULL(temp))
debugfs_remove_recursive(c->debugfs);
@@ -1789,8 +2184,16 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
clk_osm_write_reg(&pwrcl_clk, PLL_MIN_LVAL, SEQ_REG(27));
clk_osm_write_reg(&perfcl_clk, PLL_MIN_LVAL, SEQ_REG(27));
- clk_osm_setup_hw_table(&pwrcl_clk);
- clk_osm_setup_hw_table(&perfcl_clk);
+ rc = clk_osm_setup_hw_table(&pwrcl_clk);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to setup power cluster hardware table\n");
+ goto exit;
+ }
+ rc = clk_osm_setup_hw_table(&perfcl_clk);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to setup perf cluster hardware table\n");
+ goto exit;
+ }
/* Policy tuning */
rc = clk_osm_set_cc_policy(pdev);
@@ -1815,6 +2218,9 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
goto exit;
}
+ clk_osm_setup_fsms(&pwrcl_clk);
+ clk_osm_setup_fsms(&perfcl_clk);
+
/*
* Perform typical secure-world HW initialization
* as necessary.
@@ -1891,11 +2297,13 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
populate_debugfs_dir(&pwrcl_clk);
populate_debugfs_dir(&perfcl_clk);
+ of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+
pr_info("OSM driver inited\n");
return 0;
exit:
- dev_err(&pdev->dev, "OSM driver failed to initialize, rc=%d",
+ dev_err(&pdev->dev, "OSM driver failed to initialize, rc=%d\n",
rc);
panic("Unable to Setup OSM");
}
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.h b/drivers/phy/phy-qcom-ufs-qmp-v3.h
index 18dddef9f0a4..ab4179481402 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.h
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -130,6 +130,7 @@
#define UFS_PHY_TX_LARGE_AMP_DRV_LVL PHY_OFF(0x2C)
#define UFS_PHY_TX_SMALL_AMP_DRV_LVL PHY_OFF(0x34)
#define UFS_PHY_LINECFG_DISABLE PHY_OFF(0x130)
+#define UFS_PHY_RX_SYM_RESYNC_CTRL PHY_OFF(0x134)
#define UFS_PHY_RX_SIGDET_CTRL2 PHY_OFF(0x140)
#define UFS_PHY_RX_PWM_GEAR_BAND PHY_OFF(0x14C)
#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x160)
@@ -181,6 +182,7 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x02),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0A),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
@@ -196,8 +198,8 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x34),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0xCB),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x01),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xFF),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0C),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98),
@@ -206,7 +208,7 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x34),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x3F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xD6),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xB2),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0F),
@@ -229,6 +231,7 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL2, 0x6C),
UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_LARGE_AMP_DRV_LVL, 0x0A),
UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_SMALL_AMP_DRV_LVL, 0x02),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SYM_RESYNC_CTRL, 0x03),
};
static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 2e0014b3a7f9..30e554b648f5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -1647,39 +1647,40 @@ static void ipa3_destroy_imm(void *user1, int user2)
ipahal_destroy_imm_cmd(user1);
}
-static int ipa3_q6_pipe_delay(void)
+static void ipa3_q6_pipe_delay(bool delay)
{
int client_idx;
int ep_idx;
struct ipa_ep_cfg_ctrl ep_ctrl;
memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
+ ep_ctrl.ipa_ep_delay = delay;
+
for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
ep_idx = ipa3_get_ep_mapping(client_idx);
if (ep_idx == -1)
continue;
- ep_ctrl.ipa_ep_delay = 1;
-
ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n,
ep_idx, &ep_ctrl);
}
}
-
- return 0;
}
-static int ipa3_q6_avoid_holb(void)
+static void ipa3_q6_avoid_holb(void)
{
int ep_idx;
int client_idx;
- struct ipa_ep_cfg_ctrl avoid_holb;
+ struct ipa_ep_cfg_ctrl ep_suspend;
struct ipa_ep_cfg_holb ep_holb;
- memset(&avoid_holb, 0, sizeof(avoid_holb));
+ memset(&ep_suspend, 0, sizeof(ep_suspend));
memset(&ep_holb, 0, sizeof(ep_holb));
- avoid_holb.ipa_ep_suspend = true;
+
+ ep_suspend.ipa_ep_suspend = true;
+ ep_holb.tmr_val = 0;
+ ep_holb.en = 1;
for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
if (IPA_CLIENT_IS_Q6_CONS(client_idx)) {
@@ -1693,8 +1694,6 @@ static int ipa3_q6_avoid_holb(void)
* they are not valid, therefore, the above function
* will fail.
*/
- ep_holb.tmr_val = 0;
- ep_holb.en = 1;
ipahal_write_reg_n_fields(
IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
ep_idx, &ep_holb);
@@ -1702,11 +1701,11 @@ static int ipa3_q6_avoid_holb(void)
IPA_ENDP_INIT_HOL_BLOCK_EN_n,
ep_idx, &ep_holb);
- ipa3_cfg_ep_ctrl(ep_idx, &avoid_holb);
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_CTRL_n,
+ ep_idx, &ep_suspend);
}
}
-
- return 0;
}
static u32 ipa3_get_max_flt_rt_cmds(u32 num_pipes)
@@ -1785,8 +1784,7 @@ static int ipa3_q6_clean_q6_tables(void)
*/
cmd.is_read = false;
cmd.skip_pipeline_clear = 0;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr =
@@ -1810,8 +1808,7 @@ static int ipa3_q6_clean_q6_tables(void)
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr =
@@ -1839,8 +1836,7 @@ static int ipa3_q6_clean_q6_tables(void)
*/
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr =
@@ -1864,8 +1860,7 @@ static int ipa3_q6_clean_q6_tables(void)
cmd.is_read = false;
cmd.skip_pipeline_clear = 0;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr =
@@ -1897,7 +1892,7 @@ static int ipa3_q6_clean_q6_tables(void)
index++) {
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
@@ -1919,7 +1914,7 @@ static int ipa3_q6_clean_q6_tables(void)
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
@@ -1945,8 +1940,7 @@ static int ipa3_q6_clean_q6_tables(void)
index++) {
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
@@ -1968,8 +1962,7 @@ static int ipa3_q6_clean_q6_tables(void)
cmd.is_read = false;
cmd.skip_pipeline_clear = false;
- cmd.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ cmd.pipeline_clear_options = IPAHAL_HPS_CLEAR;
cmd.size = mem.size;
cmd.system_addr = mem.phys_base;
cmd.local_addr = ipa3_ctx->smem_restricted_bytes +
@@ -2008,21 +2001,7 @@ bail_dma:
return retval;
}
-static void ipa3_q6_disable_agg_reg(
- struct ipahal_imm_cmd_register_write *reg_write, int ep_idx)
-{
- struct ipahal_reg_valmask valmask;
-
- reg_write->skip_pipeline_clear = false;
- reg_write->pipeline_clear_options = IPAHAL_FULL_PIPELINE_CLEAR;
- reg_write->offset =
- ipahal_get_reg_n_ofst(IPA_ENDP_INIT_AGGR_n, ep_idx);
- ipahal_get_disable_aggr_valmask(&valmask);
- reg_write->value = valmask.val;
- reg_write->value_mask = valmask.mask;
-}
-
-static int ipa3_q6_set_ex_path_dis_agg(void)
+static int ipa3_q6_set_ex_path_to_apps(void)
{
int ep_idx;
int client_idx;
@@ -2053,7 +2032,7 @@ static int ipa3_q6_set_ex_path_dis_agg(void)
reg_write.skip_pipeline_clear = false;
reg_write.pipeline_clear_options =
- IPAHAL_FULL_PIPELINE_CLEAR;
+ IPAHAL_HPS_CLEAR;
reg_write.offset =
ipahal_get_reg_ofst(IPA_ENDP_STATUS_n);
ipahal_get_status_ep_valmask(
@@ -2079,30 +2058,6 @@ static int ipa3_q6_set_ex_path_dis_agg(void)
}
}
- /* Disable AGGR on IPA->Q6 pipes */
- for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
- if (IPA_CLIENT_IS_Q6_CONS(client_idx)) {
-
- ipa3_q6_disable_agg_reg(&reg_write,
- ipa3_get_ep_mapping(client_idx));
- cmd_pyld = ipahal_construct_imm_cmd(
- IPA_IMM_CMD_REGISTER_WRITE, &reg_write, false);
- if (!cmd_pyld) {
- IPAERR("fail construct register_write cmd\n");
- BUG();
- }
-
- desc[num_descs].opcode = ipahal_imm_cmd_get_opcode(
- IPA_IMM_CMD_REGISTER_WRITE);
- desc[num_descs].type = IPA_IMM_CMD_DESC;
- desc[num_descs].callback = ipa3_destroy_imm;
- desc[num_descs].user1 = cmd_pyld;
- desc[num_descs].pyld = cmd_pyld->data;
- desc[num_descs].len = cmd_pyld->len;
- num_descs++;
- }
- }
-
/* Will wait 150msecs for IPA tag process completion */
retval = ipa3_tag_process(desc, num_descs,
msecs_to_jiffies(CLEANUP_TAG_PROCESS_TIMEOUT));
@@ -2127,70 +2082,65 @@ static int ipa3_q6_set_ex_path_dis_agg(void)
* ipa3_q6_cleanup() - A cleanup for all Q6 related configuration
* in IPA HW. This is performed in case of SSR.
*
-* Return codes:
-* 0: success
* This is a mandatory procedure, in case one of the steps fails, the
* AP needs to restart.
*/
-int ipa3_q6_cleanup(void)
+void ipa3_q6_cleanup(void)
{
- /* If uC has notified the APPS upon a ZIP engine error,
- * APPS need to assert (This is a non recoverable error).
- */
- if (ipa3_ctx->uc_ctx.uc_zip_error)
- BUG();
+ IPADBG_LOW("ENTER\n");
- IPA_ACTIVE_CLIENTS_INC_SPECIAL("Q6");
+ IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- if (ipa3_q6_pipe_delay()) {
- IPAERR("Failed to delay Q6 pipes\n");
- BUG();
- }
- if (ipa3_q6_avoid_holb()) {
- IPAERR("Failed to set HOLB on Q6 pipes\n");
- BUG();
- }
+ ipa3_q6_pipe_delay(true);
+ ipa3_q6_avoid_holb();
if (ipa3_q6_clean_q6_tables()) {
IPAERR("Failed to clean Q6 tables\n");
BUG();
}
- if (ipa3_q6_set_ex_path_dis_agg()) {
- IPAERR("Failed to disable aggregation on Q6 pipes\n");
+ if (ipa3_q6_set_ex_path_to_apps()) {
+ IPAERR("Failed to redirect exceptions to APPS\n");
BUG();
}
+ /* Remove delay from Q6 PRODs to avoid pending descriptors
+ * on pipe reset procedure
+ */
+ ipa3_q6_pipe_delay(false);
- ipa3_ctx->q6_proxy_clk_vote_valid = true;
-
- return 0;
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+ IPADBG_LOW("Exit with success\n");
}
-/**
-* ipa3_q6_pipe_reset() - A cleanup for the Q6 pipes
-* in IPA HW. This is performed in case of SSR.
-*
-* Return codes:
-* 0: success
-* This is a mandatory procedure, in case one of the steps fails, the
-* AP needs to restart.
-*/
-int ipa3_q6_pipe_reset(void)
+/*
+ * ipa3_validate_q6_gsi_channel_empty() - Check if GSI channel related to Q6
+ * producer client is empty. This is used in case of SSR.
+ *
+ * Q6 GSI channel emptiness is needed to garantee no descriptors with invalid
+ * info are injected into IPA RX from IPA_IF, while modem is restarting.
+ */
+void ipa3_validate_q6_gsi_channel_empty(void)
{
int client_idx;
- int res;
+
+ IPADBG_LOW("ENTER\n");
+ IPA_ACTIVE_CLIENTS_INC_SIMPLE();
if (!ipa3_ctx->uc_ctx.uc_loaded) {
- IPAERR("uC is not loaded, won't reset Q6 pipes\n");
- return 0;
+ IPAERR("uC is not loaded. Skipping\n");
+ return;
}
for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++)
- if (IPA_CLIENT_IS_Q6_CONS(client_idx) ||
- IPA_CLIENT_IS_Q6_PROD(client_idx)) {
- res = ipa3_uc_reset_pipe(client_idx);
- if (res)
+ if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
+ if (ipa3_uc_is_gsi_channel_empty(client_idx)) {
+ IPAERR("fail to validate Q6 ch emptiness %d\n",
+ client_idx);
BUG();
+ return;
+ }
}
- return 0;
+
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+ IPADBG_LOW("Exit with success\n");
}
static inline void ipa3_sram_set_canary(u32 *sram_mmio, int offset)
@@ -4066,12 +4016,6 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
IPADBG("IPA Driver initialization started\n");
- /*
- * since structure alignment is implementation dependent, add test to
- * avoid different and incompatible data layouts
- */
- BUILD_BUG_ON(sizeof(struct ipa3_hw_pkt_status) != IPA_PKT_STATUS_SIZE);
-
ipa3_ctx = kzalloc(sizeof(*ipa3_ctx), GFP_KERNEL);
if (!ipa3_ctx) {
IPAERR(":kzalloc err.\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index dabf73029fa8..6c639e1c7a1a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -37,17 +37,6 @@ const char *ipa3_excp_name[] = {
__stringify_1(IPA_A5_MUX_HDR_EXCP_FLAG_IP),
};
-const char *ipa3_status_excp_name[] = {
- __stringify_1(IPA_EXCP_DEAGGR),
- __stringify_1(IPA_EXCP_REPLICATION),
- __stringify_1(IPA_EXCP_IP),
- __stringify_1(IPA_EXCP_IHL),
- __stringify_1(IPA_EXCP_FRAG_MISS),
- __stringify_1(IPA_EXCP_SW),
- __stringify_1(IPA_EXCP_NAT),
- __stringify_1(IPA_EXCP_NONE),
-};
-
const char *ipa3_event_name[] = {
__stringify(WLAN_CLIENT_CONNECT),
__stringify(WLAN_CLIENT_DISCONNECT),
@@ -929,47 +918,47 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++)
connect |= (ipa3_ctx->ep[i].valid << i);
- nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
- "sw_tx=%u\n"
- "hw_tx=%u\n"
- "tx_compl=%u\n"
- "wan_rx=%u\n"
- "stat_compl=%u\n"
- "lan_aggr_close=%u\n"
- "wan_aggr_close=%u\n"
- "act_clnt=%u\n"
- "con_clnt_bmap=0x%x\n"
- "wan_rx_empty=%u\n"
- "wan_repl_rx_empty=%u\n"
- "lan_rx_empty=%u\n"
- "lan_repl_rx_empty=%u\n"
- "flow_enable=%u\n"
- "flow_disable=%u\n",
- ipa3_ctx->stats.tx_sw_pkts,
- ipa3_ctx->stats.tx_hw_pkts,
- ipa3_ctx->stats.tx_pkts_compl,
- ipa3_ctx->stats.rx_pkts,
- ipa3_ctx->stats.stat_compl,
- ipa3_ctx->stats.aggr_close,
- ipa3_ctx->stats.wan_aggr_close,
- ipa3_ctx->ipa3_active_clients.cnt,
- connect,
- ipa3_ctx->stats.wan_rx_empty,
- ipa3_ctx->stats.wan_repl_rx_empty,
- ipa3_ctx->stats.lan_rx_empty,
- ipa3_ctx->stats.lan_repl_rx_empty,
- ipa3_ctx->stats.flow_enable,
- ipa3_ctx->stats.flow_disable);
- cnt += nbytes;
+ nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
+ "sw_tx=%u\n"
+ "hw_tx=%u\n"
+ "tx_compl=%u\n"
+ "wan_rx=%u\n"
+ "stat_compl=%u\n"
+ "lan_aggr_close=%u\n"
+ "wan_aggr_close=%u\n"
+ "act_clnt=%u\n"
+ "con_clnt_bmap=0x%x\n"
+ "wan_rx_empty=%u\n"
+ "wan_repl_rx_empty=%u\n"
+ "lan_rx_empty=%u\n"
+ "lan_repl_rx_empty=%u\n"
+ "flow_enable=%u\n"
+ "flow_disable=%u\n",
+ ipa3_ctx->stats.tx_sw_pkts,
+ ipa3_ctx->stats.tx_hw_pkts,
+ ipa3_ctx->stats.tx_pkts_compl,
+ ipa3_ctx->stats.rx_pkts,
+ ipa3_ctx->stats.stat_compl,
+ ipa3_ctx->stats.aggr_close,
+ ipa3_ctx->stats.wan_aggr_close,
+ ipa3_ctx->ipa3_active_clients.cnt,
+ connect,
+ ipa3_ctx->stats.wan_rx_empty,
+ ipa3_ctx->stats.wan_repl_rx_empty,
+ ipa3_ctx->stats.lan_rx_empty,
+ ipa3_ctx->stats.lan_repl_rx_empty,
+ ipa3_ctx->stats.flow_enable,
+ ipa3_ctx->stats.flow_disable);
+ cnt += nbytes;
- for (i = 0; i < MAX_NUM_EXCP; i++) {
- nbytes = scnprintf(dbg_buff + cnt,
- IPA_MAX_MSG_LEN - cnt,
- "lan_rx_excp[%u:%20s]=%u\n", i,
- ipa3_status_excp_name[i],
- ipa3_ctx->stats.rx_excp_pkts[i]);
- cnt += nbytes;
- }
+ for (i = 0; i < IPAHAL_PKT_STATUS_EXCEPTION_MAX; i++) {
+ nbytes = scnprintf(dbg_buff + cnt,
+ IPA_MAX_MSG_LEN - cnt,
+ "lan_rx_excp[%u:%20s]=%u\n", i,
+ ipahal_pkt_status_exception_str(i),
+ ipa3_ctx->stats.rx_excp_pkts[i]);
+ cnt += nbytes;
+ }
return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}
@@ -1492,7 +1481,7 @@ static ssize_t ipa3_rm_read_stats(struct file *file, char __user *ubuf,
return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}
-static void ipa_dump_status(struct ipa3_hw_pkt_status *status)
+static void ipa_dump_status(struct ipahal_pkt_status *status)
{
IPA_DUMP_STATUS_FIELD(status_opcode);
IPA_DUMP_STATUS_FIELD(exception);
@@ -1501,22 +1490,24 @@ static void ipa_dump_status(struct ipa3_hw_pkt_status *status)
IPA_DUMP_STATUS_FIELD(endp_src_idx);
IPA_DUMP_STATUS_FIELD(endp_dest_idx);
IPA_DUMP_STATUS_FIELD(metadata);
- IPA_DUMP_STATUS_FIELD(filt_local);
- IPA_DUMP_STATUS_FIELD(filt_hash);
- IPA_DUMP_STATUS_FIELD(filt_global);
- IPA_DUMP_STATUS_FIELD(ret_hdr);
- IPA_DUMP_STATUS_FIELD(filt_rule_id);
- IPA_DUMP_STATUS_FIELD(route_local);
- IPA_DUMP_STATUS_FIELD(route_hash);
+ IPA_DUMP_STATUS_FIELD(flt_local);
+ IPA_DUMP_STATUS_FIELD(flt_hash);
+ IPA_DUMP_STATUS_FIELD(flt_global);
+ IPA_DUMP_STATUS_FIELD(flt_ret_hdr);
+ IPA_DUMP_STATUS_FIELD(flt_miss);
+ IPA_DUMP_STATUS_FIELD(flt_rule_id);
+ IPA_DUMP_STATUS_FIELD(rt_local);
+ IPA_DUMP_STATUS_FIELD(rt_hash);
IPA_DUMP_STATUS_FIELD(ucp);
- IPA_DUMP_STATUS_FIELD(route_tbl_idx);
- IPA_DUMP_STATUS_FIELD(route_rule_id);
+ IPA_DUMP_STATUS_FIELD(rt_tbl_idx);
+ IPA_DUMP_STATUS_FIELD(rt_miss);
+ IPA_DUMP_STATUS_FIELD(rt_rule_id);
IPA_DUMP_STATUS_FIELD(nat_hit);
- IPA_DUMP_STATUS_FIELD(nat_tbl_idx);
+ IPA_DUMP_STATUS_FIELD(nat_entry_idx);
IPA_DUMP_STATUS_FIELD(nat_type);
- pr_err("tag = 0x%llx\n", (u64)status->tag & 0xFFFFFFFFFFFF);
+ pr_err("tag = 0x%llx\n", (u64)status->tag_info & 0xFFFFFFFFFFFF);
IPA_DUMP_STATUS_FIELD(seq_num);
- IPA_DUMP_STATUS_FIELD(time_day_ctr);
+ IPA_DUMP_STATUS_FIELD(time_of_day_ctr);
IPA_DUMP_STATUS_FIELD(hdr_local);
IPA_DUMP_STATUS_FIELD(hdr_offset);
IPA_DUMP_STATUS_FIELD(frag_hit);
@@ -1538,8 +1529,6 @@ static ssize_t ipa_status_stats_read(struct file *file, char __user *ubuf,
continue;
memcpy(stats, ipa3_ctx->ep[i].sys->status_stat, sizeof(*stats));
- stats->curr = (stats->curr + IPA_MAX_STATUS_STAT_NUM - 1)
- % IPA_MAX_STATUS_STAT_NUM;
pr_err("Statuses for pipe %d\n", i);
for (j = 0; j < IPA_MAX_STATUS_STAT_NUM; j++) {
pr_err("curr=%d\n", stats->curr);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 0ba23b890e37..d545de10296d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -2219,7 +2219,8 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb,
struct ipa3_sys_context *sys)
{
int rc = 0;
- struct ipa3_hw_pkt_status *status;
+ struct ipahal_pkt_status status;
+ u32 pkt_status_sz;
struct sk_buff *skb2;
int pad_len_byte;
int len;
@@ -2297,11 +2298,12 @@ static int ipa3_lan_rx_pyld_hdlr(struct sk_buff *skb,
}
begin:
+ pkt_status_sz = ipahal_pkt_status_get_size();
while (skb->len) {
drop_packet = false;
IPADBG_LOW("LEN_REM %d\n", skb->len);
- if (skb->len < IPA_PKT_STATUS_SIZE) {
+ if (skb->len < pkt_status_sz) {
WARN_ON(sys->prev_skb != NULL);
IPADBG_LOW("status straddles buffer\n");
sys->prev_skb = skb;
@@ -2309,43 +2311,47 @@ begin:
return rc;
}
- status = (struct ipa3_hw_pkt_status *)skb->data;
+ ipahal_pkt_status_parse(skb->data, &status);
IPADBG_LOW("STATUS opcode=%d src=%d dst=%d len=%d\n",
- status->status_opcode, status->endp_src_idx,
- status->endp_dest_idx, status->pkt_len);
+ status.status_opcode, status.endp_src_idx,
+ status.endp_dest_idx, status.pkt_len);
if (sys->status_stat) {
sys->status_stat->status[sys->status_stat->curr] =
- *status;
+ status;
sys->status_stat->curr++;
if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
sys->status_stat->curr = 0;
}
- if ((status->status_opcode &
- (IPA_HW_STATUS_OPCODE_DROPPED_PACKET |
- IPA_HW_STATUS_OPCODE_PACKET |
- IPA_HW_STATUS_OPCODE_SUSPENDED_PACKET |
- IPA_HW_STATUS_OPCODE_PACKET_2ND_PASS)) == 0) {
+ if ((status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_DROPPED_PACKET) &&
+ (status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_PACKET) &&
+ (status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_SUSPENDED_PACKET) &&
+ (status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS)) {
IPAERR("unsupported opcode(%d)\n",
- status->status_opcode);
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ status.status_opcode);
+ skb_pull(skb, pkt_status_sz);
continue;
}
- IPA_STATS_EXCP_CNT(status->exception,
+ IPA_STATS_EXCP_CNT(status.exception,
ipa3_ctx->stats.rx_excp_pkts);
- if (status->endp_dest_idx >= ipa3_ctx->ipa_num_pipes ||
- status->endp_src_idx >= ipa3_ctx->ipa_num_pipes ||
- status->pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
+ if (status.endp_dest_idx >= ipa3_ctx->ipa_num_pipes ||
+ status.endp_src_idx >= ipa3_ctx->ipa_num_pipes ||
+ status.pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
IPAERR("status fields invalid\n");
WARN_ON(1);
BUG();
}
- if (status->status_mask & IPA_HW_PKT_STATUS_MASK_TAG_VALID) {
+ if (IPAHAL_PKT_STATUS_MASK_FLAG_VAL(
+ IPAHAL_PKT_STATUS_MASK_TAG_VALID_SHFT, &status)) {
struct ipa3_tag_completion *comp;
IPADBG_LOW("TAG packet arrived\n");
- if (status->tag == IPA_COOKIE) {
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ if (status.tag_info == IPA_COOKIE) {
+ skb_pull(skb, pkt_status_sz);
if (skb->len < sizeof(comp)) {
IPAERR("TAG arrived without packet\n");
return rc;
@@ -2358,100 +2364,100 @@ begin:
kfree(comp);
continue;
} else {
- ptr = tag_to_pointer_wa(status->tag);
+ ptr = tag_to_pointer_wa(status.tag_info);
tx_pkt = (struct ipa3_tx_pkt_wrapper *)ptr;
IPADBG_LOW("tx_pkt recv = %p\n", tx_pkt);
}
}
- if (status->pkt_len == 0) {
+ if (status.pkt_len == 0) {
IPADBG_LOW("Skip aggr close status\n");
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ skb_pull(skb, pkt_status_sz);
IPA_STATS_INC_CNT(ipa3_ctx->stats.aggr_close);
- IPA_STATS_DEC_CNT(
- ipa3_ctx->stats.rx_excp_pkts[MAX_NUM_EXCP - 1]);
+ IPA_STATS_DEC_CNT(ipa3_ctx->stats.rx_excp_pkts
+ [IPAHAL_PKT_STATUS_EXCEPTION_NONE]);
continue;
}
- if (status->endp_dest_idx == (sys->ep - ipa3_ctx->ep)) {
+ if (status.endp_dest_idx == (sys->ep - ipa3_ctx->ep)) {
/* RX data */
- src_pipe = status->endp_src_idx;
+ src_pipe = status.endp_src_idx;
/*
* A packet which is received back to the AP after
* there was no route match.
*/
- if (!status->exception &&
- status->route_rule_id == IPA_RULE_ID_INVALID)
+ if (status.exception ==
+ IPAHAL_PKT_STATUS_EXCEPTION_NONE &&
+ status.rt_rule_id == IPA_RULE_ID_INVALID)
drop_packet = true;
- if (skb->len == IPA_PKT_STATUS_SIZE &&
- !status->exception) {
+ if (skb->len == pkt_status_sz &&
+ status.exception ==
+ IPAHAL_PKT_STATUS_EXCEPTION_NONE) {
WARN_ON(sys->prev_skb != NULL);
IPADBG_LOW("Ins header in next buffer\n");
sys->prev_skb = skb;
- sys->len_partial = skb->len;
+ sys->len_partial = skb->len;
return rc;
}
- pad_len_byte = ((status->pkt_len + 3) & ~3) -
- status->pkt_len;
+ pad_len_byte = ((status.pkt_len + 3) & ~3) -
+ status.pkt_len;
- len = status->pkt_len + pad_len_byte +
+ len = status.pkt_len + pad_len_byte +
IPA_SIZE_DL_CSUM_META_TRAILER;
IPADBG_LOW("pad %d pkt_len %d len %d\n", pad_len_byte,
- status->pkt_len, len);
+ status.pkt_len, len);
- if (status->exception ==
- IPA_HW_PKT_STATUS_EXCEPTION_DEAGGR) {
+ if (status.exception ==
+ IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR) {
IPADBG_LOW(
"Dropping packet on DeAggr Exception\n");
- skb_pull(skb, len + IPA_PKT_STATUS_SIZE);
+ skb_pull(skb, len + pkt_status_sz);
continue;
}
skb2 = ipa3_skb_copy_for_client(skb,
- status->pkt_len + IPA_PKT_STATUS_SIZE);
+ status.pkt_len + pkt_status_sz);
if (likely(skb2)) {
- if (skb->len < len + IPA_PKT_STATUS_SIZE) {
+ if (skb->len < len + pkt_status_sz) {
IPADBG_LOW("SPL skb len %d len %d\n",
skb->len, len);
sys->prev_skb = skb2;
sys->len_rem = len - skb->len +
- IPA_PKT_STATUS_SIZE;
+ pkt_status_sz;
sys->len_pad = pad_len_byte;
skb_pull(skb, skb->len);
} else {
- skb_trim(skb2, status->pkt_len +
- IPA_PKT_STATUS_SIZE);
+ skb_trim(skb2, status.pkt_len +
+ pkt_status_sz);
IPADBG_LOW("rx avail for %d\n",
- status->endp_dest_idx);
+ status.endp_dest_idx);
if (drop_packet)
dev_kfree_skb_any(skb2);
else {
skb2->truesize = skb2->len +
sizeof(struct sk_buff) +
(ALIGN(len +
- IPA_PKT_STATUS_SIZE, 32) *
+ pkt_status_sz, 32) *
unused / used_align);
sys->ep->client_notify(
sys->ep->priv,
IPA_RECEIVE,
(unsigned long)(skb2));
}
- skb_pull(skb, len +
- IPA_PKT_STATUS_SIZE);
+ skb_pull(skb, len + pkt_status_sz);
}
} else {
IPAERR("fail to alloc skb\n");
if (skb->len < len) {
sys->prev_skb = NULL;
sys->len_rem = len - skb->len +
- IPA_PKT_STATUS_SIZE;
+ pkt_status_sz;
sys->len_pad = pad_len_byte;
skb_pull(skb, skb->len);
} else {
- skb_pull(skb, len +
- IPA_PKT_STATUS_SIZE);
+ skb_pull(skb, len + pkt_status_sz);
}
}
/* TX comp */
@@ -2459,13 +2465,13 @@ begin:
IPADBG_LOW("tx comp imp for %d\n", src_pipe);
} else {
/* TX comp */
- ipa3_wq_write_done_status(status->endp_src_idx, tx_pkt);
+ ipa3_wq_write_done_status(status.endp_src_idx, tx_pkt);
IPADBG_LOW("tx comp exp for %d\n",
- status->endp_src_idx);
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ status.endp_src_idx);
+ skb_pull(skb, pkt_status_sz);
IPA_STATS_INC_CNT(ipa3_ctx->stats.stat_compl);
- IPA_STATS_DEC_CNT(
- ipa3_ctx->stats.rx_excp_pkts[MAX_NUM_EXCP - 1]);
+ IPA_STATS_DEC_CNT(ipa3_ctx->stats.rx_excp_pkts
+ [IPAHAL_PKT_STATUS_EXCEPTION_NONE]);
}
};
@@ -2504,7 +2510,7 @@ static void ipa3_wan_rx_handle_splt_pyld(struct sk_buff *skb,
if (likely(skb2)) {
IPADBG_LOW(
"removing Status element from skb and sending to WAN client");
- skb_pull(skb2, IPA_PKT_STATUS_SIZE);
+ skb_pull(skb2, ipahal_pkt_status_get_size());
skb2->truesize = skb2->len +
sizeof(struct sk_buff);
sys->ep->client_notify(sys->ep->priv,
@@ -2530,7 +2536,9 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
struct ipa3_sys_context *sys)
{
int rc = 0;
- struct ipa3_hw_pkt_status *status;
+ struct ipahal_pkt_status status;
+ unsigned char *skb_data;
+ u32 pkt_status_sz;
struct sk_buff *skb2;
u16 pkt_len_with_pad;
u32 qmap_hdr;
@@ -2553,63 +2561,69 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
if (sys->len_rem)
ipa3_wan_rx_handle_splt_pyld(skb, sys);
+ pkt_status_sz = ipahal_pkt_status_get_size();
while (skb->len) {
IPADBG_LOW("LEN_REM %d\n", skb->len);
- if (skb->len < IPA_PKT_STATUS_SIZE) {
+ if (skb->len < pkt_status_sz) {
IPAERR("status straddles buffer\n");
WARN_ON(1);
goto bail;
}
- status = (struct ipa3_hw_pkt_status *)skb->data;
+ ipahal_pkt_status_parse(skb->data, &status);
+ skb_data = skb->data;
IPADBG_LOW("STATUS opcode=%d src=%d dst=%d len=%d\n",
- status->status_opcode, status->endp_src_idx,
- status->endp_dest_idx, status->pkt_len);
+ status.status_opcode, status.endp_src_idx,
+ status.endp_dest_idx, status.pkt_len);
if (sys->status_stat) {
sys->status_stat->status[sys->status_stat->curr] =
- *status;
+ status;
sys->status_stat->curr++;
if (sys->status_stat->curr == IPA_MAX_STATUS_STAT_NUM)
sys->status_stat->curr = 0;
}
- if ((status->status_opcode &
- (IPA_HW_STATUS_OPCODE_DROPPED_PACKET |
- IPA_HW_STATUS_OPCODE_PACKET |
- IPA_HW_STATUS_OPCODE_PACKET_2ND_PASS)) == 0) {
- IPAERR("unsupported opcode\n");
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ if ((status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_DROPPED_PACKET) &&
+ (status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_PACKET) &&
+ (status.status_opcode !=
+ IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS)) {
+ IPAERR("unsupported opcode(%d)\n",
+ status.status_opcode);
+ skb_pull(skb, pkt_status_sz);
continue;
}
+
IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_pkts);
- if (status->endp_dest_idx >= ipa3_ctx->ipa_num_pipes ||
- status->endp_src_idx >= ipa3_ctx->ipa_num_pipes ||
- status->pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
+ if (status.endp_dest_idx >= ipa3_ctx->ipa_num_pipes ||
+ status.endp_src_idx >= ipa3_ctx->ipa_num_pipes ||
+ status.pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
IPAERR("status fields invalid\n");
WARN_ON(1);
goto bail;
}
- if (status->pkt_len == 0) {
+ if (status.pkt_len == 0) {
IPADBG_LOW("Skip aggr close status\n");
- skb_pull(skb, IPA_PKT_STATUS_SIZE);
+ skb_pull(skb, pkt_status_sz);
IPA_STATS_DEC_CNT(ipa3_ctx->stats.rx_pkts);
IPA_STATS_INC_CNT(ipa3_ctx->stats.wan_aggr_close);
continue;
}
ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS);
- if (status->endp_dest_idx != ep_idx) {
+ if (status.endp_dest_idx != ep_idx) {
IPAERR("expected endp_dest_idx %d received %d\n",
- ep_idx, status->endp_dest_idx);
+ ep_idx, status.endp_dest_idx);
WARN_ON(1);
goto bail;
}
/* RX data */
- if (skb->len == IPA_PKT_STATUS_SIZE) {
+ if (skb->len == pkt_status_sz) {
IPAERR("Ins header in next buffer\n");
WARN_ON(1);
goto bail;
}
- qmap_hdr = *(u32 *)(status+1);
+ qmap_hdr = *(u32 *)(skb_data + pkt_status_sz);
/*
* Take the pkt_len_with_pad from the last 2 bytes of the QMAP
* header
@@ -2619,13 +2633,12 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
pkt_len_with_pad = ntohs((qmap_hdr>>16) & 0xffff);
IPADBG_LOW("pkt_len with pad %d\n", pkt_len_with_pad);
/*get the CHECKSUM_PROCESS bit*/
- checksum_trailer_exists = status->status_mask &
- IPA_HW_PKT_STATUS_MASK_CKSUM_PROCESS;
+ checksum_trailer_exists = IPAHAL_PKT_STATUS_MASK_FLAG_VAL(
+ IPAHAL_PKT_STATUS_MASK_CKSUM_PROCESS_SHFT, &status);
IPADBG_LOW("checksum_trailer_exists %d\n",
checksum_trailer_exists);
- frame_len = IPA_PKT_STATUS_SIZE +
- IPA_QMAP_HEADER_LENGTH +
+ frame_len = pkt_status_sz + IPA_QMAP_HEADER_LENGTH +
pkt_len_with_pad;
if (checksum_trailer_exists)
frame_len += IPA_DL_CHECKSUM_LENGTH;
@@ -2646,10 +2659,10 @@ static int ipa3_wan_rx_pyld_hdlr(struct sk_buff *skb,
} else {
skb_trim(skb2, frame_len);
IPADBG_LOW("rx avail for %d\n",
- status->endp_dest_idx);
+ status.endp_dest_idx);
IPADBG_LOW(
"removing Status element from skb and sending to WAN client");
- skb_pull(skb2, IPA_PKT_STATUS_SIZE);
+ skb_pull(skb2, pkt_status_sz);
skb2->truesize = skb2->len +
sizeof(struct sk_buff) +
(ALIGN(frame_len, 32) *
@@ -2687,14 +2700,14 @@ static void ipa3_free_skb_rx(struct sk_buff *skb)
void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data)
{
struct sk_buff *rx_skb = (struct sk_buff *)data;
- struct ipa3_hw_pkt_status *status;
+ struct ipahal_pkt_status status;
struct ipa3_ep_context *ep;
unsigned int src_pipe;
u32 metadata;
- status = (struct ipa3_hw_pkt_status *)rx_skb->data;
- src_pipe = status->endp_src_idx;
- metadata = status->metadata;
+ ipahal_pkt_status_parse(rx_skb->data, &status);
+ src_pipe = status.endp_src_idx;
+ metadata = status.metadata;
ep = &ipa3_ctx->ep[src_pipe];
if (unlikely(src_pipe >= ipa3_ctx->ipa_num_pipes ||
!ep->valid ||
@@ -2704,11 +2717,11 @@ void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data)
dev_kfree_skb_any(rx_skb);
return;
}
- if (!status->exception)
- skb_pull(rx_skb, IPA_PKT_STATUS_SIZE +
+ if (status.exception == IPAHAL_PKT_STATUS_EXCEPTION_NONE)
+ skb_pull(rx_skb, ipahal_pkt_status_get_size() +
IPA_LAN_RX_HEADER_LENGTH);
else
- skb_pull(rx_skb, IPA_PKT_STATUS_SIZE);
+ skb_pull(rx_skb, ipahal_pkt_status_get_size());
/* Metadata Info
------------------------------------------
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
index a01fced6d12a..1b732efe2b2c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_defs.h
@@ -152,84 +152,4 @@ struct ipa3_a5_mux_hdr {
u32 metadata;
};
-/*! @brief Struct for the IPAv3.0 UL packet status header */
-struct ipa3_hw_pkt_status {
- u64 status_opcode:8;
- u64 exception:8;
- u64 status_mask:16;
- u64 pkt_len:16;
- u64 endp_src_idx:5;
- u64 reserved_1:3;
- u64 endp_dest_idx:5;
- u64 reserved_2:3;
- u64 metadata:32;
- u64 filt_local:1;
- u64 filt_hash:1;
- u64 filt_global:1;
- u64 ret_hdr:1;
- u64 filt_rule_id:10;
- u64 route_local:1;
- u64 route_hash:1;
- u64 ucp:1;
- u64 route_tbl_idx:5;
- u64 route_rule_id:10;
- u64 nat_hit:1;
- u64 nat_tbl_idx:13;
- u64 nat_type:2;
- u64 tag:48;
- u64 seq_num:8;
- u64 time_day_ctr:24;
- u64 hdr_local:1;
- u64 hdr_offset:10;
- u64 frag_hit:1;
- u64 frag_rule:4;
- u64 reserved_4:16;
-};
-
-#define IPA_PKT_STATUS_SIZE 32
-
-/*! @brief Status header opcodes */
-enum ipa3_hw_status_opcode {
- IPA_HW_STATUS_OPCODE_PACKET = 0x1,
- IPA_HW_STATUS_OPCODE_NEW_FRAG_RULE = 0x2,
- IPA_HW_STATUS_OPCODE_DROPPED_PACKET = 0x4,
- IPA_HW_STATUS_OPCODE_SUSPENDED_PACKET = 0x8,
- IPA_HW_STATUS_OPCODE_LOG = 0x10,
- IPA_HW_STATUS_OPCODE_DCMP = 0x20,
- IPA_HW_STATUS_OPCODE_PACKET_2ND_PASS = 0x40,
-
-};
-
-/*! @brief Possible Masks received in status */
-enum ipa3_hw_pkt_status_mask {
- IPA_HW_PKT_STATUS_MASK_FRAG_PROCESS = 0x1,
- IPA_HW_PKT_STATUS_MASK_FILT_PROCESS = 0x2,
- IPA_HW_PKT_STATUS_MASK_NAT_PROCESS = 0x4,
- IPA_HW_PKT_STATUS_MASK_ROUTE_PROCESS = 0x8,
- IPA_HW_PKT_STATUS_MASK_TAG_VALID = 0x10,
- IPA_HW_PKT_STATUS_MASK_FRAGMENT = 0x20,
- IPA_HW_PKT_STATUS_MASK_FIRST_FRAGMENT = 0x40,
- IPA_HW_PKT_STATUS_MASK_V4 = 0x80,
- IPA_HW_PKT_STATUS_MASK_CKSUM_PROCESS = 0x100,
- IPA_HW_PKT_STATUS_MASK_AGGR_PROCESS = 0x200,
- IPA_HW_PKT_STATUS_MASK_DEST_EOT = 0x400,
- IPA_HW_PKT_STATUS_MASK_DEAGGR_PROCESS = 0x800,
- IPA_HW_PKT_STATUS_MASK_DEAGG_FIRST = 0x1000,
- IPA_HW_PKT_STATUS_MASK_SRC_EOT = 0x2000
-};
-
-/*! @brief Possible Exceptions received in status */
-enum ipa3_hw_pkt_status_exception {
- IPA_HW_PKT_STATUS_EXCEPTION_NONE = 0x0,
- IPA_HW_PKT_STATUS_EXCEPTION_DEAGGR = 0x1,
- IPA_HW_PKT_STATUS_EXCEPTION_IPTYPE = 0x4,
- IPA_HW_PKT_STATUS_EXCEPTION_PACKET_LENGTH = 0x8,
- IPA_HW_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD = 0x9,
- IPA_HW_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS = 0x10,
- IPA_HW_PKT_STATUS_EXCEPTION_SW_FILT = 0x20,
- IPA_HW_PKT_STATUS_EXCEPTION_NAT = 0x40,
- IPA_HW_PKT_STATUS_EXCEPTION_ACTUAL_MAX,
- IPA_HW_PKT_STATUS_EXCEPTION_MAX = 0xFF
-};
-
#endif /* _IPA_HW_DEFS_H */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index fe929df0eb57..2b702daefddb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -34,6 +34,7 @@
#include "ipa_qmi_service.h"
#include "../ipa_api.h"
#include "ipahal/ipahal_reg.h"
+#include "ipahal/ipahal.h"
#define DRV_NAME "ipa"
#define NAT_DEV_NAME "ipaNatTable"
@@ -90,25 +91,20 @@
#define WLAN3_CONS_RX_EP 17
#define WLAN4_CONS_RX_EP 18
-#define MAX_NUM_EXCP 8
-
#define IPA_STATS
#ifdef IPA_STATS
#define IPA_STATS_INC_CNT(val) (++val)
#define IPA_STATS_DEC_CNT(val) (--val)
-#define IPA_STATS_EXCP_CNT(flags, base) do { \
- int i; \
- for (i = 0; i < MAX_NUM_EXCP; i++) \
- if (flags & BIT(i)) \
- ++base[i]; \
- if (flags == 0) \
- ++base[MAX_NUM_EXCP - 1]; \
- } while (0)
+#define IPA_STATS_EXCP_CNT(__excp, __base) do { \
+ if (__excp < 0 || __excp >= IPAHAL_PKT_STATUS_EXCEPTION_MAX) \
+ break; \
+ ++__base[__excp]; \
+ } while (0)
#else
#define IPA_STATS_INC_CNT(x) do { } while (0)
#define IPA_STATS_DEC_CNT(x)
-#define IPA_STATS_EXCP_CNT(flags, base) do { } while (0)
+#define IPA_STATS_EXCP_CNT(__excp, __base) do { } while (0)
#endif
#define IPA_TOS_EQ BIT(0)
@@ -208,6 +204,10 @@
#define IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC (1000)
#define IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC (2000)
+#define IPA_GSI_CHANNEL_EMPTY_MAX_RETRY 15
+#define IPA_GSI_CHANNEL_EMPTY_SLEEP_MIN_USEC (1000)
+#define IPA_GSI_CHANNEL_EMPTY_SLEEP_MAX_USEC (2000)
+
#define IPA_SLEEP_CLK_RATE_KHZ (32)
#define IPA_ACTIVE_CLIENTS_PREP_EP(log_info, client) \
@@ -665,7 +665,7 @@ struct ipa_gsi_ep_mem_info {
};
struct ipa3_status_stats {
- struct ipa3_hw_pkt_status status[IPA_MAX_STATUS_STAT_NUM];
+ struct ipahal_pkt_status status[IPA_MAX_STATUS_STAT_NUM];
int curr;
};
@@ -1008,7 +1008,7 @@ struct ipa3_stats {
u32 tx_sw_pkts;
u32 tx_hw_pkts;
u32 rx_pkts;
- u32 rx_excp_pkts[MAX_NUM_EXCP];
+ u32 rx_excp_pkts[IPAHAL_PKT_STATUS_EXCEPTION_MAX];
u32 rx_repl_repost;
u32 tx_pkts_compl;
u32 rx_q_len;
@@ -1085,22 +1085,29 @@ struct ipa3_controller;
* enum ipa3_hw_features - Values that represent the features supported in IPA HW
* @IPA_HW_FEATURE_COMMON : Feature related to common operation of IPA HW
* @IPA_HW_FEATURE_MHI : Feature related to MHI operation in IPA HW
+ * @IPA_HW_FEATURE_POWER_COLLAPSE: Feature related to IPA Power collapse
* @IPA_HW_FEATURE_WDI : Feature related to WDI operation in IPA HW
+ * @IPA_HW_FEATURE_ZIP: Feature related to CMP/DCMP operation in IPA HW
*/
enum ipa3_hw_features {
- IPA_HW_FEATURE_COMMON = 0x0,
- IPA_HW_FEATURE_MHI = 0x1,
- IPA_HW_FEATURE_WDI = 0x3,
- IPA_HW_FEATURE_MAX = IPA_HW_NUM_FEATURES
+ IPA_HW_FEATURE_COMMON = 0x0,
+ IPA_HW_FEATURE_MHI = 0x1,
+ IPA_HW_FEATURE_POWER_COLLAPSE = 0x2,
+ IPA_HW_FEATURE_WDI = 0x3,
+ IPA_HW_FEATURE_ZIP = 0x4,
+ IPA_HW_FEATURE_MAX = IPA_HW_NUM_FEATURES
};
/**
* enum ipa3_hw_2_cpu_events - Values that represent HW event to be sent to CPU.
+ * @IPA_HW_2_CPU_EVENT_NO_OP : No event present
* @IPA_HW_2_CPU_EVENT_ERROR : Event specify a system error is detected by the
- * device
+ * device
* @IPA_HW_2_CPU_EVENT_LOG_INFO : Event providing logging specific information
*/
enum ipa3_hw_2_cpu_events {
+ IPA_HW_2_CPU_EVENT_NO_OP =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 0),
IPA_HW_2_CPU_EVENT_ERROR =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 1),
IPA_HW_2_CPU_EVENT_LOG_INFO =
@@ -1114,7 +1121,8 @@ enum ipa3_hw_2_cpu_events {
* @IPA_HW_DMA_ERROR : Unexpected DMA error
* @IPA_HW_FATAL_SYSTEM_ERROR : HW has crashed and requires reset.
* @IPA_HW_INVALID_OPCODE : Invalid opcode sent
- * @IPA_HW_ZIP_ENGINE_ERROR : ZIP engine error
+ * @IPA_HW_INVALID_PARAMS : Invalid params for the requested command
+ * @IPA_HW_GSI_CH_NOT_EMPTY_FAILURE : GSI channel emptiness validation failed
*/
enum ipa3_hw_errors {
IPA_HW_ERROR_NONE =
@@ -1127,12 +1135,14 @@ enum ipa3_hw_errors {
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 3),
IPA_HW_INVALID_OPCODE =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 4),
- IPA_HW_ZIP_ENGINE_ERROR =
+ IPA_HW_INVALID_PARAMS =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 5),
IPA_HW_CONS_DISABLE_CMD_GSI_STOP_FAILURE =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 6),
IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 7)
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 7),
+ IPA_HW_GSI_CH_NOT_EMPTY_FAILURE =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 8)
};
/**
@@ -1166,14 +1176,13 @@ struct IpaHwSharedMemCommonMapping_t {
u32 cmdParams;
u32 cmdParams_hi;
u8 responseOp;
- u8 reserved_09;
- u16 reserved_0B_0A;
+ u8 reserved_0D;
+ u16 reserved_0F_0E;
u32 responseParams;
u8 eventOp;
- u8 reserved_11;
- u16 reserved_13_12;
+ u8 reserved_15;
+ u16 reserved_17_16;
u32 eventParams;
- u32 reserved_1B_18;
u32 firstErrorAddress;
u8 hwState;
u8 warningCounter;
@@ -1359,7 +1368,6 @@ union IpaHwMhiDlUlSyncCmdData_t {
* @uc_sram_mmio: Pointer to uC mapped memory
* @pending_cmd: The last command sent waiting to be ACKed
* @uc_status: The last status provided by the uC
- * @uc_zip_error: uC has notified the APPS upon a ZIP engine error
* @uc_error_type: error type from uC error event
* @uc_error_timestamp: tag timer sampled after uC crashed
*/
@@ -1375,7 +1383,6 @@ struct ipa3_uc_ctx {
u32 uc_event_top_ofst;
u32 pending_cmd;
u32 uc_status;
- bool uc_zip_error;
u32 uc_error_type;
u32 uc_error_timestamp;
};
@@ -2311,8 +2318,8 @@ int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id);
int ipa3_tag_process(struct ipa3_desc *desc, int num_descs,
unsigned long timeout);
-int ipa3_q6_cleanup(void);
-int ipa3_q6_pipe_reset(void);
+void ipa3_q6_cleanup(void);
+void ipa3_validate_q6_gsi_channel_empty(void);
int ipa3_init_q6_smem(void);
int ipa3_sps_connect_safe(struct sps_pipe *h, struct sps_connect *connect,
@@ -2322,6 +2329,7 @@ int ipa3_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req);
int ipa3_uc_interface_init(void);
int ipa3_uc_reset_pipe(enum ipa_client_type ipa_client);
+int ipa3_uc_is_gsi_channel_empty(enum ipa_client_type ipa_client);
int ipa3_uc_state_check(void);
int ipa3_uc_loaded_check(void);
void ipa3_uc_load_notify(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
index 744fc4f293db..5f6722d3fbac 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -34,6 +34,8 @@
pr_debug(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
#define IPAWANERR(fmt, args...) \
pr_err(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+#define IPAWANINFO(fmt, args...) \
+ pr_info(DEV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
extern struct ipa3_qmi_context *ipa3_qmi_ctx;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
index b2b193d4c9e7..1e03e6497ad6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c
@@ -13,7 +13,7 @@
#include <linux/delay.h>
#define IPA_RAM_UC_SMEM_SIZE 128
-#define IPA_HW_INTERFACE_VERSION 0x0111
+#define IPA_HW_INTERFACE_VERSION 0x2000
#define IPA_PKT_FLUSH_TO_US 100
#define IPA_UC_POLL_SLEEP_USEC 100
#define IPA_UC_POLL_MAX_RETRY 10000
@@ -40,6 +40,7 @@
* IPA_CPU_2_HW_CMD_CLK_UNGATE : CPU instructs HW to goto Clock Ungated state.
* IPA_CPU_2_HW_CMD_MEMCPY : CPU instructs HW to do memcopy using QMB.
* IPA_CPU_2_HW_CMD_RESET_PIPE : Command to reset a pipe - SW WA for a HW bug.
+ * IPA_CPU_2_HW_CMD_GSI_CH_EMPTY : Command to check for GSI channel emptiness.
*/
enum ipa3_cpu_2_hw_commands {
IPA_CPU_2_HW_CMD_NO_OP =
@@ -62,20 +63,29 @@ enum ipa3_cpu_2_hw_commands {
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 8),
IPA_CPU_2_HW_CMD_REG_WRITE =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 9),
+ IPA_CPU_2_HW_CMD_GSI_CH_EMPTY =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 10),
};
/**
* enum ipa3_hw_2_cpu_responses - Values that represent common HW responses
- * to CPU commands.
+ * to CPU commands.
+ * @IPA_HW_2_CPU_RESPONSE_NO_OP : No operation response
* @IPA_HW_2_CPU_RESPONSE_INIT_COMPLETED : HW shall send this command once
- * boot sequence is completed and HW is ready to serve commands from CPU
+ * boot sequence is completed and HW is ready to serve commands from CPU
* @IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED: Response to CPU commands
+ * @IPA_HW_2_CPU_RESPONSE_DEBUG_GET_INFO : Response to
+ * IPA_CPU_2_HW_CMD_DEBUG_GET_INFO command
*/
enum ipa3_hw_2_cpu_responses {
+ IPA_HW_2_CPU_RESPONSE_NO_OP =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 0),
IPA_HW_2_CPU_RESPONSE_INIT_COMPLETED =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 1),
IPA_HW_2_CPU_RESPONSE_CMD_COMPLETED =
FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 2),
+ IPA_HW_2_CPU_RESPONSE_DEBUG_GET_INFO =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 3),
};
/**
@@ -153,6 +163,23 @@ union IpaHwUpdateFlagsCmdData_t {
};
/**
+ * union IpaHwChkChEmptyCmdData_t - Structure holding the parameters for
+ * IPA_CPU_2_HW_CMD_GSI_CH_EMPTY command. Parameters are sent as 32b
+ * immediate parameters.
+ * @ee_n : EE owner of the channel
+ * @vir_ch_id : GSI virtual channel ID of the channel to checked of emptiness
+ * @reserved_02_04 : Reserved
+ */
+union IpaHwChkChEmptyCmdData_t {
+ struct IpaHwChkChEmptyCmdParams_t {
+ u8 ee_n;
+ u8 vir_ch_id;
+ u16 reserved_02_04;
+ } __packed params;
+ u32 raw32b;
+} __packed;
+
+/**
* When resource group 10 limitation mitigation is enabled, uC send
* cmd should be able to run in interrupt context, so using spin lock
* instead of mutex.
@@ -186,14 +213,26 @@ const char *ipa_hw_error_str(enum ipa3_hw_errors err_type)
case IPA_HW_INVALID_DOORBELL_ERROR:
str = "IPA_HW_INVALID_DOORBELL_ERROR";
break;
+ case IPA_HW_DMA_ERROR:
+ str = "IPA_HW_DMA_ERROR";
+ break;
case IPA_HW_FATAL_SYSTEM_ERROR:
str = "IPA_HW_FATAL_SYSTEM_ERROR";
break;
case IPA_HW_INVALID_OPCODE:
str = "IPA_HW_INVALID_OPCODE";
break;
- case IPA_HW_ZIP_ENGINE_ERROR:
- str = "IPA_HW_ZIP_ENGINE_ERROR";
+ case IPA_HW_INVALID_PARAMS:
+ str = "IPA_HW_INVALID_PARAMS";
+ break;
+ case IPA_HW_CONS_DISABLE_CMD_GSI_STOP_FAILURE:
+ str = "IPA_HW_CONS_DISABLE_CMD_GSI_STOP_FAILURE";
+ break;
+ case IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE:
+ str = "IPA_HW_PROD_DISABLE_CMD_GSI_STOP_FAILURE";
+ break;
+ case IPA_HW_GSI_CH_NOT_EMPTY_FAILURE:
+ str = "IPA_HW_GSI_CH_NOT_EMPTY_FAILURE";
break;
default:
str = "INVALID ipa_hw_errors type";
@@ -324,10 +363,6 @@ static void ipa3_uc_event_handler(enum ipa_irq_type interrupt,
ipa_hw_error_str(evt.params.errorType));
ipa3_ctx->uc_ctx.uc_failed = true;
ipa3_ctx->uc_ctx.uc_error_type = evt.params.errorType;
- if (evt.params.errorType == IPA_HW_ZIP_ENGINE_ERROR) {
- IPAERR("IPA has encountered a ZIP engine error\n");
- ipa3_ctx->uc_ctx.uc_zip_error = true;
- }
ipa3_ctx->uc_ctx.uc_error_timestamp =
ipahal_read_reg(IPA_TAG_TIMER);
BUG();
@@ -466,7 +501,7 @@ static int ipa3_uc_send_cmd_64b_param(u32 cmd_lo, u32 cmd_hi, u32 opcode,
unsigned long flags;
int retries = 0;
-send_cmd:
+send_cmd_lock:
IPA3_UC_LOCK(flags);
if (ipa3_uc_state_check()) {
@@ -474,7 +509,7 @@ send_cmd:
IPA3_UC_UNLOCK(flags);
return -EBADF;
}
-
+send_cmd:
if (ipa3_ctx->apply_rg10_wa) {
if (!polling_mode)
IPADBG("Overriding mode to polling mode\n");
@@ -563,6 +598,25 @@ send_cmd:
/* sleep for short period to flush IPA */
usleep_range(IPA_GSI_CHANNEL_STOP_SLEEP_MIN_USEC,
IPA_GSI_CHANNEL_STOP_SLEEP_MAX_USEC);
+ goto send_cmd_lock;
+ }
+
+ if (ipa3_ctx->uc_ctx.uc_status ==
+ IPA_HW_GSI_CH_NOT_EMPTY_FAILURE) {
+ retries++;
+ if (retries >= IPA_GSI_CHANNEL_EMPTY_MAX_RETRY) {
+ IPAERR("Failed after %d tries\n", retries);
+ IPA3_UC_UNLOCK(flags);
+ return -EFAULT;
+ }
+ if (ipa3_ctx->apply_rg10_wa)
+ udelay(
+ IPA_GSI_CHANNEL_EMPTY_SLEEP_MAX_USEC / 2 +
+ IPA_GSI_CHANNEL_EMPTY_SLEEP_MIN_USEC / 2);
+ else
+ usleep_range(
+ IPA_GSI_CHANNEL_EMPTY_SLEEP_MIN_USEC,
+ IPA_GSI_CHANNEL_EMPTY_SLEEP_MAX_USEC);
goto send_cmd;
}
@@ -784,6 +838,37 @@ int ipa3_uc_reset_pipe(enum ipa_client_type ipa_client)
return ret;
}
+int ipa3_uc_is_gsi_channel_empty(enum ipa_client_type ipa_client)
+{
+ struct ipa_gsi_ep_config *gsi_ep_info;
+ union IpaHwChkChEmptyCmdData_t cmd;
+ int ret;
+
+ gsi_ep_info = ipa3_get_gsi_ep_info(ipa3_get_ep_mapping(ipa_client));
+ if (!gsi_ep_info) {
+ IPAERR("Invalid IPA ep index\n");
+ return 0;
+ }
+
+ if (ipa3_uc_state_check()) {
+ IPADBG("uC cannot be used to validate ch emptiness clnt=%d\n"
+ , ipa_client);
+ return 0;
+ }
+
+ cmd.params.ee_n = gsi_ep_info->ee;
+ cmd.params.vir_ch_id = gsi_ep_info->ipa_gsi_chan_num;
+
+ IPADBG("uC emptiness check for IPA GSI Channel %d\n",
+ gsi_ep_info->ipa_gsi_chan_num);
+
+ ret = ipa3_uc_send_cmd(cmd.raw32b, IPA_CPU_2_HW_CMD_GSI_CH_EMPTY, 0,
+ false, 10*HZ);
+
+ return ret;
+}
+
+
/**
* ipa3_uc_notify_clk_state() - notify to uC of clock enable / disable
* @enabled: true if clock are enabled
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 0d8b3c28c113..2677c9e0c83c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -14,8 +14,6 @@
#include "ipahal_i.h"
#include "ipahal_reg_i.h"
-static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type);
-
struct ipahal_context *ipahal_ctx;
static const char *ipahal_imm_cmd_name_to_str[IPA_IMM_CMD_MAX] = {
@@ -34,6 +32,18 @@ static const char *ipahal_imm_cmd_name_to_str[IPA_IMM_CMD_MAX] = {
__stringify(IPA_IMM_CMD_DMA_TASK_32B_ADDR),
};
+static const char *ipahal_pkt_status_exception_to_str
+ [IPAHAL_PKT_STATUS_EXCEPTION_MAX] = {
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_NONE),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_NAT),
+};
+
#define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
(kzalloc((__size), ((__is_atomic_ctx)?GFP_ATOMIC:GFP_KERNEL)))
@@ -538,14 +548,14 @@ static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
*/
if (!ipahal_imm_cmd_objs[i+1][j].opcode) {
IPAHAL_ERR(
- "imm_cmd=%s with zero opcode\n",
- ipahal_imm_cmd_name_str(j));
+ "imm_cmd=%s with zero opcode ipa_ver=%d\n",
+ ipahal_imm_cmd_name_str(j), i+1);
WARN_ON(1);
}
if (!ipahal_imm_cmd_objs[i+1][j].construct) {
IPAHAL_ERR(
- "imm_cmd=%s with NULL construct fun\n",
- ipahal_imm_cmd_name_str(j));
+ "imm_cmd=%s with NULL construct func ipa_ver=%d\n",
+ ipahal_imm_cmd_name_str(j), i+1);
WARN_ON(1);
}
}
@@ -709,6 +719,270 @@ struct ipahal_imm_cmd_pyld *ipahal_construct_nop_imm_cmd(
return cmd_pyld;
}
+
+/* IPA Packet Status Logic */
+
+#define IPA_PKT_STATUS_SET_MSK(__hw_bit_msk, __shft) \
+ (status->status_mask |= \
+ ((hw_status->status_mask & (__hw_bit_msk) ? 1 : 0) << (__shft)))
+
+static void ipa_pkt_status_parse(
+ const void *unparsed_status, struct ipahal_pkt_status *status)
+{
+ enum ipahal_pkt_status_opcode opcode = 0;
+ enum ipahal_pkt_status_exception exception_type = 0;
+
+ struct ipa_pkt_status_hw *hw_status =
+ (struct ipa_pkt_status_hw *)unparsed_status;
+
+ status->pkt_len = hw_status->pkt_len;
+ status->endp_src_idx = hw_status->endp_src_idx;
+ status->endp_dest_idx = hw_status->endp_dest_idx;
+ status->metadata = hw_status->metadata;
+ status->flt_local = hw_status->flt_local;
+ status->flt_hash = hw_status->flt_hash;
+ status->flt_global = hw_status->flt_hash;
+ status->flt_ret_hdr = hw_status->flt_ret_hdr;
+ status->flt_miss = ~(hw_status->flt_rule_id) ? false : true;
+ status->flt_rule_id = hw_status->flt_rule_id;
+ status->rt_local = hw_status->rt_local;
+ status->rt_hash = hw_status->rt_hash;
+ status->ucp = hw_status->ucp;
+ status->rt_tbl_idx = hw_status->rt_tbl_idx;
+ status->rt_miss = ~(hw_status->rt_rule_id) ? false : true;
+ status->rt_rule_id = hw_status->rt_rule_id;
+ status->nat_hit = hw_status->nat_hit;
+ status->nat_entry_idx = hw_status->nat_entry_idx;
+ status->tag_info = hw_status->tag_info;
+ status->seq_num = hw_status->seq_num;
+ status->time_of_day_ctr = hw_status->time_of_day_ctr;
+ status->hdr_local = hw_status->hdr_local;
+ status->hdr_offset = hw_status->hdr_offset;
+ status->frag_hit = hw_status->frag_hit;
+ status->frag_rule = hw_status->frag_rule;
+
+ switch (hw_status->status_opcode) {
+ case 0x1:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_PACKET;
+ break;
+ case 0x2:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE;
+ break;
+ case 0x4:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_DROPPED_PACKET;
+ break;
+ case 0x8:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_SUSPENDED_PACKET;
+ break;
+ case 0x10:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_LOG;
+ break;
+ case 0x20:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_DCMP;
+ break;
+ case 0x40:
+ opcode = IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS;
+ break;
+ default:
+ IPAHAL_ERR("unsupported Status Opcode 0x%x\n",
+ hw_status->status_opcode);
+ WARN_ON(1);
+ };
+ status->status_opcode = opcode;
+
+ switch (hw_status->nat_type) {
+ case 0:
+ status->nat_type = IPAHAL_PKT_STATUS_NAT_NONE;
+ break;
+ case 1:
+ status->nat_type = IPAHAL_PKT_STATUS_NAT_SRC;
+ break;
+ case 2:
+ status->nat_type = IPAHAL_PKT_STATUS_NAT_DST;
+ break;
+ default:
+ IPAHAL_ERR("unsupported Status NAT type 0x%x\n",
+ hw_status->nat_type);
+ WARN_ON(1);
+ };
+
+ switch (hw_status->exception) {
+ case 0:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NONE;
+ break;
+ case 1:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR;
+ break;
+ case 4:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE;
+ break;
+ case 8:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH;
+ break;
+ case 16:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS;
+ break;
+ case 32:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT;
+ break;
+ case 64:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
+ break;
+ default:
+ IPAHAL_ERR("unsupported Status Exception type 0x%x\n",
+ hw_status->exception);
+ WARN_ON(1);
+ };
+ status->exception = exception_type;
+
+ IPA_PKT_STATUS_SET_MSK(0x1, IPAHAL_PKT_STATUS_MASK_FRAG_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x2, IPAHAL_PKT_STATUS_MASK_FILT_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x4, IPAHAL_PKT_STATUS_MASK_NAT_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x8, IPAHAL_PKT_STATUS_MASK_ROUTE_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x10, IPAHAL_PKT_STATUS_MASK_TAG_VALID_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x20, IPAHAL_PKT_STATUS_MASK_FRAGMENT_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x40,
+ IPAHAL_PKT_STATUS_MASK_FIRST_FRAGMENT_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x80, IPAHAL_PKT_STATUS_MASK_V4_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x100,
+ IPAHAL_PKT_STATUS_MASK_CKSUM_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x200, IPAHAL_PKT_STATUS_MASK_AGGR_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x400, IPAHAL_PKT_STATUS_MASK_DEST_EOT_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x800,
+ IPAHAL_PKT_STATUS_MASK_DEAGGR_PROCESS_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x1000, IPAHAL_PKT_STATUS_MASK_DEAGG_FIRST_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x2000, IPAHAL_PKT_STATUS_MASK_SRC_EOT_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x4000, IPAHAL_PKT_STATUS_MASK_PREV_EOT_SHFT);
+ IPA_PKT_STATUS_SET_MSK(0x8000, IPAHAL_PKT_STATUS_MASK_BYTE_LIMIT_SHFT);
+ status->status_mask &= 0xFFFF;
+}
+
+/*
+ * struct ipahal_pkt_status_obj - Pakcet Status H/W information for
+ * specific IPA version
+ * @size: H/W size of the status packet
+ * @parse: CB that parses the H/W packet status into the abstracted structure
+ */
+struct ipahal_pkt_status_obj {
+ u32 size;
+ void (*parse)(const void *unparsed_status,
+ struct ipahal_pkt_status *status);
+};
+
+/*
+ * This table contains the info regard packet status for IPAv3 and later
+ * Information like: size of packet status and parsing function
+ * All the information on the pkt Status on IPAv3 are statically defined below.
+ * If information is missing regard some IPA version, the init function
+ * will fill it with the information from the previous IPA version.
+ * Information is considered missing if all of the fields are 0
+ */
+static struct ipahal_pkt_status_obj ipahal_pkt_status_objs[IPA_HW_MAX] = {
+ /* IPAv3 */
+ [IPA_HW_v3_0] = {
+ IPA3_0_PKT_STATUS_SIZE,
+ ipa_pkt_status_parse,
+ },
+};
+
+/*
+ * ipahal_pkt_status_init() - Build the packet status information array
+ * for the different IPA versions
+ * See ipahal_pkt_status_objs[] comments
+ */
+static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type)
+{
+ int i;
+ struct ipahal_pkt_status_obj zero_obj;
+
+ IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
+
+ /*
+ * Since structure alignment is implementation dependent,
+ * add test to avoid different and incompatible data layouts.
+ *
+ * In case new H/W has different size or structure of status packet,
+ * add a compile time validty check for it like below (as well as
+ * the new defines and/or the new strucutre in the internal header).
+ */
+ BUILD_BUG_ON(sizeof(struct ipa_pkt_status_hw) !=
+ IPA3_0_PKT_STATUS_SIZE);
+
+ memset(&zero_obj, 0, sizeof(zero_obj));
+ for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
+ if (!memcmp(&ipahal_pkt_status_objs[i+1], &zero_obj,
+ sizeof(struct ipahal_pkt_status_obj))) {
+ memcpy(&ipahal_pkt_status_objs[i+1],
+ &ipahal_pkt_status_objs[i],
+ sizeof(struct ipahal_pkt_status_obj));
+ } else {
+ /*
+ * explicitly overridden Packet Status info
+ * Check validity
+ */
+ if (!ipahal_pkt_status_objs[i+1].size) {
+ IPAHAL_ERR(
+ "Packet Status with zero size ipa_ver=%d\n",
+ i+1);
+ WARN_ON(1);
+ }
+ if (!ipahal_pkt_status_objs[i+1].parse) {
+ IPAHAL_ERR(
+ "Packet Status without Parse func ipa_ver=%d\n",
+ i+1);
+ WARN_ON(1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * ipahal_pkt_status_get_size() - Get H/W size of packet status
+ */
+u32 ipahal_pkt_status_get_size(void)
+{
+ return ipahal_pkt_status_objs[ipahal_ctx->hw_type].size;
+}
+
+/*
+ * ipahal_pkt_status_parse() - Parse Packet Status payload to abstracted form
+ * @unparsed_status: Pointer to H/W format of the packet status as read from H/W
+ * @status: Pointer to pre-allocated buffer where the parsed info will be stored
+ */
+void ipahal_pkt_status_parse(const void *unparsed_status,
+ struct ipahal_pkt_status *status)
+{
+ if (!unparsed_status || !status) {
+ IPAHAL_ERR("Input Error: unparsed_status=%p status=%p\n",
+ unparsed_status, status);
+ return;
+ }
+
+ IPAHAL_DBG("Parse Status Packet\n");
+ memset(status, 0, sizeof(*status));
+ ipahal_pkt_status_objs[ipahal_ctx->hw_type].parse(unparsed_status,
+ status);
+}
+
+/*
+ * ipahal_pkt_status_exception_str() - returns string represents exception type
+ * @exception: [in] The exception type
+ */
+const char *ipahal_pkt_status_exception_str(
+ enum ipahal_pkt_status_exception exception)
+{
+ if (exception < 0 || exception >= IPAHAL_PKT_STATUS_EXCEPTION_MAX) {
+ IPAHAL_ERR(
+ "requested string of invalid pkt_status exception=%d\n",
+ exception);
+ return "Invalid PKT_STATUS_EXCEPTION";
+ }
+
+ return ipahal_pkt_status_exception_to_str[exception];
+}
+
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
{
int result;
@@ -750,6 +1024,12 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
goto bail_free_ctx;
}
+ if (ipahal_pkt_status_init(ipa_hw_type)) {
+ IPAHAL_ERR("failed to init ipahal pkt status\n");
+ result = -EFAULT;
+ goto bail_free_ctx;
+ }
+
return 0;
bail_free_ctx:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 5bdbcaf451a0..8591ff046624 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -389,6 +389,214 @@ static inline void ipahal_destroy_imm_cmd(struct ipahal_imm_cmd_pyld *pyld)
kfree(pyld);
}
+
+/* IPA Status packet Structures and Function APIs */
+
+/*
+ * enum ipahal_pkt_status_opcode - Packet Status Opcode
+ * @IPAHAL_STATUS_OPCODE_PACKET_2ND_PASS: Packet Status generated as part of
+ * IPA second processing pass for a packet (i.e. IPA XLAT processing for
+ * the translated packet).
+ */
+enum ipahal_pkt_status_opcode {
+ IPAHAL_PKT_STATUS_OPCODE_PACKET = 0,
+ IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE,
+ IPAHAL_PKT_STATUS_OPCODE_DROPPED_PACKET,
+ IPAHAL_PKT_STATUS_OPCODE_SUSPENDED_PACKET,
+ IPAHAL_PKT_STATUS_OPCODE_LOG,
+ IPAHAL_PKT_STATUS_OPCODE_DCMP,
+ IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS,
+};
+
+/*
+ * enum ipahal_pkt_status_exception - Packet Status exception type
+ * @IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH: formerly IHL exception.
+ *
+ * Note: IPTYPE, PACKET_LENGTH and PACKET_THRESHOLD exceptions means that
+ * partial / no IP processing took place and corresponding Status Mask
+ * fields should be ignored. Flt and rt info is not valid.
+ *
+ * NOTE:: Any change to this enum, need to change to
+ * ipahal_pkt_status_exception_to_str array as well.
+ */
+enum ipahal_pkt_status_exception {
+ IPAHAL_PKT_STATUS_EXCEPTION_NONE = 0,
+ IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR,
+ IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE,
+ IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH,
+ IPAHAL_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD,
+ IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS,
+ IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT,
+ IPAHAL_PKT_STATUS_EXCEPTION_NAT,
+ IPAHAL_PKT_STATUS_EXCEPTION_MAX,
+};
+
+/*
+ * enum ipahal_pkt_status_mask - Packet Status bitmask shift values of
+ * the contained flags. This bitmask indicates flags on the properties of
+ * the packet as well as IPA processing it may had.
+ * @FRAG_PROCESS: Frag block processing flag: Was pkt processed by frag block?
+ * Also means the frag info is valid unless exception or first frag
+ * @FILT_PROCESS: Flt block processing flag: Was pkt processed by flt block?
+ * Also means that flt info is valid.
+ * @NAT_PROCESS: NAT block processing flag: Was pkt processed by NAT block?
+ * Also means that NAT info is valid, unless exception.
+ * @ROUTE_PROCESS: Rt block processing flag: Was pkt processed by rt block?
+ * Also means that rt info is valid, unless exception.
+ * @TAG_VALID: Flag specifying if TAG and TAG info valid?
+ * @FRAGMENT: Flag specifying if pkt is IP fragment.
+ * @FIRST_FRAGMENT: Flag specifying if pkt is first fragment. In this case, frag
+ * info is invalid
+ * @V4: Flag specifying pkt is IPv4 or IPv6
+ * @CKSUM_PROCESS: CSUM block processing flag: Was pkt processed by csum block?
+ * If so, csum trailer exists
+ * @AGGR_PROCESS: Aggr block processing flag: Was pkt processed by aggr block?
+ * @DEST_EOT: Flag specifying if EOT was asserted for the pkt on dest endp
+ * @DEAGGR_PROCESS: Deaggr block processing flag: Was pkt processed by deaggr
+ * block?
+ * @DEAGG_FIRST: Flag specifying if this is the first pkt in deaggr frame
+ * @SRC_EOT: Flag specifying if EOT asserted by src endp when sending the buffer
+ * @PREV_EOT: Flag specifying if EOT was sent just before the pkt as part of
+ * aggr hard-byte-limit
+ * @BYTE_LIMIT: Flag specifying if pkt is over a configured byte limit.
+ */
+enum ipahal_pkt_status_mask {
+ IPAHAL_PKT_STATUS_MASK_FRAG_PROCESS_SHFT = 0,
+ IPAHAL_PKT_STATUS_MASK_FILT_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_NAT_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_ROUTE_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_TAG_VALID_SHFT,
+ IPAHAL_PKT_STATUS_MASK_FRAGMENT_SHFT,
+ IPAHAL_PKT_STATUS_MASK_FIRST_FRAGMENT_SHFT,
+ IPAHAL_PKT_STATUS_MASK_V4_SHFT,
+ IPAHAL_PKT_STATUS_MASK_CKSUM_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_AGGR_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_DEST_EOT_SHFT,
+ IPAHAL_PKT_STATUS_MASK_DEAGGR_PROCESS_SHFT,
+ IPAHAL_PKT_STATUS_MASK_DEAGG_FIRST_SHFT,
+ IPAHAL_PKT_STATUS_MASK_SRC_EOT_SHFT,
+ IPAHAL_PKT_STATUS_MASK_PREV_EOT_SHFT,
+ IPAHAL_PKT_STATUS_MASK_BYTE_LIMIT_SHFT,
+};
+
+/*
+ * Returns boolean value representing a property of the a packet.
+ * @__flag_shft: The shift value of the flag of the status bitmask of
+ * @__status: Pointer to abstracrted status structure
+ * the needed property. See enum ipahal_pkt_status_mask
+ */
+#define IPAHAL_PKT_STATUS_MASK_FLAG_VAL(__flag_shft, __status) \
+ (((__status)->status_mask) & ((u32)0x1<<(__flag_shft)) ? true : false)
+
+/*
+ * enum ipahal_pkt_status_nat_type - Type of NAT
+ */
+enum ipahal_pkt_status_nat_type {
+ IPAHAL_PKT_STATUS_NAT_NONE,
+ IPAHAL_PKT_STATUS_NAT_SRC,
+ IPAHAL_PKT_STATUS_NAT_DST,
+};
+
+/*
+ * struct ipahal_pkt_status - IPA status packet abstracted payload.
+ * This structure describes the status packet fields for the
+ * following statuses: IPA_STATUS_PACKET, IPA_STATUS_DROPPED_PACKET,
+ * IPA_STATUS_SUSPENDED_PACKET.
+ * Other statuses types has different status packet structure.
+ * @status_opcode: The Type of the status (Opcode).
+ * @exception: The first exception that took place.
+ * In case of exception, src endp and pkt len are always valid.
+ * @status_mask: Bit mask for flags on several properties on the packet
+ * and processing it may passed at IPA. See enum ipahal_pkt_status_mask
+ * @pkt_len: Pkt pyld len including hdr and retained hdr if used. Does
+ * not include padding or checksum trailer len.
+ * @endp_src_idx: Source end point index.
+ * @endp_dest_idx: Destination end point index.
+ * Not valid in case of exception
+ * @metadata: meta data value used by packet
+ * @flt_local: Filter table location flag: Does matching flt rule belongs to
+ * flt tbl that resides in lcl memory? (if not, then system mem)
+ * @flt_hash: Filter hash hit flag: Does matching flt rule was in hash tbl?
+ * @flt_global: Global filter rule flag: Does matching flt rule belongs to
+ * the global flt tbl? (if not, then the per endp tables)
+ * @flt_ret_hdr: Retain header in filter rule flag: Does matching flt rule
+ * specifies to retain header?
+ * @flt_miss: Filtering miss flag: Was their a filtering rule miss?
+ * In case of miss, all flt info to be ignored
+ * @flt_rule_id: The ID of the matching filter rule (if no miss).
+ * This info can be combined with endp_src_idx to locate the exact rule.
+ * @rt_local: Route table location flag: Does matching rt rule belongs to
+ * rt tbl that resides in lcl memory? (if not, then system mem)
+ * @rt_hash: Route hash hit flag: Does matching rt rule was in hash tbl?
+ * @ucp: UC Processing flag
+ * @rt_tbl_idx: Index of rt tbl that contains the rule on which was a match
+ * @rt_miss: Routing miss flag: Was their a routing rule miss?
+ * @rt_rule_id: The ID of the matching rt rule. (if no miss). This info
+ * can be combined with rt_tbl_idx to locate the exact rule.
+ * @nat_hit: NAT hit flag: Was their NAT hit?
+ * @nat_entry_idx: Index of the NAT entry used of NAT processing
+ * @nat_type: Defines the type of the NAT operation:
+ * @tag_info: S/W defined value provided via immediate command
+ * @seq_num: Per source endp unique packet sequence number
+ * @time_of_day_ctr: running counter from IPA clock
+ * @hdr_local: Header table location flag: In header insertion, was the header
+ * taken from the table resides in local memory? (If no, then system mem)
+ * @hdr_offset: Offset of used header in the header table
+ * @frag_hit: Frag hit flag: Was their frag rule hit in H/W frag table?
+ * @frag_rule: Frag rule index in H/W frag table in case of frag hit
+ */
+struct ipahal_pkt_status {
+ enum ipahal_pkt_status_opcode status_opcode;
+ enum ipahal_pkt_status_exception exception;
+ u32 status_mask;
+ u32 pkt_len;
+ u8 endp_src_idx;
+ u8 endp_dest_idx;
+ u32 metadata;
+ bool flt_local;
+ bool flt_hash;
+ bool flt_global;
+ bool flt_ret_hdr;
+ bool flt_miss;
+ u16 flt_rule_id;
+ bool rt_local;
+ bool rt_hash;
+ bool ucp;
+ u8 rt_tbl_idx;
+ bool rt_miss;
+ u16 rt_rule_id;
+ bool nat_hit;
+ u16 nat_entry_idx;
+ enum ipahal_pkt_status_nat_type nat_type;
+ u64 tag_info;
+ u8 seq_num;
+ u32 time_of_day_ctr;
+ bool hdr_local;
+ u16 hdr_offset;
+ bool frag_hit;
+ u8 frag_rule;
+};
+
+/*
+ * ipahal_pkt_status_get_size() - Get H/W size of packet status
+ */
+u32 ipahal_pkt_status_get_size(void);
+
+/*
+ * ipahal_pkt_status_parse() - Parse Packet Status payload to abstracted form
+ * @unparsed_status: Pointer to H/W format of the packet status as read from H/W
+ * @status: Pointer to pre-allocated buffer where the parsed info will be stored
+ */
+void ipahal_pkt_status_parse(const void *unparsed_status,
+ struct ipahal_pkt_status *status);
+
+/*
+ * ipahal_pkt_status_exception_str() - returns string represents exception type
+ * @exception: [in] The exception type
+ */
+const char *ipahal_pkt_status_exception_str(
+ enum ipahal_pkt_status_exception exception);
+
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base);
void ipahal_destroy(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index b8d6c13c30ed..c5dbf0185267 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -348,4 +348,97 @@ struct ipa_imm_cmd_hw_dma_task_32b_addr {
u64 packet_size:16;
};
+
+
+/* IPA Status packet H/W structures and info */
+
+/*
+ * struct ipa_status_pkt_hw - IPA status packet payload in H/W format.
+ * This structure describes the status packet H/W structure for the
+ * following statuses: IPA_STATUS_PACKET, IPA_STATUS_DROPPED_PACKET,
+ * IPA_STATUS_SUSPENDED_PACKET.
+ * Other statuses types has different status packet structure.
+ * @status_opcode: The Type of the status (Opcode).
+ * @exception: (not bitmask) - the first exception that took place.
+ * In case of exception, src endp and pkt len are always valid.
+ * @status_mask: Bit mask specifying on which H/W blocks the pkt was processed.
+ * @pkt_len: Pkt pyld len including hdr, include retained hdr if used. Does
+ * not include padding or checksum trailer len.
+ * @endp_src_idx: Source end point index.
+ * @rsvd1: reserved
+ * @endp_dest_idx: Destination end point index.
+ * Not valid in case of exception
+ * @rsvd2: reserved
+ * @metadata: meta data value used by packet
+ * @flt_local: Filter table location flag: Does matching flt rule belongs to
+ * flt tbl that resides in lcl memory? (if not, then system mem)
+ * @flt_hash: Filter hash hit flag: Does matching flt rule was in hash tbl?
+ * @flt_global: Global filter rule flag: Does matching flt rule belongs to
+ * the global flt tbl? (if not, then the per endp tables)
+ * @flt_ret_hdr: Retain header in filter rule flag: Does matching flt rule
+ * specifies to retain header?
+ * @flt_rule_id: The ID of the matching filter rule. This info can be combined
+ * with endp_src_idx to locate the exact rule. ID=0x3FF reserved to specify
+ * flt miss. In case of miss, all flt info to be ignored
+ * @rt_local: Route table location flag: Does matching rt rule belongs to
+ * rt tbl that resides in lcl memory? (if not, then system mem)
+ * @rt_hash: Route hash hit flag: Does matching rt rule was in hash tbl?
+ * @ucp: UC Processing flag.
+ * @rt_tbl_idx: Index of rt tbl that contains the rule on which was a match
+ * @rt_rule_id: The ID of the matching rt rule. This info can be combined
+ * with rt_tbl_idx to locate the exact rule. ID=0x3FF reserved to specify
+ * rt miss. In case of miss, all rt info to be ignored
+ * @nat_hit: NAT hit flag: Was their NAT hit?
+ * @nat_entry_idx: Index of the NAT entry used of NAT processing
+ * @nat_type: Defines the type of the NAT operation:
+ * 00: No NAT
+ * 01: Source NAT
+ * 10: Destination NAT
+ * 11: Reserved
+ * @tag_info: S/W defined value provided via immediate command
+ * @seq_num: Per source endp unique packet sequence number
+ * @time_of_day_ctr: running counter from IPA clock
+ * @hdr_local: Header table location flag: In header insertion, was the header
+ * taken from the table resides in local memory? (If no, then system mem)
+ * @hdr_offset: Offset of used header in the header table
+ * @frag_hit: Frag hit flag: Was their frag rule hit in H/W frag table?
+ * @frag_rule: Frag rule index in H/W frag table in case of frag hit
+ * @hw_specific: H/W specific reserved value
+ */
+struct ipa_pkt_status_hw {
+ u64 status_opcode:8;
+ u64 exception:8;
+ u64 status_mask:16;
+ u64 pkt_len:16;
+ u64 endp_src_idx:5;
+ u64 rsvd1:3;
+ u64 endp_dest_idx:5;
+ u64 rsvd2:3;
+ u64 metadata:32;
+ u64 flt_local:1;
+ u64 flt_hash:1;
+ u64 flt_global:1;
+ u64 flt_ret_hdr:1;
+ u64 flt_rule_id:10;
+ u64 rt_local:1;
+ u64 rt_hash:1;
+ u64 ucp:1;
+ u64 rt_tbl_idx:5;
+ u64 rt_rule_id:10;
+ u64 nat_hit:1;
+ u64 nat_entry_idx:13;
+ u64 nat_type:2;
+ u64 tag_info:48;
+ u64 seq_num:8;
+ u64 time_of_day_ctr:24;
+ u64 hdr_local:1;
+ u64 hdr_offset:10;
+ u64 frag_hit:1;
+ u64 frag_rule:4;
+ u64 hw_specific:16;
+};
+
+/* Size of H/W Packet Status */
+#define IPA3_0_PKT_STATUS_SIZE 32
+
#endif /* _IPAHAL_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 73d008758560..1e5733d3101c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1081,20 +1081,20 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
*/
if (!ipahal_reg_objs[i+1][j].offset) {
IPAHAL_ERR(
- "reg=%s with zero offset\n",
- ipahal_reg_name_str(j));
+ "reg=%s with zero offset ipa_ver=%d\n",
+ ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
if (!ipahal_reg_objs[i+1][j].construct) {
IPAHAL_ERR(
- "reg=%s with NULL construct func\n",
- ipahal_reg_name_str(j));
+ "reg=%s with NULL construct func ipa_ver=%d\n",
+ ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
if (!ipahal_reg_objs[i+1][j].parse) {
IPAHAL_ERR(
- "reg=%s with NULL parse func\n",
- ipahal_reg_name_str(j));
+ "reg=%s with NULL parse func ipa_ver=%d\n",
+ ipahal_reg_name_str(j), i+1);
WARN_ON(1);
}
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 03a4fcbbf7a5..7e7848dea52c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -2290,47 +2290,54 @@ static int ipa3_ssr_notifier_cb(struct notifier_block *this,
unsigned long code,
void *data)
{
- if (ipa3_rmnet_ctx.ipa_rmnet_ssr) {
- if (SUBSYS_BEFORE_SHUTDOWN == code) {
- pr_info("IPA received MPSS BEFORE_SHUTDOWN\n");
- atomic_set(&rmnet_ipa3_ctx->is_ssr, 1);
- ipa3_q6_cleanup();
- if (IPA_NETDEV())
- netif_stop_queue(IPA_NETDEV());
- ipa3_qmi_stop_workqueues();
- ipa3_wan_ioctl_stop_qmi_messages();
- ipa_stop_polling_stats();
- atomic_set(&rmnet_ipa3_ctx->is_ssr, 1);
- if (atomic_read(&rmnet_ipa3_ctx->is_initialized))
- platform_driver_unregister(&rmnet_ipa_driver);
- pr_info("IPA BEFORE_SHUTDOWN handling is complete\n");
- return NOTIFY_DONE;
- }
- if (SUBSYS_AFTER_SHUTDOWN == code) {
- pr_info("IPA received MPSS AFTER_SHUTDOWN\n");
- if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
- ipa3_q6_pipe_reset();
- pr_info("IPA AFTER_SHUTDOWN handling is complete\n");
- return NOTIFY_DONE;
- }
- if (SUBSYS_AFTER_POWERUP == code) {
- pr_info("IPA received MPSS AFTER_POWERUP\n");
- if (!atomic_read(&rmnet_ipa3_ctx->is_initialized)
- && atomic_read(&rmnet_ipa3_ctx->is_ssr))
- platform_driver_register(&rmnet_ipa_driver);
- pr_info("IPA AFTER_POWERUP handling is complete\n");
- return NOTIFY_DONE;
- }
- if (SUBSYS_BEFORE_POWERUP == code) {
- pr_info("IPA received MPSS BEFORE_POWERUP\n");
- if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
- /* clean up cached QMI msg/handlers */
- ipa3_qmi_service_exit();
- ipa3_proxy_clk_vote();
- pr_info("IPA BEFORE_POWERUP handling is complete\n");
- return NOTIFY_DONE;
- }
+ if (!ipa3_rmnet_ctx.ipa_rmnet_ssr)
+ return NOTIFY_DONE;
+
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ IPAWANINFO("IPA received MPSS BEFORE_SHUTDOWN\n");
+ atomic_set(&rmnet_ipa3_ctx->is_ssr, 1);
+ ipa3_q6_cleanup();
+ if (IPA_NETDEV())
+ netif_stop_queue(IPA_NETDEV());
+ ipa3_qmi_stop_workqueues();
+ ipa3_wan_ioctl_stop_qmi_messages();
+ ipa_stop_polling_stats();
+ if (atomic_read(&rmnet_ipa3_ctx->is_initialized))
+ platform_driver_unregister(&rmnet_ipa_driver);
+ IPAWANINFO("IPA BEFORE_SHUTDOWN handling is complete\n");
+ break;
+ case SUBSYS_AFTER_SHUTDOWN:
+ IPAWANINFO("IPA Received MPSS AFTER_SHUTDOWN\n");
+ if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
+ ipa3_validate_q6_gsi_channel_empty();
+ IPAWANINFO("IPA AFTER_SHUTDOWN handling is complete\n");
+ break;
+ case SUBSYS_BEFORE_POWERUP:
+ IPAWANINFO("IPA received MPSS BEFORE_POWERUP\n");
+ if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
+ /* clean up cached QMI msg/handlers */
+ ipa3_qmi_service_exit();
+ /*hold a proxy vote for the modem*/
+ ipa3_proxy_clk_vote();
+ IPAWANINFO("IPA BEFORE_POWERUP handling is complete\n");
+ break;
+ case SUBSYS_AFTER_POWERUP:
+ IPAWANINFO("%s:%d IPA received MPSS AFTER_POWERUP\n",
+ __func__, __LINE__);
+ if (!atomic_read(&rmnet_ipa3_ctx->is_initialized) &&
+ atomic_read(&rmnet_ipa3_ctx->is_ssr))
+ platform_driver_register(&rmnet_ipa_driver);
+
+ IPAWANINFO("IPA AFTER_POWERUP handling is complete\n");
+ break;
+ default:
+ IPAWANDBG("Unsupported subsys notification, IPA received: %lu",
+ code);
+ break;
}
+
+ IPAWANDBG("Exit\n");
return NOTIFY_DONE;
}
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index e36e8e216d98..e9f7b8931d9b 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/dma-mapping.h>
#include <linux/qmi_encdec.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
@@ -85,11 +86,19 @@ static struct {
struct work_struct qmi_event_work;
struct work_struct qmi_recv_msg_work;
struct workqueue_struct *qmi_event_wq;
+ phys_addr_t msa_phys;
+ uint32_t msa_mem_size;
+ void *msa_addr;
uint32_t state;
- u32 board_id;
- u32 num_peers;
- u32 mac_version;
- char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
+ struct wlfw_rf_chip_info_s_v01 chip_info;
+ 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;
+ u32 pwr_pin_result;
+ u32 phy_io_pin_result;
+ u32 rf_pin_result;
+ struct icnss_mem_region_info
+ icnss_mem_region[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01];
} *penv;
static int icnss_qmi_event_post(enum icnss_qmi_event_type type, void *data)
@@ -116,6 +125,167 @@ static int icnss_qmi_event_post(enum icnss_qmi_event_type type, void *data)
return 0;
}
+static int icnss_qmi_pin_connect_result_ind(void *msg, unsigned int msg_len)
+{
+ struct msg_desc ind_desc;
+ struct wlfw_pin_connect_result_ind_msg_v01 ind_msg;
+ int ret = 0;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ind_desc.msg_id = QMI_WLFW_PIN_CONNECT_RESULT_IND_V01;
+ ind_desc.max_msg_len = WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN;
+ ind_desc.ei_array = wlfw_pin_connect_result_ind_msg_v01_ei;
+
+ ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len);
+ if (ret < 0) {
+ pr_err("%s: Failed to decode message!\n", __func__);
+ goto out;
+ }
+
+ /* store pin result locally */
+ if (ind_msg.pwr_pin_result_valid)
+ penv->pwr_pin_result = ind_msg.pwr_pin_result;
+ if (ind_msg.phy_io_pin_result_valid)
+ penv->phy_io_pin_result = ind_msg.phy_io_pin_result;
+ if (ind_msg.rf_pin_result_valid)
+ penv->rf_pin_result = ind_msg.rf_pin_result;
+
+ pr_debug("%s: Pin connect Result: pwr_pin: 0x%x phy_io_pin: 0x%x rf_io_pin: 0x%x\n",
+ __func__, ind_msg.pwr_pin_result, ind_msg.phy_io_pin_result,
+ ind_msg.rf_pin_result);
+out:
+ return ret;
+}
+
+
+static int icnss_adrastea_power_on(void)
+{
+ int ret = 0;
+
+ /* TZ API of power on adrastea */
+
+ return ret;
+}
+
+void icnss_adrastea_power_off(void)
+{
+ /* TZ API of power off adrastea */
+}
+
+static int wlfw_msa_mem_info_send_sync_msg(void)
+{
+ int ret = 0;
+ int i;
+ struct wlfw_msa_info_req_msg_v01 req;
+ struct wlfw_msa_info_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.msa_addr = penv->msa_phys;
+ req.size = penv->msa_mem_size;
+
+ req_desc.max_msg_len = WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_MSA_INFO_REQ_V01;
+ req_desc.ei_array = wlfw_msa_info_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_MSA_INFO_RESP_V01;
+ resp_desc.ei_array = wlfw_msa_info_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+
+ pr_debug("%s: Receive mem_region_info_len: %d\n",
+ __func__, resp.mem_region_info_len);
+
+ if (resp.mem_region_info_len > 2) {
+ pr_err("%s : Invalid memory region length received\n",
+ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < resp.mem_region_info_len; i++) {
+ penv->icnss_mem_region[i].reg_addr =
+ resp.mem_region_info[i].region_addr;
+ penv->icnss_mem_region[i].size =
+ resp.mem_region_info[i].size;
+ penv->icnss_mem_region[i].secure_flag =
+ resp.mem_region_info[i].secure_flag;
+ pr_debug("%s : Memory Region: %d Addr:0x%x Size : %d Flag: %d\n",
+ __func__,
+ i,
+ (unsigned int)penv->icnss_mem_region[i].reg_addr,
+ penv->icnss_mem_region[i].size,
+ penv->icnss_mem_region[i].secure_flag);
+ }
+
+out:
+ return ret;
+}
+
+static int wlfw_msa_ready_send_sync_msg(void)
+{
+ int ret;
+ struct wlfw_msa_ready_req_msg_v01 req;
+ struct wlfw_msa_ready_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req_desc.max_msg_len = WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_MSA_READY_REQ_V01;
+ req_desc.ei_array = wlfw_msa_ready_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_MSA_READY_RESP_V01;
+ resp_desc.ei_array = wlfw_msa_ready_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+out:
+ return ret;
+}
+
static int wlfw_ind_register_send_sync_msg(void)
{
int ret;
@@ -133,6 +303,10 @@ static int wlfw_ind_register_send_sync_msg(void)
req.fw_ready_enable_valid = 1;
req.fw_ready_enable = 1;
+ req.msa_ready_enable_valid = 1;
+ req.msa_ready_enable = 1;
+ req.pin_connect_result_enable_valid = 1;
+ req.pin_connect_result_enable = 1;
req_desc.max_msg_len = WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN;
req_desc.msg_id = QMI_WLFW_IND_REGISTER_REQ_V01;
@@ -198,19 +372,25 @@ static int wlfw_cap_send_sync_msg(void)
}
/* store cap locally */
- if (resp.board_id_valid)
- penv->board_id = resp.board_id;
- if (resp.num_peers_valid)
- penv->num_peers = resp.num_peers;
- if (resp.mac_version_valid)
- penv->mac_version = resp.mac_version;
- if (resp.fw_version_valid)
- strlcpy(penv->fw_version, resp.fw_version,
- QMI_WLFW_MAX_STR_LEN_V01 + 1);
-
- pr_debug("%s: board_id:0x%0x num_peers: %d mac_version: 0x%0x fw_version: %s",
- __func__, penv->board_id, penv->num_peers,
- penv->mac_version, penv->fw_version);
+ if (resp.chip_info_valid)
+ penv->chip_info = resp.chip_info;
+ if (resp.board_info_valid)
+ penv->board_info = resp.board_info;
+ else
+ penv->board_info.board_id = 0xFF;
+ if (resp.soc_info_valid)
+ penv->soc_info = resp.soc_info;
+ if (resp.fw_version_info_valid)
+ penv->fw_version_info = resp.fw_version_info;
+
+ pr_debug("%s: chip_id: 0x%0x, chip_family: 0x%0x, board_id: 0x%0x, soc_id: 0x%0x, fw_version: 0x%0x, fw_build_timestamp: %s",
+ __func__,
+ 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);
out:
return ret;
}
@@ -301,6 +481,49 @@ out:
return ret;
}
+static int wlfw_ini_send_sync_msg(bool enablefwlog)
+{
+ int ret;
+ struct wlfw_ini_req_msg_v01 req;
+ struct wlfw_ini_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+
+ if (!penv || !penv->wlfw_clnt) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.enablefwlog_valid = 1;
+ req.enablefwlog = enablefwlog;
+
+ req_desc.max_msg_len = WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.msg_id = QMI_WLFW_INI_REQ_V01;
+ req_desc.ei_array = wlfw_ini_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.msg_id = QMI_WLFW_INI_RESP_V01;
+ resp_desc.ei_array = wlfw_ini_resp_msg_v01_ei;
+
+ ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp), WLFW_TIMEOUT_MS);
+ if (ret < 0) {
+ pr_err("%s: send req failed %d\n", __func__, ret);
+ goto out;
+ }
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("%s: QMI request failed %d %d\n",
+ __func__, resp.resp.result, resp.resp.error);
+ ret = resp.resp.result;
+ goto out;
+ }
+out:
+ return ret;
+}
+
static void icnss_qmi_wlfw_clnt_notify_work(struct work_struct *work)
{
int ret;
@@ -345,6 +568,15 @@ static void icnss_qmi_wlfw_clnt_ind(struct qmi_handle *handle,
case QMI_WLFW_FW_READY_IND_V01:
icnss_qmi_event_post(ICNSS_QMI_EVENT_FW_READY_IND, NULL);
break;
+ case QMI_WLFW_MSA_READY_IND_V01:
+ pr_debug("%s: Received MSA Ready Indication msg_id 0x%x\n",
+ __func__, msg_id);
+ break;
+ case QMI_WLFW_PIN_CONNECT_RESULT_IND_V01:
+ pr_debug("%s: Received Pin Connect Test Result msg_id 0x%x\n",
+ __func__, msg_id);
+ icnss_qmi_pin_connect_result_ind(msg, msg_len);
+ break;
default:
pr_err("%s: Invalid msg_id 0x%x\n", __func__, msg_id);
break;
@@ -377,8 +609,8 @@ static int icnss_qmi_event_server_arrive(void *data)
ret = qmi_register_ind_cb(penv->wlfw_clnt,
icnss_qmi_wlfw_clnt_ind, penv);
if (ret < 0) {
- pr_err("Failed to register indication callback: %d\n",
- ret);
+ pr_err("%s: Failed to register indication callback: %d\n",
+ __func__, ret);
goto fail;
}
@@ -386,17 +618,48 @@ static int icnss_qmi_event_server_arrive(void *data)
pr_info("%s: QMI Server Connected\n", __func__);
+ ret = icnss_adrastea_power_on();
+ if (ret < 0) {
+ pr_err("%s: Failed to power on hardware: %d\n",
+ __func__, ret);
+ goto fail;
+ }
+
ret = wlfw_ind_register_send_sync_msg();
if (ret < 0) {
- pr_err("Failed to send indication message: %d\n",
- ret);
+ pr_err("%s: Failed to send indication message: %d\n",
+ __func__, ret);
goto out;
}
+ if (penv->msa_mem_size) {
+ penv->msa_addr = dma_alloc_coherent(&penv->pdev->dev,
+ penv->msa_mem_size, &penv->msa_phys,
+ GFP_KERNEL);
+
+ pr_debug("%s: MSA addr: %p, MSA phys: %pa\n", __func__,
+ penv->msa_addr, &penv->msa_phys);
+
+ if (penv->msa_addr) {
+ ret = wlfw_msa_mem_info_send_sync_msg();
+ if (ret < 0) {
+ pr_err("%s: Failed to send MSA info: %d\n",
+ __func__, ret);
+ goto out;
+ }
+ ret = wlfw_msa_ready_send_sync_msg();
+ if (ret < 0) {
+ pr_err("%s: Failed to send MSA ready : %d\n",
+ __func__, ret);
+ goto out;
+ }
+ }
+ }
+
ret = wlfw_cap_send_sync_msg();
if (ret < 0) {
- pr_err("Failed to get capability: %d\n",
- ret);
+ pr_err("%s: Failed to get capability: %d\n",
+ __func__, ret);
goto out;
}
return ret;
@@ -404,6 +667,10 @@ fail:
qmi_handle_destroy(penv->wlfw_clnt);
penv->wlfw_clnt = NULL;
out:
+ if (penv->msa_addr) {
+ dma_free_coherent(&penv->pdev->dev, penv->msa_mem_size,
+ penv->msa_addr, penv->msa_phys);
+ }
ICNSS_ASSERT(0);
return ret;
}
@@ -416,6 +683,10 @@ static int icnss_qmi_event_server_exit(void *data)
pr_info("%s: QMI Service Disconnected\n", __func__);
qmi_handle_destroy(penv->wlfw_clnt);
+ if (penv->msa_addr) {
+ dma_free_coherent(&penv->pdev->dev, penv->msa_mem_size,
+ penv->msa_addr, penv->msa_phys);
+ }
penv->state = 0;
penv->wlfw_clnt = NULL;
@@ -436,6 +707,9 @@ static int icnss_qmi_event_fw_ready_ind(void *data)
ret = -ENODEV;
goto out;
}
+
+ icnss_adrastea_power_off();
+
if (!penv->ops || !penv->ops->probe) {
pr_err("%s: WLAN driver is not registed yet\n", __func__);
ret = -ENOENT;
@@ -458,7 +732,7 @@ static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this,
if (!penv)
return -ENODEV;
- pr_debug("Event Notify: code: %ld", code);
+ pr_debug("%s: Event Notify: code: %ld", __func__, code);
switch (code) {
case QMI_SERVER_ARRIVE:
@@ -469,7 +743,7 @@ static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this,
ret = icnss_qmi_event_post(ICNSS_QMI_EVENT_SERVER_EXIT, NULL);
break;
default:
- pr_debug("Invalid code: %ld", code);
+ pr_debug("%s: Invalid code: %ld", __func__, code);
break;
}
return ret;
@@ -499,7 +773,8 @@ static void icnss_qmi_wlfw_event_work(struct work_struct *work)
icnss_qmi_event_fw_ready_ind(event->data);
break;
default:
- pr_debug("Invalid Event type: %d", event->type);
+ pr_debug("%s: Invalid Event type: %d",
+ __func__, event->type);
break;
}
kfree(event);
@@ -536,8 +811,12 @@ int icnss_register_driver(struct icnss_driver_ops *ops)
penv->ops = ops;
/* check for all conditions before invoking probe */
- if (ICNSS_IS_FW_READY(penv->state) && penv->ops->probe)
+ if (ICNSS_IS_FW_READY(penv->state) && penv->ops->probe) {
ret = penv->ops->probe(&pdev->dev);
+ } else {
+ pr_err("icnss: FW is not ready\n");
+ ret = -ENOENT;
+ }
out:
return ret;
@@ -744,6 +1023,18 @@ int icnss_get_soc_info(struct icnss_soc_info *info)
}
EXPORT_SYMBOL(icnss_get_soc_info);
+int icnss_set_fw_debug_mode(bool enablefwlog)
+{
+ int ret;
+
+ ret = wlfw_ini_send_sync_msg(enablefwlog);
+ if (ret)
+ pr_err("icnss: Fail to send ini, ret = %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(icnss_set_fw_debug_mode);
+
int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config,
enum icnss_driver_mode mode,
const char *host_version)
@@ -838,6 +1129,8 @@ static int icnss_probe(struct platform_device *pdev)
int ret = 0;
struct resource *res;
int i;
+ struct device *dev = &pdev->dev;
+ u32 msa_mem_size = 0;
if (penv)
return -EEXIST;
@@ -873,6 +1166,15 @@ static int icnss_probe(struct platform_device *pdev)
}
}
+ if (of_property_read_u32(dev->of_node, "qcom,wlan-msa-memory",
+ &msa_mem_size) == 0) {
+ penv->msa_mem_size = msa_mem_size;
+ } else {
+ pr_err("icnss: Fail to get MSA Memory Size\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
penv->qmi_event_wq = alloc_workqueue("icnss_qmi_event", 0, 0);
if (!penv->qmi_event_wq) {
pr_err("%s: workqueue creation failed\n", __func__);
diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.c b/drivers/soc/qcom/wlan_firmware_service_v01.c
index b514f3f7c6cd..e899459a5a40 100644
--- a/drivers/soc/qcom/wlan_firmware_service_v01.c
+++ b/drivers/soc/qcom/wlan_firmware_service_v01.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2015-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
@@ -130,6 +130,127 @@ static struct elem_info wlfw_shadow_reg_cfg_s_v01_ei[] = {
},
};
+static struct elem_info wlfw_memory_region_info_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint64_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_memory_region_info_s_v01,
+ region_addr),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_memory_region_info_s_v01,
+ size),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_memory_region_info_s_v01,
+ secure_flag),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_rf_chip_info_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_rf_chip_info_s_v01,
+ chip_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_rf_chip_info_s_v01,
+ chip_family),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_rf_board_info_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_rf_board_info_s_v01,
+ board_id),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_soc_info_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_soc_info_s_v01,
+ soc_id),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_fw_version_info_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_fw_version_info_s_v01,
+ fw_version),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_fw_version_info_s_v01,
+ fw_build_timestamp),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
struct elem_info wlfw_ind_register_req_msg_v01_ei[] = {
{
.data_type = QMI_OPT_FLAG,
@@ -186,6 +307,42 @@ struct elem_info wlfw_ind_register_req_msg_v01_ei[] = {
initiate_cal_update_enable),
},
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ msa_ready_enable_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ msa_ready_enable),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ pin_connect_result_enable_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x14,
+ .offset = offsetof(struct wlfw_ind_register_req_msg_v01,
+ pin_connect_result_enable),
+ },
+ {
.data_type = QMI_EOTI,
.is_array = NO_ARRAY,
.is_array = QMI_COMMON_TLV_TYPE,
@@ -218,6 +375,82 @@ struct elem_info wlfw_fw_ready_ind_msg_v01_ei[] = {
},
};
+struct elem_info wlfw_msa_ready_ind_msg_v01_ei[] = {
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_pin_connect_result_ind_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_pin_connect_result_ind_msg_v01,
+ pwr_pin_result_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(
+ struct wlfw_pin_connect_result_ind_msg_v01,
+ pwr_pin_result),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(
+ struct wlfw_pin_connect_result_ind_msg_v01,
+ phy_io_pin_result_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(
+ struct wlfw_pin_connect_result_ind_msg_v01,
+ phy_io_pin_result),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(
+ struct wlfw_pin_connect_result_ind_msg_v01,
+ rf_pin_result_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(
+ struct wlfw_pin_connect_result_ind_msg_v01,
+ rf_pin_result),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
struct elem_info wlfw_wlan_mode_req_msg_v01_ei[] = {
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
@@ -407,16 +640,17 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = {
.is_array = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- board_id_valid),
+ chip_info_valid),
},
{
- .data_type = QMI_UNSIGNED_4_BYTE,
+ .data_type = QMI_STRUCT,
.elem_len = 1,
- .elem_size = sizeof(uint32_t),
+ .elem_size = sizeof(struct wlfw_rf_chip_info_s_v01),
.is_array = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- board_id),
+ chip_info),
+ .ei_array = wlfw_rf_chip_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
@@ -425,16 +659,17 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = {
.is_array = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- num_peers_valid),
+ board_info_valid),
},
{
- .data_type = QMI_UNSIGNED_4_BYTE,
+ .data_type = QMI_STRUCT,
.elem_len = 1,
- .elem_size = sizeof(uint32_t),
+ .elem_size = sizeof(struct wlfw_rf_board_info_s_v01),
.is_array = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- num_peers),
+ board_info),
+ .ei_array = wlfw_rf_board_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
@@ -443,16 +678,17 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = {
.is_array = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- mac_version_valid),
+ soc_info_valid),
},
{
- .data_type = QMI_UNSIGNED_4_BYTE,
+ .data_type = QMI_STRUCT,
.elem_len = 1,
- .elem_size = sizeof(uint32_t),
+ .elem_size = sizeof(struct wlfw_soc_info_s_v01),
.is_array = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- mac_version),
+ soc_info),
+ .ei_array = wlfw_soc_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
@@ -461,16 +697,17 @@ struct elem_info wlfw_cap_resp_msg_v01_ei[] = {
.is_array = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- fw_version_valid),
+ fw_version_info_valid),
},
{
- .data_type = QMI_STRING,
- .elem_len = QMI_WLFW_MAX_STR_LEN_V01 + 1,
- .elem_size = sizeof(char),
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct wlfw_fw_version_info_s_v01),
.is_array = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct wlfw_cap_resp_msg_v01,
- fw_version),
+ fw_version_info),
+ .ei_array = wlfw_fw_version_info_s_v01_ei,
},
{
.data_type = QMI_EOTI,
@@ -976,3 +1213,136 @@ struct elem_info wlfw_cal_update_resp_msg_v01_ei[] = {
.is_array = QMI_COMMON_TLV_TYPE,
},
};
+
+struct elem_info wlfw_msa_info_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint64_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct wlfw_msa_info_req_msg_v01,
+ msa_addr),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct wlfw_msa_info_req_msg_v01,
+ size),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_msa_info_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_msa_info_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x03,
+ .offset = offsetof(struct wlfw_msa_info_resp_msg_v01,
+ mem_region_info_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01,
+ .elem_size = sizeof(struct wlfw_memory_region_info_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x03,
+ .offset = offsetof(struct wlfw_msa_info_resp_msg_v01,
+ mem_region_info),
+ .ei_array = wlfw_memory_region_info_s_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_msa_ready_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_msa_ready_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_msa_ready_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,
+ },
+};
+
+struct elem_info wlfw_ini_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_ini_req_msg_v01,
+ enablefwlog_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct wlfw_ini_req_msg_v01,
+ enablefwlog),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info wlfw_ini_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_ini_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 62b7183e2141..6d007c297cf6 100644
--- a/drivers/soc/qcom/wlan_firmware_service_v01.h
+++ b/drivers/soc/qcom/wlan_firmware_service_v01.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2015-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
@@ -16,29 +16,39 @@
#define WLFW_SERVICE_ID_V01 0x45
#define WLFW_SERVICE_VERS_V01 0x01
-#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
-#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
-#define QMI_WLFW_CAP_RESP_V01 0x0024
#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
-#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
-#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
-#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
-#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
-#define QMI_WLFW_FW_READY_IND_V01 0x0021
-#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
#define QMI_WLFW_CAP_REQ_V01 0x0024
-#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
+#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
+#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
+#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_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
+#define QMI_WLFW_MSA_READY_IND_V01 0x002B
#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022
-#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023
+#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
+#define QMI_WLFW_PIN_CONNECT_RESULT_IND_V01 0x002C
+#define QMI_WLFW_FW_READY_IND_V01 0x0021
+#define QMI_WLFW_MSA_READY_RESP_V01 0x002E
+#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
+#define QMI_WLFW_INI_REQ_V01 0x002F
+#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
+#define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
+#define QMI_WLFW_MSA_READY_REQ_V01 0x002E
+#define QMI_WLFW_CAP_RESP_V01 0x0024
+#define QMI_WLFW_MSA_INFO_REQ_V01 0x002D
+#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
+#define QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01 2
#define QMI_WLFW_MAX_NUM_CAL_V01 5
#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
#define QMI_WLFW_MAX_NUM_CE_V01 12
+#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_MAX_NUM_SVC_V01 24
@@ -98,6 +108,30 @@ struct wlfw_shadow_reg_cfg_s_v01 {
uint16_t offset;
};
+struct wlfw_memory_region_info_s_v01 {
+ uint64_t region_addr;
+ uint32_t size;
+ uint8_t secure_flag;
+};
+
+struct wlfw_rf_chip_info_s_v01 {
+ uint32_t chip_id;
+ uint32_t chip_family;
+};
+
+struct wlfw_rf_board_info_s_v01 {
+ uint32_t board_id;
+};
+
+struct wlfw_soc_info_s_v01 {
+ uint32_t soc_id;
+};
+
+struct wlfw_fw_version_info_s_v01 {
+ uint32_t fw_version;
+ char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN_V01 + 1];
+};
+
struct wlfw_ind_register_req_msg_v01 {
uint8_t fw_ready_enable_valid;
uint8_t fw_ready_enable;
@@ -105,8 +139,12 @@ struct wlfw_ind_register_req_msg_v01 {
uint8_t initiate_cal_download_enable;
uint8_t initiate_cal_update_enable_valid;
uint8_t initiate_cal_update_enable;
+ uint8_t msa_ready_enable_valid;
+ uint8_t msa_ready_enable;
+ uint8_t pin_connect_result_enable_valid;
+ uint8_t pin_connect_result_enable;
};
-#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 12
+#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 20
extern struct elem_info wlfw_ind_register_req_msg_v01_ei[];
struct wlfw_ind_register_resp_msg_v01 {
@@ -121,6 +159,23 @@ struct wlfw_fw_ready_ind_msg_v01 {
#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct elem_info wlfw_fw_ready_ind_msg_v01_ei[];
+struct wlfw_msa_ready_ind_msg_v01 {
+ char placeholder;
+};
+#define WLFW_MSA_READY_IND_MSG_V01_MAX_MSG_LEN 0
+extern struct elem_info wlfw_msa_ready_ind_msg_v01_ei[];
+
+struct wlfw_pin_connect_result_ind_msg_v01 {
+ uint8_t pwr_pin_result_valid;
+ uint32_t pwr_pin_result;
+ uint8_t phy_io_pin_result_valid;
+ uint32_t phy_io_pin_result;
+ uint8_t rf_pin_result_valid;
+ uint32_t rf_pin_result;
+};
+#define WLFW_PIN_CONNECT_RESULT_IND_MSG_V01_MAX_MSG_LEN 21
+extern struct elem_info wlfw_pin_connect_result_ind_msg_v01_ei[];
+
struct wlfw_wlan_mode_req_msg_v01 {
enum wlfw_driver_mode_enum_v01 mode;
};
@@ -163,16 +218,16 @@ extern struct elem_info wlfw_cap_req_msg_v01_ei[];
struct wlfw_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
- uint8_t board_id_valid;
- uint32_t board_id;
- uint8_t num_peers_valid;
- uint32_t num_peers;
- uint8_t mac_version_valid;
- uint32_t mac_version;
- uint8_t fw_version_valid;
- char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
-};
-#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 47
+ uint8_t chip_info_valid;
+ struct wlfw_rf_chip_info_s_v01 chip_info;
+ uint8_t board_info_valid;
+ struct wlfw_rf_board_info_s_v01 board_info;
+ uint8_t soc_info_valid;
+ struct wlfw_soc_info_s_v01 soc_info;
+ uint8_t fw_version_info_valid;
+ struct wlfw_fw_version_info_s_v01 fw_version_info;
+};
+#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 72
extern struct elem_info wlfw_cap_resp_msg_v01_ei[];
struct wlfw_bdf_download_req_msg_v01 {
@@ -271,4 +326,45 @@ struct wlfw_cal_update_resp_msg_v01 {
#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6181
extern struct elem_info wlfw_cal_update_resp_msg_v01_ei[];
+struct wlfw_msa_info_req_msg_v01 {
+ uint64_t msa_addr;
+ uint32_t size;
+};
+#define WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
+extern struct elem_info wlfw_msa_info_req_msg_v01_ei[];
+
+struct wlfw_msa_info_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+ uint32_t mem_region_info_len;
+ struct wlfw_memory_region_info_s_v01
+ mem_region_info[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01];
+};
+#define WLFW_MSA_INFO_RESP_MSG_V01_MAX_MSG_LEN 37
+extern struct elem_info wlfw_msa_info_resp_msg_v01_ei[];
+
+struct wlfw_msa_ready_req_msg_v01 {
+ char placeholder;
+};
+#define WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN 0
+extern struct elem_info wlfw_msa_ready_req_msg_v01_ei[];
+
+struct wlfw_msa_ready_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_MSA_READY_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_msa_ready_resp_msg_v01_ei[];
+
+struct wlfw_ini_req_msg_v01 {
+ uint8_t enablefwlog_valid;
+ uint8_t enablefwlog;
+};
+#define WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN 4
+extern struct elem_info wlfw_ini_req_msg_v01_ei[];
+
+struct wlfw_ini_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define WLFW_INI_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct elem_info wlfw_ini_resp_msg_v01_ei[];
+
#endif
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 89045d079567..50dfaee072dc 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2424,6 +2424,42 @@ err:
return ret;
}
+static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (mdwc->vbus_active)
+ return snprintf(buf, PAGE_SIZE, "peripheral\n");
+ if (mdwc->id_state == DWC3_ID_GROUND)
+ return snprintf(buf, PAGE_SIZE, "host\n");
+
+ return snprintf(buf, PAGE_SIZE, "none\n");
+}
+
+static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+ if (sysfs_streq(buf, "peripheral")) {
+ mdwc->vbus_active = true;
+ mdwc->id_state = DWC3_ID_FLOAT;
+ } else if (sysfs_streq(buf, "host")) {
+ mdwc->vbus_active = false;
+ mdwc->id_state = DWC3_ID_GROUND;
+ } else {
+ mdwc->vbus_active = false;
+ mdwc->id_state = DWC3_ID_FLOAT;
+ }
+
+ dwc3_ext_event_notify(mdwc);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(mode);
+
static int dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node, *dwc3_node;
@@ -2738,6 +2774,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
if (of_property_read_bool(node, "qcom,disable-dev-mode-pm"))
pm_runtime_get_noresume(mdwc->dev);
+ device_create_file(&pdev->dev, &dev_attr_mode);
+
/* Update initial VBUS/ID state from extcon */
if (mdwc->extcon_vbus && extcon_get_cable_state_(mdwc->extcon_vbus,
EXTCON_USB))
@@ -2783,6 +2821,8 @@ static int dwc3_msm_remove(struct platform_device *pdev)
struct dwc3_msm *mdwc = platform_get_drvdata(pdev);
int ret_pm;
+ device_remove_file(&pdev->dev, &dev_attr_mode);
+
if (cpu_to_affin)
unregister_cpu_notifier(&mdwc->dwc3_cpu_notifier);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index c8c40d4aaf75..cd54f6410239 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -2179,11 +2179,17 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
if (len < sizeof(*d) ||
d->bFirstInterfaceNumber >= ffs->interfaces_count ||
- d->Reserved1)
+ d->Reserved1 != 1) {
+ pr_err("%s(): Invalid os_desct_ext_compat\n",
+ __func__);
return -EINVAL;
+ }
for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
- if (d->Reserved2[i])
+ if (d->Reserved2[i]) {
+ pr_err("%s(): Invalid Reserved2 of ext_compat\n",
+ __func__);
return -EINVAL;
+ }
length = sizeof(struct usb_ext_compat_desc);
}
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 69eb69ae177a..de246efcbb58 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -474,7 +474,8 @@ static int qusb_phy_init(struct usb_phy *phy)
writel_relaxed(0x0, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2);
/* save reset value to override based on clk scheme */
- reset_val = readl_relaxed(qphy->base + QUSB2PHY_PLL_TEST);
+ if (qphy->ref_clk_base)
+ reset_val = readl_relaxed(qphy->base + QUSB2PHY_PLL_TEST);
if (qphy->qusb_phy_init_seq)
qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
@@ -516,18 +517,19 @@ static int qusb_phy_init(struct usb_phy *phy)
/* Require to get phy pll lock successfully */
usleep_range(150, 160);
- if (!qphy->is_se_clk)
- reset_val &= ~CLK_REF_SEL;
- else
- reset_val |= CLK_REF_SEL;
-
/* Turn on phy ref_clk if DIFF_CLK else select SE_CLK */
- if (!qphy->is_se_clk && qphy->ref_clk_base)
- writel_relaxed((readl_relaxed(qphy->ref_clk_base) |
+ if (qphy->ref_clk_base) {
+ if (!qphy->is_se_clk) {
+ reset_val &= ~CLK_REF_SEL;
+ writel_relaxed((readl_relaxed(qphy->ref_clk_base) |
QUSB2PHY_REFCLK_ENABLE),
qphy->ref_clk_base);
- else
- writel_relaxed(reset_val, qphy->base + QUSB2PHY_PLL_TEST);
+ } else {
+ reset_val |= CLK_REF_SEL;
+ writel_relaxed(reset_val,
+ qphy->base + QUSB2PHY_PLL_TEST);
+ }
+ }
/* Make sure that above write is completed to get PLL source clock */
wmb();
@@ -835,8 +837,26 @@ static int qusb_phy_probe(struct platform_device *pdev)
if (res) {
qphy->ref_clk_base = devm_ioremap_nocache(dev,
res->start, resource_size(res));
- if (IS_ERR(qphy->ref_clk_base))
+ if (IS_ERR(qphy->ref_clk_base)) {
dev_dbg(dev, "ref_clk_address is not available.\n");
+ return PTR_ERR(qphy->ref_clk_base);
+ }
+
+ ret = of_property_read_string(dev->of_node,
+ "qcom,phy-clk-scheme", &phy_type);
+ if (ret) {
+ dev_err(dev, "error need qsub_phy_clk_scheme.\n");
+ return ret;
+ }
+
+ if (!strcasecmp(phy_type, "cml")) {
+ qphy->is_se_clk = false;
+ } else if (!strcasecmp(phy_type, "cmos")) {
+ qphy->is_se_clk = true;
+ } else {
+ dev_err(dev, "erro invalid qusb_phy_clk_scheme\n");
+ return -EINVAL;
+ }
}
qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
@@ -956,22 +976,6 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
hold_phy_reset = of_property_read_bool(dev->of_node, "qcom,hold-reset");
- ret = of_property_read_string(dev->of_node,
- "qcom,phy-clk-scheme", &phy_type);
- if (ret) {
- dev_err(dev, "error need qsub_phy_clk_scheme.\n");
- return ret;
- }
-
- if (!strcasecmp(phy_type, "cml")) {
- qphy->is_se_clk = false;
- } else if (!strcasecmp(phy_type, "cmos")) {
- qphy->is_se_clk = true;
- } else {
- dev_err(dev, "erro invalid qusb_phy_clk_scheme\n");
- return -EINVAL;
- }
-
ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
(u32 *) qphy->vdd_levels,
ARRAY_SIZE(qphy->vdd_levels));
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index 9af1a75c724e..cacb46378c94 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -274,6 +274,9 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy)
writel_relaxed(0x03, phy->base + phy->phy_reg[USB3_PHY_START]);
writel_relaxed(0x00, phy->base + phy->phy_reg[USB3_PHY_SW_RESET]);
+ /* Make sure above write completed to bring PHY out of reset */
+ mb();
+
/* Wait for PHY initialization to be done */
do {
if (readl_relaxed(phy->base +
diff --git a/include/soc/qcom/clock-alpha-pll.h b/include/soc/qcom/clock-alpha-pll.h
index b5a34b4cecb5..0b5329ba817c 100644
--- a/include/soc/qcom/clock-alpha-pll.h
+++ b/include/soc/qcom/clock-alpha-pll.h
@@ -1,5 +1,5 @@
/*
- * 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
@@ -66,6 +66,12 @@ struct alpha_pll_clk {
bool slew;
bool no_prepared_reconfig;
+ /* some PLLs support dynamically updating their rate
+ * without disabling the PLL first. Set this flag
+ * to enable this support.
+ */
+ bool dynamic_update;
+
/*
* Some chipsets need the offline request bit to be
* cleared on a second write to the register, even though
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index d1d677f6eaf5..14a22fd1b55f 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -58,6 +58,13 @@ struct icnss_wlan_enable_cfg {
struct icnss_shadow_reg_cfg *shadow_reg_cfg;
};
+/* MSA Memory Regions Information */
+struct icnss_mem_region_info {
+ uint64_t reg_addr;
+ uint32_t size;
+ uint8_t secure_flag;
+};
+
/* driver modes */
enum icnss_driver_mode {
ICNSS_MISSION,
@@ -91,5 +98,6 @@ extern int icnss_ce_request_irq(unsigned int ce_id,
irqreturn_t (*handler)(int, void *),
unsigned long flags, const char *name, void *ctx);
extern int icnss_get_ce_id(int irq);
+extern int icnss_set_fw_debug_mode(bool enablefwlog);
#endif /* _ICNSS_WLAN_H_ */