diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-04-05 18:16:21 -0700 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2016-04-05 18:16:22 -0700 |
| commit | d31ca55280c228f9e8833b7ebdfad1247e3ac7de (patch) | |
| tree | a9320836ea8bde11d162fb660e1da94b2e28b5e4 | |
| parent | 1ee82d8d00dafea331698b8d70722286d45038f6 (diff) | |
| parent | 41dd57df41626b75145c56f958e93fe2904303a9 (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
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(®_write, - ipa3_get_ep_mapping(client_idx)); - cmd_pyld = ipahal_construct_imm_cmd( - IPA_IMM_CMD_REGISTER_WRITE, ®_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_ */ |
