summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-04-08 15:15:20 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-04-08 15:15:21 -0600
commitf2bc8a14186b7468d444792d1077e3efb16ef880 (patch)
tree9c9f5f46883be5d81ba593d5da6379c4c89a3bc5
parentd31ca55280c228f9e8833b7ebdfad1247e3ac7de (diff)
parent3f901317b1835e7b26d6c72b6c8f2c79539866fc (diff)
Promotion of kernel.lnx.4.4-160407.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 969563 If9ec89ab2f2ea341f38d8952c1688d277a5082ed edac: cortex: Support L2 error reporting on Kryo2xx Gold 990478 I520b7943b85cd61065703c7bf9a5d8efb6302a56 msm: ipa: support WDI 2.0 suspend 998162 I74539e626c641c78c4b1ed759e0b9da1b82e89cf ASoC: msmcobalt: Machine driver changes for kernel 4.4 987415 I20921a97b02dce0507f58c4951ce539a2aae5597 wil6210: switch to generated wmi.h 982882 I7eac78d7beb90436d24468547aeb789f7c8ec878 wil6210: protect synchronous wmi commands handling 994255 Ic0934d795c2c7c20332358a3da603e093f94d980 ARM: dts: msm: Move SMD packet node to GLINK packet for 1000118 I95fbcd5a1b70816cb3b03b7e3652243b1c3e527e msm: defconfig: Enable CONFIG_QCOM_KGSL in msmcortex_def 998162 I625a8970e800487746d458c8f51f63c1b371f08c soc: qcom: Add avtimer device tree documentation 1000722 I2187343430efea1dc20523d6e8a5965f360864e6 soc: qcom: spm: Add SAW v4.1 support 982882 I11fa67f7040c4a728f0cd7633f4fbb829ac165d0 wil6210: prevent access to vring_tx_data lock during its 989126 I5ad87614edb1307cffaa798f9b393d816dce012a soc: qcom: msm_glink_pkt: remove the wakeup source durin 1000176 995213 Id347f540f866be6b8442d5f166c6cf7b0ae4c000 iommu/arm-smmu: Fix DOMAIN_ATTR_S1_BYPASS check 998162 Ie176b5e67263e56b296ae144e1a414b4bfa51e80 ASoC: msmcobalt: Add machine driver support for msmcobal 994871 I907adfb5f5d24c06dd038b07a17b31d42b91dfad soc: qcom: ipc_router_mhi_xprt: Code Refactor to handle 988580 I8205df6ecbeed8eca7ff9a81534edadf51309fe1 msm: camera: Change API to populate regulator name 982882 I66a6a23239710c85b9cdb5824c205692c4b53866 wil6210: wait for disconnect completion 982882 I0e438d437154b1b47c572218072a736da5013c80 wil6210: AP: prevent connecting to already connected sta 999684 I469e8609bf23bee97b3f9c612401aaf92bc72a30 dwc3: gadget: Resume controller when udc_stop is called 1000176 I6653b3b6ceb071283fb5a8e07257c496e99dd1f3 iommu/arm-smmu: Support DOMAIN_ATTR_S1_BYPASS 979349 I5633baa3d687972a2038336c78555747fc489c84 soc: qcom: Add SSR support in generic interrupt handler 1000767 I12b0341148f05a3129e8b1aed3ba322277276360 arm64: Check for parity errors on synchronous aborts 999679 Id44c91481d4c184a1991768baf13adad2fae9fb3 usb: phy: qusb: Update QUSB PHY power up functionality f 998028 I5f80603633464e7eea322fde57110e377b72d84c soc: qcom: smem: Renaming smem item SMEM_SMEM_STATIC_LOG 978953 I7a9a61c8aa11bd5c0f5f2effc487a2225e27011d icnss: Add support of skiping QMI 987962 999619 Ib64384d4cc18577c4f33f140ed35311b998f4dda ARM: dts: msm: Add camera isp and ispif soc node for msm 999935 I1b24c4e13daaae3e63c5cacefcbda12b8cfbeeb8 msm: ipa3: remove odu_bridge functions from ipa.h ARM: dts: msm: Add RTC device for msmcobalt 998951 I806ed575427b90ee82c08ac1a7f8c8692c03b6d1 defconfig: msmcortex: Enable TSENS 982882 Ia78ddf6f5243a8d28c3bfdfc29e0eb512658d0a7 wil6210: TX vring optimization 994721 I18f52fa873b332fb6ad644afc565a84bfed154cc ARM: dts: msm: Rename low power names to be same between 998740 Id59f17528ead86a7c0ac787811b716a209df1eaf icnss: Init spin lock in icnss_probe 1000759 I67181840c8e889ff31111f4fd419edbf5d8d0810 defconfig: msmcortex-perf: Enable POWER_RESET_QCOM 994255 I4a0022954d34d52899d5dd357813c4da90717e2e soc: qcom: msm_glink_pkt: Add GLINK_OPT_INITIAL_XPORT fl 447740 Ieded4bfe038ca936247fa4b638070e979b02eaa1 android/lowmemorykiller: Wait for memory to be freed 994871 I798d27248acaf7aa2ab15e8739c638a96a49b2b7 ARM: dts: msm: Add external modem to ipcrouter dtsi 987584 Ifea6c2de94071719ffede0f641f8a47526bc9e03 icnss: Allocate msa memory in icnss_probe 999679 I68ae8d863a6e438a8d11061db2c75072f4a4e012 ARM: dts: msm: Add QUSB PHY major revision for msm8996 995686 Ide2c4500cfdd0a9c684329ab5f7ac0603e4fc199 regulator: cpr3-regulator: wait for SPM availability for 993907 I55e895be945a690a707f6015c09578e31c1de693 msm: ipa: fix hdr log print 1000634 I539dc604b150f9f23fda09f343cc5e1d25a6ca47 pinctrl: qcom: Add target value for gpio interrupt on ms 995505 Iefe2d6b370f6ec303286afc139fa9913fa9a4099 cpufreq_stats: Disable cpu hotplug during stats table cr 1001094 I965a463ec4808d72ac8fc9d7aa98011ab45c984e ARM: dts: msm: Limit msmcobalt cluster frequencies to 30 954082 Ic7baf2a3da4ed8f8a9023617059e22fd81c3ba45 PM / devfreq: bw_hwmon: Fix race condition in polling in 980185 I55618784befc61e37e68d3b8d8c7c5c30f45e4fc msm: rmnet_ipa3: fix the crash issue 987593 I635d710759a94e2bb29fd3c7811816d09243de50 ARM: dts: msm: Support AVS_CTL register write for msmcob 999887 I4ef85fc64f465aa0d4901493b80dd676596affcb msm: ipa3: add ipc logging support for ipahal 999988 I59681cf42274f70d5f46b869257a838014d8bf61 pwm: Add snapshot of device tree documentation for pwm-q 987415 I5018f40be6a71b4b8c7c3ee94c8e70cfa1fb373a wil6210: Set permanent MAC address to wiphy 1000176 If2ae2021ae9ce10bd22f424967cfcd9c3f94534e arm64: dma_mapping: Support DOMAIN_ATTR_S1_BYPASS 982882 I7d6e3cf5e8abab45da5febc0129fb67830d9e6cb wil6210: remove BACK RX and TX workers 990478 I73447c5557d42817ac2214532273e0de638e13d9 msm: ipa: header change for wlan VA mapping 986484 I5921dc3978bf96221b50148bb2f86b0ffed3b5fb icnss: Update WLAN mode in wlan_firmware_service 998951 I22b8c5834a278d6ebb943e73c70966f37a7b3dcd arm: enable configurable thermal trips for ARCH_QCOM tar 1001094 I6224ecb800bcbca821f42abec43bc57ee701ce80 clk: msm: clock-osm: support OPP table with single frequ 982931 I05b99ec66b0da41697f41c547aab0b0497dd9be6 wil6210: add support for discovery mode during scan 994871 I23d391546a191eb104fb4c50e19aef8a8b566adb defconfig: msm: Enable IPC Router MHI transport 999530 Ia5d76ea4de29dbafe309a831f8a2418c058cba94 soc: qcom: Service locator for kernel clients 1000176 I2f78d5c798d0d2575d52b341aaf29b35294c93f1 ion: Fix typo in ion system secure heap 987415 Ie6684664743694f004289da9ec041f685ec0c05e wil6210: replay attack detection 1000636 I5a77c08532bb5e841f8c1e8e494857e1361dfc40 ARM: dts: msm: Modem PIL clock change for MSMCOBALT 999988 I96761cd2bf18bce6ef7795b6686c5da72fe11a89 defconfig: arm64: msmcortex: enable PWM support for msmc 999935 Ib5109681c62137d1310539daa816d5229bc08098 msm: ipa3: add odu_bridge to ipa_clients folder Id72e67e31fb52e07f01fb6e234b102f63b400aa5 arm64: process management: Add TIF_MM_RELEASED 995744 Ie763455df2cffcb4fc9447a1bbcc8d9c7d577c6c msm: camera: isp: Add camif raw path output format suppo 952834 I5fe327ea61eb2d16591861b1246fdca2ecce2b1c soc: qcom: glink_smd_xprt: Fix handling subsystem restar 986135 I796b06fae4376cda792d7f26a430ad4580899846 wil6210: add support for platform specific notification 979349 I14504819e04c3e952fcdbceba5a20f876b92ae88 ARM: dts: msm: Add SPSS SSR support for MSMCOBALT. 990478 Ib0cdd0c7614916e53f2731f61d0399959d4b739d msm: ipa: header file change for WDI2.0 982931 I9f26a8ff8433268240eb9443befadc0d279a0293 cfg80211: basic support for PBSS network type 998162 Icc1ddddfdce35ab1ca70dc68fb4878f7c0c36dc7 ARM: msm: dts: Add support for audio on msmcobalt 991098 I45809876336633a496d03e507403944c12f0abb9 ARM: dts: msm: Add bluetooth DT for msm8998 1000770 I26cc21856e9a26be71af6aa91d50e5af2f9fefc6 ARM: dts: msm: Add RTC device for msmcobalt 999530 I37cb319638ce5b6285b2f2ff4386fd92cbda83fd soc: qcom: Add infrastructure to test service locator 990478 I4ac096336f5aeb01fbba8241cda987f56edc1232 msm: ipa: change for WDI2.0 I7d8a8fd39ca5625e6448ed2efebfb621f6e93845 android/lowmemorykiller: Check all tasks for death pendi 982082 I77753fd25d5a4256a4a4cdd74518facd63becf25 msm: camera: sensor: Update actuator specific I2C struct 996222 I18f1ce72dfe93da2fdb80725ed66218eb0af2f49 msm: camera: Add support to enable eLDOs through GPIOs 999935 Ic6da089ebd7878f0d7ceebde7cd8e8549c30182e msm: ipa3: include ipa.h from ipa_odu_bridge.h 998870 I53113d6454de577d4e68f226975a078889d6b2c3 wil6210: disable PCIe relaxed ordering 998162 Ia06b7877b35c599fdb7a38c09e1cc003d88ec46b defconfig: Add support for audio drivers on msmcobalt 990478 I910ed12f79f58dd1a0b0a58fb1cceb7d79ceaaa4 ARM: dts: msm: Add IPA WDI2.0 support for MSMcobalt 999935 Iadfcf4a88472c54fbfe066fa6304146140b76201 msm: ipa3: add ipc logging for odu_bridge driver 991098 Ibf0e4a0ebd55adaadb6d26b335c3d0a9edbe8845 bluetooth: Add WCN3990 power control Change-Id: I43cbfc16fb8ce9039622425df3a0377fb12b950b CRs-Fixed: 1000634, 986484, 986135, 979349, 999684, 998028, 1000759, 994871, 1000770, 998951, 994721, 995744, 987962, 1001094, 987584, 980185, 999887, 993907, 982882, 999530, 987415, 998870, 999988, 988580, 998740, 995686, 998162, 982931, 994255, 999679, 996222, 989126, 969563, 1000722, 447740, 987593, 1000767, 999935, 999619, 952834, 991098, 1000118, 990478, 978953, 995213, 954082, 1000176, 995505, 1000636, 982082
-rw-r--r--Documentation/devicetree/bindings/cnss/icnss.txt2
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-ispif.txt159
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-vfe.txt205
-rw-r--r--Documentation/devicetree/bindings/platform/msm/ipa.txt2
-rw-r--r--Documentation/devicetree/bindings/pwm/pwm-qpnp.txt211
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/avtimer.txt26
-rwxr-xr-xDocumentation/devicetree/bindings/sound/qcom-audio-dev.txt120
-rw-r--r--Documentation/devicetree/bindings/usb/msm-phy.txt1
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi285
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmcobalt.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-ipcrouter.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi177
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi232
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi24
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi24
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi100
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi36
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-wsa881x.dtsi57
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi155
-rw-r--r--arch/arm64/Kconfig.platforms1
-rw-r--r--arch/arm64/configs/msm-perf_defconfig1
-rw-r--r--arch/arm64/configs/msm_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig13
-rw-r--r--arch/arm64/configs/msmcortex_defconfig12
-rw-r--r--arch/arm64/include/asm/thread_info.h1
-rw-r--r--arch/arm64/mm/dma-mapping.c7
-rw-r--r--arch/arm64/mm/fault.c2
-rw-r--r--drivers/bluetooth/bluetooth-power.c43
-rw-r--r--drivers/clk/msm/clock-osm.c21
-rw-r--r--drivers/cpufreq/cpufreq_stats.c4
-rw-r--r--drivers/devfreq/governor_bw_hwmon.c19
-rw-r--r--drivers/edac/cortex_arm64_edac.c88
-rw-r--r--drivers/iommu/arm-smmu.c23
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h3
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.c93
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.h20
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c7
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h1
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c76
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c42
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c82
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h11
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c81
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c162
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h7
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c67
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c79
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h5
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c133
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c61
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c87
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c204
-rw-r--r--drivers/net/wireless/ath/wil6210/trace.h19
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c93
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.h12
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h72
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.h8
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c61
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h1264
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msmcobalt.c3
-rw-r--r--drivers/platform/msm/ipa/Makefile2
-rw-r--r--drivers/platform/msm/ipa/ipa_api.c102
-rw-r--r--drivers/platform/msm/ipa/ipa_api.h11
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/Makefile3
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/ipa_usb.c64
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/odu_bridge.c (renamed from drivers/platform/msm/ipa/ipa_v2/odu_bridge.c)224
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/Makefile4
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c8
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h14
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c5
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/Makefile4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c6
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h28
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c431
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c5
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c106
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h49
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c13
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/odu_bridge.c1233
-rw-r--r--drivers/platform/msm/msm_11ad/msm_11ad.c22
-rw-r--r--drivers/regulator/cpr3-regulator.c3
-rw-r--r--drivers/soc/qcom/Kconfig9
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/glink_smd_xprt.c36
-rw-r--r--drivers/soc/qcom/icnss.c149
-rw-r--r--drivers/soc/qcom/ipc_router_mhi_xprt.c105
-rw-r--r--drivers/soc/qcom/msm-spm.c33
-rw-r--r--drivers/soc/qcom/msm_glink_pkt.c11
-rw-r--r--drivers/soc/qcom/service-locator-private.h362
-rw-r--r--drivers/soc/qcom/service-locator.c525
-rw-r--r--drivers/soc/qcom/subsys-pil-tz.c99
-rw-r--r--drivers/soc/qcom/wlan_firmware_service_v01.h2
-rw-r--r--drivers/staging/android/ion/ion_system_secure_heap.c2
-rw-r--r--drivers/staging/android/lowmemorykiller.c50
-rw-r--r--drivers/usb/dwc3/gadget.c7
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c72
-rw-r--r--include/linux/bluetooth-power.h2
-rw-r--r--include/linux/ipa.h82
-rw-r--r--include/linux/ipa_odu_bridge.h84
-rw-r--r--include/media/msm_cam_sensor.h4
-rw-r--r--include/net/cfg80211.h8
-rw-r--r--include/soc/qcom/icnss.h2
-rw-r--r--include/soc/qcom/service-locator.h88
-rw-r--r--include/soc/qcom/smem.h4
-rw-r--r--include/uapi/linux/nl80211.h7
-rw-r--r--include/uapi/media/msm_cam_sensor.h4
-rw-r--r--include/uapi/media/msm_camsensor_sdk.h4
-rw-r--r--net/wireless/nl80211.c11
-rw-r--r--net/wireless/sme.c9
-rw-r--r--sound/soc/msm/Kconfig27
-rw-r--r--sound/soc/msm/Makefile4
-rw-r--r--sound/soc/msm/msmcobalt.c2828
122 files changed, 8624 insertions, 3230 deletions
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index f07a2beafbb3..08fab81f3393 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -14,6 +14,7 @@ Required properties:
- qcom,wlan-msa-memory: MSA memory size
Optional properties:
+ - qcom,skip-qmi: Boolean property to decide whether to use QMI or not
Example:
@@ -35,4 +36,5 @@ Example:
<0 140 0 /* CE10 */ >,
<0 141 0 /* CE11 */ >;
qcom,wlan-msa-memory = <0x200000>;
+ qcom,skip-qmi;
};
diff --git a/Documentation/devicetree/bindings/media/video/msm-ispif.txt b/Documentation/devicetree/bindings/media/video/msm-ispif.txt
new file mode 100644
index 000000000000..c4086df2b283
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-ispif.txt
@@ -0,0 +1,159 @@
+* Qualcomm MSM ISPIF
+
+Required properties:
+- cell-index: ispif hardware core index
+- compatible :
+ - "qcom,ispif"
+ - "qcom,ispif-v3.0"
+- reg : offset and length of the register set for the device
+ for the ispif operating in compatible mode.
+- reg-names : should specify relevant names to each reg property defined.
+- interrupts : should contain the ispif interrupt.
+- interrupt-names : should specify relevant names to each interrupts
+ property defined.
+- camss-vdd-supply: phandle to GDSC regulator.
+- mmagic-vdd-supply: phandle to mmagic regulator.
+- vfe0-vdd-supply: phandle to vfe0 regulator.
+- vfe1-vdd-supply: phandle to vfe1 regulator.
+- clocks: list of phandles to the clock controller device and coresponding
+ clock names.
+- clock-names: name of the clocks required for the device used by the consumer.
+- qcom,clock-rates: clock rate in Hz.
+- qcom,clock-control: The valid fields are "NO_SET_RATE", "INIT_RATE" and
+ "SET_RATE". "NO_SET_RATE" the corresponding clock is enabled without setting
+ the rate assuming some other driver has already set it to appropriate rate.
+ "INIT_RATE" clock rate is not queried assuming some other driver has set
+ the clock rate and ispif will set the the clock to this rate.
+ "SET_RATE" clock is enabled and the rate is set to the value specified
+ in the property qcom,clock-rates.
+
+Optional properties:
+- qcom,num-isps: The number of ISPs the ISPIF module is connected to. If not set
+ the default value used is 1
+
+Example:
+
+ qcom,ispif@fda0a000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif";
+ reg = <0xfda0a000 0x300>;
+ reg-names = "ispif";
+ interrupts = <0 55 0>;
+ interrupt-names = "ispif";
+ camss-vdd-supply = <&gdsc_camss_top>;
+ mmagic-vdd-supply = <&gdsc_mmagic_camss>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ vfe1-vdd-supply = <&gdsc_vfe1>;
+ clocks = <&clock_mmss clk_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csi0_clk_src>,
+ <&clock_mmss clk_camss_csi0_clk>,
+ <&clock_mmss clk_camss_csi0rdi_clk>,
+ <&clock_mmss clk_camss_csi0pix_clk>,
+ <&clock_mmss clk_csi1_clk_src>,
+ <&clock_mmss clk_camss_csi1_clk>,
+ <&clock_mmss clk_camss_csi1rdi_clk>,
+ <&clock_mmss clk_camss_csi1pix_clk>,
+ <&clock_mmss clk_csi2_clk_src>,
+ <&clock_mmss clk_camss_csi2_clk>,
+ <&clock_mmss clk_camss_csi2rdi_clk>,
+ <&clock_mmss clk_camss_csi2pix_clk>,
+ <&clock_mmss clk_csi3_clk_src>,
+ <&clock_mmss clk_camss_csi3_clk>,
+ <&clock_mmss clk_camss_csi3rdi_clk>,
+ <&clock_mmss clk_camss_csi3pix_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_camss_vfe0_clk>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_camss_vfe1_clk>,
+ <&clock_mmss clk_camss_csi_vfe1_clk>;
+ clock-names = "ispif_ahb_clk",
+ "csi0_src_clk", "csi0_clk",
+ "csi0_pix_clk", "csi0_rdi_clk",
+ "csi1_src_clk", "csi1_clk",
+ "csi1_pix_clk", "csi1_rdi_clk",
+ "csi2_src_clk", "csi2_clk",
+ "csi2_pix_clk", "csi2_rdi_clk",
+ "csi3_src_clk", "csi3_clk",
+ "csi3_pix_clk", "csi3_rdi_clk",
+ "vfe0_clk_src", "camss_vfe_vfe0_clk", "camss_csi_vfe0_clk",
+ "vfe1_clk_src", "camss_vfe_vfe1_clk", "camss_csi_vfe1_clk";
+ qcom,clock-rates = <0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 0 0 0
+ 0 0 0>;
+ qcom,clock-control = "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE", "NO_SET_RATE";
+
+ };
+
+or
+
+ qcom,ispif@fda0a000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif-v3.0", "qcom,ispif";
+ reg = <0xfda0a000 0x300>;
+ reg-names = "ispif";
+ interrupts = <0 55 0>;
+ interrupt-names = "ispif";
+ qcom,num-isps = <2>
+ vdd-supply = <&gdsc_camss_top>;
+ clocks = <&clock_mmss clk_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csi0_clk_src>,
+ <&clock_mmss clk_camss_csi0_clk>,
+ <&clock_mmss clk_camss_csi0rdi_clk>,
+ <&clock_mmss clk_camss_csi0pix_clk>,
+ <&clock_mmss clk_csi1_clk_src>,
+ <&clock_mmss clk_camss_csi1_clk>,
+ <&clock_mmss clk_camss_csi1rdi_clk>,
+ <&clock_mmss clk_camss_csi1pix_clk>,
+ <&clock_mmss clk_csi2_clk_src>,
+ <&clock_mmss clk_camss_csi2_clk>,
+ <&clock_mmss clk_camss_csi2rdi_clk>,
+ <&clock_mmss clk_camss_csi2pix_clk>,
+ <&clock_mmss clk_csi3_clk_src>,
+ <&clock_mmss clk_camss_csi3_clk>,
+ <&clock_mmss clk_camss_csi3rdi_clk>,
+ <&clock_mmss clk_camss_csi3pix_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_camss_vfe0_clk>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_camss_vfe1_clk>,
+ <&clock_mmss clk_camss_csi_vfe1_clk>;
+ clock-names = "ispif_ahb_clk",
+ "csi0_src_clk", "csi0_clk",
+ "csi0_pix_clk", "csi0_rdi_clk",
+ "csi1_src_clk", "csi1_clk",
+ "csi1_pix_clk", "csi1_rdi_clk",
+ "csi2_src_clk", "csi2_clk",
+ "csi2_pix_clk", "csi2_rdi_clk",
+ "csi3_src_clk", "csi3_clk",
+ "csi3_pix_clk", "csi3_rdi_clk",
+ "vfe0_clk_src", "camss_vfe_vfe0_clk", "camss_csi_vfe0_clk",
+ "vfe1_clk_src", "camss_vfe_vfe1_clk", "camss_csi_vfe1_clk";
+ qcom,clock-rates = <0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 0 0 0
+ 0 0 0>;
+ qcom,clock-control = "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE", "NO_SET_RATE", "NO_SET_RATE";
+
+ };
+
diff --git a/Documentation/devicetree/bindings/media/video/msm-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
new file mode 100644
index 000000000000..39a4bd1601e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-vfe.txt
@@ -0,0 +1,205 @@
+* Qualcomm MSM VFE
+
+Required properties for parent node:
+- compatible :
+ - "qcom,vfe"
+- #address-cells : Number of address related values in the reg field
+- #size-cells : Number of size related values in the reg field
+- ranges: How the register offsets for child translate to parent.
+
+Required properties for child node:
+- cell-index: vfe hardware core index
+- compatible :
+ - "qcom,vfe32"
+ - "qcom,vfe40"
+ - "qcom,vfe44"
+ - "qcom,vfe46"
+ - "qcom,vfe47"
+ - "qcom,vfe48"
+- reg : offset and length of the register set for the device
+ for the vfe operating in compatible mode. For parent node, add union of
+ all registers for both vfe.
+- reg-names : should specify relevant names to each reg property defined.
+ Only needed for child node.
+ - "vfe" - Required.
+ - "vfe_vbif" - Optional for "vfe32". Required for "vfe40".
+- interrupts : should contain the vfe interrupt.
+- interrupt-names : should specify relevant names to each interrupts
+ property defined.
+ - "vfe" - Required.
+- vdd-supply: phandle to GDSC regulator controlling VFE core.
+- qos-entries: number of QoS registers to program
+- qos-regs: relative address offsets of QoS registers
+- qos-settings: QoS values to be written to QoS registers
+- vbif-entries - number of VBIF registers to program (optional)
+- vbif-regs: relative address offsets of VBIF registers (optional)
+- vbif-settings: VBIF values to be written to VBIF registers (optional)
+- ds-entries: number danger/safe registers to program (optional)
+- ds-regs: relative address offsets of danger/safe registers (optional)
+- ds-settings: danger/safe values to be written to registers (optional)
+ NOTE: For all qos*, vbif*, ds* parameters, same SoC can have different
+ hardware versions with different entries/registers/settings. They can be
+ specified by adding version to the string e.g. qos-v2-settings. Also
+ different SoC can have same hardware version and still different QOS, VBIF,
+ and DS parameters. In this case they are exported if separate SoC version
+ specific dts files.
+- max-svs-clk: svs rate of the VFE clock in Hertz.
+- max-nominal-clk: nominal rate of the VFE clock in Hertz.
+- max-turbo-clk: turbo/high rate of the VFE clock in Hertz.
+
+Example:
+
+vfe0: qcom,vfe0@fda10000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe44";
+ reg = <0xfda10000 0x1000>;
+ <0xfda40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 57 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe>;
+ qos-entries = <8>;
+ qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+ 0x2dc 0x2e0>;
+ qos-settings = <0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
+ 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
+ 0xaaaaaaaa 0x0002aaaa>;
+ qos-v2-settings = <0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0x0001aaa9>;
+ qos-v3-settings = <0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0x0001aaa9>;
+ vbif-entries = <17>;
+ vbif-regs = <0x4 0xb0 0xb4 0xb8 0xc0 0xc4 0xc8 0xd0
+ 0xd4 0xd8 0xdc 0xf0 0x178 0x17c 0x124 0x160
+ 0x164>;
+ vbif-settings = <0x1 0x01010101 0x01010101 0x10010110
+ 0x10101010 0x10101010 0x10101010 0x00001010
+ 0x00001010 0x00000707 0x00000707 0x00000030
+ 0x00000fff 0x0fff0fff 0x00000001 0x22222222
+ 0x00002222>;
+ vbif-v2-entries = <16>;
+ vbif-v2-regs = <0x4 0xb0 0xb4 0xb8 0xc0 0xc4 0xc8 0xd0
+ 0xd4 0xd8 0xf0 0x178 0x17c 0x124 0x160
+ 0x164>;
+ vbif-v2-settings = <0x1 0x10101010 0x10101010 0x10101010
+ 0x10101010 0x10101010 0x10101010 0x00000010
+ 0x00000010 0x00000707 0x00000010 0x00000fff
+ 0x0fff0fff 0x00000003 0x22222222 0x00002222>;
+ ds-entries = <17>;
+ ds-regs = <0x988 0x98c 0x990 0x994 0x998
+ 0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+ 0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+ ds-settings = <0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x00000103>;
+ max-clk-svs = <300000000>;
+ max-clk-nominal = <465000000>;
+ max-clk-turbo = <600000000>;
+};
+
+vfe1: qcom,vfe1@fda14000 {
+ cell-index = <1>;
+ compatible = "qcom,vfe44";
+ reg = <0xfda14000 0x1000>;
+ <0xfda40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 58 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe>;
+ qos-entries = <8>;
+ qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+ 0x2dc 0x2e0>;
+ qos-settings = <0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
+ 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
+ 0xaaaaaaaa 0x0002aaaa>;
+ qos-v2-settings = <0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0x0001aaa9>;
+ qos-v3-settings = <0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0xaaa9aaa9 0xaaa9aaa9
+ 0xaaa9aaa9 0x0001aaa9>;
+ vbif-entries = <17>;
+ vbif-regs = <0x4 0xb0 0xb4 0xb8 0xc0 0xc4 0xc8 0xd0
+ 0xd4 0xd8 0xdc 0xf0 0x178 0x17c 0x124 0x160
+ 0x164>;
+ vbif-settings = <0x1 0x01010101 0x01010101 0x10010110
+ 0x10101010 0x10101010 0x10101010 0x00001010
+ 0x00001010 0x00000707 0x00000707 0x00000030
+ 0x00000fff 0x0fff0fff 0x00000001 0x22222222
+ 0x00002222>;
+ vbif-v2-entries = <16>;
+ vbif-v2-regs = <0x4 0xb0 0xb4 0xb8 0xc0 0xc4 0xc8 0xd0
+ 0xd4 0xd8 0xf0 0x178 0x17c 0x124 0x160
+ 0x164>;
+ vbif-v2-settings = <0x1 0x10101010 0x10101010 0x10101010
+ 0x10101010 0x10101010 0x10101010 0x00000010
+ 0x00000010 0x00000707 0x00000010 0x00000fff
+ 0x0fff0fff 0x00000003 0x22222222 0x00002222>;
+ ds-entries = <17>;
+ ds-regs = <0x988 0x98c 0x990 0x994 0x998
+ 0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+ 0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+ ds-settings = <0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x44441111 0x44441111
+ 0x44441111 0x00000103>;
+ max-clk-svs = <300000000>;
+ max-clk-nominal = <465000000>;
+ max-clk-turbo = <600000000>;
+};
+
+qcom,vfe {
+ compatible = "qcom,vfe";
+ num_child = <2>;
+};
+
+In version specific file one needs to move only entries that differ between
+SoC versions with same VFE HW version:
+
+ &vfe0 {
+ qos-entries = <8>;
+ qos-regs = <0x378 0x37C 0x380 0x384 0x388 0x38C
+ 0x390 0x394>;
+ qos-settings = <0xAAA9AAA9
+ 0xAAA9AAA9
+ 0xAAA9AAA9
+ 0xAAA9AAA9
+ 0xAAA9AAA9
+ 0xAAA9AAA9
+ 0xAAA9AAA9
+ 0x0001AAA9>;
+ vbif-entries = <1>;
+ vbif-regs = <0x124>;
+ vbif-settings = <0x3>;
+ ds-entries = <17>;
+ ds-regs = <0xBD8 0xBDC 0xBE0 0xBE4 0xBE8
+ 0xBEC 0xBF0 0xBF4 0xBF8 0xBFC 0xC00
+ 0xC04 0xC08 0xC0C 0xC10 0xC14 0xC18>;
+ ds-settings = <0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x44441111
+ 0x00000103>;
+ max-clk-svs = <300000000>;
+ max-clk-nominal = <465000000>;
+ max-clk-turbo = <600000000>;
+ };
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index b4b74e98092b..c8f7c6c4391e 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -53,6 +53,8 @@ memory allocation over a PCIe bridge
configures embedded pipe filtering rules
- qcom,skip-uc-pipe-reset: Boolean context flag to indicate whether
a pipe reset via the IPA uC is required
+- qcom,ipa-wdi2: Boolean context flag to indicate whether
+ using wdi-2.0 or not
- qcom,use-dma-zone: Boolean context flag to indicate whether memory
allocations controlled by IPA driver that do not
specify a struct device * should use GFP_DMA to
diff --git a/Documentation/devicetree/bindings/pwm/pwm-qpnp.txt b/Documentation/devicetree/bindings/pwm/pwm-qpnp.txt
new file mode 100644
index 000000000000..52a4bc81b4c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-qpnp.txt
@@ -0,0 +1,211 @@
+Qualcomm Technologies, Inc. QPNP PWM/LPG controller
+
+qpnp-pwm driver supports Pulse Width Module (PWM) functionality. PWM feature is
+used in range of applications such as varying Display brightness, LED dimming,
+etc. QTI PMICs have a physical device called Light Pulse Generator (LPG). In
+addition to support PWM functionality, the LPG module provides a rich set of
+user defined PWM pattern configurations, such as sawtooth, linear up, linear
+down, triangular patterns etc. The PWM patterns are used in applications such as
+charger driver where the driver uses these patterns to indicate various states
+of charging.
+
+Required device bindings:
+- compatible: should be "qcom,qpnp-pwm"
+- reg: Offset and length of the controller's LPG channel register.
+- reg-names: Name for the above register.
+ "qpnp-lpg-channel-base" = physical base address of the
+ controller's LPG channel register.
+- qcom,channel-id: channel Id for the PWM.
+- qcom,supported-sizes: Supported PWM sizes.
+ Following three pwm sizes lists are supported by PWM/LPG controllers.
+ <6>, <9>;
+ <7>, <8>;
+ <6>, <7>, <9>;
+- qcom,ramp-index: Ramp index in LUT ramp control register.
+ Each LPG has an index in the LUT ramp control register.
+ One exception is that, if LPG does not support LUT mode
+ and supports only PWM mode then there is no need to
+ provide the ramp-index.
+
+Optional device bindings:
+- qcom,force-pwm-size: For certain LPG channels, PWM size can be forced.
+ Possible values 6, 7, 8 and 9.
+- qcom,channel-owner: A string value to supply owner information.
+- qcom,mode-select: 0 = PWM mode
+ 1 = LPG mode
+- qcom,lpg-dtest-line: indicates which DTEST line to be configured for LPG
+ output. Possible values are 1, 2, 3 and 4.
+- qcom,dtest-output: indicates the output configuration for DTEST line.
+ 0 = Disabled
+ 1 = LPG output low
+ 2 = LPG output high
+ 3,4,5 = DTEST line specific configuration
+ 6,7 = Not used
+If this binding is specified along with the required bindings of PWM/LPG then
+in addition to configure PWM/LPG the qpnp-pwm driver also enables the feature
+at the probe time. In the case where the binding is not specified the qpnp-pwm
+driver does not enable the feature. Also, it is considered an error to specify
+a particular mode using this binding but not the respective feature subnode.
+
+All PWM devices support both PWM and LPG features within the same device.
+To support each feature, there are some required and optional bindings passed
+through device tree.
+
+The PWM device can enable one feature (either PWM or LPG) at any given time.
+Therefore, the qpnp-pwm driver applies the last PWM or LPG feature configuration
+and enables that feature.
+
+Required bindings to support PWM feature:
+- qcom,period: PWM period time in microseconds.
+- qcom,duty: PWM duty time in microseconds.
+- label: "pwm"
+
+Required bindings to support LPG feature:
+The following bindings are needed to configure LPG mode, where a list of
+duty cycle percentages is populated. The size of the list cannot exceed
+the size of the LPG look-up table.
+
+- reg: Offset and length of LPG look-up table (LUT). The LPG look-up table is a
+ contiguous address space that is populated with PWM values.
+ The size of PWM value is 9 bit and the size of each
+ entry of the table is 8 bit. Thus, two entries are used
+ to fill each PWM value. The lower entry is used for PWM
+ LSB byte and higher entry is used for PWM MSB bit.
+- reg-names: Name for the above register.
+ "qpnp-lpg-lut-base" = physical base address of LPG LUT.
+- qcom,period: PWM period time in microseconds.
+- qcom,duty-percents: List of entries for look-up table
+- cell-index: Index of look-up table that should be used to start
+ filling up the duty-pct list. start-idx + size of list
+ cannot exceed the size of look-up table.
+- label: "lpg"
+
+
+Optional bindings to support LPG feature:
+- qcom,ramp-step-duration: Time (in ms) to wait before loading next entry of LUT
+- qcom,lpg-lut-pause-hi: Time (in ms) to wait once pattern reaches to hi
+ index.
+- qcom,lpg-lut-pause-lo: Time (in ms) to wait once pattern reaches to lo
+ index.
+- qcom,lpg-lut-ramp-direction: 1 = Start the pattern from lo index to hi index.
+ 0 = Start the pattern from hi index to lo index.
+- qcom,lpg-lut-pattern-repeat: 1 = Repeat the pattern after the pause once it
+ reaches to last duty cycle.
+ 0 = Do not repeat the pattern.
+- qcom,lpg-lut-ramp-toggle: 1 = Toggle the direction of the pattern.
+ 0 = Do not toggle the direction.
+- qcom,lpg-lut-enable-pause-hi: 1 = Enable pause time at hi index.
+ 0 = Disable pause time at hi index.
+- qcom,lpg-lut-enable-pause-lo: 1 = Enable pause time at lo index.
+ 0 = Disable pause time at lo index.
+
+
+Example:
+ qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,pm8941@1 {
+ spmi-slave-container;
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pwm@b100 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb100 0x100>, <0xb040 0x80>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <0>;
+ qcom,supported-sizes = <6>, <7>, <9>;
+ qcom,ramp-index = <0>;
+ status = "okay";
+ };
+
+ pwm@b200 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb200 0x100>, <0xb040 0x80>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <1>;
+ qcom,supported-sizes = <6>, <7>, <9>;
+ qcom,ramp-index = <1>;
+ qcom,force-pwm-size = <9>;
+ qcom,period = <6000000>;
+ status = "okay";
+
+ qcom,pwm {
+ qcom,duty = <4000000>;
+ label = "pwm";
+ };
+ };
+
+ pwm@b500 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-pwm"
+ reg = <0xb500 0x100>, <0xb040 0x80>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <4>;
+ qcom,supported-sizes = <6>, <7>, <9>;
+ qcom,ramp-index = <4>;
+ qcom,period = <6000000>;
+ qcom,mode-select = <0>;
+ qcom,channel-owner = "RGB-led";
+ status = "okay";
+
+ qcom,pwm {
+ qcom,duty = <4000000>;
+ label = "pwm";
+ };
+
+ qcom,lpg {
+ qcom,duty-percents = <1 14 28 42 56 84 100
+ 100 84 56 42 28 14 1>;
+ cell-index = <0>;
+ qcom,ramp-step-duration = <20>;
+ label = "lpg";
+ };
+ };
+
+ pwm@b300 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xb200 0x100>, <0xb040 0x80>;
+ reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+ qcom,channel-id = <2>;
+ qcom,supported-sizes = <6>, <7>, <9>;
+ qcom,ramp-index = <1>;
+ qcom,force-pwm-size = <9>;
+ qcom,period = <6000000>;
+ qcom,lpg-dtest-line = <3>;
+ qcom,dtest-output = <1>;
+ status = "okay";
+
+ qcom,pwm {
+ qcom,duty = <4000000>;
+ label = "pwm";
+ };
+ };
+ };
+ };
+
+There are couple of ways to configure PWM device channels as shown in above
+example,
+1. The PWM device channel #0 is configured with only required device bindings.
+In this case, the qpnp-pwm driver does not configure any mode by default.
+
+2. The qpnp-pwm driver configures PWM device channel #1 with PWM feature
+configuration, but does not enable the channel since "qcom,mode-select" binding
+is not specified in the devicetree.
+
+3. Both the PWM and LPG configurations are provided for PWM device channel #4.
+The qpnp-pwm driver configures both the modes, but enables PWM mode at the probe
+time. It also sets the channel owner information for the channel.
+
+4. This configuration is pretty similar to #2 above except in this case channel
+#3 is configured for PWM mode. Also it's DTEST3 line is configured to output
+LPG OUT low.
diff --git a/Documentation/devicetree/bindings/soc/qcom/avtimer.txt b/Documentation/devicetree/bindings/soc/qcom/avtimer.txt
new file mode 100644
index 000000000000..157f79b2b07a
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/avtimer.txt
@@ -0,0 +1,26 @@
+* avtimer
+
+Avtimer provides an interface for clients to enable avtimer block
+on qdsp6. 64 bit AVtimer exposed by qdsp6 is used for audio and video
+stream synchronization during capture and playback usecases.
+
+Required properties:
+- reg : physical address and length of avtimer register
+- reg-names : AVtimer register name
+ Required register resource entries are:
+ "avtimer_lsb_addr" : AVtimer lsb physical address
+ "avtimer_msb_addr" : AVtimer msb physical address
+- compatible : Must be "qcom,avtimer"
+
+Optional properties:
+- clk-div : The clk is at 27MHz and hence ticks are to be
+ divided by 27 to achive the msec value.
+
+Example:
+ qcom,avtimer@90f7000 {
+ compatible = "qcom,avtimer";
+ reg = <0x90f700c 0x4>,
+ <0x90f7010 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ qcom,clk-div = <27>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index d34bc841863d..cb92feb9a613 100755
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -87,6 +87,14 @@ Required properties:
- compatible : "qcom,msm-stub-codec"
+* msm-hdmi-dba-codec-rx
+
+Required properties:
+
+ - compatible : "qcom,msm-hdmi-dba-codec-rx"
+ - qcom,dba-bridge-chip: String info to indicate which bridge-chip
+ is used for HDMI using DBA.
+
* msm-dai-fe
Required properties:
@@ -1935,3 +1943,115 @@ Example:
asoc-codec = <&stub_codec>;
asoc-codec-names = "msm-stub-codec.1";
};
+
+* MSMCOBALT ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,msmcobalt-asoc-snd-tasha"
+- qcom,model : The user-visible name of this sound card.
+- qcom,tasha-mclk-clk-freq : MCLK frequency value for tasha codec
+- qcom,audio-routing : A list of the connections between audio components.
+- asoc-platform: This is phandle list containing the references to platform device
+ nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+ the platform names should match to that of the phandle order
+ given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+ that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+ cpu dai names should match to that of the phandle order given
+ in "asoc-cpu". The cpu names are in the form of "%s.%d" form,
+ where the id (%d) field represents the back-end AFE port id that
+ this CPU dai is associated with.
+- asoc-codec: This is phandle list containing the references to codec dai device
+ nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+ codec dai names should match to that of the phandle order given
+ in "asoc-codec".
+Optional properties:
+- qcom,mbhc-audio-jack-type : String to indicate the jack type on the hardware.
+ Possible Values:
+ 4-pole-jack : Jack on the hardware is 4-pole.
+ 5-pole-jack : Jack on the hardware is 5-pole.
+ 6-pole-jack : Jack on the hardware is 6-pole.
+- clock-names : clock name defined for external clock.
+- clocks : external clock defined for codec clock.
+- qcom,hph-en1-gpio : GPIO to enable HiFi amplifiers.
+- qcom,hph-en0-gpio : GPIO to enable HiFi audio route to headset.
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+
+Example:
+
+ sound-9335 {
+ compatible = "qcom,msmcobalt-asoc-snd";
+ qcom,model = "msmcobalt-tasha-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "AIF4 MAD", "MCLK",
+ "ultrasound amp", "LINEOUT1",
+ "ultrasound amp", "LINEOUT3",
+ "AMIC1", "MIC BIAS1 Internal1",
+ "MIC BIAS1 Internal1", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic",
+ "DMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic1",
+ "DMIC2", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic2",
+ "DMIC3", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic3",
+ "DMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic4",
+ "DMIC5", "MIC BIAS4 External",
+ "MIC BIAS4 External", "Digital Mic5",
+ "DMIC6", "MIC BIAS4 External",
+ "MIC BIAS4 External", "Digital Mic6";
+
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,tasha-mclk-clk-freq = <9600000>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-cpe-lsm",
+ "msm-compr-dsp";
+ asoc-cpu = <&dai_hdmi>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+ <&afe_proxy_tx>, <&incall_record_rx>,
+ <&incall_record_tx>, <&incall_music_rx>,
+ <&incall_music_2_rx>, <&sb_5_rx>;
+ asoc-cpu-names = "msm-dai-q6-hdmi.8",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224",
+ "msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394";
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+ <&wsa881x_213>, <&wsa881x_214>;
+ qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
+ "SpkrRight", "SpkrLeft";
+ };
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index 048d00057ea9..cccdb281a31d 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -175,6 +175,7 @@ Optional properties:
- 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.
+ - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0
Example:
qusb_phy: qusb@f9b39000 {
diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
new file mode 100644
index 000000000000..82302c735cbb
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+
+ pcm0: qcom,msm-pcm {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
+ };
+
+ routing: qcom,msm-pcm-routing {
+ compatible = "qcom,msm-pcm-routing";
+ };
+
+ compr: qcom,msm-compr-dsp {
+ compatible = "qcom,msm-compr-dsp";
+ };
+
+ pcm1: qcom,msm-pcm-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <1>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "regular";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ compress: qcom,msm-compress-dsp {
+ compatible = "qcom,msm-compress-dsp";
+ };
+
+ voip: qcom,msm-voip-dsp {
+ compatible = "qcom,msm-voip-dsp";
+ };
+
+ voice: qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ qcom,destroy-cvd;
+ qcom,vote-bms;
+ };
+
+ stub_codec: qcom,msm-stub-codec {
+ compatible = "qcom,msm-stub-codec";
+ };
+
+ qcom,msm-dai-fe {
+ compatible = "qcom,msm-dai-fe";
+ };
+
+ afe: qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
+ dai_hdmi: qcom,msm-dai-q6-hdmi {
+ compatible = "qcom,msm-dai-q6-hdmi";
+ qcom,msm-dai-q6-dev-id = <8>;
+ };
+
+ loopback: qcom,msm-pcm-loopback {
+ compatible = "qcom,msm-pcm-loopback";
+ };
+
+ qcom,msm-dai-mi2s {
+ compatible = "qcom,msm-dai-mi2s";
+ dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <0>;
+ qcom,msm-mi2s-rx-lines = <3>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s1: qcom,msm-dai-q6-mi2s-sec {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <1>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <0>;
+ };
+
+ dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <2>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+
+ dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <3>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s4: qcom,msm-dai-q6-mi2s-quin {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <5>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <2>;
+ };
+
+ dai_mi2s5: qcom,msm-dai-q6-mi2s-senary {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <6>;
+ qcom,msm-mi2s-rx-lines = <0>;
+ qcom,msm-mi2s-tx-lines = <3>;
+ };
+ };
+
+ lsm: qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
+ qcom,msm-dai-q6 {
+ compatible = "qcom,msm-dai-q6";
+ sb_0_rx: qcom,msm-dai-q6-sb-0-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16384>;
+ };
+
+ sb_0_tx: qcom,msm-dai-q6-sb-0-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16385>;
+ };
+
+ sb_1_rx: qcom,msm-dai-q6-sb-1-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16386>;
+ };
+
+ sb_1_tx: qcom,msm-dai-q6-sb-1-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16387>;
+ };
+
+ sb_2_rx: qcom,msm-dai-q6-sb-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16388>;
+ };
+
+ sb_2_tx: qcom,msm-dai-q6-sb-2-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16389>;
+ };
+
+
+ sb_3_rx: qcom,msm-dai-q6-sb-3-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16390>;
+ };
+
+ sb_3_tx: qcom,msm-dai-q6-sb-3-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16391>;
+ };
+
+ sb_4_rx: qcom,msm-dai-q6-sb-4-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16392>;
+ };
+
+ sb_4_tx: qcom,msm-dai-q6-sb-4-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16393>;
+ };
+
+ sb_5_tx: qcom,msm-dai-q6-sb-5-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16395>;
+ };
+
+ sb_5_rx: qcom,msm-dai-q6-sb-5-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16394>;
+ };
+
+ bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12288>;
+ };
+
+ bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12289>;
+ };
+
+ int_fm_rx: qcom,msm-dai-q6-int-fm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12292>;
+ };
+
+ int_fm_tx: qcom,msm-dai-q6-int-fm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12293>;
+ };
+
+ afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
+
+ incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
+
+ incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32770>;
+ };
+ };
+
+ hostless: qcom,msm-pcm-hostless {
+ compatible = "qcom,msm-pcm-hostless";
+ };
+
+ dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "primary";
+ };
+
+ hdmi_dba: qcom,msm-hdmi-dba-codec-rx {
+ compatible = "qcom,msm-hdmi-dba-codec-rx";
+ qcom,dba-bridge-chip = "adv7533";
+ };
+
+ msm_audio_ion: qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,smmu-version = <1>;
+ qcom,smmu-enabled;
+ iommus = <&adsp_io 1>;
+ };
+
+ qcom,msm-adsp-loader {
+ status = "ok";
+ compatible = "qcom,adsp-loader";
+ qcom,adsp-state = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pmcobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmcobalt.dtsi
index 318197221357..40ae5fc03472 100644
--- a/arch/arm/boot/dts/qcom/msm-pmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmcobalt.dtsi
@@ -234,6 +234,22 @@
compatible = "qcom,qpnp-coincell";
reg = <0x2800 0x100>;
};
+
+ pmcobalt_rtc: qcom,pmcobalt_rtc {
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pmcobalt_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+ qcom,pmcobalt_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+ };
+ };
};
qcom,pmcobalt@1 {
diff --git a/arch/arm/boot/dts/qcom/msm8996-ipcrouter.dtsi b/arch/arm/boot/dts/qcom/msm8996-ipcrouter.dtsi
index a443f90e4cb8..a034754f8719 100644
--- a/arch/arm/boot/dts/qcom/msm8996-ipcrouter.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-ipcrouter.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014, 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
@@ -45,4 +45,14 @@
qcom,xprt-version = <1>;
qcom,fragmented-data;
};
+
+ qcom,ipc_router_external_modem_xprt2 {
+ compatible = "qcom,ipc_router_mhi_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,out-chan-id = <34>;
+ qcom,in-chan-id = <35>;
+ qcom,xprt-remote = "external-modem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <3>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 3672d6f313cd..3a5b55848d53 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -2086,6 +2086,7 @@
0x00 0x18>;
phy_type= "utmi";
qcom,phy-clk-scheme = "cmos";
+ qcom,major-rev = <1>;
clocks = <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>,
<&clock_gcc clk_gcc_qusb2phy_prim_reset>,
@@ -2122,6 +2123,7 @@
0x00 0x18>;
phy_type = "utmi";
qcom,phy-clk-scheme = "cmos";
+ qcom,major-rev = <1>;
qcom,hold-reset;
clocks = <&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi
new file mode 100644
index 000000000000..0f8b0908816b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msmcobalt-wsa881x.dtsi"
+
+&msm_audio_ion {
+ qcom,smmu-version = <2>;
+ iommus = <&lpass_q6_smmu 1>;
+};
+
+&soc {
+ qcom,avtimer@170f7000 {
+ compatible = "qcom,avtimer";
+ reg = <0x170f700c 0x4>,
+ <0x170f7010 0x4>;
+ reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+ qcom,clk-div = <27>;
+ };
+
+ sound-9335 {
+ compatible = "qcom,msmcobalt-asoc-snd-tasha";
+ qcom,model = "msmcobalt-tasha-snd-card";
+
+ qcom,audio-routing =
+ "AIF4 VI", "MCLK",
+ "RX_BIAS", "MCLK",
+ "MADINPUT", "MCLK",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "AMIC3", "MIC BIAS2",
+ "MIC BIAS2", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2",
+ "MIC BIAS2", "ANCLeft Headset Mic",
+ "AMIC5", "MIC BIAS3",
+ "MIC BIAS3", "Handset Mic",
+ "AMIC6", "MIC BIAS4",
+ "MIC BIAS4", "Analog Mic6",
+ "DMIC0", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic0",
+ "DMIC1", "MIC BIAS1",
+ "MIC BIAS1", "Digital Mic1",
+ "DMIC2", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic2",
+ "DMIC3", "MIC BIAS3",
+ "MIC BIAS3", "Digital Mic3",
+ "DMIC4", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic4",
+ "DMIC5", "MIC BIAS4",
+ "MIC BIAS4", "Digital Mic5",
+ "SpkrLeft IN", "SPK1 OUT",
+ "SpkrRight IN", "SPK2 OUT";
+
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,tasha-mclk-clk-freq = <9600000>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-cpe-lsm",
+ "msm-compr-dsp";
+ asoc-cpu = <&dai_hdmi>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+ <&afe_proxy_tx>, <&incall_record_rx>,
+ <&incall_record_tx>, <&incall_music_rx>,
+ <&incall_music_2_rx>, <&sb_5_rx>;
+ asoc-cpu-names = "msm-dai-q6-hdmi.8",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224",
+ "msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394";
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ };
+
+ cpe: qcom,msm-cpe-lsm {
+ compatible = "qcom,msm-cpe-lsm";
+ };
+
+ wcd9xxx_intc: wcd9xxx-irq {
+ status = "ok";
+ compatible = "qcom,wcd9xxx-irq";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-names = "cdc-int";
+ };
+
+ clock_audio: audio_ext_clk {
+ status = "ok";
+ compatible = "qcom,audio-ref-clk";
+ clock-names = "osr_clk";
+ qcom,node_has_rpm_clock;
+ #clock-cells = <1>;
+ };
+};
+
+&slim_msm {
+ msm_dai_slim {
+ compatible = "qcom,msm-dai-slim";
+ elemental-addr = [ff ff ff fe 17 02];
+ };
+
+ tasha_codec {
+ compatible = "qcom,tasha-slim-pgd";
+ elemental-addr = [00 01 A0 01 17 02];
+
+ interrupt-parent = <&wcd9xxx_intc>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ 17 18 19 20 21 22 23 24 25 26 27 28 29
+ 30>;
+
+ qcom,cdc-reset-gpio = <&tlmm 64 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&cdc_reset_active>;
+ pinctrl-1 = <&cdc_reset_sleep>;
+
+ cdc-vdd-buck-supply = <&pmcobalt_s4>;
+ qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-buck-current = <650000>;
+
+ cdc-buck-sido-supply = <&pmcobalt_s4>;
+ qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+ qcom,cdc-buck-sido-current = <250000>;
+
+ cdc-vdd-tx-h-supply = <&pmcobalt_s4>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <25000>;
+
+ cdc-vdd-rx-h-supply = <&pmcobalt_s4>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <25000>;
+
+ cdc-vddpx-1-supply = <&pmcobalt_s4>;
+ qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+ qcom,cdc-vddpx-1-current = <10000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-buck-sido",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1";
+
+ qcom,cdc-micbias1-mv = <1800>;
+ qcom,cdc-micbias2-mv = <1800>;
+ qcom,cdc-micbias3-mv = <1800>;
+ qcom,cdc-micbias4-mv = <1800>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+ qcom,cdc-slim-ifd = "tasha-slim-ifd";
+ qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 01 17 02];
+ qcom,cdc-dmic-sample-rate = <4800000>;
+ qcom,cdc-mad-dmic-rate = <600000>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
index c6d6666f66a0..ada4500d432e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
@@ -164,4 +164,236 @@
qcom,dup-frame-indicator-off = <70>;
};
};
+
+ qcom,ispif@ca31000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif-v3.0", "qcom,ispif";
+ reg = <0xca31000 0xc00>,
+ <0xca00020 0x4>;
+ reg-names = "ispif", "csi_clk_mux";
+ interrupts = <0 309 0>;
+ interrupt-names = "ispif";
+ qcom,num-isps = <0x2>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ vfe1-vdd-supply = <&gdsc_vfe1>;
+ qcom,vdd-names = "camss-vdd", "vfe0-vdd",
+ "vfe1-vdd";
+ clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_csi0_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi0_clk>,
+ <&clock_mmss clk_mmss_camss_csi0rdi_clk>,
+ <&clock_mmss clk_mmss_camss_csi0pix_clk>,
+ <&clock_mmss clk_csi1_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi1_clk>,
+ <&clock_mmss clk_mmss_camss_csi1rdi_clk>,
+ <&clock_mmss clk_mmss_camss_csi1pix_clk>,
+ <&clock_mmss clk_csi2_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi2_clk>,
+ <&clock_mmss clk_mmss_camss_csi2rdi_clk>,
+ <&clock_mmss clk_mmss_camss_csi2pix_clk>,
+ <&clock_mmss clk_csi3_clk_src>,
+ <&clock_mmss clk_mmss_camss_csi3_clk>,
+ <&clock_mmss clk_mmss_camss_csi3rdi_clk>,
+ <&clock_mmss clk_mmss_camss_csi3pix_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_mmss_camss_vfe0_clk>,
+ <&clock_mmss clk_mmss_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_mmss_camss_vfe1_clk>,
+ <&clock_mmss clk_mmss_camss_csi_vfe1_clk>;
+ clock-names = "camss_top_ahb_clk",
+ "camss_ahb_clk", "ispif_ahb_clk",
+ "csi0_src_clk", "csi0_clk",
+ "csi0_pix_clk", "csi0_rdi_clk",
+ "csi1_src_clk", "csi1_clk",
+ "csi1_pix_clk", "csi1_rdi_clk",
+ "csi2_src_clk", "csi2_clk",
+ "csi2_pix_clk", "csi2_rdi_clk",
+ "csi3_src_clk", "csi3_clk",
+ "csi3_pix_clk", "csi3_rdi_clk",
+ "vfe0_clk_src", "camss_vfe_vfe0_clk",
+ "camss_csi_vfe0_clk",
+ "vfe1_clk_src", "camss_vfe_vfe1_clk",
+ "camss_csi_vfe1_clk";
+ qcom,clock-rates = <0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0 0
+ 0 0 0
+ 0 0 0>;
+ qcom,clock-control = "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "INIT_RATE",
+ "NO_SET_RATE", "NO_SET_RATE";
+ status = "disabled";
+ };
+
+ vfe0: qcom,vfe0@ca10000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe48";
+ reg = <0xca10000 0x4000>,
+ <0xca40000 0x3000>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 314 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe0>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
+ clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_mmss_camss_vfe0_clk>,
+ <&clock_mmss clk_mmss_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_mmss_camss_vfe0_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_vfe_vbif_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_mmss_camss_vfe_vbif_axi_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
+ clock-names = "camss_top_ahb_clk" , "camss_ahb_clk",
+ "vfe_clk_src", "camss_vfe_clk",
+ "camss_csi_vfe_clk",
+ "vfe_ahb_clk", "vfe_vbif_ahb_clk",
+ "vfe_stream_clk", "vfe_vbif_axi_clk",
+ "mmss_smmu_axi_clk";
+ qcom,clock-rates = <0 0 384000000 0 0 0 0 0 0 0
+ 0 0 576000000 0 0 0 0 0 0 0
+ 0 0 600000000 0 0 0 0 0 0 0>;
+ status = "disabled";
+ qos-entries = <8>;
+ qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
+ 0x41c 0x420>;
+ qos-settings = <0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9>;
+ vbif-entries = <3>;
+ vbif-regs = <0x124 0xac 0xd0>;
+ vbif-settings = <0x3 0x40 0x1010>;
+ ds-entries = <17>;
+ ds-regs = <0x424 0x428 0x42c 0x430 0x434
+ 0x438 0x43c 0x440 0x444 0x448 0x44c
+ 0x450 0x454 0x458 0x45c 0x460 0x464>;
+ ds-settings = <0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0x40000103>;
+ qcom,msm-bus,name = "msm_camera_vfe";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <29 512 0 0>,
+ <29 512 100000000 100000000>;
+ qcom,msm-bus-vector-dyn-vote;
+ };
+
+ vfe1: qcom,vfe1@ca14000 {
+ cell-index = <1>;
+ compatible = "qcom,vfe48";
+ reg = <0xca14000 0x4000>,
+ <0xca40000 0x3000>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 315 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe1>;
+ camss-vdd-supply = <&gdsc_camss_top>;
+ smmu-vdd-supply = <&gdsc_bimc_smmu>;
+ qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
+ clocks = <&clock_mmss clk_mmss_camss_top_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_ahb_clk>,
+ <&clock_mmss clk_vfe1_clk_src>,
+ <&clock_mmss clk_mmss_camss_vfe1_clk>,
+ <&clock_mmss clk_mmss_camss_csi_vfe1_clk>,
+ <&clock_mmss clk_mmss_camss_vfe1_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_vfe_vbif_ahb_clk>,
+ <&clock_mmss clk_mmss_camss_vfe1_stream_clk>,
+ <&clock_mmss clk_mmss_camss_vfe_vbif_axi_clk>,
+ <&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
+ clock-names = "camss_top_ahb_clk" , "camss_ahb_clk",
+ "vfe_clk_src", "camss_vfe_clk",
+ "camss_csi_vfe_clk",
+ "vfe_ahb_clk", "vfe_vbif_ahb_clk",
+ "vfe_stream_clk", "vfe_vbif_axi_clk",
+ "mmss_smmu_axi_clk";
+ qcom,clock-rates = <0 0 384000000 0 0 0 0 0 0 0
+ 0 0 576000000 0 0 0 0 0 0 0
+ 0 0 600000000 0 0 0 0 0 0 0>;
+ status = "disabled";
+ qos-entries = <8>;
+ qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
+ 0x41c 0x420>;
+ qos-settings = <0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9
+ 0xaaa9aaa9>;
+ vbif-entries = <3>;
+ vbif-regs = <0x124 0xac 0xd0>;
+ vbif-settings = <0x3 0x40 0x1010>;
+ ds-entries = <17>;
+ ds-regs = <0x424 0x428 0x42c 0x430 0x434
+ 0x438 0x43c 0x440 0x444 0x448 0x44c
+ 0x450 0x454 0x458 0x45c 0x460 0x464>;
+ ds-settings = <0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0xcccc0011
+ 0x40000103>;
+ qcom,msm-bus,name = "msm_camera_vfe";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <29 512 0 0>,
+ <29 512 100000000 100000000>;
+ qcom,msm-bus-vector-dyn-vote;
+ };
+
+ qcom,vfe {
+ compatible = "qcom,vfe";
+ num_child = <2>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
index 14791077a5bc..bada543c9a2f 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
@@ -11,3 +11,27 @@
*/
#include "msmcobalt-pinctrl.dtsi"
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pmcobalt_s3>;
+ qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l17_pin_ctrl>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
+
+ qca,bt-vdd-io-voltage-level = <1350000 1350000>;
+ qca,bt-vdd-xtal-voltage-level = <2050000 2050000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-ldo-voltage-level = <1300000 1300000>;
+ qca,bt-vdd-pa-voltage-level = <3300000 3300000>;
+ qca,bt-chip-pwd-voltage-level = <3600000 3600000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <0>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <0>; /* LPM/PFM */
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
index 14791077a5bc..139ca5c8fec8 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
@@ -11,3 +11,27 @@
*/
#include "msmcobalt-pinctrl.dtsi"
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pmcobalt_s3>;
+ qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l17_pin_ctrl>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
+
+ qca,bt-vdd-io-voltage-level = <1350000 1350000>;
+ qca,bt-vdd-xtal-voltage-level = <2050000 2050000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-ldo-voltage-level = <1300000 1300000>;
+ qca,bt-vdd-pa-voltage-level = <3300000 3300000>;
+ qca,bt-chip-pwd-voltage-level = <3600000 3600000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <0>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <0>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <0>; /* LPM/PFM */
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 28e459c03b3a..0185570a96bd 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -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
@@ -32,5 +32,103 @@
bias-disable;
};
};
+
+ wcd9xxx_intr {
+ wcd_intr_default: wcd_intr_default{
+ mux {
+ pins = "gpio54";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio54";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ input-enable;
+ };
+ };
+ };
+
+ cdc_reset_ctrl {
+ cdc_reset_sleep: cdc_reset_sleep {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+ };
+ cdc_reset_active:cdc_reset_active {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio64";
+ drive-strength = <16>;
+ bias-pull-down;
+ output-high;
+ };
+ };
+ };
+
+ spkr_1_sd_n {
+ spkr_1_sd_n_sleep: spkr_1_sd_n_sleep {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down;
+ input-enable;
+ };
+ };
+ spkr_1_sd_n_active: spkr_1_sd_n_active {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio65";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable;
+ output-high;
+ };
+ };
+ };
+
+ spkr_2_sd_n {
+ spkr_2_sd_n_sleep: spkr_2_sd_n_sleep {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down;
+ input-enable;
+ };
+ };
+ spkr_2_sd_n_active: spkr_2_sd_n_active {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio66";
+ drive-strength = <16>; /* 16 mA */
+ bias-disable;
+ output-high;
+ };
+ };
+ };
+
};
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
index d48efe70c34a..31b1c9486226 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pm.dtsi
@@ -11,6 +11,38 @@
*/
&soc {
+ qcom,spm@178120000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x17812000 0x1000>;
+ qcom,name = "gold-l2"; /* Gold L2 SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,cpu-vctl-list = <&CPU4 &CPU5 &CPU6 &CPU7>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,saw2-avs-ctl = <0x1010031>;
+ qcom,saw2-avs-limit = <0x4000208>;
+ qcom,pfm-port = <0x2>;
+ };
+
+ qcom,spm@179120000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x17912000 0x1000>;
+ qcom,name = "silver-l2"; /* Silver L2 SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,saw2-avs-ctl = <0x1010031>;
+ qcom,saw2-avs-limit = <0x4000208>;
+ qcom,pfm-port = <0x2>;
+ };
+
qcom,lpm-levels {
compatible = "qcom,lpm-levels";
qcom,use-psci;
@@ -161,7 +193,7 @@
qcom,pm-cluster-level@1{ /* D2D */
reg = <1>;
- label = "perf-l2-ret";
+ label = "perf-l2-dynret";
qcom,psci-mode = <2>;
qcom,latency-us = <60>;
qcom,ss-power = <700>;
@@ -172,7 +204,7 @@
qcom,pm-cluster-level@2{ /* D2E */
reg = <2>;
- label = "perf-l2-memret";
+ label = "perf-l2-ret";
qcom,psci-mode = <3>;
qcom,latency-us = <100>;
qcom,ss-power = <640>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-wsa881x.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-wsa881x.dtsi
new file mode 100644
index 000000000000..6417564b8533
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-wsa881x.dtsi
@@ -0,0 +1,57 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&slim_msm {
+ tasha_codec {
+ swr_master {
+ compatible = "qcom,swr-wcd";
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ wsa881x_211: wsa881x@20170211 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x20170211>;
+ qcom,spkr-sd-n-gpio = <&tlmm 65 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&spkr_1_sd_n_active>;
+ pinctrl-1 = <&spkr_1_sd_n_sleep>;
+ };
+
+ wsa881x_212: wsa881x@20170212 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x20170212>;
+ qcom,spkr-sd-n-gpio = <&tlmm 66 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&spkr_2_sd_n_active>;
+ pinctrl-1 = <&spkr_2_sd_n_sleep>;
+ };
+
+ wsa881x_213: wsa881x@21170213 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170213>;
+ qcom,spkr-sd-n-gpio = <&tlmm 65 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&spkr_1_sd_n_active>;
+ pinctrl-1 = <&spkr_1_sd_n_sleep>;
+ };
+
+ wsa881x_214: wsa881x@21170214 {
+ compatible = "qcom,wsa881x";
+ reg = <0x00 0x21170214>;
+ qcom,spkr-sd-n-gpio = <&tlmm 66 0>;
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&spkr_2_sd_n_active>;
+ pinctrl-1 = <&spkr_2_sd_n_sleep>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index c157f544e5ba..e9b60a996f83 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -521,55 +521,10 @@
qcom,governor-per-policy;
qcom,cpufreq-table-0 =
- < 300000 >,
- < 345600 >,
- < 422400 >,
- < 499200 >,
- < 576000 >,
- < 633600 >,
- < 710400 >,
- < 806400 >,
- < 883200 >,
- < 960000 >,
- < 1036800 >,
- < 1113600 >,
- < 1190400 >,
- < 1248000 >,
- < 1324800 >,
- < 1401600 >,
- < 1478400 >,
- < 1574400 >,
- < 1651200 >,
- < 1728000 >,
- < 1804800 >,
- < 1881600 >;
+ < 300000 >;
qcom,cpufreq-table-4 =
- < 300000 >,
- < 345600 >,
- < 422400 >,
- < 480000 >,
- < 556800 >,
- < 633600 >,
- < 710400 >,
- < 787200 >,
- < 844800 >,
- < 902400 >,
- < 979200 >,
- < 1056000 >,
- < 1171200 >,
- < 1248000 >,
- < 1324800 >,
- < 1401600 >,
- < 1478400 >,
- < 1536000 >,
- < 1632000 >,
- < 1708800 >,
- < 1785600 >,
- < 1862400 >,
- < 1939200 >,
- < 2016000 >,
- < 2092800 >;
+ < 300000 >;
};
arm64-cpu-erp {
@@ -653,55 +608,10 @@
interrupt-names = "pwrcl-irq", "perfcl-irq";
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>,
- < 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>;
+ < 300000000 0x0004000f 0x031e001e 0x1>;
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>,
- < 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>;
+ < 300000000 0x0004000f 0x03200020 0x1>;
qcom,osm-pll-setup;
@@ -813,6 +723,7 @@
qcom,use-gsi;
qcom,use-ipa-tethering-bridge;
qcom,modem-cfg-emb-pipe-flt;
+ qcom,ipa-wdi2;
clock-names = "core_clk";
clocks = <&clock_gcc clk_ipa_clk>;
qcom,msm-bus,name = "ipa";
@@ -901,22 +812,6 @@
rpm-channel-name = "rpm_requests";
};
- qcom,smdpkt {
- compatible = "qcom,smdpkt";
-
- qcom,smdpkt-apr-apps2 {
- qcom,smdpkt-remote = "adsp";
- qcom,smdpkt-port-name = "apr_apps2";
- qcom,smdpkt-dev-name = "apr_apps2";
- };
-
- qcom,smdpkt-loopback {
- qcom,smdpkt-remote = "modem";
- qcom,smdpkt-port-name = "LOOPBACK";
- qcom,smdpkt-dev-name = "smd_pkt_loopback";
- };
- };
-
glink_mpss: qcom,glink-ssr-modem {
compatible = "qcom,glink_ssr";
label = "modem";
@@ -1021,7 +916,7 @@
compatible = "qcom,glinkpkt";
qcom,glinkpkt-at-mdm0 {
- qcom,glinkpkt-transport = "smd_trans";
+ qcom,glinkpkt-transport = "smem";
qcom,glinkpkt-edge = "mpss";
qcom,glinkpkt-ch-name = "DS";
qcom,glinkpkt-dev-name = "at_mdm0";
@@ -1040,6 +935,20 @@
qcom,glinkpkt-ch-name = "glink_pkt_lloop_CLNT";
qcom,glinkpkt-dev-name = "glink_pkt_loopback";
};
+
+ qcom,glinkpkt-apr-apps2 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "adsp";
+ qcom,glinkpkt-ch-name = "apr_apps2";
+ qcom,glinkpkt-dev-name = "apr_apps2";
+ };
+
+ qcom,glinkpkt-data40-cntl {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DATA40_CNTL";
+ qcom,glinkpkt-dev-name = "smdcntl8";
+ };
};
qcom,ipc_router {
@@ -1549,7 +1458,7 @@
clocks = <&clock_gcc clk_cxo_clk_src>,
<&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
<&clock_gcc clk_pnoc_clk>,
- <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+ <&clock_gcc clk_gcc_bimc_mss_q6_axi_clk>,
<&clock_gcc clk_gcc_boot_rom_ahb_clk>,
<&clock_gcc clk_gpll0_out_msscc>,
<&clock_gcc clk_gcc_mss_snoc_axi_clk>,
@@ -1591,6 +1500,18 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
+ slim_msm: slim@91c0000 {
+ cell-index = <1>;
+ compatible = "qcom,slim-ngd";
+ reg = <0x91c0000 0x2C000>,
+ <0x9184000 0x32000>;
+ reg-names = "slimbus_physical", "slimbus_bam_physical";
+ interrupts = <0 163 0>, <0 164 0>;
+ interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+ qcom,apps-ch-pipes = <0x600000>;
+ qcom,ea-pc = <0x160>;
+ };
+
tsens0: tsens@10aa000 {
compatible = "qcom,msmcobalt-tsens";
reg = <0x10aa000 0x2000>,
@@ -1898,9 +1819,10 @@
reg = <0x1d0101c 0x4>,
<0x1d01024 0x4>,
<0x1d01028 0x4>,
- <0x1d0103c 0x4>;
+ <0x1d0103c 0x4>,
+ <0x1d02030 0x4>;
reg-names = "sp2soc_irq_status", "sp2soc_irq_clr",
- "sp2soc_irq_mask","rmb_err";
+ "sp2soc_irq_mask", "rmb_err", "rmb_err_spare2";
interrupts = <0 352 1>;
vdd_cx-supply = <&pmcobalt_s1_level>;
@@ -1917,7 +1839,7 @@
qcom,proxy-timeout-ms = <10000>;
qcom,firmware-name = "spss";
memory-region = <&peripheral_mem>;
- qcom,spss-scsr-bits = <0 1 2 3 16 17 24 25>;
+ qcom,spss-scsr-bits = <24 25>;
};
qcom,msm-rtb {
@@ -2199,3 +2121,6 @@
#include "msmcobalt-gpu.dtsi"
#include "msm-pmcobalt.dtsi"
#include "msm-pmicobalt.dtsi"
+#include "msmcobalt-pinctrl.dtsi"
+#include "msm-audio-lpass.dtsi"
+#include "msmcobalt-audio.dtsi"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 8087882ac33f..559ac84dcaa2 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -55,6 +55,7 @@ config ARCH_QCOM
select PM_OPP
select SOC_BUS
select MSM_IRQ
+ select THERMAL_WRITABLE_TRIPS
help
This enables support for the ARMv8 based Qualcomm chipsets.
diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig
index 95a96e34c4c4..5791959408bd 100644
--- a/arch/arm64/configs/msm-perf_defconfig
+++ b/arch/arm64/configs/msm-perf_defconfig
@@ -533,6 +533,7 @@ CONFIG_QCOM_BUSPM_DEV=m
CONFIG_QCOM_BUS_TOPOLOGY_ADHOC=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y
CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 5ca974ffac43..deffb3241e12 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -536,6 +536,7 @@ CONFIG_QCOM_BUSPM_DEV=m
CONFIG_QCOM_BUS_TOPOLOGY_ADHOC=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y
CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 3f44a31d4dc4..763e73dea5e1 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -277,6 +277,9 @@ CONFIG_VIRTIO_CONSOLE=y
CONFIG_MSM_ADSPRPC=y
CONFIG_I2C=y
CONFIG_I2C_QUP=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SOUNDWIRE=y
CONFIG_SPMI=y
CONFIG_PINCTRL_MSMCOBALT=y
CONFIG_GPIOLIB=y
@@ -285,11 +288,15 @@ CONFIG_GPIO_QPNP_PIN=y
CONFIG_QPNP_SMBCHARGER=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_MSM_APM=y
# CONFIG_HWMON is not set
+CONFIG_THERMAL_TSENS8974=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_WCD9335_CODEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_RPM_SMD=y
@@ -307,6 +314,10 @@ CONFIG_FB_ARMCLCD=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSMCOBALT=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
@@ -421,6 +432,8 @@ CONFIG_TRACER_PKT=y
CONFIG_MSM_CORE_CTL_HELPER=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_EXTCON=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
CONFIG_PHY_XGENE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index c358c2a1cc56..2fd4f2ebf418 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -290,6 +290,9 @@ CONFIG_VIRTIO_CONSOLE=y
CONFIG_MSM_ADSPRPC=y
CONFIG_I2C=y
CONFIG_I2C_QUP=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SOUNDWIRE=y
CONFIG_SPMI=y
CONFIG_PINCTRL_MSMCOBALT=y
CONFIG_GPIOLIB=y
@@ -304,7 +307,9 @@ CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_MSM_APM=y
# CONFIG_HWMON is not set
+CONFIG_THERMAL_TSENS8974=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_WCD9335_CODEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_RPM_SMD=y
@@ -317,12 +322,17 @@ CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_MEM_ACC=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
CONFIG_REGULATOR_STUB=y
+CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
CONFIG_FB_VIRTUAL=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSMCOBALT=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
@@ -448,6 +458,8 @@ CONFIG_TRACER_PKT=y
CONFIG_MSM_CORE_CTL_HELPER=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_EXTCON=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
CONFIG_PHY_XGENE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 90c7ff233735..bfef76e14e2d 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -113,6 +113,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTORE_SIGMASK 20
#define TIF_SINGLESTEP 21
#define TIF_32BIT 22 /* 32bit process */
+#define TIF_MM_RELEASED 24
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 1a665e04d139..e6777606a934 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -2112,14 +2112,19 @@ int arm_iommu_attach_device(struct device *dev,
struct dma_iommu_mapping *mapping)
{
int err;
+ int s1_bypass = 0;
err = iommu_attach_device(mapping->domain, dev);
if (err)
return err;
+ iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
+ &s1_bypass);
+
kref_get(&mapping->kref);
dev->archdata.mapping = mapping;
- set_dma_ops(dev, &iommu_ops);
+ if (!s1_bypass)
+ set_dma_ops(dev, &iommu_ops);
pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
return 0;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 92ddac1e8ca2..c2a5a018bd00 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -38,6 +38,7 @@
#include <asm/system_misc.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+#include <asm/edac.h>
static const char *fault_name(unsigned int esr);
@@ -376,6 +377,7 @@ static int __kprobes do_translation_fault(unsigned long addr,
*/
static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
{
+ arm64_check_cache_ecc(NULL);
return 1;
}
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index 3ca376f9c2e3..00cb1064ea13 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -36,6 +36,7 @@
static const struct of_device_id bt_power_match_table[] = {
{ .compatible = "qca,ar3002" },
{ .compatible = "qca,qca6174" },
+ { .compatible = "qca,wcn3990" },
{}
};
@@ -85,6 +86,16 @@ static int bt_vreg_enable(struct bt_power_vreg_data *vreg)
}
}
+ if (vreg->load_uA >= 0) {
+ rc = regulator_set_load(vreg->reg,
+ vreg->load_uA);
+ if (rc < 0) {
+ BT_PWR_ERR("vreg_set_mode(%s) failed rc=%d\n",
+ vreg->name, rc);
+ goto out;
+ }
+ }
+
rc = regulator_enable(vreg->reg);
if (rc < 0) {
BT_PWR_ERR("regulator_enable(%s) failed. rc=%d\n",
@@ -117,14 +128,19 @@ static int bt_vreg_disable(struct bt_power_vreg_data *vreg)
if (vreg->set_voltage_sup) {
/* Set the min voltage to 0 */
- rc = regulator_set_voltage(vreg->reg,
- 0,
- vreg->high_vol_level);
+ rc = regulator_set_voltage(vreg->reg, 0,
+ vreg->high_vol_level);
if (rc < 0) {
BT_PWR_ERR("vreg_set_vol(%s) failed rc=%d\n",
vreg->name, rc);
goto out;
-
+ }
+ }
+ if (vreg->load_uA >= 0) {
+ rc = regulator_set_load(vreg->reg, 0);
+ if (rc < 0) {
+ BT_PWR_ERR("vreg_set_mode(%s) failed rc=%d\n",
+ vreg->name, rc);
}
}
}
@@ -154,7 +170,7 @@ static int bt_configure_gpios(int on)
int rc = 0;
int bt_reset_gpio = bt_power_pdata->bt_gpio_sys_rst;
- BT_PWR_DBG("%s bt_gpio= %d on: %d", __func__, bt_reset_gpio, on);
+ BT_PWR_DBG("bt_gpio= %d on: %d", bt_reset_gpio, on);
if (on) {
rc = gpio_request(bt_reset_gpio, "bt_sys_rst_n");
@@ -211,7 +227,6 @@ static int bluetooth_power(int on)
goto vdd_core_fail;
}
}
-
if (bt_power_pdata->bt_vdd_pa) {
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_pa);
if (rc < 0) {
@@ -378,6 +393,7 @@ static int bt_dt_parse_vreg_info(struct device *dev,
vreg->name = vreg_name;
+ /* Parse voltage-level from each node */
snprintf(prop_name, MAX_PROP_SIZE,
"%s-voltage-level", vreg_name);
prop = of_get_property(np, prop_name, &len);
@@ -389,10 +405,21 @@ static int bt_dt_parse_vreg_info(struct device *dev,
vreg->high_vol_level = be32_to_cpup(&prop[1]);
}
+ /* Parse current-level from each node */
+ snprintf(prop_name, MAX_PROP_SIZE,
+ "%s-current-level", vreg_name);
+ ret = of_property_read_u32(np, prop_name, &vreg->load_uA);
+ if (ret < 0) {
+ BT_PWR_DBG("%s property is not valid\n", prop_name);
+ vreg->load_uA = -1;
+ ret = 0;
+ }
+
*vreg_data = vreg;
- BT_PWR_DBG("%s: vol=[%d %d]uV\n",
+ BT_PWR_DBG("%s: vol=[%d %d]uV, current=[%d]uA\n",
vreg->name, vreg->low_vol_level,
- vreg->high_vol_level);
+ vreg->high_vol_level,
+ vreg->load_uA);
} else
BT_PWR_INFO("%s: is not provided in device tree", vreg_name);
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 173f9214d7f7..14b988c1e089 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -1681,13 +1681,14 @@ static u32 find_voltage(struct clk_osm *c, unsigned long rate)
return -EINVAL;
}
-static int add_opp(struct clk_osm *c, struct device *dev,
- unsigned long max_rate, unsigned long min_rate)
+static int add_opp(struct clk_osm *c, struct device *dev)
{
unsigned long rate = 0;
u32 uv;
long rc;
- int j = 1;
+ int j = 0;
+ unsigned long min_rate = c->c.fmax[0];
+ unsigned long max_rate = c->c.fmax[c->c.num_fmax - 1];
while (1) {
rate = c->c.fmax[j++];
@@ -1712,11 +1713,15 @@ static int add_opp(struct clk_osm *c, struct device *dev,
if (rate == min_rate)
pr_info("Set OPP pair (%lu Hz, %d uv) on %s\n",
rate, uv, dev_name(dev));
- if (rate == max_rate) {
+
+ if (rate == max_rate && max_rate != min_rate) {
pr_info("Set OPP pair (%lu Hz, %d uv) on %s\n",
rate, uv, dev_name(dev));
break;
}
+
+ if (min_rate == max_rate)
+ break;
}
return 0;
@@ -1762,15 +1767,11 @@ static void populate_opp_table(struct platform_device *pdev)
for_each_possible_cpu(cpu) {
if (logical_cpu_to_clk(cpu) == &pwrcl_clk.c) {
- WARN(add_opp(&pwrcl_clk, get_cpu_device(cpu),
- pwrcl_clk.c.fmax[pwrcl_clk.c.num_fmax - 1],
- pwrcl_clk.c.fmax[1]),
+ WARN(add_opp(&pwrcl_clk, get_cpu_device(cpu)),
"Failed to add OPP levels for power cluster\n");
}
if (logical_cpu_to_clk(cpu) == &perfcl_clk.c) {
- WARN(add_opp(&perfcl_clk, get_cpu_device(cpu),
- perfcl_clk.c.fmax[perfcl_clk.c.num_fmax - 1],
- perfcl_clk.c.fmax[1]),
+ WARN(add_opp(&perfcl_clk, get_cpu_device(cpu)),
"Failed to add OPP levels for perf cluster\n");
}
}
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 5e370a30a964..1be58ffd3bce 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -322,16 +322,20 @@ static int __init cpufreq_stats_init(void)
if (ret)
return ret;
+ get_online_cpus();
for_each_online_cpu(cpu)
cpufreq_stats_create_table(cpu);
+ put_online_cpus();
ret = cpufreq_register_notifier(&notifier_trans_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret) {
cpufreq_unregister_notifier(&notifier_policy_block,
CPUFREQ_POLICY_NOTIFIER);
+ get_online_cpus();
for_each_online_cpu(cpu)
cpufreq_stats_free_table(cpu);
+ put_online_cpus();
return ret;
}
diff --git a/drivers/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c
index 05198a17ad5f..e0f75b0022fc 100644
--- a/drivers/devfreq/governor_bw_hwmon.c
+++ b/drivers/devfreq/governor_bw_hwmon.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
@@ -764,6 +764,8 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df,
{
int ret;
unsigned int sample_ms;
+ struct hwmon_node *node;
+ struct bw_hwmon *hw;
switch (event) {
case DEVFREQ_GOV_START:
@@ -790,7 +792,22 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df,
sample_ms = *(unsigned int *)data;
sample_ms = max(MIN_MS, sample_ms);
sample_ms = min(MAX_MS, sample_ms);
+ /*
+ * Suspend/resume the HW monitor around the interval update
+ * to prevent the HW monitor IRQ from trying to change
+ * stop/start the delayed workqueue while the interval update
+ * is happening.
+ */
+ node = df->data;
+ hw = node->hw;
+ hw->suspend_hwmon(hw);
devfreq_interval_update(df, &sample_ms);
+ ret = hw->resume_hwmon(hw);
+ if (ret) {
+ dev_err(df->dev.parent,
+ "Unable to resume HW monitor (%d)\n", ret);
+ return ret;
+ }
break;
case DEVFREQ_GOV_SUSPEND:
diff --git a/drivers/edac/cortex_arm64_edac.c b/drivers/edac/cortex_arm64_edac.c
index d134e8822c9d..2268bd3fa8f0 100644
--- a/drivers/edac/cortex_arm64_edac.c
+++ b/drivers/edac/cortex_arm64_edac.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
@@ -63,6 +63,14 @@
#define A57_L2MERRSR_CPUID(a) (((a) >> 18) & 0x0f)
#define A57_L2MERRSR_INDEX(a) ((a) & 0x1ffff)
+#define KRYO2XX_GOLD_L2MERRSR_FATAL(a) ((a) & (1LL << 63))
+#define KRYO2XX_GOLD_L2MERRSR_OTHER(a) (((a) >> 40) & 0x3f)
+#define KRYO2XX_GOLD_L2MERRSR_REPT(a) (((a) >> 32) & 0x3f)
+#define KRYO2XX_GOLD_L2MERRSR_VALID(a) ((a) & (1 << 31))
+#define KRYO2XX_GOLD_L2MERRSR_RAMID(a) ((a) & (1 << 24))
+#define KRYO2XX_GOLD_L2MERRSR_WAY(a) (((a) >> 18) & 0x0f)
+#define KRYO2XX_GOLD_L2MERRSR_INDEX(a) (((a) >> 3) & 0x3fff)
+
#define L2ECTLR_INT_ERR (1 << 30)
#define L2ECTLR_EXT_ERR (1 << 29)
@@ -220,6 +228,32 @@ static void ca53_ca57_print_error_state_regs(void)
"Double bit error on dirty L2 cacheline\n");
}
+static void kryo2xx_gold_print_error_state_regs(void)
+{
+ u64 l2merrsr;
+ u32 esr_el1;
+ u32 l2ectlr;
+
+ l2merrsr = read_l2merrsr_el1;
+ esr_el1 = read_esr_el1;
+ l2ectlr = read_l2ectlr_el1;
+
+ uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
+ (void *)l2merrsr);
+ uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
+ (void *)((u64)esr_el1));
+ uncached_logk_pc(LOGK_READL, __builtin_return_address(0),
+ (void *)((u64)l2ectlr));
+
+ edac_printk(KERN_CRIT, EDAC_CPU, "L2MERRSR value = %#llx\n", l2merrsr);
+
+ edac_printk(KERN_CRIT, EDAC_CPU, "ESR value = %#x\n", esr_el1);
+ edac_printk(KERN_CRIT, EDAC_CPU, "L2ECTLR value = %#x\n", l2ectlr);
+ if (ESR_L2_DBE(esr_el1))
+ edac_printk(KERN_CRIT, EDAC_CPU,
+ "Double bit error on dirty L2 cacheline\n");
+}
+
static void ca53_parse_cpumerrsr(struct erp_local_data *ed)
{
u64 cpumerrsr;
@@ -480,6 +514,50 @@ static void ca57_parse_l2merrsr(struct erp_local_data *ed)
write_l2merrsr_el1(0);
}
+
+static void kryo2xx_gold_parse_l2merrsr(struct erp_local_data *ed)
+{
+ u64 l2merrsr;
+ int ramid, way;
+
+ l2merrsr = read_l2merrsr_el1;
+
+ if (!KRYO2XX_GOLD_L2MERRSR_VALID(l2merrsr))
+ return;
+
+ if (KRYO2XX_GOLD_L2MERRSR_FATAL(l2merrsr))
+ ed->err = DBE;
+
+ edac_printk(KERN_CRIT, EDAC_CPU, "Gold L2 %s Error detected\n",
+ err_name[ed->err]);
+ kryo2xx_gold_print_error_state_regs();
+ if (ed->err == DBE)
+ edac_printk(KERN_CRIT, EDAC_CPU, "Fatal error\n");
+
+ way = KRYO2XX_GOLD_L2MERRSR_WAY(l2merrsr);
+ ramid = KRYO2XX_GOLD_L2MERRSR_RAMID(l2merrsr);
+
+ edac_printk(KERN_CRIT, EDAC_CPU,
+ "L2 %s RAM error in way 0x%02x, index 0x%04x\n",
+ ramid ? "data" : "tag",
+ (int) KRYO2XX_GOLD_L2MERRSR_WAY(l2merrsr),
+ (int) KRYO2XX_GOLD_L2MERRSR_INDEX(l2merrsr));
+
+ edac_printk(KERN_CRIT, EDAC_CPU, "Repeated error count: %d\n",
+ (int) KRYO2XX_GOLD_L2MERRSR_REPT(l2merrsr));
+ edac_printk(KERN_CRIT, EDAC_CPU, "Other error count: %d\n",
+ (int) KRYO2XX_GOLD_L2MERRSR_OTHER(l2merrsr));
+
+ if (ed->err == SBE) {
+ errors[A57_L2_CE].func(ed->drv->edev_ctl, smp_processor_id(),
+ L2_CACHE, errors[A57_L2_CE].msg);
+ } else if (ed->err == DBE) {
+ errors[A57_L2_UE].func(ed->drv->edev_ctl, smp_processor_id(),
+ L2_CACHE, errors[A57_L2_UE].msg);
+ }
+ write_l2merrsr_el1(0);
+}
+
static DEFINE_SPINLOCK(local_handler_lock);
static DEFINE_SPINLOCK(l2ectlr_lock);
@@ -508,6 +586,10 @@ static void arm64_erp_local_handler(void *info)
ca57_parse_l2merrsr(errdata);
break;
+ case ARM_CPU_PART_KRYO2XX_GOLD:
+ kryo2xx_gold_parse_l2merrsr(errdata);
+ break;
+
default:
edac_printk(KERN_CRIT, EDAC_CPU, "Unknown CPU Part Number in MIDR: %#04x (%#08x)\n",
partnum, cpuid);
@@ -675,6 +757,10 @@ static void check_sbe_event(struct erp_drvdata *drv)
ca57_parse_cpumerrsr(&errdata);
ca57_parse_l2merrsr(&errdata);
break;
+
+ case ARM_CPU_PART_KRYO2XX_GOLD:
+ kryo2xx_gold_parse_l2merrsr(&errdata);
+ break;
};
spin_unlock_irqrestore(&local_handler_lock, flags);
}
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index b2c53de88b03..a9b6b24725b4 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1453,7 +1453,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
}
/* SCTLR */
- reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_M | SCTLR_EAE_SBOP;
+ reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_EAE_SBOP;
+
+ if (!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) ||
+ !stage1)
+ reg |= SCTLR_M;
if (stage1)
reg |= SCTLR_S1_ASIDPNE;
#ifdef __BIG_ENDIAN
@@ -2898,6 +2902,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
& (1 << DOMAIN_ATTR_NON_FATAL_FAULTS));
ret = 0;
break;
+ case DOMAIN_ATTR_S1_BYPASS:
+ *((int *)data) = !!(smmu_domain->attributes
+ & (1 << DOMAIN_ATTR_S1_BYPASS));
+ ret = 0;
+ break;
default:
ret = -ENODEV;
break;
@@ -3009,6 +3018,18 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
smmu_domain->non_fatal_faults = *((int *)data);
ret = 0;
break;
+ case DOMAIN_ATTR_S1_BYPASS: {
+ int bypass = *((int *)data);
+
+ if (bypass)
+ smmu_domain->attributes |= 1 << DOMAIN_ATTR_S1_BYPASS;
+ else
+ smmu_domain->attributes &=
+ ~(1 << DOMAIN_ATTR_S1_BYPASS);
+
+ ret = 0;
+ break;
+ }
default:
ret = -ENODEV;
break;
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h
index 015c2099603c..97aadc8446c7 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_hw_ops.h
@@ -9,6 +9,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#ifndef _CAM_HW_OPS_H_
+#define _CAM_HW_OPS_H_
enum cam_ahb_clk_vote {
/* need to update the voting requests
@@ -37,3 +39,4 @@ enum cam_ahb_clk_client {
int cam_config_ahb_clk(struct device *dev, unsigned long freq,
enum cam_ahb_clk_client id, enum cam_ahb_clk_vote vote);
int cam_ahb_clk_init(struct platform_device *pdev);
+#endif /* _CAM_HW_OPS_H_ */
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
index d699d091e3c7..33e1299cd027 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
@@ -473,16 +473,16 @@ EXPORT_SYMBOL(msm_camera_put_clk_info_and_rates);
/* Get regulators from DT */
int msm_camera_get_regulator_info(struct platform_device *pdev,
- struct regulator ***vdd,
+ struct msm_cam_regulator **vdd_info,
int *num_reg)
{
uint32_t cnt;
int i, rc;
struct device_node *of_node;
- const char *name;
char prop_name[32];
+ struct msm_cam_regulator *tmp_reg;
- if (!pdev || !vdd || !num_reg)
+ if (!pdev || !vdd_info || !num_reg)
return -EINVAL;
of_node = pdev->dev.of_node;
@@ -499,82 +499,95 @@ int msm_camera_get_regulator_info(struct platform_device *pdev,
return -EINVAL;
}
- *num_reg = cnt;
- (*vdd) = devm_kcalloc(&pdev->dev, cnt, sizeof(struct regulator *),
- GFP_KERNEL);
- if (!*vdd)
+ tmp_reg = devm_kcalloc(&pdev->dev, cnt,
+ sizeof(struct msm_cam_regulator), GFP_KERNEL);
+ if (!tmp_reg)
return -ENOMEM;
for (i = 0; i < cnt; i++) {
rc = of_property_read_string_index(of_node,
- "qcom,vdd-names", i, &name);
+ "qcom,vdd-names", i, &tmp_reg[i].name);
if (rc < 0) {
pr_err("Fail to fetch regulators: %d\n", i);
rc = -EINVAL;
goto err1;
}
- CDBG("regulator-names[%d] = %s\n", i, name);
+ CDBG("regulator-names[%d] = %s\n", i, tmp_reg[i].name);
- snprintf(prop_name, 32, "%s-supply", name);
+ snprintf(prop_name, 32, "%s-supply", tmp_reg[i].name);
if (of_get_property(of_node, prop_name, NULL)) {
- (*vdd)[i] = devm_regulator_get(&pdev->dev, name);
- if (IS_ERR((*vdd)[i])) {
+ tmp_reg[i].vdd =
+ devm_regulator_get(&pdev->dev, tmp_reg[i].name);
+ if (IS_ERR(tmp_reg[i].vdd)) {
rc = -EINVAL;
pr_err("Fail to get regulator :%d\n", i);
goto err1;
}
} else {
- pr_err("Regulator phandle not found :%s\n", name);
+ pr_err("Regulator phandle not found :%s\n",
+ tmp_reg[i].name);
+ rc = -EINVAL;
goto err1;
}
- CDBG("vdd ptr[%d] :%p\n", i, (*vdd)[i]);
+ CDBG("vdd ptr[%d] :%p\n", i, tmp_reg[i].vdd);
}
+ *num_reg = cnt;
+ *vdd_info = tmp_reg;
+
return 0;
err1:
for (--i; i >= 0; i--)
- devm_regulator_put((*vdd)[i]);
- devm_kfree(&pdev->dev, *vdd);
+ devm_regulator_put(tmp_reg[i].vdd);
+ devm_kfree(&pdev->dev, tmp_reg);
return rc;
}
EXPORT_SYMBOL(msm_camera_get_regulator_info);
/* Enable/Disable regulators */
-int msm_camera_regulator_enable(struct regulator **vdd,
+int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
int cnt, int enable)
{
int i;
int rc;
+ struct msm_cam_regulator *tmp = vdd_info;
- CDBG("cnt : %d, enable : %d\n", cnt, enable);
- if (!vdd) {
+ if (!tmp) {
pr_err("Invalid params");
return -EINVAL;
}
+ CDBG("cnt : %d\n", cnt);
for (i = 0; i < cnt; i++) {
- if (enable) {
- rc = regulator_enable(vdd[i]);
- if (rc < 0) {
- pr_err("regulator enable failed %d\n", i);
- goto error;
+ if (tmp && !IS_ERR_OR_NULL(tmp->vdd)) {
+ CDBG("name : %s, enable : %d\n", tmp->name, enable);
+ if (enable) {
+ rc = regulator_enable(tmp->vdd);
+ if (rc < 0) {
+ pr_err("regulator enable failed %d\n",
+ i);
+ goto error;
+ }
+ } else {
+ rc = regulator_disable(tmp->vdd);
+ if (rc < 0)
+ pr_err("regulator disable failed %d\n",
+ i);
}
- } else {
- rc = regulator_disable(vdd[i]);
- if (rc < 0)
- pr_err("regulator disable failed %d\n", i);
}
+ tmp++;
}
return 0;
error:
for (--i; i > 0; i--) {
- if (!IS_ERR_OR_NULL(vdd[i]))
- regulator_disable(vdd[i]);
+ --tmp;
+ if (!IS_ERR_OR_NULL(tmp->vdd))
+ regulator_disable(tmp->vdd);
}
return rc;
}
@@ -582,24 +595,23 @@ EXPORT_SYMBOL(msm_camera_regulator_enable);
/* Put regulators regulators */
void msm_camera_put_regulators(struct platform_device *pdev,
- struct regulator ***vdd,
- int cnt)
+ struct msm_cam_regulator **vdd_info, int cnt)
{
int i;
- if (!*vdd) {
+ if (!vdd_info || !*vdd_info) {
pr_err("Invalid params\n");
return;
}
for (i = cnt - 1; i >= 0; i--) {
- if (!IS_ERR_OR_NULL((*vdd)[i]))
- devm_regulator_put((*vdd)[i]);
- CDBG("vdd ptr[%d] :%p\n", i, (*vdd)[i]);
+ if (vdd_info[i] && !IS_ERR_OR_NULL(vdd_info[i]->vdd))
+ devm_regulator_put(vdd_info[i]->vdd);
+ CDBG("vdd ptr[%d] :%p\n", i, vdd_info[i]->vdd);
}
- devm_kfree(&pdev->dev, *vdd);
- *vdd = NULL;
+ devm_kfree(&pdev->dev, *vdd_info);
+ *vdd_info = NULL;
}
EXPORT_SYMBOL(msm_camera_put_regulators);
@@ -643,12 +655,11 @@ EXPORT_SYMBOL(msm_camera_register_irq);
int msm_camera_register_threaded_irq(struct platform_device *pdev,
struct resource *irq, irq_handler_t handler_fn,
irq_handler_t thread_fn, unsigned long irqflags,
- char *irq_name, void *dev_id)
+ const char *irq_name, void *dev_id)
{
int rc = 0;
- if (!pdev || !irq || !handler_fn || !thread_fn ||
- !irq_name || !dev_id) {
+ if (!pdev || !irq || !irq_name || !dev_id) {
pr_err("Invalid params\n");
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
index 0b60d4137354..9724d5951862 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
@@ -34,6 +34,11 @@ enum cam_bus_client {
CAM_BUS_CLIENT_MAX
};
+struct msm_cam_regulator {
+ const char *name;
+ struct regulator *vdd;
+};
+
/**
* @brief : Gets clock information from dtsi
*
@@ -154,28 +159,28 @@ long msm_camera_clk_set_rate(struct device *dev,
* platform device
*
* @param pdev : platform device to get regulator information
- * @param vdd: Pointer to populate the regulator names
+ * @param vdd_info: Pointer to populate the regulator names
* @param num_reg: Pointer to populate the number of regulators
* extracted from dtsi
*
* @return Status of operation. Negative in case of error. Zero otherwise.
*/
int msm_camera_get_regulator_info(struct platform_device *pdev,
- struct regulator ***vddd, int *num_reg);
+ struct msm_cam_regulator **vdd_info, int *num_reg);
/**
* @brief : Enable/Disable the regultors
*
* This function enables/disables the regulators for a specific
* platform device
*
- * @param vdd: Pointer to list of regulators
+ * @param vdd_info: Pointer to list of regulators
* @param cnt: Number of regulators to enable/disable
* @param enable: Flags specifies either enable/disable
*
* @return Status of operation. Negative in case of error. Zero otherwise.
*/
-int msm_camera_regulator_enable(struct regulator **vdd,
+int msm_camera_regulator_enable(struct msm_cam_regulator *vdd_info,
int cnt, int enable);
/**
@@ -184,13 +189,12 @@ int msm_camera_regulator_enable(struct regulator **vdd,
* This function releases the regulator resources.
*
* @param pdev: Pointer to platform device
- * @param vdd: Pointer to list of regulators
+ * @param vdd_info: Pointer to list of regulators
* @param cnt: Number of regulators to release
*/
void msm_camera_put_regulators(struct platform_device *pdev,
- struct regulator ***vdd,
- int cnt);
+ struct msm_cam_regulator **vdd_info, int cnt);
/**
* @brief : Get the IRQ resource
*
@@ -248,7 +252,7 @@ int msm_camera_register_threaded_irq(struct platform_device *pdev,
irq_handler_t handler_fn,
irq_handler_t thread_fn,
unsigned long irqflags,
- char *irq_name,
+ const char *irq_name,
void *dev);
/**
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
index bc6d8b439292..98afe4cd3074 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
@@ -1224,7 +1224,7 @@ static int fd_probe(struct platform_device *pdev)
goto error_mem_resources;
}
- ret = msm_camera_get_regulator_info(pdev, &fd->vdd,
+ ret = msm_camera_get_regulator_info(pdev, &fd->vdd_info,
&fd->num_reg);
if (ret < 0) {
dev_err(&pdev->dev, "Fail to get regulators\n");
@@ -1298,7 +1298,7 @@ error_get_bus:
msm_camera_put_clk_info_and_rates(pdev, &fd->clk_info,
&fd->clk, &fd->clk_rates, fd->clk_rates_num, fd->clk_num);
error_get_clocks:
- msm_camera_put_regulators(pdev, &fd->vdd, fd->num_reg);
+ msm_camera_put_regulators(pdev, &fd->vdd_info, fd->num_reg);
error_get_regulator:
msm_fd_hw_release_mem_resources(fd);
error_mem_resources:
@@ -1325,7 +1325,7 @@ static int fd_device_remove(struct platform_device *pdev)
msm_camera_unregister_bus_client(CAM_BUS_CLIENT_FD);
msm_camera_put_clk_info_and_rates(pdev, &fd->clk_info,
&fd->clk, &fd->clk_rates, fd->clk_rates_num, fd->clk_num);
- msm_camera_put_regulators(pdev, &fd->vdd, fd->num_reg);
+ msm_camera_put_regulators(pdev, &fd->vdd_info, fd->num_reg);
msm_fd_hw_release_mem_resources(fd);
kfree(fd);
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
index e86a9abf7126..b96c33b3fd07 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h
@@ -225,7 +225,7 @@ struct msm_fd_device {
int irq_num;
void __iomem *iomem_base[MSM_FD_IOMEM_LAST];
struct msm_cam_clk_info *clk_info;
- struct regulator **vdd;
+ struct msm_cam_regulator *vdd_info;
int num_reg;
struct resource *irq;
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c
index b8ee18da44cd..1e6398e54d68 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c
@@ -838,7 +838,8 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx)
if (fd->ref_count == 0) {
ret =
- msm_camera_regulator_enable(fd->vdd, fd->num_reg, true);
+ msm_camera_regulator_enable(fd->vdd_info,
+ fd->num_reg, true);
if (ret < 0) {
dev_err(fd->dev, "Fail to enable vdd\n");
goto error;
@@ -881,7 +882,7 @@ error_set_dt:
fd->clk, fd->clk_num, false);
error_clocks:
error_bus_request:
- msm_camera_regulator_enable(fd->vdd, fd->num_reg, false);
+ msm_camera_regulator_enable(fd->vdd_info, fd->num_reg, false);
error:
mutex_unlock(&fd->lock);
return ret;
@@ -909,7 +910,7 @@ void msm_fd_hw_put(struct msm_fd_device *fd)
msm_fd_hw_bus_request(fd, 0);
msm_camera_clk_enable(&fd->pdev->dev, fd->clk_info,
fd->clk, fd->clk_num, false);
- msm_camera_regulator_enable(fd->vdd, fd->num_reg, false);
+ msm_camera_regulator_enable(fd->vdd_info, fd->num_reg, false);
}
mutex_unlock(&fd->lock);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 8a9a4f2a1c30..bc22a3987f85 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -721,7 +721,6 @@ struct vfe_device {
uint32_t isp_raw0_debug;
uint32_t isp_raw1_debug;
uint32_t isp_raw2_debug;
- uint8_t is_camif_raw_crop_supported;
/* irq info */
uint32_t irq0_mask;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 337ae59f88e8..850cffaef3a4 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -433,8 +433,6 @@ static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
break;
case VFE40_8937_VERSION:
case VFE40_8953_VERSION:
- vfe_dev->is_camif_raw_crop_supported = 1;
- break;
default:
ISP_DBG("%s: No special QOS\n", __func__);
}
@@ -1400,44 +1398,44 @@ static void msm_vfe40_cfg_camif(struct vfe_device *vfe_dev,
msm_camera_io_w((subsample_cfg->line_skip << 16) |
subsample_cfg->pixel_skip,
vfe_dev->vfe_base + 0x30C);
- if (vfe_dev->is_camif_raw_crop_supported) {
- /* Pdaf output will be sent in PLAIN16 format*/
- val = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
- switch (subsample_cfg->output_format) {
- case CAMIF_PLAIN_8:
- val |= 4 << 9;
- break;
- case CAMIF_PLAIN_16:
- val |= 5 << 9;
- break;
- case CAMIF_MIPI_RAW:
- val |= 1 << 9;
- break;
- case CAMIF_QCOM_RAW:
- default:
- break;
- }
- msm_camera_io_w(val, vfe_dev->vfe_base + 0x54);
- if (subsample_cfg->first_pixel ||
- subsample_cfg->last_pixel ||
- subsample_cfg->first_line ||
- subsample_cfg->last_line) {
- msm_camera_io_w(
- subsample_cfg->first_pixel << 16 |
- subsample_cfg->last_pixel,
- vfe_dev->vfe_base + 0x8A4);
- msm_camera_io_w(
- subsample_cfg->first_line << 16 |
- subsample_cfg->last_line,
- vfe_dev->vfe_base + 0x8A8);
- val = msm_camera_io_r(
- vfe_dev->vfe_base + 0x2F8);
- val |= 1 << 22;
- msm_camera_io_w(val,
- vfe_dev->vfe_base + 0x2F8);
- }
- }
+ if (subsample_cfg->first_pixel ||
+ subsample_cfg->last_pixel ||
+ subsample_cfg->first_line ||
+ subsample_cfg->last_line) {
+ msm_camera_io_w(
+ subsample_cfg->first_pixel << 16 |
+ subsample_cfg->last_pixel,
+ vfe_dev->vfe_base + 0x8A4);
+ msm_camera_io_w(
+ subsample_cfg->first_line << 16 |
+ subsample_cfg->last_line,
+ vfe_dev->vfe_base + 0x8A8);
+ val = msm_camera_io_r(
+ vfe_dev->vfe_base + 0x2F8);
+ val |= 1 << 22;
+ msm_camera_io_w(val,
+ vfe_dev->vfe_base + 0x2F8);
+ }
+ ISP_DBG("%s:camif raw op fmt %d\n",
+ __func__, subsample_cfg->output_format);
+ /* Pdaf output will be sent in PLAIN16 format*/
+ val = msm_camera_io_r(vfe_dev->vfe_base + 0x54);
+ switch (subsample_cfg->output_format) {
+ case CAMIF_PLAIN_8:
+ val |= 4 << 9;
+ break;
+ case CAMIF_PLAIN_16:
+ val |= 5 << 9;
+ break;
+ case CAMIF_MIPI_RAW:
+ val |= 1 << 9;
+ break;
+ case CAMIF_QCOM_RAW:
+ default:
+ break;
+ }
+ msm_camera_io_w(val, vfe_dev->vfe_base + 0x54);
}
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 054d736a2dc3..ea3c8f71912b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1317,6 +1317,48 @@ static void msm_vfe47_cfg_camif(struct vfe_device *vfe_dev,
msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x49C);
}
+ if (subsample_cfg->first_pixel ||
+ subsample_cfg->last_pixel ||
+ subsample_cfg->first_line ||
+ subsample_cfg->last_line) {
+ msm_camera_io_w(
+ subsample_cfg->first_pixel << 16 |
+ subsample_cfg->last_pixel,
+ vfe_dev->vfe_base + 0xCE4);
+ msm_camera_io_w(
+ subsample_cfg->first_line << 16 |
+ subsample_cfg->last_line,
+ vfe_dev->vfe_base + 0xCE4);
+ val = msm_camera_io_r(
+ vfe_dev->vfe_base + 0x47C);
+ ISP_DBG("%s: camif raw crop enabled\n", __func__);
+ val |= 1 << 22;
+ msm_camera_io_w(val,
+ vfe_dev->vfe_base + 0x47C);
+ }
+
+ ISP_DBG("%s: camif raw op fmt %d\n",
+ __func__, subsample_cfg->output_format);
+ /* Pdaf output can be sent in below formats */
+ val = msm_camera_io_r(vfe_dev->vfe_base + 0x88);
+ switch (subsample_cfg->output_format) {
+ case CAMIF_PLAIN_8:
+ val |= PLAIN8 << 9;
+ break;
+ case CAMIF_PLAIN_16:
+ val |= PLAIN16 << 9;
+ break;
+ case CAMIF_MIPI_RAW:
+ val |= MIPI << 9;
+ break;
+ case CAMIF_QCOM_RAW:
+ val |= QCOM << 9;
+ break;
+ default:
+ break;
+ }
+ msm_camera_io_w(val, vfe_dev->vfe_base + 0x88);
+
val = msm_camera_io_r(vfe_dev->vfe_base + 0x46C);
val |= camif_cfg->camif_input;
msm_camera_io_w(val, vfe_dev->vfe_base + 0x46C);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
index 6ceaa4130a78..30a91d32be87 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.h
@@ -67,7 +67,7 @@ struct msm_jpeg_device {
struct msm_cam_clk_info *jpeg_clk_info;
size_t num_clk;
int num_reg;
- struct regulator **jpeg_vdd;
+ struct msm_cam_regulator *jpeg_vdd;
uint32_t hw_version;
struct device *device;
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index d3e65bd2ee36..034789880a1f 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -1206,7 +1206,7 @@ static int jpegdma_probe(struct platform_device *pdev)
goto error_mem_resources;
/* get all the regulators */
- ret = msm_camera_get_regulator_info(pdev, &jpegdma->vdd,
+ ret = msm_camera_get_regulator_info(pdev, &jpegdma->dma_vdd,
&jpegdma->num_reg);
if (ret < 0)
goto error_get_regulators;
@@ -1313,7 +1313,7 @@ error_qos_get:
msm_camera_put_clk_info(pdev, &jpegdma->jpeg_clk_info,
&jpegdma->clk, jpegdma->num_clk);
error_get_clocks:
- msm_camera_put_regulators(pdev, &jpegdma->vdd,
+ msm_camera_put_regulators(pdev, &jpegdma->dma_vdd,
jpegdma->num_reg);
error_get_regulators:
msm_jpegdma_hw_release_mem_resources(jpegdma);
@@ -1341,7 +1341,7 @@ static int jpegdma_device_remove(struct platform_device *pdev)
/* unregister bus client */
msm_camera_unregister_bus_client(dma->bus_client);
/* release all the regulators */
- msm_camera_put_regulators(dma->pdev, &dma->vdd,
+ msm_camera_put_regulators(dma->pdev, &dma->dma_vdd,
dma->num_reg);
/* release all the clocks */
msm_camera_put_clk_info(dma->pdev, &dma->jpeg_clk_info,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h
index 48d0aaca2cd9..adb8b94f098c 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.h
@@ -334,7 +334,7 @@ struct msm_jpegdma_device {
void __iomem *iomem_base[MSM_JPEGDMA_IOMEM_LAST];
struct resource *irq;
- struct regulator **vdd;
+ struct msm_cam_regulator *dma_vdd;
int num_reg;
struct clk **clk;
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
index 46970a3e73b5..41086936a0b1 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_hw.c
@@ -1524,7 +1524,7 @@ int msm_jpegdma_hw_get_capabilities(struct msm_jpegdma_device *dma)
mutex_lock(&dma->lock);
/* enable all the regulators */
- ret = msm_camera_regulator_enable(dma->vdd,
+ ret = msm_camera_regulator_enable(dma->dma_vdd,
dma->num_reg, true);
if (ret < 0) {
dev_err(dma->dev, "Fail to enable regulators\n");
@@ -1547,14 +1547,14 @@ int msm_jpegdma_hw_get_capabilities(struct msm_jpegdma_device *dma)
dma->jpeg_clk_info, dma->clk,
dma->num_clk, false);
/* disable all the regulators */
- msm_camera_regulator_enable(dma->vdd, dma->num_reg, false);
+ msm_camera_regulator_enable(dma->dma_vdd, dma->num_reg, false);
mutex_unlock(&dma->lock);
return 0;
error_clocks:
- msm_camera_regulator_enable(dma->vdd, dma->num_reg, false);
+ msm_camera_regulator_enable(dma->dma_vdd, dma->num_reg, false);
error_regulators_get:
mutex_unlock(&dma->lock);
return ret;
@@ -1577,7 +1577,7 @@ int msm_jpegdma_hw_get(struct msm_jpegdma_device *dma)
dev_dbg(dma->dev, "msm_jpegdma_hw_get E\n");
/* enable all the regulators */
- ret = msm_camera_regulator_enable(dma->vdd,
+ ret = msm_camera_regulator_enable(dma->dma_vdd,
dma->num_reg, true);
if (ret < 0) {
dev_err(dma->dev, "Fail to enable regulators\n");
@@ -1620,7 +1620,7 @@ error_hw_reset:
msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info,
dma->clk, dma->num_clk, false);
error_clocks:
- msm_camera_regulator_enable(dma->vdd, dma->num_reg, false);
+ msm_camera_regulator_enable(dma->dma_vdd, dma->num_reg, false);
error_regulators_get:
mutex_unlock(&dma->lock);
return ret;
@@ -1650,7 +1650,7 @@ void msm_jpegdma_hw_put(struct msm_jpegdma_device *dma)
msm_camera_clk_enable(&dma->pdev->dev, dma->jpeg_clk_info,
dma->clk, dma->num_clk, false);
/* disable all the regulators */
- msm_camera_regulator_enable(dma->vdd, dma->num_reg, false);
+ msm_camera_regulator_enable(dma->dma_vdd, dma->num_reg, false);
}
/* Reset clock rate, need to be updated on next processing */
dma->active_clock_rate = -1;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 203314b182a7..b11e37ffef30 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -210,7 +210,7 @@ struct cpp_device {
struct clk **cpp_clk;
struct msm_cam_clk_info *clk_info;
size_t num_clks;
- struct regulator **cpp_vdd;
+ struct msm_cam_regulator *cpp_vdd;
int num_reg;
struct mutex mutex;
enum cpp_state state;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 7653b1b07cb8..0ad3d9a51f20 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -1022,7 +1022,7 @@ static int32_t msm_actuator_vreg_control(struct msm_actuator_ctrl_t *a_ctrl,
if (!cnt)
return 0;
- if (cnt >= MSM_ACTUATOT_MAX_VREGS) {
+ if (cnt >= MSM_ACTUATOR_MAX_VREGS) {
pr_err("%s failed %d cnt %d\n", __func__, __LINE__, cnt);
return -EINVAL;
}
@@ -1048,6 +1048,8 @@ static int32_t msm_actuator_vreg_control(struct msm_actuator_ctrl_t *a_ctrl,
static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
{
int32_t rc = 0;
+ enum msm_sensor_power_seq_gpio_t gpio;
+
CDBG("Enter\n");
if (a_ctrl->actuator_state != ACT_DISABLE_STATE) {
@@ -1064,6 +1066,41 @@ static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
return rc;
}
+ for (gpio = SENSOR_GPIO_AF_PWDM;
+ gpio < SENSOR_GPIO_MAX; gpio++) {
+ if (a_ctrl->gconf &&
+ a_ctrl->gconf->gpio_num_info &&
+ a_ctrl->gconf->gpio_num_info->
+ valid[gpio] == 1) {
+
+ gpio_set_value_cansleep(
+ a_ctrl->gconf->gpio_num_info->
+ gpio_num[gpio],
+ GPIOF_OUT_INIT_LOW);
+
+ if (a_ctrl->cam_pinctrl_status) {
+ rc = pinctrl_select_state(
+ a_ctrl->pinctrl_info.pinctrl,
+ a_ctrl->pinctrl_info.
+ gpio_state_suspend);
+ if (rc < 0)
+ pr_err("ERR:%s:%d cannot set pin to suspend state: %d",
+ __func__, __LINE__, rc);
+
+ devm_pinctrl_put(
+ a_ctrl->pinctrl_info.pinctrl);
+ }
+ a_ctrl->cam_pinctrl_status = 0;
+ rc = msm_camera_request_gpio_table(
+ a_ctrl->gconf->cam_gpio_req_tbl,
+ a_ctrl->gconf->cam_gpio_req_tbl_size,
+ 0);
+ if (rc < 0)
+ pr_err("ERR:%s:Failed in selecting state in actuator power down: %d\n",
+ __func__, rc);
+ }
+ }
+
kfree(a_ctrl->step_position_table);
a_ctrl->step_position_table = NULL;
kfree(a_ctrl->i2c_reg_tbl);
@@ -1657,6 +1694,8 @@ static long msm_actuator_subdev_fops_ioctl(struct file *file, unsigned int cmd,
static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
+ enum msm_sensor_power_seq_gpio_t gpio;
+
CDBG("%s called\n", __func__);
rc = msm_actuator_vreg_control(a_ctrl, 1);
@@ -1665,6 +1704,33 @@ static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
return rc;
}
+ for (gpio = SENSOR_GPIO_AF_PWDM; gpio < SENSOR_GPIO_MAX; gpio++) {
+ if (a_ctrl->gconf &&
+ a_ctrl->gconf->gpio_num_info &&
+ a_ctrl->gconf->gpio_num_info->valid[gpio] == 1) {
+ rc = msm_camera_request_gpio_table(
+ a_ctrl->gconf->cam_gpio_req_tbl,
+ a_ctrl->gconf->cam_gpio_req_tbl_size, 1);
+ if (rc < 0) {
+ pr_err("ERR:%s:Failed in selecting state for actuator: %d\n",
+ __func__, rc);
+ return rc;
+ }
+ if (a_ctrl->cam_pinctrl_status) {
+ rc = pinctrl_select_state(
+ a_ctrl->pinctrl_info.pinctrl,
+ a_ctrl->pinctrl_info.gpio_state_active);
+ if (rc < 0)
+ pr_err("ERR:%s:%d cannot set pin to active state: %d",
+ __func__, __LINE__, rc);
+ }
+
+ gpio_set_value_cansleep(
+ a_ctrl->gconf->gpio_num_info->gpio_num[gpio],
+ 1);
+ }
+ }
+
/* VREG needs some delay to power up */
usleep_range(2000, 3000);
a_ctrl->actuator_state = ACT_ENABLE_STATE;
@@ -1825,6 +1891,20 @@ static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
return rc;
}
}
+ rc = msm_sensor_driver_get_gpio_data(&(msm_actuator_t->gconf),
+ (&pdev->dev)->of_node);
+ if (rc < 0) {
+ pr_err("%s: No/Error Actuator GPIOs\n", __func__);
+ } else {
+ msm_actuator_t->cam_pinctrl_status = 1;
+ rc = msm_camera_pinctrl_init(
+ &(msm_actuator_t->pinctrl_info), &(pdev->dev));
+ if (rc < 0) {
+ pr_err("ERR:%s: Error in reading actuator pinctrl\n",
+ __func__);
+ msm_actuator_t->cam_pinctrl_status = 0;
+ }
+ }
msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
index fb819a7935cb..3b61ee0acabb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -25,7 +25,7 @@
#define DEFINE_MSM_MUTEX(mutexname) \
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
-#define MSM_ACTUATOT_MAX_VREGS (10)
+#define MSM_ACTUATOR_MAX_VREGS (10)
#define ACTUATOR_MAX_POLL_COUNT 10
struct msm_actuator_ctrl_t;
@@ -68,7 +68,7 @@ struct msm_actuator {
struct msm_actuator_vreg {
struct camera_vreg_t *cam_vreg;
- void *data[MSM_ACTUATOT_MAX_VREGS];
+ void *data[MSM_ACTUATOR_MAX_VREGS];
int num_vreg;
};
@@ -82,7 +82,7 @@ struct msm_actuator_ctrl_t {
enum af_camera_name cam_name;
struct mutex *actuator_mutex;
struct msm_actuator_func_tbl *func_tbl;
- enum msm_actuator_data_type i2c_data_type;
+ enum msm_camera_i2c_data_type i2c_data_type;
struct v4l2_subdev sdev;
struct v4l2_subdev_ops *act_v4l2_subdev_ops;
@@ -105,6 +105,9 @@ struct msm_actuator_ctrl_t {
struct msm_actuator_vreg vreg_cfg;
struct park_lens_data_t park_lens;
uint32_t max_code_size;
+ struct msm_camera_gpio_conf *gconf;
+ struct msm_pinctrl_info pinctrl_info;
+ uint8_t cam_pinctrl_status;
};
#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 97df0d690153..86d61e7a8185 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -681,77 +681,6 @@ static struct v4l2_subdev_ops msm_flash_subdev_ops = {
static const struct v4l2_subdev_internal_ops msm_flash_internal_ops;
-static int32_t msm_flash_get_gpio_dt_data(struct device_node *of_node,
- struct msm_flash_ctrl_t *fctrl)
-{
- int32_t rc = 0, i = 0;
- uint16_t *gpio_array = NULL;
- int16_t gpio_array_size = 0;
- struct msm_camera_gpio_conf *gconf = NULL;
-
- gpio_array_size = of_gpio_count(of_node);
- CDBG("%s gpio count %d\n", __func__, gpio_array_size);
-
- if (gpio_array_size > 0) {
- fctrl->power_info.gpio_conf =
- kzalloc(sizeof(struct msm_camera_gpio_conf),
- GFP_KERNEL);
- if (!fctrl->power_info.gpio_conf) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- rc = -ENOMEM;
- return rc;
- }
- gconf = fctrl->power_info.gpio_conf;
-
- gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
- GFP_KERNEL);
- if (!gpio_array) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- rc = -ENOMEM;
- goto free_gpio_conf;
- }
- for (i = 0; i < gpio_array_size; i++) {
- gpio_array[i] = of_get_gpio(of_node, i);
- if (((int16_t)gpio_array[i]) < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- rc = -EINVAL;
- goto free_gpio_array;
- }
- CDBG("%s gpio_array[%d] = %d\n", __func__, i,
- gpio_array[i]);
- }
-
- rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto free_gpio_array;
- }
-
- rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto free_cam_gpio_req_tbl;
- }
-
- if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
- fctrl->flash_driver_type = FLASH_DRIVER_GPIO;
- CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
- fctrl->flash_driver_type);
- }
-
- return 0;
-
-free_cam_gpio_req_tbl:
- kfree(gconf->cam_gpio_req_tbl);
-free_gpio_array:
- kfree(gpio_array);
-free_gpio_conf:
- kfree(fctrl->power_info.gpio_conf);
- return rc;
-}
-
static int32_t msm_flash_get_pmic_source_info(
struct device_node *of_node,
struct msm_flash_ctrl_t *fctrl)
@@ -977,13 +906,19 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
}
/* Read the gpio information from device tree */
- rc = msm_flash_get_gpio_dt_data(of_node, fctrl);
+ rc = msm_sensor_driver_get_gpio_data(
+ &(fctrl->power_info.gpio_conf), of_node);
if (rc < 0) {
- pr_err("%s:%d msm_flash_get_gpio_dt_data failed rc %d\n",
+ pr_err("%s:%d msm_sensor_driver_get_gpio_data failed rc %d\n",
__func__, __LINE__, rc);
return rc;
}
+ if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT)
+ fctrl->flash_driver_type = FLASH_DRIVER_GPIO;
+ CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
+ fctrl->flash_driver_type);
+
/* Read the flash and torch source info from device tree node */
rc = msm_flash_get_pmic_source_info(of_node, fctrl);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
index 6ad68151d867..af4723520045 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -67,8 +67,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VIO:
@@ -88,8 +86,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VANA:
@@ -109,8 +105,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_VAF:
@@ -130,8 +124,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
break;
case CAM_V_CUSTOM1:
@@ -152,9 +144,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
- break;
case CAM_V_CUSTOM2:
for (j = 0; j < num_vreg; j++) {
@@ -174,8 +163,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
- if (j == num_vreg)
- power_setting[i].seq_val = INVALID_VREG;
break;
default:
@@ -184,7 +171,6 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
break;
}
}
-
return 0;
}
@@ -762,7 +748,6 @@ int msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
rc = -ENOMEM;
return rc;
}
-
rc = of_property_read_u32(of_node, "qcom,gpio-vana", &val);
if (rc != -EINVAL) {
if (rc < 0) {
@@ -1036,6 +1021,7 @@ int msm_camera_get_dt_vreg_data(struct device_node *of_node,
if (!count || (count == -EINVAL)) {
pr_err("%s:%d number of entries is 0 or not present in dts\n",
__func__, __LINE__);
+ *num_vreg = 0;
return 0;
}
@@ -1190,12 +1176,10 @@ static int msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
return 0;
}
-static int msm_camera_pinctrl_init(struct msm_camera_power_ctrl_t *ctrl)
-{
- struct msm_pinctrl_info *sensor_pctrl = NULL;
+int msm_camera_pinctrl_init(
+ struct msm_pinctrl_info *sensor_pctrl, struct device *dev) {
- sensor_pctrl = &ctrl->pinctrl_info;
- sensor_pctrl->pinctrl = devm_pinctrl_get(ctrl->dev);
+ sensor_pctrl->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR_OR_NULL(sensor_pctrl->pinctrl)) {
pr_err("%s:%d Getting pinctrl handle failed\n",
__func__, __LINE__);
@@ -1220,6 +1204,120 @@ static int msm_camera_pinctrl_init(struct msm_camera_power_ctrl_t *ctrl)
return 0;
}
+int msm_cam_sensor_handle_reg_gpio(int seq_val,
+ struct msm_camera_gpio_conf *gconf, int val) {
+
+ int gpio_offset = -1;
+
+ if (!gconf) {
+ pr_err("ERR:%s: Input Parameters are not proper\n", __func__);
+ return -EINVAL;
+ }
+ CDBG("%s: %d Seq val: %d, config: %d", __func__, __LINE__,
+ seq_val, val);
+
+ switch (seq_val) {
+ case CAM_VDIG:
+ gpio_offset = SENSOR_GPIO_VDIG;
+ break;
+
+ case CAM_VIO:
+ gpio_offset = SENSOR_GPIO_VIO;
+ break;
+
+ case CAM_VANA:
+ gpio_offset = SENSOR_GPIO_VANA;
+ break;
+
+ case CAM_VAF:
+ gpio_offset = SENSOR_GPIO_VAF;
+ break;
+
+ case CAM_V_CUSTOM1:
+ gpio_offset = SENSOR_GPIO_CUSTOM1;
+ break;
+
+ case CAM_V_CUSTOM2:
+ gpio_offset = SENSOR_GPIO_CUSTOM2;
+ break;
+
+ default:
+ pr_err("%s:%d Invalid VREG seq val %d\n", __func__,
+ __LINE__, seq_val);
+ return -EINVAL;
+ }
+
+ CDBG("%s: %d GPIO offset: %d, seq_val: %d\n", __func__, __LINE__,
+ gpio_offset, seq_val);
+
+ if ((gconf->gpio_num_info->valid[gpio_offset] == 1)) {
+ gpio_set_value_cansleep(
+ gconf->gpio_num_info->gpio_num
+ [gpio_offset], val);
+ }
+ return 0;
+}
+
+int32_t msm_sensor_driver_get_gpio_data(
+ struct msm_camera_gpio_conf **gpio_conf,
+ struct device_node *of_node)
+{
+ int32_t rc = 0, i = 0;
+ uint16_t *gpio_array = NULL;
+ int16_t gpio_array_size = 0;
+ struct msm_camera_gpio_conf *gconf = NULL;
+
+ /* Validate input parameters */
+ if (!of_node) {
+ pr_err("failed: invalid param of_node %pK", of_node);
+ return -EINVAL;
+ }
+
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("gpio count %d\n", gpio_array_size);
+ if (gpio_array_size <= 0)
+ return 0;
+
+ gconf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+ GFP_KERNEL);
+ if (!gconf)
+ return -ENOMEM;
+
+ *gpio_conf = gconf;
+
+ gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL);
+ if (!gpio_array)
+ goto FREE_GPIO_CONF;
+
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("gpio_array[%d] = %d", i, gpio_array[i]);
+ }
+ rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf, gpio_array,
+ gpio_array_size);
+ if (rc < 0) {
+ pr_err("failed in msm_camera_get_dt_gpio_req_tbl\n");
+ goto FREE_GPIO_CONF;
+ }
+
+ rc = msm_camera_init_gpio_pin_tbl(of_node, gconf, gpio_array,
+ gpio_array_size);
+ if (rc < 0) {
+ pr_err("failed in msm_camera_init_gpio_pin_tbl\n");
+ goto FREE_GPIO_REQ_TBL;
+ }
+ kfree(gpio_array);
+ return rc;
+
+FREE_GPIO_REQ_TBL:
+ kfree(gconf->cam_gpio_req_tbl);
+FREE_GPIO_CONF:
+ kfree(gconf);
+ kfree(gpio_array);
+ *gpio_conf = NULL;
+ return rc;
+}
+
int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client)
@@ -1236,7 +1334,7 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
if (ctrl->gpio_conf->cam_gpiomux_conf_tbl != NULL)
pr_err("%s:%d mux install\n", __func__, __LINE__);
- ret = msm_camera_pinctrl_init(ctrl);
+ ret = msm_camera_pinctrl_init(&(ctrl->pinctrl_info), ctrl->dev);
if (ret < 0) {
pr_err("%s:%d Initialization of pinctrl failed\n",
__func__, __LINE__);
@@ -1303,8 +1401,6 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
(int) power_setting->config_val);
break;
case SENSOR_VREG:
- if (power_setting->seq_val == INVALID_VREG)
- break;
if (power_setting->seq_val >= CAM_VREG_MAX) {
pr_err("%s vreg index %d >= max %d\n", __func__,
power_setting->seq_val,
@@ -1319,9 +1415,18 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
&power_setting->data[0],
1);
else
- pr_err("ERR:%s: %d usr_idx:%d dts_idx:%d\n",
+ pr_err("%s: %d usr_idx:%d dts_idx:%d\n",
__func__, __LINE__,
power_setting->seq_val, ctrl->num_vreg);
+
+ rc = msm_cam_sensor_handle_reg_gpio(
+ power_setting->seq_val,
+ ctrl->gpio_conf, 1);
+ if (rc < 0) {
+ pr_err("ERR:%s Error in handling VREG GPIO\n",
+ __func__);
+ goto power_up_failed;
+ }
break;
case SENSOR_I2C_MUX:
if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
@@ -1348,7 +1453,6 @@ int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
goto power_up_failed;
}
}
-
CDBG("%s exit\n", __func__);
return 0;
power_up_failed:
@@ -1380,6 +1484,9 @@ power_up_failed:
pr_err("%s:%d:seq_val: %d > num_vreg: %d\n",
__func__, __LINE__,
power_setting->seq_val, ctrl->num_vreg);
+
+ msm_cam_sensor_handle_reg_gpio(power_setting->seq_val,
+ ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
break;
case SENSOR_I2C_MUX:
if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
@@ -1505,6 +1612,11 @@ int msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
} else
pr_err("%s error in power up/down seq data\n",
__func__);
+ ret = msm_cam_sensor_handle_reg_gpio(pd->seq_val,
+ ctrl->gpio_conf, GPIOF_OUT_INIT_LOW);
+ if (ret < 0)
+ pr_err("ERR:%s Error while disabling VREG GPIO\n",
+ __func__);
break;
case SENSOR_I2C_MUX:
if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
index baf883fcfc36..220915511cce 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
@@ -15,6 +15,7 @@
#include <soc/qcom/camera2.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/of.h>
#include "msm_camera_i2c.h"
#include "cam_soc_api.h"
@@ -58,4 +59,10 @@ int msm_camera_fill_vreg_params(struct camera_vreg_t *cam_vreg,
int num_vreg, struct msm_sensor_power_setting *power_setting,
uint16_t power_setting_size);
+int msm_camera_pinctrl_init
+ (struct msm_pinctrl_info *sensor_pctrl, struct device *dev);
+
+int32_t msm_sensor_driver_get_gpio_data(
+ struct msm_camera_gpio_conf **gpio_conf,
+ struct device_node *of_node);
#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index 24b2631d1bd5..addefb4e5a58 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -982,70 +982,6 @@ free_slave_info:
return rc;
}
-static int32_t msm_sensor_driver_get_gpio_data(
- struct msm_camera_sensor_board_info *sensordata,
- struct device_node *of_node)
-{
- int32_t rc = 0, i = 0;
- struct msm_camera_gpio_conf *gconf = NULL;
- uint16_t *gpio_array = NULL;
- uint16_t gpio_array_size = 0;
-
- /* Validate input paramters */
- if (!sensordata || !of_node) {
- pr_err("failed: invalid params sensordata %p of_node %p",
- sensordata, of_node);
- return -EINVAL;
- }
-
- sensordata->power_info.gpio_conf = kzalloc(
- sizeof(struct msm_camera_gpio_conf), GFP_KERNEL);
- if (!sensordata->power_info.gpio_conf) {
- pr_err("failed");
- return -ENOMEM;
- }
- gconf = sensordata->power_info.gpio_conf;
-
- gpio_array_size = of_gpio_count(of_node);
- CDBG("gpio count %d", gpio_array_size);
- if (!gpio_array_size)
- return 0;
-
- gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size, GFP_KERNEL);
- if (!gpio_array) {
- pr_err("failed");
- goto FREE_GPIO_CONF;
- }
- for (i = 0; i < gpio_array_size; i++) {
- gpio_array[i] = of_get_gpio(of_node, i);
- CDBG("gpio_array[%d] = %d", i, gpio_array[i]);
- }
-
- rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf, gpio_array,
- gpio_array_size);
- if (rc < 0) {
- pr_err("failed");
- goto FREE_GPIO_CONF;
- }
-
- rc = msm_camera_init_gpio_pin_tbl(of_node, gconf, gpio_array,
- gpio_array_size);
- if (rc < 0) {
- pr_err("failed");
- goto FREE_GPIO_REQ_TBL;
- }
-
- kfree(gpio_array);
- return rc;
-
-FREE_GPIO_REQ_TBL:
- kfree(sensordata->power_info.gpio_conf->cam_gpio_req_tbl);
-FREE_GPIO_CONF:
- kfree(sensordata->power_info.gpio_conf);
- kfree(gpio_array);
- return rc;
-}
-
static int32_t msm_sensor_driver_get_dt_data(struct msm_sensor_ctrl_t *s_ctrl)
{
int32_t rc = 0;
@@ -1113,7 +1049,8 @@ static int32_t msm_sensor_driver_get_dt_data(struct msm_sensor_ctrl_t *s_ctrl)
}
/* Read gpio information */
- rc = msm_sensor_driver_get_gpio_data(sensordata, of_node);
+ rc = msm_sensor_driver_get_gpio_data
+ (&(sensordata->power_info.gpio_conf), of_node);
if (rc < 0) {
pr_err("failed: msm_sensor_driver_get_gpio_data rc %d", rc);
goto FREE_VREG_DATA;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
index fc2c6b6e95b1..947eeafc480c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
@@ -153,6 +153,8 @@ static int32_t msm_ois_vreg_control(struct msm_ois_ctrl_t *o_ctrl,
static int32_t msm_ois_power_down(struct msm_ois_ctrl_t *o_ctrl)
{
int32_t rc = 0;
+ enum msm_sensor_power_seq_gpio_t gpio;
+
CDBG("Enter\n");
if (o_ctrl->ois_state != OIS_DISABLE_STATE) {
@@ -162,6 +164,39 @@ static int32_t msm_ois_power_down(struct msm_ois_ctrl_t *o_ctrl)
return rc;
}
+ for (gpio = SENSOR_GPIO_AF_PWDM; gpio < SENSOR_GPIO_MAX;
+ gpio++) {
+ if (o_ctrl->gconf &&
+ o_ctrl->gconf->gpio_num_info &&
+ o_ctrl->gconf->
+ gpio_num_info->valid[gpio] == 1) {
+ gpio_set_value_cansleep(
+ o_ctrl->gconf->gpio_num_info
+ ->gpio_num[gpio],
+ GPIOF_OUT_INIT_LOW);
+
+ if (o_ctrl->cam_pinctrl_status) {
+ rc = pinctrl_select_state(
+ o_ctrl->pinctrl_info.pinctrl,
+ o_ctrl->pinctrl_info.
+ gpio_state_suspend);
+ if (rc < 0)
+ pr_err("ERR:%s:%d cannot set pin to suspend state: %d",
+ __func__, __LINE__, rc);
+ devm_pinctrl_put(
+ o_ctrl->pinctrl_info.pinctrl);
+ }
+ o_ctrl->cam_pinctrl_status = 0;
+ rc = msm_camera_request_gpio_table(
+ o_ctrl->gconf->cam_gpio_req_tbl,
+ o_ctrl->gconf->cam_gpio_req_tbl_size,
+ 0);
+ if (rc < 0)
+ pr_err("ERR:%s:Failed in selecting state in ois power down: %d\n",
+ __func__, rc);
+ }
+ }
+
o_ctrl->i2c_tbl_index = 0;
o_ctrl->ois_state = OIS_OPS_INACTIVE;
}
@@ -438,6 +473,8 @@ static long msm_ois_subdev_ioctl(struct v4l2_subdev *sd,
static int32_t msm_ois_power_up(struct msm_ois_ctrl_t *o_ctrl)
{
int rc = 0;
+ enum msm_sensor_power_seq_gpio_t gpio;
+
CDBG("%s called\n", __func__);
rc = msm_ois_vreg_control(o_ctrl, 1);
@@ -446,6 +483,33 @@ static int32_t msm_ois_power_up(struct msm_ois_ctrl_t *o_ctrl)
return rc;
}
+ for (gpio = SENSOR_GPIO_AF_PWDM;
+ gpio < SENSOR_GPIO_MAX; gpio++) {
+ if (o_ctrl->gconf && o_ctrl->gconf->gpio_num_info &&
+ o_ctrl->gconf->gpio_num_info->valid[gpio] == 1) {
+ rc = msm_camera_request_gpio_table(
+ o_ctrl->gconf->cam_gpio_req_tbl,
+ o_ctrl->gconf->cam_gpio_req_tbl_size, 1);
+ if (rc < 0) {
+ pr_err("ERR:%s:Failed in selecting state for ois: %d\n",
+ __func__, rc);
+ return rc;
+ }
+ if (o_ctrl->cam_pinctrl_status) {
+ rc = pinctrl_select_state(
+ o_ctrl->pinctrl_info.pinctrl,
+ o_ctrl->pinctrl_info.gpio_state_active);
+ if (rc < 0)
+ pr_err("ERR:%s:%d cannot set pin to active state: %d",
+ __func__, __LINE__, rc);
+ }
+
+ gpio_set_value_cansleep(
+ o_ctrl->gconf->gpio_num_info->gpio_num[gpio],
+ 1);
+ }
+ }
+
o_ctrl->ois_state = OIS_ENABLE_STATE;
CDBG("Exit\n");
return rc;
@@ -662,6 +726,21 @@ static int32_t msm_ois_platform_probe(struct platform_device *pdev)
}
}
+ rc = msm_sensor_driver_get_gpio_data(&(msm_ois_t->gconf),
+ (&pdev->dev)->of_node);
+ if (rc < 0) {
+ pr_err("%s: No/Error OIS GPIO\n", __func__);
+ } else {
+ msm_ois_t->cam_pinctrl_status = 1;
+ rc = msm_camera_pinctrl_init(
+ &(msm_ois_t->pinctrl_info), &(pdev->dev));
+ if (rc < 0) {
+ pr_err("ERR:%s: Error in reading OIS pinctrl\n",
+ __func__);
+ msm_ois_t->cam_pinctrl_status = 0;
+ }
+ }
+
msm_ois_t->ois_v4l2_subdev_ops = &msm_ois_subdev_ops;
msm_ois_t->ois_mutex = &msm_ois_mutex;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
index e6db9ad4ffa0..b9f8d4a0c3c8 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.h
@@ -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
@@ -58,6 +58,9 @@ struct msm_ois_ctrl_t {
uint32_t subdev_id;
enum msm_ois_state_t ois_state;
struct msm_ois_vreg vreg_cfg;
+ struct msm_camera_gpio_conf *gconf;
+ struct msm_pinctrl_info pinctrl_info;
+ uint8_t cam_pinctrl_status;
};
#endif
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 774352f9e256..0c25e8beec3c 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -82,6 +82,12 @@ static const u32 wil_cipher_suites[] = {
WLAN_CIPHER_SUITE_GCMP,
};
+static const char * const key_usage_str[] = {
+ [WMI_KEY_USE_PAIRWISE] = "PTK",
+ [WMI_KEY_USE_RX_GROUP] = "RX_GTK",
+ [WMI_KEY_USE_TX_GROUP] = "TX_GTK",
+};
+
int wil_iftype_nl2wmi(enum nl80211_iftype type)
{
static const struct {
@@ -113,7 +119,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
.interval_usec = 0,
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_notify_req_done_event evt;
} __packed reply;
struct wil_net_stats *stats = &wil->sta[cid].stats;
@@ -313,6 +319,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
cmd.cmd.num_channels = 0;
n = min(request->n_channels, 4U);
for (i = 0; i < n; i++) {
@@ -340,6 +347,11 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
if (rc)
goto out;
+ if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
+ cmd.cmd.discovery_mode = 1;
+ wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
+ }
+
rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
@@ -422,6 +434,11 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
if (sme->privacy && !rsn_eid)
wil_info(wil, "WSC connection\n");
+ if (sme->pbss) {
+ wil_err(wil, "connect - PBSS not yet supported\n");
+ return -EOPNOTSUPP;
+ }
+
bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
sme->ssid, sme->ssid_len,
IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
@@ -535,7 +552,18 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code);
- rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
+ if (!(test_bit(wil_status_fwconnecting, wil->status) ||
+ test_bit(wil_status_fwconnected, wil->status))) {
+ wil_err(wil, "%s: Disconnect was called while disconnected\n",
+ __func__);
+ return 0;
+ }
+
+ rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
+ WMI_DISCONNECT_EVENTID, NULL, 0,
+ WIL6210_DISCONNECT_TO_MS);
+ if (rc)
+ wil_err(wil, "%s: disconnect error %d\n", __func__, rc);
return rc;
}
@@ -552,7 +580,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_mgmt *mgmt_frame = (void *)buf;
struct wmi_sw_tx_req_cmd *cmd;
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_sw_tx_complete_event evt;
} __packed evt;
@@ -594,11 +622,6 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
{
struct wireless_dev *wdev = wil->wdev;
enum wmi_key_usage rc;
- static const char * const key_usage_str[] = {
- [WMI_KEY_USE_PAIRWISE] = "WMI_KEY_USE_PAIRWISE",
- [WMI_KEY_USE_RX_GROUP] = "WMI_KEY_USE_RX_GROUP",
- [WMI_KEY_USE_TX_GROUP] = "WMI_KEY_USE_TX_GROUP",
- };
if (pairwise) {
rc = WMI_KEY_USE_PAIRWISE;
@@ -622,20 +645,86 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
return rc;
}
+static struct wil_tid_crypto_rx_single *
+wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
+ enum wmi_key_usage key_usage, const u8 *mac_addr)
+{
+ int cid = -EINVAL;
+ int tid = 0;
+ struct wil_sta_info *s;
+ struct wil_tid_crypto_rx *c;
+
+ if (key_usage == WMI_KEY_USE_TX_GROUP)
+ return NULL; /* not needed */
+
+ /* supplicant provides Rx group key in STA mode with NULL MAC address */
+ if (mac_addr)
+ cid = wil_find_cid(wil, mac_addr);
+ else if (key_usage == WMI_KEY_USE_RX_GROUP)
+ cid = wil_find_cid_by_idx(wil, 0);
+ if (cid < 0) {
+ wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr,
+ key_usage_str[key_usage], key_index);
+ return ERR_PTR(cid);
+ }
+
+ s = &wil->sta[cid];
+ if (key_usage == WMI_KEY_USE_PAIRWISE)
+ c = &s->tid_crypto_rx[tid];
+ else
+ c = &s->group_crypto_rx;
+
+ return &c->key_id[key_index];
+}
+
static int wil_cfg80211_add_key(struct wiphy *wiphy,
struct net_device *ndev,
u8 key_index, bool pairwise,
const u8 *mac_addr,
struct key_params *params)
{
+ int rc;
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
+ struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
+ key_index,
+ key_usage,
+ mac_addr);
+
+ wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
+ mac_addr, key_usage_str[key_usage], key_index,
+ params->seq_len, params->seq);
+
+ if (IS_ERR(cc)) {
+ wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
+ __func__, mac_addr, key_usage_str[key_usage], key_index,
+ params->seq_len, params->seq);
+ return -EINVAL;
+ }
- wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
- pairwise ? "PTK" : "GTK");
+ if (cc)
+ cc->key_set = false;
- return wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
- params->key, key_usage);
+ if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
+ wil_err(wil,
+ "Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n",
+ params->seq_len, __func__, mac_addr,
+ key_usage_str[key_usage], key_index,
+ params->seq_len, params->seq);
+ return -EINVAL;
+ }
+
+ rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
+ params->key, key_usage);
+ if ((rc == 0) && cc) {
+ if (params->seq)
+ memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
+ else
+ memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
+ cc->key_set = true;
+ }
+
+ return rc;
}
static int wil_cfg80211_del_key(struct wiphy *wiphy,
@@ -645,9 +734,20 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
+ struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
+ key_index,
+ key_usage,
+ mac_addr);
+
+ wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
+ key_usage_str[key_usage], key_index);
- wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
- pairwise ? "PTK" : "GTK");
+ if (IS_ERR(cc))
+ wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
+ mac_addr, key_usage_str[key_usage], key_index);
+
+ if (!IS_ERR_OR_NULL(cc))
+ cc->key_set = false;
return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
}
@@ -938,6 +1038,11 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
return -EINVAL;
}
+ if (info->pbss) {
+ wil_err(wil, "AP: PBSS not yet supported\n");
+ return -EOPNOTSUPP;
+ }
+
switch (info->hidden_ssid) {
case NL80211_HIDDEN_SSID_NOT_IN_USE:
hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 97bc186f9728..96169cb0dfd0 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,6 +37,7 @@ enum dbg_off_type {
doff_x32 = 1,
doff_ulong = 2,
doff_io32 = 3,
+ doff_u8 = 4
};
/* offset to "wil" */
@@ -68,13 +69,13 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
seq_puts(s, "???\n");
}
- if (vring->va && (vring->size < 1025)) {
+ if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) {
uint i;
for (i = 0; i < vring->size; i++) {
volatile struct vring_tx_desc *d = &vring->va[i].tx;
- if ((i % 64) == 0 && (i != 0))
+ if ((i % 128) == 0 && (i != 0))
seq_puts(s, "\n");
seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
_s : (vring->ctx[i].skb ? _h : 'h'));
@@ -346,6 +347,10 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil,
tbl[i].mode, dbg,
base + tbl[i].off);
break;
+ case doff_u8:
+ f = debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg,
+ base + tbl[i].off);
+ break;
default:
f = ERR_PTR(-EINVAL);
}
@@ -827,9 +832,9 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
struct wil6210_priv *wil = file->private_data;
- struct wil6210_mbox_hdr_wmi *wmi;
+ struct wmi_cmd_hdr *wmi;
void *cmd;
- int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
+ int cmdlen = len - sizeof(struct wmi_cmd_hdr);
u16 cmdid;
int rc, rc1;
@@ -847,7 +852,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
}
cmd = &wmi[1];
- cmdid = le16_to_cpu(wmi->id);
+ cmdid = le16_to_cpu(wmi->command_id);
rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
kfree(wmi);
@@ -991,7 +996,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
.interval_usec = 0,
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_notify_req_done_event evt;
} __packed reply;
@@ -1339,6 +1344,34 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
r->ssn_last_drop);
}
+static void wil_print_rxtid_crypto(struct seq_file *s, int tid,
+ struct wil_tid_crypto_rx *c)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ struct wil_tid_crypto_rx_single *cc = &c->key_id[i];
+
+ if (cc->key_set)
+ goto has_keys;
+ }
+ return;
+
+has_keys:
+ if (tid < WIL_STA_TID_NUM)
+ seq_printf(s, " [%2d] PN", tid);
+ else
+ seq_puts(s, " [GR] PN");
+
+ for (i = 0; i < 4; i++) {
+ struct wil_tid_crypto_rx_single *cc = &c->key_id[i];
+
+ seq_printf(s, " [%i%s]%6phN", i, cc->key_set ? "+" : "-",
+ cc->pn);
+ }
+ seq_puts(s, "\n");
+}
+
static int wil_sta_debugfs_show(struct seq_file *s, void *data)
__acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
{
@@ -1366,18 +1399,25 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
spin_lock_bh(&p->tid_rx_lock);
for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
struct wil_tid_ampdu_rx *r = p->tid_rx[tid];
+ struct wil_tid_crypto_rx *c =
+ &p->tid_crypto_rx[tid];
if (r) {
- seq_printf(s, "[%2d] ", tid);
+ seq_printf(s, " [%2d] ", tid);
wil_print_rxtid(s, r);
}
+
+ wil_print_rxtid_crypto(s, tid, c);
}
+ wil_print_rxtid_crypto(s, WIL_STA_TID_NUM,
+ &p->group_crypto_rx);
spin_unlock_bh(&p->tid_rx_lock);
seq_printf(s,
- "Rx invalid frame: non-data %lu, short %lu, large %lu\n",
+ "Rx invalid frame: non-data %lu, short %lu, large %lu, replay %lu\n",
p->stats.rx_non_data_frame,
p->stats.rx_short_frame,
- p->stats.rx_large_frame);
+ p->stats.rx_large_frame,
+ p->stats.rx_replay);
seq_puts(s, "Rx/MCS:");
for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
@@ -1493,6 +1533,7 @@ static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(hw_version, S_IRUGO, doff_x32),
WIL_FIELD(recovery_count, S_IRUGO, doff_u32),
WIL_FIELD(ap_isolate, S_IRUGO, doff_u32),
+ WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR, doff_u8),
{},
};
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 4f2ffa5c6e17..ae902958bf55 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -394,9 +394,10 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
wil_fw_core_dump(wil);
wil_notify_fw_error(wil);
isr &= ~ISR_MISC_FW_ERROR;
- if (wil->platform_ops.notify_crash) {
+ if (wil->platform_ops.notify) {
wil_err(wil, "notify platform driver about FW crash");
- wil->platform_ops.notify_crash(wil->platform_handle);
+ wil->platform_ops.notify(wil->platform_handle,
+ WIL_PLATFORM_EVT_FW_CRASH);
} else {
wil_fw_error_recovery(wil);
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 26606ef49d61..f1bdcf4c783b 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -23,9 +23,6 @@
#include "wmi.h"
#include "boot_loader.h"
-#define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
-#define WAIT_FOR_DISCONNECT_INTERVAL_MS 10
-
bool debug_fw; /* = false; */
module_param(debug_fw, bool, S_IRUGO);
MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
@@ -152,7 +149,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
might_sleep();
wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
sta->status);
-
+ /* inform upper/lower layers */
if (sta->status != wil_sta_unused) {
if (!from_event)
wmi_disconnect_sta(wil, sta->addr, reason_code, true);
@@ -168,7 +165,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
}
sta->status = wil_sta_unused;
}
-
+ /* reorder buffers */
for (i = 0; i < WIL_STA_TID_NUM; i++) {
struct wil_tid_ampdu_rx *r;
@@ -180,10 +177,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
spin_unlock_bh(&sta->tid_rx_lock);
}
+ /* crypto context */
+ memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx));
+ memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx));
+ /* release vrings */
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
if (wil->vring2cid_tid[i][0] == cid)
wil_vring_fini_tx(wil, i);
}
+ /* statistics */
memset(&sta->stats, 0, sizeof(sta->stats));
}
@@ -438,10 +440,11 @@ int wil_priv_init(struct wil6210_priv *wil)
for (i = 0; i < WIL6210_MAX_CID; i++)
spin_lock_init(&wil->sta[i].tid_rx_lock);
+ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
+ spin_lock_init(&wil->vring_tx_data[i].lock);
+
mutex_init(&wil->mutex);
mutex_init(&wil->wmi_mutex);
- mutex_init(&wil->back_rx_mutex);
- mutex_init(&wil->back_tx_mutex);
mutex_init(&wil->probe_client_mutex);
init_completion(&wil->wmi_ready);
@@ -454,13 +457,9 @@ int wil_priv_init(struct wil6210_priv *wil)
INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
- INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker);
- INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker);
INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
INIT_LIST_HEAD(&wil->pending_wmi_ev);
- INIT_LIST_HEAD(&wil->back_rx_pending);
- INIT_LIST_HEAD(&wil->back_tx_pending);
INIT_LIST_HEAD(&wil->probe_client_pending);
spin_lock_init(&wil->wmi_ev_lock);
init_waitqueue_head(&wil->wq);
@@ -520,10 +519,6 @@ void wil_priv_deinit(struct wil6210_priv *wil)
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
mutex_unlock(&wil->mutex);
wmi_event_flush(wil);
- wil_back_rx_flush(wil);
- cancel_work_sync(&wil->back_rx_worker);
- wil_back_tx_flush(wil);
- cancel_work_sync(&wil->back_tx_worker);
wil_probe_client_flush(wil);
cancel_work_sync(&wil->probe_client_worker);
destroy_workqueue(wil->wq_service);
@@ -622,8 +617,7 @@ static int wil_target_reset(struct wil6210_priv *wil)
BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC);
/* Enable fix for PCIe HW bug, set "No snoop" for RX transactions */
- wil_s(wil, RGF_DMA_PEDI_DIF, BIT_DMA_WR_CMD_ATTR_NO_SNOOP |
- BIT_DMA_WR_CMD_ATTR_RELAXED_ORDERING);
+ wil_s(wil, RGF_DMA_PEDI_DIF, BIT_DMA_WR_CMD_ATTR_NO_SNOOP);
wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
return 0;
@@ -641,6 +635,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
static int wil_get_bl_info(struct wil6210_priv *wil)
{
struct net_device *ndev = wil_to_ndev(wil);
+ struct wiphy *wiphy = wil_to_wiphy(wil);
union {
struct bl_dedicated_registers_v0 bl0;
struct bl_dedicated_registers_v1 bl1;
@@ -685,6 +680,7 @@ static int wil_get_bl_info(struct wil6210_priv *wil)
}
ether_addr_copy(ndev->perm_addr, mac);
+ ether_addr_copy(wiphy->perm_addr, mac);
if (!is_valid_ether_addr(ndev->dev_addr))
ether_addr_copy(ndev->dev_addr, mac);
@@ -771,6 +767,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
if (wil->hw_version == HW_VER_UNKNOWN)
return -ENODEV;
+ if (wil->platform_ops.notify) {
+ rc = wil->platform_ops.notify(wil->platform_handle,
+ WIL_PLATFORM_EVT_PRE_RESET);
+ if (rc)
+ wil_err(wil,
+ "%s: PRE_RESET platform notify failed, rc %d\n",
+ __func__, rc);
+ }
+
set_bit(wil_status_resetting, wil->status);
cancel_work_sync(&wil->disconnect_worker);
@@ -850,8 +855,27 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
/* we just started MAC, wait for FW ready */
rc = wil_wait_for_fw_ready(wil);
- if (rc == 0) /* check FW is responsive */
- rc = wmi_echo(wil);
+ if (rc)
+ return rc;
+
+ /* check FW is responsive */
+ rc = wmi_echo(wil);
+ if (rc) {
+ wil_err(wil, "%s: wmi_echo failed, rc %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (wil->platform_ops.notify) {
+ rc = wil->platform_ops.notify(wil->platform_handle,
+ WIL_PLATFORM_EVT_FW_RDY);
+ if (rc) {
+ wil_err(wil,
+ "%s: FW_RDY notify failed, rc %d\n",
+ __func__, rc);
+ rc = 0;
+ }
+ }
}
return rc;
@@ -943,8 +967,7 @@ int wil_up(struct wil6210_priv *wil)
int __wil_down(struct wil6210_priv *wil)
{
- int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS /
- WAIT_FOR_DISCONNECT_INTERVAL_MS;
+ int rc;
WARN_ON(!mutex_is_locked(&wil->mutex));
@@ -968,22 +991,16 @@ int __wil_down(struct wil6210_priv *wil)
}
if (test_bit(wil_status_fwconnected, wil->status) ||
- test_bit(wil_status_fwconnecting, wil->status))
- wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
+ test_bit(wil_status_fwconnecting, wil->status)) {
- /* make sure wil is idle (not connected) */
- mutex_unlock(&wil->mutex);
- while (iter--) {
- int idle = !test_bit(wil_status_fwconnected, wil->status) &&
- !test_bit(wil_status_fwconnecting, wil->status);
- if (idle)
- break;
- msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS);
+ mutex_unlock(&wil->mutex);
+ rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
+ WMI_DISCONNECT_EVENTID, NULL, 0,
+ WIL6210_DISCONNECT_TO_MS);
+ mutex_lock(&wil->mutex);
+ if (rc)
+ wil_err(wil, "timeout waiting for disconnect\n");
}
- mutex_lock(&wil->mutex);
-
- if (iter < 0)
- wil_err(wil, "timeout waiting for idle FW/HW\n");
wil_reset(wil, false);
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 32031e7a11d5..19ed127d4d05 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -291,35 +291,15 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
return min(max_agg_size, req_agg_wsize);
}
-/* Block Ack - Rx side (recipient */
+/* Block Ack - Rx side (recipient) */
int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl)
-{
- struct wil_back_rx *req = kzalloc(sizeof(*req), GFP_KERNEL);
-
- if (!req)
- return -ENOMEM;
-
- req->cidxtid = cidxtid;
- req->dialog_token = dialog_token;
- req->ba_param_set = le16_to_cpu(ba_param_set);
- req->ba_timeout = le16_to_cpu(ba_timeout);
- req->ba_seq_ctrl = le16_to_cpu(ba_seq_ctrl);
-
- mutex_lock(&wil->back_rx_mutex);
- list_add_tail(&req->list, &wil->back_rx_pending);
- mutex_unlock(&wil->back_rx_mutex);
-
- queue_work(wil->wq_service, &wil->back_rx_worker);
-
- return 0;
-}
-
-static void wil_back_rx_handle(struct wil6210_priv *wil,
- struct wil_back_rx *req)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
+ u16 param_set = le16_to_cpu(ba_param_set);
+ u16 agg_timeout = le16_to_cpu(ba_timeout);
+ u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl);
struct wil_sta_info *sta;
u8 cid, tid;
u16 agg_wsize = 0;
@@ -328,34 +308,35 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
* bits 2..5: TID
* bits 6..15: buffer size
*/
- u16 req_agg_wsize = WIL_GET_BITS(req->ba_param_set, 6, 15);
- bool agg_amsdu = !!(req->ba_param_set & BIT(0));
- int ba_policy = req->ba_param_set & BIT(1);
- u16 agg_timeout = req->ba_timeout;
+ u16 req_agg_wsize = WIL_GET_BITS(param_set, 6, 15);
+ bool agg_amsdu = !!(param_set & BIT(0));
+ int ba_policy = param_set & BIT(1);
u16 status = WLAN_STATUS_SUCCESS;
- u16 ssn = req->ba_seq_ctrl >> 4;
+ u16 ssn = seq_ctrl >> 4;
struct wil_tid_ampdu_rx *r;
- int rc;
+ int rc = 0;
might_sleep();
- parse_cidxtid(req->cidxtid, &cid, &tid);
+ parse_cidxtid(cidxtid, &cid, &tid);
/* sanity checks */
if (cid >= WIL6210_MAX_CID) {
wil_err(wil, "BACK: invalid CID %d\n", cid);
- return;
+ rc = -EINVAL;
+ goto out;
}
sta = &wil->sta[cid];
if (sta->status != wil_sta_connected) {
wil_err(wil, "BACK: CID %d not connected\n", cid);
- return;
+ rc = -EINVAL;
+ goto out;
}
wil_dbg_wmi(wil,
"ADDBA request for CID %d %pM TID %d size %d timeout %d AMSDU%s policy %d token %d SSN 0x%03x\n",
- cid, sta->addr, tid, req_agg_wsize, req->ba_timeout,
- agg_amsdu ? "+" : "-", !!ba_policy, req->dialog_token, ssn);
+ cid, sta->addr, tid, req_agg_wsize, agg_timeout,
+ agg_amsdu ? "+" : "-", !!ba_policy, dialog_token, ssn);
/* apply policies */
if (ba_policy) {
@@ -365,10 +346,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
if (status == WLAN_STATUS_SUCCESS)
agg_wsize = wil_agg_size(wil, req_agg_wsize);
- rc = wmi_addba_rx_resp(wil, cid, tid, req->dialog_token, status,
+ rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status,
agg_amsdu, agg_wsize, agg_timeout);
- if (rc || (status != WLAN_STATUS_SUCCESS))
- return;
+ if (rc || (status != WLAN_STATUS_SUCCESS)) {
+ wil_err(wil, "%s: do not apply ba, rc(%d), status(%d)\n",
+ __func__, rc, status);
+ goto out;
+ }
/* apply */
r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn);
@@ -376,143 +360,37 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]);
sta->tid_rx[tid] = r;
spin_unlock_bh(&sta->tid_rx_lock);
-}
-
-void wil_back_rx_flush(struct wil6210_priv *wil)
-{
- struct wil_back_rx *evt, *t;
- wil_dbg_misc(wil, "%s()\n", __func__);
-
- mutex_lock(&wil->back_rx_mutex);
-
- list_for_each_entry_safe(evt, t, &wil->back_rx_pending, list) {
- list_del(&evt->list);
- kfree(evt);
- }
-
- mutex_unlock(&wil->back_rx_mutex);
-}
-
-/* Retrieve next ADDBA request from the pending list */
-static struct list_head *next_back_rx(struct wil6210_priv *wil)
-{
- struct list_head *ret = NULL;
-
- mutex_lock(&wil->back_rx_mutex);
-
- if (!list_empty(&wil->back_rx_pending)) {
- ret = wil->back_rx_pending.next;
- list_del(ret);
- }
-
- mutex_unlock(&wil->back_rx_mutex);
-
- return ret;
-}
-
-void wil_back_rx_worker(struct work_struct *work)
-{
- struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
- back_rx_worker);
- struct wil_back_rx *evt;
- struct list_head *lh;
-
- while ((lh = next_back_rx(wil)) != NULL) {
- evt = list_entry(lh, struct wil_back_rx, list);
-
- wil_back_rx_handle(wil, evt);
- kfree(evt);
- }
+out:
+ return rc;
}
-/* BACK - Tx (originator) side */
-static void wil_back_tx_handle(struct wil6210_priv *wil,
- struct wil_back_tx *req)
+/* BACK - Tx side (originator) */
+int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
{
- struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid];
- int rc;
+ u8 agg_wsize = wil_agg_size(wil, wsize);
+ u16 agg_timeout = 0;
+ struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
+ int rc = 0;
if (txdata->addba_in_progress) {
wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n",
- req->ringid);
- return;
+ ringid);
+ goto out;
}
if (txdata->agg_wsize) {
wil_dbg_misc(wil,
- "ADDBA for vring[%d] already established wsize %d\n",
- req->ringid, txdata->agg_wsize);
- return;
+ "ADDBA for vring[%d] already done for wsize %d\n",
+ ringid, txdata->agg_wsize);
+ goto out;
}
txdata->addba_in_progress = true;
- rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout);
- if (rc)
+ rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout);
+ if (rc) {
+ wil_err(wil, "%s: wmi_addba failed, rc (%d)", __func__, rc);
txdata->addba_in_progress = false;
-}
-
-static struct list_head *next_back_tx(struct wil6210_priv *wil)
-{
- struct list_head *ret = NULL;
-
- mutex_lock(&wil->back_tx_mutex);
-
- if (!list_empty(&wil->back_tx_pending)) {
- ret = wil->back_tx_pending.next;
- list_del(ret);
- }
-
- mutex_unlock(&wil->back_tx_mutex);
-
- return ret;
-}
-
-void wil_back_tx_worker(struct work_struct *work)
-{
- struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
- back_tx_worker);
- struct wil_back_tx *evt;
- struct list_head *lh;
-
- while ((lh = next_back_tx(wil)) != NULL) {
- evt = list_entry(lh, struct wil_back_tx, list);
-
- wil_back_tx_handle(wil, evt);
- kfree(evt);
}
-}
-
-void wil_back_tx_flush(struct wil6210_priv *wil)
-{
- struct wil_back_tx *evt, *t;
-
- wil_dbg_misc(wil, "%s()\n", __func__);
-
- mutex_lock(&wil->back_tx_mutex);
-
- list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) {
- list_del(&evt->list);
- kfree(evt);
- }
-
- mutex_unlock(&wil->back_tx_mutex);
-}
-
-int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
-{
- struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL);
-
- if (!req)
- return -ENOMEM;
- req->ringid = ringid;
- req->agg_wsize = wil_agg_size(wil, wsize);
- req->agg_timeout = 0;
-
- mutex_lock(&wil->back_tx_mutex);
- list_add_tail(&req->list, &wil->back_tx_pending);
- mutex_unlock(&wil->back_tx_mutex);
-
- queue_work(wil->wq_service, &wil->back_tx_worker);
-
- return 0;
+out:
+ return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h
index e59239d22b94..c4db2a9d9f7f 100644
--- a/drivers/net/wireless/ath/wil6210/trace.h
+++ b/drivers/net/wireless/ath/wil6210/trace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ * Copyright (c) 2013-2016 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,39 +37,40 @@ static inline void trace_ ## name(proto) {}
#endif /* !CONFIG_WIL6210_TRACING || defined(__CHECKER__) */
DECLARE_EVENT_CLASS(wil6210_wmi,
- TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+ TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
TP_ARGS(wmi, buf, buf_len),
TP_STRUCT__entry(
__field(u8, mid)
- __field(u16, id)
- __field(u32, timestamp)
+ __field(u16, command_id)
+ __field(u32, fw_timestamp)
__field(u16, buf_len)
__dynamic_array(u8, buf, buf_len)
),
TP_fast_assign(
__entry->mid = wmi->mid;
- __entry->id = le16_to_cpu(wmi->id);
- __entry->timestamp = le32_to_cpu(wmi->timestamp);
+ __entry->command_id = le16_to_cpu(wmi->command_id);
+ __entry->fw_timestamp = le32_to_cpu(wmi->fw_timestamp);
__entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len);
),
TP_printk(
"MID %d id 0x%04x len %d timestamp %d",
- __entry->mid, __entry->id, __entry->buf_len, __entry->timestamp
+ __entry->mid, __entry->command_id, __entry->buf_len,
+ __entry->fw_timestamp
)
);
DEFINE_EVENT(wil6210_wmi, wil6210_wmi_cmd,
- TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+ TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
TP_ARGS(wmi, buf, buf_len)
);
DEFINE_EVENT(wil6210_wmi, wil6210_wmi_event,
- TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+ TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
TP_ARGS(wmi, buf, buf_len)
);
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 9680b970b863..f260b232fd57 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -549,6 +549,60 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count)
return rc;
}
+/**
+ * reverse_memcmp - Compare two areas of memory, in reverse order
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ *
+ * Cut'n'paste from original memcmp (see lib/string.c)
+ * with minimal modifications
+ */
+static int reverse_memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs + count - 1, su2 = ct + count - 1; count > 0;
+ --su1, --su2, count--) {
+ res = *su1 - *su2;
+ if (res)
+ break;
+ }
+ return res;
+}
+
+static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
+{
+ struct vring_rx_desc *d = wil_skb_rxdesc(skb);
+ int cid = wil_rxdesc_cid(d);
+ int tid = wil_rxdesc_tid(d);
+ int key_id = wil_rxdesc_key_id(d);
+ int mc = wil_rxdesc_mcast(d);
+ struct wil_sta_info *s = &wil->sta[cid];
+ struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
+ &s->tid_crypto_rx[tid];
+ struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
+ const u8 *pn = (u8 *)&d->mac.pn_15_0;
+
+ if (!cc->key_set) {
+ wil_err_ratelimited(wil,
+ "Key missing. CID %d TID %d MCast %d KEY_ID %d\n",
+ cid, tid, mc, key_id);
+ return -EINVAL;
+ }
+
+ if (reverse_memcmp(pn, cc->pn, IEEE80211_GCMP_PN_LEN) <= 0) {
+ wil_err_ratelimited(wil,
+ "Replay attack. CID %d TID %d MCast %d KEY_ID %d PN %6phN last %6phN\n",
+ cid, tid, mc, key_id, pn, cc->pn);
+ return -EINVAL;
+ }
+ memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+ return 0;
+}
+
/*
* Pass Rx packet to the netif. Update statistics.
* Called in softirq context (NAPI poll).
@@ -561,6 +615,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
unsigned int len = skb->len;
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
+ int security = wil_rxdesc_security(d);
struct ethhdr *eth = (void *)skb->data;
/* here looking for DA, not A1, thus Rxdesc's 'mcast' indication
* is not suitable, need to look at data
@@ -586,6 +641,13 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
skb_orphan(skb);
+ if (security && (wil_rx_crypto_check(wil, skb) != 0)) {
+ rc = GRO_DROP;
+ dev_kfree_skb(skb);
+ stats->rx_replay++;
+ goto stats;
+ }
+
if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) {
if (mcast) {
/* send multicast frames both to higher layers in
@@ -627,6 +689,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n",
len, gro_res_str[rc]);
}
+stats:
/* statistics. rc set to GRO_NORMAL for AP bridging */
if (unlikely(rc == GRO_DROP)) {
ndev->stats.rx_dropped++;
@@ -717,6 +780,21 @@ void wil_rx_fini(struct wil6210_priv *wil)
wil_vring_free(wil, vring, 0);
}
+static inline void wil_tx_data_init(struct vring_tx_data *txdata)
+{
+ spin_lock_bh(&txdata->lock);
+ txdata->dot1x_open = 0;
+ txdata->enabled = 0;
+ txdata->idle = 0;
+ txdata->last_idle = 0;
+ txdata->begin = 0;
+ txdata->agg_wsize = 0;
+ txdata->agg_timeout = 0;
+ txdata->agg_amsdu = 0;
+ txdata->addba_in_progress = false;
+ spin_unlock_bh(&txdata->lock);
+}
+
int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
int cid, int tid)
{
@@ -742,7 +820,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
},
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_vring_cfg_done_event cmd;
} __packed reply;
struct vring *vring = &wil->vring_tx[id];
@@ -758,8 +836,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
goto out;
}
- memset(txdata, 0, sizeof(*txdata));
- spin_lock_init(&txdata->lock);
+ wil_tx_data_init(txdata);
vring->size = size;
rc = wil_vring_alloc(wil, vring);
if (rc)
@@ -791,8 +868,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
return 0;
out_free:
+ spin_lock_bh(&txdata->lock);
txdata->dot1x_open = false;
txdata->enabled = 0;
+ spin_unlock_bh(&txdata->lock);
wil_vring_free(wil, vring, 1);
wil->vring2cid_tid[id][0] = WIL6210_MAX_CID;
wil->vring2cid_tid[id][1] = 0;
@@ -818,7 +897,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
},
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_vring_cfg_done_event cmd;
} __packed reply;
struct vring *vring = &wil->vring_tx[id];
@@ -834,8 +913,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
goto out;
}
- memset(txdata, 0, sizeof(*txdata));
- spin_lock_init(&txdata->lock);
+ wil_tx_data_init(txdata);
vring->size = size;
rc = wil_vring_alloc(wil, vring);
if (rc)
@@ -865,8 +943,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
return 0;
out_free:
+ spin_lock_bh(&txdata->lock);
txdata->enabled = 0;
txdata->dot1x_open = false;
+ spin_unlock_bh(&txdata->lock);
wil_vring_free(wil, vring, 1);
out:
@@ -894,7 +974,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
napi_synchronize(&wil->napi_tx);
wil_vring_free(wil, vring, 1);
- memset(txdata, 0, sizeof(*txdata));
}
static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index ee7c7b4b9a17..fcdffaa8251b 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -480,6 +480,16 @@ static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
return WIL_GET_BITS(d->mac.d0, 28, 31);
}
+static inline int wil_rxdesc_key_id(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 4, 5);
+}
+
+static inline int wil_rxdesc_security(struct vring_rx_desc *d)
+{
+ return WIL_GET_BITS(d->mac.d1, 7, 7);
+}
+
static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d1, 8, 9);
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index e07ce3832c27..fa0df00c1c11 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -22,6 +22,7 @@
#include <net/cfg80211.h>
#include <linux/timex.h>
#include <linux/types.h>
+#include "wmi.h"
#include "wil_platform.h"
extern bool no_fw_recovery;
@@ -51,7 +52,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
#define WIL_TX_Q_LEN_DEFAULT (4000)
#define WIL_RX_RING_SIZE_ORDER_DEFAULT (10)
-#define WIL_TX_RING_SIZE_ORDER_DEFAULT (10)
+#define WIL_TX_RING_SIZE_ORDER_DEFAULT (12)
#define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7)
#define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */
/* limit ring size in range [32..32k] */
@@ -92,6 +93,7 @@ static inline u32 wil_mtu2macbuf(u32 mtu)
#define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */
#define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000)
#define WIL6210_SCAN_TO msecs_to_jiffies(10000)
+#define WIL6210_DISCONNECT_TO_MS (2000)
#define WIL6210_RX_HIGH_TRSH_INIT (0)
#define WIL6210_RX_HIGH_TRSH_DEFAULT \
(1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3))
@@ -336,29 +338,11 @@ struct wil6210_mbox_hdr {
/* max. value for wil6210_mbox_hdr.len */
#define MAX_MBOXITEM_SIZE (240)
-/**
- * struct wil6210_mbox_hdr_wmi - WMI header
- *
- * @mid: MAC ID
- * 00 - default, created by FW
- * 01..0f - WiFi ports, driver to create
- * 10..fe - debug
- * ff - broadcast
- * @id: command/event ID
- * @timestamp: FW fills for events, free-running msec timer
- */
-struct wil6210_mbox_hdr_wmi {
- u8 mid;
- u8 reserved;
- __le16 id;
- __le32 timestamp;
-} __packed;
-
struct pending_wmi_event {
struct list_head list;
struct {
struct wil6210_mbox_hdr hdr;
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
u8 data[0];
} __packed event;
};
@@ -457,6 +441,21 @@ struct wil_tid_ampdu_rx {
bool first_time; /* is it 1-st time this buffer used? */
};
+/**
+ * struct wil_tid_crypto_rx_single - TID crypto information (Rx).
+ *
+ * @pn: GCMP PN for the session
+ * @key_set: valid key present
+ */
+struct wil_tid_crypto_rx_single {
+ u8 pn[IEEE80211_GCMP_PN_LEN];
+ bool key_set;
+};
+
+struct wil_tid_crypto_rx {
+ struct wil_tid_crypto_rx_single key_id[4];
+};
+
enum wil_sta_status {
wil_sta_unused = 0,
wil_sta_conn_pending = 1,
@@ -476,6 +475,7 @@ struct wil_net_stats {
unsigned long rx_non_data_frame;
unsigned long rx_short_frame;
unsigned long rx_large_frame;
+ unsigned long rx_replay;
u16 last_mcs_rx;
u64 rx_per_mcs[WIL_MCS_MAX + 1];
};
@@ -497,6 +497,8 @@ struct wil_sta_info {
spinlock_t tid_rx_lock; /* guarding tid_rx array */
unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)];
unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)];
+ struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM];
+ struct wil_tid_crypto_rx group_crypto_rx;
};
enum {
@@ -509,24 +511,6 @@ enum {
hw_capability_last
};
-struct wil_back_rx {
- struct list_head list;
- /* request params, converted to CPU byte order - what we asked for */
- u8 cidxtid;
- u8 dialog_token;
- u16 ba_param_set;
- u16 ba_timeout;
- u16 ba_seq_ctrl;
-};
-
-struct wil_back_tx {
- struct list_head list;
- /* request params, converted to CPU byte order - what we asked for */
- u8 ringid;
- u8 agg_wsize;
- u16 agg_timeout;
-};
-
struct wil_probe_client_req {
struct list_head list;
u64 cookie;
@@ -597,13 +581,6 @@ struct wil6210_priv {
spinlock_t wmi_ev_lock;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
- /* BACK */
- struct list_head back_rx_pending;
- struct mutex back_rx_mutex; /* protect @back_rx_pending */
- struct work_struct back_rx_worker;
- struct list_head back_tx_pending;
- struct mutex back_tx_mutex; /* protect @back_tx_pending */
- struct work_struct back_tx_worker;
/* keep alive */
struct list_head probe_client_pending;
struct mutex probe_client_mutex; /* protect @probe_client_pending */
@@ -624,6 +601,7 @@ struct wil6210_priv {
/* debugfs */
struct dentry *debug;
struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
+ u8 discovery_mode;
void *platform_handle;
struct wil_platform_ops platform_ops;
@@ -767,11 +745,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
u8 dialog_token, __le16 ba_param_set,
__le16 ba_timeout, __le16 ba_seq_ctrl);
-void wil_back_rx_worker(struct work_struct *work);
-void wil_back_rx_flush(struct wil6210_priv *wil);
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
-void wil_back_tx_worker(struct work_struct *work);
-void wil_back_tx_flush(struct wil6210_priv *wil);
void wil6210_clear_irq(struct wil6210_priv *wil);
int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h
index 9a949d910343..33d4a34b3b1c 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -19,6 +19,12 @@
struct device;
+enum wil_platform_event {
+ WIL_PLATFORM_EVT_FW_CRASH = 0,
+ WIL_PLATFORM_EVT_PRE_RESET = 1,
+ WIL_PLATFORM_EVT_FW_RDY = 2,
+};
+
/**
* struct wil_platform_ops - wil platform module calls from this
* driver to platform driver
@@ -28,7 +34,7 @@ struct wil_platform_ops {
int (*suspend)(void *handle);
int (*resume)(void *handle);
void (*uninit)(void *handle);
- int (*notify_crash)(void *handle);
+ int (*notify)(void *handle, enum wil_platform_event evt);
};
/**
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index e1a6cb8840ed..db7d2b602d1a 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -176,7 +176,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
{
struct {
struct wil6210_mbox_hdr hdr;
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
} __packed cmd = {
.hdr = {
.type = WIL_MBOX_HDR_TYPE_WMI,
@@ -185,7 +185,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
},
.wmi = {
.mid = 0,
- .id = cpu_to_le16(cmdid),
+ .command_id = cpu_to_le16(cmdid),
},
};
struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
@@ -487,6 +487,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
return;
}
del_timer_sync(&wil->connect_timer);
+ } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
+ (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
+ if (wil->sta[evt->cid].status != wil_sta_unused) {
+ wil_err(wil, "%s: AP: Invalid status %d for CID %d\n",
+ __func__, wil->sta[evt->cid].status, evt->cid);
+ mutex_unlock(&wil->mutex);
+ return;
+ }
}
/* FIXME FW can transmit only ucast frames to peer */
@@ -648,7 +656,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
int len)
{
- struct wmi_vring_ba_status_event *evt = d;
+ struct wmi_ba_status_event *evt = d;
struct vring_tx_data *txdata;
wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
@@ -834,10 +842,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
offsetof(struct wil6210_mbox_ring_desc, sync), 0);
/* indicate */
if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
- (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
- struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
- u16 id = le16_to_cpu(wmi->id);
- u32 tstamp = le32_to_cpu(wmi->timestamp);
+ (len >= sizeof(struct wmi_cmd_hdr))) {
+ struct wmi_cmd_hdr *wmi = &evt->event.wmi;
+ u16 id = le16_to_cpu(wmi->command_id);
+ u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
+ spin_lock_irqsave(&wil->wmi_ev_lock, flags);
if (wil->reply_id && wil->reply_id == id) {
if (wil->reply_buf) {
memcpy(wil->reply_buf, wmi,
@@ -845,6 +854,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
immed_reply = true;
}
}
+ spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
id, wmi->mid, tstamp);
@@ -888,13 +898,16 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
mutex_lock(&wil->wmi_mutex);
+ spin_lock(&wil->wmi_ev_lock);
+ wil->reply_id = reply_id;
+ wil->reply_buf = reply;
+ wil->reply_size = reply_size;
+ spin_unlock(&wil->wmi_ev_lock);
+
rc = __wmi_send(wil, cmdid, buf, len);
if (rc)
goto out;
- wil->reply_id = reply_id;
- wil->reply_buf = reply;
- wil->reply_size = reply_size;
remain = wait_for_completion_timeout(&wil->wmi_call,
msecs_to_jiffies(to_msec));
if (0 == remain) {
@@ -907,10 +920,14 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
cmdid, reply_id,
to_msec - jiffies_to_msecs(remain));
}
+
+out:
+ spin_lock(&wil->wmi_ev_lock);
wil->reply_id = 0;
wil->reply_buf = NULL;
wil->reply_size = 0;
- out:
+ spin_unlock(&wil->wmi_ev_lock);
+
mutex_unlock(&wil->wmi_mutex);
return rc;
@@ -951,7 +968,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
.hidden_ssid = hidden_ssid,
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_pcp_started_event evt;
} __packed reply;
@@ -1005,7 +1022,7 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
{
int rc;
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_set_ssid_cmd cmd;
} __packed reply;
int len; /* reply.cmd.ssid_len in CPU order */
@@ -1038,7 +1055,7 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
{
int rc;
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_set_pcp_channel_cmd cmd;
} __packed reply;
@@ -1146,7 +1163,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
{
int rc;
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_listen_started_event evt;
} __packed reply;
@@ -1183,7 +1200,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
.host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_cfg_rx_chain_done_event evt;
} __packed evt;
int rc;
@@ -1237,7 +1254,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
.measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_temp_sense_done_event evt;
} __packed reply;
@@ -1263,7 +1280,7 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
.disconnect_reason = cpu_to_le16(reason),
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_disconnect_event evt;
} __packed reply;
@@ -1355,7 +1372,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
.ba_timeout = cpu_to_le16(timeout),
};
struct {
- struct wil6210_mbox_hdr_wmi wmi;
+ struct wmi_cmd_hdr wmi;
struct wmi_rcp_addba_resp_sent_event evt;
} __packed reply;
@@ -1411,10 +1428,10 @@ static void wmi_event_handle(struct wil6210_priv *wil,
u16 len = le16_to_cpu(hdr->len);
if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
- (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
- struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
+ (len >= sizeof(struct wmi_cmd_hdr))) {
+ struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
void *evt_data = (void *)(&wmi[1]);
- u16 id = le16_to_cpu(wmi->id);
+ u16 id = le16_to_cpu(wmi->command_id);
wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
id, wil->reply_id);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index 6e90e78f1554..29865e0b5203 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
- * Copyright (c) 2006-2012 Wilocity .
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2006-2012 Wilocity
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,187 +17,197 @@
/*
* This file contains the definitions of the WMI protocol specified in the
- * Wireless Module Interface (WMI) for the Wilocity
- * MARLON 60 Gigabit wireless solution.
+ * Wireless Module Interface (WMI) for the Qualcomm
+ * 60 GHz wireless solution.
* It includes definitions of all the commands and events.
* Commands are messages from the host to the WM.
* Events are messages from the WM to the host.
+ *
+ * This is an automatically generated file.
*/
#ifndef __WILOCITY_WMI_H__
#define __WILOCITY_WMI_H__
/* General */
-#define WILOCITY_MAX_ASSOC_STA (8)
-#define WILOCITY_DEFAULT_ASSOC_STA (1)
-#define WMI_MAC_LEN (6)
-#define WMI_PROX_RANGE_NUM (3)
-#define WMI_MAX_LOSS_DMG_BEACONS (32)
+#define WMI_MAX_ASSOC_STA (8)
+#define WMI_DEFAULT_ASSOC_STA (1)
+#define WMI_MAC_LEN (6)
+#define WMI_PROX_RANGE_NUM (3)
+#define WMI_MAX_LOSS_DMG_BEACONS (20)
+
+/* Mailbox interface
+ * used for commands and events
+ */
+enum wmi_mid {
+ MID_DEFAULT = 0x00,
+ FIRST_DBG_MID_ID = 0x10,
+ LAST_DBG_MID_ID = 0xFE,
+ MID_BROADCAST = 0xFF,
+};
+
+/* WMI_CMD_HDR */
+struct wmi_cmd_hdr {
+ u8 mid;
+ u8 reserved;
+ __le16 command_id;
+ __le32 fw_timestamp;
+} __packed;
/* List of Commands */
enum wmi_command_id {
- WMI_CONNECT_CMDID = 0x0001,
- WMI_DISCONNECT_CMDID = 0x0003,
- WMI_DISCONNECT_STA_CMDID = 0x0004,
- WMI_START_SCAN_CMDID = 0x0007,
- WMI_SET_BSS_FILTER_CMDID = 0x0009,
- WMI_SET_PROBED_SSID_CMDID = 0x000a,
- WMI_SET_LISTEN_INT_CMDID = 0x000b,
- WMI_BCON_CTRL_CMDID = 0x000f,
- WMI_ADD_CIPHER_KEY_CMDID = 0x0016,
- WMI_DELETE_CIPHER_KEY_CMDID = 0x0017,
- WMI_SET_APPIE_CMDID = 0x003f,
- WMI_SET_WSC_STATUS_CMDID = 0x0041,
- WMI_PXMT_RANGE_CFG_CMDID = 0x0042,
- WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043,
-/* WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, */
- WMI_MEM_READ_CMDID = 0x0800,
- WMI_MEM_WR_CMDID = 0x0801,
- WMI_ECHO_CMDID = 0x0803,
- WMI_DEEP_ECHO_CMDID = 0x0804,
- WMI_CONFIG_MAC_CMDID = 0x0805,
- WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806,
- WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808,
- WMI_PHY_GET_STATISTICS_CMDID = 0x0809,
- WMI_FS_TUNE_CMDID = 0x080a,
- WMI_CORR_MEASURE_CMDID = 0x080b,
- WMI_READ_RSSI_CMDID = 0x080c,
- WMI_TEMP_SENSE_CMDID = 0x080e,
- WMI_DC_CALIB_CMDID = 0x080f,
- WMI_SEND_TONE_CMDID = 0x0810,
- WMI_IQ_TX_CALIB_CMDID = 0x0811,
- WMI_IQ_RX_CALIB_CMDID = 0x0812,
- WMI_SET_UCODE_IDLE_CMDID = 0x0813,
- WMI_SET_WORK_MODE_CMDID = 0x0815,
- WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816,
- WMI_MARLON_R_READ_CMDID = 0x0818,
- WMI_MARLON_R_WRITE_CMDID = 0x0819,
- WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a,
- MAC_IO_STATIC_PARAMS_CMDID = 0x081b,
- MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c,
- WMI_SILENT_RSSI_CALIB_CMDID = 0x081d,
- WMI_RF_RX_TEST_CMDID = 0x081e,
- WMI_CFG_RX_CHAIN_CMDID = 0x0820,
- WMI_VRING_CFG_CMDID = 0x0821,
- WMI_BCAST_VRING_CFG_CMDID = 0x0822,
- WMI_VRING_BA_EN_CMDID = 0x0823,
- WMI_VRING_BA_DIS_CMDID = 0x0824,
- WMI_RCP_ADDBA_RESP_CMDID = 0x0825,
- WMI_RCP_DELBA_CMDID = 0x0826,
- WMI_SET_SSID_CMDID = 0x0827,
- WMI_GET_SSID_CMDID = 0x0828,
- WMI_SET_PCP_CHANNEL_CMDID = 0x0829,
- WMI_GET_PCP_CHANNEL_CMDID = 0x082a,
- WMI_SW_TX_REQ_CMDID = 0x082b,
- WMI_READ_MAC_RXQ_CMDID = 0x0830,
- WMI_READ_MAC_TXQ_CMDID = 0x0831,
- WMI_WRITE_MAC_RXQ_CMDID = 0x0832,
- WMI_WRITE_MAC_TXQ_CMDID = 0x0833,
- WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834,
- WMI_MLME_PUSH_CMDID = 0x0835,
- WMI_BEAMFORMING_MGMT_CMDID = 0x0836,
- WMI_BF_TXSS_MGMT_CMDID = 0x0837,
- WMI_BF_SM_MGMT_CMDID = 0x0838,
- WMI_BF_RXSS_MGMT_CMDID = 0x0839,
- WMI_BF_TRIG_CMDID = 0x083A,
- WMI_SET_SECTORS_CMDID = 0x0849,
- WMI_MAINTAIN_PAUSE_CMDID = 0x0850,
- WMI_MAINTAIN_RESUME_CMDID = 0x0851,
- WMI_RS_MGMT_CMDID = 0x0852,
- WMI_RF_MGMT_CMDID = 0x0853,
- WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x0854,
- WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x0855,
+ WMI_CONNECT_CMDID = 0x01,
+ WMI_DISCONNECT_CMDID = 0x03,
+ WMI_DISCONNECT_STA_CMDID = 0x04,
+ WMI_START_SCAN_CMDID = 0x07,
+ WMI_SET_BSS_FILTER_CMDID = 0x09,
+ WMI_SET_PROBED_SSID_CMDID = 0x0A,
+ WMI_SET_LISTEN_INT_CMDID = 0x0B,
+ WMI_BCON_CTRL_CMDID = 0x0F,
+ WMI_ADD_CIPHER_KEY_CMDID = 0x16,
+ WMI_DELETE_CIPHER_KEY_CMDID = 0x17,
+ WMI_PCP_CONF_CMDID = 0x18,
+ WMI_SET_APPIE_CMDID = 0x3F,
+ WMI_SET_WSC_STATUS_CMDID = 0x41,
+ WMI_PXMT_RANGE_CFG_CMDID = 0x42,
+ WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x43,
+ WMI_MEM_READ_CMDID = 0x800,
+ WMI_MEM_WR_CMDID = 0x801,
+ WMI_ECHO_CMDID = 0x803,
+ WMI_DEEP_ECHO_CMDID = 0x804,
+ WMI_CONFIG_MAC_CMDID = 0x805,
+ WMI_CONFIG_PHY_DEBUG_CMDID = 0x806,
+ WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x808,
+ WMI_PHY_GET_STATISTICS_CMDID = 0x809,
+ WMI_FS_TUNE_CMDID = 0x80A,
+ WMI_CORR_MEASURE_CMDID = 0x80B,
+ WMI_READ_RSSI_CMDID = 0x80C,
+ WMI_TEMP_SENSE_CMDID = 0x80E,
+ WMI_DC_CALIB_CMDID = 0x80F,
+ WMI_SEND_TONE_CMDID = 0x810,
+ WMI_IQ_TX_CALIB_CMDID = 0x811,
+ WMI_IQ_RX_CALIB_CMDID = 0x812,
+ WMI_SET_UCODE_IDLE_CMDID = 0x813,
+ WMI_SET_WORK_MODE_CMDID = 0x815,
+ WMI_LO_LEAKAGE_CALIB_CMDID = 0x816,
+ WMI_MARLON_R_READ_CMDID = 0x818,
+ WMI_MARLON_R_WRITE_CMDID = 0x819,
+ WMI_MARLON_R_TXRX_SEL_CMDID = 0x81A,
+ MAC_IO_STATIC_PARAMS_CMDID = 0x81B,
+ MAC_IO_DYNAMIC_PARAMS_CMDID = 0x81C,
+ WMI_SILENT_RSSI_CALIB_CMDID = 0x81D,
+ WMI_RF_RX_TEST_CMDID = 0x81E,
+ WMI_CFG_RX_CHAIN_CMDID = 0x820,
+ WMI_VRING_CFG_CMDID = 0x821,
+ WMI_BCAST_VRING_CFG_CMDID = 0x822,
+ WMI_VRING_BA_EN_CMDID = 0x823,
+ WMI_VRING_BA_DIS_CMDID = 0x824,
+ WMI_RCP_ADDBA_RESP_CMDID = 0x825,
+ WMI_RCP_DELBA_CMDID = 0x826,
+ WMI_SET_SSID_CMDID = 0x827,
+ WMI_GET_SSID_CMDID = 0x828,
+ WMI_SET_PCP_CHANNEL_CMDID = 0x829,
+ WMI_GET_PCP_CHANNEL_CMDID = 0x82A,
+ WMI_SW_TX_REQ_CMDID = 0x82B,
+ WMI_READ_MAC_RXQ_CMDID = 0x830,
+ WMI_READ_MAC_TXQ_CMDID = 0x831,
+ WMI_WRITE_MAC_RXQ_CMDID = 0x832,
+ WMI_WRITE_MAC_TXQ_CMDID = 0x833,
+ WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x834,
+ WMI_MLME_PUSH_CMDID = 0x835,
+ WMI_BEAMFORMING_MGMT_CMDID = 0x836,
+ WMI_BF_TXSS_MGMT_CMDID = 0x837,
+ WMI_BF_SM_MGMT_CMDID = 0x838,
+ WMI_BF_RXSS_MGMT_CMDID = 0x839,
+ WMI_BF_TRIG_CMDID = 0x83A,
+ WMI_SET_SECTORS_CMDID = 0x849,
+ WMI_MAINTAIN_PAUSE_CMDID = 0x850,
+ WMI_MAINTAIN_RESUME_CMDID = 0x851,
+ WMI_RS_MGMT_CMDID = 0x852,
+ WMI_RF_MGMT_CMDID = 0x853,
+ WMI_THERMAL_THROTTLING_CTRL_CMDID = 0x854,
+ WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855,
+ WMI_OTP_READ_CMDID = 0x856,
+ WMI_OTP_WRITE_CMDID = 0x857,
/* Performance monitoring commands */
- WMI_BF_CTRL_CMDID = 0x0862,
- WMI_NOTIFY_REQ_CMDID = 0x0863,
- WMI_GET_STATUS_CMDID = 0x0864,
- WMI_UNIT_TEST_CMDID = 0x0900,
- WMI_HICCUP_CMDID = 0x0901,
- WMI_FLASH_READ_CMDID = 0x0902,
- WMI_FLASH_WRITE_CMDID = 0x0903,
- WMI_SECURITY_UNIT_TEST_CMDID = 0x0904,
- /*P2P*/
- WMI_P2P_CFG_CMDID = 0x0910,
- WMI_PORT_ALLOCATE_CMDID = 0x0911,
- WMI_PORT_DELETE_CMDID = 0x0912,
- WMI_POWER_MGMT_CFG_CMDID = 0x0913,
- WMI_START_LISTEN_CMDID = 0x0914,
- WMI_START_SEARCH_CMDID = 0x0915,
- WMI_DISCOVERY_START_CMDID = 0x0916,
- WMI_DISCOVERY_STOP_CMDID = 0x0917,
- WMI_PCP_START_CMDID = 0x0918,
- WMI_PCP_STOP_CMDID = 0x0919,
- WMI_GET_PCP_FACTOR_CMDID = 0x091b,
-
- WMI_SET_MAC_ADDRESS_CMDID = 0xf003,
- WMI_ABORT_SCAN_CMDID = 0xf007,
- WMI_SET_PMK_CMDID = 0xf028,
-
- WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041,
- WMI_GET_PMK_CMDID = 0xf048,
- WMI_SET_PASSPHRASE_CMDID = 0xf049,
- WMI_SEND_ASSOC_RES_CMDID = 0xf04a,
- WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b,
- WMI_EAPOL_TX_CMDID = 0xf04c,
- WMI_MAC_ADDR_REQ_CMDID = 0xf04d,
- WMI_FW_VER_CMDID = 0xf04e,
- WMI_PMC_CMDID = 0xf04f,
+ WMI_BF_CTRL_CMDID = 0x862,
+ WMI_NOTIFY_REQ_CMDID = 0x863,
+ WMI_GET_STATUS_CMDID = 0x864,
+ WMI_UNIT_TEST_CMDID = 0x900,
+ WMI_HICCUP_CMDID = 0x901,
+ WMI_FLASH_READ_CMDID = 0x902,
+ WMI_FLASH_WRITE_CMDID = 0x903,
+ /* P2P */
+ WMI_P2P_CFG_CMDID = 0x910,
+ WMI_PORT_ALLOCATE_CMDID = 0x911,
+ WMI_PORT_DELETE_CMDID = 0x912,
+ WMI_POWER_MGMT_CFG_CMDID = 0x913,
+ WMI_START_LISTEN_CMDID = 0x914,
+ WMI_START_SEARCH_CMDID = 0x915,
+ WMI_DISCOVERY_START_CMDID = 0x916,
+ WMI_DISCOVERY_STOP_CMDID = 0x917,
+ WMI_PCP_START_CMDID = 0x918,
+ WMI_PCP_STOP_CMDID = 0x919,
+ WMI_GET_PCP_FACTOR_CMDID = 0x91B,
+ WMI_SET_MAC_ADDRESS_CMDID = 0xF003,
+ WMI_ABORT_SCAN_CMDID = 0xF007,
+ WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041,
+ WMI_GET_PMK_CMDID = 0xF048,
+ WMI_SET_PASSPHRASE_CMDID = 0xF049,
+ WMI_SEND_ASSOC_RES_CMDID = 0xF04A,
+ WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xF04B,
+ WMI_MAC_ADDR_REQ_CMDID = 0xF04D,
+ WMI_FW_VER_CMDID = 0xF04E,
+ WMI_PMC_CMDID = 0xF04F,
};
-/*
- * Commands data structures
- */
-
-/*
- * WMI_CONNECT_CMDID
- */
+/* WMI_CONNECT_CMDID */
enum wmi_network_type {
WMI_NETTYPE_INFRA = 0x01,
WMI_NETTYPE_ADHOC = 0x02,
WMI_NETTYPE_ADHOC_CREATOR = 0x04,
WMI_NETTYPE_AP = 0x10,
WMI_NETTYPE_P2P = 0x20,
- WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */
+ /* PCIE over 60g */
+ WMI_NETTYPE_WBE = 0x40,
};
enum wmi_dot11_auth_mode {
- WMI_AUTH11_OPEN = 0x01,
- WMI_AUTH11_SHARED = 0x02,
- WMI_AUTH11_LEAP = 0x04,
- WMI_AUTH11_WSC = 0x08,
+ WMI_AUTH11_OPEN = 0x01,
+ WMI_AUTH11_SHARED = 0x02,
+ WMI_AUTH11_LEAP = 0x04,
+ WMI_AUTH11_WSC = 0x08,
};
enum wmi_auth_mode {
- WMI_AUTH_NONE = 0x01,
- WMI_AUTH_WPA = 0x02,
- WMI_AUTH_WPA2 = 0x04,
- WMI_AUTH_WPA_PSK = 0x08,
- WMI_AUTH_WPA2_PSK = 0x10,
- WMI_AUTH_WPA_CCKM = 0x20,
- WMI_AUTH_WPA2_CCKM = 0x40,
+ WMI_AUTH_NONE = 0x01,
+ WMI_AUTH_WPA = 0x02,
+ WMI_AUTH_WPA2 = 0x04,
+ WMI_AUTH_WPA_PSK = 0x08,
+ WMI_AUTH_WPA2_PSK = 0x10,
+ WMI_AUTH_WPA_CCKM = 0x20,
+ WMI_AUTH_WPA2_CCKM = 0x40,
};
enum wmi_crypto_type {
- WMI_CRYPT_NONE = 0x01,
- WMI_CRYPT_WEP = 0x02,
- WMI_CRYPT_TKIP = 0x04,
- WMI_CRYPT_AES = 0x08,
- WMI_CRYPT_AES_GCMP = 0x20,
+ WMI_CRYPT_NONE = 0x01,
+ WMI_CRYPT_AES_GCMP = 0x20,
};
enum wmi_connect_ctrl_flag_bits {
- WMI_CONNECT_ASSOC_POLICY_USER = 0x0001,
- WMI_CONNECT_SEND_REASSOC = 0x0002,
- WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x0004,
- WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008,
- WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010,
- WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020,
- WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040,
- WMI_CONNECT_DO_NOT_DEAUTH = 0x0080,
+ WMI_CONNECT_ASSOC_POLICY_USER = 0x01,
+ WMI_CONNECT_SEND_REASSOC = 0x02,
+ WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER = 0x04,
+ WMI_CONNECT_PROFILE_MATCH_DONE = 0x08,
+ WMI_CONNECT_IGNORE_AAC_BEACON = 0x10,
+ WMI_CONNECT_CSA_FOLLOW_BSS = 0x20,
+ WMI_CONNECT_DO_WPA_OFFLOAD = 0x40,
+ WMI_CONNECT_DO_NOT_DEAUTH = 0x80,
};
-#define WMI_MAX_SSID_LEN (32)
+#define WMI_MAX_SSID_LEN (32)
+/* WMI_CONNECT_CMDID */
struct wmi_connect_cmd {
u8 network_type;
u8 dot11_auth_mode;
@@ -216,31 +226,17 @@ struct wmi_connect_cmd {
u8 reserved1[2];
} __packed;
-/*
- * WMI_DISCONNECT_STA_CMDID
- */
+/* WMI_DISCONNECT_STA_CMDID */
struct wmi_disconnect_sta_cmd {
u8 dst_mac[WMI_MAC_LEN];
__le16 disconnect_reason;
} __packed;
-/*
- * WMI_SET_PMK_CMDID
- */
-
-#define WMI_MIN_KEY_INDEX (0)
#define WMI_MAX_KEY_INDEX (3)
#define WMI_MAX_KEY_LEN (32)
#define WMI_PASSPHRASE_LEN (64)
-#define WMI_PMK_LEN (32)
-
-struct wmi_set_pmk_cmd {
- u8 pmk[WMI_PMK_LEN];
-} __packed;
-/*
- * WMI_SET_PASSPHRASE_CMDID
- */
+/* WMI_SET_PASSPHRASE_CMDID */
struct wmi_set_passphrase_cmd {
u8 ssid[WMI_MAX_SSID_LEN];
u8 passphrase[WMI_PASSPHRASE_LEN];
@@ -248,36 +244,34 @@ struct wmi_set_passphrase_cmd {
u8 passphrase_len;
} __packed;
-/*
- * WMI_ADD_CIPHER_KEY_CMDID
- */
+/* WMI_ADD_CIPHER_KEY_CMDID */
enum wmi_key_usage {
- WMI_KEY_USE_PAIRWISE = 0,
- WMI_KEY_USE_RX_GROUP = 1,
- WMI_KEY_USE_TX_GROUP = 2,
+ WMI_KEY_USE_PAIRWISE = 0x00,
+ WMI_KEY_USE_RX_GROUP = 0x01,
+ WMI_KEY_USE_TX_GROUP = 0x02,
};
struct wmi_add_cipher_key_cmd {
u8 key_index;
u8 key_type;
- u8 key_usage; /* enum wmi_key_usage */
+ /* enum wmi_key_usage */
+ u8 key_usage;
u8 key_len;
- u8 key_rsc[8]; /* key replay sequence counter */
+ /* key replay sequence counter */
+ u8 key_rsc[8];
u8 key[WMI_MAX_KEY_LEN];
- u8 key_op_ctrl; /* Additional Key Control information */
+ /* Additional Key Control information */
+ u8 key_op_ctrl;
u8 mac[WMI_MAC_LEN];
} __packed;
-/*
- * WMI_DELETE_CIPHER_KEY_CMDID
- */
+/* WMI_DELETE_CIPHER_KEY_CMDID */
struct wmi_delete_cipher_key_cmd {
u8 key_index;
u8 mac[WMI_MAC_LEN];
} __packed;
-/*
- * WMI_START_SCAN_CMDID
+/* WMI_START_SCAN_CMDID
*
* Start L1 scan operation
*
@@ -286,146 +280,142 @@ struct wmi_delete_cipher_key_cmd {
* - WMI_SCAN_COMPLETE_EVENTID
*/
enum wmi_scan_type {
- WMI_LONG_SCAN = 0,
- WMI_SHORT_SCAN = 1,
- WMI_PBC_SCAN = 2,
- WMI_DIRECT_SCAN = 3,
- WMI_ACTIVE_SCAN = 4,
+ WMI_ACTIVE_SCAN = 0x00,
+ WMI_SHORT_SCAN = 0x01,
+ WMI_PASSIVE_SCAN = 0x02,
+ WMI_DIRECT_SCAN = 0x03,
+ WMI_LONG_SCAN = 0x04,
};
+/* WMI_START_SCAN_CMDID */
struct wmi_start_scan_cmd {
- u8 direct_scan_mac_addr[6];
- u8 reserved[2];
- __le32 home_dwell_time; /* Max duration in the home channel(ms) */
- __le32 force_scan_interval; /* Time interval between scans (ms)*/
- u8 scan_type; /* wmi_scan_type */
- u8 num_channels; /* how many channels follow */
+ u8 direct_scan_mac_addr[WMI_MAC_LEN];
+ /* DMG Beacon frame is transmitted during active scanning */
+ u8 discovery_mode;
+ /* reserved */
+ u8 reserved;
+ /* Max duration in the home channel(ms) */
+ __le32 dwell_time;
+ /* Time interval between scans (ms) */
+ __le32 force_scan_interval;
+ /* enum wmi_scan_type */
+ u8 scan_type;
+ /* how many channels follow */
+ u8 num_channels;
+ /* channels ID's:
+ * 0 - 58320 MHz
+ * 1 - 60480 MHz
+ * 2 - 62640 MHz
+ */
struct {
u8 channel;
u8 reserved;
- } channel_list[0]; /* channels ID's */
- /* 0 - 58320 MHz */
- /* 1 - 60480 MHz */
- /* 2 - 62640 MHz */
+ } channel_list[0];
} __packed;
-/*
- * WMI_SET_PROBED_SSID_CMDID
- */
+/* WMI_SET_PROBED_SSID_CMDID */
#define MAX_PROBED_SSID_INDEX (3)
enum wmi_ssid_flag {
- WMI_SSID_FLAG_DISABLE = 0, /* disables entry */
- WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */
- WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */
+ /* disables entry */
+ WMI_SSID_FLAG_DISABLE = 0x00,
+ /* probes specified ssid */
+ WMI_SSID_FLAG_SPECIFIC = 0x01,
+ /* probes for any ssid */
+ WMI_SSID_FLAG_ANY = 0x02,
};
struct wmi_probed_ssid_cmd {
- u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */
- u8 flag; /* enum wmi_ssid_flag */
+ /* 0 to MAX_PROBED_SSID_INDEX */
+ u8 entry_index;
+ /* enum wmi_ssid_flag */
+ u8 flag;
u8 ssid_len;
u8 ssid[WMI_MAX_SSID_LEN];
} __packed;
-/*
- * WMI_SET_APPIE_CMDID
+/* WMI_SET_APPIE_CMDID
* Add Application specified IE to a management frame
*/
-#define WMI_MAX_IE_LEN (1024)
+#define WMI_MAX_IE_LEN (1024)
-/*
- * Frame Types
- */
+/* Frame Types */
enum wmi_mgmt_frame_type {
- WMI_FRAME_BEACON = 0,
- WMI_FRAME_PROBE_REQ = 1,
- WMI_FRAME_PROBE_RESP = 2,
- WMI_FRAME_ASSOC_REQ = 3,
- WMI_FRAME_ASSOC_RESP = 4,
- WMI_NUM_MGMT_FRAME,
+ WMI_FRAME_BEACON = 0x00,
+ WMI_FRAME_PROBE_REQ = 0x01,
+ WMI_FRAME_PROBE_RESP = 0x02,
+ WMI_FRAME_ASSOC_REQ = 0x03,
+ WMI_FRAME_ASSOC_RESP = 0x04,
+ WMI_NUM_MGMT_FRAME = 0x05,
};
struct wmi_set_appie_cmd {
- u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */
+ /* enum wmi_mgmt_frame_type */
+ u8 mgmt_frm_type;
u8 reserved;
- __le16 ie_len; /* Length of the IE to be added to MGMT frame */
+ /* Length of the IE to be added to MGMT frame */
+ __le16 ie_len;
u8 ie_info[0];
} __packed;
-/*
- * WMI_PXMT_RANGE_CFG_CMDID
- */
+/* WMI_PXMT_RANGE_CFG_CMDID */
struct wmi_pxmt_range_cfg_cmd {
u8 dst_mac[WMI_MAC_LEN];
__le16 range;
} __packed;
-/*
- * WMI_PXMT_SNR2_RANGE_CFG_CMDID
- */
+/* WMI_PXMT_SNR2_RANGE_CFG_CMDID */
struct wmi_pxmt_snr2_range_cfg_cmd {
- s8 snr2range_arr[WMI_PROX_RANGE_NUM-1];
+ s8 snr2range_arr[2];
} __packed;
-/*
- * WMI_RF_MGMT_CMDID
- */
+/* WMI_RF_MGMT_CMDID */
enum wmi_rf_mgmt_type {
- WMI_RF_MGMT_W_DISABLE = 0,
- WMI_RF_MGMT_W_ENABLE = 1,
- WMI_RF_MGMT_GET_STATUS = 2,
+ WMI_RF_MGMT_W_DISABLE = 0x00,
+ WMI_RF_MGMT_W_ENABLE = 0x01,
+ WMI_RF_MGMT_GET_STATUS = 0x02,
};
+/* WMI_RF_MGMT_CMDID */
struct wmi_rf_mgmt_cmd {
__le32 rf_mgmt_type;
} __packed;
-/*
- * WMI_THERMAL_THROTTLING_CTRL_CMDID
- */
+/* WMI_THERMAL_THROTTLING_CTRL_CMDID */
#define THERMAL_THROTTLING_USE_DEFAULT_MAX_TXOP_LENGTH (0xFFFFFFFF)
+/* WMI_THERMAL_THROTTLING_CTRL_CMDID */
struct wmi_thermal_throttling_ctrl_cmd {
__le32 time_on_usec;
__le32 time_off_usec;
__le32 max_txop_length_usec;
} __packed;
-/*
- * WMI_RF_RX_TEST_CMDID
- */
+/* WMI_RF_RX_TEST_CMDID */
struct wmi_rf_rx_test_cmd {
__le32 sector;
} __packed;
-/*
- * WMI_CORR_MEASURE_CMDID
- */
+/* WMI_CORR_MEASURE_CMDID */
struct wmi_corr_measure_cmd {
- s32 freq_mhz;
+ __le32 freq_mhz;
__le32 length_samples;
__le32 iterations;
} __packed;
-/*
- * WMI_SET_SSID_CMDID
- */
+/* WMI_SET_SSID_CMDID */
struct wmi_set_ssid_cmd {
__le32 ssid_len;
u8 ssid[WMI_MAX_SSID_LEN];
} __packed;
-/*
- * WMI_SET_PCP_CHANNEL_CMDID
- */
+/* WMI_SET_PCP_CHANNEL_CMDID */
struct wmi_set_pcp_channel_cmd {
u8 channel;
u8 reserved[3];
} __packed;
-/*
- * WMI_BCON_CTRL_CMDID
- */
+/* WMI_BCON_CTRL_CMDID */
struct wmi_bcon_ctrl_cmd {
__le16 bcon_interval;
__le16 frag_num;
@@ -434,214 +424,192 @@ struct wmi_bcon_ctrl_cmd {
u8 pcp_max_assoc_sta;
u8 disable_sec_offload;
u8 disable_sec;
+ u8 hidden_ssid;
+ u8 is_go;
+ u8 reserved[2];
} __packed;
-/******* P2P ***********/
-
-/*
- * WMI_PORT_ALLOCATE_CMDID
- */
+/* WMI_PORT_ALLOCATE_CMDID */
enum wmi_port_role {
- WMI_PORT_STA = 0,
- WMI_PORT_PCP = 1,
- WMI_PORT_AP = 2,
- WMI_PORT_P2P_DEV = 3,
- WMI_PORT_P2P_CLIENT = 4,
- WMI_PORT_P2P_GO = 5,
+ WMI_PORT_STA = 0x00,
+ WMI_PORT_PCP = 0x01,
+ WMI_PORT_AP = 0x02,
+ WMI_PORT_P2P_DEV = 0x03,
+ WMI_PORT_P2P_CLIENT = 0x04,
+ WMI_PORT_P2P_GO = 0x05,
};
+/* WMI_PORT_ALLOCATE_CMDID */
struct wmi_port_allocate_cmd {
u8 mac[WMI_MAC_LEN];
u8 port_role;
u8 mid;
} __packed;
-/*
- * WMI_PORT_DELETE_CMDID
- */
-struct wmi_delete_port_cmd {
+/* WMI_PORT_DELETE_CMDID */
+struct wmi_port_delete_cmd {
u8 mid;
u8 reserved[3];
} __packed;
-/*
- * WMI_P2P_CFG_CMDID
- */
+/* WMI_P2P_CFG_CMDID */
enum wmi_discovery_mode {
- WMI_DISCOVERY_MODE_NON_OFFLOAD = 0,
- WMI_DISCOVERY_MODE_OFFLOAD = 1,
- WMI_DISCOVERY_MODE_PEER2PEER = 2,
+ WMI_DISCOVERY_MODE_NON_OFFLOAD = 0x00,
+ WMI_DISCOVERY_MODE_OFFLOAD = 0x01,
+ WMI_DISCOVERY_MODE_PEER2PEER = 0x02,
};
struct wmi_p2p_cfg_cmd {
- u8 discovery_mode; /* wmi_discovery_mode */
+ /* enum wmi_discovery_mode */
+ u8 discovery_mode;
u8 channel;
- __le16 bcon_interval; /* base to listen/search duration calculation */
+ /* base to listen/search duration calculation */
+ __le16 bcon_interval;
} __packed;
-/*
- * WMI_POWER_MGMT_CFG_CMDID
- */
+/* WMI_POWER_MGMT_CFG_CMDID */
enum wmi_power_source_type {
- WMI_POWER_SOURCE_BATTERY = 0,
- WMI_POWER_SOURCE_OTHER = 1,
+ WMI_POWER_SOURCE_BATTERY = 0x00,
+ WMI_POWER_SOURCE_OTHER = 0x01,
};
struct wmi_power_mgmt_cfg_cmd {
- u8 power_source; /* wmi_power_source_type */
+ /* enum wmi_power_source_type */
+ u8 power_source;
u8 reserved[3];
} __packed;
-/*
- * WMI_PCP_START_CMDID
- */
-
-enum wmi_hidden_ssid {
- WMI_HIDDEN_SSID_DISABLED = 0,
- WMI_HIDDEN_SSID_SEND_EMPTY = 1,
- WMI_HIDDEN_SSID_CLEAR = 2,
-};
-
+/* WMI_PCP_START_CMDID */
struct wmi_pcp_start_cmd {
__le16 bcon_interval;
u8 pcp_max_assoc_sta;
u8 hidden_ssid;
- u8 reserved0[8];
+ u8 is_go;
+ u8 reserved0[7];
u8 network_type;
u8 channel;
u8 disable_sec_offload;
u8 disable_sec;
} __packed;
-/*
- * WMI_SW_TX_REQ_CMDID
- */
+/* WMI_SW_TX_REQ_CMDID */
struct wmi_sw_tx_req_cmd {
u8 dst_mac[WMI_MAC_LEN];
__le16 len;
u8 payload[0];
} __packed;
-/*
- * WMI_VRING_CFG_CMDID
- */
-
struct wmi_sw_ring_cfg {
__le64 ring_mem_base;
__le16 ring_size;
__le16 max_mpdu_size;
} __packed;
+/* wmi_vring_cfg_schd */
struct wmi_vring_cfg_schd {
__le16 priority;
__le16 timeslot_us;
} __packed;
enum wmi_vring_cfg_encap_trans_type {
- WMI_VRING_ENC_TYPE_802_3 = 0,
- WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1,
+ WMI_VRING_ENC_TYPE_802_3 = 0x00,
+ WMI_VRING_ENC_TYPE_NATIVE_WIFI = 0x01,
};
enum wmi_vring_cfg_ds_cfg {
- WMI_VRING_DS_PBSS = 0,
- WMI_VRING_DS_STATION = 1,
- WMI_VRING_DS_AP = 2,
- WMI_VRING_DS_ADDR4 = 3,
+ WMI_VRING_DS_PBSS = 0x00,
+ WMI_VRING_DS_STATION = 0x01,
+ WMI_VRING_DS_AP = 0x02,
+ WMI_VRING_DS_ADDR4 = 0x03,
};
enum wmi_vring_cfg_nwifi_ds_trans_type {
- WMI_NWIFI_TX_TRANS_MODE_NO = 0,
- WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1,
- WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2,
+ WMI_NWIFI_TX_TRANS_MODE_NO = 0x00,
+ WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 0x01,
+ WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 0x02,
};
enum wmi_vring_cfg_schd_params_priority {
- WMI_SCH_PRIO_REGULAR = 0,
- WMI_SCH_PRIO_HIGH = 1,
+ WMI_SCH_PRIO_REGULAR = 0x00,
+ WMI_SCH_PRIO_HIGH = 0x01,
};
-#define CIDXTID_CID_POS (0)
-#define CIDXTID_CID_LEN (4)
-#define CIDXTID_CID_MSK (0xF)
-#define CIDXTID_TID_POS (4)
-#define CIDXTID_TID_LEN (4)
-#define CIDXTID_TID_MSK (0xF0)
+#define CIDXTID_CID_POS (0)
+#define CIDXTID_CID_LEN (4)
+#define CIDXTID_CID_MSK (0xF)
+#define CIDXTID_TID_POS (4)
+#define CIDXTID_TID_LEN (4)
+#define CIDXTID_TID_MSK (0xF0)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2)
+#define VRING_CFG_TO_RESOLUTION_VALUE_POS (0)
+#define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6)
+#define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F)
struct wmi_vring_cfg {
struct wmi_sw_ring_cfg tx_sw_ring;
- u8 ringid; /* 0-23 vrings */
-
+ /* 0-23 vrings */
+ u8 ringid;
u8 cidxtid;
-
u8 encap_trans_type;
- u8 ds_cfg; /* 802.3 DS cfg */
+ /* 802.3 DS cfg */
+ u8 ds_cfg;
u8 nwifi_ds_trans_type;
-
- #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0)
- #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1)
- #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1)
- #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1)
- #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1)
- #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2)
u8 mac_ctrl;
-
- #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0)
- #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6)
- #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F)
u8 to_resolution;
u8 agg_max_wsize;
struct wmi_vring_cfg_schd schd_params;
} __packed;
enum wmi_vring_cfg_cmd_action {
- WMI_VRING_CMD_ADD = 0,
- WMI_VRING_CMD_MODIFY = 1,
- WMI_VRING_CMD_DELETE = 2,
+ WMI_VRING_CMD_ADD = 0x00,
+ WMI_VRING_CMD_MODIFY = 0x01,
+ WMI_VRING_CMD_DELETE = 0x02,
};
+/* WMI_VRING_CFG_CMDID */
struct wmi_vring_cfg_cmd {
__le32 action;
struct wmi_vring_cfg vring_cfg;
} __packed;
-/*
- * WMI_BCAST_VRING_CFG_CMDID
- */
struct wmi_bcast_vring_cfg {
struct wmi_sw_ring_cfg tx_sw_ring;
- u8 ringid; /* 0-23 vrings */
+ /* 0-23 vrings */
+ u8 ringid;
u8 encap_trans_type;
- u8 ds_cfg; /* 802.3 DS cfg */
+ /* 802.3 DS cfg */
+ u8 ds_cfg;
u8 nwifi_ds_trans_type;
} __packed;
+/* WMI_BCAST_VRING_CFG_CMDID */
struct wmi_bcast_vring_cfg_cmd {
__le32 action;
struct wmi_bcast_vring_cfg vring_cfg;
} __packed;
-/*
- * WMI_VRING_BA_EN_CMDID
- */
+/* WMI_VRING_BA_EN_CMDID */
struct wmi_vring_ba_en_cmd {
u8 ringid;
u8 agg_max_wsize;
__le16 ba_timeout;
u8 amsdu;
+ u8 reserved[3];
} __packed;
-/*
- * WMI_VRING_BA_DIS_CMDID
- */
+/* WMI_VRING_BA_DIS_CMDID */
struct wmi_vring_ba_dis_cmd {
u8 ringid;
u8 reserved;
__le16 reason;
} __packed;
-/*
- * WMI_NOTIFY_REQ_CMDID
- */
+/* WMI_NOTIFY_REQ_CMDID */
struct wmi_notify_req_cmd {
u8 cid;
u8 year;
@@ -654,102 +622,100 @@ struct wmi_notify_req_cmd {
u8 miliseconds;
} __packed;
-/*
- * WMI_CFG_RX_CHAIN_CMDID
- */
+/* WMI_CFG_RX_CHAIN_CMDID */
enum wmi_sniffer_cfg_mode {
- WMI_SNIFFER_OFF = 0,
- WMI_SNIFFER_ON = 1,
+ WMI_SNIFFER_OFF = 0x00,
+ WMI_SNIFFER_ON = 0x01,
};
enum wmi_sniffer_cfg_phy_info_mode {
- WMI_SNIFFER_PHY_INFO_DISABLED = 0,
- WMI_SNIFFER_PHY_INFO_ENABLED = 1,
+ WMI_SNIFFER_PHY_INFO_DISABLED = 0x00,
+ WMI_SNIFFER_PHY_INFO_ENABLED = 0x01,
};
enum wmi_sniffer_cfg_phy_support {
- WMI_SNIFFER_CP = 0,
- WMI_SNIFFER_DP = 1,
- WMI_SNIFFER_BOTH_PHYS = 2,
+ WMI_SNIFFER_CP = 0x00,
+ WMI_SNIFFER_DP = 0x01,
+ WMI_SNIFFER_BOTH_PHYS = 0x02,
};
+/* wmi_sniffer_cfg */
struct wmi_sniffer_cfg {
- __le32 mode; /* enum wmi_sniffer_cfg_mode */
- __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */
- __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */
+ /* enum wmi_sniffer_cfg_mode */
+ __le32 mode;
+ /* enum wmi_sniffer_cfg_phy_info_mode */
+ __le32 phy_info_mode;
+ /* enum wmi_sniffer_cfg_phy_support */
+ __le32 phy_support;
u8 channel;
u8 reserved[3];
} __packed;
enum wmi_cfg_rx_chain_cmd_action {
- WMI_RX_CHAIN_ADD = 0,
- WMI_RX_CHAIN_DEL = 1,
+ WMI_RX_CHAIN_ADD = 0x00,
+ WMI_RX_CHAIN_DEL = 0x01,
};
enum wmi_cfg_rx_chain_cmd_decap_trans_type {
- WMI_DECAP_TYPE_802_3 = 0,
- WMI_DECAP_TYPE_NATIVE_WIFI = 1,
- WMI_DECAP_TYPE_NONE = 2,
+ WMI_DECAP_TYPE_802_3 = 0x00,
+ WMI_DECAP_TYPE_NATIVE_WIFI = 0x01,
+ WMI_DECAP_TYPE_NONE = 0x02,
};
enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type {
- WMI_NWIFI_RX_TRANS_MODE_NO = 0,
- WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1,
- WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2,
+ WMI_NWIFI_RX_TRANS_MODE_NO = 0x00,
+ WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 0x01,
+ WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 0x02,
};
enum wmi_cfg_rx_chain_cmd_reorder_type {
- WMI_RX_HW_REORDER = 0,
- WMI_RX_SW_REORDER = 1,
+ WMI_RX_HW_REORDER = 0x00,
+ WMI_RX_SW_REORDER = 0x01,
};
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0)
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1)
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_POS (1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8)
+
+/* WMI_CFG_RX_CHAIN_CMDID */
struct wmi_cfg_rx_chain_cmd {
__le32 action;
struct wmi_sw_ring_cfg rx_sw_ring;
u8 mid;
u8 decap_trans_type;
-
- #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0)
- #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1)
- #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1)
- #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1)
- #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1)
- #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2)
u8 l2_802_3_offload_ctrl;
-
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0)
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1)
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1)
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1)
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1)
- #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2)
u8 l2_nwifi_offload_ctrl;
-
u8 vlan_id;
u8 nwifi_ds_trans_type;
-
- #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0)
- #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1)
- #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1)
- #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1)
- #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1)
- #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2)
u8 l3_l4_ctrl;
-
- #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0)
- #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1)
- #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1)
- #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1)
- #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1)
- #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2)
- #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2)
- #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1)
- #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4)
- #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3)
- #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1)
- #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8)
u8 ring_ctrl;
-
__le16 prefetch_thrsh;
__le16 wb_thrsh;
__le32 itr_value;
@@ -757,31 +723,27 @@ struct wmi_cfg_rx_chain_cmd {
u8 reorder_type;
u8 reserved;
struct wmi_sniffer_cfg sniffer_cfg;
+ __le16 max_rx_pl_per_desc;
} __packed;
-/*
- * WMI_RCP_ADDBA_RESP_CMDID
- */
+/* WMI_RCP_ADDBA_RESP_CMDID */
struct wmi_rcp_addba_resp_cmd {
u8 cidxtid;
u8 dialog_token;
__le16 status_code;
- __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */
+ /* ieee80211_ba_parameterset field to send */
+ __le16 ba_param_set;
__le16 ba_timeout;
} __packed;
-/*
- * WMI_RCP_DELBA_CMDID
- */
+/* WMI_RCP_DELBA_CMDID */
struct wmi_rcp_delba_cmd {
u8 cidxtid;
u8 reserved;
__le16 reason;
} __packed;
-/*
- * WMI_RCP_ADDBA_REQ_CMDID
- */
+/* WMI_RCP_ADDBA_REQ_CMDID */
struct wmi_rcp_addba_req_cmd {
u8 cidxtid;
u8 dialog_token;
@@ -792,32 +754,16 @@ struct wmi_rcp_addba_req_cmd {
__le16 ba_seq_ctrl;
} __packed;
-/*
- * WMI_SET_MAC_ADDRESS_CMDID
- */
+/* WMI_SET_MAC_ADDRESS_CMDID */
struct wmi_set_mac_address_cmd {
u8 mac[WMI_MAC_LEN];
u8 reserved[2];
} __packed;
-/*
-* WMI_EAPOL_TX_CMDID
-*/
-struct wmi_eapol_tx_cmd {
- u8 dst_mac[WMI_MAC_LEN];
- __le16 eapol_len;
- u8 eapol[0];
-} __packed;
-
-/*
- * WMI_ECHO_CMDID
- *
+/* WMI_ECHO_CMDID
* Check FW is alive
- *
* WMI_DEEP_ECHO_CMDID
- *
* Check FW and ucode are alive
- *
* Returned event: WMI_ECHO_RSP_EVENTID
* same event for both commands
*/
@@ -825,70 +771,79 @@ struct wmi_echo_cmd {
__le32 value;
} __packed;
-/*
- * WMI_TEMP_SENSE_CMDID
+/* WMI_OTP_READ_CMDID */
+struct wmi_otp_read_cmd {
+ __le32 addr;
+ __le32 size;
+ __le32 values;
+} __packed;
+
+/* WMI_OTP_WRITE_CMDID */
+struct wmi_otp_write_cmd {
+ __le32 addr;
+ __le32 size;
+ __le32 values;
+} __packed;
+
+/* WMI_TEMP_SENSE_CMDID
*
* Measure MAC and radio temperatures
+ *
+ * Possible modes for temperature measurement
*/
-
-/* Possible modes for temperature measurement */
enum wmi_temperature_measure_mode {
- TEMPERATURE_USE_OLD_VALUE = 0x1,
- TEMPERATURE_MEASURE_NOW = 0x2,
+ TEMPERATURE_USE_OLD_VALUE = 0x01,
+ TEMPERATURE_MEASURE_NOW = 0x02,
};
+/* WMI_TEMP_SENSE_CMDID */
struct wmi_temp_sense_cmd {
__le32 measure_baseband_en;
__le32 measure_rf_en;
__le32 measure_mode;
} __packed;
-/*
- * WMI_PMC_CMDID
- */
-enum wmi_pmc_op_e {
- WMI_PMC_ALLOCATE = 0,
- WMI_PMC_RELEASE = 1,
+enum wmi_pmc_op {
+ WMI_PMC_ALLOCATE = 0x00,
+ WMI_PMC_RELEASE = 0x01,
};
+/* WMI_PMC_CMDID */
struct wmi_pmc_cmd {
- u8 op; /* enum wmi_pmc_cmd_op_type */
+ /* enum wmi_pmc_cmd_op_type */
+ u8 op;
u8 reserved;
__le16 ring_size;
__le64 mem_base;
} __packed;
-/*
- * WMI Events
- */
-
-/*
+/* WMI Events
* List of Events (target to host)
*/
enum wmi_event_id {
WMI_READY_EVENTID = 0x1001,
WMI_CONNECT_EVENTID = 0x1002,
WMI_DISCONNECT_EVENTID = 0x1003,
- WMI_SCAN_COMPLETE_EVENTID = 0x100a,
- WMI_REPORT_STATISTICS_EVENTID = 0x100b,
+ WMI_SCAN_COMPLETE_EVENTID = 0x100A,
+ WMI_REPORT_STATISTICS_EVENTID = 0x100B,
WMI_RD_MEM_RSP_EVENTID = 0x1800,
WMI_FW_READY_EVENTID = 0x1801,
- WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200,
+ WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x200,
WMI_ECHO_RSP_EVENTID = 0x1803,
- WMI_FS_TUNE_DONE_EVENTID = 0x180a,
- WMI_CORR_MEASURE_EVENTID = 0x180b,
- WMI_READ_RSSI_EVENTID = 0x180c,
- WMI_TEMP_SENSE_DONE_EVENTID = 0x180e,
- WMI_DC_CALIB_DONE_EVENTID = 0x180f,
+ WMI_FS_TUNE_DONE_EVENTID = 0x180A,
+ WMI_CORR_MEASURE_EVENTID = 0x180B,
+ WMI_READ_RSSI_EVENTID = 0x180C,
+ WMI_TEMP_SENSE_DONE_EVENTID = 0x180E,
+ WMI_DC_CALIB_DONE_EVENTID = 0x180F,
WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811,
WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812,
WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815,
WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816,
WMI_MARLON_R_READ_DONE_EVENTID = 0x1818,
WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819,
- WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a,
- WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d,
- WMI_RF_RX_TEST_DONE_EVENTID = 0x181e,
+ WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181A,
+ WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181D,
+ WMI_RF_RX_TEST_DONE_EVENTID = 0x181E,
WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820,
WMI_VRING_CFG_DONE_EVENTID = 0x1821,
WMI_BA_STATUS_EVENTID = 0x1823,
@@ -896,15 +851,13 @@ enum wmi_event_id {
WMI_RCP_ADDBA_RESP_SENT_EVENTID = 0x1825,
WMI_DELBA_EVENTID = 0x1826,
WMI_GET_SSID_EVENTID = 0x1828,
- WMI_GET_PCP_CHANNEL_EVENTID = 0x182a,
- WMI_SW_TX_COMPLETE_EVENTID = 0x182b,
-
+ WMI_GET_PCP_CHANNEL_EVENTID = 0x182A,
+ WMI_SW_TX_COMPLETE_EVENTID = 0x182B,
WMI_READ_MAC_RXQ_EVENTID = 0x1830,
WMI_READ_MAC_TXQ_EVENTID = 0x1831,
WMI_WRITE_MAC_RXQ_EVENTID = 0x1832,
WMI_WRITE_MAC_TXQ_EVENTID = 0x1833,
WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834,
-
WMI_BEAMFORMING_MGMT_DONE_EVENTID = 0x1836,
WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837,
WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839,
@@ -914,20 +867,18 @@ enum wmi_event_id {
WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838,
WMI_RX_MGMT_PACKET_EVENTID = 0x1840,
WMI_TX_MGMT_PACKET_EVENTID = 0x1841,
-
+ WMI_OTP_READ_RESULT_EVENTID = 0x1856,
/* Performance monitoring events */
WMI_DATA_PORT_OPEN_EVENTID = 0x1860,
WMI_WBE_LINK_DOWN_EVENTID = 0x1861,
-
WMI_BF_CTRL_DONE_EVENTID = 0x1862,
WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863,
WMI_GET_STATUS_DONE_EVENTID = 0x1864,
WMI_VRING_EN_EVENTID = 0x1865,
-
WMI_UNIT_TEST_EVENTID = 0x1900,
WMI_FLASH_READ_DONE_EVENTID = 0x1902,
WMI_FLASH_WRITE_DONE_EVENTID = 0x1903,
- /*P2P*/
+ /* P2P */
WMI_P2P_CFG_DONE_EVENTID = 0x1910,
WMI_PORT_ALLOCATED_EVENTID = 0x1911,
WMI_PORT_DELETED_EVENTID = 0x1912,
@@ -937,49 +888,42 @@ enum wmi_event_id {
WMI_DISCOVERY_STOPPED_EVENTID = 0x1917,
WMI_PCP_STARTED_EVENTID = 0x1918,
WMI_PCP_STOPPED_EVENTID = 0x1919,
- WMI_PCP_FACTOR_EVENTID = 0x191a,
+ WMI_PCP_FACTOR_EVENTID = 0x191A,
WMI_SET_CHANNEL_EVENTID = 0x9000,
WMI_ASSOC_REQ_EVENTID = 0x9001,
WMI_EAPOL_RX_EVENTID = 0x9002,
WMI_MAC_ADDR_RESP_EVENTID = 0x9003,
WMI_FW_VER_EVENTID = 0x9004,
+ WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005,
};
-/*
- * Events data structures
- */
-
+/* Events data structures */
enum wmi_fw_status {
- WMI_FW_STATUS_SUCCESS,
- WMI_FW_STATUS_FAILURE,
+ WMI_FW_STATUS_SUCCESS = 0x00,
+ WMI_FW_STATUS_FAILURE = 0x01,
};
-/*
- * WMI_RF_MGMT_STATUS_EVENTID
- */
+/* WMI_RF_MGMT_STATUS_EVENTID */
enum wmi_rf_status {
- WMI_RF_ENABLED = 0,
- WMI_RF_DISABLED_HW = 1,
- WMI_RF_DISABLED_SW = 2,
- WMI_RF_DISABLED_HW_SW = 3,
+ WMI_RF_ENABLED = 0x00,
+ WMI_RF_DISABLED_HW = 0x01,
+ WMI_RF_DISABLED_SW = 0x02,
+ WMI_RF_DISABLED_HW_SW = 0x03,
};
+/* WMI_RF_MGMT_STATUS_EVENTID */
struct wmi_rf_mgmt_status_event {
__le32 rf_status;
} __packed;
-/*
- * WMI_THERMAL_THROTTLING_STATUS_EVENTID
- */
+/* WMI_THERMAL_THROTTLING_STATUS_EVENTID */
struct wmi_thermal_throttling_status_event {
__le32 time_on_usec;
__le32 time_off_usec;
__le32 max_txop_length_usec;
} __packed;
-/*
- * WMI_GET_STATUS_DONE_EVENTID
- */
+/* WMI_GET_STATUS_DONE_EVENTID */
struct wmi_get_status_done_event {
__le32 is_associated;
u8 cid;
@@ -995,9 +939,7 @@ struct wmi_get_status_done_event {
__le32 is_secured;
} __packed;
-/*
- * WMI_FW_VER_EVENTID
- */
+/* WMI_FW_VER_EVENTID */
struct wmi_fw_ver_event {
u8 major;
u8 minor;
@@ -1005,9 +947,7 @@ struct wmi_fw_ver_event {
__le16 build;
} __packed;
-/*
-* WMI_MAC_ADDR_RESP_EVENTID
-*/
+/* WMI_MAC_ADDR_RESP_EVENTID */
struct wmi_mac_addr_resp_event {
u8 mac[WMI_MAC_LEN];
u8 auth_mode;
@@ -1015,42 +955,38 @@ struct wmi_mac_addr_resp_event {
__le32 offload_mode;
} __packed;
-/*
-* WMI_EAPOL_RX_EVENTID
-*/
+/* WMI_EAPOL_RX_EVENTID */
struct wmi_eapol_rx_event {
u8 src_mac[WMI_MAC_LEN];
__le16 eapol_len;
u8 eapol[0];
} __packed;
-/*
-* WMI_READY_EVENTID
-*/
+/* WMI_READY_EVENTID */
enum wmi_phy_capability {
- WMI_11A_CAPABILITY = 1,
- WMI_11G_CAPABILITY = 2,
- WMI_11AG_CAPABILITY = 3,
- WMI_11NA_CAPABILITY = 4,
- WMI_11NG_CAPABILITY = 5,
- WMI_11NAG_CAPABILITY = 6,
- WMI_11AD_CAPABILITY = 7,
- WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY,
+ WMI_11A_CAPABILITY = 0x01,
+ WMI_11G_CAPABILITY = 0x02,
+ WMI_11AG_CAPABILITY = 0x03,
+ WMI_11NA_CAPABILITY = 0x04,
+ WMI_11NG_CAPABILITY = 0x05,
+ WMI_11NAG_CAPABILITY = 0x06,
+ WMI_11AD_CAPABILITY = 0x07,
+ WMI_11N_CAPABILITY_OFFSET = 0x03,
};
struct wmi_ready_event {
__le32 sw_version;
__le32 abi_version;
u8 mac[WMI_MAC_LEN];
- u8 phy_capability; /* enum wmi_phy_capability */
+ /* enum wmi_phy_capability */
+ u8 phy_capability;
u8 numof_additional_mids;
} __packed;
-/*
- * WMI_NOTIFY_REQ_DONE_EVENTID
- */
+/* WMI_NOTIFY_REQ_DONE_EVENTID */
struct wmi_notify_req_done_event {
- __le32 status; /* beamforming status, 0: fail; 1: OK; 2: retrying */
+ /* beamforming status, 0: fail; 1: OK; 2: retrying */
+ __le32 status;
__le64 tsf;
__le32 snr_val;
__le32 tx_tpt;
@@ -1066,9 +1002,7 @@ struct wmi_notify_req_done_event {
u8 reserved[3];
} __packed;
-/*
- * WMI_CONNECT_EVENTID
- */
+/* WMI_CONNECT_EVENTID */
struct wmi_connect_event {
u8 channel;
u8 reserved0;
@@ -1082,68 +1016,103 @@ struct wmi_connect_event {
u8 assoc_resp_len;
u8 cid;
u8 reserved2[3];
+ /* not in use */
u8 assoc_info[0];
} __packed;
-/*
- * WMI_DISCONNECT_EVENTID
- */
+/* WMI_DISCONNECT_EVENTID */
enum wmi_disconnect_reason {
- WMI_DIS_REASON_NO_NETWORK_AVAIL = 1,
- WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */
- WMI_DIS_REASON_DISCONNECT_CMD = 3,
- WMI_DIS_REASON_BSS_DISCONNECTED = 4,
- WMI_DIS_REASON_AUTH_FAILED = 5,
- WMI_DIS_REASON_ASSOC_FAILED = 6,
- WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7,
- WMI_DIS_REASON_CSERV_DISCONNECT = 8,
- WMI_DIS_REASON_INVALID_PROFILE = 10,
- WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11,
- WMI_DIS_REASON_PROFILE_MISMATCH = 12,
- WMI_DIS_REASON_CONNECTION_EVICTED = 13,
- WMI_DIS_REASON_IBSS_MERGE = 14,
+ WMI_DIS_REASON_NO_NETWORK_AVAIL = 0x01,
+ /* bmiss */
+ WMI_DIS_REASON_LOST_LINK = 0x02,
+ WMI_DIS_REASON_DISCONNECT_CMD = 0x03,
+ WMI_DIS_REASON_BSS_DISCONNECTED = 0x04,
+ WMI_DIS_REASON_AUTH_FAILED = 0x05,
+ WMI_DIS_REASON_ASSOC_FAILED = 0x06,
+ WMI_DIS_REASON_NO_RESOURCES_AVAIL = 0x07,
+ WMI_DIS_REASON_CSERV_DISCONNECT = 0x08,
+ WMI_DIS_REASON_INVALID_PROFILE = 0x0A,
+ WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 0x0B,
+ WMI_DIS_REASON_PROFILE_MISMATCH = 0x0C,
+ WMI_DIS_REASON_CONNECTION_EVICTED = 0x0D,
+ WMI_DIS_REASON_IBSS_MERGE = 0x0E,
};
struct wmi_disconnect_event {
- __le16 protocol_reason_status; /* reason code, see 802.11 spec. */
- u8 bssid[WMI_MAC_LEN]; /* set if known */
- u8 disconnect_reason; /* see wmi_disconnect_reason */
- u8 assoc_resp_len; /* not used */
- u8 assoc_info[0]; /* not used */
+ /* reason code, see 802.11 spec. */
+ __le16 protocol_reason_status;
+ /* set if known */
+ u8 bssid[WMI_MAC_LEN];
+ /* see enum wmi_disconnect_reason */
+ u8 disconnect_reason;
+ /* last assoc req may passed to host - not in used */
+ u8 assoc_resp_len;
+ /* last assoc req may passed to host - not in used */
+ u8 assoc_info[0];
} __packed;
-/*
- * WMI_SCAN_COMPLETE_EVENTID
- */
+/* WMI_SCAN_COMPLETE_EVENTID */
enum scan_status {
- WMI_SCAN_SUCCESS = 0,
- WMI_SCAN_FAILED = 1,
- WMI_SCAN_ABORTED = 2,
- WMI_SCAN_REJECTED = 3,
+ WMI_SCAN_SUCCESS = 0x00,
+ WMI_SCAN_FAILED = 0x01,
+ WMI_SCAN_ABORTED = 0x02,
+ WMI_SCAN_REJECTED = 0x03,
+ WMI_SCAN_ABORT_REJECTED = 0x04,
};
struct wmi_scan_complete_event {
- __le32 status; /* scan_status */
+ /* enum scan_status */
+ __le32 status;
} __packed;
-/*
- * WMI_BA_STATUS_EVENTID
- */
+/* WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT */
+enum wmi_acs_info_bitmask {
+ WMI_ACS_INFO_BITMASK_BEACON_FOUND = 0x01,
+ WMI_ACS_INFO_BITMASK_BUSY_TIME = 0x02,
+ WMI_ACS_INFO_BITMASK_TX_TIME = 0x04,
+ WMI_ACS_INFO_BITMASK_RX_TIME = 0x08,
+ WMI_ACS_INFO_BITMASK_NOISE = 0x10,
+};
+
+struct scan_acs_info {
+ u8 channel;
+ u8 beacon_found;
+ /* msec */
+ __le16 busy_time;
+ __le16 tx_time;
+ __le16 rx_time;
+ u8 noise;
+ u8 reserved[3];
+} __packed;
+
+struct wmi_acs_passive_scan_complete_event {
+ __le32 dwell_time;
+ /* valid fields within channel info according to
+ * their appearance in struct order
+ */
+ __le16 filled;
+ u8 num_scanned_channels;
+ u8 reserved;
+ struct scan_acs_info scan_info_list[0];
+} __packed;
+
+/* WMI_BA_STATUS_EVENTID */
enum wmi_vring_ba_status {
- WMI_BA_AGREED = 0,
- WMI_BA_NON_AGREED = 1,
+ WMI_BA_AGREED = 0x00,
+ WMI_BA_NON_AGREED = 0x01,
/* BA_EN in middle of teardown flow */
- WMI_BA_TD_WIP = 2,
+ WMI_BA_TD_WIP = 0x02,
/* BA_DIS or BA_EN in middle of BA SETUP flow */
- WMI_BA_SETUP_WIP = 3,
+ WMI_BA_SETUP_WIP = 0x03,
/* BA_EN when the BA session is already active */
- WMI_BA_SESSION_ACTIVE = 4,
+ WMI_BA_SESSION_ACTIVE = 0x04,
/* BA_DIS when the BA session is not active */
- WMI_BA_SESSION_NOT_ACTIVE = 5,
+ WMI_BA_SESSION_NOT_ACTIVE = 0x05,
};
-struct wmi_vring_ba_status_event {
- __le16 status; /* enum wmi_vring_ba_status */
+struct wmi_ba_status_event {
+ /* enum wmi_vring_ba_status */
+ __le16 status;
u8 reserved[2];
u8 ringid;
u8 agg_wsize;
@@ -1151,18 +1120,14 @@ struct wmi_vring_ba_status_event {
u8 amsdu;
} __packed;
-/*
- * WMI_DELBA_EVENTID
- */
+/* WMI_DELBA_EVENTID */
struct wmi_delba_event {
u8 cidxtid;
u8 from_initiator;
__le16 reason;
} __packed;
-/*
- * WMI_VRING_CFG_DONE_EVENTID
- */
+/* WMI_VRING_CFG_DONE_EVENTID */
struct wmi_vring_cfg_done_event {
u8 ringid;
u8 status;
@@ -1170,174 +1135,151 @@ struct wmi_vring_cfg_done_event {
__le32 tx_vring_tail_ptr;
} __packed;
-/*
- * WMI_RCP_ADDBA_RESP_SENT_EVENTID
- */
+/* WMI_RCP_ADDBA_RESP_SENT_EVENTID */
struct wmi_rcp_addba_resp_sent_event {
u8 cidxtid;
u8 reserved;
__le16 status;
} __packed;
-/*
- * WMI_RCP_ADDBA_REQ_EVENTID
- */
+/* WMI_RCP_ADDBA_REQ_EVENTID */
struct wmi_rcp_addba_req_event {
u8 cidxtid;
u8 dialog_token;
- __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */
+ /* ieee80211_ba_parameterset as it received */
+ __le16 ba_param_set;
__le16 ba_timeout;
- __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */
+ /* ieee80211_ba_seqstrl field as it received */
+ __le16 ba_seq_ctrl;
} __packed;
-/*
- * WMI_CFG_RX_CHAIN_DONE_EVENTID
- */
+/* WMI_CFG_RX_CHAIN_DONE_EVENTID */
enum wmi_cfg_rx_chain_done_event_status {
- WMI_CFG_RX_CHAIN_SUCCESS = 1,
+ WMI_CFG_RX_CHAIN_SUCCESS = 0x01,
};
struct wmi_cfg_rx_chain_done_event {
- __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */
+ /* V-Ring Tail pointer */
+ __le32 rx_ring_tail_ptr;
__le32 status;
} __packed;
-/*
- * WMI_WBE_LINK_DOWN_EVENTID
- */
+/* WMI_WBE_LINK_DOWN_EVENTID */
enum wmi_wbe_link_down_event_reason {
- WMI_WBE_REASON_USER_REQUEST = 0,
- WMI_WBE_REASON_RX_DISASSOC = 1,
- WMI_WBE_REASON_BAD_PHY_LINK = 2,
+ WMI_WBE_REASON_USER_REQUEST = 0x00,
+ WMI_WBE_REASON_RX_DISASSOC = 0x01,
+ WMI_WBE_REASON_BAD_PHY_LINK = 0x02,
};
+/* WMI_WBE_LINK_DOWN_EVENTID */
struct wmi_wbe_link_down_event {
u8 cid;
u8 reserved[3];
__le32 reason;
} __packed;
-/*
- * WMI_DATA_PORT_OPEN_EVENTID
- */
+/* WMI_DATA_PORT_OPEN_EVENTID */
struct wmi_data_port_open_event {
u8 cid;
u8 reserved[3];
} __packed;
-/*
- * WMI_VRING_EN_EVENTID
- */
+/* WMI_VRING_EN_EVENTID */
struct wmi_vring_en_event {
u8 vring_index;
u8 reserved[3];
} __packed;
-/*
- * WMI_GET_PCP_CHANNEL_EVENTID
- */
+/* WMI_GET_PCP_CHANNEL_EVENTID */
struct wmi_get_pcp_channel_event {
u8 channel;
u8 reserved[3];
} __packed;
-/*
- * WMI_P2P_CFG_DONE_EVENTID
- */
+/* WMI_P2P_CFG_DONE_EVENTID */
struct wmi_p2p_cfg_done_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
-* WMI_PORT_ALLOCATED_EVENTID
-*/
+/* WMI_PORT_ALLOCATED_EVENTID */
struct wmi_port_allocated_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
-* WMI_PORT_DELETED_EVENTID
-*/
+/* WMI_PORT_DELETED_EVENTID */
struct wmi_port_deleted_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
- * WMI_LISTEN_STARTED_EVENTID
- */
+/* WMI_LISTEN_STARTED_EVENTID */
struct wmi_listen_started_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
- * WMI_SEARCH_STARTED_EVENTID
- */
+/* WMI_SEARCH_STARTED_EVENTID */
struct wmi_search_started_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
- * WMI_PCP_STARTED_EVENTID
- */
+/* WMI_PCP_STARTED_EVENTID */
struct wmi_pcp_started_event {
- u8 status; /* wmi_fw_status */
+ /* wmi_fw_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
- * WMI_PCP_FACTOR_EVENTID
- */
+/* WMI_PCP_FACTOR_EVENTID */
struct wmi_pcp_factor_event {
__le32 pcp_factor;
} __packed;
-/*
- * WMI_SW_TX_COMPLETE_EVENTID
- */
enum wmi_sw_tx_status {
- WMI_TX_SW_STATUS_SUCCESS = 0,
- WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1,
- WMI_TX_SW_STATUS_FAILED_TX = 2,
+ WMI_TX_SW_STATUS_SUCCESS = 0x00,
+ WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 0x01,
+ WMI_TX_SW_STATUS_FAILED_TX = 0x02,
};
+/* WMI_SW_TX_COMPLETE_EVENTID */
struct wmi_sw_tx_complete_event {
- u8 status; /* enum wmi_sw_tx_status */
+ /* enum wmi_sw_tx_status */
+ u8 status;
u8 reserved[3];
} __packed;
-/*
- * WMI_CORR_MEASURE_EVENTID
- */
+/* WMI_CORR_MEASURE_EVENTID */
struct wmi_corr_measure_event {
- s32 i;
- s32 q;
- s32 image_i;
- s32 image_q;
+ /* signed */
+ __le32 i;
+ /* signed */
+ __le32 q;
+ /* signed */
+ __le32 image_i;
+ /* signed */
+ __le32 image_q;
} __packed;
-/*
- * WMI_READ_RSSI_EVENTID
- */
+/* WMI_READ_RSSI_EVENTID */
struct wmi_read_rssi_event {
__le32 ina_rssi_adc_dbm;
} __packed;
-/*
- * WMI_GET_SSID_EVENTID
- */
+/* WMI_GET_SSID_EVENTID */
struct wmi_get_ssid_event {
__le32 ssid_len;
u8 ssid[WMI_MAX_SSID_LEN];
} __packed;
-/*
- * WMI_RX_MGMT_PACKET_EVENTID
- */
+/* wmi_rx_mgmt_info */
struct wmi_rx_mgmt_info {
u8 mcs;
s8 snr;
@@ -1346,39 +1288,65 @@ struct wmi_rx_mgmt_info {
__le16 stype;
__le16 status;
__le32 len;
+ /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */
u8 qid;
+ /* Not resolved when == 0xFFFFFFFF ==> Broadcast to all MIDS */
u8 mid;
u8 cid;
- u8 channel; /* From Radio MNGR */
+ /* From Radio MNGR */
+ u8 channel;
} __packed;
-/*
- * WMI_TX_MGMT_PACKET_EVENTID
- */
+/* wmi_otp_read_write_cmd */
+struct wmi_otp_read_write_cmd {
+ __le32 addr;
+ __le32 size;
+ u8 values[0];
+} __packed;
+
+/* WMI_OTP_READ_RESULT_EVENTID */
+struct wmi_otp_read_result_event {
+ u8 payload[0];
+} __packed;
+
+/* WMI_TX_MGMT_PACKET_EVENTID */
struct wmi_tx_mgmt_packet_event {
u8 payload[0];
} __packed;
+/* WMI_RX_MGMT_PACKET_EVENTID */
struct wmi_rx_mgmt_packet_event {
struct wmi_rx_mgmt_info info;
u8 payload[0];
} __packed;
-/*
- * WMI_ECHO_RSP_EVENTID
- */
-struct wmi_echo_event {
+/* WMI_ECHO_RSP_EVENTID */
+struct wmi_echo_rsp_event {
__le32 echoed_value;
} __packed;
-/*
- * WMI_TEMP_SENSE_DONE_EVENTID
+/* WMI_TEMP_SENSE_DONE_EVENTID
*
* Measure MAC and radio temperatures
*/
struct wmi_temp_sense_done_event {
+ /* Temperature times 1000 (actual temperature will be achieved by
+ * dividing the value by 1000)
+ */
__le32 baseband_t1000;
+ /* Temperature times 1000 (actual temperature will be achieved by
+ * dividing the value by 1000)
+ */
__le32 rf_t1000;
} __packed;
+#define WMI_SCAN_DWELL_TIME_MS (100)
+#define WMI_SURVEY_TIMEOUT_MS (10000)
+
+enum wmi_hidden_ssid {
+ WMI_HIDDEN_SSID_DISABLED = 0x00,
+ WMI_HIDDEN_SSID_SEND_EMPTY = 0x10,
+ WMI_HIDDEN_SSID_CLEAR = 0xFE,
+};
+
#endif /* __WILOCITY_WMI_H__ */
diff --git a/drivers/pinctrl/qcom/pinctrl-msmcobalt.c b/drivers/pinctrl/qcom/pinctrl-msmcobalt.c
index 27d692b66583..ef44df7bc6f1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msmcobalt.c
+++ b/drivers/pinctrl/qcom/pinctrl-msmcobalt.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -61,6 +61,7 @@
.intr_enable_bit = 0, \
.intr_status_bit = 0, \
.intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
.intr_raw_status_bit = 4, \
.intr_polarity_bit = 1, \
.intr_detection_bit = 2, \
diff --git a/drivers/platform/msm/ipa/Makefile b/drivers/platform/msm/ipa/Makefile
index 19ae5234a6d0..8bc7d8a498f6 100644
--- a/drivers/platform/msm/ipa/Makefile
+++ b/drivers/platform/msm/ipa/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_IPA) += ipa_v2/
+obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/
obj-$(CONFIG_IPA) += ipa_api.o
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 31db8ff2709f..04054fe1211f 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -1868,108 +1868,6 @@ bool ipa_get_client_uplink(int pipe_idx)
EXPORT_SYMBOL(ipa_get_client_uplink);
/**
- * odu_bridge_init() - Initialize the ODU bridge driver
- * @params: initialization parameters
- *
- * This function initialize all bridge internal data and register odu bridge to
- * kernel for IOCTL and debugfs.
- * Header addition and properties are registered to IPA driver.
- *
- * Return codes: 0: success,
- * -EINVAL - Bad parameter
- * Other negative value - Failure
- */
-int odu_bridge_init(struct odu_bridge_params *params)
-{
- int ret;
-
- IPA_API_DISPATCH_RETURN(odu_bridge_init, params);
-
- return ret;
-}
-EXPORT_SYMBOL(odu_bridge_init);
-
-/**
- * odu_bridge_disconnect() - Disconnect odu bridge
- *
- * Disconnect all pipes and deletes IPA RM dependencies on bridge mode
- *
- * Return codes: 0- success, error otherwise
- */
-int odu_bridge_disconnect(void)
-{
- int ret;
-
- IPA_API_DISPATCH_RETURN(odu_bridge_disconnect);
-
- return ret;
-}
-EXPORT_SYMBOL(odu_bridge_disconnect);
-
-/**
- * odu_bridge_connect() - Connect odu bridge.
- *
- * Call to the mode-specific connect function for connection IPA pipes
- * and adding IPA RM dependencies
-
- * Return codes: 0: success
- * -EINVAL: invalid parameters
- * -EPERM: Operation not permitted as the bridge is already
- * connected
- */
-int odu_bridge_connect(void)
-{
- int ret;
-
- IPA_API_DISPATCH_RETURN(odu_bridge_connect);
-
- return ret;
-}
-EXPORT_SYMBOL(odu_bridge_connect);
-
-/**
- * odu_bridge_tx_dp() - Send skb to ODU bridge
- * @skb: skb to send
- * @metadata: metadata on packet
- *
- * This function handles uplink packet.
- * In Router Mode:
- * packet is sent directly to IPA.
- * In Router Mode:
- * packet is classified if it should arrive to network stack.
- * QMI IP packet should arrive to APPS network stack
- * IPv6 Multicast packet should arrive to APPS network stack and Q6
- *
- * Return codes: 0- success, error otherwise
- */
-int odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
-{
- int ret;
-
- IPA_API_DISPATCH_RETURN(odu_bridge_tx_dp, skb, metadata);
-
- return ret;
-}
-EXPORT_SYMBOL(odu_bridge_tx_dp);
-
-/**
- * odu_bridge_cleanup() - De-Initialize the ODU bridge driver
- *
- * Return codes: 0: success,
- * -EINVAL - Bad parameter
- * Other negative value - Failure
- */
-int odu_bridge_cleanup(void)
-{
- int ret;
-
- IPA_API_DISPATCH_RETURN(odu_bridge_cleanup);
-
- return ret;
-}
-EXPORT_SYMBOL(odu_bridge_cleanup);
-
-/**
* ipa_dma_init() -Initialize IPADMA.
*
* This function initialize all IPADMA internal data and connect in dma:
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index e108f0ca0bae..04b7ba64a6aa 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -236,17 +236,6 @@ struct ipa_api_controller {
bool (*ipa_get_client_uplink)(int pipe_idx);
- int (*odu_bridge_init)(struct odu_bridge_params *params);
-
- int (*odu_bridge_connect)(void);
-
- int (*odu_bridge_disconnect)(void);
-
- int (*odu_bridge_tx_dp)(struct sk_buff *skb,
- struct ipa_tx_meta *metadata);
-
- int (*odu_bridge_cleanup)(void);
-
int (*ipa_dma_init)(void);
int (*ipa_dma_enable)(void);
diff --git a/drivers/platform/msm/ipa/ipa_clients/Makefile b/drivers/platform/msm/ipa/ipa_clients/Makefile
index eb0e91b70690..26b45a6c2b42 100644
--- a/drivers/platform/msm/ipa/ipa_clients/Makefile
+++ b/drivers/platform/msm/ipa/ipa_clients/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_IPA3) += ipa_usb.o \ No newline at end of file
+obj-$(CONFIG_IPA3) += ipa_usb.o odu_bridge.o
+obj-$(CONFIG_IPA) += odu_bridge.o \ No newline at end of file
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index 9b9ec31f34fc..a0c94c8e37ec 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -1788,6 +1788,33 @@ connect_ul_fail:
return result;
}
+static int ipa_usb_ipc_logging_init(void)
+{
+ int result;
+
+ ipa3_usb_ctx->logbuf = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES,
+ "ipa_usb", 0);
+ if (ipa3_usb_ctx->logbuf == NULL) {
+ /* we can't use ipa_usb print macros on failures */
+ pr_err("ipa_usb: failed to get logbuf\n");
+ return -ENOMEM;
+ }
+
+ ipa3_usb_ctx->logbuf_low = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES,
+ "ipa_usb_low", 0);
+ if (ipa3_usb_ctx->logbuf_low == NULL) {
+ pr_err("ipa_usb: failed to get logbuf_low\n");
+ result = -ENOMEM;
+ goto fail_logbuf_low;
+ }
+
+ return 0;
+
+fail_logbuf_low:
+ ipc_log_context_destroy(ipa3_usb_ctx->logbuf);
+ return result;
+}
+
#ifdef CONFIG_DEBUG_FS
static char dbg_buff[IPA_USB_MAX_MSG_LEN];
@@ -1949,7 +1976,7 @@ const struct file_operations ipa3_ipa_usb_ops = {
.read = ipa3_read_usb_state_info,
};
-void ipa_usb_debugfs_init(void)
+static void ipa_usb_debugfs_init(void)
{
const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH |
@@ -1987,45 +2014,18 @@ fail:
ipa3_usb_ctx->dent = NULL;
}
-static int ipa_usb_ipc_logging_init(void)
-{
- int result;
-
- ipa3_usb_ctx->logbuf = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES,
- "ipa_usb", 0);
- if (ipa3_usb_ctx->logbuf == NULL) {
- /* we can't use ipa_usb print macros on failures */
- pr_err("ipa_usb: failed to get logbuf\n");
- return -ENOMEM;
- }
-
- ipa3_usb_ctx->logbuf_low = ipc_log_context_create(IPA_USB_IPC_LOG_PAGES,
- "ipa_usb_low", 0);
- if (ipa3_usb_ctx->logbuf_low == NULL) {
- pr_err("ipa_usb: failed to get logbuf_low\n");
- result = -ENOMEM;
- goto fail_logbuf_low;
- }
-
- return 0;
-
-fail_logbuf_low:
- ipc_log_context_destroy(ipa3_usb_ctx->logbuf);
- return result;
-}
-
-void ipa_usb_debugfs_remove(void)
+static void ipa_usb_debugfs_remove(void)
{
if (IS_ERR(ipa3_usb_ctx->dent)) {
- IPA_USB_ERR("ipa_debugfs_remove: folder was not created.\n");
+ IPA_USB_ERR("ipa_usb debugfs folder was not created.\n");
return;
}
debugfs_remove_recursive(ipa3_usb_ctx->dent);
}
#else /* CONFIG_DEBUG_FS */
-void ipa_usb_debugfs_init(void){}
-void ipa_usb_debugfs_remove(void){}
+static void ipa_usb_debugfs_init(void){}
+static void ipa_usb_debugfs_remove(void){}
#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/platform/msm/ipa/ipa_v2/odu_bridge.c b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
index 9dbd2f6e8f79..c388925f4679 100644
--- a/drivers/platform/msm/ipa/ipa_v2/odu_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.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
@@ -23,20 +23,55 @@
#include <linux/types.h>
#include <linux/ipv6.h>
#include <net/addrconf.h>
+#include <linux/ipc_logging.h>
#include <linux/ipa.h>
-#include "ipa_i.h"
+#include <linux/cdev.h>
+#include <linux/ipa_odu_bridge.h>
#define ODU_BRIDGE_DRV_NAME "odu_ipa_bridge"
+#define ODU_IPC_LOG_PAGES 10
+#define ODU_IPC_LOG(buf, fmt, args...) \
+ ipc_log_string((buf), \
+ ODU_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+
#define ODU_BRIDGE_DBG(fmt, args...) \
- pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
- __func__, __LINE__, ## args)
+ do { \
+ pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (odu_bridge_ctx) { \
+ ODU_IPC_LOG(odu_bridge_ctx->logbuf, \
+ fmt, ## args); \
+ ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
+#define ODU_BRIDGE_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (odu_bridge_ctx && \
+ odu_bridge_ctx->enable_low_prio_print) { \
+ ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
#define ODU_BRIDGE_ERR(fmt, args...) \
- pr_err(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (odu_bridge_ctx) { \
+ ODU_IPC_LOG(odu_bridge_ctx->logbuf, \
+ fmt, ## args); \
+ ODU_IPC_LOG(odu_bridge_ctx->logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
+
#define ODU_BRIDGE_FUNC_ENTRY() \
- ODU_BRIDGE_DBG("ENTRY\n")
+ ODU_BRIDGE_DBG_LOW("ENTRY\n")
#define ODU_BRIDGE_FUNC_EXIT() \
- ODU_BRIDGE_DBG("EXIT\n")
+ ODU_BRIDGE_DBG_LOW("EXIT\n")
#define ODU_BRIDGE_IS_QMI_ADDR(daddr) \
@@ -54,6 +89,17 @@
compat_uptr_t)
#endif
+#define IPA_ODU_VER_CHECK() \
+ do { \
+ ret = 0;\
+ if (ipa_get_hw_type() == IPA_HW_None) { \
+ pr_err("IPA HW is unknown\n"); \
+ ret = -EFAULT; \
+ } \
+ else if (ipa_get_hw_type() < IPA_HW_v3_0) \
+ ret = 1; \
+ } while (0)
+
/**
* struct stats - driver statistics, viewable using debugfs
* @num_ul_packets: number of packets bridged in uplink direction
@@ -110,6 +156,9 @@ struct odu_bridge_ctx {
u32 odu_emb_cons_hdl;
u32 odu_teth_cons_hdl;
u32 ipa_sys_desc_size;
+ void *logbuf;
+ void *logbuf_low;
+ u32 enable_low_prio_print;
};
static struct odu_bridge_ctx *odu_bridge_ctx;
@@ -149,7 +198,7 @@ static void odu_bridge_teth_cons_cb(void *priv, enum ipa_dp_evt_type evt,
ipv6hdr = (struct ipv6hdr *)(skb->data + ETH_HLEN);
if (ipv6hdr->version == 6 &&
ipv6_addr_is_multicast(&ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("Multicast pkt, send to APPS and adapter\n");
+ ODU_BRIDGE_DBG_LOW("Multicast pkt, send to APPS and adapter\n");
skb_copied = skb_clone(skb, GFP_KERNEL);
if (skb_copied) {
odu_bridge_ctx->tx_dp_notify(odu_bridge_ctx->priv,
@@ -185,7 +234,7 @@ static int odu_bridge_connect_router(void)
odu_prod_params.priv = odu_bridge_ctx->priv;
odu_prod_params.notify = odu_bridge_ctx->tx_dp_notify;
odu_prod_params.keep_ipa_awake = true;
- res = ipa2_setup_sys_pipe(&odu_prod_params,
+ res = ipa_setup_sys_pipe(&odu_prod_params,
&odu_bridge_ctx->odu_prod_hdl);
if (res) {
ODU_BRIDGE_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
@@ -200,7 +249,7 @@ static int odu_bridge_connect_router(void)
odu_emb_cons_params.priv = odu_bridge_ctx->priv;
odu_emb_cons_params.notify = odu_bridge_emb_cons_cb;
odu_emb_cons_params.keep_ipa_awake = true;
- res = ipa2_setup_sys_pipe(&odu_emb_cons_params,
+ res = ipa_setup_sys_pipe(&odu_emb_cons_params,
&odu_bridge_ctx->odu_emb_cons_hdl);
if (res) {
ODU_BRIDGE_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
@@ -215,7 +264,7 @@ static int odu_bridge_connect_router(void)
return 0;
fail_odu_emb_cons:
- ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
+ ipa_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
odu_bridge_ctx->odu_prod_hdl = 0;
fail_odu_prod:
return res;
@@ -234,18 +283,18 @@ static int odu_bridge_connect_bridge(void)
memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));
/* Build IPA Resource manager dependency graph */
- ODU_BRIDGE_DBG("build dependency graph\n");
- res = ipa2_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ ODU_BRIDGE_DBG_LOW("build dependency graph\n");
+ res = ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
IPA_RM_RESOURCE_Q6_CONS);
if (res && res != -EINPROGRESS) {
- ODU_BRIDGE_ERR("ipa2_rm_add_dependency() failed\n");
+ ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
goto fail_add_dependency_1;
}
- res = ipa2_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
+ res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
IPA_RM_RESOURCE_ODU_ADAPT_CONS);
if (res && res != -EINPROGRESS) {
- ODU_BRIDGE_ERR("ipa2_rm_add_dependency() failed\n");
+ ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
goto fail_add_dependency_2;
}
@@ -256,7 +305,7 @@ static int odu_bridge_connect_bridge(void)
odu_prod_params.notify = odu_bridge_ctx->tx_dp_notify;
odu_prod_params.keep_ipa_awake = true;
odu_prod_params.skip_ep_cfg = true;
- res = ipa2_setup_sys_pipe(&odu_prod_params,
+ res = ipa_setup_sys_pipe(&odu_prod_params,
&odu_bridge_ctx->odu_prod_hdl);
if (res) {
ODU_BRIDGE_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
@@ -270,7 +319,7 @@ static int odu_bridge_connect_bridge(void)
odu_teth_cons_params.notify = odu_bridge_teth_cons_cb;
odu_teth_cons_params.keep_ipa_awake = true;
odu_teth_cons_params.skip_ep_cfg = true;
- res = ipa2_setup_sys_pipe(&odu_teth_cons_params,
+ res = ipa_setup_sys_pipe(&odu_teth_cons_params,
&odu_bridge_ctx->odu_teth_cons_hdl);
if (res) {
ODU_BRIDGE_ERR("fail to setup sys pipe ODU_TETH_CONS %d\n",
@@ -286,16 +335,16 @@ static int odu_bridge_connect_bridge(void)
odu_emb_cons_params.priv = odu_bridge_ctx->priv;
odu_emb_cons_params.notify = odu_bridge_emb_cons_cb;
odu_emb_cons_params.keep_ipa_awake = true;
- res = ipa2_setup_sys_pipe(&odu_emb_cons_params,
+ res = ipa_setup_sys_pipe(&odu_emb_cons_params,
&odu_bridge_ctx->odu_emb_cons_hdl);
if (res) {
ODU_BRIDGE_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
goto fail_odu_emb_cons;
}
- ODU_BRIDGE_DBG("odu_prod_hdl = %d, odu_emb_cons_hdl = %d\n",
+ ODU_BRIDGE_DBG_LOW("odu_prod_hdl = %d, odu_emb_cons_hdl = %d\n",
odu_bridge_ctx->odu_prod_hdl, odu_bridge_ctx->odu_emb_cons_hdl);
- ODU_BRIDGE_DBG("odu_teth_cons_hdl = %d\n",
+ ODU_BRIDGE_DBG_LOW("odu_teth_cons_hdl = %d\n",
odu_bridge_ctx->odu_teth_cons_hdl);
ODU_BRIDGE_FUNC_EXIT();
@@ -303,16 +352,16 @@ static int odu_bridge_connect_bridge(void)
return 0;
fail_odu_emb_cons:
- ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_teth_cons_hdl);
+ ipa_teardown_sys_pipe(odu_bridge_ctx->odu_teth_cons_hdl);
odu_bridge_ctx->odu_teth_cons_hdl = 0;
fail_odu_teth_cons:
- ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
+ ipa_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
odu_bridge_ctx->odu_prod_hdl = 0;
fail_odu_prod:
- ipa2_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
IPA_RM_RESOURCE_ODU_ADAPT_CONS);
fail_add_dependency_2:
- ipa2_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
IPA_RM_RESOURCE_Q6_CONS);
fail_add_dependency_1:
return res;
@@ -324,12 +373,12 @@ static int odu_bridge_disconnect_router(void)
ODU_BRIDGE_FUNC_ENTRY();
- res = ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
+ res = ipa_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
if (res)
ODU_BRIDGE_ERR("teardown ODU PROD failed\n");
odu_bridge_ctx->odu_prod_hdl = 0;
- res = ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_emb_cons_hdl);
+ res = ipa_teardown_sys_pipe(odu_bridge_ctx->odu_emb_cons_hdl);
if (res)
ODU_BRIDGE_ERR("teardown ODU EMB CONS failed\n");
odu_bridge_ctx->odu_emb_cons_hdl = 0;
@@ -345,44 +394,44 @@ static int odu_bridge_disconnect_bridge(void)
ODU_BRIDGE_FUNC_ENTRY();
- res = ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
+ res = ipa_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
if (res)
ODU_BRIDGE_ERR("teardown ODU PROD failed\n");
odu_bridge_ctx->odu_prod_hdl = 0;
- res = ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_teth_cons_hdl);
+ res = ipa_teardown_sys_pipe(odu_bridge_ctx->odu_teth_cons_hdl);
if (res)
ODU_BRIDGE_ERR("teardown ODU TETH CONS failed\n");
odu_bridge_ctx->odu_teth_cons_hdl = 0;
- res = ipa2_teardown_sys_pipe(odu_bridge_ctx->odu_emb_cons_hdl);
+ res = ipa_teardown_sys_pipe(odu_bridge_ctx->odu_emb_cons_hdl);
if (res)
ODU_BRIDGE_ERR("teardown ODU EMB CONS failed\n");
odu_bridge_ctx->odu_emb_cons_hdl = 0;
/* Delete IPA Resource manager dependency graph */
ODU_BRIDGE_DBG("deleting dependency graph\n");
- res = ipa2_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+ res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
IPA_RM_RESOURCE_Q6_CONS);
if (res && res != -EINPROGRESS)
- ODU_BRIDGE_ERR("ipa2_rm_delete_dependency() failed\n");
+ ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
- res = ipa2_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+ res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
IPA_RM_RESOURCE_ODU_ADAPT_CONS);
if (res && res != -EINPROGRESS)
- ODU_BRIDGE_ERR("ipa2_rm_delete_dependency() failed\n");
+ ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
return 0;
}
/**
- * ipa2_odu_bridge_disconnect() - Disconnect odu bridge
+ * odu_bridge_disconnect() - Disconnect odu bridge
*
* Disconnect all pipes and deletes IPA RM dependencies on bridge mode
*
* Return codes: 0- success, error otherwise
*/
-int ipa2_odu_bridge_disconnect(void)
+int odu_bridge_disconnect(void)
{
int res;
@@ -420,9 +469,10 @@ out:
ODU_BRIDGE_FUNC_EXIT();
return res;
}
+EXPORT_SYMBOL(odu_bridge_disconnect);
/**
- * ipa2_odu_bridge_connect() - Connect odu bridge.
+ * odu_bridge_connect() - Connect odu bridge.
*
* Call to the mode-specific connect function for connection IPA pipes
* and adding IPA RM dependencies
@@ -432,7 +482,7 @@ out:
* -EPERM: Operation not permitted as the bridge is already
* connected
*/
-int ipa2_odu_bridge_connect(void)
+int odu_bridge_connect(void)
{
int res;
@@ -470,6 +520,7 @@ bail:
ODU_BRIDGE_FUNC_EXIT();
return res;
}
+EXPORT_SYMBOL(odu_bridge_connect);
/**
* odu_bridge_set_mode() - Set bridge mode to Router/Bridge
@@ -486,11 +537,11 @@ static int odu_bridge_set_mode(enum odu_bridge_mode mode)
return -EFAULT;
}
- ODU_BRIDGE_DBG("setting mode: %d\n", mode);
+ ODU_BRIDGE_DBG_LOW("setting mode: %d\n", mode);
mutex_lock(&odu_bridge_ctx->lock);
if (odu_bridge_ctx->mode == mode) {
- ODU_BRIDGE_DBG("same mode\n");
+ ODU_BRIDGE_DBG_LOW("same mode\n");
res = 0;
goto bail;
}
@@ -553,7 +604,7 @@ static int odu_bridge_set_llv6_addr(struct in6_addr *llv6_addr)
memcpy(&odu_bridge_ctx->llv6_addr, &llv6_addr_host,
sizeof(odu_bridge_ctx->llv6_addr));
- ODU_BRIDGE_DBG("LLV6 addr: %pI6c\n", &odu_bridge_ctx->llv6_addr);
+ ODU_BRIDGE_DBG_LOW("LLV6 addr: %pI6c\n", &odu_bridge_ctx->llv6_addr);
ODU_BRIDGE_FUNC_EXIT();
@@ -632,6 +683,7 @@ static long compat_odu_bridge_ioctl(struct file *file,
static struct dentry *dent;
static struct dentry *dfile_stats;
static struct dentry *dfile_mode;
+static struct dentry *dfile_low_prio;
static ssize_t odu_debugfs_stats(struct file *file,
char __user *ubuf,
@@ -725,7 +777,7 @@ const struct file_operations odu_hw_bridge_mode_ops = {
.write = odu_debugfs_hw_bridge_mode_write,
};
-void odu_debugfs_init(void)
+static void odu_debugfs_init(void)
{
const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH |
@@ -754,6 +806,14 @@ void odu_debugfs_init(void)
goto fail;
}
+ dfile_low_prio = debugfs_create_u32("enable_low_prio_print",
+ read_write_mode,
+ dent, &odu_bridge_ctx->enable_low_prio_print);
+ if (!dfile_low_prio) {
+ ODU_BRIDGE_ERR("could not create enable_low_prio_print file\n");
+ goto fail;
+ }
+
return;
fail:
debugfs_remove_recursive(dent);
@@ -779,7 +839,7 @@ static const struct file_operations odu_bridge_drv_fops = {
};
/**
- * ipa2_odu_bridge_tx_dp() - Send skb to ODU bridge
+ * odu_bridge_tx_dp() - Send skb to ODU bridge
* @skb: skb to send
* @metadata: metadata on packet
*
@@ -793,7 +853,7 @@ static const struct file_operations odu_bridge_drv_fops = {
*
* Return codes: 0- success, error otherwise
*/
-int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
+int odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
{
struct sk_buff *skb_copied = NULL;
struct ipv6hdr *ipv6hdr;
@@ -804,7 +864,7 @@ int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
switch (odu_bridge_ctx->mode) {
case ODU_BRIDGE_MODE_ROUTER:
/* Router mode - pass skb to IPA */
- res = ipa2_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
+ res = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
if (res) {
ODU_BRIDGE_DBG("tx dp failed %d\n", res);
goto out;
@@ -816,7 +876,7 @@ int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
ipv6hdr = (struct ipv6hdr *)(skb->data + ETH_HLEN);
if (ipv6hdr->version == 6 &&
ODU_BRIDGE_IS_QMI_ADDR(ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("QMI packet\n");
+ ODU_BRIDGE_DBG_LOW("QMI packet\n");
skb_copied = skb_clone(skb, GFP_KERNEL);
if (!skb_copied) {
ODU_BRIDGE_ERR("No memory\n");
@@ -836,14 +896,15 @@ int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
if (ipv6hdr->version == 6 &&
ipv6_addr_is_multicast(&ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("Multicast pkt, send to APPS and IPA\n");
+ ODU_BRIDGE_DBG_LOW(
+ "Multicast pkt, send to APPS and IPA\n");
skb_copied = skb_clone(skb, GFP_KERNEL);
if (!skb_copied) {
ODU_BRIDGE_ERR("No memory\n");
return -ENOMEM;
}
- res = ipa2_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
+ res = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
if (res) {
ODU_BRIDGE_DBG("tx dp failed %d\n", res);
dev_kfree_skb(skb_copied);
@@ -858,7 +919,7 @@ int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
goto out;
}
- res = ipa2_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
+ res = ipa_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
if (res) {
ODU_BRIDGE_DBG("tx dp failed %d\n", res);
goto out;
@@ -876,6 +937,7 @@ out:
ODU_BRIDGE_FUNC_EXIT();
return res;
}
+EXPORT_SYMBOL(odu_bridge_tx_dp);
static int odu_bridge_add_hdrs(void)
{
@@ -916,7 +978,7 @@ static int odu_bridge_add_hdrs(void)
ipv6_hdr->eth2_ofst = 0;
hdrs->commit = 1;
hdrs->num_hdrs = 2;
- res = ipa2_add_hdr(hdrs);
+ res = ipa_add_hdr(hdrs);
if (res) {
ODU_BRIDGE_ERR("Fail on Header-Insertion(%d)\n", res);
goto out_free_mem;
@@ -961,9 +1023,9 @@ static void odu_bridge_del_hdrs(void)
ipv4->hdl = odu_bridge_ctx->odu_br_ipv4_hdr_hdl;
ipv6 = &del_hdr->hdl[1];
ipv6->hdl = odu_bridge_ctx->odu_br_ipv6_hdr_hdl;
- result = ipa2_del_hdr(del_hdr);
+ result = ipa_del_hdr(del_hdr);
if (result || ipv4->status || ipv6->status)
- ODU_BRIDGE_ERR("ipa2_del_hdr failed");
+ ODU_BRIDGE_ERR("ipa_del_hdr failed");
kfree(del_hdr);
}
@@ -1019,7 +1081,7 @@ static int odu_bridge_register_properties(void)
rx_ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
rx_properties.num_props = 2;
- res = ipa2_register_intf(odu_bridge_ctx->netdev_name, &tx_properties,
+ res = ipa_register_intf(odu_bridge_ctx->netdev_name, &tx_properties,
&rx_properties);
if (res) {
ODU_BRIDGE_ERR("fail on Tx/Rx properties registration %d\n",
@@ -1036,14 +1098,42 @@ static void odu_bridge_deregister_properties(void)
int res;
ODU_BRIDGE_FUNC_ENTRY();
- res = ipa2_deregister_intf(odu_bridge_ctx->netdev_name);
+ res = ipa_deregister_intf(odu_bridge_ctx->netdev_name);
if (res)
ODU_BRIDGE_ERR("Fail on Tx prop deregister %d\n", res);
ODU_BRIDGE_FUNC_EXIT();
}
+static int odu_bridge_ipc_logging_init(void)
+{
+ int result;
+
+ odu_bridge_ctx->logbuf = ipc_log_context_create(ODU_IPC_LOG_PAGES,
+ "ipa_odu_bridge", 0);
+ if (odu_bridge_ctx->logbuf == NULL) {
+ /* we can't use odu_bridge print macros on failures */
+ pr_err("odu_bridge: failed to get logbuf\n");
+ return -ENOMEM;
+ }
+
+ odu_bridge_ctx->logbuf_low =
+ ipc_log_context_create(ODU_IPC_LOG_PAGES,
+ "ipa_odu_bridge_low", 0);
+ if (odu_bridge_ctx->logbuf_low == NULL) {
+ pr_err("odu_bridge: failed to get logbuf_low\n");
+ result = -ENOMEM;
+ goto fail_logbuf_low;
+ }
+
+ return 0;
+
+fail_logbuf_low:
+ ipc_log_context_destroy(odu_bridge_ctx->logbuf);
+ return result;
+}
+
/**
- * ipa2_odu_bridge_init() - Initialize the ODU bridge driver
+ * odu_bridge_init() - Initialize the ODU bridge driver
* @params: initialization parameters
*
* This function initialize all bridge internal data and register odu bridge to
@@ -1054,7 +1144,7 @@ static void odu_bridge_deregister_properties(void)
* -EINVAL - Bad parameter
* Other negative value - Failure
*/
-int ipa2_odu_bridge_init(struct odu_bridge_params *params)
+int odu_bridge_init(struct odu_bridge_params *params)
{
int res;
@@ -1080,6 +1170,10 @@ int ipa2_odu_bridge_init(struct odu_bridge_params *params)
ODU_BRIDGE_ERR("Already initialized\n");
return -EFAULT;
}
+ if (!ipa_is_ready()) {
+ ODU_BRIDGE_ERR("IPA is not ready\n");
+ return -EFAULT;
+ }
ODU_BRIDGE_DBG("device_ethaddr=%pM\n", params->device_ethaddr);
@@ -1089,6 +1183,13 @@ int ipa2_odu_bridge_init(struct odu_bridge_params *params)
return -ENOMEM;
}
+ res = odu_bridge_ipc_logging_init();
+ if (res) {
+ /* ODU_BRIDGE_ERR will crash on NULL if we use it here*/
+ pr_err("odu_bridge: failed to initialize ipc logging\n");
+ res = -EFAULT;
+ goto fail_ipc_create;
+ }
odu_bridge_ctx->class = class_create(THIS_MODULE, ODU_BRIDGE_DRV_NAME);
if (!odu_bridge_ctx->class) {
ODU_BRIDGE_ERR("Class_create err.\n");
@@ -1163,19 +1264,23 @@ fail_device_create:
fail_alloc_chrdev_region:
class_destroy(odu_bridge_ctx->class);
fail_class_create:
+ ipc_log_context_destroy(odu_bridge_ctx->logbuf);
+ ipc_log_context_destroy(odu_bridge_ctx->logbuf_low);
+fail_ipc_create:
kfree(odu_bridge_ctx);
odu_bridge_ctx = NULL;
return res;
}
+EXPORT_SYMBOL(odu_bridge_init);
/**
- * ipa2_odu_bridge_cleanup() - De-Initialize the ODU bridge driver
+ * odu_bridge_cleanup() - De-Initialize the ODU bridge driver
*
* Return codes: 0: success,
* -EINVAL - Bad parameter
* Other negative value - Failure
*/
-int ipa2_odu_bridge_cleanup(void)
+int odu_bridge_cleanup(void)
{
ODU_BRIDGE_FUNC_ENTRY();
@@ -1196,12 +1301,15 @@ int ipa2_odu_bridge_cleanup(void)
device_destroy(odu_bridge_ctx->class, odu_bridge_ctx->dev_num);
unregister_chrdev_region(odu_bridge_ctx->dev_num, 1);
class_destroy(odu_bridge_ctx->class);
+ ipc_log_context_destroy(odu_bridge_ctx->logbuf);
+ ipc_log_context_destroy(odu_bridge_ctx->logbuf_low);
kfree(odu_bridge_ctx);
odu_bridge_ctx = NULL;
ODU_BRIDGE_FUNC_EXIT();
return 0;
}
+EXPORT_SYMBOL(odu_bridge_cleanup);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/msm/ipa/ipa_v2/Makefile b/drivers/platform/msm/ipa/ipa_v2/Makefile
index c1ca6b7dba75..1bb9c91d3bd4 100644
--- a/drivers/platform/msm/ipa/ipa_v2/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v2/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_IPA) += ipat.o
ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
- ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o odu_bridge.o \
- ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o \
+ ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o ipa_rm.o \
+ ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o \
ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o
obj-$(CONFIG_RMNET_IPA) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 1452c59e2787..761aa6f9a4a1 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -785,7 +785,11 @@ int __ipa_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
- IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
+ if (entry->is_hdr_proc_ctx)
+ IPADBG("del hdr of sz=%d hdr_cnt=%d phys_base=%pa\n",
+ entry->hdr_len, htbl->hdr_cnt, &entry->phys_base);
+ else
+ IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
if (--entry->ref_cnt) {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index f4148a5e52f1..3f538a3ed8cf 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -1838,20 +1838,6 @@ enum ipacm_client_enum ipa2_get_client(int pipe_idx);
bool ipa2_get_client_uplink(int pipe_idx);
/*
- * ODU bridge
- */
-
-int ipa2_odu_bridge_init(struct odu_bridge_params *params);
-
-int ipa2_odu_bridge_connect(void);
-
-int ipa2_odu_bridge_disconnect(void);
-
-int ipa2_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata);
-
-int ipa2_odu_bridge_cleanup(void);
-
-/*
* IPADMA
*/
int ipa2_dma_init(void);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index ca8b9c41f94a..888345a23ba5 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5039,11 +5039,6 @@ int ipa2_bind_api_controller(enum ipa_hw_type ipa_hw_type,
api_ctrl->ipa_set_client = ipa2_set_client;
api_ctrl->ipa_get_client = ipa2_get_client;
api_ctrl->ipa_get_client_uplink = ipa2_get_client_uplink;
- api_ctrl->odu_bridge_init = ipa2_odu_bridge_init;
- api_ctrl->odu_bridge_connect = ipa2_odu_bridge_connect;
- api_ctrl->odu_bridge_disconnect = ipa2_odu_bridge_disconnect;
- api_ctrl->odu_bridge_tx_dp = ipa2_odu_bridge_tx_dp;
- api_ctrl->odu_bridge_cleanup = ipa2_odu_bridge_cleanup;
api_ctrl->ipa_dma_init = ipa2_dma_init;
api_ctrl->ipa_dma_enable = ipa2_dma_enable;
api_ctrl->ipa_dma_disable = ipa2_dma_disable;
diff --git a/drivers/platform/msm/ipa/ipa_v3/Makefile b/drivers/platform/msm/ipa/ipa_v3/Makefile
index 6452b12f553a..2ba86bbfd80c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/Makefile
@@ -2,8 +2,8 @@ obj-$(CONFIG_IPA3) += ipahal/
obj-$(CONFIG_IPA3) += ipat.o
ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
- ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o odu_bridge.o \
- ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o \
+ ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o ipa_rm.o \
+ ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o \
ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o
obj-$(CONFIG_RMNET_IPA3) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 30e554b648f5..d09363b725de 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -4046,6 +4046,7 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
ipa3_ctx->use_ipa_teth_bridge = resource_p->use_ipa_teth_bridge;
ipa3_ctx->ipa_bam_remote_mode = resource_p->ipa_bam_remote_mode;
ipa3_ctx->modem_cfg_emb_pipe_flt = resource_p->modem_cfg_emb_pipe_flt;
+ ipa3_ctx->ipa_wdi2 = resource_p->ipa_wdi2;
ipa3_ctx->wan_rx_ring_size = resource_p->wan_rx_ring_size;
ipa3_ctx->skip_uc_pipe_reset = resource_p->skip_uc_pipe_reset;
ipa3_ctx->tethered_flow_control = resource_p->tethered_flow_control;
@@ -4549,6 +4550,7 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->ipa3_hw_mode = 0;
ipa_drv_res->ipa_bam_remote_mode = false;
ipa_drv_res->modem_cfg_emb_pipe_flt = false;
+ ipa_drv_res->ipa_wdi2 = false;
ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ;
ipa_drv_res->apply_rg10_wa = false;
@@ -4609,6 +4611,13 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
ipa_drv_res->modem_cfg_emb_pipe_flt
? "True" : "False");
+ ipa_drv_res->ipa_wdi2 =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,ipa-wdi2");
+ IPADBG(": WDI-2.0 = %s\n",
+ ipa_drv_res->ipa_wdi2
+ ? "True" : "False");
+
ipa_drv_res->skip_uc_pipe_reset =
of_property_read_bool(pdev->dev.of_node,
"qcom,skip-uc-pipe-reset");
@@ -5203,6 +5212,11 @@ int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data)
{
struct ipa3_ready_cb_info *cb_info = NULL;
+ /* check ipa3_ctx existed or not */
+ if (!ipa3_ctx) {
+ IPADBG("IPA driver haven't initialized\n");
+ return -ENXIO;
+ }
mutex_lock(&ipa3_ctx->lock);
if (ipa3_ctx->ipa_initialization_complete) {
mutex_unlock(&ipa3_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index b8baa53ae9e9..f58751d4c0d3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -657,7 +657,11 @@ int __ipa3_del_hdr(u32 hdr_hdl)
return -EINVAL;
}
- IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
+ if (entry->is_hdr_proc_ctx)
+ IPADBG("del hdr of sz=%d hdr_cnt=%d phys_base=%pa\n",
+ entry->hdr_len, htbl->hdr_cnt, &entry->phys_base);
+ else
+ IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
if (--entry->ref_cnt) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 2b702daefddb..3fa7d4121a1b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -49,6 +49,9 @@
#define IPA_DL_CHECKSUM_LENGTH (8)
#define IPA_NUM_DESC_PER_SW_TX (3)
#define IPA_GENERIC_RX_POOL_SZ 192
+#define IPA_UC_FINISH_MAX 6
+#define IPA_UC_WAIT_MIN_SLEEP 1000
+#define IPA_UC_WAII_MAX_SLEEP 1200
#define IPA_MAX_STATUS_STAT_NUM 30
#define __FILENAME__ \
@@ -1385,6 +1388,14 @@ struct ipa3_uc_ctx {
u32 uc_status;
u32 uc_error_type;
u32 uc_error_timestamp;
+ phys_addr_t rdy_ring_base_pa;
+ phys_addr_t rdy_ring_rp_pa;
+ u32 rdy_ring_size;
+ phys_addr_t rdy_comp_ring_base_pa;
+ phys_addr_t rdy_comp_ring_wp_pa;
+ u32 rdy_comp_ring_size;
+ u32 *rdy_ring_rp_va;
+ u32 *rdy_comp_ring_wp_va;
};
/**
@@ -1514,6 +1525,7 @@ struct ipa3_ready_cb_info {
* @modem_cfg_emb_pipe_flt: modem configure embedded pipe filtering rules
* @logbuf: ipc log buffer for high priority messages
* @logbuf_low: ipc log buffer for low priority messages
+ * @ipa_wdi2: using wdi-2.0
* @ipa_bus_hdl: msm driver handle for the data path bus
* @ctrl: holds the core specific operations based on
* core version (vtable like)
@@ -1610,6 +1622,7 @@ struct ipa3_context {
bool use_ipa_teth_bridge;
bool ipa_bam_remote_mode;
bool modem_cfg_emb_pipe_flt;
+ bool ipa_wdi2;
/* featurize if memory footprint becomes a concern */
struct ipa3_stats stats;
void *smem_pipe_mem;
@@ -1685,6 +1698,7 @@ struct ipa3_plat_drv_res {
u32 ee;
bool ipa_bam_remote_mode;
bool modem_cfg_emb_pipe_flt;
+ bool ipa_wdi2;
u32 wan_rx_ring_size;
bool skip_uc_pipe_reset;
enum ipa_transport_type transport_prototype;
@@ -2088,20 +2102,6 @@ enum ipacm_client_enum ipa3_get_client(int pipe_idx);
bool ipa3_get_client_uplink(int pipe_idx);
/*
- * ODU bridge
- */
-
-int ipa3_odu_bridge_init(struct odu_bridge_params *params);
-
-int ipa3_odu_bridge_connect(void);
-
-int ipa3_odu_bridge_disconnect(void);
-
-int ipa3_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata);
-
-int ipa3_odu_bridge_cleanup(void);
-
-/*
* IPADMA
*/
int ipa3_dma_init(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 18784a64cf58..8ba2aa2a8b4d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -12,6 +12,7 @@
#include "ipa_i.h"
#include <linux/dmapool.h>
#include <linux/delay.h>
+#include <linux/mm.h>
#define IPA_HOLB_TMR_DIS 0x0
@@ -25,12 +26,14 @@
#define IPA_WDI_RESUMED BIT(2)
#define IPA_UC_POLL_SLEEP_USEC 100
-#define IPA_WDI_RX_RING_RES 0
-#define IPA_WDI_RX_RING_RP_RES 1
-#define IPA_WDI_TX_RING_RES 2
-#define IPA_WDI_CE_RING_RES 3
-#define IPA_WDI_CE_DB_RES 4
-#define IPA_WDI_MAX_RES 5
+#define IPA_WDI_RX_RING_RES 0
+#define IPA_WDI_RX_RING_RP_RES 1
+#define IPA_WDI_RX_COMP_RING_RES 2
+#define IPA_WDI_RX_COMP_RING_WP_RES 3
+#define IPA_WDI_TX_RING_RES 4
+#define IPA_WDI_CE_RING_RES 5
+#define IPA_WDI_CE_DB_RES 6
+#define IPA_WDI_MAX_RES 7
struct ipa_wdi_res {
struct ipa_wdi_buffer_info *res;
@@ -232,6 +235,21 @@ struct IpaHwWdiTxSetUpCmdData_t {
u8 reserved;
} __packed;
+struct IpaHwWdi2TxSetUpCmdData_t {
+ u32 comp_ring_base_pa;
+ u32 comp_ring_base_pa_hi;
+ u16 comp_ring_size;
+ u16 reserved_comp_ring;
+ u32 ce_ring_base_pa;
+ u32 ce_ring_base_pa_hi;
+ u16 ce_ring_size;
+ u16 reserved_ce_ring;
+ u32 ce_ring_doorbell_pa;
+ u32 ce_ring_doorbell_pa_hi;
+ u16 num_tx_buffers;
+ u8 ipa_pipe_number;
+ u8 reserved;
+} __packed;
/**
* struct IpaHwWdiRxSetUpCmdData_t - Structure holding the parameters for
* IPA_CPU_2_HW_CMD_WDI_RX_SET_UP command.
@@ -253,6 +271,19 @@ struct IpaHwWdiRxSetUpCmdData_t {
u8 ipa_pipe_number;
} __packed;
+struct IpaHwWdi2RxSetUpCmdData_t {
+ u32 rx_ring_base_pa;
+ u32 rx_ring_base_pa_hi;
+ u32 rx_ring_size;
+ u32 rx_ring_rp_pa;
+ u32 rx_ring_rp_pa_hi;
+ u32 rx_comp_ring_base_pa;
+ u32 rx_comp_ring_base_pa_hi;
+ u32 rx_comp_ring_size;
+ u32 rx_comp_ring_wp_pa;
+ u32 rx_comp_ring_wp_pa_hi;
+ u8 ipa_pipe_number;
+} __packed;
/**
* union IpaHwWdiRxExtCfgCmdData_t - Structure holding the parameters for
* IPA_CPU_2_HW_CMD_WDI_RX_EXT_CFG command.
@@ -554,7 +585,10 @@ static void ipa_release_uc_smmu_mappings(enum ipa_client_type client)
end = IPA_WDI_CE_DB_RES;
} else {
start = IPA_WDI_RX_RING_RES;
- end = IPA_WDI_RX_RING_RP_RES;
+ if (ipa3_ctx->ipa_wdi2)
+ end = IPA_WDI_RX_COMP_RING_WP_RES;
+ else
+ end = IPA_WDI_RX_RING_RP_RES;
}
for (i = start; i <= end; i++) {
@@ -656,6 +690,7 @@ static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
if (wlan_smmu_en && ipa3_ctx->smmu_present) {
switch (res_idx) {
case IPA_WDI_RX_RING_RP_RES:
+ case IPA_WDI_RX_COMP_RING_WP_RES:
case IPA_WDI_CE_DB_RES:
if (ipa_create_uc_smmu_mapping_pa(pa, len,
(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
@@ -667,6 +702,7 @@ static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
ipa_save_uc_smmu_mapping_pa(res_idx, pa, *iova, len);
break;
case IPA_WDI_RX_RING_RES:
+ case IPA_WDI_RX_COMP_RING_RES:
case IPA_WDI_TX_RING_RES:
case IPA_WDI_CE_RING_RES:
if (ipa_create_uc_smmu_mapping_sgt(sgt, iova)) {
@@ -702,6 +738,9 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
struct ipa3_mem_buffer cmd;
struct IpaHwWdiTxSetUpCmdData_t *tx;
struct IpaHwWdiRxSetUpCmdData_t *rx;
+ struct IpaHwWdi2TxSetUpCmdData_t *tx_2;
+ struct IpaHwWdi2RxSetUpCmdData_t *rx_2;
+
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
unsigned long va;
phys_addr_t pa;
@@ -749,7 +788,10 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
IPADBG("client=%d ep=%d\n", in->sys.client, ipa_ep_idx);
if (IPA_CLIENT_IS_CONS(in->sys.client)) {
- cmd.size = sizeof(*tx);
+ if (ipa3_ctx->ipa_wdi2)
+ cmd.size = sizeof(*tx_2);
+ else
+ cmd.size = sizeof(*tx);
IPADBG("comp_ring_base_pa=0x%pa\n",
&in->u.dl.comp_ring_base_pa);
IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
@@ -759,10 +801,54 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
&in->u.dl.ce_door_bell_pa);
IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
} else {
- cmd.size = sizeof(*rx);
- IPADBG("rx_ring_base_pa=0x%pa\n", &in->u.ul.rdy_ring_base_pa);
- IPADBG("rx_ring_size=%d\n", in->u.ul.rdy_ring_size);
- IPADBG("rx_ring_rp_pa=0x%pa\n", &in->u.ul.rdy_ring_rp_pa);
+ if (ipa3_ctx->ipa_wdi2)
+ cmd.size = sizeof(*rx_2);
+ else
+ cmd.size = sizeof(*rx);
+ IPADBG("rx_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_base_pa);
+ IPADBG("rx_ring_size=%d\n",
+ in->u.ul.rdy_ring_size);
+ IPADBG("rx_ring_rp_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_rp_pa);
+ IPADBG("rdy_ring_rp value =%d\n",
+ *in->u.ul.rdy_ring_rp_va);
+ IPADBG("rx_comp_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_base_pa);
+ IPADBG("rx_comp_ring_size=%d\n",
+ in->u.ul.rdy_comp_ring_size);
+ IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_wp_pa);
+ IPADBG("rx_comp_ring_wp value=%d\n",
+ *in->u.ul.rdy_comp_ring_wp_va);
+ ipa3_ctx->uc_ctx.rdy_ring_base_pa =
+ in->u.ul.rdy_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+ in->u.ul.rdy_ring_rp_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_size =
+ in->u.ul.rdy_ring_size;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
+ in->u.ul.rdy_comp_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+ in->u.ul.rdy_comp_ring_wp_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+ in->u.ul.rdy_comp_ring_size;
+ ipa3_ctx->uc_ctx.rdy_ring_rp_va =
+ in->u.ul.rdy_ring_rp_va;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va =
+ in->u.ul.rdy_comp_ring_wp_va;
+ /* check if the VA is empty */
+ if (!in->u.ul.rdy_ring_rp_va && ipa3_ctx->ipa_wdi2) {
+ IPAERR("rdy_ring_rp_va is empty, wdi2.0(%d)\n",
+ ipa3_ctx->ipa_wdi2);
+ goto dma_alloc_fail;
+ }
+ if (!in->u.ul.rdy_comp_ring_wp_va &&
+ ipa3_ctx->ipa_wdi2) {
+ IPAERR("comp_ring_wp_va is empty, wdi2.0(%d)\n",
+ ipa3_ctx->ipa_wdi2);
+ goto dma_alloc_fail;
+ }
}
cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
@@ -774,14 +860,16 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
}
if (IPA_CLIENT_IS_CONS(in->sys.client)) {
- tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base;
+ if (ipa3_ctx->ipa_wdi2) {
+ tx_2 = (struct IpaHwWdi2TxSetUpCmdData_t *)cmd.base;
- len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size :
- in->u.dl.comp_ring_size;
- IPADBG("TX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled,
+ len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size :
+ in->u.dl.comp_ring_size;
+ IPADBG("TX_2 ring smmu_en=%d ring_size=%d %d\n",
+ in->smmu_enabled,
in->u.dl_smmu.comp_ring_size,
in->u.dl.comp_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
in->smmu_enabled,
in->u.dl.comp_ring_base_pa,
&in->u.dl_smmu.comp_ring,
@@ -791,90 +879,260 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
IPAERR("fail to create uc mapping TX ring.\n");
result = -ENOMEM;
goto uc_timeout;
- }
- tx->comp_ring_base_pa = va;
- tx->comp_ring_size = len;
-
- len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
- in->u.dl.ce_ring_size;
- IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n",
- in->smmu_enabled,
- in->u.dl_smmu.ce_ring_size,
- in->u.dl.ce_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ }
+ tx_2->comp_ring_base_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ tx_2->comp_ring_base_pa = (u32) (va & 0xFFFFFFFF);
+ tx_2->comp_ring_size = len;
+ IPADBG("TX_2 comp_ring_base_pa_hi=0x%08x :0x%08x\n",
+ tx_2->comp_ring_base_pa_hi,
+ tx_2->comp_ring_base_pa);
+
+ len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
+ in->u.dl.ce_ring_size;
+ IPADBG("TX_2 CE ring smmu_en=%d ring_size=%d %d\n",
in->smmu_enabled,
- in->u.dl.ce_ring_base_pa,
- &in->u.dl_smmu.ce_ring,
- len,
- false,
- &va)) {
+ in->u.dl_smmu.ce_ring_size,
+ in->u.dl.ce_ring_size);
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ in->smmu_enabled,
+ in->u.dl.ce_ring_base_pa,
+ &in->u.dl_smmu.ce_ring,
+ len,
+ false,
+ &va)) {
IPAERR("fail to create uc mapping CE ring.\n");
result = -ENOMEM;
goto uc_timeout;
- }
- tx->ce_ring_base_pa = va;
- tx->ce_ring_size = len;
-
- pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
- in->u.dl.ce_door_bell_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ }
+ tx_2->ce_ring_base_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ tx_2->ce_ring_base_pa = (u32) (va & 0xFFFFFFFF);
+ tx_2->ce_ring_size = len;
+ IPADBG("TX_2 ce_ring_base_pa_hi=0x%08x :0x%08x\n",
+ tx_2->ce_ring_base_pa_hi,
+ tx_2->ce_ring_base_pa);
+
+ pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
+ in->u.dl.ce_door_bell_pa;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ in->smmu_enabled,
+ pa,
+ NULL,
+ 4,
+ true,
+ &va)) {
+ IPAERR("fail to create uc mapping CE DB.\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ tx_2->ce_ring_doorbell_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ tx_2->ce_ring_doorbell_pa = (u32) (va & 0xFFFFFFFF);
+ IPADBG("TX_2 ce_ring_doorbell_pa_hi=0x%08x :0x%08x\n",
+ tx_2->ce_ring_doorbell_pa_hi,
+ tx_2->ce_ring_doorbell_pa);
+
+ tx_2->num_tx_buffers = in->u.dl.num_tx_buffers;
+ tx_2->ipa_pipe_number = ipa_ep_idx;
+ } else {
+ tx = (struct IpaHwWdiTxSetUpCmdData_t *)cmd.base;
+
+ len = in->smmu_enabled ? in->u.dl_smmu.comp_ring_size :
+ in->u.dl.comp_ring_size;
+ IPADBG("TX ring smmu_en=%d ring_size=%d %d\n",
in->smmu_enabled,
- pa,
- NULL,
- 4,
- true,
- &va)) {
+ in->u.dl_smmu.comp_ring_size,
+ in->u.dl.comp_ring_size);
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+ in->smmu_enabled,
+ in->u.dl.comp_ring_base_pa,
+ &in->u.dl_smmu.comp_ring,
+ len,
+ false,
+ &va)) {
+ IPAERR("fail to create uc mapping TX ring.\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ tx->comp_ring_base_pa = va;
+ tx->comp_ring_size = len;
+ len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
+ in->u.dl.ce_ring_size;
+ IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n",
+ in->smmu_enabled,
+ in->u.dl_smmu.ce_ring_size,
+ in->u.dl.ce_ring_size);
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+ in->smmu_enabled,
+ in->u.dl.ce_ring_base_pa,
+ &in->u.dl_smmu.ce_ring,
+ len,
+ false,
+ &va)) {
+ IPAERR("fail to create uc mapping CE ring.\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ tx->ce_ring_base_pa = va;
+ tx->ce_ring_size = len;
+ pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
+ in->u.dl.ce_door_bell_pa;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+ in->smmu_enabled,
+ pa,
+ NULL,
+ 4,
+ true,
+ &va)) {
IPAERR("fail to create uc mapping CE DB.\n");
result = -ENOMEM;
goto uc_timeout;
+ }
+ tx->ce_ring_doorbell_pa = va;
+ tx->num_tx_buffers = in->u.dl.num_tx_buffers;
+ tx->ipa_pipe_number = ipa_ep_idx;
}
- tx->ce_ring_doorbell_pa = va;
-
- tx->num_tx_buffers = in->u.dl.num_tx_buffers;
- tx->ipa_pipe_number = ipa_ep_idx;
out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base +
ipahal_get_reg_base() +
ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
IPA_HW_WDI_TX_MBOX_START_INDEX/32,
IPA_HW_WDI_TX_MBOX_START_INDEX % 32);
} else {
- rx = (struct IpaHwWdiRxSetUpCmdData_t *)cmd.base;
+ if (ipa3_ctx->ipa_wdi2) {
+ rx_2 = (struct IpaHwWdi2RxSetUpCmdData_t *)cmd.base;
- len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size :
- in->u.ul.rdy_ring_size;
- IPADBG("RX ring smmu_en=%d ring_size=%d %d\n", in->smmu_enabled,
+ len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size :
+ in->u.ul.rdy_ring_size;
+ IPADBG("RX_2 ring smmu_en=%d ring_size=%d %d\n",
+ in->smmu_enabled,
in->u.ul_smmu.rdy_ring_size,
in->u.ul.rdy_ring_size);
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ in->smmu_enabled,
+ in->u.ul.rdy_ring_base_pa,
+ &in->u.ul_smmu.rdy_ring,
+ len,
+ false,
+ &va)) {
+ IPAERR("fail to create uc RX_2 ring.\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ rx_2->rx_ring_base_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ rx_2->rx_ring_base_pa = (u32) (va & 0xFFFFFFFF);
+ rx_2->rx_ring_size = len;
+ IPADBG("RX_2 rx_ring_base_pa_hi=0x%08x:0x%08x\n",
+ rx_2->rx_ring_base_pa_hi,
+ rx_2->rx_ring_base_pa);
+
+ pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
+ in->u.ul.rdy_ring_rp_pa;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ in->smmu_enabled,
+ pa,
+ NULL,
+ 4,
+ false,
+ &va)) {
+ IPAERR("fail to create uc RX_2 rng RP\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ rx_2->rx_ring_rp_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ rx_2->rx_ring_rp_pa = (u32) (va & 0xFFFFFFFF);
+ IPADBG("RX_2 rx_ring_rp_pa_hi=0x%08x :0x%08x\n",
+ rx_2->rx_ring_rp_pa_hi,
+ rx_2->rx_ring_rp_pa);
+ len = in->smmu_enabled ?
+ in->u.ul_smmu.rdy_comp_ring_size :
+ in->u.ul.rdy_comp_ring_size;
+ IPADBG("RX_2 ring smmu_en=%d comp_ring_size=%d %d\n",
in->smmu_enabled,
- in->u.ul.rdy_ring_base_pa,
- &in->u.ul_smmu.rdy_ring,
- len,
- false,
- &va)) {
- IPAERR("fail to create uc mapping RX ring.\n");
+ in->u.ul_smmu.rdy_comp_ring_size,
+ in->u.ul.rdy_comp_ring_size);
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_COMP_RING_RES,
+ in->smmu_enabled,
+ in->u.ul.rdy_comp_ring_base_pa,
+ &in->u.ul_smmu.rdy_comp_ring,
+ len,
+ false,
+ &va)) {
+ IPAERR("fail to create uc RX_2 comp_ring.\n");
result = -ENOMEM;
goto uc_timeout;
- }
- rx->rx_ring_base_pa = va;
- rx->rx_ring_size = len;
-
- pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
- in->u.ul.rdy_ring_rp_pa;
- if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ }
+ rx_2->rx_comp_ring_base_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ rx_2->rx_comp_ring_base_pa = (u32) (va & 0xFFFFFFFF);
+ rx_2->rx_comp_ring_size = len;
+ IPADBG("RX_2 rx_comp_ring_base_pa_hi=0x%08x:0x%08x\n",
+ rx_2->rx_comp_ring_base_pa_hi,
+ rx_2->rx_comp_ring_base_pa);
+
+ pa = in->smmu_enabled ?
+ in->u.ul_smmu.rdy_comp_ring_wp_pa :
+ in->u.ul.rdy_comp_ring_wp_pa;
+ if (ipa_create_uc_smmu_mapping(
+ IPA_WDI_RX_COMP_RING_WP_RES,
+ in->smmu_enabled,
+ pa,
+ NULL,
+ 4,
+ false,
+ &va)) {
+ IPAERR("fail to create uc RX_2 comp_rng WP\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ rx_2->rx_comp_ring_wp_pa_hi =
+ (u32) ((va & 0xFFFFFFFF00000000) >> 32);
+ rx_2->rx_comp_ring_wp_pa = (u32) (va & 0xFFFFFFFF);
+ IPADBG("RX_2 rx_comp_ring_wp_pa_hi=0x%08x:0x%08x\n",
+ rx_2->rx_comp_ring_wp_pa_hi,
+ rx_2->rx_comp_ring_wp_pa);
+ rx_2->ipa_pipe_number = ipa_ep_idx;
+ } else {
+ rx = (struct IpaHwWdiRxSetUpCmdData_t *)cmd.base;
+
+ len = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_size :
+ in->u.ul.rdy_ring_size;
+ IPADBG("RX ring smmu_en=%d ring_size=%d %d\n",
in->smmu_enabled,
- pa,
- NULL,
- 4,
- false,
- &va)) {
+ in->u.ul_smmu.rdy_ring_size,
+ in->u.ul.rdy_ring_size);
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+ in->smmu_enabled,
+ in->u.ul.rdy_ring_base_pa,
+ &in->u.ul_smmu.rdy_ring,
+ len,
+ false,
+ &va)) {
+ IPAERR("fail to create uc mapping RX ring.\n");
+ result = -ENOMEM;
+ goto uc_timeout;
+ }
+ rx->rx_ring_base_pa = va;
+ rx->rx_ring_size = len;
+
+ pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
+ in->u.ul.rdy_ring_rp_pa;
+ if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+ in->smmu_enabled,
+ pa,
+ NULL,
+ 4,
+ false,
+ &va)) {
IPAERR("fail to create uc mapping RX rng RP\n");
result = -ENOMEM;
goto uc_timeout;
+ }
+ rx->rx_ring_rp_pa = va;
+ rx->ipa_pipe_number = ipa_ep_idx;
}
- rx->rx_ring_rp_pa = va;
-
- rx->ipa_pipe_number = ipa_ep_idx;
out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base +
ipahal_get_reg_base() +
ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
@@ -1083,6 +1341,7 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
union IpaHwWdiCommonChCmdData_t disable;
struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
u32 prod_hdl;
+ int i;
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
ipa3_ctx->ep[clnt_hdl].valid == 0) {
@@ -1094,6 +1353,28 @@ int ipa3_disable_wdi_pipe(u32 clnt_hdl)
if (result)
return result;
+ /* checking rdy_ring_rp_pa matches the rdy_comp_ring_wp_pa on WDI2.0 */
+ if (ipa3_ctx->ipa_wdi2) {
+ for (i = 0; i < IPA_UC_FINISH_MAX; i++) {
+ IPADBG("(%d) rp_value(%u), comp_wp_value(%u)\n",
+ i,
+ *ipa3_ctx->uc_ctx.rdy_ring_rp_va,
+ *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va);
+ if (*ipa3_ctx->uc_ctx.rdy_ring_rp_va !=
+ *ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va) {
+ usleep_range(IPA_UC_WAIT_MIN_SLEEP,
+ IPA_UC_WAII_MAX_SLEEP);
+ } else {
+ break;
+ }
+ }
+ /* In case ipa_uc still haven't processed all
+ * pending descriptors, we have to assert
+ */
+ if (i == IPA_UC_FINISH_MAX)
+ WARN_ON(1);
+ }
+
IPADBG("ep=%d\n", clnt_hdl);
ep = &ipa3_ctx->ep[clnt_hdl];
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index f1ec3069d365..1c4f812bc40f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4543,11 +4543,6 @@ int ipa3_bind_api_controller(enum ipa_hw_type ipa_hw_type,
api_ctrl->ipa_set_client = ipa3_set_client;
api_ctrl->ipa_get_client = ipa3_get_client;
api_ctrl->ipa_get_client_uplink = ipa3_get_client_uplink;
- api_ctrl->odu_bridge_init = ipa3_odu_bridge_init;
- api_ctrl->odu_bridge_connect = ipa3_odu_bridge_connect;
- api_ctrl->odu_bridge_disconnect = ipa3_odu_bridge_disconnect;
- api_ctrl->odu_bridge_tx_dp = ipa3_odu_bridge_tx_dp;
- api_ctrl->odu_bridge_cleanup = ipa3_odu_bridge_cleanup;
api_ctrl->ipa_dma_init = ipa3_dma_init;
api_ctrl->ipa_dma_enable = ipa3_dma_enable;
api_ctrl->ipa_dma_disable = ipa3_dma_disable;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index 2677c9e0c83c..f7a74283056c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -10,6 +10,8 @@
* GNU General Public License for more details.
*/
+#include <linux/ipc_logging.h>
+#include <linux/debugfs.h>
#include "ipahal.h"
#include "ipahal_i.h"
#include "ipahal_reg_i.h"
@@ -531,7 +533,7 @@ static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
int j;
struct ipahal_imm_cmd_obj zero_obj;
- IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
@@ -592,7 +594,8 @@ u16 ipahal_imm_cmd_get_opcode(enum ipahal_imm_cmd_name cmd)
return -EFAULT;
}
- IPAHAL_DBG("Get opcode of IMM_CMD=%s\n", ipahal_imm_cmd_name_str(cmd));
+ IPAHAL_DBG_LOW("Get opcode of IMM_CMD=%s\n",
+ ipahal_imm_cmd_name_str(cmd));
opcode = ipahal_imm_cmd_objs[ipahal_ctx->hw_type][cmd].opcode;
if (opcode == -1) {
IPAHAL_ERR("Try to get opcode of obsolete IMM_CMD=%s\n",
@@ -624,7 +627,8 @@ u16 ipahal_imm_cmd_get_opcode_param(enum ipahal_imm_cmd_name cmd, int param)
return -EFAULT;
}
- IPAHAL_DBG("Get opcode of IMM_CMD=%s\n", ipahal_imm_cmd_name_str(cmd));
+ IPAHAL_DBG_LOW("Get opcode of IMM_CMD=%s\n",
+ ipahal_imm_cmd_name_str(cmd));
if (!ipahal_imm_cmd_objs[ipahal_ctx->hw_type][cmd].dyn_op) {
IPAHAL_ERR("IMM_CMD=%s does not support dynamic opcode\n",
@@ -681,7 +685,7 @@ struct ipahal_imm_cmd_pyld *ipahal_construct_imm_cmd(
return NULL;
}
- IPAHAL_DBG("construct IMM_CMD:%s\n", ipahal_imm_cmd_name_str(cmd));
+ IPAHAL_DBG_LOW("construct IMM_CMD:%s\n", ipahal_imm_cmd_name_str(cmd));
return ipahal_imm_cmd_objs[ipahal_ctx->hw_type][cmd].construct(
cmd, params, is_atomic_ctx);
}
@@ -895,7 +899,7 @@ 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);
+ IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
/*
* Since structure alignment is implementation dependent,
@@ -960,7 +964,7 @@ void ipahal_pkt_status_parse(const void *unparsed_status,
return;
}
- IPAHAL_DBG("Parse Status Packet\n");
+ IPAHAL_DBG_LOW("Parse Status Packet\n");
memset(status, 0, sizeof(*status));
ipahal_pkt_status_objs[ipahal_ctx->hw_type].parse(unparsed_status,
status);
@@ -983,6 +987,72 @@ const char *ipahal_pkt_status_exception_str(
return ipahal_pkt_status_exception_to_str[exception];
}
+static int ipahal_ipc_logging_init(void)
+{
+ ipahal_ctx->ipc_logbuf =
+ ipc_log_context_create(IPAHAL_IPC_LOG_PAGES, "ipahal", 0);
+ if (!ipahal_ctx->ipc_logbuf) {
+ /* Cannot use the logging macros as no log buffers yet */
+ pr_err("ipaghal: failed to create ipc_logbuf\n");
+ return -ENOMEM;
+ }
+
+ ipahal_ctx->ipc_logbuf_low =
+ ipc_log_context_create(IPAHAL_IPC_LOG_PAGES, "ipahal_low", 0);
+ if (!ipahal_ctx->ipc_logbuf_low) {
+ /* Cannot use the logging macros as no log buffers yet */
+ pr_err("ipaghal: failed to create ipc_logbuf_low\n");
+ ipc_log_context_destroy(ipahal_ctx->ipc_logbuf);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void ipahal_debugfs_init(void)
+{
+ const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH |
+ S_IWUSR | S_IWGRP;
+
+ ipahal_ctx->dent = debugfs_create_dir("ipahal", 0);
+ if (!ipahal_ctx->dent || IS_ERR(ipahal_ctx->dent)) {
+ IPAHAL_ERR("fail to create ipahal debugfs folder\n");
+ return;
+ }
+
+ ipahal_ctx->dfile_enable_low_prio_ipc =
+ debugfs_create_u32("enable_low_prio_log", read_write_mode,
+ ipahal_ctx->dent, &ipahal_ctx->enable_low_prio_ipc);
+ if (!ipahal_ctx->dfile_enable_low_prio_ipc ||
+ IS_ERR(ipahal_ctx->dfile_enable_low_prio_ipc)) {
+ IPAHAL_ERR("fail create enable_low_prio_log debugfs file\n");
+ goto fail;
+ }
+
+ return;
+fail:
+ debugfs_remove_recursive(ipahal_ctx->dent);
+ ipahal_ctx->dent = NULL;
+}
+
+static void ipahal_debugfs_remove(void)
+{
+ if (!ipahal_ctx)
+ return;
+
+ if (IS_ERR(ipahal_ctx->dent)) {
+ IPAHAL_ERR("ipahal debugfs folder was not created\n");
+ return;
+ }
+
+ debugfs_remove_recursive(ipahal_ctx->dent);
+}
+#else /* CONFIG_DEBUG_FS */
+static void ipahal_debugfs_init(void) {}
+static void ipahal_debugfs_remove(void) {}
+#endif /* CONFIG_DEBUG_FS */
+
int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
{
int result;
@@ -997,16 +1067,23 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
goto bail_err_exit;
}
+ if (ipahal_ipc_logging_init()) {
+ /* Cannot use the logging macros as no log buffers yet */
+ pr_err("ipahal: failed to initialize ipc logging\n");
+ result = -ENOMEM;
+ goto bail_free_ctx;
+ }
+
if (ipa_hw_type < IPA_HW_v3_0) {
IPAHAL_ERR("ipahal supported on IPAv3 and later only\n");
result = -EINVAL;
- goto bail_free_ctx;
+ goto bail_destroy_ipc;
}
if (!base) {
IPAHAL_ERR("invalid memory io mapping addr\n");
result = -EINVAL;
- goto bail_free_ctx;
+ goto bail_destroy_ipc;
}
ipahal_ctx->hw_type = ipa_hw_type;
@@ -1015,23 +1092,28 @@ int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base)
if (ipahal_reg_init(ipa_hw_type)) {
IPAHAL_ERR("failed to init ipahal reg\n");
result = -EFAULT;
- goto bail_free_ctx;
+ goto bail_destroy_ipc;
}
if (ipahal_imm_cmd_init(ipa_hw_type)) {
IPAHAL_ERR("failed to init ipahal imm cmd\n");
result = -EFAULT;
- goto bail_free_ctx;
+ goto bail_destroy_ipc;
}
if (ipahal_pkt_status_init(ipa_hw_type)) {
IPAHAL_ERR("failed to init ipahal pkt status\n");
result = -EFAULT;
- goto bail_free_ctx;
+ goto bail_destroy_ipc;
}
+ ipahal_debugfs_init();
+
return 0;
+bail_destroy_ipc:
+ ipc_log_context_destroy(ipahal_ctx->ipc_logbuf_low);
+ ipc_log_context_destroy(ipahal_ctx->ipc_logbuf);
bail_free_ctx:
kfree(ipahal_ctx);
ipahal_ctx = NULL;
@@ -1042,7 +1124,7 @@ bail_err_exit:
void ipahal_destroy(void)
{
IPAHAL_DBG("Entry\n");
-
+ ipahal_debugfs_remove();
kfree(ipahal_ctx);
ipahal_ctx = NULL;
}
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 c5dbf0185267..3c513a7d4dc1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -14,20 +14,65 @@
#define _IPAHAL_I_H_
#define IPAHAL_DRV_NAME "ipahal"
+
+#define IPAHAL_IPC_LOG_PAGES 10
+#define IPAHAL_IPC_LOG(buf, fmt, args...) \
+ ipc_log_string((buf), \
+ IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+
#define IPAHAL_DBG(fmt, args...) \
- pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (likely(ipahal_ctx)) { \
+ IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf, fmt, ## args); \
+ IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
+
+#define IPAHAL_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPAHAL_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (likely(ipahal_ctx) && \
+ ipahal_ctx->enable_low_prio_ipc) { \
+ IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
+
#define IPAHAL_ERR(fmt, args...) \
- pr_err(IPAHAL_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(IPAHAL_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ if (likely(ipahal_ctx)) { \
+ IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf, fmt, ## args); \
+ IPAHAL_IPC_LOG(ipahal_ctx->ipc_logbuf_low, \
+ fmt, ## args); \
+ } \
+ } while (0)
/*
* struct ipahal_context - HAL global context data
* @hw_type: IPA H/W type/version.
* @base: Base address to be used for accessing IPA memory. This is
* I/O memory mapped address.
+ * @ipc_logbuf: IPC debug logs buffer
+ * @ipc_logbuf_low: IPC Low priority debug logs buffer
+ * @enable_low_prio_ipc: Flag telling to enable low priority logging
+ * Controlled by debugfs. default is off
+ * @dent: Debugfs folder dir entry
+ * @dfile_enable_low_prio_ipc: Debugfs file for enable_low_prio_ipc
*/
struct ipahal_context {
enum ipa_hw_type hw_type;
void __iomem *base;
+ void *ipc_logbuf;
+ void *ipc_logbuf_low;
+ u32 enable_low_prio_ipc;
+ struct dentry *dent;
+ struct dentry *dfile_enable_low_prio_ipc;
};
extern struct ipahal_context *ipahal_ctx;
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 1e5733d3101c..cf0fa16b2bbc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <linux/ipc_logging.h>
#include <linux/init.h>
#include <linux/ipa.h>
#include <linux/kernel.h>
@@ -1064,7 +1065,7 @@ int ipahal_reg_init(enum ipa_hw_type ipa_hw_type)
int j;
struct ipahal_reg_obj zero_obj;
- IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
+ IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
memset(&zero_obj, 0, sizeof(zero_obj));
for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
@@ -1131,7 +1132,7 @@ u32 ipahal_read_reg_n(enum ipahal_reg_name reg, u32 n)
return -EFAULT;
}
- IPAHAL_DBG("read from %s n=%u\n",
+ IPAHAL_DBG_LOW("read from %s n=%u\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
@@ -1157,7 +1158,7 @@ void ipahal_write_reg_mn(enum ipahal_reg_name reg, u32 m, u32 n, u32 val)
return;
}
- IPAHAL_DBG("write to %s m=%u n=%u val=%u\n",
+ IPAHAL_DBG_LOW("write to %s m=%u n=%u val=%u\n",
ipahal_reg_name_str(reg), m, n, val);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
@@ -1197,7 +1198,7 @@ u32 ipahal_read_reg_n_fields(enum ipahal_reg_name reg, u32 n, void *fields)
return -EFAULT;
}
- IPAHAL_DBG("read from %s n=%u and parse it\n",
+ IPAHAL_DBG_LOW("read from %s n=%u and parse it\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
@@ -1232,7 +1233,7 @@ void ipahal_write_reg_n_fields(enum ipahal_reg_name reg, u32 n,
return;
}
- IPAHAL_DBG("write to %s n=%u after constructing it\n",
+ IPAHAL_DBG_LOW("write to %s n=%u after constructing it\n",
ipahal_reg_name_str(reg), n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
@@ -1260,7 +1261,7 @@ u32 ipahal_get_reg_mn_ofst(enum ipahal_reg_name reg, u32 m, u32 n)
return -EFAULT;
}
- IPAHAL_DBG("get offset of %s m=%u n=%u\n",
+ IPAHAL_DBG_LOW("get offset of %s m=%u n=%u\n",
ipahal_reg_name_str(reg), m, n);
offset = ipahal_reg_objs[ipahal_ctx->hw_type][reg].offset;
if (offset == -1) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/odu_bridge.c b/drivers/platform/msm/ipa/ipa_v3/odu_bridge.c
deleted file mode 100644
index aef1e5130421..000000000000
--- a/drivers/platform/msm/ipa/ipa_v3/odu_bridge.c
+++ /dev/null
@@ -1,1233 +0,0 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/debugfs.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/if_ether.h>
-#include <linux/ioctl.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/msm_ipa.h>
-#include <linux/mutex.h>
-#include <linux/skbuff.h>
-#include <linux/types.h>
-#include <linux/ipv6.h>
-#include <net/addrconf.h>
-#include <linux/ipa.h>
-#include "ipa_i.h"
-
-#define ODU_BRIDGE_DRV_NAME "odu_ipa_bridge"
-
-#define ODU_BRIDGE_DBG(fmt, args...) \
- pr_debug(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, \
- __func__, __LINE__, ## args)
-#define ODU_BRIDGE_ERR(fmt, args...) \
- pr_err(ODU_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
-#define ODU_BRIDGE_FUNC_ENTRY() \
- ODU_BRIDGE_DBG("ENTRY\n")
-#define ODU_BRIDGE_FUNC_EXIT() \
- ODU_BRIDGE_DBG("EXIT\n")
-
-
-#define ODU_BRIDGE_IS_QMI_ADDR(daddr) \
- (memcmp(&(daddr), &ipa3_odu_bridge_ctx->llv6_addr, sizeof((daddr))) \
- == 0)
-
-#define ODU_BRIDGE_IPV4_HDR_NAME "odu_br_ipv4"
-#define ODU_BRIDGE_IPV6_HDR_NAME "odu_br_ipv6"
-
-#define IPA_ODU_SYS_DESC_FIFO_SZ 0x800
-
-#ifdef CONFIG_COMPAT
-#define ODU_BRIDGE_IOC_SET_LLV6_ADDR32 _IOW(ODU_BRIDGE_IOC_MAGIC, \
- ODU_BRIDGE_IOCTL_SET_LLV6_ADDR, \
- compat_uptr_t)
-#endif
-
-/**
- * struct stats - driver statistics, viewable using debugfs
- * @num_ul_packets: number of packets bridged in uplink direction
- * @num_dl_packets: number of packets bridged in downink direction
- * bridge
- * @num_lan_packets: number of packets bridged to APPS on bridge mode
- */
-struct stats {
- u64 num_ul_packets;
- u64 num_dl_packets;
- u64 num_lan_packets;
-};
-
-/**
- * struct ipa3_odu_bridge_ctx - ODU bridge driver context information
- * @class: kernel class pointer
- * @dev_num: kernel device number
- * @dev: kernel device struct pointer
- * @cdev: kernel character device struct
- * @netdev_name: network interface name
- * @device_ethaddr: network interface ethernet address
- * @priv: client's private data. to be used in client's callbacks
- * @tx_dp_notify: client callback for handling IPA ODU_PROD callback
- * @send_dl_skb: client callback for sending skb in downlink direction
- * @stats: statistics, how many packets were transmitted using the SW bridge
- * @is_conencted: is bridge connected ?
- * @mode: ODU mode (router/bridge)
- * @lock: for the initialization, connect and disconnect synchronization
- * @llv6_addr: link local IPv6 address of ODU network interface
- * @odu_br_ipv4_hdr_hdl: handle for partial ipv4 ethernet header
- * @odu_br_ipv6_hdr_hdl: handle for partial ipv6 ethernet header
- * @odu_prod_hdl: handle for IPA_CLIENT_ODU_PROD pipe
- * @odu_emb_cons_hdl: handle for IPA_CLIENT_ODU_EMB_CONS pipe
- * @odu_teth_cons_hdl: handle for IPA_CLIENT_ODU_TETH_CONS pipe
- */
-struct ipa3_odu_bridge_ctx {
- struct class *class;
- dev_t dev_num;
- struct device *dev;
- struct cdev cdev;
- char netdev_name[IPA_RESOURCE_NAME_MAX];
- u8 device_ethaddr[ETH_ALEN];
- void *priv;
- ipa_notify_cb tx_dp_notify;
- int (*send_dl_skb)(void *priv, struct sk_buff *skb);
- struct stats stats;
- bool is_connected;
- enum odu_bridge_mode mode;
- struct mutex lock;
- struct in6_addr llv6_addr;
- uint32_t odu_br_ipv4_hdr_hdl;
- uint32_t odu_br_ipv6_hdr_hdl;
- u32 odu_prod_hdl;
- u32 odu_emb_cons_hdl;
- u32 odu_teth_cons_hdl;
- u32 ipa_sys_desc_size;
-};
-static struct ipa3_odu_bridge_ctx *ipa3_odu_bridge_ctx;
-
-#ifdef CONFIG_DEBUG_FS
-#define ODU_MAX_MSG_LEN 512
-static char dbg_buff[ODU_MAX_MSG_LEN];
-#endif
-
-static void ipa3_odu_bridge_emb_cons_cb(void *priv, enum ipa_dp_evt_type evt,
- unsigned long data)
-{
- ODU_BRIDGE_FUNC_ENTRY();
- if (evt != IPA_RECEIVE) {
- ODU_BRIDGE_ERR("unexpected event\n");
- WARN_ON(1);
- return;
- }
- ipa3_odu_bridge_ctx->send_dl_skb(priv, (struct sk_buff *)data);
- ipa3_odu_bridge_ctx->stats.num_dl_packets++;
- ODU_BRIDGE_FUNC_EXIT();
-}
-
-static void ipa3_odu_bridge_teth_cons_cb(void *priv, enum ipa_dp_evt_type evt,
- unsigned long data)
-{
- struct ipv6hdr *ipv6hdr;
- struct sk_buff *skb = (struct sk_buff *)data;
- struct sk_buff *skb_copied;
-
- ODU_BRIDGE_FUNC_ENTRY();
- if (evt != IPA_RECEIVE) {
- ODU_BRIDGE_ERR("unexpected event\n");
- WARN_ON(1);
- return;
- }
-
- ipv6hdr = (struct ipv6hdr *)(skb->data + ETH_HLEN);
- if (ipv6hdr->version == 6 &&
- ipv6_addr_is_multicast(&ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("Multicast pkt, send to APPS and adapter\n");
- skb_copied = skb_clone(skb, GFP_KERNEL);
- if (skb_copied) {
- ipa3_odu_bridge_ctx->
- tx_dp_notify(ipa3_odu_bridge_ctx->priv,
- IPA_RECEIVE,
- (unsigned long) skb_copied);
- ipa3_odu_bridge_ctx->stats.num_lan_packets++;
- } else {
- ODU_BRIDGE_ERR("No memory\n");
- }
- }
-
- ipa3_odu_bridge_ctx->send_dl_skb(priv, skb);
- ipa3_odu_bridge_ctx->stats.num_dl_packets++;
- ODU_BRIDGE_FUNC_EXIT();
-}
-
-static int ipa3_odu_bridge_connect_router(void)
-{
- struct ipa_sys_connect_params odu_prod_params;
- struct ipa_sys_connect_params odu_emb_cons_params;
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- memset(&odu_prod_params, 0, sizeof(odu_prod_params));
- memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));
-
- /* configure RX (ODU->IPA) EP */
- odu_prod_params.client = IPA_CLIENT_ODU_PROD;
- odu_prod_params.ipa_ep_cfg.hdr.hdr_len = ETH_HLEN;
- odu_prod_params.ipa_ep_cfg.nat.nat_en = IPA_SRC_NAT;
- odu_prod_params.desc_fifo_sz = ipa3_odu_bridge_ctx->ipa_sys_desc_size;
- odu_prod_params.priv = ipa3_odu_bridge_ctx->priv;
- odu_prod_params.notify = ipa3_odu_bridge_ctx->tx_dp_notify;
- odu_prod_params.keep_ipa_awake = true;
- res = ipa3_setup_sys_pipe(&odu_prod_params,
- &ipa3_odu_bridge_ctx->odu_prod_hdl);
- if (res) {
- ODU_BRIDGE_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
- goto fail_odu_prod;
- }
-
- /* configure TX (IPA->ODU) EP */
- odu_emb_cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
- odu_emb_cons_params.ipa_ep_cfg.hdr.hdr_len = ETH_HLEN;
- odu_emb_cons_params.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
- odu_emb_cons_params.desc_fifo_sz =
- ipa3_odu_bridge_ctx->ipa_sys_desc_size;
- odu_emb_cons_params.priv = ipa3_odu_bridge_ctx->priv;
- odu_emb_cons_params.notify = ipa3_odu_bridge_emb_cons_cb;
- odu_emb_cons_params.keep_ipa_awake = true;
- res = ipa3_setup_sys_pipe(&odu_emb_cons_params,
- &ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
- if (res) {
- ODU_BRIDGE_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
- goto fail_odu_emb_cons;
- }
-
- ODU_BRIDGE_DBG("odu_prod_hdl = %d, odu_emb_cons_hdl = %d\n",
- ipa3_odu_bridge_ctx->odu_prod_hdl,
- ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
-
- ODU_BRIDGE_FUNC_EXIT();
-
- return 0;
-
-fail_odu_emb_cons:
- ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_prod_hdl);
- ipa3_odu_bridge_ctx->odu_prod_hdl = 0;
-fail_odu_prod:
- return res;
-}
-
-static int ipa3_odu_bridge_connect_bridge(void)
-{
- struct ipa_sys_connect_params odu_prod_params;
- struct ipa_sys_connect_params odu_emb_cons_params;
- struct ipa_sys_connect_params odu_teth_cons_params;
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- memset(&odu_prod_params, 0, sizeof(odu_prod_params));
- memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));
-
- /* Build IPA Resource manager dependency graph */
- ODU_BRIDGE_DBG("build dependency graph\n");
- res = ipa3_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
- IPA_RM_RESOURCE_Q6_CONS);
- if (res && res != -EINPROGRESS) {
- ODU_BRIDGE_ERR("ipa3_rm_add_dependency() failed\n");
- goto fail_add_dependency_1;
- }
-
- res = ipa3_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
- IPA_RM_RESOURCE_ODU_ADAPT_CONS);
- if (res && res != -EINPROGRESS) {
- ODU_BRIDGE_ERR("ipa3_rm_add_dependency() failed\n");
- goto fail_add_dependency_2;
- }
-
- /* configure RX (ODU->IPA) EP */
- odu_prod_params.client = IPA_CLIENT_ODU_PROD;
- odu_prod_params.desc_fifo_sz = IPA_ODU_SYS_DESC_FIFO_SZ;
- odu_prod_params.priv = ipa3_odu_bridge_ctx->priv;
- odu_prod_params.notify = ipa3_odu_bridge_ctx->tx_dp_notify;
- odu_prod_params.keep_ipa_awake = true;
- odu_prod_params.skip_ep_cfg = true;
- res = ipa3_setup_sys_pipe(&odu_prod_params,
- &ipa3_odu_bridge_ctx->odu_prod_hdl);
- if (res) {
- ODU_BRIDGE_ERR("fail to setup sys pipe ODU_PROD %d\n", res);
- goto fail_odu_prod;
- }
-
- /* configure TX tethered (IPA->ODU) EP */
- odu_teth_cons_params.client = IPA_CLIENT_ODU_TETH_CONS;
- odu_teth_cons_params.desc_fifo_sz = IPA_ODU_SYS_DESC_FIFO_SZ;
- odu_teth_cons_params.priv = ipa3_odu_bridge_ctx->priv;
- odu_teth_cons_params.notify = ipa3_odu_bridge_teth_cons_cb;
- odu_teth_cons_params.keep_ipa_awake = true;
- odu_teth_cons_params.skip_ep_cfg = true;
- res = ipa3_setup_sys_pipe(&odu_teth_cons_params,
- &ipa3_odu_bridge_ctx->odu_teth_cons_hdl);
- if (res) {
- ODU_BRIDGE_ERR("fail to setup sys pipe ODU_TETH_CONS %d\n",
- res);
- goto fail_odu_teth_cons;
- }
-
- /* configure TX embedded(IPA->ODU) EP */
- odu_emb_cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
- odu_emb_cons_params.ipa_ep_cfg.hdr.hdr_len = ETH_HLEN;
- odu_emb_cons_params.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
- odu_emb_cons_params.desc_fifo_sz = IPA_ODU_SYS_DESC_FIFO_SZ;
- odu_emb_cons_params.priv = ipa3_odu_bridge_ctx->priv;
- odu_emb_cons_params.notify = ipa3_odu_bridge_emb_cons_cb;
- odu_emb_cons_params.keep_ipa_awake = true;
- res = ipa3_setup_sys_pipe(&odu_emb_cons_params,
- &ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
- if (res) {
- ODU_BRIDGE_ERR("fail to setup sys pipe ODU_EMB_CONS %d\n", res);
- goto fail_odu_emb_cons;
- }
-
- ODU_BRIDGE_DBG("odu_prod_hdl = %d, odu_emb_cons_hdl = %d\n",
- ipa3_odu_bridge_ctx->odu_prod_hdl,
- ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
- ODU_BRIDGE_DBG("odu_teth_cons_hdl = %d\n",
- ipa3_odu_bridge_ctx->odu_teth_cons_hdl);
-
- ODU_BRIDGE_FUNC_EXIT();
-
- return 0;
-
-fail_odu_emb_cons:
- ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_teth_cons_hdl);
- ipa3_odu_bridge_ctx->odu_teth_cons_hdl = 0;
-fail_odu_teth_cons:
- ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_prod_hdl);
- ipa3_odu_bridge_ctx->odu_prod_hdl = 0;
-fail_odu_prod:
- ipa3_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
- IPA_RM_RESOURCE_ODU_ADAPT_CONS);
-fail_add_dependency_2:
- ipa3_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
- IPA_RM_RESOURCE_Q6_CONS);
-fail_add_dependency_1:
- return res;
-}
-
-static int ipa3_odu_bridge_disconnect_router(void)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- res = ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_prod_hdl);
- if (res)
- ODU_BRIDGE_ERR("teardown ODU PROD failed\n");
- ipa3_odu_bridge_ctx->odu_prod_hdl = 0;
-
- res = ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
- if (res)
- ODU_BRIDGE_ERR("teardown ODU EMB CONS failed\n");
- ipa3_odu_bridge_ctx->odu_emb_cons_hdl = 0;
-
- ODU_BRIDGE_FUNC_EXIT();
-
- return 0;
-}
-
-static int ipa3_odu_bridge_disconnect_bridge(void)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- res = ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_prod_hdl);
- if (res)
- ODU_BRIDGE_ERR("teardown ODU PROD failed\n");
- ipa3_odu_bridge_ctx->odu_prod_hdl = 0;
-
- res = ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_teth_cons_hdl);
- if (res)
- ODU_BRIDGE_ERR("teardown ODU TETH CONS failed\n");
- ipa3_odu_bridge_ctx->odu_teth_cons_hdl = 0;
-
- res = ipa3_teardown_sys_pipe(ipa3_odu_bridge_ctx->odu_emb_cons_hdl);
- if (res)
- ODU_BRIDGE_ERR("teardown ODU EMB CONS failed\n");
- ipa3_odu_bridge_ctx->odu_emb_cons_hdl = 0;
-
- /* Delete IPA Resource manager dependency graph */
- ODU_BRIDGE_DBG("deleting dependency graph\n");
- res = ipa3_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
- IPA_RM_RESOURCE_Q6_CONS);
- if (res && res != -EINPROGRESS)
- ODU_BRIDGE_ERR("ipa3_rm_delete_dependency() failed\n");
-
- res = ipa3_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
- IPA_RM_RESOURCE_ODU_ADAPT_CONS);
- if (res && res != -EINPROGRESS)
- ODU_BRIDGE_ERR("ipa3_rm_delete_dependency() failed\n");
-
- return 0;
-}
-
-/**
- * ipa3_odu_bridge_disconnect() - Disconnect odu bridge
- *
- * Disconnect all pipes and deletes IPA RM dependencies on bridge mode
- *
- * Return codes: 0- success, error otherwise
- */
-int ipa3_odu_bridge_disconnect(void)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- if (!ipa3_odu_bridge_ctx) {
- ODU_BRIDGE_ERR("Not initialized\n");
- return -EFAULT;
- }
-
- if (!ipa3_odu_bridge_ctx->is_connected) {
- ODU_BRIDGE_ERR("Not connected\n");
- return -EFAULT;
- }
-
- mutex_lock(&ipa3_odu_bridge_ctx->lock);
- if (ipa3_odu_bridge_ctx->mode == ODU_BRIDGE_MODE_ROUTER) {
- res = ipa3_odu_bridge_disconnect_router();
- if (res) {
- ODU_BRIDGE_ERR("disconnect_router failed %d\n", res);
- goto out;
- }
- } else {
- res = ipa3_odu_bridge_disconnect_bridge();
- if (res) {
- ODU_BRIDGE_ERR("disconnect_bridge failed %d\n", res);
- goto out;
- }
- }
-
- ipa3_odu_bridge_ctx->is_connected = false;
- res = 0;
-out:
- mutex_unlock(&ipa3_odu_bridge_ctx->lock);
- ODU_BRIDGE_FUNC_EXIT();
- return res;
-}
-
-/**
- * ipa3_odu_bridge_connect() - Connect odu bridge.
- *
- * Call to the mode-specific connect function for connection IPA pipes
- * and adding IPA RM dependencies
-
- * Return codes: 0: success
- * -EINVAL: invalid parameters
- * -EPERM: Operation not permitted as the bridge is already
- * connected
- */
-int ipa3_odu_bridge_connect(void)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- if (!ipa3_odu_bridge_ctx) {
- ODU_BRIDGE_ERR("Not initialized\n");
- return -EFAULT;
- }
-
- if (ipa3_odu_bridge_ctx->is_connected) {
- ODU_BRIDGE_ERR("already connected\n");
- return -EFAULT;
- }
-
- mutex_lock(&ipa3_odu_bridge_ctx->lock);
- if (ipa3_odu_bridge_ctx->mode == ODU_BRIDGE_MODE_ROUTER) {
- res = ipa3_odu_bridge_connect_router();
- if (res) {
- ODU_BRIDGE_ERR("connect_router failed\n");
- goto bail;
- }
- } else {
- res = ipa3_odu_bridge_connect_bridge();
- if (res) {
- ODU_BRIDGE_ERR("connect_bridge failed\n");
- goto bail;
- }
- }
-
- ipa3_odu_bridge_ctx->is_connected = true;
- res = 0;
-bail:
- mutex_unlock(&ipa3_odu_bridge_ctx->lock);
- ODU_BRIDGE_FUNC_EXIT();
- return res;
-}
-
-/**
- * ipa3_odu_bridge_set_mode() - Set bridge mode to Router/Bridge
- * @mode: mode to be set
- */
-static int ipa3_odu_bridge_set_mode(enum odu_bridge_mode mode)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- if (mode < 0 || mode >= ODU_BRIDGE_MODE_MAX) {
- ODU_BRIDGE_ERR("Unsupported mode: %d\n", mode);
- return -EFAULT;
- }
-
- ODU_BRIDGE_DBG("setting mode: %d\n", mode);
- mutex_lock(&ipa3_odu_bridge_ctx->lock);
-
- if (ipa3_odu_bridge_ctx->mode == mode) {
- ODU_BRIDGE_DBG("same mode\n");
- res = 0;
- goto bail;
- }
-
- if (ipa3_odu_bridge_ctx->is_connected) {
- /* first disconnect the old configuration */
- if (ipa3_odu_bridge_ctx->mode == ODU_BRIDGE_MODE_ROUTER) {
- res = ipa3_odu_bridge_disconnect_router();
- if (res) {
- ODU_BRIDGE_ERR("disconnect_router failed\n");
- goto bail;
- }
- } else {
- res = ipa3_odu_bridge_disconnect_bridge();
- if (res) {
- ODU_BRIDGE_ERR("disconnect_bridge failed\n");
- goto bail;
- }
- }
-
- /* connect the new configuration */
- if (mode == ODU_BRIDGE_MODE_ROUTER) {
- res = ipa3_odu_bridge_connect_router();
- if (res) {
- ODU_BRIDGE_ERR("connect_router failed\n");
- goto bail;
- }
- } else {
- res = ipa3_odu_bridge_connect_bridge();
- if (res) {
- ODU_BRIDGE_ERR("connect_bridge failed\n");
- goto bail;
- }
- }
- }
- ipa3_odu_bridge_ctx->mode = mode;
- res = 0;
-bail:
- mutex_unlock(&ipa3_odu_bridge_ctx->lock);
- ODU_BRIDGE_FUNC_EXIT();
- return res;
-};
-
-/**
- * ipa3_odu_bridge_set_llv6_addr() - Set link local ipv6 address
- * @llv6_addr: odu network interface link local address
- *
- * This function sets the link local ipv6 address provided by IOCTL
- */
-static int ipa3_odu_bridge_set_llv6_addr(struct in6_addr *llv6_addr)
-{
- struct in6_addr llv6_addr_host;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- llv6_addr_host.s6_addr32[0] = ntohl(llv6_addr->s6_addr32[0]);
- llv6_addr_host.s6_addr32[1] = ntohl(llv6_addr->s6_addr32[1]);
- llv6_addr_host.s6_addr32[2] = ntohl(llv6_addr->s6_addr32[2]);
- llv6_addr_host.s6_addr32[3] = ntohl(llv6_addr->s6_addr32[3]);
-
- memcpy(&ipa3_odu_bridge_ctx->llv6_addr, &llv6_addr_host,
- sizeof(ipa3_odu_bridge_ctx->llv6_addr));
- ODU_BRIDGE_DBG("LLV6 addr: %pI6c\n", &ipa3_odu_bridge_ctx->llv6_addr);
-
- ODU_BRIDGE_FUNC_EXIT();
-
- return 0;
-};
-
-static long ipa3_odu_bridge_ioctl(struct file *filp,
- unsigned int cmd,
- unsigned long arg)
-{
- int res = 0;
- struct in6_addr llv6_addr;
-
- ODU_BRIDGE_DBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
-
- if ((_IOC_TYPE(cmd) != ODU_BRIDGE_IOC_MAGIC) ||
- (_IOC_NR(cmd) >= ODU_BRIDGE_IOCTL_MAX)) {
- ODU_BRIDGE_ERR("Invalid ioctl\n");
- return -ENOIOCTLCMD;
- }
-
- switch (cmd) {
- case ODU_BRIDGE_IOC_SET_MODE:
- ODU_BRIDGE_DBG("ODU_BRIDGE_IOC_SET_MODE ioctl called\n");
- res = ipa3_odu_bridge_set_mode(arg);
- if (res) {
- ODU_BRIDGE_ERR("Error, res = %d\n", res);
- break;
- }
- break;
-
- case ODU_BRIDGE_IOC_SET_LLV6_ADDR:
- ODU_BRIDGE_DBG("ODU_BRIDGE_IOC_SET_LLV6_ADDR ioctl called\n");
- res = copy_from_user(&llv6_addr,
- (struct in6_addr *)arg,
- sizeof(llv6_addr));
- if (res) {
- ODU_BRIDGE_ERR("Error, res = %d\n", res);
- res = -EFAULT;
- break;
- }
-
- res = ipa3_odu_bridge_set_llv6_addr(&llv6_addr);
- if (res) {
- ODU_BRIDGE_ERR("Error, res = %d\n", res);
- break;
- }
- break;
-
- default:
- ODU_BRIDGE_ERR("Unknown ioctl: %d\n", cmd);
- WARN_ON(1);
- }
-
- return res;
-}
-
-#ifdef CONFIG_COMPAT
-static long ipa3_compat_odu_bridge_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case ODU_BRIDGE_IOC_SET_LLV6_ADDR32:
- cmd = ODU_BRIDGE_IOC_SET_LLV6_ADDR;
- break;
- case ODU_BRIDGE_IOC_SET_MODE:
- break;
- default:
- return -ENOIOCTLCMD;
- }
- return ipa3_odu_bridge_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-}
-#endif
-
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *dent;
-static struct dentry *dfile_stats;
-static struct dentry *dfile_mode;
-
-static ssize_t ipa3_odu_debugfs_stats(struct file *file,
- char __user *ubuf,
- size_t count,
- loff_t *ppos)
-{
- int nbytes = 0;
-
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "UL packets: %lld\n",
- ipa3_odu_bridge_ctx->stats.num_ul_packets);
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "DL packets: %lld\n",
- ipa3_odu_bridge_ctx->stats.num_dl_packets);
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "LAN packets: %lld\n",
- ipa3_odu_bridge_ctx->stats.num_lan_packets);
- return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
-}
-
-static ssize_t ipa3_odu_debugfs_hw_bridge_mode_write(struct file *file,
- const char __user *ubuf,
- size_t count,
- loff_t *ppos)
-{
- unsigned long missing;
- enum odu_bridge_mode mode;
-
- if (sizeof(dbg_buff) < count + 1)
- return -EFAULT;
-
- missing = copy_from_user(dbg_buff, ubuf, count);
- if (missing)
- return -EFAULT;
-
- if (count > 0)
- dbg_buff[count-1] = '\0';
-
- if (strcmp(dbg_buff, "router") == 0) {
- mode = ODU_BRIDGE_MODE_ROUTER;
- } else if (strcmp(dbg_buff, "bridge") == 0) {
- mode = ODU_BRIDGE_MODE_BRIDGE;
- } else {
- ODU_BRIDGE_ERR("Bad mode, got %s,\n"
- "Use <router> or <bridge>.\n", dbg_buff);
- return count;
- }
-
- ipa3_odu_bridge_set_mode(mode);
- return count;
-}
-
-static ssize_t ipa3_odu_debugfs_hw_bridge_mode_read(struct file *file,
- char __user *ubuf,
- size_t count,
- loff_t *ppos)
-{
- int nbytes = 0;
-
- switch (ipa3_odu_bridge_ctx->mode) {
- case ODU_BRIDGE_MODE_ROUTER:
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "router\n");
- break;
- case ODU_BRIDGE_MODE_BRIDGE:
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "bridge\n");
- break;
- default:
- nbytes += scnprintf(&dbg_buff[nbytes],
- ODU_MAX_MSG_LEN - nbytes,
- "mode error\n");
- break;
-
- }
-
- return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
-}
-
-const struct file_operations ipa3_odu_stats_ops = {
- .read = ipa3_odu_debugfs_stats,
-};
-
-const struct file_operations ipa3_odu_hw_bridge_mode_ops = {
- .read = ipa3_odu_debugfs_hw_bridge_mode_read,
- .write = ipa3_odu_debugfs_hw_bridge_mode_write,
-};
-
-void ipa3_odu_debugfs_init(void)
-{
- const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
- const mode_t read_write_mode = S_IRUSR | S_IRGRP | S_IROTH |
- S_IWUSR | S_IWGRP | S_IWOTH;
-
- dent = debugfs_create_dir("odu_ipa_bridge", 0);
- if (IS_ERR(dent)) {
- ODU_BRIDGE_ERR("fail to create folder odu_ipa_bridge\n");
- return;
- }
-
- dfile_stats =
- debugfs_create_file("stats", read_only_mode, dent,
- 0, &ipa3_odu_stats_ops);
- if (!dfile_stats || IS_ERR(dfile_stats)) {
- ODU_BRIDGE_ERR("fail to create file stats\n");
- goto fail;
- }
-
- dfile_mode =
- debugfs_create_file("mode", read_write_mode,
- dent, 0, &ipa3_odu_hw_bridge_mode_ops);
- if (!dfile_mode ||
- IS_ERR(dfile_mode)) {
- ODU_BRIDGE_ERR("fail to create file dfile_mode\n");
- goto fail;
- }
-
- return;
-fail:
- debugfs_remove_recursive(dent);
-}
-
-static void ipa3_odu_debugfs_destroy(void)
-{
- debugfs_remove_recursive(dent);
-}
-
-#else
-static void ipa3_odu_debugfs_init(void) {}
-static void ipa3_odu_debugfs_destroy(void) {}
-#endif /* CONFIG_DEBUG_FS */
-
-
-static const struct file_operations ipa3_odu_bridge_drv_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = ipa3_odu_bridge_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = ipa3_compat_odu_bridge_ioctl,
-#endif
-};
-
-/**
- * ipa3_odu_bridge_tx_dp() - Send skb to ODU bridge
- * @skb: skb to send
- * @metadata: metadata on packet
- *
- * This function handles uplink packet.
- * In Router Mode:
- * packet is sent directly to IPA.
- * In Router Mode:
- * packet is classified if it should arrive to network stack.
- * QMI IP packet should arrive to APPS network stack
- * IPv6 Multicast packet should arrive to APPS network stack and Q6
- *
- * Return codes: 0- success, error otherwise
- */
-int ipa3_odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata)
-{
- struct sk_buff *skb_copied = NULL;
- struct ipv6hdr *ipv6hdr;
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- switch (ipa3_odu_bridge_ctx->mode) {
- case ODU_BRIDGE_MODE_ROUTER:
- /* Router mode - pass skb to IPA */
- res = ipa3_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
- if (res) {
- ODU_BRIDGE_DBG("tx dp failed %d\n", res);
- goto out;
- }
- ipa3_odu_bridge_ctx->stats.num_ul_packets++;
- goto out;
-
- case ODU_BRIDGE_MODE_BRIDGE:
- ipv6hdr = (struct ipv6hdr *)(skb->data + ETH_HLEN);
- if (ipv6hdr->version == 6 &&
- ODU_BRIDGE_IS_QMI_ADDR(ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("QMI packet\n");
- skb_copied = skb_clone(skb, GFP_KERNEL);
- if (!skb_copied) {
- ODU_BRIDGE_ERR("No memory\n");
- return -ENOMEM;
- }
- ipa3_odu_bridge_ctx->
- tx_dp_notify(ipa3_odu_bridge_ctx->priv,
- IPA_RECEIVE,
- (unsigned long)skb_copied);
- ipa3_odu_bridge_ctx->
- tx_dp_notify(ipa3_odu_bridge_ctx->priv,
- IPA_WRITE_DONE,
- (unsigned long)skb);
- ipa3_odu_bridge_ctx->stats.num_ul_packets++;
- ipa3_odu_bridge_ctx->stats.num_lan_packets++;
- res = 0;
- goto out;
- }
-
- if (ipv6hdr->version == 6 &&
- ipv6_addr_is_multicast(&ipv6hdr->daddr)) {
- ODU_BRIDGE_DBG("Multicast pkt, send to APPS and IPA\n");
- skb_copied = skb_clone(skb, GFP_KERNEL);
- if (!skb_copied) {
- ODU_BRIDGE_ERR("No memory\n");
- return -ENOMEM;
- }
-
- res = ipa3_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
- if (res) {
- ODU_BRIDGE_DBG("tx dp failed %d\n", res);
- dev_kfree_skb(skb_copied);
- goto out;
- }
-
- ipa3_odu_bridge_ctx->tx_dp_notify(
- ipa3_odu_bridge_ctx->priv,
- IPA_RECEIVE,
- (unsigned long)skb_copied);
- ipa3_odu_bridge_ctx->stats.num_ul_packets++;
- ipa3_odu_bridge_ctx->stats.num_lan_packets++;
- goto out;
- }
-
- res = ipa3_tx_dp(IPA_CLIENT_ODU_PROD, skb, metadata);
- if (res) {
- ODU_BRIDGE_DBG("tx dp failed %d\n", res);
- goto out;
- }
- ipa3_odu_bridge_ctx->stats.num_ul_packets++;
- goto out;
-
- default:
- ODU_BRIDGE_ERR("Unsupported mode: %d\n",
- ipa3_odu_bridge_ctx->mode);
- WARN_ON(1);
- res = -EFAULT;
-
- }
-out:
- ODU_BRIDGE_FUNC_EXIT();
- return res;
-}
-
-static int ipa3_odu_bridge_add_hdrs(void)
-{
- struct ipa_ioc_add_hdr *hdrs;
- struct ipa_hdr_add *ipv4_hdr;
- struct ipa_hdr_add *ipv6_hdr;
- struct ethhdr *eth_ipv4;
- struct ethhdr *eth_ipv6;
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
- hdrs = kzalloc(sizeof(*hdrs) + sizeof(*ipv4_hdr) + sizeof(*ipv6_hdr),
- GFP_KERNEL);
- if (!hdrs) {
- ODU_BRIDGE_ERR("no mem\n");
- res = -ENOMEM;
- goto out;
- }
- ipv4_hdr = &hdrs->hdr[0];
- eth_ipv4 = (struct ethhdr *)(ipv4_hdr->hdr);
- ipv6_hdr = &hdrs->hdr[1];
- eth_ipv6 = (struct ethhdr *)(ipv6_hdr->hdr);
- strlcpy(ipv4_hdr->name, ODU_BRIDGE_IPV4_HDR_NAME,
- IPA_RESOURCE_NAME_MAX);
- memcpy(eth_ipv4->h_source,
- ipa3_odu_bridge_ctx->device_ethaddr,
- ETH_ALEN);
- eth_ipv4->h_proto = htons(ETH_P_IP);
- ipv4_hdr->hdr_len = ETH_HLEN;
- ipv4_hdr->is_partial = 1;
- ipv4_hdr->is_eth2_ofst_valid = 1;
- ipv4_hdr->eth2_ofst = 0;
- strlcpy(ipv6_hdr->name, ODU_BRIDGE_IPV6_HDR_NAME,
- IPA_RESOURCE_NAME_MAX);
- memcpy(eth_ipv6->h_source,
- ipa3_odu_bridge_ctx->device_ethaddr,
- ETH_ALEN);
- eth_ipv6->h_proto = htons(ETH_P_IPV6);
- ipv6_hdr->hdr_len = ETH_HLEN;
- ipv6_hdr->is_partial = 1;
- ipv6_hdr->is_eth2_ofst_valid = 1;
- ipv6_hdr->eth2_ofst = 0;
- hdrs->commit = 1;
- hdrs->num_hdrs = 2;
- res = ipa3_add_hdr(hdrs);
- if (res) {
- ODU_BRIDGE_ERR("Fail on Header-Insertion(%d)\n", res);
- goto out_free_mem;
- }
- if (ipv4_hdr->status) {
- ODU_BRIDGE_ERR("Fail on Header-Insertion ipv4(%d)\n",
- ipv4_hdr->status);
- res = ipv4_hdr->status;
- goto out_free_mem;
- }
- if (ipv6_hdr->status) {
- ODU_BRIDGE_ERR("Fail on Header-Insertion ipv6(%d)\n",
- ipv6_hdr->status);
- res = ipv6_hdr->status;
- goto out_free_mem;
- }
- ipa3_odu_bridge_ctx->odu_br_ipv4_hdr_hdl = ipv4_hdr->hdr_hdl;
- ipa3_odu_bridge_ctx->odu_br_ipv6_hdr_hdl = ipv6_hdr->hdr_hdl;
-
- res = 0;
-out_free_mem:
- kfree(hdrs);
-out:
- ODU_BRIDGE_FUNC_EXIT();
- return res;
-}
-
-static void ipa3_odu_bridge_del_hdrs(void)
-{
- struct ipa_ioc_del_hdr *del_hdr;
- struct ipa_hdr_del *ipv4;
- struct ipa_hdr_del *ipv6;
- int result;
-
- del_hdr = kzalloc(sizeof(*del_hdr) + sizeof(*ipv4) +
- sizeof(*ipv6), GFP_KERNEL);
- if (!del_hdr)
- return;
- del_hdr->commit = 1;
- del_hdr->num_hdls = 2;
- ipv4 = &del_hdr->hdl[0];
- ipv4->hdl = ipa3_odu_bridge_ctx->odu_br_ipv4_hdr_hdl;
- ipv6 = &del_hdr->hdl[1];
- ipv6->hdl = ipa3_odu_bridge_ctx->odu_br_ipv6_hdr_hdl;
- result = ipa3_del_hdr(del_hdr);
- if (result || ipv4->status || ipv6->status)
- ODU_BRIDGE_ERR("ipa3_del_hdr failed");
- kfree(del_hdr);
-}
-
-/**
- * ipa3_odu_bridge_register_properties() - set Tx/Rx properties for ipacm
- *
- * Register the network interface interface with Tx and Rx properties
- * Tx properties are for data flowing from IPA to adapter, they
- * have Header-Insertion properties both for Ipv4 and Ipv6 Ethernet framing.
- * Rx properties are for data flowing from adapter to IPA, they have
- * simple rule which always "hit".
- *
- */
-static int ipa3_odu_bridge_register_properties(void)
-{
- struct ipa_tx_intf tx_properties = {0};
- struct ipa_ioc_tx_intf_prop properties[2] = { {0}, {0} };
- struct ipa_ioc_tx_intf_prop *ipv4_property;
- struct ipa_ioc_tx_intf_prop *ipv6_property;
- struct ipa_ioc_rx_intf_prop rx_ioc_properties[2] = { {0}, {0} };
- struct ipa_rx_intf rx_properties = {0};
- struct ipa_ioc_rx_intf_prop *rx_ipv4_property;
- struct ipa_ioc_rx_intf_prop *rx_ipv6_property;
- int res = 0;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- tx_properties.prop = properties;
- ipv4_property = &tx_properties.prop[0];
- ipv4_property->ip = IPA_IP_v4;
- ipv4_property->dst_pipe = IPA_CLIENT_ODU_EMB_CONS;
- ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- strlcpy(ipv4_property->hdr_name, ODU_BRIDGE_IPV4_HDR_NAME,
- IPA_RESOURCE_NAME_MAX);
- ipv6_property = &tx_properties.prop[1];
- ipv6_property->ip = IPA_IP_v6;
- ipv6_property->dst_pipe = IPA_CLIENT_ODU_EMB_CONS;
- ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- strlcpy(ipv6_property->hdr_name, ODU_BRIDGE_IPV6_HDR_NAME,
- IPA_RESOURCE_NAME_MAX);
- tx_properties.num_props = 2;
-
- rx_properties.prop = rx_ioc_properties;
- rx_ipv4_property = &rx_properties.prop[0];
- rx_ipv4_property->ip = IPA_IP_v4;
- rx_ipv4_property->attrib.attrib_mask = 0;
- rx_ipv4_property->src_pipe = IPA_CLIENT_ODU_PROD;
- rx_ipv4_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- rx_ipv6_property = &rx_properties.prop[1];
- rx_ipv6_property->ip = IPA_IP_v6;
- rx_ipv6_property->attrib.attrib_mask = 0;
- rx_ipv6_property->src_pipe = IPA_CLIENT_ODU_PROD;
- rx_ipv6_property->hdr_l2_type = IPA_HDR_L2_ETHERNET_II;
- rx_properties.num_props = 2;
-
- res = ipa3_register_intf(ipa3_odu_bridge_ctx->netdev_name,
- &tx_properties,
- &rx_properties);
- if (res) {
- ODU_BRIDGE_ERR("fail on Tx/Rx properties registration %d\n",
- res);
- }
-
- ODU_BRIDGE_FUNC_EXIT();
-
- return res;
-}
-
-static void ipa3_odu_bridge_deregister_properties(void)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
- res = ipa3_deregister_intf(ipa3_odu_bridge_ctx->netdev_name);
- if (res)
- ODU_BRIDGE_ERR("Fail on Tx prop deregister %d\n", res);
- ODU_BRIDGE_FUNC_EXIT();
-}
-
-/**
- * ipa3_odu_bridge_init() - Initialize the ODU bridge driver
- * @params: initialization parameters
- *
- * This function initialize all bridge internal data and register odu bridge to
- * kernel for IOCTL and debugfs.
- * Header addition and properties are registered to IPA driver.
- *
- * Return codes: 0: success,
- * -EINVAL - Bad parameter
- * Other negative value - Failure
- */
-int ipa3_odu_bridge_init(struct odu_bridge_params *params)
-{
- int res;
-
- ODU_BRIDGE_FUNC_ENTRY();
-
- if (!params) {
- ODU_BRIDGE_ERR("null pointer params\n");
- return -EINVAL;
- }
- if (!params->netdev_name) {
- ODU_BRIDGE_ERR("null pointer params->netdev_name\n");
- return -EINVAL;
- }
- if (!params->tx_dp_notify) {
- ODU_BRIDGE_ERR("null pointer params->tx_dp_notify\n");
- return -EINVAL;
- }
- if (!params->send_dl_skb) {
- ODU_BRIDGE_ERR("null pointer params->send_dl_skb\n");
- return -EINVAL;
- }
- if (ipa3_odu_bridge_ctx) {
- ODU_BRIDGE_ERR("Already initialized\n");
- return -EFAULT;
- }
- if (!ipa3_is_ready()) {
- ODU_BRIDGE_ERR("IPA is not ready\n");
- return -EFAULT;
- }
-
- ODU_BRIDGE_DBG("device_ethaddr=%pM\n", params->device_ethaddr);
-
- ipa3_odu_bridge_ctx = kzalloc(sizeof(*ipa3_odu_bridge_ctx), GFP_KERNEL);
- if (!ipa3_odu_bridge_ctx) {
- ODU_BRIDGE_ERR("kzalloc err.\n");
- return -ENOMEM;
- }
-
- ipa3_odu_bridge_ctx->class = class_create(THIS_MODULE,
- ODU_BRIDGE_DRV_NAME);
- if (!ipa3_odu_bridge_ctx->class) {
- ODU_BRIDGE_ERR("Class_create err.\n");
- res = -ENODEV;
- goto fail_class_create;
- }
-
- res = alloc_chrdev_region(&ipa3_odu_bridge_ctx->dev_num, 0, 1,
- ODU_BRIDGE_DRV_NAME);
- if (res) {
- ODU_BRIDGE_ERR("alloc_chrdev_region err.\n");
- res = -ENODEV;
- goto fail_alloc_chrdev_region;
- }
-
- ipa3_odu_bridge_ctx->dev = device_create(ipa3_odu_bridge_ctx->class,
- NULL,
- ipa3_odu_bridge_ctx->dev_num,
- ipa3_odu_bridge_ctx,
- ODU_BRIDGE_DRV_NAME);
- if (IS_ERR(ipa3_odu_bridge_ctx->dev)) {
- ODU_BRIDGE_ERR(":device_create err.\n");
- res = -ENODEV;
- goto fail_device_create;
- }
-
- cdev_init(&ipa3_odu_bridge_ctx->cdev, &ipa3_odu_bridge_drv_fops);
- ipa3_odu_bridge_ctx->cdev.owner = THIS_MODULE;
- ipa3_odu_bridge_ctx->cdev.ops = &ipa3_odu_bridge_drv_fops;
-
- res = cdev_add(&ipa3_odu_bridge_ctx->cdev,
- ipa3_odu_bridge_ctx->dev_num,
- 1);
- if (res) {
- ODU_BRIDGE_ERR(":cdev_add err=%d\n", -res);
- res = -ENODEV;
- goto fail_cdev_add;
- }
-
- ipa3_odu_debugfs_init();
-
- strlcpy(ipa3_odu_bridge_ctx->netdev_name, params->netdev_name,
- IPA_RESOURCE_NAME_MAX);
- ipa3_odu_bridge_ctx->priv = params->priv;
- ipa3_odu_bridge_ctx->tx_dp_notify = params->tx_dp_notify;
- ipa3_odu_bridge_ctx->send_dl_skb = params->send_dl_skb;
- memcpy(ipa3_odu_bridge_ctx->device_ethaddr, params->device_ethaddr,
- ETH_ALEN);
- ipa3_odu_bridge_ctx->ipa_sys_desc_size = params->ipa_desc_size;
- ipa3_odu_bridge_ctx->mode = ODU_BRIDGE_MODE_ROUTER;
-
- mutex_init(&ipa3_odu_bridge_ctx->lock);
-
- res = ipa3_odu_bridge_add_hdrs();
- if (res) {
- ODU_BRIDGE_ERR("fail on odu_bridge_add_hdr %d\n", res);
- goto fail_add_hdrs;
- }
-
- res = ipa3_odu_bridge_register_properties();
- if (res) {
- ODU_BRIDGE_ERR("fail on register properties %d\n", res);
- goto fail_register_properties;
- }
-
- ODU_BRIDGE_FUNC_EXIT();
- return 0;
-
-fail_register_properties:
- ipa3_odu_bridge_del_hdrs();
-fail_add_hdrs:
- ipa3_odu_debugfs_destroy();
-fail_cdev_add:
- device_destroy(ipa3_odu_bridge_ctx->class,
- ipa3_odu_bridge_ctx->dev_num);
-fail_device_create:
- unregister_chrdev_region(ipa3_odu_bridge_ctx->dev_num, 1);
-fail_alloc_chrdev_region:
- class_destroy(ipa3_odu_bridge_ctx->class);
-fail_class_create:
- kfree(ipa3_odu_bridge_ctx);
- ipa3_odu_bridge_ctx = NULL;
- return res;
-}
-
-/**
- * ipa3_odu_bridge_cleanup() - De-Initialize the ODU bridge driver
- *
- * Return codes: 0: success,
- * -EINVAL - Bad parameter
- * Other negative value - Failure
- */
-int ipa3_odu_bridge_cleanup(void)
-{
- ODU_BRIDGE_FUNC_ENTRY();
-
- if (!ipa3_odu_bridge_ctx) {
- ODU_BRIDGE_ERR("Not initialized\n");
- return -EFAULT;
- }
-
- if (ipa3_odu_bridge_ctx->is_connected) {
- ODU_BRIDGE_ERR("cannot deinit while bridge is conncetd\n");
- return -EFAULT;
- }
-
- ipa3_odu_bridge_deregister_properties();
- ipa3_odu_bridge_del_hdrs();
- ipa3_odu_debugfs_destroy();
- cdev_del(&ipa3_odu_bridge_ctx->cdev);
- device_destroy(ipa3_odu_bridge_ctx->class,
- ipa3_odu_bridge_ctx->dev_num);
- unregister_chrdev_region(ipa3_odu_bridge_ctx->dev_num, 1);
- class_destroy(ipa3_odu_bridge_ctx->class);
- kfree(ipa3_odu_bridge_ctx);
- ipa3_odu_bridge_ctx = NULL;
-
- ODU_BRIDGE_FUNC_EXIT();
- return 0;
-}
-
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ODU bridge driver");
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index ec2e15e9478a..35f461f4fcac 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -900,9 +900,8 @@ static void ops_uninit(void *handle)
ops_suspend(ctx);
}
-static int ops_notify_crash(void *handle)
+static int msm_11ad_notify_crash(struct msm11ad_ctx *ctx)
{
- struct msm11ad_ctx *ctx = (struct msm11ad_ctx *)handle;
int rc;
if (ctx->subsys) {
@@ -919,6 +918,23 @@ static int ops_notify_crash(void *handle)
return 0;
}
+static int ops_notify(void *handle, enum wil_platform_event evt)
+{
+ struct msm11ad_ctx *ctx = (struct msm11ad_ctx *)handle;
+ int rc = 0;
+
+ switch (evt) {
+ case WIL_PLATFORM_EVT_FW_CRASH:
+ rc = msm_11ad_notify_crash(ctx);
+ break;
+ default:
+ pr_debug("%s: Unhandled event %d\n", __func__, evt);
+ break;
+ }
+
+ return rc;
+}
+
void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
const struct wil_platform_rops *rops, void *wil_handle)
{
@@ -957,7 +973,7 @@ void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
ops->suspend = ops_suspend;
ops->resume = ops_resume;
ops->uninit = ops_uninit;
- ops->notify_crash = ops_notify_crash;
+ ops->notify = ops_notify;
return ctx;
}
diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c
index 087b6a8364f8..a4f51489f764 100644
--- a/drivers/regulator/cpr3-regulator.c
+++ b/drivers/regulator/cpr3-regulator.c
@@ -5839,8 +5839,7 @@ int cpr3_regulator_register(struct platform_device *pdev,
}
}
- if (ctrl->supports_hw_closed_loop && ctrl->ctrl_type !=
- CPR_CTRL_TYPE_CPRH) {
+ if (ctrl->supports_hw_closed_loop) {
rc = msm_spm_probe_done();
if (rc) {
if (rc != -EPROBE_DEFER)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e9bf44e6d79d..a14feed47dcb 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -210,6 +210,15 @@ config QCOM_SMEM
The driver provides an interface to items in a heap shared among all
processors in a Qualcomm platform.
+config MSM_SERVICE_LOCATOR
+ bool "Service Locator"
+ depends on MSM_QMI_INTERFACE
+ help
+ The Service Locator provides a library to retrieve location
+ information given a service identifier. Location here translates
+ to what process domain exports the service, and which subsystem
+ that process domain will execute in.
+
config MSM_HVC
bool "MSM Hypervisor Call Support"
help
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 66a97b1f0a11..13c63d6e59bf 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -82,3 +82,4 @@ obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_kryo.o
obj-$(CONFIG_MSM_KERNEL_PROTECT) += kernel_protect.o
obj-$(CONFIG_MSM_RTB) += msm_rtb-hotplug.o
obj-$(CONFIG_QCOM_REMOTEQDSS) += remoteqdss.o
+obj-$(CONFIG_MSM_SERVICE_LOCATOR) += service-locator.o
diff --git a/drivers/soc/qcom/glink_smd_xprt.c b/drivers/soc/qcom/glink_smd_xprt.c
index c4ac66f81af4..c3fb34773db0 100644
--- a/drivers/soc/qcom/glink_smd_xprt.c
+++ b/drivers/soc/qcom/glink_smd_xprt.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
@@ -113,6 +113,7 @@ struct edge_info {
* @name: The name of this channel.
* @lcid: The local channel id the core uses for this channel.
* @rcid: The true remote channel id for this channel.
+ * @ch_probe_lock: Lock to protect channel probe status.
* @wait_for_probe: This channel is waiting for a probe from SMD.
* @had_probed: This channel probed in the past and may skip probe.
* @edge: Handle to the edge_info this channel is associated with.
@@ -138,6 +139,7 @@ struct channel {
char name[GLINK_NAME_SIZE];
uint32_t lcid;
uint32_t rcid;
+ struct mutex ch_probe_lock;
bool wait_for_probe;
bool had_probed;
struct edge_info *edge;
@@ -321,6 +323,7 @@ static void process_ctl_event(struct work_struct *work)
}
strlcpy(ch->name, name, GLINK_NAME_SIZE);
ch->edge = einfo;
+ mutex_init(&ch->ch_probe_lock);
INIT_LIST_HEAD(&ch->intents);
INIT_LIST_HEAD(&ch->used_intents);
spin_lock_init(&ch->intents_lock);
@@ -879,10 +882,11 @@ static void smd_data_ch_close(struct channel *ch)
__func__, ch->lcid);
ch->is_closing = true;
- ch->wait_for_probe = false;
ch->tx_resume_needed = false;
flush_workqueue(ch->wq);
+ mutex_lock(&ch->ch_probe_lock);
+ ch->wait_for_probe = false;
if (ch->smd_ch) {
smd_close(ch->smd_ch);
ch->smd_ch = NULL;
@@ -893,6 +897,7 @@ static void smd_data_ch_close(struct channel *ch)
ch->lcid);
mutex_unlock(&ch->edge->rx_cmd_lock);
}
+ mutex_unlock(&ch->ch_probe_lock);
ch->local_legacy = false;
@@ -965,13 +970,17 @@ static int channel_probe(struct platform_device *pdev)
if (!found)
return -EPROBE_DEFER;
- if (!ch->wait_for_probe)
+ mutex_lock(&ch->ch_probe_lock);
+ if (!ch->wait_for_probe) {
+ mutex_unlock(&ch->ch_probe_lock);
return -EPROBE_DEFER;
+ }
ch->wait_for_probe = false;
ch->had_probed = true;
data_ch_probe_body(ch);
+ mutex_unlock(&ch->ch_probe_lock);
return 0;
}
@@ -1012,6 +1021,7 @@ static int add_platform_driver(struct channel *ch)
static bool first = true;
mutex_lock(&pdrv_list_mutex);
+ mutex_lock(&ch->ch_probe_lock);
ch->wait_for_probe = true;
list_for_each_entry(pdrv, &pdrv_list, node) {
if (!strcmp(ch->name, pdrv->pdrv.driver.name)) {
@@ -1021,10 +1031,13 @@ static int add_platform_driver(struct channel *ch)
}
if (!found) {
+ mutex_unlock(&ch->ch_probe_lock);
pdrv = kzalloc(sizeof(*pdrv), GFP_KERNEL);
if (!pdrv) {
ret = -ENOMEM;
+ mutex_lock(&ch->ch_probe_lock);
ch->wait_for_probe = false;
+ mutex_unlock(&ch->ch_probe_lock);
goto out;
}
pdrv->pdrv.driver.name = ch->name;
@@ -1035,12 +1048,14 @@ static int add_platform_driver(struct channel *ch)
if (ret) {
list_del(&pdrv->node);
kfree(pdrv);
+ mutex_lock(&ch->ch_probe_lock);
ch->wait_for_probe = false;
+ mutex_unlock(&ch->ch_probe_lock);
}
} else {
if (ch->had_probed)
data_ch_probe_body(ch);
-
+ mutex_unlock(&ch->ch_probe_lock);
/*
* channel_probe might have seen the device we want, but
* returned EPROBE_DEFER so we need to kick the deferred list
@@ -1170,6 +1185,7 @@ static int tx_cmd_ch_open(struct glink_transport_if *if_ptr, uint32_t lcid,
}
strlcpy(ch->name, name, GLINK_NAME_SIZE);
ch->edge = einfo;
+ mutex_init(&ch->ch_probe_lock);
INIT_LIST_HEAD(&ch->intents);
INIT_LIST_HEAD(&ch->used_intents);
spin_lock_init(&ch->intents_lock);
@@ -1445,14 +1461,16 @@ static int ssr(struct glink_transport_if *if_ptr)
spin_lock_irqsave(&einfo->channels_lock, flags);
list_for_each_entry(ch, &einfo->channels, node) {
- if (!ch->smd_ch)
- continue;
spin_unlock_irqrestore(&einfo->channels_lock, flags);
ch->is_closing = true;
- ch->wait_for_probe = false;
flush_workqueue(ch->wq);
- smd_close(ch->smd_ch);
- ch->smd_ch = NULL;
+ mutex_lock(&ch->ch_probe_lock);
+ ch->wait_for_probe = false;
+ if (ch->smd_ch) {
+ smd_close(ch->smd_ch);
+ ch->smd_ch = NULL;
+ }
+ mutex_unlock(&ch->ch_probe_lock);
ch->local_legacy = false;
ch->remote_legacy = false;
ch->rcid = 0;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index e9f7b8931d9b..84b47f789214 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -86,9 +86,9 @@ 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;
+ phys_addr_t msa_pa;
uint32_t msa_mem_size;
- void *msa_addr;
+ void *msa_va;
uint32_t state;
struct wlfw_rf_chip_info_s_v01 chip_info;
struct wlfw_rf_board_info_s_v01 board_info;
@@ -99,6 +99,7 @@ static struct {
u32 rf_pin_result;
struct icnss_mem_region_info
icnss_mem_region[QMI_WLFW_MAX_NUM_MEMORY_REGIONS_V01];
+ bool skip_qmi;
} *penv;
static int icnss_qmi_event_post(enum icnss_qmi_event_type type, void *data)
@@ -192,7 +193,7 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
- req.msa_addr = penv->msa_phys;
+ req.msa_addr = penv->msa_pa;
req.size = penv->msa_mem_size;
req_desc.max_msg_len = WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN;
@@ -629,48 +630,39 @@ static int icnss_qmi_event_server_arrive(void *data)
if (ret < 0) {
pr_err("%s: Failed to send indication message: %d\n",
__func__, ret);
- goto out;
+ goto fail;
}
- 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;
- }
+ if (penv->msa_va) {
+ ret = wlfw_msa_mem_info_send_sync_msg();
+ if (ret < 0) {
+ pr_err("%s: Failed to send MSA info: %d\n",
+ __func__, ret);
+ goto fail;
+ }
+ ret = wlfw_msa_ready_send_sync_msg();
+ if (ret < 0) {
+ pr_err("%s: Failed to send MSA ready : %d\n",
+ __func__, ret);
+ goto fail;
}
+ } else {
+ pr_err("%s: Invalid MSA address\n", __func__);
+ ret = -EINVAL;
+ goto fail;
}
ret = wlfw_cap_send_sync_msg();
if (ret < 0) {
pr_err("%s: Failed to get capability: %d\n",
__func__, ret);
- goto out;
+ goto fail;
}
return ret;
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;
}
@@ -683,10 +675,7 @@ 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;
@@ -810,6 +799,9 @@ int icnss_register_driver(struct icnss_driver_ops *ops)
}
penv->ops = ops;
+ if (penv->skip_qmi)
+ penv->state |= ICNSS_FW_READY;
+
/* check for all conditions before invoking probe */
if (ICNSS_IS_FW_READY(penv->state) && penv->ops->probe) {
ret = penv->ops->probe(&pdev->dev);
@@ -1045,7 +1037,7 @@ int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config,
memset(&req, 0, sizeof(req));
- if (mode == ICNSS_WALTEST)
+ if (mode == ICNSS_WALTEST || mode == ICNSS_CCPM)
goto skip;
else if (!config || !host_version) {
pr_err("%s: Invalid cfg pointer\n", __func__);
@@ -1101,6 +1093,9 @@ skip:
if (ret)
pr_err("%s: Failed to send mode, ret = %d\n", __func__, ret);
out:
+ if (penv->skip_qmi)
+ ret = 0;
+
return ret;
}
EXPORT_SYMBOL(icnss_wlan_enable);
@@ -1124,13 +1119,44 @@ int icnss_get_ce_id(int irq)
}
EXPORT_SYMBOL(icnss_get_ce_id);
+static ssize_t icnss_wlan_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int val;
+ int ret;
+
+ if (!penv)
+ return -ENODEV;
+
+ ret = kstrtoint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val == ICNSS_WALTEST || val == ICNSS_CCPM) {
+ pr_debug("%s: WLAN Test Mode -> %d\n", __func__, val);
+ ret = icnss_wlan_enable(NULL, val, NULL);
+ if (ret)
+ pr_err("%s: WLAN Test Mode %d failed with %d\n",
+ __func__, val, ret);
+ } else {
+ pr_err("%s: Mode %d is not supported from command line\n",
+ __func__, val);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static DEVICE_ATTR(icnss_wlan_mode, S_IWUSR, NULL, icnss_wlan_mode_store);
+
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;
@@ -1167,19 +1193,43 @@ 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;
+ &penv->msa_mem_size) == 0) {
+ if (penv->msa_mem_size) {
+ penv->msa_va = dma_alloc_coherent(&pdev->dev,
+ penv->msa_mem_size,
+ &penv->msa_pa,
+ GFP_KERNEL);
+ if (!penv->msa_va) {
+ pr_err("%s: DMA alloc failed\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ pr_debug("%s: MAS va: %p, MSA pa: %pa\n",
+ __func__, penv->msa_va, &penv->msa_pa);
+ }
} else {
- pr_err("icnss: Fail to get MSA Memory Size\n");
+ pr_err("%s: Fail to get MSA Memory Size\n", __func__);
ret = -ENODEV;
goto out;
}
+ penv->skip_qmi = of_property_read_bool(dev->of_node,
+ "qcom,skip-qmi");
+
+ ret = device_create_file(dev, &dev_attr_icnss_wlan_mode);
+ if (ret) {
+ pr_err("%s: wlan_mode sys file creation failed\n",
+ __func__);
+ goto err_wlan_mode;
+ }
+
+ spin_lock_init(&penv->qmi_event_lock);
+
penv->qmi_event_wq = alloc_workqueue("icnss_qmi_event", 0, 0);
if (!penv->qmi_event_wq) {
pr_err("%s: workqueue creation failed\n", __func__);
ret = -EFAULT;
- goto out;
+ goto err_workqueue;
}
INIT_WORK(&penv->qmi_event_work, icnss_qmi_wlfw_event_work);
@@ -1192,11 +1242,22 @@ static int icnss_probe(struct platform_device *pdev)
&wlfw_clnt_nb);
if (ret < 0) {
pr_err("%s: notifier register failed\n", __func__);
- destroy_workqueue(penv->qmi_event_wq);
- goto out;
+ goto err_qmi;
}
pr_debug("icnss: Platform driver probed successfully\n");
+
+ return ret;
+
+err_qmi:
+ if (penv->qmi_event_wq)
+ destroy_workqueue(penv->qmi_event_wq);
+err_workqueue:
+ device_remove_file(&pdev->dev, &dev_attr_icnss_wlan_mode);
+err_wlan_mode:
+ if (penv->msa_va)
+ dma_free_coherent(&pdev->dev, penv->msa_mem_size,
+ penv->msa_va, penv->msa_pa);
out:
return ret;
}
@@ -1209,6 +1270,10 @@ static int icnss_remove(struct platform_device *pdev)
&wlfw_clnt_nb);
if (penv->qmi_event_wq)
destroy_workqueue(penv->qmi_event_wq);
+ device_remove_file(&pdev->dev, &dev_attr_icnss_wlan_mode);
+ if (penv->msa_va)
+ dma_free_coherent(&pdev->dev, penv->msa_mem_size,
+ penv->msa_va, penv->msa_pa);
return 0;
}
diff --git a/drivers/soc/qcom/ipc_router_mhi_xprt.c b/drivers/soc/qcom/ipc_router_mhi_xprt.c
index faf01c8aa013..9a0624804c21 100644
--- a/drivers/soc/qcom/ipc_router_mhi_xprt.c
+++ b/drivers/soc/qcom/ipc_router_mhi_xprt.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
@@ -39,18 +39,15 @@ if (ipc_router_mhi_xprt_debug_mask) \
#define IPC_ROUTER_MHI_XPRT_NUM_TRBS 10
/**
- * ipc_router_mhi_addr_map - DMA to virtual address mapping for an IPC Router
- * packet.
+ * ipc_router_mhi_addr_map - Struct for virtual address to IPC Router
+ * packet mapping.
* @list_node: Address mapping list node used by mhi transport map list.
* @virt_addr: The virtual address in mapping.
- * @dma_addr: The dma address in mapping.
- * @pkt: The IPC Router packet for which the virtual address of skbs are mapped
- * to DMA address during TX/RX operations.
+ * @pkt: The IPC Router packet for the virtual address
*/
struct ipc_router_mhi_addr_map {
struct list_head list_node;
void *virt_addr;
- dma_addr_t dma_addr;
struct rr_packet *pkt;
};
@@ -109,10 +106,10 @@ struct ipc_router_mhi_channel {
* @xprt_option: XPRT specific options to be handled by IPC Router.
* @tx_addr_map_list_lock: The lock to protect the address mapping list for TX
* operations.
- * @tx_addr_map_list: DMA to virtual address mapping list for TX operations.
+ * @tx_addr_map_list: Virtual address mapping list for TX operations.
* @rx_addr_map_list_lock: The lock to protect the address mapping list for RX
* operations.
- * @rx_addr_map_list: DMA to virtual address mapping list for RX operations.
+ * @rx_addr_map_list: Virtual address mapping list for RX operations.
*/
struct ipc_router_mhi_xprt {
struct list_head list;
@@ -177,13 +174,13 @@ void ipc_router_mhi_release_pkt(struct kref *ref)
* ipc_router_mhi_xprt_find_addr_map() - Search the mapped virtual address
* @addr_map_list: The list of address mappings.
* @addr_map_list_lock: Reference to the lock that protects the @addr_map_list.
- * @addr: The dma address for which mapped virtual address need to be found.
+ * @addr: The virtual address that needs to be found.
*
* Return: The mapped virtual Address if found, NULL otherwise.
*/
void *ipc_router_mhi_xprt_find_addr_map(struct list_head *addr_map_list,
struct mutex *addr_map_list_lock,
- dma_addr_t addr)
+ void *addr)
{
struct ipc_router_mhi_addr_map *addr_mapping;
struct ipc_router_mhi_addr_map *tmp_addr_mapping;
@@ -194,7 +191,7 @@ void *ipc_router_mhi_xprt_find_addr_map(struct list_head *addr_map_list,
mutex_lock(addr_map_list_lock);
list_for_each_entry_safe(addr_mapping, tmp_addr_mapping,
addr_map_list, list_node) {
- if (addr_mapping->dma_addr == addr) {
+ if (addr_mapping->virt_addr == addr) {
virt_addr = addr_mapping->virt_addr;
list_del(&addr_mapping->list_node);
if (addr_mapping->pkt)
@@ -207,26 +204,23 @@ void *ipc_router_mhi_xprt_find_addr_map(struct list_head *addr_map_list,
}
mutex_unlock(addr_map_list_lock);
IPC_RTR_ERR(
- "%s: Virtual address mapping for DMA addr [%p] not found\n",
+ "%s: Virtual address mapping [%p] not found\n",
__func__, (void *)addr);
return NULL;
}
/*
- * ipc_router_mhi_xprt_add_addr_map() - Add a mapping of virtual address to dma
- * address
+ * ipc_router_mhi_xprt_add_addr_map() - Add a virtual address mapping structure
* @addr_map_list: The list of address mappings.
* @addr_map_list_lock: Reference to the lock that protects the @addr_map_list.
* @pkt: The IPC Router packet that contains the virtual address in skbs.
- * @addr: The virtual address which needs to be added.
- * @dma_addr: The dma address which needs to be added.
+ * @virt_addr: The virtual address which needs to be added.
*
* Return: 0 on success, standard Linux error code otherwise.
*/
int ipc_router_mhi_xprt_add_addr_map(struct list_head *addr_map_list,
struct mutex *addr_map_list_lock,
- struct rr_packet *pkt, void *virt_addr,
- dma_addr_t dma_addr)
+ struct rr_packet *pkt, void *virt_addr)
{
struct ipc_router_mhi_addr_map *addr_mapping;
@@ -236,7 +230,6 @@ int ipc_router_mhi_xprt_add_addr_map(struct list_head *addr_map_list,
if (!addr_mapping)
return -ENOMEM;
addr_mapping->virt_addr = virt_addr;
- addr_mapping->dma_addr = dma_addr;
addr_mapping->pkt = pkt;
mutex_lock(addr_map_list_lock);
if (addr_mapping->pkt)
@@ -258,9 +251,8 @@ int mhi_xprt_queue_in_buffers(struct ipc_router_mhi_xprt *mhi_xprtp,
{
int i;
struct sk_buff *skb;
- dma_addr_t dma_addr;
uint32_t buf_size = mhi_xprtp->ch_hndl.max_packet_size;
- enum MHI_STATUS rc_val = MHI_STATUS_SUCCESS;
+ int rc_val = 0;
for (i = 0; i < num_trbs; i++) {
skb = alloc_skb(buf_size, GFP_KERNEL);
@@ -269,31 +261,21 @@ int mhi_xprt_queue_in_buffers(struct ipc_router_mhi_xprt *mhi_xprtp,
__func__, (i + 1));
break;
}
- dma_addr = dma_map_single(NULL, skb->data,
- buf_size, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(NULL, dma_addr)) {
- IPC_RTR_ERR("%s: Failed to map DMA for SKB # %d\n",
- __func__, (i + 1));
- kfree_skb(skb);
- break;
- }
if (ipc_router_mhi_xprt_add_addr_map(
&mhi_xprtp->rx_addr_map_list,
&mhi_xprtp->rx_addr_map_list_lock, NULL,
- skb->data, dma_addr) < 0) {
- IPC_RTR_ERR("%s: Could not map %d SKB->DMA address\n",
+ skb->data) < 0) {
+ IPC_RTR_ERR("%s: Could not map %d SKB address\n",
__func__, (i + 1));
break;
}
mutex_lock(&mhi_xprtp->ch_hndl.in_skbq_lock);
rc_val = mhi_queue_xfer(mhi_xprtp->ch_hndl.in_handle,
- dma_addr, buf_size, MHI_EOT);
- if (rc_val != MHI_STATUS_SUCCESS) {
+ skb->data, buf_size, MHI_EOT);
+ if (rc_val) {
mutex_unlock(&mhi_xprtp->ch_hndl.in_skbq_lock);
IPC_RTR_ERR("%s: Failed to queue TRB # %d into MHI\n",
__func__, (i + 1));
- dma_unmap_single(NULL, dma_addr,
- buf_size, DMA_TO_DEVICE);
kfree_skb(skb);
break;
}
@@ -388,7 +370,6 @@ static int ipc_router_mhi_write_skb(struct ipc_router_mhi_xprt *mhi_xprtp,
size_t sz_to_write = 0;
size_t offset = 0;
int rc;
- dma_addr_t dma_addr;
while (offset < skb->len) {
wait_event(mhi_xprtp->write_wait_q,
@@ -404,29 +385,20 @@ static int ipc_router_mhi_write_skb(struct ipc_router_mhi_xprt *mhi_xprtp,
sz_to_write = min((size_t)(skb->len - offset),
(size_t)IPC_ROUTER_MHI_XPRT_MAX_PKT_SIZE);
- dma_addr = dma_map_single(NULL, skb->data + offset,
- sz_to_write, DMA_TO_DEVICE);
- if (dma_mapping_error(NULL, dma_addr)) {
- mutex_unlock(&mhi_xprtp->ch_hndl.state_lock);
- IPC_RTR_ERR("%s: Failed to map DMA 0x%zx\n",
- __func__, sz_to_write);
- return -ENOMEM;
- }
if (ipc_router_mhi_xprt_add_addr_map(
&mhi_xprtp->tx_addr_map_list,
&mhi_xprtp->tx_addr_map_list_lock, pkt,
- skb->data + offset, dma_addr) < 0) {
- IPC_RTR_ERR("%s: Could not map SKB->DMA address\n",
+ skb->data + offset) < 0) {
+ IPC_RTR_ERR("%s: Could not map SKB address\n",
__func__);
break;
}
rc = mhi_queue_xfer(mhi_xprtp->ch_hndl.out_handle,
- dma_addr, sz_to_write, MHI_EOT | MHI_EOB);
- if (rc != 0) {
+ skb->data + offset, sz_to_write,
+ MHI_EOT | MHI_EOB);
+ if (rc) {
mutex_unlock(&mhi_xprtp->ch_hndl.state_lock);
- dma_unmap_single(NULL, dma_addr, sz_to_write,
- DMA_TO_DEVICE);
IPC_RTR_ERR("%s: Error queueing mhi_xfer 0x%zx\n",
__func__, sz_to_write);
return -EFAULT;
@@ -496,7 +468,7 @@ static int ipc_router_mhi_write(void *data,
*/
static void mhi_xprt_read_data(struct work_struct *work)
{
- dma_addr_t data_addr;
+ void *data_addr;
ssize_t data_sz;
void *skb_data;
struct sk_buff *skb;
@@ -520,15 +492,15 @@ static void mhi_xprt_read_data(struct work_struct *work)
while (1) {
rc = mhi_poll_inbound(mhi_xprtp->ch_hndl.in_handle, &result);
- if (rc || !result.payload_buf || !result.bytes_xferd) {
- if (rc != MHI_STATUS_RING_EMPTY)
+ if (rc || !result.buf_addr || !result.bytes_xferd) {
+ if (rc != -ENODATA)
IPC_RTR_ERR("%s: Poll failed %s:%d:%p:%u\n",
__func__, mhi_xprtp->xprt_name, rc,
- (void *)result.payload_buf,
- result.bytes_xferd);
+ result.buf_addr,
+ (unsigned int) result.bytes_xferd);
break;
}
- data_addr = result.payload_buf;
+ data_addr = result.buf_addr;
data_sz = result.bytes_xferd;
/* Create a new rr_packet, if first fragment */
@@ -547,7 +519,6 @@ static void mhi_xprt_read_data(struct work_struct *work)
&mhi_xprtp->rx_addr_map_list_lock,
data_addr);
- dma_unmap_single(NULL, data_addr, data_sz, DMA_BIDIRECTIONAL);
if (!skb_data)
continue;
mutex_lock(&mhi_xprtp->ch_hndl.in_skbq_lock);
@@ -638,7 +609,7 @@ static void mhi_xprt_enable_event(struct work_struct *work)
if (xprt_work->chan_id == mhi_xprtp->ch_hndl.out_chan_id) {
rc = mhi_open_channel(mhi_xprtp->ch_hndl.out_handle);
- if (rc != MHI_STATUS_SUCCESS) {
+ if (rc) {
IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n",
__func__, mhi_xprtp->ch_hndl.out_chan_id, rc);
goto out_enable_event;
@@ -650,7 +621,7 @@ static void mhi_xprt_enable_event(struct work_struct *work)
mutex_unlock(&mhi_xprtp->ch_hndl.state_lock);
} else if (xprt_work->chan_id == mhi_xprtp->ch_hndl.in_chan_id) {
rc = mhi_open_channel(mhi_xprtp->ch_hndl.in_handle);
- if (rc != MHI_STATUS_SUCCESS) {
+ if (rc) {
IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n",
__func__, mhi_xprtp->ch_hndl.in_chan_id, rc);
goto out_enable_event;
@@ -743,17 +714,15 @@ static void mhi_xprt_disable_event(struct work_struct *work)
static void mhi_xprt_xfer_event(struct mhi_cb_info *cb_info)
{
struct ipc_router_mhi_xprt *mhi_xprtp;
- dma_addr_t out_dma_addr;
+ void *out_addr;
mhi_xprtp = (struct ipc_router_mhi_xprt *)(cb_info->result->user_data);
if (cb_info->chan == mhi_xprtp->ch_hndl.out_chan_id) {
- out_dma_addr = (dma_addr_t)cb_info->result->payload_buf;
- dma_unmap_single(NULL, out_dma_addr,
- cb_info->result->bytes_xferd, DMA_TO_DEVICE);
+ out_addr = cb_info->result->buf_addr;
mutex_lock(&mhi_xprtp->ch_hndl.state_lock);
ipc_router_mhi_xprt_find_addr_map(&mhi_xprtp->tx_addr_map_list,
&mhi_xprtp->tx_addr_map_list_lock,
- out_dma_addr);
+ out_addr);
wake_up(&mhi_xprtp->write_wait_q);
mutex_unlock(&mhi_xprtp->ch_hndl.state_lock);
} else if (cb_info->chan == mhi_xprtp->ch_hndl.in_chan_id) {
@@ -821,13 +790,13 @@ static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info)
static int ipc_router_mhi_driver_register(
struct ipc_router_mhi_xprt *mhi_xprtp)
{
- enum MHI_STATUS rc_status;
+ int rc_status;
rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle,
mhi_xprtp->ch_hndl.out_chan_id, 0,
&mhi_xprtp->ch_hndl.out_clnt_info,
(void *)mhi_xprtp);
- if (rc_status != MHI_STATUS_SUCCESS) {
+ if (rc_status) {
IPC_RTR_ERR("%s: Error %d registering out_chan for %s\n",
__func__, rc_status, mhi_xprtp->xprt_name);
return -EFAULT;
@@ -837,7 +806,7 @@ static int ipc_router_mhi_driver_register(
mhi_xprtp->ch_hndl.in_chan_id, 0,
&mhi_xprtp->ch_hndl.in_clnt_info,
(void *)mhi_xprtp);
- if (rc_status != MHI_STATUS_SUCCESS) {
+ if (rc_status) {
mhi_deregister_channel(mhi_xprtp->ch_hndl.out_handle);
IPC_RTR_ERR("%s: Error %d registering in_chan for %s\n",
__func__, rc_status, mhi_xprtp->xprt_name);
diff --git a/drivers/soc/qcom/msm-spm.c b/drivers/soc/qcom/msm-spm.c
index 4a42d9a213f9..14ecea1636e1 100644
--- a/drivers/soc/qcom/msm-spm.c
+++ b/drivers/soc/qcom/msm-spm.c
@@ -94,6 +94,33 @@ static uint32_t msm_spm_reg_offsets_saw2_v3_0[MSM_SPM_REG_NR] = {
[MSM_SPM_REG_SAW_VERSION] = 0xFD0,
};
+static uint32_t msm_spm_reg_offsets_saw2_v4_1[MSM_SPM_REG_NR] = {
+ [MSM_SPM_REG_SAW_SECURE] = 0xC00,
+ [MSM_SPM_REG_SAW_ID] = 0xC04,
+ [MSM_SPM_REG_SAW_STS2] = 0xC10,
+ [MSM_SPM_REG_SAW_SPM_STS] = 0xC0C,
+ [MSM_SPM_REG_SAW_AVS_STS] = 0xC14,
+ [MSM_SPM_REG_SAW_PMIC_STS] = 0xC18,
+ [MSM_SPM_REG_SAW_RST] = 0xC1C,
+ [MSM_SPM_REG_SAW_VCTL] = 0x900,
+ [MSM_SPM_REG_SAW_AVS_CTL] = 0x904,
+ [MSM_SPM_REG_SAW_AVS_LIMIT] = 0x908,
+ [MSM_SPM_REG_SAW_AVS_DLY] = 0x90C,
+ [MSM_SPM_REG_SAW_SPM_CTL] = 0x0,
+ [MSM_SPM_REG_SAW_SPM_DLY] = 0x4,
+ [MSM_SPM_REG_SAW_CFG] = 0x0C,
+ [MSM_SPM_REG_SAW_PMIC_DATA_0] = 0x40,
+ [MSM_SPM_REG_SAW_PMIC_DATA_1] = 0x44,
+ [MSM_SPM_REG_SAW_PMIC_DATA_2] = 0x48,
+ [MSM_SPM_REG_SAW_PMIC_DATA_3] = 0x4C,
+ [MSM_SPM_REG_SAW_PMIC_DATA_4] = 0x50,
+ [MSM_SPM_REG_SAW_PMIC_DATA_5] = 0x54,
+ [MSM_SPM_REG_SAW_PMIC_DATA_6] = 0x58,
+ [MSM_SPM_REG_SAW_PMIC_DATA_7] = 0x5C,
+ [MSM_SPM_REG_SAW_SEQ_ENTRY] = 0x400,
+ [MSM_SPM_REG_SAW_VERSION] = 0xFD0,
+};
+
static struct saw2_data saw2_info[] = {
[0] = {
"SAW_v2.1",
@@ -113,6 +140,12 @@ static struct saw2_data saw2_info[] = {
0x0,
msm_spm_reg_offsets_saw2_v3_0,
},
+ [3] = {
+ "SAW_v4.0",
+ 0x4,
+ 0x1,
+ msm_spm_reg_offsets_saw2_v4_1,
+ },
};
static uint32_t num_pmic_data;
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index 95b67fcaafd2..7589ea3b747e 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.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
@@ -984,6 +984,7 @@ int glink_pkt_release(struct inode *inode, struct file *file)
{
int ret = 0;
struct glink_pkt_dev *devp = file->private_data;
+ unsigned long flags;
GLINK_PKT_INFO("%s() on dev id:%d by [%s] ref_cnt[%d]\n",
__func__, devp->i, current->comm, devp->ref_cnt);
@@ -1011,7 +1012,12 @@ int glink_pkt_release(struct inode *inode, struct file *file)
mutex_lock(&devp->ch_lock);
}
devp->poll_mode = 0;
- devp->ws_locked = 0;
+ spin_lock_irqsave(&devp->pa_spinlock, flags);
+ if (devp->ws_locked) {
+ __pm_relax(&devp->pa_ws);
+ devp->ws_locked = 0;
+ }
+ spin_unlock_irqrestore(&devp->pa_spinlock, flags);
devp->sigs_updated = false;
devp->in_reset = 0;
}
@@ -1050,6 +1056,7 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i)
devp->open_cfg.notify_state = glink_pkt_notify_state;
devp->open_cfg.notify_rx_intent_req = glink_pkt_rmt_rx_intent_req_cb;
devp->open_cfg.notify_rx_sigs = glink_pkt_notify_rx_sigs;
+ devp->open_cfg.options |= GLINK_OPT_INITIAL_XPORT;
devp->open_cfg.priv = devp;
devp->i = i;
diff --git a/drivers/soc/qcom/service-locator-private.h b/drivers/soc/qcom/service-locator-private.h
new file mode 100644
index 000000000000..df42080e362b
--- /dev/null
+++ b/drivers/soc/qcom/service-locator-private.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef SERVICE_LOCATOR_V01_H
+#define SERVICE_LOCATOR_V01_H
+
+#include <linux/qmi_encdec.h>
+
+#include <soc/qcom/msm_qmi_interface.h>
+#include <soc/qcom/service-locator.h>
+
+#define SERVREG_LOC_SERVICE_ID_V01 0x40
+#define SERVREG_LOC_SERVICE_VERS_V01 0x01
+
+#define QMI_SERVREG_LOC_INDICATION_REGISTER_RESP_V01 0x0020
+#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_REQ_V01 0x0022
+#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_V01 0x0021
+#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_V01 0x0021
+#define QMI_SERVREG_LOC_DATABASE_UPDATED_IND_V01 0x0023
+#define QMI_SERVREG_LOC_INDICATION_REGISTER_REQ_V01 0x0020
+#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_RESP_V01 0x0022
+
+#define QMI_SERVREG_LOC_NAME_LENGTH_V01 64
+#define QMI_SERVREG_LOC_LIST_LENGTH_V01 32
+
+enum qmi_servreg_loc_service_instance_enum_type_v01 {
+ QMI_SERVREG_LOC_SERVICE_INSTANCE_ENUM_TYPE_MIN_VAL_V01 = INT_MIN,
+ QMI_SERVREG_LOC_SERVICE_INSTANCE_APSS_V01 = 0x1,
+ QMI_SERVREG_LOC_SERVICE_INSTANCE_ENUM_TYPE_MAX_VAL_V01 = INT_MAX,
+};
+
+struct qmi_servreg_loc_indication_register_req_msg_v01 {
+ uint8_t enable_database_updated_indication_valid;
+ uint8_t enable_database_updated_indication;
+};
+#define QMI_SERVREG_LOC_INDICATION_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 4
+struct elem_info qmi_servreg_loc_indication_register_req_msg_v01_ei[];
+
+struct qmi_servreg_loc_indication_register_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define QMI_SERVREG_LOC_INDICATION_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 7
+struct elem_info qmi_servreg_loc_indication_register_resp_msg_v01_ei[];
+
+struct qmi_servreg_loc_get_domain_list_req_msg_v01 {
+ char service_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
+ uint8_t domain_offset_valid;
+ uint32_t domain_offset;
+};
+#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN 74
+struct elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[];
+
+struct qmi_servreg_loc_get_domain_list_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+ uint8_t total_domains_valid;
+ uint16_t total_domains;
+ uint8_t db_rev_count_valid;
+ uint16_t db_rev_count;
+ uint8_t domain_list_valid;
+ uint32_t domain_list_len;
+ struct servreg_loc_entry_v01
+ domain_list[QMI_SERVREG_LOC_LIST_LENGTH_V01];
+};
+#define QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_MSG_V01_MAX_MSG_LEN 2389
+struct elem_info qmi_servreg_loc_get_domain_list_resp_msg_v01_ei[];
+
+struct qmi_servreg_loc_register_service_list_req_msg_v01 {
+ char domain_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
+ uint32_t service_list_len;
+ struct servreg_loc_entry_v01
+ service_list[QMI_SERVREG_LOC_LIST_LENGTH_V01];
+};
+#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_REQ_MSG_V01_MAX_MSG_LEN 2439
+struct elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[];
+
+struct qmi_servreg_loc_register_service_list_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+#define QMI_SERVREG_LOC_REGISTER_SERVICE_LIST_RESP_MSG_V01_MAX_MSG_LEN 7
+struct elem_info qmi_servreg_loc_register_service_list_resp_msg_v01_ei[];
+
+struct qmi_servreg_loc_database_updated_ind_msg_v01 {
+ char placeholder;
+};
+#define QMI_SERVREG_LOC_DATABASE_UPDATED_IND_MSG_V01_MAX_MSG_LEN 0
+struct elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[];
+
+#define QMI_EOTI_DATA_TYPE \
+{ \
+ .data_type = QMI_EOTI, \
+ .elem_len = 0, \
+ .elem_size = 0, \
+ .is_array = NO_ARRAY, \
+ .tlv_type = 0x00, \
+ .offset = 0, \
+ .ei_array = NULL, \
+},
+
+static struct elem_info servreg_loc_entry_v01_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_loc_entry_v01,
+ name),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_loc_entry_v01,
+ instance_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_loc_entry_v01,
+ service_data_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_loc_entry_v01,
+ service_data),
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_indication_register_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
+ qmi_servreg_loc_indication_register_req_msg_v01,
+ enable_database_updated_indication_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
+ qmi_servreg_loc_indication_register_req_msg_v01,
+ enable_database_updated_indication),
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_indication_register_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
+ qmi_servreg_loc_indication_register_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_get_domain_list_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_req_msg_v01,
+ service_name),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_req_msg_v01,
+ domain_offset_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
+ qmi_servreg_loc_get_domain_list_req_msg_v01,
+ domain_offset),
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_get_domain_list_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
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_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
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ total_domains_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ total_domains),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ db_rev_count_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint16_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ db_rev_count),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ domain_list_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ domain_list_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_SERVREG_LOC_LIST_LENGTH_V01,
+ .elem_size = sizeof(struct servreg_loc_entry_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_servreg_loc_get_domain_list_resp_msg_v01,
+ domain_list),
+ .ei_array = servreg_loc_entry_v01_ei,
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_register_service_list_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1,
+ .elem_size = sizeof(char),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct
+ qmi_servreg_loc_register_service_list_req_msg_v01,
+ domain_name),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct
+ qmi_servreg_loc_register_service_list_req_msg_v01,
+ service_list_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_SERVREG_LOC_LIST_LENGTH_V01,
+ .elem_size = sizeof(struct servreg_loc_entry_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct
+ qmi_servreg_loc_register_service_list_req_msg_v01,
+ service_list),
+ .ei_array = servreg_loc_entry_v01_ei,
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_register_service_list_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
+ qmi_servreg_loc_register_service_list_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ QMI_EOTI_DATA_TYPE
+};
+
+struct elem_info qmi_servreg_loc_database_updated_ind_msg_v01_ei[] = {
+ QMI_EOTI_DATA_TYPE
+};
+
+#endif
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
new file mode 100644
index 000000000000..49fce3602cd4
--- /dev/null
+++ b/drivers/soc/qcom/service-locator.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "servloc: %s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/debugfs.h>
+
+#include <soc/qcom/msm_qmi_interface.h>
+#include <soc/qcom/service-locator.h>
+#include "service-locator-private.h"
+
+#define SERVREG_LOC_SERVICE_INSTANCE_ID 1
+
+#define QMI_RESP_BIT_SHIFT(x) (x << 16)
+#define QMI_SERVREG_LOC_SERVER_INITIAL_TIMEOUT 2000
+#define QMI_SERVREG_LOC_SERVER_TIMEOUT 2000
+#define INITIAL_TIMEOUT 100000
+
+#define LOCATOR_NOT_PRESENT 0
+#define LOCATOR_PRESENT 1
+#define LOCATOR_UNKNOWN -1
+
+static u32 locator_status = LOCATOR_UNKNOWN;
+static bool service_inited;
+
+DECLARE_COMPLETION(locator_status_known);
+
+static void service_locator_svc_arrive(struct work_struct *work);
+static void service_locator_svc_exit(struct work_struct *work);
+static void service_locator_recv_msg(struct work_struct *work);
+
+struct workqueue_struct *servloc_wq;
+
+struct pd_qmi_data {
+ struct work_struct svc_arrive;
+ struct work_struct svc_exit;
+ struct work_struct svc_rcv_msg;
+ struct notifier_block notifier;
+ struct completion service_available;
+ struct mutex service_mutex;
+ struct qmi_handle *clnt_handle;
+};
+
+DEFINE_MUTEX(service_init_mutex);
+struct pd_qmi_data service_locator;
+
+/* Please refer soc/qcom/service-locator.h for use about APIs defined here */
+
+static ssize_t show_service_locator_status(struct class *cl,
+ struct class_attribute *attr,
+ char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%x\n", locator_status);
+}
+
+static ssize_t store_service_locator_status(struct class *cl,
+ struct class_attribute *attr,
+ const char *buf, size_t size)
+{
+ u32 val;
+
+ if (kstrtos32(buf, 10, &val) < 0)
+ goto err;
+ if (val != LOCATOR_NOT_PRESENT && val != LOCATOR_PRESENT)
+ goto err;
+
+ mutex_lock(&service_init_mutex);
+ locator_status = val;
+ complete_all(&locator_status_known);
+ mutex_unlock(&service_init_mutex);
+ return size;
+err:
+ pr_err("Invalid input parameters\n");
+ return -EINVAL;
+}
+
+static struct class_attribute service_locator_class_attr[] = {
+ __ATTR(service_locator_status, S_IRUGO | S_IWUSR,
+ show_service_locator_status,
+ store_service_locator_status),
+ __ATTR_NULL,
+};
+
+static struct class service_locator_class = {
+ .name = "service_locator",
+ .owner = THIS_MODULE,
+ .class_attrs = service_locator_class_attr,
+};
+
+static int service_locator_svc_event_notify(struct notifier_block *this,
+ unsigned long code,
+ void *_cmd)
+{
+ switch (code) {
+ case QMI_SERVER_ARRIVE:
+ queue_work(servloc_wq, &service_locator.svc_arrive);
+ break;
+ case QMI_SERVER_EXIT:
+ queue_work(servloc_wq, &service_locator.svc_exit);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void service_locator_clnt_notify(struct qmi_handle *handle,
+ enum qmi_event_type event, void *notify_priv)
+{
+ switch (event) {
+ case QMI_RECV_MSG:
+ schedule_work(&service_locator.svc_rcv_msg);
+ break;
+ default:
+ break;
+ }
+}
+
+static void service_locator_svc_arrive(struct work_struct *work)
+{
+ int rc = 0;
+
+ /* Create a Local client port for QMI communication */
+ mutex_lock(&service_locator.service_mutex);
+ service_locator.clnt_handle =
+ qmi_handle_create(service_locator_clnt_notify, NULL);
+ if (!service_locator.clnt_handle) {
+ service_locator.clnt_handle = NULL;
+ mutex_unlock(&service_locator.service_mutex);
+ pr_err("Service locator QMI client handle alloc failed!\n");
+ return;
+ }
+
+ /* Connect to service */
+ rc = qmi_connect_to_service(service_locator.clnt_handle,
+ SERVREG_LOC_SERVICE_ID_V01, SERVREG_LOC_SERVICE_VERS_V01,
+ SERVREG_LOC_SERVICE_INSTANCE_ID);
+ if (rc) {
+ qmi_handle_destroy(service_locator.clnt_handle);
+ service_locator.clnt_handle = NULL;
+ mutex_unlock(&service_locator.service_mutex);
+ pr_err("Unable to connnect to service\n");
+ return;
+ }
+ if (!service_inited)
+ complete_all(&service_locator.service_available);
+ mutex_unlock(&service_locator.service_mutex);
+ pr_info("Connection established with the Service locator\n");
+}
+
+static void service_locator_svc_exit(struct work_struct *work)
+{
+ mutex_lock(&service_locator.service_mutex);
+ qmi_handle_destroy(service_locator.clnt_handle);
+ service_locator.clnt_handle = NULL;
+ mutex_unlock(&service_locator.service_mutex);
+ pr_info("Connection with service locator lost\n");
+}
+
+static void service_locator_recv_msg(struct work_struct *work)
+{
+ int ret;
+
+ do {
+ pr_debug("Notified about a Receive event\n");
+ } while ((ret = qmi_recv_msg(service_locator.clnt_handle)) == 0);
+
+ if (ret != -ENOMSG)
+ pr_err("Error receiving message\n");
+}
+
+static void store_get_domain_list_response(struct pd_qmi_client_data *pd,
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp,
+ int offset)
+{
+ int i;
+
+ for (i = offset; i < resp->domain_list_len; i++) {
+ pd->domain_list[i].instance_id =
+ resp->domain_list[i].instance_id;
+ strlcpy(pd->domain_list[i].name, resp->domain_list[i].name,
+ QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1);
+ pd->domain_list[i].service_data_valid =
+ resp->domain_list[i].service_data_valid;
+ pd->domain_list[i].service_data =
+ resp->domain_list[i].service_data;
+ }
+}
+
+static int servreg_loc_send_msg(struct msg_desc *req_desc,
+ struct msg_desc *resp_desc,
+ struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req,
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp,
+ struct pd_qmi_client_data *pd)
+{
+ int rc;
+
+ /*
+ * Send msg and get response. There is a chance that the service went
+ * away since the time we last checked for it to be available and
+ * actually made this call. In that case the call just fails.
+ */
+ rc = qmi_send_req_wait(service_locator.clnt_handle, req_desc, req,
+ sizeof(*req), resp_desc, resp, sizeof(*resp),
+ msecs_to_jiffies(QMI_SERVREG_LOC_SERVER_TIMEOUT));
+ if (rc < 0) {
+ pr_err("QMI send req failed for client %s, ret - %d\n",
+ pd->client_name, rc);
+ return rc;
+ }
+
+ /* Check the response */
+ if (QMI_RESP_BIT_SHIFT(resp->resp.result) != QMI_RESULT_SUCCESS_V01) {
+ pr_err("QMI request for client %s failed 0x%x\n",
+ pd->client_name, QMI_RESP_BIT_SHIFT(resp->resp.error));
+ return -EREMOTEIO;
+ }
+ return rc;
+}
+
+static int service_locator_send_msg(struct pd_qmi_client_data *pd)
+{
+ struct msg_desc req_desc, resp_desc;
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp;
+ struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req;
+ int rc;
+ int db_rev_count = 0, domains_read = 0;
+
+ if (!service_locator.clnt_handle) {
+ pr_err("Service locator not available!\n");
+ return -EAGAIN;
+ }
+
+ req = kmalloc(sizeof(
+ struct qmi_servreg_loc_get_domain_list_req_msg_v01),
+ GFP_KERNEL);
+ if (!req) {
+ pr_err("Unable to allocate memory for req message\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ resp = kmalloc(sizeof(
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01),
+ GFP_KERNEL);
+ if (!resp) {
+ pr_err("Unable to allocate memory for resp message\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ /* Prepare req and response message formats */
+ req_desc.msg_id = QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_V01;
+ req_desc.max_msg_len =
+ QMI_SERVREG_LOC_GET_DOMAIN_LIST_REQ_MSG_V01_MAX_MSG_LEN;
+ req_desc.ei_array = qmi_servreg_loc_get_domain_list_req_msg_v01_ei;
+
+ resp_desc.msg_id = QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_V01;
+ resp_desc.max_msg_len =
+ QMI_SERVREG_LOC_GET_DOMAIN_LIST_RESP_MSG_V01_MAX_MSG_LEN;
+ resp_desc.ei_array = qmi_servreg_loc_get_domain_list_resp_msg_v01_ei;
+
+ /* Prepare req and response message */
+ strlcpy(req->service_name, pd->service_name,
+ QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1);
+ req->domain_offset_valid = true;
+ req->domain_offset = 0;
+
+ pd->domain_list = NULL;
+ do {
+ req->domain_offset += domains_read;
+ rc = servreg_loc_send_msg(&req_desc, &resp_desc, req, resp,
+ pd);
+ if (rc < 0) {
+ pr_err("send msg failed! 0x%x\n", rc);
+ goto out;
+ }
+ if (!domains_read) {
+ db_rev_count = pd->db_rev_count = resp->db_rev_count;
+ pd->total_domains = resp->total_domains;
+ if (!pd->total_domains && resp->domain_list_len) {
+ pr_err("total domains not set\n");
+ pd->total_domains = resp->domain_list_len;
+ }
+ pd->domain_list = kmalloc(
+ sizeof(struct servreg_loc_entry_v01) *
+ resp->total_domains, GFP_KERNEL);
+ if (!pd->domain_list) {
+ pr_err("Cannot allocate domain list\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ }
+ if (db_rev_count != resp->db_rev_count) {
+ pr_err("Service Locator DB updated for client %s\n",
+ pd->client_name);
+ kfree(pd->domain_list);
+ rc = -EAGAIN;
+ goto out;
+ }
+ /* Copy the response*/
+ store_get_domain_list_response(pd, resp, domains_read);
+ domains_read += resp->domain_list_len;
+ } while (domains_read < resp->total_domains);
+ rc = 0;
+out:
+ kfree(req);
+ kfree(resp);
+ return rc;
+}
+
+static int init_service_locator(void)
+{
+ static bool service_inited;
+ int rc = 0;
+
+ mutex_lock(&service_init_mutex);
+ if (locator_status == LOCATOR_NOT_PRESENT) {
+ pr_err("Service Locator not present\n");
+ rc = -ENODEV;
+ goto inited;
+ }
+ if (service_inited)
+ goto inited;
+
+ if (locator_status != LOCATOR_PRESENT) {
+ mutex_unlock(&service_init_mutex);
+ rc = wait_for_completion_timeout(&locator_status_known,
+ msecs_to_jiffies(INITIAL_TIMEOUT));
+ if (!rc) {
+ locator_status = LOCATOR_NOT_PRESENT;
+ pr_err("Timed out waiting for Service Locator\n");
+ return -ENODEV;
+ }
+ mutex_lock(&service_init_mutex);
+ if (locator_status == LOCATOR_NOT_PRESENT) {
+ pr_err("Service Locator not present\n");
+ rc = -ENODEV;
+ goto inited;
+ }
+ }
+
+ service_locator.notifier.notifier_call =
+ service_locator_svc_event_notify;
+ init_completion(&service_locator.service_available);
+ mutex_init(&service_locator.service_mutex);
+
+ servloc_wq = create_singlethread_workqueue("servloc_wq");
+ if (!servloc_wq) {
+ rc = -ENOMEM;
+ pr_err("Could not create workqueue\n");
+ goto inited;
+ }
+
+ INIT_WORK(&service_locator.svc_arrive, service_locator_svc_arrive);
+ INIT_WORK(&service_locator.svc_exit, service_locator_svc_exit);
+ INIT_WORK(&service_locator.svc_rcv_msg, service_locator_recv_msg);
+
+ rc = qmi_svc_event_notifier_register(SERVREG_LOC_SERVICE_ID_V01,
+ SERVREG_LOC_SERVICE_VERS_V01, SERVREG_LOC_SERVICE_INSTANCE_ID,
+ &service_locator.notifier);
+ if (rc < 0) {
+ pr_err("Notifier register failed!\n");
+ goto inited;
+ }
+
+ rc = wait_for_completion_timeout(&service_locator.service_available,
+ msecs_to_jiffies(QMI_SERVREG_LOC_SERVER_INITIAL_TIMEOUT));
+ if (!rc) {
+ rc = -ENODEV;
+ mutex_unlock(&service_init_mutex);
+ pr_err("Process domain service locator response timeout!\n");
+ goto error;
+ }
+ service_inited = true;
+ mutex_unlock(&service_init_mutex);
+ pr_info("Service locator initialized\n");
+ return 0;
+error:
+ qmi_svc_event_notifier_unregister(SERVREG_LOC_SERVICE_ID_V01,
+ SERVREG_LOC_SERVICE_VERS_V01, SERVREG_LOC_SERVICE_INSTANCE_ID,
+ &service_locator.notifier);
+ destroy_workqueue(servloc_wq);
+inited:
+ mutex_unlock(&service_init_mutex);
+ return rc;
+}
+
+int get_service_location(struct pd_qmi_client_data *data)
+{
+ int rc = 0;
+
+ if (!data || !data->client_name || !data->service_name) {
+ rc = -EINVAL;
+ pr_err("Invalid input!\n");
+ goto err;
+ }
+ rc = init_service_locator();
+ if (rc) {
+ pr_err("Unable to connect to service locator!, rc = %d\n", rc);
+ goto err;
+ }
+ rc = service_locator_send_msg(data);
+ if (rc)
+ pr_err("Failed to get process domains for %s for client %s\n",
+ data->service_name, data->client_name);
+err:
+ return rc;
+}
+EXPORT_SYMBOL(get_service_location);
+
+int find_subsys(const char *pd_path, char *subsys)
+{
+ char *start, *end;
+
+ if (!subsys || !pd_path)
+ return -EINVAL;
+
+ start = strnstr(pd_path, "/", QMI_SERVREG_LOC_NAME_LENGTH_V01);
+ if (!start)
+ return -EINVAL;
+ start++;
+ end = strnstr(start, "/", QMI_SERVREG_LOC_NAME_LENGTH_V01);
+ if (!end || start == end)
+ return -EINVAL;
+
+ strlcpy(subsys, start, end - start + 1);
+ return 0;
+}
+EXPORT_SYMBOL(find_subsys);
+
+static struct pd_qmi_client_data test_data;
+
+static ssize_t show_servloc(struct seq_file *f, void *unused)
+{
+ int rc = 0, i = 0;
+ char subsys[QMI_SERVREG_LOC_NAME_LENGTH_V01];
+
+ rc = get_service_location(&test_data);
+ if (rc) {
+ seq_printf(f, "Failed to get process domain!, rc = %d\n", rc);
+ return -EIO;
+ }
+
+ seq_printf(f, "Service Name: %s\tTotal Domains: %d\n",
+ test_data.service_name, test_data.total_domains);
+ for (i = 0; i < test_data.total_domains; i++) {
+ seq_printf(f, "Instance ID: %d\t ",
+ test_data.domain_list[i].instance_id);
+ seq_printf(f, "Domain Name: %s\n",
+ test_data.domain_list[i].name);
+ rc = find_subsys(test_data.domain_list[i].name, subsys);
+ if (rc < 0)
+ seq_printf(f, "No valid subsys found for %s!\n",
+ test_data.domain_list[i].name);
+ else
+ seq_printf(f, "Subsys: %s\n", subsys);
+ }
+ return 0;
+}
+
+static ssize_t store_servloc(struct file *fp, const char __user *buf,
+ size_t count, loff_t *unused)
+{
+ if (!buf)
+ return -EIO;
+ snprintf(test_data.service_name, sizeof(test_data.service_name),
+ "%.*s", (int) min((size_t)count - 1,
+ (sizeof(test_data.service_name) - 1)), buf);
+ return count;
+}
+
+static int servloc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, (void *)show_servloc, inode->i_private);
+}
+
+static const struct file_operations servloc_fops = {
+ .open = servloc_open,
+ .read = seq_read,
+ .write = store_servloc,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct dentry *test_servloc_file;
+
+static int __init service_locator_init(void)
+{
+ class_register(&service_locator_class);
+ test_servloc_file = debugfs_create_file("test_servloc",
+ S_IRUGO | S_IWUSR, NULL, NULL,
+ &servloc_fops);
+ if (!test_servloc_file)
+ pr_err("Could not create test_servloc debugfs entry!");
+ return 0;
+}
+
+static void __exit service_locator_exit(void)
+{
+ class_unregister(&service_locator_class);
+ debugfs_remove(test_servloc_file);
+}
+
+module_init(service_locator_init);
+module_exit(service_locator_exit);
diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c
index 5a7c6dd17b09..0a9cfc3827df 100644
--- a/drivers/soc/qcom/subsys-pil-tz.c
+++ b/drivers/soc/qcom/subsys-pil-tz.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
@@ -40,14 +40,8 @@
#define STOP_ACK_TIMEOUT_MS 1000
#define CRASH_STOP_ACK_TO_MS 200
-#define COLD_BOOT_DONE 0
-#define GDSC_DONE 1
-#define RAM_WIPE_DONE 2
-#define CPU_BOOT_DONE 3
-#define WDOG_BITE 4
-#define CLR_WDOG_BITE 5
-#define ERR_READY 6
-#define PBL_DONE 7
+#define ERR_READY 1
+#define PBL_DONE 2
#define desc_to_data(d) container_of(d, struct pil_tz_data, desc)
#define subsys_to_data(d) container_of(d, struct pil_tz_data, subsys_desc)
@@ -89,7 +83,7 @@ struct reg_info {
* @desc: PIL descriptor
* @subsys: subsystem device pointer
* @subsys_desc: subsystem descriptor
- * @u32 bits_arr[8]: array of bit positions in SCSR registers
+ * @u32 bits_arr[2]: array of bit positions in SCSR registers
*/
struct pil_tz_data {
struct reg_info *regs;
@@ -114,7 +108,8 @@ struct pil_tz_data {
void __iomem *irq_clear;
void __iomem *irq_mask;
void __iomem *err_status;
- u32 bits_arr[8];
+ void __iomem *err_status_spare;
+ u32 bits_arr[2];
};
enum scm_cmd {
@@ -913,50 +908,63 @@ static irqreturn_t subsys_stop_ack_intr_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static irqreturn_t subsys_generic_handler(int irq, void *dev_id)
+static void check_pbl_done(struct pil_tz_data *d)
{
- struct pil_tz_data *d = subsys_to_data(dev_id);
- uint32_t status_val, clear_val, err_value;
+ uint32_t err_value;
- if (subsys_get_crash_status(d->subsys))
- return IRQ_HANDLED;
+ err_value = __raw_readl(d->err_status);
+ pr_debug("PBL_DONE received from %s!\n", d->subsys_desc.name);
+ if (!err_value)
+ __raw_writel(BIT(d->bits_arr[PBL_DONE]), d->irq_clear);
+ else
+ pr_err("PBL error status register: 0x%08x\n", err_value);
+}
- /* Masking interrupts not handled by HLOS */
- clear_val = __raw_readl(d->irq_mask);
- __raw_writel(clear_val | BIT(d->bits_arr[COLD_BOOT_DONE]) |
- BIT(d->bits_arr[GDSC_DONE]) | BIT(d->bits_arr[RAM_WIPE_DONE]) |
- BIT(d->bits_arr[CPU_BOOT_DONE]), d->irq_mask);
- status_val = __raw_readl(d->irq_status);
+static void check_err_ready(struct pil_tz_data *d)
+{
+ uint32_t err_value;
- if (status_val & BIT(d->bits_arr[WDOG_BITE])) {
+ err_value = __raw_readl(d->err_status_spare);
+ if (!err_value) {
+ pr_debug("Subsystem error services up received from %s!\n",
+ d->subsys_desc.name);
+ __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear);
+ complete_err_ready(d->subsys);
+ } else {
pr_err("wdog bite received from %s!\n", d->subsys_desc.name);
- clear_val = __raw_readl(d->irq_clear);
- __raw_writel(clear_val | BIT(d->bits_arr[CLR_WDOG_BITE]),
- d->irq_clear);
+ __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear);
subsys_set_crash_status(d->subsys, true);
log_failure_reason(d);
subsystem_restart_dev(d->subsys);
- } else if (status_val & BIT(d->bits_arr[ERR_READY])) {
- pr_debug("Subsystem error services up received from %s!\n",
- d->subsys_desc.name);
- clear_val = __raw_readl(d->irq_clear);
- __raw_writel(clear_val | BIT(d->bits_arr[ERR_READY]),
- d->irq_clear);
- complete_err_ready(d->subsys);
- } else if (status_val & BIT(d->bits_arr[PBL_DONE])) {
- err_value = __raw_readl(d->err_status);
- pr_debug("PBL_DONE received from %s!\n",
- d->subsys_desc.name);
- if (!err_value) {
- clear_val = __raw_readl(d->irq_clear);
- __raw_writel(clear_val | BIT(d->bits_arr[PBL_DONE]),
- d->irq_clear);
- } else
- pr_err("SP-PBL rmb error status: 0x%08x\n", err_value);
}
+}
+
+static irqreturn_t subsys_generic_handler(int irq, void *dev_id)
+{
+ struct pil_tz_data *d = subsys_to_data(dev_id);
+ uint32_t status_val;
+
+ if (subsys_get_crash_status(d->subsys))
+ return IRQ_HANDLED;
+
+ status_val = __raw_readl(d->irq_status);
+
+ if (status_val & BIT(d->bits_arr[ERR_READY]))
+ check_err_ready(d);
+ else if (status_val & BIT(d->bits_arr[PBL_DONE]))
+ check_pbl_done(d);
return IRQ_HANDLED;
}
+static void mask_scsr_irqs(struct pil_tz_data *d)
+{
+ uint32_t mask_val;
+ /* Masking all interrupts not handled by HLOS */
+ mask_val = ~0;
+ __raw_writel(mask_val & ~BIT(d->bits_arr[ERR_READY]) &
+ ~BIT(d->bits_arr[PBL_DONE]), d->irq_mask);
+}
+
static int pil_tz_driver_probe(struct platform_device *pdev)
{
struct pil_tz_data *d;
@@ -1046,11 +1054,16 @@ static int pil_tz_driver_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"rmb_err");
d->err_status = devm_ioremap_resource(&pdev->dev, res);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "rmb_err_spare2");
+ d->err_status_spare = devm_ioremap_resource(&pdev->dev, res);
rc = of_property_read_u32_array(pdev->dev.of_node,
"qcom,spss-scsr-bits", d->bits_arr, sizeof(d->bits_arr)/
sizeof(d->bits_arr[0]));
if (rc)
dev_err(&pdev->dev, "Failed to read qcom,spss-scsr-bits");
+ mask_scsr_irqs(d);
+
} else {
d->subsys_desc.err_fatal_handler =
subsys_err_fatal_intr_handler;
diff --git a/drivers/soc/qcom/wlan_firmware_service_v01.h b/drivers/soc/qcom/wlan_firmware_service_v01.h
index 6d007c297cf6..6e96cbabd9d8 100644
--- a/drivers/soc/qcom/wlan_firmware_service_v01.h
+++ b/drivers/soc/qcom/wlan_firmware_service_v01.h
@@ -60,6 +60,8 @@ enum wlfw_driver_mode_enum_v01 {
QMI_WLFW_EPPING_V01 = 2,
QMI_WLFW_WALTEST_V01 = 3,
QMI_WLFW_OFF_V01 = 4,
+ QMI_WLFW_CCPM_V01 = 5,
+ QMI_WLFW_QVIT_V01 = 6,
WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
};
diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c
index 296a6557a8a1..5c0225cd4e24 100644
--- a/drivers/staging/android/ion/ion_system_secure_heap.c
+++ b/drivers/staging/android/ion/ion_system_secure_heap.c
@@ -264,7 +264,7 @@ static void ion_system_secure_heap_unmap_dma(struct ion_heap *heap,
struct ion_system_secure_heap,
heap);
- secure_heap->sys_heap->ops->map_dma(secure_heap->sys_heap,
+ secure_heap->sys_heap->ops->unmap_dma(secure_heap->sys_heap,
buffer);
}
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 424343f9c549..b9be6d9a52ef 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -42,6 +42,8 @@
#include <linux/rcupdate.h>
#include <linux/profile.h>
#include <linux/notifier.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
#define CREATE_TRACE_POINTS
#include "trace/lowmemorykiller.h"
@@ -79,6 +81,24 @@ static unsigned long lowmem_count(struct shrinker *s,
global_page_state(NR_INACTIVE_FILE);
}
+static int test_task_flag(struct task_struct *p, int flag)
+{
+ struct task_struct *t = p;
+
+ do {
+ task_lock(t);
+ if (test_tsk_thread_flag(t, flag)) {
+ task_unlock(t);
+ return 1;
+ }
+ task_unlock(t);
+ } while_each_thread(p, t);
+
+ return 0;
+}
+
+static DEFINE_MUTEX(scan_mutex);
+
static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -91,8 +111,14 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
int selected_tasksize = 0;
short selected_oom_score_adj;
int array_size = ARRAY_SIZE(lowmem_adj);
- int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;
- int other_file = global_page_state(NR_FILE_PAGES) -
+ int other_free;
+ int other_file;
+
+ if (mutex_lock_interruptible(&scan_mutex) < 0)
+ return 0;
+
+ other_free = global_page_state(NR_FREE_PAGES);
+ other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM) -
total_swapcache_pages();
@@ -115,6 +141,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
lowmem_print(5, "lowmem_scan %lu, %x, return 0\n",
sc->nr_to_scan, sc->gfp_mask);
+ mutex_unlock(&scan_mutex);
return 0;
}
@@ -128,16 +155,20 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
if (tsk->flags & PF_KTHREAD)
continue;
+ if (time_before_eq(jiffies, lowmem_deathpending_timeout)) {
+ if (test_task_flag(tsk, TIF_MEMDIE)) {
+ rcu_read_unlock();
+ /* give the system time to free up the memory */
+ msleep_interruptible(20);
+ mutex_unlock(&scan_mutex);
+ return 0;
+ }
+ }
+
p = find_lock_task_mm(tsk);
if (!p)
continue;
- if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
- time_before_eq(jiffies, lowmem_deathpending_timeout)) {
- task_unlock(p);
- rcu_read_unlock();
- return 0;
- }
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
task_unlock(p);
@@ -189,11 +220,14 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
free);
lowmem_deathpending_timeout = jiffies + HZ;
rem += selected_tasksize;
+ /* give the system time to free up the memory */
+ msleep_interruptible(20);
}
lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
sc->nr_to_scan, sc->gfp_mask, rem);
rcu_read_unlock();
+ mutex_unlock(&scan_mutex);
return rem;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3da70925d565..448cbdf6fa40 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2094,6 +2094,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
unsigned long flags;
int irq;
+ pm_runtime_get_sync(dwc->dev);
+ dbg_event(0xFF, "Stop gsync",
+ atomic_read(&dwc->dev->power.usage_count));
dwc3_gadget_disable_irq(dwc);
tasklet_kill(&dwc->bh);
@@ -2107,6 +2110,10 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
spin_unlock_irqrestore(&dwc->lock, flags);
+ pm_runtime_mark_last_busy(dwc->dev);
+ pm_runtime_put_autosuspend(dwc->dev);
+ dbg_event(0xFF, "Auto_susgsync", 0);
+
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
free_irq(irq, dwc);
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index de246efcbb58..1eb0c8d6b62f 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -46,6 +46,13 @@
#define FREEZIO_N BIT(1)
#define POWER_DOWN BIT(0)
+#define QUSB2PHY_PWR_CTRL1 0x210
+#define PWR_CTRL1_CLAMP_N_EN BIT(1)
+#define PWR_CTRL1_POWR_DOWN BIT(0)
+
+#define QUSB2PHY_PLL_COMMON_STATUS_ONE 0x1A0
+#define CORE_READY_STATUS BIT(0)
+
#define QUSB2PHY_PORT_UTMI_CTRL1 0xC0
#define TERM_SELECT BIT(4)
#define XCVR_SELECT_FS BIT(2)
@@ -117,6 +124,7 @@ struct qusb_phy {
int vdd_levels[3]; /* none, low, high */
int init_seq_len;
int *qusb_phy_init_seq;
+ u32 major_rev;
u32 tune2_val;
int tune2_efuse_bit_pos;
@@ -410,6 +418,8 @@ static int qusb_phy_init(struct usb_phy *phy)
{
struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
int ret, reset_val = 0;
+ u8 reg;
+ bool pll_lock_fail = false;
dev_dbg(phy->dev, "%s\n", __func__);
@@ -466,8 +476,13 @@ static int qusb_phy_init(struct usb_phy *phy)
}
/* Disable the PHY */
- writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
- qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ if (qphy->major_rev < 2)
+ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
+ qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ else
+ writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+ PWR_CTRL1_POWR_DOWN,
+ qphy->base + QUSB2PHY_PWR_CTRL1);
/* configure for ULPI mode if requested */
if (qphy->ulpi_mode)
@@ -508,8 +523,13 @@ static int qusb_phy_init(struct usb_phy *phy)
wmb();
/* Enable the PHY */
- writel_relaxed(CLAMP_N_EN | FREEZIO_N,
- qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ if (qphy->major_rev < 2)
+ writel_relaxed(CLAMP_N_EN | FREEZIO_N,
+ qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ else
+ writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) &
+ ~PWR_CTRL1_POWR_DOWN,
+ qphy->base + QUSB2PHY_PWR_CTRL1);
/* Ensure above write is completed before turning ON ref clk */
wmb();
@@ -529,18 +549,29 @@ static int qusb_phy_init(struct usb_phy *phy)
writel_relaxed(reset_val,
qphy->base + QUSB2PHY_PLL_TEST);
}
- }
- /* Make sure that above write is completed to get PLL source clock */
- wmb();
+ /* Make sure above write is completed to get PLL source clock */
+ wmb();
- /* Required to get PHY PLL lock successfully */
- usleep_range(100, 110);
+ /* Required to get PHY PLL lock successfully */
+ usleep_range(100, 110);
+ }
+
+ if (qphy->major_rev < 2) {
+ reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS);
+ dev_dbg(phy->dev, "QUSB2PHY_PLL_STATUS:%x\n", reg);
+ if (!(reg & QUSB2PHY_PLL_LOCK))
+ pll_lock_fail = true;
+ } else {
+ reg = readb_relaxed(qphy->base +
+ QUSB2PHY_PLL_COMMON_STATUS_ONE);
+ dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
+ if (!(reg & CORE_READY_STATUS))
+ pll_lock_fail = true;
+ }
- if (!(readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS) &
- QUSB2PHY_PLL_LOCK)) {
- dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n",
- readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS));
+ if (pll_lock_fail) {
+ dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
WARN_ON(1);
}
@@ -556,8 +587,13 @@ static void qusb_phy_shutdown(struct usb_phy *phy)
qusb_phy_enable_clocks(qphy, true);
/* Disable the PHY */
- writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
- qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ if (qphy->major_rev < 2)
+ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
+ qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ else
+ writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+ PWR_CTRL1_POWR_DOWN,
+ qphy->base + QUSB2PHY_PWR_CTRL1);
wmb();
qusb_phy_enable_clocks(qphy, false);
@@ -976,6 +1012,12 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
hold_phy_reset = of_property_read_bool(dev->of_node, "qcom,hold-reset");
+
+ /* use default major revision as 2 */
+ qphy->major_rev = 2;
+ ret = of_property_read_u32(dev->of_node, "qcom,major-rev",
+ &qphy->major_rev);
+
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/include/linux/bluetooth-power.h b/include/linux/bluetooth-power.h
index a411520a83b2..7211c48dbc7b 100644
--- a/include/linux/bluetooth-power.h
+++ b/include/linux/bluetooth-power.h
@@ -27,6 +27,8 @@ struct bt_power_vreg_data {
/* voltage levels to be set */
unsigned int low_vol_level;
unsigned int high_vol_level;
+ /* current level to be set */
+ unsigned int load_uA;
/*
* is set voltage supported for this regulator?
* false => set voltage is not supported
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index fe99c620b85b..3a87177b623f 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -907,12 +907,23 @@ struct IpaHwStatsWDIInfoData_t {
* Rx buffers)
* @rdy_ring_size: size of the Rx ring in bytes
* @rdy_ring_rp_pa: physical address of the location through which IPA uc is
+ * reading (WDI-1.0)
+ * @rdy_comp_ring_base_pa: physical address of the base of the Rx completion
+ * ring (WDI-2.0)
+ * @rdy_comp_ring_wp_pa: physical address of the location through which IPA
+ * uc is writing (WDI-2.0)
+ * @rdy_comp_ring_size: size of the Rx_completion ring in bytes
* expected to communicate about the Read pointer into the Rx Ring
*/
struct ipa_wdi_ul_params {
phys_addr_t rdy_ring_base_pa;
u32 rdy_ring_size;
phys_addr_t rdy_ring_rp_pa;
+ phys_addr_t rdy_comp_ring_base_pa;
+ phys_addr_t rdy_comp_ring_wp_pa;
+ u32 rdy_comp_ring_size;
+ u32 *rdy_ring_rp_va;
+ u32 *rdy_comp_ring_wp_va;
};
/**
@@ -926,6 +937,9 @@ struct ipa_wdi_ul_params_smmu {
struct sg_table rdy_ring;
u32 rdy_ring_size;
phys_addr_t rdy_ring_rp_pa;
+ struct sg_table rdy_comp_ring;
+ phys_addr_t rdy_comp_ring_wp_pa;
+ u32 rdy_comp_ring_size;
};
/**
@@ -1038,30 +1052,6 @@ struct ipa_wdi_buffer_info {
};
/**
- * struct odu_bridge_params - parameters for odu bridge initialization API
- *
- * @netdev_name: network interface name
- * @priv: private data that will be supplied to client's callback
- * @tx_dp_notify: callback for handling SKB. the following event are supported:
- * IPA_WRITE_DONE: will be called after client called to odu_bridge_tx_dp()
- * Client is expected to free the skb.
- * IPA_RECEIVE: will be called for delivering skb to APPS.
- * Client is expected to deliver the skb to network stack.
- * @send_dl_skb: callback for sending skb on downlink direction to adapter.
- * Client is expected to free the skb.
- * @device_ethaddr: device Ethernet address in network order.
- * @ipa_desc_size: IPA Sys Pipe Desc Size
- */
-struct odu_bridge_params {
- const char *netdev_name;
- void *priv;
- ipa_notify_cb tx_dp_notify;
- int (*send_dl_skb)(void *priv, struct sk_buff *skb);
- u8 device_ethaddr[ETH_ALEN];
- u32 ipa_desc_size;
-};
-
-/**
* enum ipa_mhi_event_type - event type for mhi callback
*
* @IPA_MHI_EVENT_READY: IPA MHI is ready and IPA uC is loaded. After getting
@@ -1424,20 +1414,6 @@ enum ipacm_client_enum ipa_get_client(int pipe_idx);
bool ipa_get_client_uplink(int pipe_idx);
/*
- * ODU bridge
- */
-
-int odu_bridge_init(struct odu_bridge_params *params);
-
-int odu_bridge_connect(void);
-
-int odu_bridge_disconnect(void);
-
-int odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata);
-
-int odu_bridge_cleanup(void);
-
-/*
* IPADMA
*/
int ipa_dma_init(void);
@@ -2090,36 +2066,6 @@ static inline bool ipa_get_client_uplink(int pipe_idx)
return -EPERM;
}
-
-/*
- * ODU bridge
- */
-static inline int odu_bridge_init(struct odu_bridge_params *params)
-{
- return -EPERM;
-}
-
-static inline int odu_bridge_disconnect(void)
-{
- return -EPERM;
-}
-
-static inline int odu_bridge_connect(void)
-{
- return -EPERM;
-}
-
-static inline int odu_bridge_tx_dp(struct sk_buff *skb,
- struct ipa_tx_meta *metadata)
-{
- return -EPERM;
-}
-
-static inline int odu_bridge_cleanup(void)
-{
- return -EPERM;
-}
-
/*
* IPADMA
*/
diff --git a/include/linux/ipa_odu_bridge.h b/include/linux/ipa_odu_bridge.h
new file mode 100644
index 000000000000..5d30a9784998
--- /dev/null
+++ b/include/linux/ipa_odu_bridge.h
@@ -0,0 +1,84 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _IPA_ODO_BRIDGE_H_
+#define _IPA_ODO_BRIDGE_H_
+
+#include <linux/ipa.h>
+
+/**
+ * struct odu_bridge_params - parameters for odu bridge initialization API
+ *
+ * @netdev_name: network interface name
+ * @priv: private data that will be supplied to client's callback
+ * @tx_dp_notify: callback for handling SKB. the following event are supported:
+ * IPA_WRITE_DONE: will be called after client called to odu_bridge_tx_dp()
+ * Client is expected to free the skb.
+ * IPA_RECEIVE: will be called for delivering skb to APPS.
+ * Client is expected to deliver the skb to network stack.
+ * @send_dl_skb: callback for sending skb on downlink direction to adapter.
+ * Client is expected to free the skb.
+ * @device_ethaddr: device Ethernet address in network order.
+ * @ipa_desc_size: IPA Sys Pipe Desc Size
+ */
+struct odu_bridge_params {
+ const char *netdev_name;
+ void *priv;
+ ipa_notify_cb tx_dp_notify;
+ int (*send_dl_skb)(void *priv, struct sk_buff *skb);
+ u8 device_ethaddr[ETH_ALEN];
+ u32 ipa_desc_size;
+};
+
+#if defined CONFIG_IPA || defined CONFIG_IPA3
+
+int odu_bridge_init(struct odu_bridge_params *params);
+
+int odu_bridge_connect(void);
+
+int odu_bridge_disconnect(void);
+
+int odu_bridge_tx_dp(struct sk_buff *skb, struct ipa_tx_meta *metadata);
+
+int odu_bridge_cleanup(void);
+
+#else
+
+static inline int odu_bridge_init(struct odu_bridge_params *params)
+{
+ return -EPERM;
+}
+
+static inline int odu_bridge_disconnect(void)
+{
+ return -EPERM;
+}
+
+static inline int odu_bridge_connect(void)
+{
+ return -EPERM;
+}
+
+static inline int odu_bridge_tx_dp(struct sk_buff *skb,
+ struct ipa_tx_meta *metadata)
+{
+ return -EPERM;
+}
+
+static inline int odu_bridge_cleanup(void)
+{
+ return -EPERM;
+}
+
+#endif /* CONFIG_IPA || defined CONFIG_IPA3 */
+
+#endif /* _IPA_ODO_BRIDGE_H */
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 66c0e8f43883..fb650ab2693f 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -135,8 +135,8 @@ struct msm_actuator_params_t32 {
uint16_t init_setting_size;
uint32_t i2c_addr;
enum i2c_freq_mode_t i2c_freq_mode;
- enum msm_actuator_addr_type i2c_addr_type;
- enum msm_actuator_data_type i2c_data_type;
+ enum msm_camera_i2c_reg_addr_type i2c_addr_type;
+ enum msm_camera_i2c_data_type i2c_data_type;
compat_uptr_t reg_tbl_params;
compat_uptr_t init_settings;
struct park_lens_data_t park_lens;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d67f3873e10..63568caf0de8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -712,6 +712,8 @@ struct cfg80211_acl_data {
* @p2p_opp_ps: P2P opportunistic PS
* @acl: ACL configuration used by the drivers which has support for
* MAC address based access control
+ * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
+ * networks.
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
@@ -730,6 +732,7 @@ struct cfg80211_ap_settings {
u8 p2p_ctwindow;
bool p2p_opp_ps;
const struct cfg80211_acl_data *acl;
+ bool pbss;
};
/**
@@ -1888,6 +1891,8 @@ struct cfg80211_ibss_params {
* @ht_capa_mask: The bits of ht_capa which are to be used.
* @vht_capa: VHT Capability overrides
* @vht_capa_mask: The bits of vht_capa which are to be used.
+ * @pbss: if set, connect to a PCP instead of AP. Valid for DMG
+ * networks.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@@ -1910,6 +1915,7 @@ struct cfg80211_connect_params {
struct ieee80211_ht_cap ht_capa_mask;
struct ieee80211_vht_cap vht_capa;
struct ieee80211_vht_cap vht_capa_mask;
+ bool pbss;
};
/**
@@ -3488,6 +3494,7 @@ struct cfg80211_cached_keys;
* registered for unexpected class 3 frames (AP mode)
* @conn: (private) cfg80211 software SME connection state machine data
* @connect_keys: (private) keys to set after connection is established
+ * @conn_bss_type: connecting/connected BSS type
* @ibss_fixed: (private) IBSS is using fixed BSSID
* @ibss_dfs_possible: (private) IBSS may change to a DFS channel
* @event_list: (private) list for internal event processing
@@ -3518,6 +3525,7 @@ struct wireless_dev {
u8 ssid_len, mesh_id_len, mesh_id_up_len;
struct cfg80211_conn *conn;
struct cfg80211_cached_keys *connect_keys;
+ enum ieee80211_bss_type conn_bss_type;
struct list_head event_list;
spinlock_t event_lock;
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 14a22fd1b55f..27ae1332947c 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -72,6 +72,8 @@ enum icnss_driver_mode {
ICNSS_EPPING,
ICNSS_WALTEST,
ICNSS_OFF,
+ ICNSS_CCPM,
+ ICNSS_QVIT,
};
struct icnss_soc_info {
diff --git a/include/soc/qcom/service-locator.h b/include/soc/qcom/service-locator.h
new file mode 100644
index 000000000000..be1a2b431dd9
--- /dev/null
+++ b/include/soc/qcom/service-locator.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Process Domain Service Locator API header
+ */
+
+#ifndef _SERVICE_LOCATOR_H
+#define _SERVICE_LOCATOR_H
+
+#define QMI_SERVREG_LOC_NAME_LENGTH_V01 64
+#define QMI_SERVREG_LOC_LIST_LENGTH_V01 32
+
+/*
+ * @name: The full process domain path for a process domain which provides
+ * a particular service
+ * @instance_id: The QMI instance id corresponding to the root process
+ * domain which is responsible for notifications for this
+ * process domain
+ * @service_data_valid: Indicates if service_data field has valid data
+ * @service_data: Optional service data provided by the service locator
+ */
+struct servreg_loc_entry_v01 {
+ char name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
+ uint32_t instance_id;
+ uint8_t service_data_valid;
+ uint32_t service_data;
+};
+
+/*
+ * @client_name: Name of the client calling the api
+ * @service_name: Name of the service for which the list of process domains
+ * is requested
+ * @total_domains: Length of the process domain list
+ * @db_rev_count: Process domain list database revision number
+ * @domain_list: List of process domains providing the service
+ */
+struct pd_qmi_client_data {
+ char client_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
+ char service_name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
+ int total_domains;
+ int db_rev_count;
+ struct servreg_loc_entry_v01 *domain_list;
+};
+
+#if defined(CONFIG_MSM_SERVICE_LOCATOR)
+/*
+ * Use this api to request information regarding the process domains on which
+ * a particular service runs. The client name and the service name inside the
+ * pd_qmi_client_data structure need to be filled in by the client calling the
+ * api. The total domains, db revision and the domain list will be filled in
+ * by the service locator.
+ * Returns 0 on success; otherwise a value < 0 if no valid subsystem is found.
+ */
+int get_service_location(struct pd_qmi_client_data *data);
+
+/*
+ * Use this api to request information regarding the subsystem the process
+ * domain runs on.
+ * @pd_path: The name field from inside the servreg_loc_entry that one
+ * gets back using the get_processdomains api.
+ * Returns 0 on success; otherwise a value < 0 if no valid subsystem is found.
+ */
+int find_subsys(const char *pd_path, char *subsys);
+
+#else
+
+static inline int get_service_location(struct pd_qmi_client_data *data)
+{
+ return 0;
+}
+
+static inline int find_subsys(const char *pd_path, const char *subsys)
+{
+ return 0;
+}
+
+#endif /* CONFIG_MSM_SERVICE_LOCATOR */
+
+#endif
diff --git a/include/soc/qcom/smem.h b/include/soc/qcom/smem.h
index c83caede1763..d8ee4d523880 100644
--- a/include/soc/qcom/smem.h
+++ b/include/soc/qcom/smem.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
@@ -76,7 +76,7 @@ enum {
SMEM_SMD_BASE_ID,
SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_STREAM_CHANNELS,
SMEM_SMEM_LOG_EVENTS,
- SMEM_SMEM_STATIC_LOG_IDX,
+ SMEM_XBL_LOADER_CORE_INFO,
SMEM_SMEM_STATIC_LOG_EVENTS,
SMEM_SMEM_SLOW_CLOCK_SYNC,
SMEM_SMEM_SLOW_CLOCK_VALUE,
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1f0b4cf5dd03..25627f584405 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1783,6 +1783,11 @@ enum nl80211_commands {
* between scans. The scan plans are executed sequentially.
* Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan.
*
+ * @NL80211_ATTR_PBSS: flag attribute. If set it means operate
+ * in a PBSS. Specified in %NL80211_CMD_CONNECT to request
+ * connecting to a PCP, and in %NL80211_CMD_START_AP to start
+ * a PCP instead of AP. Relevant for DMG networks only.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2157,6 +2162,8 @@ enum nl80211_attrs {
NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
NL80211_ATTR_SCHED_SCAN_PLANS,
+ NL80211_ATTR_PBSS,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h
index c534911d864a..d83e00876fd5 100644
--- a/include/uapi/media/msm_cam_sensor.h
+++ b/include/uapi/media/msm_cam_sensor.h
@@ -409,8 +409,8 @@ struct msm_actuator_params_t {
uint16_t init_setting_size;
uint32_t i2c_addr;
enum i2c_freq_mode_t i2c_freq_mode;
- enum msm_actuator_addr_type i2c_addr_type;
- enum msm_actuator_data_type i2c_data_type;
+ enum msm_camera_i2c_reg_addr_type i2c_addr_type;
+ enum msm_camera_i2c_data_type i2c_data_type;
struct msm_actuator_reg_params_t *reg_tbl_params;
struct reg_settings_t *init_settings;
struct park_lens_data_t park_lens;
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index eab853bf137f..3985e9750af7 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -367,9 +367,9 @@ struct region_params_t {
struct reg_settings_t {
unsigned short reg_addr;
- enum msm_actuator_addr_type addr_type;
+ enum msm_camera_i2c_reg_addr_type addr_type;
unsigned short reg_data;
- enum msm_actuator_data_type data_type;
+ enum msm_camera_i2c_data_type data_type;
enum msm_actuator_i2c_operation i2c_operation;
unsigned int delay;
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b30a0a8030d3..816c9075ba3c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -401,6 +401,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 },
[NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
[NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
+ [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -3461,6 +3462,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
return PTR_ERR(params.acl);
}
+ params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
+ if (params.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ])
+ return -EOPNOTSUPP;
+
wdev_lock(wdev);
err = rdev_start_ap(rdev, dev, &params);
if (!err) {
@@ -7951,6 +7956,12 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
connect.flags |= ASSOC_REQ_USE_RRM;
}
+ connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
+ if (connect.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ]) {
+ kzfree(connkeys);
+ return -EOPNOTSUPP;
+ }
+
wdev_lock(dev->ieee80211_ptr);
err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8020b5b094d4..79bd3a171caa 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -264,7 +264,7 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
wdev->conn->params.bssid,
wdev->conn->params.ssid,
wdev->conn->params.ssid_len,
- IEEE80211_BSS_TYPE_ESS,
+ wdev->conn_bss_type,
IEEE80211_PRIVACY(wdev->conn->params.privacy));
if (!bss)
return NULL;
@@ -687,7 +687,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect);
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
wdev->ssid, wdev->ssid_len,
- IEEE80211_BSS_TYPE_ESS,
+ wdev->conn_bss_type,
IEEE80211_PRIVACY_ANY);
if (bss)
cfg80211_hold_bss(bss_from_pub(bss));
@@ -846,7 +846,7 @@ void cfg80211_roamed(struct net_device *dev,
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid,
wdev->ssid_len,
- IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
+ wdev->conn_bss_type, IEEE80211_PRIVACY_ANY);
if (WARN_ON(!bss))
return;
@@ -1017,6 +1017,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
wdev->ssid_len = connect->ssid_len;
+ wdev->conn_bss_type = connect->pbss ? IEEE80211_BSS_TYPE_PBSS :
+ IEEE80211_BSS_TYPE_ESS;
+
if (!rdev->ops->connect)
err = cfg80211_sme_connect(wdev, connect, prev_bssid);
else
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 6a4f5099833f..e8fc5f622c3e 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -114,4 +114,31 @@ config SND_SOC_MSM8996
the machine driver and the corresponding
DAI-links
+config SND_SOC_MSMCOBALT
+ tristate "SoC Machine driver for MSMCOBALT boards"
+ depends on ARCH_QCOM
+ select SND_SOC_COMPRESS
+ select SND_SOC_QDSP6V2
+ select SND_SOC_MSM_STUB
+ select SND_SOC_MSM_HOSTLESS_PCM
+ select SND_DYNAMIC_MINORS
+ select MSM_QDSP6_APRV2
+ select MSM_QDSP6V2_CODECS
+ select SND_SOC_WCD9335
+ select SND_SOC_WSA881X
+ select SND_SOC_MSM_HDMI_CODEC_RX
+ select DTS_SRS_TM
+ select QTI_PP
+ select SND_SOC_CPE
+ select MSM_ULTRASOUND
+ select DOLBY_DS2
+ select SND_HWDEP
+ select DTS_EAGLE
+ help
+ To add support for SoC audio on MSMCOBALT.
+ This will enable sound soc drivers which
+ interfaces with DSP, also it will enable
+ the machine driver and the corresponding
+ DAI-links
+
endmenu
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 12514d9775c6..3ad34be41578 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -15,3 +15,7 @@ obj-$(CONFIG_SND_SOC_CPE) += snd-soc-cpe.o
# for MSM8996 sound card driver
snd-soc-msm8996-objs := msm8996.o
obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o
+
+# for MSMCOBALT sound card driver
+snd-soc-msmcobalt-objs := msmcobalt.o
+obj-$(CONFIG_SND_SOC_MSMCOBALT) += snd-soc-msmcobalt.o
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
new file mode 100644
index 000000000000..c78265e5a23c
--- /dev/null
+++ b/sound/soc/msm/msmcobalt.c
@@ -0,0 +1,2828 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/switch.h>
+#include <linux/input.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <sound/q6afe-v2.h>
+#include <sound/q6core.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <device_event.h>
+#include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "../codecs/wcd9335.h"
+#include "../codecs/wsa881x.h"
+
+#define DRV_NAME "msmcobalt-asoc-snd"
+
+#define __CHIPSET__ "MSMCOBALT "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#define SAMPLING_RATE_8KHZ 8000
+#define SAMPLING_RATE_16KHZ 16000
+#define SAMPLING_RATE_32KHZ 32000
+#define SAMPLING_RATE_44P1KHZ 44100
+#define SAMPLING_RATE_48KHZ 48000
+#define SAMPLING_RATE_96KHZ 96000
+#define SAMPLING_RATE_192KHZ 192000
+
+#define WCD9XXX_MBHC_DEF_BUTTONS 8
+#define WCD9XXX_MBHC_DEF_RLOADS 5
+#define CODEC_EXT_CLK_RATE 9600000
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+#define DEV_NAME_STR_LEN 32
+
+#define WSA8810_NAME_1 "wsa881x.20170211"
+#define WSA8810_NAME_2 "wsa881x.20170212"
+
+enum {
+ SLIM_RX_0 = 0,
+ SLIM_RX_1,
+ SLIM_RX_2,
+ SLIM_RX_3,
+ SLIM_RX_4,
+ SLIM_RX_5,
+ SLIM_RX_MAX,
+};
+
+enum {
+ SLIM_TX_0 = 0,
+ SLIM_TX_1,
+ SLIM_TX_2,
+ SLIM_TX_3,
+ SLIM_TX_4,
+ SLIM_TX_5,
+ SLIM_TX_6,
+ SLIM_TX_7,
+ SLIM_TX_MAX,
+};
+
+struct slim_ch_config {
+ u32 sample_rate;
+ u32 bit_format;
+ u32 channels;
+};
+
+struct msm_wsa881x_dev_info {
+ struct device_node *of_node;
+ u32 index;
+};
+
+struct msm_asoc_mach_data {
+ u32 mclk_freq;
+ int us_euro_gpio;
+ int hph_en1_gpio;
+ int hph_en0_gpio;
+ struct snd_info_entry *codec_root;
+};
+
+struct msm_asoc_wcd93xx_codec {
+ void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
+ enum afe_config_type config_type);
+ void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
+};
+
+/* Default configuration of slimbus channels */
+static struct slim_ch_config slim_rx_cfg[] = {
+ [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct slim_ch_config slim_tx_cfg[] = {
+ [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_7] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static int msm_vi_feed_tx_ch = 2;
+static const char *const slim_rx_ch_text[] = {"One", "Two"};
+static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven",
+ "Eight"};
+static const char *const vi_feed_ch_text[] = {"One", "Two"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE"};
+static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
+ "KHZ_32", "KHZ_44P1", "KHZ_48",
+ "KHZ_96", "KHZ_192"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_1_tx_chs, slim_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
+
+static struct platform_device *spdev;
+
+static bool codec_reg_done;
+static struct snd_soc_aux_dev *msm_aux_dev;
+static struct snd_soc_codec_conf *msm_codec_conf;
+static struct msm_asoc_wcd93xx_codec msm_codec_fn;
+static void *adsp_state_notifier;
+
+static void *def_tasha_mbhc_cal(void);
+static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
+ int enable, bool dapm);
+static int msm_wsa881x_init(struct snd_soc_component *component);
+
+/*
+ * Need to report LINEIN
+ * if R/L channel impedance is larger than 5K ohm
+ */
+static struct wcd_mbhc_config wcd_mbhc_cfg = {
+ .read_fw_bin = false,
+ .calibration = NULL,
+ .detect_extn_cable = true,
+ .mono_stero_detection = false,
+ .swap_gnd_mic = NULL,
+ .hs_ext_micbias = true,
+ .key_code[0] = KEY_MEDIA,
+ .key_code[1] = KEY_VOICECOMMAND,
+ .key_code[2] = KEY_VOLUMEUP,
+ .key_code[3] = KEY_VOLUMEDOWN,
+ .key_code[4] = 0,
+ .key_code[5] = 0,
+ .key_code[6] = 0,
+ .key_code[7] = 0,
+ .linein_th = 5000,
+ .moist_cfg = { V_45_MV, I_3P0_UA },
+};
+
+static struct snd_soc_dapm_route wcd9335_audio_paths[] = {
+ {"MIC BIAS1", NULL, "MCLK"},
+ {"MIC BIAS2", NULL, "MCLK"},
+ {"MIC BIAS3", NULL, "MCLK"},
+ {"MIC BIAS4", NULL, "MCLK"},
+};
+
+static int slim_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val = 0;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 6;
+ break;
+ default:
+ sample_rate_val = 4;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int slim_get_sample_rate(int value)
+{
+ int sample_rate = 0;
+
+ switch (value) {
+ case 0:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ default:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int slim_get_bit_format_val(int bit_format)
+{
+ int val = 0;
+
+ switch (bit_format) {
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ val = 0;
+ break;
+ }
+ return val;
+}
+
+static int slim_get_bit_format(int val)
+{
+ int bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+
+ switch (val) {
+ case 0:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ case 1:
+ bit_fmt = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ default:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ return bit_fmt;
+}
+
+static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+ int port_id = 0;
+
+ if (strnstr(kcontrol->id.name, "SLIM_0_RX", sizeof("SLIM_0_RX")))
+ port_id = SLIM_RX_0;
+ else if (strnstr(kcontrol->id.name, "SLIM_5_RX", sizeof("SLIM_5_RX")))
+ port_id = SLIM_RX_5;
+ else if (strnstr(kcontrol->id.name, "SLIM_0_TX", sizeof("SLIM_0_TX")))
+ port_id = SLIM_TX_0;
+ else if (strnstr(kcontrol->id.name, "SLIM_1_TX", sizeof("SLIM_1_TX")))
+ port_id = SLIM_TX_1;
+ else {
+ pr_err("%s: unsupported channel: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return port_id;
+}
+
+static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_sample_rate_val(slim_rx_cfg[ch_num].sample_rate);
+
+ pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].sample_rate =
+ slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_sample_rate_val(slim_tx_cfg[ch_num].sample_rate);
+
+ pr_debug("%s: slim[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int sample_rate = 0;
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ sample_rate = slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
+ if (sample_rate == SAMPLING_RATE_44P1KHZ) {
+ pr_err("%s: Unsupported sample rate %d: for Tx path\n",
+ __func__, sample_rate);
+ return -EINVAL;
+ }
+ slim_tx_cfg[ch_num].sample_rate = sample_rate;
+
+ pr_debug("%s: slim[%d]_tx_sample_rate = %d, value = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_bit_format_val(slim_rx_cfg[ch_num].bit_format);
+
+ pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].bit_format =
+ slim_get_bit_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_bit_format_val(slim_tx_cfg[ch_num].bit_format);
+
+ pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_tx_cfg[ch_num].bit_format =
+ slim_get_bit_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int msm_slim_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].channels);
+ ucontrol->value.enumerated.item[0] = slim_rx_cfg[ch_num].channels - 1;
+
+ return 0;
+}
+
+static int msm_slim_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].channels);
+
+ return 1;
+}
+
+static int msm_slim_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].channels);
+ ucontrol->value.enumerated.item[0] = slim_tx_cfg[ch_num].channels - 1;
+
+ return 0;
+}
+
+static int msm_slim_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].channels);
+
+ return 1;
+}
+
+static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
+ pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
+ return 1;
+}
+
+static const struct snd_kcontrol_new msm_snd_controls[] = {
+ SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("SLIM_0_TX Channels", slim_0_tx_chs,
+ msm_slim_tx_ch_get, msm_slim_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_1_TX Channels", slim_1_tx_chs,
+ msm_slim_tx_ch_get, msm_slim_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_5_RX Channels", slim_5_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
+ msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format,
+ slim_rx_bit_format_get, slim_rx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format,
+ slim_rx_bit_format_get, slim_rx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format,
+ slim_tx_bit_format_get, slim_tx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate,
+ slim_tx_sample_rate_get, slim_tx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_5_RX SampleRate", slim_5_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+};
+
+static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec,
+ int enable, bool dapm)
+{
+ int ret = 0;
+
+ if (!strcmp(dev_name(codec->dev), "tasha_codec"))
+ ret = tasha_cdc_mclk_enable(codec, enable, dapm);
+ else {
+ dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
+ __func__);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int msm_mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return msm_snd_enable_codec_ext_clk(codec, 1, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return msm_snd_enable_codec_ext_clk(codec, 0, true);
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
+
+ SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
+ msm_mclk_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
+ SND_SOC_DAPM_MIC("Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic5", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic6", NULL),
+
+ SND_SOC_DAPM_MIC("Digital Mic0", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic2", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic3", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic4", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic5", NULL),
+};
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
+ int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ int rc = 0;
+ void *config = NULL;
+ struct snd_soc_codec *codec = NULL;
+
+ pr_debug("%s: format = %d, rate = %d\n",
+ __func__, params_format(params), params_rate(params));
+
+ switch (dai_link->be_id) {
+ case MSM_BACKEND_DAI_SLIMBUS_0_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_1_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_3_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_4_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[0].bit_format);
+ rate->min = rate->max = slim_rx_cfg[0].sample_rate;
+ channels->min = channels->max = slim_rx_cfg[0].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_0_TX:
+ case MSM_BACKEND_DAI_SLIMBUS_3_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_tx_cfg[0].bit_format);
+ rate->min = rate->max = slim_tx_cfg[0].sample_rate;
+ channels->min = channels->max = slim_tx_cfg[0].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_1_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_tx_cfg[1].bit_format);
+ rate->min = rate->max = slim_tx_cfg[1].sample_rate;
+ channels->min = channels->max = slim_tx_cfg[1].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_4_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FORMAT_S32_LE);
+ rate->min = rate->max = SAMPLING_RATE_8KHZ;
+ channels->min = channels->max = msm_vi_feed_tx_ch;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_5_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[5].bit_format);
+ rate->min = rate->max = slim_rx_cfg[5].sample_rate;
+ channels->min = channels->max = slim_rx_cfg[5].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_5_TX:
+ codec = rtd->codec;
+ rate->min = rate->max = SAMPLING_RATE_16KHZ;
+ channels->min = channels->max = 1;
+
+ config = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_SLIMBUS_SLAVE_PORT_CONFIG);
+ if (config) {
+ rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG,
+ config, SLIMBUS_5_TX);
+ if (rc)
+ pr_err("%s: Failed to set slimbus slave port config %d\n",
+ __func__, rc);
+ }
+ break;
+
+ default:
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return 0;
+}
+
+static bool msm_swap_gnd_mic(struct snd_soc_codec *codec)
+{
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+ int value = gpio_get_value_cansleep(pdata->us_euro_gpio);
+
+ pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
+ gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
+ return true;
+}
+
+static int msm_afe_set_config(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+ void *config_data = NULL;
+
+ if (!msm_codec_fn.get_afe_config_fn) {
+ dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_REGISTERS_CONFIG);
+ if (config_data) {
+ ret = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+ if (ret) {
+ dev_err(codec->dev,
+ "%s: Failed to set codec registers config %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_REGISTER_PAGE_CONFIG);
+ if (config_data) {
+ ret = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
+ 0);
+ if (ret)
+ dev_err(codec->dev,
+ "%s: Failed to set cdc register page config\n",
+ __func__);
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_SLIMBUS_SLAVE_CONFIG);
+ if (config_data) {
+ ret = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+ if (ret) {
+ dev_err(codec->dev,
+ "%s: Failed to set slimbus slave config %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void msm_afe_clear_config(void)
+{
+ afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
+ afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
+}
+
+static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+ unsigned long timeout;
+ int adsp_ready = 0;
+
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+
+ do {
+ if (q6core_is_adsp_ready()) {
+ pr_debug("%s: ADSP Audio is ready\n", __func__);
+ adsp_ready = 1;
+ break;
+ }
+ } while (time_after(timeout, jiffies));
+
+ if (!adsp_ready) {
+ pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
+ ret = -ETIMEDOUT;
+ goto err_fail;
+ }
+
+ ret = msm_afe_set_config(codec);
+ if (ret)
+ pr_err("%s: Failed to set AFE config. err %d\n",
+ __func__, ret);
+
+ return 0;
+
+err_fail:
+ return ret;
+}
+
+static int msm_adsp_state_callback(struct notifier_block *nb,
+ unsigned long value, void *priv)
+{
+ int ret = NOTIFY_OK;
+ struct snd_soc_card *card = NULL;
+ const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *codec;
+
+ if (!spdev)
+ return -EINVAL;
+
+ card = platform_get_drvdata(spdev);
+ rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+ if (!rtd) {
+ dev_err(card->dev,
+ "%s: snd_soc_get_pcm_runtime for %s failed!\n",
+ __func__, be_dl_name);
+ ret = -EINVAL;
+ goto err_pcm_runtime;
+ }
+
+ codec = rtd->codec;
+ if (value == SUBSYS_BEFORE_SHUTDOWN) {
+ pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
+ __func__);
+ msm_afe_clear_config();
+ } else if (value == SUBSYS_AFTER_POWERUP) {
+ ret = msm_adsp_power_up_config(codec);
+ if (ret) {
+ ret = -EINVAL;
+ } else {
+ pr_debug("%s: ADSP is up\n", __func__);
+ ret = NOTIFY_OK;
+ }
+ }
+
+err_pcm_runtime:
+ return ret;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = msm_adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+static int msm_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
+{
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata;
+ int val;
+
+ if (!card)
+ return 0;
+
+ pdata = snd_soc_card_get_drvdata(card);
+ if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
+ return 0;
+
+ val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
+ if ((!!val) == high)
+ return 0;
+
+ gpio_direction_output(pdata->hph_en0_gpio, (int)high);
+
+ return 1;
+}
+
+static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret = 0;
+ void *config_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
+ struct snd_card *card;
+ struct snd_info_entry *entry;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(rtd->card);
+
+ /* Codec SLIMBUS configuration
+ * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
+ * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+ * TX14, TX15, TX16
+ */
+ unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156};
+ unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143};
+
+ pr_info("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+ rtd->pmdown_time = 0;
+
+ ret = snd_soc_add_codec_controls(codec, msm_snd_controls,
+ ARRAY_SIZE(msm_snd_controls));
+ if (ret < 0) {
+ pr_err("%s: add_codec_controls failed, err %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
+ ARRAY_SIZE(msm_dapm_widgets));
+
+ snd_soc_dapm_add_routes(dapm, wcd9335_audio_paths,
+ ARRAY_SIZE(wcd9335_audio_paths));
+
+ snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic5");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
+ snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
+ snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
+ snd_soc_dapm_ignore_suspend(dapm, "EAR");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
+ snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
+
+ snd_soc_dapm_sync(dapm);
+
+ snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+
+ msm_codec_fn.get_afe_config_fn = tasha_get_afe_config;
+ msm_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
+
+ ret = msm_adsp_power_up_config(codec);
+ if (ret) {
+ pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
+ goto err_afe_cfg;
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_AANC_VERSION);
+ if (config_data) {
+ ret = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set aanc version %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_CLIP_REGISTERS_CONFIG);
+ if (config_data) {
+ ret = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
+ config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set clip registers %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CLIP_BANK_SEL);
+ if (config_data) {
+ ret = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set AFE bank selection %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+ adsp_state_notifier = subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+ if (!adsp_state_notifier) {
+ pr_err("%s: Failed to register adsp state notifier\n",
+ __func__);
+ ret = -EFAULT;
+ goto err_adsp_notify;
+ }
+ /*
+ * Send speaker configuration only for WSA8810.
+ * Defalut configuration is for WSA8815.
+ */
+ if (rtd_aux && rtd_aux->component)
+ if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
+ !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
+ tasha_set_spkr_gain_offset(rtd->codec,
+ RX_GAIN_OFFSET_M1P5_DB);
+ }
+ codec_reg_done = true;
+
+ card = rtd->card->snd_card;
+ entry = snd_register_module_info(card->module, "codecs",
+ card->proc_root);
+ if (!entry) {
+ pr_debug("%s: Cannot create codecs module entry\n",
+ __func__);
+ ret = 0;
+ goto err_snd_module;
+ }
+ pdata->codec_root = entry;
+ tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
+
+ return 0;
+
+err_snd_module:
+err_adsp_notify:
+err_afe_cfg:
+ return ret;
+}
+
+static void *def_tasha_mbhc_cal(void)
+{
+ void *tasha_wcd_cal;
+ struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+ u16 *btn_high;
+
+ tasha_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+ WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
+ if (!tasha_wcd_cal)
+ return NULL;
+
+#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tasha_wcd_cal)->X) = (Y))
+ S(v_hs_max, 1500);
+#undef S
+#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal)->X) = (Y))
+ S(num_btn, WCD_MBHC_DEF_BUTTONS);
+#undef S
+
+ btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tasha_wcd_cal);
+ btn_high = ((void *)&btn_cfg->_v_btn_low) +
+ (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+ btn_high[0] = 75;
+ btn_high[1] = 150;
+ btn_high[2] = 237;
+ btn_high[3] = 500;
+ btn_high[4] = 500;
+ btn_high[5] = 500;
+ btn_high[6] = 500;
+ btn_high[7] = 500;
+
+ return tasha_wcd_cal;
+}
+
+static int msm_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+ int ret = 0;
+ u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ u32 user_set_tx_ch = 0;
+ u32 rx_ch_count;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
+ pr_debug("%s: rx_5_ch=%d\n", __func__,
+ slim_rx_cfg[5].channels);
+ rx_ch_count = slim_rx_cfg[5].channels;
+ } else {
+ pr_debug("%s: rx_0_ch=%d\n", __func__,
+ slim_rx_cfg[0].channels);
+ rx_ch_count = slim_rx_cfg[0].channels;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ rx_ch_count, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ } else {
+
+ pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
+ codec_dai->name, codec_dai->id, user_set_tx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ /* For <codec>_tx1 case */
+ if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
+ user_set_tx_ch = slim_tx_cfg[0].channels;
+ /* For <codec>_tx3 case */
+ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
+ user_set_tx_ch = slim_tx_cfg[1].channels;
+ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
+ user_set_tx_ch = msm_vi_feed_tx_ch;
+ else
+ user_set_tx_ch = tx_ch_cnt;
+
+ pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), be_id (%d)\n",
+ __func__, slim_tx_cfg[0].channels, user_set_tx_ch,
+ tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ user_set_tx_ch, tx_ch, 0, 0);
+ if (ret < 0)
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ }
+
+err_ch_map:
+ return ret;
+}
+
+static int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+ int ret = 0;
+ u32 tx_ch[SLIM_MAX_TX_PORTS];
+ u32 tx_ch_cnt = 0;
+ u32 user_set_tx_ch = 0;
+
+ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
+ pr_err("%s: Invalid stream type %d\n",
+ __func__, substream->stream);
+ ret = -EINVAL;
+ goto err_stream_type;
+ }
+
+ pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
+ codec_dai->name, codec_dai->id);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, NULL, NULL);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+
+ user_set_tx_ch = tx_ch_cnt;
+
+ pr_debug("%s: tx_ch_cnt(%d) be_id %d\n",
+ __func__, tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ user_set_tx_ch, tx_ch, 0, 0);
+ if (ret < 0)
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+err_ch_map:
+err_stream_type:
+ return ret;
+}
+
+static int msm_slimbus_2_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+ unsigned int num_tx_ch = 0;
+ unsigned int num_rx_ch = 0;
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ num_rx_ch = params_channels(params);
+ pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
+ codec_dai->name, codec_dai->id, num_rx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ num_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ } else {
+ num_tx_ch = params_channels(params);
+ pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
+ codec_dai->name, codec_dai->id, num_tx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ num_tx_ch, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ }
+
+err_ch_map:
+ return ret;
+}
+
+static struct snd_soc_ops msm_be_ops = {
+ .hw_params = msm_snd_hw_params,
+};
+
+static struct snd_soc_ops msm_cpe_ops = {
+ .hw_params = msm_snd_cpe_hw_params,
+};
+
+static struct snd_soc_ops msm_slimbus_2_be_ops = {
+ .hw_params = msm_slimbus_2_hw_params,
+};
+
+static int msm_get_ll_qos_val(struct snd_pcm_runtime *runtime)
+{
+ int usecs;
+
+ /* take 10% of period time as the deadline */
+ usecs = (100000 / runtime->rate) * runtime->period_size;
+ usecs += ((100000 % runtime->rate) * runtime->period_size) /
+ runtime->rate;
+
+ return usecs;
+}
+
+static int msm_mm5_prepare(struct snd_pcm_substream *substream)
+{
+ if (pm_qos_request_active(&substream->latency_pm_qos_req))
+ pm_qos_remove_request(&substream->latency_pm_qos_req);
+ pm_qos_add_request(&substream->latency_pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ msm_get_ll_qos_val(substream->runtime));
+ return 0;
+}
+
+static struct snd_soc_ops msm_mm5_ops = {
+ .prepare = msm_mm5_prepare,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_common_dai_links[] = {
+ /* FrontEnd DAI Links */
+ {
+ .name = MSM_DAILINK_NAME(Media1),
+ .stream_name = "MultiMedia1",
+ .cpu_dai_name = "MultiMedia1",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ },
+ {
+ .name = MSM_DAILINK_NAME(Media2),
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {
+ .name = "VoiceMMode1",
+ .stream_name = "VoiceMMode1",
+ .cpu_dai_name = "VoiceMMode1",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE1,
+ },
+ {
+ .name = "MSM VoIP",
+ .stream_name = "VoIP",
+ .cpu_dai_name = "VoIP",
+ .platform_name = "msm-voip-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_VOIP,
+ },
+ {
+ .name = MSM_DAILINK_NAME(ULL),
+ .stream_name = "MultiMedia3",
+ .cpu_dai_name = "MultiMedia3",
+ .platform_name = "msm-pcm-dsp.2",
+ .dynamic = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ },
+ /* Hostless PCM purpose */
+ {
+ .name = "SLIMBUS_0 Hostless",
+ .stream_name = "SLIMBUS_0 Hostless",
+ .cpu_dai_name = "SLIMBUS0_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "MSM AFE-PCM RX",
+ .stream_name = "AFE-PROXY RX",
+ .cpu_dai_name = "msm-dai-q6-dev.241",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .platform_name = "msm-pcm-afe",
+ .dpcm_playback = 1,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = "MSM AFE-PCM TX",
+ .stream_name = "AFE-PROXY TX",
+ .cpu_dai_name = "msm-dai-q6-dev.240",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .platform_name = "msm-pcm-afe",
+ .dpcm_capture = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress1),
+ .stream_name = "Compress1",
+ .cpu_dai_name = "MultiMedia4",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ },
+ {
+ .name = "AUXPCM Hostless",
+ .stream_name = "AUXPCM Hostless",
+ .cpu_dai_name = "AUXPCM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "SLIMBUS_1 Hostless",
+ .stream_name = "SLIMBUS_1 Hostless",
+ .cpu_dai_name = "SLIMBUS1_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "SLIMBUS_3 Hostless",
+ .stream_name = "SLIMBUS_3 Hostless",
+ .cpu_dai_name = "SLIMBUS3_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "SLIMBUS_4 Hostless",
+ .stream_name = "SLIMBUS_4 Hostless",
+ .cpu_dai_name = "SLIMBUS4_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = MSM_DAILINK_NAME(LowLatency),
+ .stream_name = "MultiMedia5",
+ .cpu_dai_name = "MultiMedia5",
+ .platform_name = "msm-pcm-dsp.1",
+ .dynamic = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+ .ops = &msm_mm5_ops,
+ },
+ {
+ .name = "Listen 1 Audio Service",
+ .stream_name = "Listen 1 Audio Service",
+ .cpu_dai_name = "LSM1",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM1,
+ },
+ /* Multiple Tunnel instances */
+ {
+ .name = MSM_DAILINK_NAME(Compress2),
+ .stream_name = "Compress2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress3),
+ .stream_name = "Compress3",
+ .cpu_dai_name = "MultiMedia10",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compr8),
+ .stream_name = "COMPR8",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
+ /* HDMI Hostless */
+ {
+ .name = "HDMI_RX_HOSTLESS",
+ .stream_name = "HDMI_RX_HOSTLESS",
+ .cpu_dai_name = "HDMI_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "VoiceMMode2",
+ .stream_name = "VoiceMMode2",
+ .cpu_dai_name = "VoiceMMode2",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE2,
+ },
+ /* LSM FE */
+ {
+ .name = "Listen 2 Audio Service",
+ .stream_name = "Listen 2 Audio Service",
+ .cpu_dai_name = "LSM2",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM2,
+ },
+ {
+ .name = "Listen 3 Audio Service",
+ .stream_name = "Listen 3 Audio Service",
+ .cpu_dai_name = "LSM3",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM3,
+ },
+ {
+ .name = "Listen 4 Audio Service",
+ .stream_name = "Listen 4 Audio Service",
+ .cpu_dai_name = "LSM4",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM4,
+ },
+ {
+ .name = "Listen 5 Audio Service",
+ .stream_name = "Listen 5 Audio Service",
+ .cpu_dai_name = "LSM5",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM5,
+ },
+ {
+ .name = "Listen 6 Audio Service",
+ .stream_name = "Listen 6 Audio Service",
+ .cpu_dai_name = "LSM6",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM6,
+ },
+ {
+ .name = "Listen 7 Audio Service",
+ .stream_name = "Listen 7 Audio Service",
+ .cpu_dai_name = "LSM7",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM7,
+ },
+ {
+ .name = "Listen 8 Audio Service",
+ .stream_name = "Listen 8 Audio Service",
+ .cpu_dai_name = "LSM8",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM8,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Media9),
+ .stream_name = "MultiMedia9",
+ .cpu_dai_name = "MultiMedia9",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress4),
+ .stream_name = "Compress4",
+ .cpu_dai_name = "MultiMedia11",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress5),
+ .stream_name = "Compress5",
+ .cpu_dai_name = "MultiMedia12",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress6),
+ .stream_name = "Compress6",
+ .cpu_dai_name = "MultiMedia13",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress7),
+ .stream_name = "Compress7",
+ .cpu_dai_name = "MultiMedia14",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress8),
+ .stream_name = "Compress8",
+ .cpu_dai_name = "MultiMedia15",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+ },
+ {
+ .name = MSM_DAILINK_NAME(Compress9),
+ .stream_name = "Compress9",
+ .cpu_dai_name = "MultiMedia16",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+ },
+};
+
+static struct snd_soc_dai_link msm_tasha_fe_dai_links[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_vifeedback",
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ /* Ultrasound RX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Playback",
+ .stream_name = "SLIMBUS_2 Hostless Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16388",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_rx2",
+ .ignore_suspend = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_slimbus_2_be_ops,
+ },
+ /* Ultrasound TX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Capture",
+ .stream_name = "SLIMBUS_2 Hostless Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16389",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx2",
+ .ignore_suspend = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_slimbus_2_be_ops,
+ },
+ /* CPE LSM direct dai-link */
+ {
+ .name = "CPE Listen service",
+ .stream_name = "CPE Listen Audio Service",
+ .cpu_dai_name = "msm-dai-slim",
+ .platform_name = "msm-cpe-lsm",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "tasha_mad1",
+ .codec_name = "tasha_codec",
+ .ops = &msm_cpe_ops,
+ },
+};
+
+static struct snd_soc_dai_link msm_common_be_dai_links[] = {
+ /* Backend AFE DAI Links */
+ {
+ .name = LPASS_BE_AFE_PCM_RX,
+ .stream_name = "AFE Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.224",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_TX,
+ .stream_name = "AFE Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.225",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE_PLAYBACK_TX,
+ .stream_name = "Voice Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32773",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music 2 BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE2_PLAYBACK_TX,
+ .stream_name = "Voice2 Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32770",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ }
+};
+
+static struct snd_soc_dai_link msm_tasha_be_dai_links[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm_audrx_init,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ops = &msm_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_RX,
+ .stream_name = "Slimbus1 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16386",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_TX,
+ .stream_name = "Slimbus1 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16387",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx3",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_RX,
+ .stream_name = "Slimbus3 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16390",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_TX,
+ .stream_name = "Slimbus3 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16391",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_4_RX,
+ .stream_name = "Slimbus4 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16392",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_5_RX,
+ .stream_name = "Slimbus5 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16394",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_rx3",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ /* MAD BE */
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mad1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_tasha_dai_links[
+ ARRAY_SIZE(msm_common_dai_links) +
+ ARRAY_SIZE(msm_tasha_fe_dai_links) +
+ ARRAY_SIZE(msm_common_be_dai_links) +
+ ARRAY_SIZE(msm_tasha_be_dai_links)];
+
+static int msm_snd_card_late_probe(struct snd_soc_card *card)
+{
+ const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+ struct snd_soc_pcm_runtime *rtd;
+ int ret = 0;
+ void *mbhc_calibration;
+
+ rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+ if (!rtd) {
+ dev_err(card->dev,
+ "%s: snd_soc_get_pcm_runtime for %s failed!\n",
+ __func__, be_dl_name);
+ ret = -EINVAL;
+ goto err_pcm_runtime;
+ }
+
+ tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
+
+ mbhc_calibration = def_tasha_mbhc_cal();
+ if (!mbhc_calibration) {
+ ret = -ENOMEM;
+ goto err_mbhc_cal;
+ }
+ wcd_mbhc_cfg.calibration = mbhc_calibration;
+ ret = tasha_mbhc_hs_detect(rtd->codec, &wcd_mbhc_cfg);
+ if (ret) {
+ dev_err(card->dev, "%s: mbhc hs detect failed, err:%d\n",
+ __func__, ret);
+ goto err_hs_detect;
+ }
+ return 0;
+
+err_hs_detect:
+ kfree(mbhc_calibration);
+err_mbhc_cal:
+err_pcm_runtime:
+ return ret;
+}
+
+struct snd_soc_card snd_soc_card_tasha_msm = {
+ .name = "msmcobalt-tasha-snd-card",
+ .late_probe = msm_snd_card_late_probe,
+};
+
+static int msm_populate_dai_link_component_of_node(
+ struct snd_soc_card *card)
+{
+ int i, index, ret = 0;
+ struct device *cdev = card->dev;
+ struct snd_soc_dai_link *dai_link = card->dai_link;
+ struct device_node *np;
+
+ if (!cdev) {
+ pr_err("%s: Sound card device memory NULL\n", __func__);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < card->num_links; i++) {
+ if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
+ continue;
+
+ /* populate platform_of_node for snd card dai links */
+ if (dai_link[i].platform_name &&
+ !dai_link[i].platform_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-platform-names",
+ dai_link[i].platform_name);
+ if (index < 0) {
+ pr_err("%s: No match found for platform name: %s\n",
+ __func__, dai_link[i].platform_name);
+ ret = index;
+ goto err;
+ }
+ np = of_parse_phandle(cdev->of_node, "asoc-platform",
+ index);
+ if (!np) {
+ pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
+ __func__, dai_link[i].platform_name,
+ index);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].platform_of_node = np;
+ dai_link[i].platform_name = NULL;
+ }
+
+ /* populate cpu_of_node for snd card dai links */
+ if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-cpu-names",
+ dai_link[i].cpu_dai_name);
+ if (index >= 0) {
+ np = of_parse_phandle(cdev->of_node, "asoc-cpu",
+ index);
+ if (!np) {
+ pr_err("%s: retrieving phandle for cpu dai %s failed\n",
+ __func__,
+ dai_link[i].cpu_dai_name);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].cpu_of_node = np;
+ dai_link[i].cpu_dai_name = NULL;
+ }
+ }
+
+ /* populate codec_of_node for snd card dai links */
+ if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-codec-names",
+ dai_link[i].codec_name);
+ if (index < 0)
+ continue;
+ np = of_parse_phandle(cdev->of_node, "asoc-codec",
+ index);
+ if (!np) {
+ pr_err("%s: retrieving phandle for codec %s failed\n",
+ __func__, dai_link[i].codec_name);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].codec_of_node = np;
+ dai_link[i].codec_name = NULL;
+ }
+ }
+
+err:
+ return ret;
+}
+
+static int msm_prepare_us_euro(struct snd_soc_card *card)
+{
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+ int ret = 0;
+
+ if (pdata->us_euro_gpio >= 0) {
+ dev_dbg(card->dev, "%s: us_euro gpio request %d", __func__,
+ pdata->us_euro_gpio);
+ ret = gpio_request(pdata->us_euro_gpio, "TASHA_CODEC_US_EURO");
+ if (ret) {
+ dev_err(card->dev,
+ "%s: Failed to request codec US/EURO gpio %d error %d\n",
+ __func__, pdata->us_euro_gpio, ret);
+ }
+ }
+
+ return ret;
+}
+
+static int msm_prepare_hifi(struct snd_soc_card *card)
+{
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+ int ret = 0;
+
+ if (gpio_is_valid(pdata->hph_en1_gpio)) {
+ dev_dbg(card->dev, "%s: hph_en1_gpio request %d\n", __func__,
+ pdata->hph_en1_gpio);
+ ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
+ if (ret) {
+ dev_err(card->dev,
+ "%s: hph_en1_gpio request failed, ret:%d\n",
+ __func__, ret);
+ goto err;
+ }
+ }
+ if (gpio_is_valid(pdata->hph_en0_gpio)) {
+ dev_dbg(card->dev, "%s: hph_en0_gpio request %d\n", __func__,
+ pdata->hph_en0_gpio);
+ ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
+ if (ret)
+ dev_err(card->dev,
+ "%s: hph_en0_gpio request failed, ret:%d\n",
+ __func__, ret);
+ }
+
+err:
+ return ret;
+}
+
+static const struct of_device_id msmcobalt_asoc_machine_of_match[] = {
+ { .compatible = "qcom,msmcobalt-asoc-snd-tasha",
+ .data = "tasha_codec"},
+ {},
+};
+
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+ struct snd_soc_card *card = NULL;
+ struct snd_soc_dai_link *dailink;
+ int len_1, len_2, len_3, len_4;
+ const struct of_device_id *match;
+
+ match = of_match_node(msmcobalt_asoc_machine_of_match, dev->of_node);
+ if (!match) {
+ dev_err(dev, "%s: No DT match found for sound card\n",
+ __func__);
+ return NULL;
+ }
+
+ if (!strcmp(match->data, "tasha_codec")) {
+ card = &snd_soc_card_tasha_msm;
+ len_1 = ARRAY_SIZE(msm_common_dai_links);
+ len_2 = len_1 + ARRAY_SIZE(msm_tasha_fe_dai_links);
+ len_3 = len_2 + ARRAY_SIZE(msm_common_be_dai_links);
+
+ memcpy(msm_tasha_dai_links,
+ msm_common_dai_links,
+ sizeof(msm_common_dai_links));
+ memcpy(msm_tasha_dai_links + len_1,
+ msm_tasha_fe_dai_links,
+ sizeof(msm_tasha_fe_dai_links));
+ memcpy(msm_tasha_dai_links + len_2,
+ msm_common_be_dai_links,
+ sizeof(msm_common_be_dai_links));
+ memcpy(msm_tasha_dai_links + len_3,
+ msm_tasha_be_dai_links,
+ sizeof(msm_tasha_be_dai_links));
+
+ dailink = msm_tasha_dai_links;
+ len_4 = len_3 + ARRAY_SIZE(msm_tasha_be_dai_links);
+ }
+ dev_dbg(dev, "%s(): No hdmi audio support\n", __func__);
+
+ if (card) {
+ card->dai_link = dailink;
+ card->num_links = len_4;
+ }
+
+ return card;
+}
+
+static int msm_wsa881x_init(struct snd_soc_component *component)
+{
+ u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106};
+ u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107};
+ unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200};
+ unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
+ struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
+ struct msm_asoc_mach_data *pdata;
+ struct snd_soc_dapm_context *dapm;
+ int ret = 0;
+
+ if (!codec) {
+ pr_err("%s codec is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ dapm = snd_soc_codec_get_dapm(codec);
+
+ if (!strcmp(component->name_prefix, "SpkrLeft")) {
+ dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n",
+ __func__, codec->component.name);
+ wsa881x_set_channel_map(codec, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0]);
+ if (dapm->component) {
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
+ }
+ } else if (!strcmp(component->name_prefix, "SpkrRight")) {
+ dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n",
+ __func__, codec->component.name);
+ wsa881x_set_channel_map(codec, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0]);
+ if (dapm->component) {
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
+ }
+ } else {
+ dev_err(codec->dev, "%s: wrong codec name %s\n", __func__,
+ codec->component.name);
+ ret = -EINVAL;
+ goto err_codec;
+ }
+ pdata = snd_soc_card_get_drvdata(component->card);
+ if (pdata && pdata->codec_root)
+ wsa881x_codec_info_create_codec_entry(pdata->codec_root,
+ codec);
+
+err_codec:
+ return ret;
+}
+
+static int msm_init_wsa_dev(struct platform_device *pdev,
+ struct snd_soc_card *card)
+{
+ struct device_node *wsa_of_node;
+ u32 wsa_max_devs;
+ u32 wsa_dev_cnt;
+ int i;
+ struct msm_wsa881x_dev_info *wsa881x_dev_info;
+ const char *wsa_auxdev_name_prefix[1];
+ char *dev_name_str = NULL;
+ int found = 0;
+ int ret = 0;
+
+ /* Get maximum WSA device count for this platform */
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,wsa-max-devs", &wsa_max_devs);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
+ __func__, pdev->dev.of_node->full_name, ret);
+ goto err_dt;
+ }
+ if (wsa_max_devs == 0) {
+ dev_warn(&pdev->dev,
+ "%s: Max WSA devices is 0 for this target?\n",
+ __func__);
+ goto err_dt;
+ }
+
+ /* Get count of WSA device phandles for this platform */
+ wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
+ "qcom,wsa-devs", NULL);
+ if (wsa_dev_cnt == -ENOENT) {
+ dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
+ __func__);
+ goto err_dt;
+ } else if (wsa_dev_cnt <= 0) {
+ dev_err(&pdev->dev,
+ "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
+ __func__, wsa_dev_cnt);
+ ret = -EINVAL;
+ goto err_dt;
+ }
+
+ /*
+ * Expect total phandles count to be NOT less than maximum possible
+ * WSA count. However, if it is less, then assign same value to
+ * max count as well.
+ */
+ if (wsa_dev_cnt < wsa_max_devs) {
+ dev_dbg(&pdev->dev,
+ "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
+ __func__, wsa_max_devs, wsa_dev_cnt);
+ wsa_max_devs = wsa_dev_cnt;
+ }
+
+ /* Make sure prefix string passed for each WSA device */
+ ret = of_property_count_strings(pdev->dev.of_node,
+ "qcom,wsa-aux-dev-prefix");
+ if (ret != wsa_dev_cnt) {
+ dev_err(&pdev->dev,
+ "%s: expecting %d wsa prefix. Defined only %d in DT\n",
+ __func__, wsa_dev_cnt, ret);
+ ret = -EINVAL;
+ goto err_dt;
+ }
+
+ /*
+ * Alloc mem to store phandle and index info of WSA device, if already
+ * registered with ALSA core
+ */
+ wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
+ sizeof(struct msm_wsa881x_dev_info),
+ GFP_KERNEL);
+ if (!wsa881x_dev_info) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ /*
+ * search and check whether all WSA devices are already
+ * registered with ALSA core or not. If found a node, store
+ * the node and the index in a local array of struct for later
+ * use.
+ */
+ for (i = 0; i < wsa_dev_cnt; i++) {
+ wsa_of_node = of_parse_phandle(pdev->dev.of_node,
+ "qcom,wsa-devs", i);
+ if (unlikely(!wsa_of_node)) {
+ /* we should not be here */
+ dev_err(&pdev->dev,
+ "%s: wsa dev node is not present\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_dev_node;
+ }
+ if (soc_find_component(wsa_of_node, NULL)) {
+ /* WSA device registered with ALSA core */
+ wsa881x_dev_info[found].of_node = wsa_of_node;
+ wsa881x_dev_info[found].index = i;
+ found++;
+ if (found == wsa_max_devs)
+ break;
+ }
+ }
+
+ if (found < wsa_max_devs) {
+ dev_dbg(&pdev->dev,
+ "%s: failed to find %d components. Found only %d\n",
+ __func__, wsa_max_devs, found);
+ return -EPROBE_DEFER;
+ }
+ dev_info(&pdev->dev,
+ "%s: found %d wsa881x devices registered with ALSA core\n",
+ __func__, found);
+
+ card->num_aux_devs = wsa_max_devs;
+ card->num_configs = wsa_max_devs;
+
+ /* Alloc array of AUX devs struct */
+ msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
+ sizeof(struct snd_soc_aux_dev),
+ GFP_KERNEL);
+ if (!msm_aux_dev) {
+ ret = -ENOMEM;
+ goto err_auxdev_mem;
+ }
+
+ /* Alloc array of codec conf struct */
+ msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
+ sizeof(struct snd_soc_codec_conf),
+ GFP_KERNEL);
+ if (!msm_codec_conf) {
+ ret = -ENOMEM;
+ goto err_codec_conf;
+ }
+
+ for (i = 0; i < card->num_aux_devs; i++) {
+ dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
+ GFP_KERNEL);
+ if (!dev_name_str) {
+ ret = -ENOMEM;
+ goto err_dev_str;
+ }
+
+ ret = of_property_read_string_index(pdev->dev.of_node,
+ "qcom,wsa-aux-dev-prefix",
+ wsa881x_dev_info[i].index,
+ wsa_auxdev_name_prefix);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: failed to read wsa aux dev prefix, ret = %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ goto err_dt_prop;
+ }
+
+ snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
+ msm_aux_dev[i].name = dev_name_str;
+ msm_aux_dev[i].codec_name = NULL;
+ msm_aux_dev[i].codec_of_node =
+ wsa881x_dev_info[i].of_node;
+ msm_aux_dev[i].init = msm_wsa881x_init;
+ msm_codec_conf[i].dev_name = NULL;
+ msm_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0];
+ msm_codec_conf[i].of_node =
+ wsa881x_dev_info[i].of_node;
+ }
+ card->codec_conf = msm_codec_conf;
+ card->aux_dev = msm_aux_dev;
+
+ return 0;
+
+err_dt_prop:
+ devm_kfree(&pdev->dev, dev_name_str);
+err_dev_str:
+ devm_kfree(&pdev->dev, msm_codec_conf);
+err_codec_conf:
+ devm_kfree(&pdev->dev, msm_aux_dev);
+err_auxdev_mem:
+err_dev_node:
+ devm_kfree(&pdev->dev, wsa881x_dev_info);
+err_mem:
+err_dt:
+ return ret;
+}
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card;
+ struct msm_asoc_mach_data *pdata;
+ const char *mbhc_audio_jack_type = NULL;
+ char *mclk_freq_prop_name;
+ const struct of_device_id *match;
+ int ret;
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev, "No platform supplied from device tree\n");
+ return -EINVAL;
+ }
+
+ pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ card = populate_snd_card_dailinks(&pdev->dev);
+ if (!card) {
+ dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, pdata);
+
+ ret = snd_soc_of_parse_card_name(card, "qcom,model");
+ if (ret) {
+ dev_err(&pdev->dev, "parse card name failed, err:%d\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+ if (ret) {
+ dev_err(&pdev->dev, "parse audio routing failed, err:%d\n",
+ ret);
+ goto err;
+ }
+
+ match = of_match_node(msmcobalt_asoc_machine_of_match,
+ pdev->dev.of_node);
+ if (!match) {
+ dev_err(&pdev->dev, "%s: no matched codec is found.\n",
+ __func__);
+ goto err;
+ }
+
+ mclk_freq_prop_name = "qcom,tasha-mclk-clk-freq";
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ mclk_freq_prop_name, &pdata->mclk_freq);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Looking up %s property in node %s failed, err%d\n",
+ mclk_freq_prop_name,
+ pdev->dev.of_node->full_name, ret);
+ goto err;
+ }
+
+ if (pdata->mclk_freq != CODEC_EXT_CLK_RATE) {
+ dev_err(&pdev->dev, "unsupported mclk freq %u\n",
+ pdata->mclk_freq);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ spdev = pdev;
+
+ ret = msm_populate_dai_link_component_of_node(card);
+ if (ret) {
+ ret = -EPROBE_DEFER;
+ goto err;
+ }
+ ret = msm_init_wsa_dev(pdev, card);
+ if (ret)
+ goto err;
+
+ pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,hph-en1-gpio", 0);
+ if (pdata->hph_en1_gpio < 0) {
+ dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
+ __func__, "qcom,hph-en1-gpio", pdata->hph_en1_gpio);
+ }
+
+ pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,hph-en0-gpio", 0);
+ if (pdata->hph_en0_gpio < 0) {
+ dev_dbg(&pdev->dev, "%s: %s property not found %d\n",
+ __func__, "qcom,hph-en0-gpio", pdata->hph_en0_gpio);
+ }
+ ret = msm_prepare_hifi(card);
+ if (ret)
+ dev_dbg(&pdev->dev, "msm_prepare_hifi failed (%d)\n",
+ ret);
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret == -EPROBE_DEFER) {
+ if (codec_reg_done)
+ ret = -EINVAL;
+ goto err;
+ } else if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err;
+ }
+ dev_info(&pdev->dev, "Sound card %s registered\n", card->name);
+
+ ret = of_property_read_string(pdev->dev.of_node,
+ "qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
+ if (ret) {
+ dev_dbg(&pdev->dev, "Looking up %s property in node %s failed",
+ "qcom,mbhc-audio-jack-type",
+ pdev->dev.of_node->full_name);
+ dev_dbg(&pdev->dev, "Jack type properties set to default");
+ } else {
+ if (!strcmp(mbhc_audio_jack_type, "4-pole-jack"))
+ dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
+ else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack"))
+ dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
+ else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack"))
+ dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
+ else
+ dev_dbg(&pdev->dev, "Unknown value, set to default");
+ }
+ /*
+ * Parse US-Euro gpio info from DT. Report no error if us-euro
+ * entry is not found in DT file as some targets do not support
+ * US-Euro detection
+ */
+ pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,us-euro-gpios", 0);
+ if (pdata->us_euro_gpio < 0) {
+ dev_info(&pdev->dev, "property %s not detected in node %s",
+ "qcom,us-euro-gpios",
+ pdev->dev.of_node->full_name);
+ } else {
+ dev_dbg(&pdev->dev, "%s detected %d",
+ "qcom,us-euro-gpios", pdata->us_euro_gpio);
+ wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
+ }
+
+ ret = msm_prepare_us_euro(card);
+ if (ret)
+ dev_info(&pdev->dev, "msm_prepare_us_euro failed (%d)\n",
+ ret);
+ return 0;
+err:
+ if (pdata->us_euro_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
+ __func__, pdata->us_euro_gpio);
+ gpio_free(pdata->us_euro_gpio);
+ pdata->us_euro_gpio = 0;
+ }
+ if (pdata->hph_en1_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free hph_en1_gpio %d\n",
+ __func__, pdata->hph_en1_gpio);
+ gpio_free(pdata->hph_en1_gpio);
+ pdata->hph_en1_gpio = 0;
+ }
+ if (pdata->hph_en0_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free hph_en0_gpio %d\n",
+ __func__, pdata->hph_en0_gpio);
+ gpio_free(pdata->hph_en0_gpio);
+ pdata->hph_en0_gpio = 0;
+ }
+ devm_kfree(&pdev->dev, pdata);
+ return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+
+ gpio_free(pdata->us_euro_gpio);
+ gpio_free(pdata->hph_en1_gpio);
+ gpio_free(pdata->hph_en0_gpio);
+
+ snd_soc_unregister_card(card);
+ return 0;
+}
+
+static struct platform_driver msmcobalt_asoc_machine_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = msmcobalt_asoc_machine_of_match,
+ },
+ .probe = msm_asoc_machine_probe,
+ .remove = msm_asoc_machine_remove,
+};
+module_platform_driver(msmcobalt_asoc_machine_driver);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, msmcobalt_asoc_machine_of_match);