Merge "clk: msm: gcc: Add support for clocks for SDM632"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 9bc8168..d150116 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -328,6 +328,9 @@
compatible = "qcom,sdm450-cdp"
compatible = "qcom,sdm450-qrd"
compatible = "qcom,sdm632-rumi"
+compatible = "qcom,sdm632-cdp"
+compatible = "qcom,sdm632-mtp"
+compatible = "qcom,sdm632-qrd"
compatible = "qcom,mdm9640-cdp"
compatible = "qcom,mdm9640-mtp"
compatible = "qcom,mdm9640-rumi"
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
index 07667a4..8d6fad0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
@@ -31,6 +31,7 @@
* "qcom,pdc-sdm845": For sdm845 pin data
* "qcom,pdc-sdm845-v2": For sdm845 v2 pin data
* "qcom,pdc-sdm670": For sdm670 pin data
+ * "qcom,pdc-sdxpoorwills": For sdxpoorwills pin data
- reg:
Usage: required
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
index b7ce662..1a76d5d 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
@@ -118,6 +118,18 @@
Following properties are specific only to LRA vibrators.
+- qcom,lra-auto-mode
+ Usage: optional
+ Value type: <empty>
+ Definition: If specified, a set of pre-configured settings will be applied
+ based on the pattern duration. For example, for a duration of
+ < 20 ms (short duration), one set of settings will be applied
+ and for a duration of >= 20 ms (long duration), another set of
+ settings will be applied. The parameters configured in the
+ driver when this property is specified is based on the LRA
+ tested internally. Those parameters should be fine-tuned or
+ adjusted based on the LRA used on different hardware platforms.
+
- qcom,lra-auto-res-mode
Usage: optional
Value type: <string>
@@ -200,9 +212,13 @@
- qcom,wave-samples
Usage: optional
Value type: <prop-encoded-array>
- Definition: Wave samples in an array of 8 elements. Each element takes the
+ Definition: Wave samples in an array of 32 elements. Each element takes the
following representation, bit 0: unused, bits[5:1] : amplitude,
bit 6: overdrive, bit 7: sign. Default sample value is 0x3E.
+ Since the hardware supports configuring upto 8 samples, a set
+ of 8 samples will be configured initially and the next set will
+ be configured upon the play interrupt until all the samples are
+ configured and played.
Following properties are applicable only when "qcom,play-mode" is set to
"pwm".
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt
new file mode 100644
index 0000000..f697704
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt
@@ -0,0 +1,204 @@
+Qualcomm Technologies, Inc. MSM8937 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8937 platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be "qcom,msm8937-pinctrl"
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+ Usage: required
+ Value type: <none>
+ Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: must be 2. Specifying the pin number and flags, as defined
+ in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+ Usage: required
+ Value type: <string-array>
+ Definition: List of gpio pins affected by the properties specified in
+ this subnode.
+ Valid pins are:
+ gpio0-gpio133,
+ sdc1_clk,
+ sdc1_cmd,
+ sdc1_data,
+ sdc1_rclk,
+ sdc2_clk,
+ sdc2_cmd,
+ sdc2_data,
+ qdsd_clk,
+ qdsd_cmd,
+ qdsd_data0,
+ qdsd_data1,
+ qdsd_data2,
+ qdsd_data3,
+
+- function:
+ Usage: required
+ Value type: <string>
+ Definition: Specify the alternative function to be configured for the
+ specified pins. Functions are only valid for gpio pins.
+ Valid values are:
+ qdss_tracedata_b, blsp_uart1, gpio, blsp_spi1, adsp_ext, blsp_i2c1, prng_rosc,
+ qdss_cti_trig_out_b0, blsp_spi2, blsp_uart2, blsp_uart3, pbs0, pbs1,
+ pwr_modem_enabled_b, blsp_i2c3, gcc_gp2_clk_b, ldo_update,
+ atest_combodac_to_gpio_native, ldo_en, blsp_i2c2, gcc_gp1_clk_b, pbs2,
+ atest_gpsadc_dtest0_native, blsp_spi3, gcc_gp3_clk_b, blsp_spi4, blsp_uart4,
+ sec_mi2s, pwr_nav_enabled_b, codec_mad, pwr_crypto_enabled_b, blsp_i2c4,
+ blsp_spi5, blsp_uart5, qdss_traceclk_a, atest_bbrx1, m_voc,
+ qdss_cti_trig_in_a0, qdss_cti_trig_in_b0, blsp_i2c6, qdss_traceclk_b,
+ atest_wlan0, atest_wlan1, atest_bbrx0, blsp_i2c5, qdss_tracectl_a,
+ atest_gpsadc_dtest1_native, qdss_tracedata_a, blsp_spi6, blsp_uart6,
+ qdss_tracectl_b, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a, cam_mclk,
+ cci_i2c, pwr_modem_enabled_a, cci_timer0, cci_timer1, cam1_standby,
+ pwr_nav_enabled_a, cam1_rst, pwr_crypto_enabled_a, forced_usb,
+ qdss_cti_trig_out_b1, cam2_rst, webcam_standby, cci_async, webcam_rst,
+ ov_ldo, sd_write, accel_int, gcc_gp1_clk_a, alsp_int, gcc_gp2_clk_a,
+ mag_int, gcc_gp3_clk_a, blsp6_spi, fp_int, qdss_cti_trig_in_b1, uim_batt,
+ cam2_standby, uim1_data, uim1_clk, uim1_reset, uim1_present, uim2_data,
+ uim2_clk, uim2_reset, uim2_present, sensor_rst, mipi_dsi0, smb_int,
+ cam0_ldo, us_euro, atest_char3, dbg_out, bimc_dte0, ts_resout, ts_sample,
+ sec_mi2s_mclk_b, pri_mi2s, sdcard_det, atest_char1, ebi_cdc, audio_reset,
+ atest_char0, audio_ref, cdc_pdm0, pri_mi2s_mclk_b, lpass_slimbus,
+ lpass_slimbus0, lpass_slimbus1, codec_int1, codec_int2, wcss_bt,
+ atest_char2, ebi_ch0, wcss_wlan2, wcss_wlan1, wcss_wlan0, wcss_wlan,
+ wcss_fm, ext_lpass, cri_trng, cri_trng1, cri_trng0, blsp_spi7, blsp_uart7,
+ pri_mi2s_ws, blsp_i2c7, gcc_tlmm, dmic0_clk, dmic0_data, key_volp,
+ qdss_cti_trig_in_a1, us_emitter, wsa_irq, wsa_io, wsa_reset, blsp_spi8,
+ blsp_uart8, blsp_i2c8, gcc_plltest, nav_pps_in_a, pa_indicator, modem_tsync,
+ nav_tsync, nav_pps_in_b, nav_pps, gsm0_tx, atest_char, atest_tsens,
+ bimc_dte1, ssbi_wtr1, fp_gpio, coex_uart, key_snapshot, key_focus, nfc_pwr,
+ blsp8_spi, qdss_cti_trig_out_a0, qdss_cti_trig_out_a1
+
+- bias-disable:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins should be configued as pull up.
+
+- output-high:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ high.
+ Not valid for sdc pins.
+
+- output-low:
+ Usage: optional
+ Value type: <none>
+ Definition: The specified pins are configured in output mode, driven
+ low.
+ Not valid for sdc pins.
+
+- drive-strength:
+ Usage: optional
+ Value type: <u32>
+ Definition: Selects the drive strength for the specified pins, in mA.
+ Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8937-pinctrl";
+ reg = <0x1000000 0x300000>;
+ interrupts = <0 208 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ pmx-uartconsole {
+ uart_console_active: uart_console_active {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ uart_console_sleep: uart_console_sleep {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index f50fd88..75996a5 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -104,6 +104,13 @@
this property is not specified, then the default value used
will be 75mA.
+- qcom,fg-cutoff-current
+ Usage: optional
+ Value type: <u32>
+ Definition: Minimum Battery current (in mA) used for cutoff SOC
+ estimate. If this property is not specified, then a default
+ value of 500 mA will be applied.
+
- qcom,fg-delta-soc-thr
Usage: optional
Value type: <u32>
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index be8c2f0..e64599c 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -74,9 +74,11 @@
Required properties:
- compatible : Must be "qcom,msm-adsprpc-mem-region"
- memory-region : CMA region which is owned by this device
+- restrict-access : Blocking vote for hyp_assign_phys function call
Example:
qcom,adsprpc-mem {
compatible = "qcom,msm-adsprpc-mem-region";
memory-region = <&adsp_mem>;
+ restrict-access;
};
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index f8c8a69..f7f4ced 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -184,6 +184,10 @@
state when attached in host mode and "suspend" state when detached.
- qcom,tune2-efuse-correction: The value to be adjusted from fused value for
improved rise/fall times.
+ - nvmem-cells: specifies the handle to represent the SoC revision.
+ usually it is defined by qfprom device node.
+ - nvmem-cell-names: specifies the given nvmem cell name as defined in
+ qfprom node.
Example:
qusb_phy: qusb@f9b39000 {
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d8d8b82..41245ce 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -12,6 +12,7 @@
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANT_IPC_PARSE_VERSION
+ select ARM_PSCI_FW if PM
select BUILDTIME_EXTABLE_SORT if MMU
select CLONE_BACKWARDS
select CPU_PM if (SUSPEND || CPU_IDLE)
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
new file mode 100644
index 0000000..f8baa04
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
@@ -0,0 +1,1070 @@
+/* Copyright (c) 2018, 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 {
+ csr: csr@6001000 {
+ compatible = "qcom,coresight-csr";
+ reg = <0x6001000 0x1000>;
+ reg-names = "csr-base";
+
+ coresight-name = "coresight-csr";
+
+ qcom,blk-size = <1>;
+ };
+
+ tmc_etr: tmc@6048000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b961>;
+
+ reg = <0x6048000 0x1000>,
+ <0x6064000 0x15000>;
+ reg-names = "tmc-base", "bam-base";
+
+ arm,buffer-size = <0x400000>;
+ arm,sg-enable;
+
+ coresight-name = "coresight-tmc-etr";
+ coresight-ctis = <&cti0 &cti8>;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ interrupts = <GIC_SPI 251 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "byte-cntr-irq";
+
+ port {
+ tmc_etr_in_replicator: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out_tmc_etr>;
+ };
+ };
+ };
+
+ replicator_qdss: replicator@6046000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b909>;
+
+ reg = <0x6046000 0x1000>;
+ reg-names = "replicator-base";
+
+ coresight-name = "coresight-replicator";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ replicator_out_tmc_etr: endpoint {
+ remote-endpoint=
+ <&tmc_etr_in_replicator>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ replicator_in_tmc_etf: endpoint {
+ slave-mode;
+ remote-endpoint=
+ <&tmc_etf_out_replicator>;
+ };
+ };
+ };
+ };
+
+ tmc_etf: tmc@6047000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b961>;
+
+ reg = <0x6047000 0x1000>;
+ reg-names = "tmc-base";
+
+ coresight-name = "coresight-tmc-etf";
+ coresight-ctis = <&cti0 &cti8>;
+ arm,default-sink;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ tmc_etf_out_replicator: endpoint {
+ remote-endpoint =
+ <&replicator_in_tmc_etf>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ tmc_etf_in_funnel_merg: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_merg_out_tmc_etf>;
+ };
+ };
+ };
+ };
+
+ funnel_merg: funnel@6045000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6045000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-merg";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_merg_out_tmc_etf: endpoint {
+ remote-endpoint =
+ <&tmc_etf_in_funnel_merg>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ funnel_merg_in_funnel_in0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_in0_out_funnel_merg>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ funnel_merg_in_funnel_in1: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_in1_out_funnel_merg>;
+ };
+ };
+ };
+ };
+
+ funnel_in0: funnel@6041000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6041000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-in0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_in0_out_funnel_merg: endpoint {
+ remote-endpoint =
+ <&funnel_merg_in_funnel_in0>;
+ };
+ };
+
+ port@1 {
+ reg = <6>;
+ funnel_in0_in_funnel_qatb: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_qatb_out_funnel_in0>;
+ };
+ };
+
+ port@2 {
+ reg = <7>;
+ funnel_in0_in_stm: endpoint {
+ slave-mode;
+ remote-endpoint = <&stm_out_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ stm: stm@6002000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b962>;
+
+ reg = <0x6002000 0x1000>,
+ <0x16280000 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ coresight-name = "coresight-stm";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port {
+ stm_out_funnel_in0: endpoint {
+ remote-endpoint = <&funnel_in0_in_stm>;
+ };
+ };
+
+ };
+
+ funnel_qatb: funnel@6005000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6005000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-qatb";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_qatb_out_funnel_in0: endpoint {
+ remote-endpoint =
+ <&funnel_in0_in_funnel_qatb>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ funnel_qatb_in_tpda: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpda_out_funnel_qatb>;
+ };
+ };
+ };
+ };
+
+ tpda: tpda@6004000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
+ reg = <0x6004000 0x1000>;
+ reg-names = "tpda-base";
+
+ coresight-name = "coresight-tpda";
+
+ qcom,tpda-atid = <65>;
+ qcom,bc-elem-size = <10 32>,
+ <13 32>;
+ qcom,tc-elem-size = <13 32>;
+ qcom,dsb-elem-size = <0 32>,
+ <2 32>,
+ <3 32>,
+ <5 32>,
+ <6 32>,
+ <10 32>,
+ <11 32>,
+ <13 32>;
+ qcom,cmb-elem-size = <3 64>,
+ <7 64>,
+ <9 64>,
+ <13 64>;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ tpda_out_funnel_qatb: endpoint {
+ remote-endpoint =
+ <&funnel_qatb_in_tpda>;
+ };
+
+ };
+
+ port@1 {
+ reg = <0>;
+ tpda_in_funnel_ddr_0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_ddr_0_out_tpda>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ tpda_in_tpdm_vsense: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_vsense_out_tpda>;
+ };
+ };
+
+ port@3 {
+ reg = <2>;
+ tpda_in_tpdm_dcc: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_dcc_out_tpda>;
+ };
+ };
+
+ port@4 {
+ reg = <5>;
+ tpda_in_tpdm_center: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_center_out_tpda>;
+ };
+ };
+ };
+ };
+
+ funnel_ddr_0: funnel@69e2000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x69e2000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-ddr-0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_ddr_0_out_tpda: endpoint {
+ remote-endpoint =
+ <&tpda_in_funnel_ddr_0>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ funnel_ddr_0_in_tpdm_ddr: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_ddr_out_funnel_ddr_0>;
+ };
+ };
+ };
+ };
+
+ tpdm_dcc: tpdm@6870280 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x6870280 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-dcc";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port{
+ tpdm_dcc_out_tpda: endpoint {
+ remote-endpoint = <&tpda_in_tpdm_dcc>;
+ };
+ };
+ };
+
+ tpdm_vsense: tpdm@6840000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x6840000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-vsense";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port{
+ tpdm_vsense_out_tpda: endpoint {
+ remote-endpoint = <&tpda_in_tpdm_vsense>;
+ };
+ };
+ };
+
+ tpdm_center: tpdm@6c28000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x6c28000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-center";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port{
+ tpdm_center_out_tpda: endpoint {
+ remote-endpoint = <&tpda_in_tpdm_center>;
+ };
+ };
+ };
+
+ tpdm_ddr: tpdm@69e0000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x69e0000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-ddr";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ qcom,msr-fix-req;
+
+ port {
+ tpdm_ddr_out_funnel_ddr_0: endpoint {
+ remote-endpoint = <&funnel_ddr_0_in_tpdm_ddr>;
+ };
+ };
+ };
+
+ funnel_in1: funnel@6042000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6042000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-in1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_in1_out_funnel_merg: endpoint {
+ remote-endpoint =
+ <&funnel_merg_in_funnel_in1>;
+ };
+ };
+
+ port@1 {
+ reg = <2>;
+ funnel_in1_in_funnel_swao: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_swao_out_funnel_in1>;
+ };
+ };
+
+ port@2 {
+ reg = <3>;
+ funnel_in1_in_modem_etm0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&modem_etm0_out_funnel_in1>;
+ };
+ };
+
+ port@3 {
+ reg = <7>;
+ funnel_in1_in_tpda_modem: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpda_modem_out_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-remote-etm";
+
+ coresight-name = "coresight-modem-etm0";
+ qcom,inst-id = <2>;
+
+ port {
+ modem_etm0_out_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel_in1_in_modem_etm0>;
+ };
+ };
+ };
+
+ funnel_swao:funnel@6b08000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6b08000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-swao";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_swao_out_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel_in1_in_funnel_swao>;
+ };
+ };
+
+ port@1 {
+ reg = <7>;
+ funnel_swao_in_tpda_swao: endpoint {
+ slave-mode;
+ remote-endpoint=
+ <&tpda_swao_out_funnel_swao>;
+ };
+ };
+ };
+ };
+
+ tpda_modem: tpda@6832000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
+ reg = <0x6832000 0x1000>;
+ reg-names = "tpda-base";
+
+ coresight-name = "coresight-tpda-modem";
+
+ qcom,tpda-atid = <67>;
+ qcom,dsb-elem-size = <0 32>;
+ qcom,cmb-elem-size = <0 64>;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ tpda_modem_out_funnel_in1: endpoint {
+ remote-endpoint =
+ <&funnel_in1_in_tpda_modem>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ tpda_modem_in_tpdm_modem: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_modem_out_tpda_modem>;
+ };
+ };
+ };
+ };
+
+ tpdm_modem: tpdm@6830000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x6830000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-modem";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port {
+ tpdm_modem_out_tpda_modem: endpoint {
+ remote-endpoint = <&tpda_modem_in_tpdm_modem>;
+ };
+ };
+ };
+
+ tpda_swao: tpda@6b01000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
+ reg = <0x6b01000 0x1000>;
+ reg-names = "tpda-base";
+
+ coresight-name = "coresight-tpda-swao";
+
+ qcom,tpda-atid = <71>;
+ qcom,dsb-elem-size = <1 32>;
+ qcom,cmb-elem-size = <0 64>;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ tpda_swao_out_funnel_swao: endpoint {
+ remote-endpoint =
+ <&funnel_swao_in_tpda_swao>;
+ };
+
+ };
+
+ port@1 {
+ reg = <0>;
+ tpda_swao_in_tpdm_swao0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_swao0_out_tpda_swao>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ tpda_swao_in_tpdm_swao1: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_swao1_out_tpda_swao>;
+ };
+
+ };
+ };
+ };
+
+ tpdm_swao0: tpdm@6b02000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+
+ reg = <0x6b02000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-swao-0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ port {
+ tpdm_swao0_out_tpda_swao: endpoint {
+ remote-endpoint = <&tpda_swao_in_tpdm_swao0>;
+ };
+ };
+ };
+
+ tpdm_swao1: tpdm@6b03000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
+ reg = <0x6b03000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name="coresight-tpdm-swao-1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ qcom,msr-fix-req;
+
+ port {
+ tpdm_swao1_out_tpda_swao: endpoint {
+ remote-endpoint = <&tpda_swao_in_tpdm_swao1>;
+ };
+ };
+ };
+
+ ipcb_tgu: tgu@6b0c000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b999>;
+ reg = <0x6b0c000 0x1000>;
+ reg-names = "tgu-base";
+ tgu-steps = <3>;
+ tgu-conditions = <4>;
+ tgu-regs = <4>;
+ tgu-timer-counters = <8>;
+
+ coresight-name = "coresight-tgu-ipcb";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti0: cti@6010000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6010000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti1: cti@6011000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6011000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti2: cti@6012000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6012000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti2";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti3: cti@6013000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6013000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti3";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti4: cti@6014000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6014000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti4";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti5: cti@6015000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6015000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti5";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti6: cti@6016000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6016000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti6";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti7: cti@6017000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6017000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti7";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti8: cti@6018000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6018000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti8";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti9: cti@6019000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6019000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti9";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti10: cti@601a000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601a000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti10";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti11: cti@601b000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601b000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti11";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti12: cti@601c000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601c000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti12";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti13: cti@601d000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti13";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti14: cti@601e000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601e000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti14";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti15: cti@601f000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x601f000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti15";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti_cpu0: cti@7003000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x7003000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-cpu0";
+ cpu = <&CPU0>;
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ };
+
+ cti_modem_cpu0:cti@6837000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6837000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-modem-cpu0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti_modem_cpu1:cti@683b000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x683b000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-modem-cpu1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti0_swao:cti@6b04000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6b04000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-swao_cti0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti1_swao:cti@6b05000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6b05000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-swao_cti1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti2_swao:cti@6b06000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6b06000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-swao_cti2";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti3_swao:cti@6b07000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x6b07000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-swao_cti3";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti0_ddr0: cti@69e1000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x69e1000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-ddr_dl_0_cti";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti0_ddr1: cti@69e4000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x69e4000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-ddr_dl_1_cti0";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti1_ddr1: cti@69e5000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x69e5000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-ddr_dl_1_cti1";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ cti2_ddr1: cti@69e6000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
+ reg = <0x69e6000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-name = "coresight-cti-ddr_dl_1_cti2";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+
+ hwevent: hwevent@0x014066f0 {
+ compatible = "qcom,coresight-hwevent";
+ reg = <0x14066f0 0x4>,
+ <0x14166f0 0x4>,
+ <0x1406038 0x4>,
+ <0x1416038 0x4>;
+ reg-names = "ddr-ch0-cfg", "ddr-ch23-cfg", "ddr-ch0-ctrl",
+ "ddr-ch23-ctrl";
+
+ coresight-name = "coresight-hwevent";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 1e212b7..deed94d 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -13,11 +13,13 @@
&soc {
tlmm: pinctrl@3900000 {
compatible = "qcom,sdxpoorwills-pinctrl";
- reg = <0x3900000 0x300000>;
+ reg = <0x3900000 0x300000>,
+ <0xB204900 0x280>;
interrupts = <0 212 0>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
+ interrupt-parent = <&pdc>;
#interrupt-cells = <2>;
uart2_console_active: uart2_console_active {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
new file mode 100644
index 0000000..eab887c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -0,0 +1,95 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&soc {
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,pm-cluster@0{
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ label = "system";
+ qcom,psci-mode-shift = <0>;
+ qcom,psci-mode-mask = <0xf>;
+
+ qcom,pm-cluster-level@0 {
+ reg = <0>;
+ label = "cx_active";
+ qcom,psci-mode = <0x0>;
+ qcom,latency-us = <270>;
+ qcom,ss-power = <455>;
+ qcom,energy-overhead = <270621>;
+ qcom,time-overhead = <500>;
+ };
+
+ qcom,pm-cluster-level@1 {
+ reg = <1>;
+ label = "cx_min";
+ qcom,psci-mode = <0x0>;
+ qcom,latency-us = <285>;
+ qcom,ss-power = <442>;
+ qcom,energy-overhead = <306621>;
+ qcom,time-overhead = <540>;
+ qcom,min-child-idx = <2>;
+ qcom,notify-rpm;
+ qcom,is-reset;
+ };
+
+ qcom,pm-cpu@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ qcom,psci-mode-shift = <0>;
+ qcom,psci-mode-mask = <0xf>;
+ qcom,cpu = <&CPU0>;
+
+ qcom,pm-cpu-level@0{
+ reg = <0>;
+ label = "wfi";
+ qcom,psci-cpu-mode = <0x1>;
+ qcom,latency-us = <1>;
+ qcom,ss-power = <473>;
+ qcom,energy-overhead = <100000>;
+ qcom,time-overhead = <25>;
+ };
+
+ qcom,pm-cpu-level@1 {
+ reg = <1>;
+ label ="standalone_pc";
+ qcom,psci-cpu-mode = <0x4>;
+ qcom,latency-us = <240>;
+ qcom,ss-power = <467>;
+ qcom,energy-overhead = <202781>;
+ qcom,time-overhead = <420>;
+ qcom,use-broadcast-timer;
+ qcom,is-reset;
+ };
+
+ qcom,pm-cpu-level@2 {
+ reg = <2>;
+ label = "system-pc";
+ qcom,psci-cpu-mode = <0x8>;
+ qcom,latency-us = <270>;
+ qcom,ss-power = <455>;
+ qcom,energy-overhead = <270621>;
+ qcom,time-overhead = <500>;
+ qcom,use-broadcast-timer;
+ qcom,is-reset;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 5829942..13d50f8 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -23,7 +23,7 @@
model = "Qualcomm Technologies, Inc. SDX POORWILLS";
compatible = "qcom,sdxpoorwills";
qcom,msm-id = <334 0x0>, <335 0x0>;
- interrupt-parent = <&intc>;
+ interrupt-parent = <&pdc>;
reserved-memory {
#address-cells = <1>;
@@ -70,6 +70,7 @@
CPU0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a7";
+ enable-method = "psci";
reg = <0x0>;
#cooling-cells = <2>;
};
@@ -81,6 +82,11 @@
sdhc1 = &sdhc_1; /* SDC1 eMMC/SD/SDIO slot */
};
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
soc: soc { };
};
@@ -96,6 +102,15 @@
#interrupt-cells = <3>;
reg = <0x17800000 0x1000>,
<0x17802000 0x1000>;
+ interrupt-parent = <&intc>;
+ };
+
+ pdc: interrupt-controller@b210000{
+ compatible = "qcom,pdc-sdxpoorwills";
+ reg = <0xb210000 0x30000>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ interrupt-controller;
};
timer {
@@ -591,6 +606,8 @@
qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
qcom,modem-cfg-emb-pipe-flt;
qcom,use-ipa-pm;
+ qcom,arm-smmu;
+ qcom,smmu-fast-map;
qcom,bandwidth-vote-for-ipa;
qcom,msm-bus,name = "ipa";
qcom,msm-bus,num-cases = <5>;
@@ -729,6 +746,29 @@
compatible = "qcom,smp2pgpio-map-ipa-1-in";
gpios = <&smp2pgpio_ipa_1_in 0 0>;
};
+
+ ipa_smmu_ap: ipa_smmu_ap {
+ compatible = "qcom,ipa-smmu-ap-cb";
+ iommus = <&apps_smmu 0x5E0 0x0>;
+ qcom,iova-mapping = <0x20000000 0x40000000>;
+ qcom,additional-mapping =
+ /* modem tables in IMEM */
+ <0x14686000 0x14686000 0x3000>;
+ };
+
+ ipa_smmu_wlan: ipa_smmu_wlan {
+ compatible = "qcom,ipa-smmu-wlan-cb";
+ iommus = <&apps_smmu 0x5E1 0x0>;
+ qcom,additional-mapping =
+ /* ipa-uc ram */
+ <0x1E60000 0x1E60000 0xA000>;
+ };
+
+ ipa_smmu_uc: ipa_smmu_uc {
+ compatible = "qcom,ipa-smmu-uc-cb";
+ iommus = <&apps_smmu 0x5E2 0x0>;
+ qcom,iova-mapping = <0x40000000 0x20000000>;
+ };
};
qmp_aop: qcom,qmp-aop@c300000 {
@@ -764,6 +804,7 @@
#include "sdxpoorwills-audio.dtsi"
#include "sdxpoorwills-ion.dtsi"
#include "msm-arm-smmu-sdxpoorwills.dtsi"
+#include "sdxpoorwills-coresight.dtsi"
&soc {
emac_hw: qcom,emac@00020000 {
@@ -809,3 +850,16 @@
};
};
};
+
+#include "pmxpoorwills.dtsi"
+#include "sdxpoorwills-blsp.dtsi"
+#include "sdxpoorwills-regulator.dtsi"
+#include "sdxpoorwills-smp2p.dtsi"
+#include "sdxpoorwills-usb.dtsi"
+#include "sdxpoorwills-pcie.dtsi"
+#include "sdxpoorwills-bus.dtsi"
+#include "sdxpoorwills-thermal.dtsi"
+#include "sdxpoorwills-audio.dtsi"
+#include "sdxpoorwills-ion.dtsi"
+#include "msm-arm-smmu-sdxpoorwills.dtsi"
+#include "sdxpoorwills-pm.dtsi"
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index d3500ae..a515e00 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -286,6 +286,7 @@
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_UEVENT=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index af75d1e..ba1acda 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -285,6 +285,7 @@
CONFIG_USB_GADGET_DEBUG_FS=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_UEVENT=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 4952b98..405e34d 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -51,6 +51,7 @@
select COMMON_CLK
select COMMON_CLK_QCOM
select QCOM_GDSC
+ select GENERIC_CLOCKEVENTS_BROADCAST
config ARCH_MSM8953
bool "Enable support for MSM8953"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index d35cecb..b7640d3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -154,6 +154,15 @@
This enables support for the MSM8953 chipset. If you do not
wish to build a kernel that runs on this chipset, say 'N' here.
+config ARCH_MSM8937
+ bool "Enable Support for Qualcomm Technologies Inc. MSM8937"
+ depends on ARCH_QCOM
+ select CPU_FREQ_QCOM
+ select COMMON_CLK_MSM
+ help
+ This enables support for the MSM8937 chipset. If you do not
+ wish to build a kernel that runs on this chipset, say 'N' here.
+
config ARCH_SDM450
bool "Enable Support for Qualcomm Technologies Inc. SDM450"
depends on ARCH_QCOM
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 80d3e82c..31386bd 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -287,7 +287,10 @@
sdm450-pmi632-cdp-s2.dtb \
sdm450-pmi632-mtp-s3.dtb
-dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb
+dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb \
+ sdm632-cdp-s2.dtb \
+ sdm632-mtp-s3.dtb \
+ sdm632-qrd-sku4.dtb
endif
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
index a178aa1..a208e1a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
@@ -24,6 +24,7 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
+ extcon = <&pmi8937_charger>;
};
&pmi8937_charger {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
index 71d6941..28fc0d7 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
@@ -24,6 +24,7 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
+ extcon = <&pmi8940_charger>;
};
&labibb {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
index b9c2a18..944868b 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
@@ -29,6 +29,7 @@
&usb3 {
vbus_dwc3-supply = <&smbcharger_charger_otg>;
+ extcon = <&pmi8950_charger>;
};
&pmi8950_charger {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 69cd4fc..1f651fd 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -1281,6 +1281,22 @@
status = "disabled";
};
+ qcom,msm-adsprpc-mem {
+ compatible = "qcom,msm-adsprpc-mem-region";
+ memory-region = <&adsp_mem>;
+ };
+
+ qcom,msm_fastrpc {
+ compatible = "qcom,msm-fastrpc-legacy-compute";
+ qcom,msm_fastrpc_compute_cb {
+ compatible = "qcom,msm-fastrpc-legacy-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_iommu 0x2408 0x7>;
+ sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
+ };
+ };
+
+
ipa_hw: qcom,ipa@07900000 {
compatible = "qcom,ipa";
reg = <0x07900000 0x4effc>, <0x07904000 0x26934>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 4830af4..903f170a 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -218,7 +218,6 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
};
chan@4f {
@@ -230,7 +229,6 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
- qcom,vadc-thermal-node;
};
chan@1d {
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
index 97be32de..bab5774 100644
--- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -11,6 +11,8 @@
*/
#include <dt-bindings/msm/power-on.h>
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
&spmi_bus {
qcom,pmi8950@2 {
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 6cf9a82..fcde397 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -18,6 +18,30 @@
qcom,msm-id = <347 0x0>;
};
+&pil_modem_mem {
+ reg = <0 0x8b000000 0 0x3c00000>;
+};
+
+&pil_video_mem {
+ reg = <0 0x8ec00000 0 0x500000>;
+};
+
+&wlan_msa_mem {
+ reg = <0 0x8f100000 0 0x100000>;
+};
+
+&pil_cdsp_mem {
+ reg = <0 0x8f200000 0 0x800000>;
+};
+
+&pil_mba_mem {
+ reg = <0 0x8fa00000 0 0x200000>;
+};
+
+&pil_adsp_mem {
+ reg = <0 0x8fc00000 0 0x1e00000>;
+};
+
&soc {
qcom,rmnet-ipa {
status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
new file mode 100644
index 0000000..903b432
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-cdp-s2.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 CDP S2";
+ compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+ qcom,board-id = <1 2>;
+ qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
new file mode 100644
index 0000000..6339c3c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-mtp-s3.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S3";
+ compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
+ qcom,board-id = <8 3>;
+ qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
new file mode 100644
index 0000000..9f33721
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-qrd-sku4.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 QRD SKU4";
+ compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
+ qcom,board-id = <0xb 1>;
+ qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
index 4f5a9b1..aa7cc97 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -669,35 +669,6 @@
qcom,bcms = <&bcm_cn0>;
};
- mas_qhm_tic: mas-qhm-tic {
- cell-id = <MSM_BUS_MASTER_TIC>;
- label = "mas-qhm-tic";
- qcom,buswidth = <4>;
- qcom,agg-ports = <1>;
- qcom,connections = <&slv_qhs_tlmm_south
- &slv_qhs_camera_cfg &slv_qhs_sdc4
- &slv_qhs_sdc2 &slv_qhs_mnoc_cfg
- &slv_qhs_ufs_mem_cfg &slv_qhs_glm
- &slv_qhs_pdm &slv_qhs_a2_noc_cfg
- &slv_qhs_qdss_cfg &slv_qhs_display_cfg
- &slv_qhs_tcsr &slv_qhs_dcc_cfg
- &slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
- &slv_qhs_snoc_cfg &slv_qhs_phy_refgen_south
- &slv_qhs_gpuss_cfg &slv_qhs_venus_cfg
- &slv_qhs_tsif &slv_qhs_compute_dsp_cfg
- &slv_qhs_aop &slv_qhs_qupv3_north
- &slv_srvc_cnoc &slv_qhs_usb3_0
- &slv_qhs_ipa &slv_qhs_cpr_cx
- &slv_qhs_a1_noc_cfg &slv_qhs_aoss
- &slv_qhs_prng &slv_qhs_vsense_ctrl_cfg
- &slv_qhs_emmc_cfg &slv_qhs_qupv3_south
- &slv_qhs_spdm &slv_qhs_crypto0_cfg
- &slv_qhs_pimem_cfg &slv_qhs_tlmm_north
- &slv_qhs_clk_ctl &slv_qhs_imem_cfg>;
- qcom,bus-dev = <&fab_config_noc>;
- qcom,bcms = <&bcm_cn0>;
- };
-
mas_qnm_snoc: mas-qnm-snoc {
cell-id = <MSM_BUS_SNOC_CNOC_MAS>;
label = "mas-qnm-snoc";
@@ -727,36 +698,6 @@
qcom,bcms = <&bcm_cn0>;
};
- mas_xm_qdss_dap: mas-xm-qdss-dap {
- cell-id = <MSM_BUS_MASTER_QDSS_DAP>;
- label = "mas-xm-qdss-dap";
- qcom,buswidth = <8>;
- qcom,agg-ports = <1>;
- qcom,connections = <&slv_qhs_tlmm_south
- &slv_qhs_camera_cfg
- &slv_qhs_sdc4
- &slv_qhs_sdc2 &slv_qhs_mnoc_cfg
- &slv_qhs_ufs_mem_cfg &slv_qhs_glm
- &slv_qhs_pdm &slv_qhs_a2_noc_cfg
- &slv_qhs_qdss_cfg &slv_qhs_display_cfg
- &slv_qhs_tcsr &slv_qhs_dcc_cfg
- &slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
- &slv_qhs_snoc_cfg &slv_qhs_phy_refgen_south
- &slv_qhs_gpuss_cfg &slv_qhs_venus_cfg
- &slv_qhs_tsif &slv_qhs_compute_dsp_cfg
- &slv_qhs_aop &slv_qhs_qupv3_north
- &slv_srvc_cnoc &slv_qhs_usb3_0
- &slv_qhs_ipa &slv_qhs_cpr_cx
- &slv_qhs_a1_noc_cfg &slv_qhs_aoss
- &slv_qhs_prng &slv_qhs_vsense_ctrl_cfg
- &slv_qhs_qupv3_south &slv_qhs_spdm
- &slv_qhs_crypto0_cfg &slv_qhs_pimem_cfg
- &slv_qhs_tlmm_north &slv_qhs_clk_ctl
- &slv_qhs_imem_cfg>;
- qcom,bus-dev = <&fab_config_noc>;
- qcom,bcms = <&bcm_cn0>;
- };
-
mas_qhm_cnoc: mas-qhm-cnoc {
cell-id = <MSM_BUS_MASTER_CNOC_DC_NOC>;
label = "mas-qhm-cnoc";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
index 5d3975c..ab49970 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -175,8 +175,8 @@
io-channel-names = "rradc_batt_id",
"rradc_die_temp";
qcom,rradc-base = <0x4500>;
- qcom,fg-esr-timer-awake = <96 96>;
- qcom,fg-esr-timer-asleep = <256 256>;
+ qcom,fg-esr-timer-awake = <64 96>;
+ qcom,fg-esr-timer-asleep = <224 256>;
qcom,fg-esr-timer-charging = <0 96>;
qcom,cycle-counter-en;
qcom,hold-soc-while-full;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
index 32864a0..3df6d09 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
@@ -27,8 +27,6 @@
};
&usb0 {
- /delete-property/ iommus;
- /delete-property/ qcom,smmu-s1-bypass;
qcom,pm-qos-latency = <601>; /* CPU-CLUSTER-WFI-LVL latency +1 */
extcon = <0>, <0>, <&eud>, <0>, <0>;
};
@@ -57,6 +55,8 @@
0x03 0x250 /* TUNE5 */
0x00 0x23c /* CHG_CTRL2 */
0x22 0x210>; /* PWR_CTRL1 */
+ nvmem-cells = <&minor_rev>;
+ nvmem-cell-names = "minor_rev";
};
&usb_qmp_dp_phy {
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 9bc083f..3cc0aa3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2139,6 +2139,7 @@
compatible = "qcom,pil-tz-generic";
qcom,pas-id = <0xf>;
qcom,firmware-name = "ipa_fws";
+ memory-region = <&pil_ipa_fw_mem>;
};
pil_modem: qcom,mss@4080000 {
@@ -2440,6 +2441,7 @@
qcom,msm-adsprpc-mem {
compatible = "qcom,msm-adsprpc-mem-region";
memory-region = <&adsp_mem>;
+ restrict-access;
};
qcom,msm_fastrpc {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 947d28b..1551952 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -51,6 +51,7 @@
compatible = "qcom,memshare-peripheral";
qcom,peripheral-size = <0x500000>;
qcom,client-id = <1>;
+ qcom,allocate-boot-time;
label = "modem";
};
};
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 801c66a..34b6097 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -52,6 +52,7 @@
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_MSM8953=y
+CONFIG_ARCH_MSM8937=y
CONFIG_ARCH_SDM450=y
CONFIG_ARCH_SDM632=y
CONFIG_SCHED_MC=y
@@ -295,6 +296,7 @@
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
CONFIG_MSM_RDBG=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 009c420..ed222d2 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -56,6 +56,7 @@
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_MSM8953=y
+CONFIG_ARCH_MSM8937=y
CONFIG_ARCH_SDM450=y
CONFIG_ARCH_SDM632=y
CONFIG_SCHED_MC=y
@@ -305,6 +306,7 @@
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
CONFIG_MSM_RDBG=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MSM_V2=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 8022e88..667377f 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -621,7 +621,6 @@
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
CONFIG_DEBUG_OBJECTS_WORK=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index f7ef61e..11c95ea 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -290,6 +290,11 @@
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index a4f0ffa..6aa09e5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -294,6 +294,11 @@
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 1ea2053..b0d0181 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -607,7 +607,7 @@
config MSM_ADSPRPC
tristate "QTI ADSP RPC driver"
- depends on MSM_GLINK
+ depends on MSM_GLINK || MSM_SMD
help
Provides a communication mechanism that allows for clients to
make remote method invocations across processor boundary to
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 3f35d54..9a0424a 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1381,7 +1381,7 @@
/* copy non ion buffers */
PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_COPY),
rlen = copylen - metalen;
- for (oix = 0; oix < inbufs + outbufs; ++oix) {
+ for (oix = 0; rpra && oix < inbufs + outbufs; ++oix) {
int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i];
size_t mlen;
@@ -1432,7 +1432,7 @@
if (map && (map->attr & FASTRPC_ATTR_COHERENT))
continue;
- if (rpra[i].buf.len && ctx->overps[oix]->mstart)
+ if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart)
dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
}
@@ -3399,7 +3399,8 @@
break;
}
}
- if (range.addr) {
+ if (range.addr && !of_property_read_bool(dev->of_node,
+ "restrict-access")) {
int srcVM[1] = {VMID_HLOS};
int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
VMID_ADSP_Q6};
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index f510c14..223bc03 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, 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
@@ -536,8 +536,7 @@
}
static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
@@ -545,23 +544,30 @@
struct diag_msg_ssid_query_t rsp;
struct diag_ssid_range_t ssid_range;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
mutex_lock(&driver->msg_mask_lock);
rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
@@ -583,12 +589,12 @@
write_len += sizeof(ssid_range);
}
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i = 0;
int write_len = 0;
@@ -641,8 +647,7 @@
}
static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
@@ -651,6 +656,10 @@
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -658,15 +667,19 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
mutex_lock(&driver->msg_mask_lock);
req = (struct diag_build_mask_req_t *)src_buf;
@@ -681,6 +694,7 @@
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -700,12 +714,12 @@
memcpy(dest_buf, &rsp, sizeof(rsp));
write_len += sizeof(rsp);
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
uint32_t mask_size = 0, offset = 0;
uint32_t *temp = NULL;
@@ -716,6 +730,10 @@
struct diag_msg_build_mask_t rsp;
struct diag_mask_info *mask_info = NULL;
struct diag_msg_mask_t *mask_next = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -723,11 +741,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -740,6 +760,7 @@
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -782,6 +803,7 @@
mutex_unlock(&mask->lock);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -ENOMEM;
}
mask->ptr = temp;
@@ -802,6 +824,7 @@
}
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -842,8 +865,7 @@
}
static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i, write_len = 0, peripheral;
int header_len = sizeof(struct diag_msg_config_rsp_t);
@@ -851,6 +873,10 @@
struct diag_msg_config_rsp_t *req = NULL;
struct diag_msg_mask_t *mask = NULL;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -858,11 +884,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -877,6 +905,7 @@
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
@@ -889,7 +918,7 @@
}
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
-
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -923,8 +952,7 @@
}
static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int write_len = 0;
uint32_t mask_size;
@@ -959,26 +987,30 @@
}
static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i, write_len = 0, mask_len = 0, peripheral;
int header_len = sizeof(struct diag_event_mask_config_t);
struct diag_event_mask_config_t rsp;
struct diag_event_mask_config_t *req;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
req = (struct diag_event_mask_config_t *)src_buf;
@@ -986,6 +1018,7 @@
if (mask_len <= 0 || mask_len > event_mask.mask_len) {
pr_err("diag: In %s, invalid event mask len: %d\n", __func__,
mask_len);
+ mutex_unlock(&driver->md_session_lock);
return -EIO;
}
@@ -993,6 +1026,7 @@
memcpy(mask_info->ptr, src_buf + header_len, mask_len);
mask_info->status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(EVENT_MASKS_TYPE);
@@ -1027,25 +1061,29 @@
}
static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int write_len = 0, i, peripheral;
uint8_t toggle = 0;
struct diag_event_report_t header;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -1059,6 +1097,7 @@
memset(mask_info->ptr, 0, mask_info->mask_len);
}
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(EVENT_MASKS_TYPE);
@@ -1088,8 +1127,7 @@
}
static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int status = LOG_STATUS_INVALID;
@@ -1102,6 +1140,10 @@
struct diag_log_config_req_t *req;
struct diag_log_config_rsp_t rsp;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1109,16 +1151,20 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
req = (struct diag_log_config_req_t *)src_buf;
read_len += req_header_len;
@@ -1138,6 +1184,7 @@
if (!log_item->ptr) {
pr_err("diag: Invalid input in %s, mask: %pK\n",
__func__, log_item);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
@@ -1179,28 +1226,27 @@
rsp.status = status;
memcpy(dest_buf, &rsp, rsp_header_len);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
struct diag_log_config_rsp_t rsp;
- struct diag_mask_info *mask_info = NULL;
struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr;
+ if (!mask)
+ return -EINVAL;
+
if (!diag_apps_responds())
return 0;
- mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
- pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
- __func__, src_buf, src_len, dest_buf, dest_len,
- mask_info);
+ if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
+ __func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
}
@@ -1223,7 +1269,7 @@
static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ int pid)
{
int i, peripheral, write_len = 0;
int status = LOG_STATUS_SUCCESS;
@@ -1236,6 +1282,10 @@
struct diag_log_mask_t *mask = NULL;
struct diag_mask_info *mask_info = NULL;
unsigned char *temp_buf = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1243,11 +1293,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -1257,6 +1309,7 @@
if (!mask->ptr) {
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (req->equip_id >= MAX_EQUIP_ID) {
@@ -1319,6 +1372,7 @@
break;
}
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(LOG_MASKS_TYPE);
@@ -1365,13 +1419,16 @@
}
static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
struct diag_mask_info *mask_info = NULL;
struct diag_log_mask_t *mask = NULL;
struct diag_log_config_rsp_t header;
int write_len = 0, i, peripheral;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1379,17 +1436,20 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
mask = (struct diag_log_mask_t *)mask_info->ptr;
if (!mask->ptr) {
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
@@ -1398,6 +1458,7 @@
mutex_unlock(&mask->lock);
}
mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(LOG_MASKS_TYPE);
@@ -2144,13 +2205,11 @@
}
}
-int diag_process_apps_masks(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+int diag_process_apps_masks(unsigned char *buf, int len, int pid)
{
int size = 0, sub_cmd = 0;
int (*hdlr)(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info) = NULL;
+ unsigned char *dest_buf, int dest_len, int pid) = NULL;
if (!buf || len <= 0)
return -EINVAL;
@@ -2200,7 +2259,7 @@
if (hdlr)
size = hdlr(buf, len, driver->apps_rsp_buf,
- DIAG_MAX_RSP_SIZE, info);
+ DIAG_MAX_RSP_SIZE, pid);
return (size > 0) ? size : 0;
}
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index 1a52f94..6edeee9 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018 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
@@ -167,8 +167,7 @@
void diag_log_mask_free(struct diag_mask_info *mask_info);
void diag_msg_mask_free(struct diag_mask_info *mask_info);
void diag_event_mask_free(struct diag_mask_info *mask_info);
-int diag_process_apps_masks(unsigned char *buf, int len,
- struct diag_md_session_t *info);
+int diag_process_apps_masks(unsigned char *buf, int len, int pid);
void diag_send_updates_peripheral(uint8_t peripheral);
extern int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask,
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 9cecb03..ce0c7bb 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -129,11 +129,10 @@
int diag_md_write(int id, unsigned char *buf, int len, int ctx)
{
- int i;
+ int i, peripheral, pid = 0;
uint8_t found = 0;
unsigned long flags;
struct diag_md_info *ch = NULL;
- int peripheral;
struct diag_md_session_t *session_info = NULL;
if (id < 0 || id >= NUM_DIAG_MD_DEV || id >= DIAG_NUM_PROC)
@@ -146,10 +145,14 @@
if (peripheral < 0)
return -EINVAL;
- session_info =
- diag_md_session_get_peripheral(peripheral);
- if (!session_info)
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_peripheral(peripheral);
+ if (!session_info) {
+ mutex_unlock(&driver->md_session_lock);
return -EIO;
+ }
+ pid = session_info->pid;
+ mutex_unlock(&driver->md_session_lock);
ch = &diag_md[id];
if (!ch)
@@ -192,8 +195,7 @@
found = 0;
for (i = 0; i < driver->num_clients && !found; i++) {
- if ((driver->client_map[i].pid !=
- session_info->pid) ||
+ if ((driver->client_map[i].pid != pid) ||
(driver->client_map[i].pid == 0))
continue;
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 1cf7f52..060f03f 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018 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
@@ -221,7 +221,7 @@
if (!atomic_read(&ch->connected) &&
driver->usb_connected && diag_mask_param())
- diag_clear_masks(NULL);
+ diag_clear_masks(0);
if (ch && ch->ops && ch->ops->close)
ch->ops->close(ch->ctxt, DIAG_USB_MODE);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9de40b0..3cecebf 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -714,7 +714,7 @@
void diag_cmd_remove_reg_by_proc(int proc);
int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
int diag_mask_param(void);
-void diag_clear_masks(struct diag_md_session_t *info);
+void diag_clear_masks(int pid);
uint8_t diag_mask_to_pd_value(uint32_t peripheral_mask);
int diag_query_pd(char *process_name);
int diag_search_peripheral_by_pd(uint8_t pd_val);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0158549..694b483 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, 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
@@ -167,7 +167,7 @@
void *diag_ipc_log;
#endif
-static void diag_md_session_close(struct diag_md_session_t *session_info);
+static void diag_md_session_close(int pid);
/*
* Returns the next delayed rsp id. If wrapping is enabled,
@@ -243,12 +243,13 @@
timer_in_progress = 0;
mutex_lock(&apps_data_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (!hdlc_disabled)
diag_drain_apps_data(&hdlc_data);
else
@@ -422,7 +423,7 @@
{
return diag_mask_clear_param;
}
-void diag_clear_masks(struct diag_md_session_t *info)
+void diag_clear_masks(int pid)
{
int ret;
char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0};
@@ -431,14 +432,14 @@
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag: %s: masks clear request upon %s\n", __func__,
- ((info) ? "ODL exit" : "USB Disconnection"));
+ ((pid) ? "ODL exit" : "USB Disconnection"));
ret = diag_process_apps_masks(cmd_disable_log_mask,
- sizeof(cmd_disable_log_mask), info);
+ sizeof(cmd_disable_log_mask), pid);
ret = diag_process_apps_masks(cmd_disable_msg_mask,
- sizeof(cmd_disable_msg_mask), info);
+ sizeof(cmd_disable_msg_mask), pid);
ret = diag_process_apps_masks(cmd_disable_event_mask,
- sizeof(cmd_disable_event_mask), info);
+ sizeof(cmd_disable_event_mask), pid);
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag:%s: masks cleared successfully\n", __func__);
}
@@ -451,21 +452,23 @@
struct diag_md_session_t *session_info = NULL;
struct diag_logging_mode_param_t params;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(pid);
- if (!session_info)
+ if (!session_info) {
+ mutex_unlock(&driver->md_session_lock);
return;
+ }
+ session_mask = session_info->peripheral_mask;
+ mutex_unlock(&driver->md_session_lock);
if (diag_mask_clear_param)
- diag_clear_masks(session_info);
+ diag_clear_masks(pid);
mutex_lock(&driver->diag_maskclear_mutex);
driver->mask_clear = 1;
mutex_unlock(&driver->diag_maskclear_mutex);
mutex_lock(&driver->diagchar_mutex);
- session_mask = session_info->peripheral_mask;
- diag_md_session_close(session_info);
-
p_mask =
diag_translate_kernel_to_user_mask(session_mask);
@@ -489,7 +492,9 @@
}
}
}
-
+ mutex_lock(&driver->md_session_lock);
+ diag_md_session_close(pid);
+ mutex_unlock(&driver->md_session_lock);
diag_switch_logging(¶ms);
mutex_unlock(&driver->diagchar_mutex);
}
@@ -1024,11 +1029,13 @@
if (driver->hdlc_encode_buf_len != 0)
return -EAGAIN;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled) {
if (len < 4) {
pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
@@ -1386,15 +1393,16 @@
return err;
}
-static void diag_md_session_close(struct diag_md_session_t *session_info)
+static void diag_md_session_close(int pid)
{
int i;
uint8_t found = 0;
+ struct diag_md_session_t *session_info = NULL;
+ session_info = diag_md_session_get_pid(pid);
if (!session_info)
return;
- mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] != session_info)
continue;
@@ -1420,13 +1428,14 @@
driver->md_session_mode = (found) ? DIAG_MD_PERIPHERAL : DIAG_MD_NONE;
kfree(session_info);
session_info = NULL;
- mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE, "cleared up session\n");
}
struct diag_md_session_t *diag_md_session_get_pid(int pid)
{
int i;
+ if (pid <= 0)
+ return NULL;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] &&
driver->md_session_map[i]->pid == pid)
@@ -1442,10 +1451,12 @@
return driver->md_session_map[peripheral];
}
-static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
+static int diag_md_peripheral_switch(int pid,
int peripheral_mask, int req_mode) {
int i, bit = 0;
+ struct diag_md_session_t *session_info = NULL;
+ session_info = diag_md_session_get_pid(pid);
if (!session_info)
return -EINVAL;
if (req_mode != DIAG_USB_MODE || req_mode != DIAG_MEMORY_DEVICE_MODE)
@@ -1455,25 +1466,20 @@
* check that md_session_map for i == session_info,
* if not then race condition occurred and bail
*/
- mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
bit = MD_PERIPHERAL_MASK(i) & peripheral_mask;
if (!bit)
continue;
if (req_mode == DIAG_USB_MODE) {
- if (driver->md_session_map[i] != session_info) {
- mutex_unlock(&driver->md_session_lock);
+ if (driver->md_session_map[i] != session_info)
return -EINVAL;
- }
driver->md_session_map[i] = NULL;
driver->md_session_mask &= ~bit;
session_info->peripheral_mask &= ~bit;
} else {
- if (driver->md_session_map[i] != NULL) {
- mutex_unlock(&driver->md_session_lock);
+ if (driver->md_session_map[i] != NULL)
return -EINVAL;
- }
driver->md_session_map[i] = session_info;
driver->md_session_mask |= bit;
session_info->peripheral_mask |= bit;
@@ -1482,7 +1488,6 @@
}
driver->md_session_mode = DIAG_MD_PERIPHERAL;
- mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE, "Changed Peripherals:0x%x to mode:%d\n",
peripheral_mask, req_mode);
}
@@ -1491,7 +1496,7 @@
const struct diag_logging_mode_param_t *param,
uint8_t *change_mode)
{
- int i, bit = 0, err = 0;
+ int i, bit = 0, err = 0, peripheral_mask = 0;
int change_mask = 0;
struct diag_md_session_t *session_info = NULL;
@@ -1515,12 +1520,13 @@
if (req_mode == DIAG_USB_MODE) {
if (curr_mode == DIAG_USB_MODE)
return 0;
+ mutex_lock(&driver->md_session_lock);
if (driver->md_session_mode == DIAG_MD_NONE
&& driver->md_session_mask == 0 && driver->logging_mask) {
*change_mode = 1;
+ mutex_unlock(&driver->md_session_lock);
return 0;
}
-
/*
* curr_mode is either DIAG_MULTI_MODE or DIAG_MD_MODE
* Check if requested peripherals are already in usb mode
@@ -1532,8 +1538,10 @@
if (bit & driver->logging_mask)
change_mask |= bit;
}
- if (!change_mask)
+ if (!change_mask) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
/*
* Change is needed. Check if this md_session has set all the
@@ -1542,29 +1550,29 @@
* If this session owns all the requested peripherals, then
* call function to switch the modes/masks for the md_session
*/
- mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
-
if (!session_info) {
*change_mode = 1;
+ mutex_unlock(&driver->md_session_lock);
return 0;
}
- if ((change_mask & session_info->peripheral_mask)
+ peripheral_mask = session_info->peripheral_mask;
+ if ((change_mask & peripheral_mask)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
*change_mode = 1;
/* If all peripherals are being set to USB Mode, call close */
- if (~change_mask & session_info->peripheral_mask) {
- err = diag_md_peripheral_switch(session_info,
+ if (~change_mask & peripheral_mask) {
+ err = diag_md_peripheral_switch(current->tgid,
change_mask, DIAG_USB_MODE);
} else
- diag_md_session_close(session_info);
-
+ diag_md_session_close(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
return err;
} else if (req_mode == DIAG_MEMORY_DEVICE_MODE) {
@@ -1573,21 +1581,23 @@
* been set. Check that requested peripherals already set are
* owned by this md session
*/
- change_mask = driver->md_session_mask & param->peripheral_mask;
mutex_lock(&driver->md_session_lock);
+ change_mask = driver->md_session_mask & param->peripheral_mask;
session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
if (session_info) {
if ((session_info->peripheral_mask & change_mask)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- err = diag_md_peripheral_switch(session_info,
+ err = diag_md_peripheral_switch(current->tgid,
change_mask, DIAG_USB_MODE);
+ mutex_unlock(&driver->md_session_lock);
} else {
+ mutex_unlock(&driver->md_session_lock);
if (change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
@@ -2047,19 +2057,17 @@
{
uint8_t hdlc_support;
struct diag_md_session_t *session_info = NULL;
- mutex_lock(&driver->md_session_lock);
- session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
if (copy_from_user(&hdlc_support, (void __user *)ioarg,
sizeof(uint8_t)))
return -EFAULT;
mutex_lock(&driver->hdlc_disable_mutex);
- if (session_info) {
- mutex_lock(&driver->md_session_lock);
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(current->tgid);
+ if (session_info)
session_info->hdlc_disabled = hdlc_support;
- mutex_unlock(&driver->md_session_lock);
- } else
+ else
driver->hdlc_disabled = hdlc_support;
+ mutex_unlock(&driver->md_session_lock);
mutex_unlock(&driver->hdlc_disable_mutex);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
@@ -2885,7 +2893,6 @@
int remote_proc = 0;
const int mempool = POOL_TYPE_COPY;
unsigned char *user_space_data = NULL;
- struct diag_md_session_t *info = NULL;
if (!buf || len <= 0 || len > CALLBACK_BUF_SIZE) {
pr_err_ratelimited("diag: In %s, invalid buf %pK len: %d\n",
@@ -2936,13 +2943,11 @@
} else {
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
- mutex_lock(&driver->md_session_lock);
- info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
- ret = diag_process_apps_pkt(user_space_data, len, info);
+ ret = diag_process_apps_pkt(user_space_data, len,
+ current->tgid);
if (ret == 1)
diag_send_error_rsp((void *)(user_space_data), len,
- info);
+ current->tgid);
}
fail:
diagmem_free(driver, user_space_data, mempool);
@@ -3008,24 +3013,25 @@
if (!remote_proc) {
mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
if (!session_info) {
pr_err("diag:In %s request came from invalid md session pid:%d",
__func__, current->tgid);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (!hdlc_disabled)
diag_process_hdlc_pkt((void *)
(driver->user_space_data_buf),
- len, session_info);
+ len, current->tgid);
else
diag_process_non_hdlc_pkt((char *)
(driver->user_space_data_buf),
- len, session_info);
+ len, current->tgid);
return 0;
}
@@ -3102,11 +3108,13 @@
mutex_lock(&apps_data_mutex);
mutex_lock(&driver->hdlc_disable_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled)
ret = diag_process_apps_data_non_hdlc(user_space_data, len,
pkt_type);
@@ -3177,9 +3185,9 @@
ret += sizeof(int);
mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
exit_stat = diag_md_copy_to_user(buf, &ret, count,
session_info);
+ mutex_unlock(&driver->md_session_lock);
goto exit;
} else if (driver->data_ready[index] & USER_SPACE_DATA_TYPE) {
/* In case, the thread wakes up and the logging mode is not
@@ -3199,14 +3207,16 @@
mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
- mutex_unlock(&driver->md_session_lock);
if (session_info) {
COPY_USER_SPACE_OR_ERR(buf+4,
session_info->hdlc_disabled,
sizeof(uint8_t));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
}
+ mutex_unlock(&driver->md_session_lock);
goto exit;
}
@@ -3226,12 +3236,16 @@
if (driver->data_ready[index] & MSG_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
write_len = diag_copy_to_user_msg_mask(buf + ret, count,
session_info);
+ mutex_unlock(&driver->md_session_lock);
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= MSG_MASKS_TYPE;
@@ -3242,25 +3256,32 @@
if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, 4);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
-
+ }
if (session_info && session_info->event_mask &&
session_info->event_mask->ptr) {
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(session_info->event_mask->ptr),
session_info->event_mask->mask_len);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
} else {
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(event_mask.ptr),
event_mask.mask_len);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
}
+ mutex_unlock(&driver->md_session_lock);
driver->data_ready[index] ^= EVENT_MASKS_TYPE;
atomic_dec(&driver->data_ready_notif[index]);
goto exit;
@@ -3269,13 +3290,17 @@
if (driver->data_ready[index] & LOG_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
write_len = diag_copy_to_user_log_mask(buf + ret, count,
session_info);
+ mutex_unlock(&driver->md_session_lock);
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= LOG_MASKS_TYPE;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 1155087..33048e1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -242,7 +242,7 @@
}
static void pack_rsp_and_send(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
int err;
int retry_count = 0, i, rsp_ctxt;
@@ -250,6 +250,7 @@
unsigned long flags;
unsigned char *rsp_ptr = driver->encoded_rsp_buf;
struct diag_pkt_frame_t header;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
if (!rsp_ptr || !buf)
return;
@@ -260,6 +261,11 @@
return;
}
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(pid);
+ info = (session_info) ? session_info :
+ diag_md_session_get_peripheral(APPS_DATA);
+
/*
* Explicitly check for the Peripheral Modem here
* is necessary till a way to identify a peripheral
@@ -279,6 +285,7 @@
}
} else
rsp_ctxt = driver->rsp_buf_ctxt;
+ mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
@@ -302,8 +309,11 @@
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
- driver->logging_mode == DIAG_MULTI_MODE)
+ driver->logging_mode == DIAG_MULTI_MODE) {
+ mutex_lock(&driver->md_session_lock);
chk_logging_wakeup();
+ mutex_unlock(&driver->md_session_lock);
+ }
}
if (driver->rsp_buf_busy) {
pr_err("diag: unable to get hold of response buffer\n");
@@ -332,13 +342,14 @@
}
static void encode_rsp_and_send(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
unsigned char *rsp_ptr = driver->encoded_rsp_buf;
int err, i, rsp_ctxt, retry_count = 0;
unsigned long flags;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
if (!rsp_ptr || !buf)
return;
@@ -349,6 +360,11 @@
return;
}
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(pid);
+ info = (session_info) ? session_info :
+ diag_md_session_get_peripheral(APPS_DATA);
+
/*
* Explicitly check for the Peripheral Modem here
* is necessary till a way to identify a peripheral
@@ -368,7 +384,7 @@
}
} else
rsp_ctxt = driver->rsp_buf_ctxt;
-
+ mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
* take one or two iterations. When this loops till UINT_MAX, it
@@ -391,8 +407,11 @@
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
- driver->logging_mode == DIAG_MULTI_MODE)
+ driver->logging_mode == DIAG_MULTI_MODE) {
+ mutex_lock(&driver->md_session_lock);
chk_logging_wakeup();
+ mutex_unlock(&driver->md_session_lock);
+ }
}
if (driver->rsp_buf_busy) {
@@ -424,22 +443,23 @@
}
static void diag_send_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
- struct diag_md_session_t *session_info = NULL;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
uint8_t hdlc_disabled;
-
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
session_info = (info) ? info :
diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled)
- pack_rsp_and_send(buf, len, session_info);
+ pack_rsp_and_send(buf, len, pid);
else
- encode_rsp_and_send(buf, len, session_info);
+ encode_rsp_and_send(buf, len, pid);
}
void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type)
@@ -506,13 +526,14 @@
int i, j;
mutex_lock(&driver->diagchar_mutex);
+ mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] != NULL)
for (j = 0; j < driver->num_clients; j++) {
if (driver->client_map[j].pid != 0 &&
driver->client_map[j].pid ==
driver->md_session_map[i]->pid) {
- if (!(driver->data_ready[i] & type)) {
+ if (!(driver->data_ready[j] & type)) {
driver->data_ready[j] |= type;
atomic_inc(
&driver->data_ready_notif[j]);
@@ -521,6 +542,7 @@
}
}
}
+ mutex_unlock(&driver->md_session_lock);
wake_up_interruptible(&driver->wait_q);
mutex_unlock(&driver->diagchar_mutex);
}
@@ -982,7 +1004,7 @@
}
void diag_send_error_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
/* -1 to accommodate the first byte 0x13 */
if (len > (DIAG_MAX_RSP_SIZE - 1)) {
@@ -992,13 +1014,12 @@
*(uint8_t *)driver->apps_rsp_buf = DIAG_CMD_ERROR;
memcpy((driver->apps_rsp_buf + sizeof(uint8_t)), buf, len);
- diag_send_rsp(driver->apps_rsp_buf, len + 1, info);
+ diag_send_rsp(driver->apps_rsp_buf, len + 1, pid);
}
-int diag_process_apps_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
{
- int i;
+ int i, p_mask = 0;
int mask_ret;
int write_len = 0;
unsigned char *temp = NULL;
@@ -1007,14 +1028,15 @@
struct diag_cmd_reg_t *reg_item = NULL;
struct diagfwd_info *fwd_info = NULL;
uint32_t pd_mask = 0;
+ struct diag_md_session_t *info = NULL;
if (!buf)
return -EIO;
/* Check if the command is a supported mask command */
- mask_ret = diag_process_apps_masks(buf, len, info);
+ mask_ret = diag_process_apps_masks(buf, len, pid);
if (mask_ret > 0) {
- diag_send_rsp(driver->apps_rsp_buf, mask_ret, info);
+ diag_send_rsp(driver->apps_rsp_buf, mask_ret, pid);
return 0;
}
@@ -1036,7 +1058,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
@@ -1045,18 +1067,22 @@
if (temp_entry) {
reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
entry);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info) {
+ p_mask = info->peripheral_mask;
+ mutex_unlock(&driver->md_session_lock);
MD_PERIPHERAL_PD_MASK(TYPE_CMD, reg_item->proc,
pd_mask);
if ((MD_PERIPHERAL_MASK(reg_item->proc) &
- info->peripheral_mask) ||
- (pd_mask & info->peripheral_mask))
+ p_mask) || (pd_mask & p_mask))
write_len = diag_send_data(reg_item, buf, len);
} else {
+ mutex_unlock(&driver->md_session_lock);
if (MD_PERIPHERAL_MASK(reg_item->proc) &
driver->logging_mask) {
mutex_unlock(&driver->cmd_reg_mutex);
- diag_send_error_rsp(buf, len, info);
+ diag_send_error_rsp(buf, len, pid);
return write_len;
}
else
@@ -1074,13 +1100,13 @@
for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
- diag_send_rsp(driver->apps_rsp_buf, 8, info);
+ diag_send_rsp(driver->apps_rsp_buf, 8, pid);
return 0;
} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
if (len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, len, info);
+ diag_send_rsp(driver->apps_rsp_buf, len, pid);
return 0;
}
return len;
@@ -1093,7 +1119,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for time sync switch command */
@@ -1104,7 +1130,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for diag id command */
@@ -1115,14 +1141,14 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for download command */
else if ((chk_apps_master()) && (*buf == 0x3A)) {
/* send response back */
driver->apps_rsp_buf[0] = *buf;
- diag_send_rsp(driver->apps_rsp_buf, 1, info);
+ diag_send_rsp(driver->apps_rsp_buf, 1, pid);
msleep(5000);
/* call download API */
msm_set_restart_mode(RESTART_DLOAD);
@@ -1142,7 +1168,7 @@
for (i = 0; i < 13; i++)
driver->apps_rsp_buf[i+3] = 0;
- diag_send_rsp(driver->apps_rsp_buf, 16, info);
+ diag_send_rsp(driver->apps_rsp_buf, 16, pid);
return 0;
}
}
@@ -1151,7 +1177,7 @@
(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_enabled;
- diag_send_rsp(driver->apps_rsp_buf, 5, info);
+ diag_send_rsp(driver->apps_rsp_buf, 5, pid);
return 0;
}
/* Wrap the Delayed Rsp ID */
@@ -1160,7 +1186,7 @@
wrap_enabled = true;
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_count;
- diag_send_rsp(driver->apps_rsp_buf, 6, info);
+ diag_send_rsp(driver->apps_rsp_buf, 6, pid);
return 0;
}
/* Mobile ID Rsp */
@@ -1171,7 +1197,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
}
@@ -1191,7 +1217,7 @@
for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0;
- diag_send_rsp(driver->apps_rsp_buf, 55, info);
+ diag_send_rsp(driver->apps_rsp_buf, 55, pid);
return 0;
}
/* respond to 0x7c command */
@@ -1204,14 +1230,14 @@
chk_config_get_id();
*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
- diag_send_rsp(driver->apps_rsp_buf, 14, info);
+ diag_send_rsp(driver->apps_rsp_buf, 14, pid);
return 0;
}
}
write_len = diag_cmd_chk_stats(buf, len, driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
write_len = diag_cmd_disable_hdlc(buf, len, driver->apps_rsp_buf,
@@ -1223,7 +1249,7 @@
* before disabling HDLC encoding on Apps processor.
*/
mutex_lock(&driver->hdlc_disable_mutex);
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
/*
* Set the value of hdlc_disabled after sending the response to
* the tools. This is required since the tools is expecting a
@@ -1231,10 +1257,13 @@
*/
pr_debug("diag: In %s, disabling HDLC encoding\n",
__func__);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info)
info->hdlc_disabled = 1;
else
driver->hdlc_disabled = 1;
+ mutex_unlock(&driver->md_session_lock);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
mutex_unlock(&driver->hdlc_disable_mutex);
return 0;
@@ -1243,13 +1272,12 @@
/* We have now come to the end of the function. */
if (chk_apps_only())
- diag_send_error_rsp(buf, len, info);
+ diag_send_error_rsp(buf, len, pid);
return 0;
}
-void diag_process_hdlc_pkt(void *data, unsigned int len,
- struct diag_md_session_t *info)
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid)
{
int err = 0;
int ret = 0;
@@ -1309,7 +1337,7 @@
}
err = diag_process_apps_pkt(driver->hdlc_buf,
- driver->hdlc_buf_len, info);
+ driver->hdlc_buf_len, pid);
if (err < 0)
goto fail;
} else {
@@ -1326,7 +1354,7 @@
* recovery algorithm. Send an error response if the
* packet is not in expected format.
*/
- diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, info);
+ diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, pid);
driver->hdlc_buf_len = 0;
end:
mutex_unlock(&driver->diag_hdlc_mutex);
@@ -1423,9 +1451,11 @@
static uint8_t hdlc_reset;
-static void hdlc_reset_timer_start(struct diag_md_session_t *info)
+static void hdlc_reset_timer_start(int pid)
{
+ struct diag_md_session_t *info = NULL;
mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (!hdlc_timer_in_progress) {
hdlc_timer_in_progress = 1;
if (info)
@@ -1467,15 +1497,16 @@
}
static void diag_hdlc_start_recovery(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
int i;
static uint32_t bad_byte_counter;
unsigned char *start_ptr = NULL;
struct diag_pkt_frame_t *actual_pkt = NULL;
+ struct diag_md_session_t *info = NULL;
hdlc_reset = 1;
- hdlc_reset_timer_start(info);
+ hdlc_reset_timer_start(pid);
actual_pkt = (struct diag_pkt_frame_t *)buf;
for (i = 0; i < len; i++) {
@@ -1495,10 +1526,13 @@
pr_err("diag: In %s, re-enabling HDLC encoding\n",
__func__);
mutex_lock(&driver->hdlc_disable_mutex);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info)
info->hdlc_disabled = 0;
else
driver->hdlc_disabled = 0;
+ mutex_unlock(&driver->md_session_lock);
mutex_unlock(&driver->hdlc_disable_mutex);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
@@ -1511,12 +1545,11 @@
mutex_lock(&driver->hdlc_recovery_mutex);
driver->incoming_pkt.processing = 0;
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_process_non_hdlc_pkt(start_ptr, len - i, info);
+ diag_process_non_hdlc_pkt(start_ptr, len - i, pid);
}
}
-void diag_process_non_hdlc_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+void diag_process_non_hdlc_pkt(unsigned char *buf, int len, int pid)
{
int err = 0;
uint16_t pkt_len = 0;
@@ -1572,11 +1605,11 @@
if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
CONTROL_CHAR) {
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
mutex_lock(&driver->hdlc_recovery_mutex);
}
err = diag_process_apps_pkt(data_ptr,
- actual_pkt->length, info);
+ actual_pkt->length, pid);
if (err) {
pr_err("diag: In %s, unable to process incoming data packet, err: %d\n",
__func__, err);
@@ -1598,8 +1631,8 @@
pkt_len = actual_pkt->length;
if (actual_pkt->start != CONTROL_CHAR) {
- diag_hdlc_start_recovery(buf, len, info);
- diag_send_error_rsp(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
+ diag_send_error_rsp(buf, len, pid);
goto end;
}
mutex_lock(&driver->hdlc_recovery_mutex);
@@ -1607,7 +1640,7 @@
pr_err("diag: In %s, incoming data is too large for the request buffer %d\n",
__func__, pkt_len);
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
break;
}
if ((pkt_len + header_len) > (len - read_bytes)) {
@@ -1624,13 +1657,13 @@
if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
CONTROL_CHAR) {
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
mutex_lock(&driver->hdlc_recovery_mutex);
}
else
hdlc_reset = 0;
err = diag_process_apps_pkt(data_ptr,
- actual_pkt->length, info);
+ actual_pkt->length, pid);
if (err) {
mutex_unlock(&driver->hdlc_recovery_mutex);
break;
@@ -1649,9 +1682,9 @@
return -EINVAL;
if (!driver->hdlc_disabled)
- diag_process_hdlc_pkt(buf, len, NULL);
+ diag_process_hdlc_pkt(buf, len, 0);
else
- diag_process_non_hdlc_pkt(buf, len, NULL);
+ diag_process_non_hdlc_pkt(buf, len, 0);
diag_mux_queue_read(ctxt);
return 0;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 0e0bf2d..687aeb7 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -30,10 +30,8 @@
int diagfwd_init(void);
void diagfwd_exit(void);
-void diag_process_hdlc_pkt(void *data, unsigned int len,
- struct diag_md_session_t *info);
-void diag_process_non_hdlc_pkt(unsigned char *data, int len,
- struct diag_md_session_t *info);
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid);
+void diag_process_non_hdlc_pkt(unsigned char *data, int len, int pid);
int chk_config_get_id(void);
int chk_apps_only(void);
int chk_apps_master(void);
@@ -45,10 +43,8 @@
int diag_check_common_cmd(struct diag_pkt_header_t *header);
void diag_update_userspace_clients(unsigned int type);
void diag_update_sleeping_process(int process_id, int data_type);
-int diag_process_apps_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info);
-void diag_send_error_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info);
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid);
+void diag_send_error_rsp(unsigned char *buf, int len, int pid);
void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type);
int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf);
void diag_md_hdlc_reset_timer_func(unsigned long pid);
diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c
index f27f358..f8c3fde 100644
--- a/drivers/char/diag/diagfwd_mhi.c
+++ b/drivers/char/diag/diagfwd_mhi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, 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
@@ -552,6 +552,8 @@
struct mhi_result *result = NULL;
struct diag_mhi_ch_t *ch = NULL;
void *buf = NULL;
+ struct diag_mhi_info *mhi_info = NULL;
+ unsigned long flags;
if (!cb_info)
return;
@@ -603,13 +605,6 @@
queue_work(diag_mhi[index].mhi_wq,
&(diag_mhi[index].open_work));
break;
- case MHI_CB_MHI_DISABLED:
- DIAG_LOG(DIAG_DEBUG_BRIDGE,
- "received mhi disabled notifiation port: %d ch: %d\n",
- index, ch->type);
- atomic_set(&(ch->opened), 0);
- __mhi_close(&diag_mhi[index], CHANNELS_CLOSED);
- break;
case MHI_CB_XFER:
/*
* If the channel is a read channel, this is a read
@@ -636,6 +631,24 @@
result->bytes_xferd,
diag_mhi[index].id);
break;
+ case MHI_CB_MHI_DISABLED:
+ case MHI_CB_SYS_ERROR:
+ case MHI_CB_MHI_SHUTDOWN:
+ DIAG_LOG(DIAG_DEBUG_BRIDGE,
+ "received mhi link down cb: %d port: %d ch: %d\n",
+ cb_info->cb_reason, index, ch->type);
+ mhi_info = &diag_mhi[index];
+ if (!mhi_info->enabled)
+ return;
+ spin_lock_irqsave(&mhi_info->lock, flags);
+ mhi_info->enabled = 0;
+ spin_unlock_irqrestore(&mhi_info->lock, flags);
+ atomic_set(&(mhi_info->read_ch.opened), 0);
+ atomic_set(&(mhi_info->write_ch.opened), 0);
+ flush_workqueue(mhi_info->mhi_wq);
+ mhi_buf_tbl_clear(mhi_info);
+ diag_remote_dev_close(mhi_info->dev_id);
+ break;
default:
pr_err("diag: In %s, invalid cb reason 0x%x\n", __func__,
cb_info->cb_reason);
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index c7bd2205..c4e6107 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -343,14 +343,13 @@
diag_ws_release();
return;
}
-
- session_info =
- diag_md_session_get_peripheral(peripheral);
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_peripheral(peripheral);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled) {
/* The data is raw and and on APPS side HDLC is disabled */
if (!buf) {
@@ -633,12 +632,13 @@
mutex_lock(&driver->hdlc_disable_mutex);
mutex_lock(&fwd_info->data_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(fwd_info->peripheral);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (!driver->feature[fwd_info->peripheral].encode_hdlc) {
if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) {
temp_buf = fwd_info->buf_1;
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 3f9fcd9..7290205 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
#include "mdss-dsi-pll.h"
#include "mdss-pll.h"
#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
+#define CREATE_TRACE_POINTS
+#include "mdss_pll_trace.h"
#define VCO_DELAY_USEC 1
@@ -890,8 +892,13 @@
MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE,
pll->cached_outdiv);
}
-
+ MDSS_PLL_ATRACE_BEGIN("pll_lock");
+ trace_mdss_pll_lock_start((u64)pll->vco_cached_rate,
+ pll->vco_current_rate,
+ pll->cached_cfg0, pll->cached_cfg1,
+ pll->cached_outdiv, pll->resource_ref_cnt);
rc = dsi_pll_enable(vco);
+ MDSS_PLL_ATRACE_END("pll_lock");
if (rc) {
mdss_pll_resource_enable(pll, false);
pr_err("pll(%d) enable failed, rc=%d\n", pll->index, rc);
diff --git a/drivers/clk/qcom/mdss/mdss_pll_trace.h b/drivers/clk/qcom/mdss/mdss_pll_trace.h
new file mode 100644
index 0000000..cd4fda6
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss_pll_trace.h
@@ -0,0 +1,116 @@
+/* Copyright (c) 2018, 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.
+ */
+
+#if !defined(_MDSS_PLL_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _MDSS_PLL_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mdss_pll
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE mdss_pll_trace
+
+
+TRACE_EVENT(mdss_pll_lock_start,
+ TP_PROTO(
+ u64 vco_cached_rate,
+ s64 vco_current_rate,
+ u32 cached_cfg0,
+ u32 cached_cfg1,
+ u32 cached_outdiv,
+ u32 resource_ref_cnt),
+ TP_ARGS(
+ vco_cached_rate,
+ vco_current_rate,
+ cached_cfg0,
+ cached_cfg1,
+ cached_outdiv,
+ resource_ref_cnt),
+ TP_STRUCT__entry(
+ __field(u64, vco_cached_rate)
+ __field(s64, vco_current_rate)
+ __field(u32, cached_cfg0)
+ __field(u32, cached_cfg1)
+ __field(u32, cached_outdiv)
+ __field(u32, resource_ref_cnt)
+
+ ),
+ TP_fast_assign(
+ __entry->vco_cached_rate = vco_cached_rate;
+ __entry->vco_current_rate = vco_current_rate;
+ __entry->cached_cfg0 = cached_cfg0;
+ __entry->cached_cfg1 = cached_cfg1;
+ __entry->cached_outdiv = cached_outdiv;
+ __entry->resource_ref_cnt = resource_ref_cnt;
+ ),
+ TP_printk(
+ "vco_cached_rate=%llu vco_current_rate=%lld cached_cfg0=%d cached_cfg1=%d cached_outdiv=%d resource_ref_cnt=%d",
+ __entry->vco_cached_rate,
+ __entry->vco_current_rate,
+ __entry->cached_cfg0,
+ __entry->cached_cfg1,
+ __entry->cached_outdiv,
+ __entry->resource_ref_cnt)
+);
+
+TRACE_EVENT(pll_tracing_mark_write,
+ TP_PROTO(int pid, const char *name, bool trace_begin),
+ TP_ARGS(pid, name, trace_begin),
+ TP_STRUCT__entry(
+ __field(int, pid)
+ __string(trace_name, name)
+ __field(bool, trace_begin)
+ ),
+ TP_fast_assign(
+ __entry->pid = pid;
+ __assign_str(trace_name, name);
+ __entry->trace_begin = trace_begin;
+ ),
+ TP_printk("%s|%d|%s", __entry->trace_begin ? "B" : "E",
+ __entry->pid, __get_str(trace_name))
+)
+
+TRACE_EVENT(mdss_pll_trace_counter,
+ TP_PROTO(int pid, char *name, int value),
+ TP_ARGS(pid, name, value),
+ TP_STRUCT__entry(
+ __field(int, pid)
+ __string(counter_name, name)
+ __field(int, value)
+ ),
+ TP_fast_assign(
+ __entry->pid = current->tgid;
+ __assign_str(counter_name, name);
+ __entry->value = value;
+ ),
+ TP_printk("%d|%s|%d", __entry->pid,
+ __get_str(counter_name), __entry->value)
+)
+
+#define MDSS_PLL_ATRACE_END(name) trace_pll_tracing_mark_write(current->tgid,\
+ name, 0)
+#define MDSS_PLL_ATRACE_BEGIN(name) trace_pll_tracing_mark_write(current->tgid,\
+ name, 1)
+#define MDSS_PLL_ATRACE_FUNC() MDSS_PLL_ATRACE_BEGIN(__func__)
+#define MDSS_PLL_ATRACE_INT(name, value) \
+ trace_mdss_pll_trace_counter(current->tgid, name, value)
+
+
+#endif /* _MDSS_PLL_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 19fe223..6c66b7f 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1251,7 +1251,6 @@
state_id |= (level->psci_id & cluster->psci_mode_mask)
<< cluster->psci_mode_shift;
- (*aff_lvl)++;
/*
* We may have updated the broadcast timers, update
@@ -1259,6 +1258,8 @@
*/
if (level->notify_rpm)
system_sleep_update_wakeup();
+ if (level->psci_id)
+ (*aff_lvl)++;
}
unlock_and_return:
spin_unlock(&cluster->sync_lock);
@@ -1731,6 +1732,18 @@
{
int rc;
+#ifdef CONFIG_ARM
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ rc = arm_cpuidle_init(smp_processor_id());
+ if (rc) {
+ pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc);
+ return rc;
+ }
+ }
+#endif
+
rc = platform_driver_register(&lpm_driver);
if (rc) {
pr_info("Error registering %s\n", lpm_driver.driver.name);
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 2b6b112..3d50bae 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -249,8 +249,9 @@
}
#ifdef CONFIG_CPU_IDLE
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+static __maybe_unused DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+#ifdef CONFIG_DT_IDLE_STATES
static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
{
int i, ret, count = 0;
@@ -303,6 +304,10 @@
kfree(psci_states);
return ret;
}
+#else
+static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+{ return 0; }
+#endif
#ifdef CONFIG_ACPI
#include <acpi/processor.h>
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 79f2ec9..0a3fb24 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -29,22 +29,25 @@
struct dp_aux dp_aux;
struct dp_catalog_aux *catalog;
struct dp_aux_cfg *cfg;
-
struct mutex mutex;
struct completion comp;
+ struct drm_dp_aux drm_aux;
- u32 aux_error_num;
- u32 retry_cnt;
bool cmd_busy;
bool native;
bool read;
bool no_send_addr;
bool no_send_stop;
+
u32 offset;
u32 segment;
+ u32 aux_error_num;
+ u32 retry_cnt;
+
atomic_t aborted;
- struct drm_dp_aux drm_aux;
+ u8 *dpcd;
+ u8 *edid;
};
static char *dp_aux_get_error(u32 aux_error)
@@ -320,6 +323,7 @@
*
* @aux: DP AUX private structure
* @input_msg: input message from DRM upstream APIs
+ * @send_seg: send the seg to sink
*
* return: void
*
@@ -327,7 +331,7 @@
* sinks that do not handle the i2c middle-of-transaction flag correctly.
*/
static void dp_aux_transfer_helper(struct dp_aux_private *aux,
- struct drm_dp_aux_msg *input_msg)
+ struct drm_dp_aux_msg *input_msg, bool send_seg)
{
struct drm_dp_aux_msg helper_msg;
u32 const message_size = 0x10;
@@ -346,7 +350,7 @@
* duplicate AUX transactions related to this while reading the
* first 16 bytes of each block.
*/
- if (!(aux->offset % edid_block_length))
+ if (!(aux->offset % edid_block_length) || !send_seg)
goto end;
aux->read = false;
@@ -388,26 +392,16 @@
aux->segment = 0x0; /* reset segment at end of block */
}
-/*
- * This function does the real job to process an AUX transaction.
- * It will call aux_reset() function to reset the AUX channel,
- * if the waiting is timeout.
- */
-static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
- struct drm_dp_aux_msg *msg)
+static int dp_aux_transfer_ready(struct dp_aux_private *aux,
+ struct drm_dp_aux_msg *msg, bool send_seg)
{
- ssize_t ret;
+ int ret = 0;
int const aux_cmd_native_max = 16;
int const aux_cmd_i2c_max = 128;
- int const retry_count = 5;
- struct dp_aux_private *aux = container_of(drm_aux,
- struct dp_aux_private, drm_aux);
-
- mutex_lock(&aux->mutex);
if (atomic_read(&aux->aborted)) {
ret = -ETIMEDOUT;
- goto unlock_exit;
+ goto error;
}
aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
@@ -416,8 +410,7 @@
if ((msg->size == 0) || (msg->buffer == NULL)) {
msg->reply = aux->native ?
DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
- ret = msg->size;
- goto unlock_exit;
+ goto error;
}
/* msg sanity check */
@@ -426,14 +419,14 @@
pr_err("%s: invalid msg: size(%zu), request(%x)\n",
__func__, msg->size, msg->request);
ret = -EINVAL;
- goto unlock_exit;
+ goto error;
}
dp_aux_update_offset_and_segment(aux, msg);
- dp_aux_transfer_helper(aux, msg);
+
+ dp_aux_transfer_helper(aux, msg, send_seg);
aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
- aux->cmd_busy = true;
if (aux->read) {
aux->no_send_addr = true;
@@ -443,6 +436,98 @@
aux->no_send_stop = true;
}
+ aux->cmd_busy = true;
+error:
+ return ret;
+}
+
+static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
+ struct drm_dp_aux_msg *msg)
+{
+ u8 buf[SZ_64];
+ u32 timeout;
+ ssize_t ret;
+ struct dp_aux_private *aux = container_of(drm_aux,
+ struct dp_aux_private, drm_aux);
+
+ ret = dp_aux_transfer_ready(aux, msg, false);
+ if (ret)
+ goto end;
+
+ aux->aux_error_num = DP_AUX_ERR_NONE;
+
+ if (aux->native) {
+ if (aux->read && ((msg->address + msg->size) < SZ_1K)) {
+ aux->dp_aux.reg = msg->address;
+
+ reinit_completion(&aux->comp);
+ timeout = wait_for_completion_timeout(&aux->comp, HZ);
+ if (!timeout)
+ pr_err("aux timeout for 0x%x\n", msg->address);
+
+ aux->dp_aux.reg = 0xFFFF;
+
+ memcpy(msg->buffer, aux->dpcd + msg->address,
+ msg->size);
+ aux->aux_error_num = DP_AUX_ERR_NONE;
+ } else {
+ memset(msg->buffer, 0, msg->size);
+ }
+ } else {
+ if (aux->read && msg->address == 0x50) {
+ memcpy(msg->buffer,
+ aux->edid + aux->offset - 16,
+ msg->size);
+ }
+ }
+
+ if (aux->aux_error_num == DP_AUX_ERR_NONE) {
+ snprintf(buf, SZ_64, "[drm-dp] dbg: %5s %5s %5xh(%2zu): ",
+ aux->native ? "NATIVE" : "I2C",
+ aux->read ? "READ" : "WRITE",
+ msg->address, msg->size);
+
+ print_hex_dump(KERN_DEBUG, buf,
+ DUMP_PREFIX_NONE, 8, 1, msg->buffer, msg->size, false);
+
+ msg->reply = aux->native ?
+ DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
+ } else {
+ /* Reply defer to retry */
+ msg->reply = aux->native ?
+ DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
+ }
+
+ ret = msg->size;
+end:
+ return ret;
+}
+
+/*
+ * This function does the real job to process an AUX transaction.
+ * It will call aux_reset() function to reset the AUX channel,
+ * if the waiting is timeout.
+ */
+static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
+ struct drm_dp_aux_msg *msg)
+{
+ u8 buf[SZ_64];
+ ssize_t ret;
+ int const retry_count = 5;
+ struct dp_aux_private *aux = container_of(drm_aux,
+ struct dp_aux_private, drm_aux);
+
+ mutex_lock(&aux->mutex);
+
+ ret = dp_aux_transfer_ready(aux, msg, true);
+ if (ret)
+ goto unlock_exit;
+
+ if (!aux->cmd_busy) {
+ ret = msg->size;
+ goto unlock_exit;
+ }
+
ret = dp_aux_cmd_fifo_tx(aux, msg);
if ((ret < 0) && aux->native && !atomic_read(&aux->aborted)) {
aux->retry_cnt++;
@@ -459,6 +544,14 @@
if (aux->read)
dp_aux_cmd_fifo_rx(aux, msg);
+ snprintf(buf, SZ_64, "[drm-dp] %5s %5s %5xh(%2zu): ",
+ aux->native ? "NATIVE" : "I2C",
+ aux->read ? "READ" : "WRITE",
+ msg->address, msg->size);
+
+ print_hex_dump(KERN_DEBUG, buf,
+ DUMP_PREFIX_NONE, 8, 1, msg->buffer, msg->size, false);
+
msg->reply = aux->native ?
DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
} else {
@@ -558,6 +651,41 @@
drm_dp_aux_unregister(&aux->drm_aux);
}
+static void dp_aux_dpcd_updated(struct dp_aux *dp_aux)
+{
+ struct dp_aux_private *aux;
+
+ if (!dp_aux) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+ complete(&aux->comp);
+}
+
+static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en,
+ u8 *edid, u8 *dpcd)
+{
+ struct dp_aux_private *aux;
+
+ if (!dp_aux) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+ aux->edid = edid;
+ aux->dpcd = dpcd;
+
+ if (en)
+ aux->drm_aux.transfer = dp_aux_transfer_debug;
+ else
+ aux->drm_aux.transfer = dp_aux_transfer;
+}
+
struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
struct dp_aux_cfg *aux_cfg)
{
@@ -586,6 +714,7 @@
aux->cfg = aux_cfg;
dp_aux = &aux->dp_aux;
aux->retry_cnt = 0;
+ aux->dp_aux.reg = 0xFFFF;
dp_aux->isr = dp_aux_isr;
dp_aux->init = dp_aux_init;
@@ -594,6 +723,8 @@
dp_aux->drm_aux_deregister = dp_aux_deregister;
dp_aux->reconfig = dp_aux_reconfig;
dp_aux->abort = dp_aux_abort_transaction;
+ dp_aux->dpcd_updated = dp_aux_dpcd_updated;
+ dp_aux->set_sim_mode = dp_aux_set_sim_mode;
return dp_aux;
error:
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
index e8cb1cc..bf52d57 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.h
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -18,6 +18,19 @@
#include "dp_catalog.h"
#include "drm_dp_helper.h"
+#define DP_STATE_NOTIFICATION_SENT BIT(0)
+#define DP_STATE_TRAIN_1_STARTED BIT(1)
+#define DP_STATE_TRAIN_1_SUCCEEDED BIT(2)
+#define DP_STATE_TRAIN_1_FAILED BIT(3)
+#define DP_STATE_TRAIN_2_STARTED BIT(4)
+#define DP_STATE_TRAIN_2_SUCCEEDED BIT(5)
+#define DP_STATE_TRAIN_2_FAILED BIT(6)
+#define DP_STATE_CTRL_POWERED_ON BIT(7)
+#define DP_STATE_CTRL_POWERED_OFF BIT(8)
+#define DP_STATE_LINK_MAINTENANCE_STARTED BIT(9)
+#define DP_STATE_LINK_MAINTENANCE_COMPLETED BIT(10)
+#define DP_STATE_LINK_MAINTENANCE_FAILED BIT(11)
+
enum dp_aux_error {
DP_AUX_ERR_NONE = 0,
DP_AUX_ERR_ADDR = -1,
@@ -29,6 +42,9 @@
};
struct dp_aux {
+ u32 reg;
+ u32 state;
+
struct drm_dp_aux *drm_aux;
int (*drm_aux_register)(struct dp_aux *aux);
void (*drm_aux_deregister)(struct dp_aux *aux);
@@ -37,6 +53,8 @@
void (*deinit)(struct dp_aux *aux);
void (*reconfig)(struct dp_aux *aux);
void (*abort)(struct dp_aux *aux);
+ void (*dpcd_updated)(struct dp_aux *aux);
+ void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd);
};
struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index cb54b5f..2e2887e 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -820,6 +820,10 @@
u8 link_status[DP_LINK_STATUS_SIZE];
int const maximum_retries = 5;
+ ctrl->aux->state &= ~DP_STATE_TRAIN_1_FAILED;
+ ctrl->aux->state &= ~DP_STATE_TRAIN_1_SUCCEEDED;
+ ctrl->aux->state |= DP_STATE_TRAIN_1_STARTED;
+
dp_ctrl_state_ctrl(ctrl, 0);
/* Make sure to clear the current pattern before starting a new one */
wmb();
@@ -829,13 +833,13 @@
DP_LINK_SCRAMBLING_DISABLE); /* train_1 */
if (ret <= 0) {
ret = -EINVAL;
- return ret;
+ goto end;
}
ret = dp_ctrl_update_vx_px(ctrl);
if (ret <= 0) {
ret = -EINVAL;
- return ret;
+ goto end;
}
tries = 0;
@@ -879,6 +883,13 @@
break;
}
}
+end:
+ ctrl->aux->state &= ~DP_STATE_TRAIN_1_STARTED;
+
+ if (ret)
+ ctrl->aux->state |= DP_STATE_TRAIN_1_FAILED;
+ else
+ ctrl->aux->state |= DP_STATE_TRAIN_1_SUCCEEDED;
return ret;
}
@@ -922,6 +933,10 @@
int const maximum_retries = 5;
u8 link_status[DP_LINK_STATUS_SIZE];
+ ctrl->aux->state &= ~DP_STATE_TRAIN_2_FAILED;
+ ctrl->aux->state &= ~DP_STATE_TRAIN_2_SUCCEEDED;
+ ctrl->aux->state |= DP_STATE_TRAIN_2_STARTED;
+
dp_ctrl_state_ctrl(ctrl, 0);
/* Make sure to clear the current pattern before starting a new one */
wmb();
@@ -934,14 +949,14 @@
ret = dp_ctrl_update_vx_px(ctrl);
if (ret <= 0) {
ret = -EINVAL;
- return ret;
+ goto end;
}
ctrl->catalog->set_pattern(ctrl->catalog, pattern);
ret = dp_ctrl_train_pattern_set(ctrl,
pattern | DP_RECOVERED_CLOCK_OUT_EN);
if (ret <= 0) {
ret = -EINVAL;
- return ret;
+ goto end;
}
do {
@@ -968,7 +983,13 @@
break;
}
} while (!atomic_read(&ctrl->aborted));
+end:
+ ctrl->aux->state &= ~DP_STATE_TRAIN_2_STARTED;
+ if (ret)
+ ctrl->aux->state |= DP_STATE_TRAIN_2_FAILED;
+ else
+ ctrl->aux->state |= DP_STATE_TRAIN_2_SUCCEEDED;
return ret;
}
@@ -1109,8 +1130,7 @@
return ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, false);
}
-static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl,
- bool flip, bool multi_func)
+static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
{
struct dp_ctrl_private *ctrl;
struct dp_catalog_ctrl *catalog;
@@ -1125,7 +1145,7 @@
ctrl->orientation = flip;
catalog = ctrl->catalog;
- if (!multi_func) {
+ if (reset) {
catalog->usb_reset(ctrl->catalog, flip);
catalog->phy_reset(ctrl->catalog);
}
@@ -1192,6 +1212,10 @@
return -EINVAL;
}
+ ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_COMPLETED;
+ ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_FAILED;
+ ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_STARTED;
+
ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
@@ -1231,6 +1255,13 @@
ret = dp_ctrl_setup_main_link(ctrl, true);
} while (ret == -EAGAIN);
+ ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_STARTED;
+
+ if (ret)
+ ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_FAILED;
+ else
+ ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED;
+
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 229c779..31d8f07 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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,7 +23,7 @@
#include "dp_catalog.h"
struct dp_ctrl {
- int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool multi_func);
+ int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
void (*deinit)(struct dp_ctrl *dp_ctrl);
int (*on)(struct dp_ctrl *dp_ctrl);
void (*off)(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 054b3c8..a63b2c5 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -36,15 +36,52 @@
u8 *dpcd;
u32 dpcd_size;
+ int vdo;
+
struct dp_usbpd *usbpd;
struct dp_link *link;
struct dp_panel *panel;
+ struct dp_aux *aux;
struct drm_connector **connector;
struct device *dev;
-
+ struct work_struct sim_work;
struct dp_debug dp_debug;
};
+static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
+{
+ int rc = 0;
+
+ if (!debug->edid) {
+ debug->edid = devm_kzalloc(debug->dev, SZ_256, GFP_KERNEL);
+ if (!debug->edid) {
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ debug->edid_size = SZ_256;
+ }
+end:
+ return rc;
+}
+
+static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug)
+{
+ int rc = 0;
+
+ if (!debug->dpcd) {
+ debug->dpcd = devm_kzalloc(debug->dev, SZ_1K, GFP_KERNEL);
+ if (!debug->dpcd) {
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ debug->dpcd_size = SZ_1K;
+ }
+end:
+ return rc;
+}
+
static ssize_t dp_debug_write_edid(struct file *file,
const char __user *user_buff, size_t count, loff_t *ppos)
{
@@ -75,7 +112,8 @@
edid_size = size / char_to_nib;
buf_t = buf;
- memset(debug->edid, 0, debug->edid_size);
+ if (dp_debug_get_edid_buf(debug))
+ goto bail;
if (edid_size != debug->edid_size) {
pr_debug("clearing debug edid\n");
@@ -100,13 +138,13 @@
buf_t += char_to_nib;
}
- print_hex_dump(KERN_DEBUG, "DEBUG EDID: ", DUMP_PREFIX_NONE,
- 16, 1, debug->edid, debug->edid_size, false);
-
edid = debug->edid;
bail:
kfree(buf);
- debug->panel->set_edid(debug->panel, edid);
+
+ if (!debug->dp_debug.sim_mode)
+ debug->panel->set_edid(debug->panel, edid);
+
return rc;
}
@@ -119,8 +157,8 @@
size_t dpcd_size = 0;
size_t size = 0, dpcd_buf_index = 0;
ssize_t rc = count;
-
- pr_debug("count=%zu\n", count);
+ char offset_ch[5];
+ u32 offset;
if (!debug)
return -ENODEV;
@@ -128,7 +166,7 @@
if (*ppos)
goto bail;
- size = min_t(size_t, count, SZ_32);
+ size = min_t(size_t, count, SZ_2K);
buf = kzalloc(size, GFP_KERNEL);
if (!buf) {
@@ -139,16 +177,30 @@
if (copy_from_user(buf, user_buff, size))
goto bail;
- dpcd_size = size / char_to_nib;
- buf_t = buf;
+ memcpy(offset_ch, buf, 4);
+ offset_ch[4] = '\0';
- memset(debug->dpcd, 0, debug->dpcd_size);
-
- if (dpcd_size != debug->dpcd_size) {
- pr_debug("clearing debug dpcd\n");
+ if (kstrtoint(offset_ch, 16, &offset)) {
+ pr_err("offset kstrtoint error\n");
goto bail;
}
+ if (dp_debug_get_dpcd_buf(debug))
+ goto bail;
+
+ if (offset == 0xFFFF) {
+ pr_err("clearing dpcd\n");
+ memset(debug->dpcd, 0, debug->dpcd_size);
+ goto bail;
+ }
+
+ size -= 4;
+
+ dpcd_size = size / char_to_nib;
+ buf_t = buf + 4;
+
+ dpcd_buf_index = offset;
+
while (dpcd_size--) {
char t[3];
int d;
@@ -167,16 +219,39 @@
buf_t += char_to_nib;
}
- print_hex_dump(KERN_DEBUG, "DEBUG DPCD: ", DUMP_PREFIX_NONE,
- 8, 1, debug->dpcd, debug->dpcd_size, false);
-
dpcd = debug->dpcd;
bail:
kfree(buf);
- debug->panel->set_dpcd(debug->panel, dpcd);
+ if (debug->dp_debug.sim_mode)
+ debug->aux->dpcd_updated(debug->aux);
+ else
+ debug->panel->set_dpcd(debug->panel, dpcd);
+
return rc;
}
+static ssize_t dp_debug_read_dpcd(struct file *file,
+ char __user *user_buff, size_t count, loff_t *ppos)
+{
+ struct dp_debug_private *debug = file->private_data;
+ char buf[SZ_8];
+ u32 len = 0;
+
+ if (!debug)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg);
+
+ if (copy_to_user(user_buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len;
+ return len;
+}
+
static ssize_t dp_debug_write_hpd(struct file *file,
const char __user *user_buff, size_t count, loff_t *ppos)
{
@@ -421,7 +496,6 @@
struct dp_debug_private *debug = file->private_data;
char *buf;
u32 len = 0, rc = 0;
- u64 lclk = 0;
u32 max_size = SZ_4K;
if (!debug)
@@ -434,124 +508,60 @@
if (!buf)
return -ENOMEM;
- rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME);
+ rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- rc = snprintf(buf + len, max_size,
- "\tdp_panel\n\t\tmax_pclk_khz = %d\n",
- debug->panel->max_pclk_khz);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\tdrm_dp_link\n\t\trate = %u\n",
+ rc = snprintf(buf + len, max_size, "\tlink_rate=%u\n",
debug->panel->link_info.rate);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- rc = snprintf(buf + len, max_size,
- "\t\tnum_lanes = %u\n",
+ rc = snprintf(buf + len, max_size, "\tnum_lanes=%u\n",
debug->panel->link_info.num_lanes);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- rc = snprintf(buf + len, max_size,
- "\t\tcapabilities = %lu\n",
- debug->panel->link_info.capabilities);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\tdp_panel_info:\n\t\tactive = %dx%d\n",
+ rc = snprintf(buf + len, max_size, "\tresolution=%dx%d@%dHz\n",
debug->panel->pinfo.h_active,
- debug->panel->pinfo.v_active);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tback_porch = %dx%d\n",
- debug->panel->pinfo.h_back_porch,
- debug->panel->pinfo.v_back_porch);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tfront_porch = %dx%d\n",
- debug->panel->pinfo.h_front_porch,
- debug->panel->pinfo.v_front_porch);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tsync_width = %dx%d\n",
- debug->panel->pinfo.h_sync_width,
- debug->panel->pinfo.v_sync_width);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\tactive_low = %dx%d\n",
- debug->panel->pinfo.h_active_low,
- debug->panel->pinfo.v_active_low);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\th_skew = %d\n",
- debug->panel->pinfo.h_skew);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- rc = snprintf(buf + len, max_size,
- "\t\trefresh rate = %d\n",
+ debug->panel->pinfo.v_active,
debug->panel->pinfo.refresh_rate);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- rc = snprintf(buf + len, max_size,
- "\t\tpixel clock khz = %d\n",
+ rc = snprintf(buf + len, max_size, "\tpclock=%dKHz\n",
debug->panel->pinfo.pixel_clk_khz);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
- rc = snprintf(buf + len, max_size,
- "\t\tbpp = %d\n",
+ rc = snprintf(buf + len, max_size, "\tbpp=%d\n",
debug->panel->pinfo.bpp);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
/* Link Information */
- rc = snprintf(buf + len, max_size,
- "\tdp_link:\n\t\ttest_requested = %d\n",
- debug->link->sink_request);
+ rc = snprintf(buf + len, max_size, "\ttest_req=%s\n",
+ dp_link_get_test_name(debug->link->sink_request));
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tlane_count = %d\n", debug->link->link_params.lane_count);
+ "\tlane_count=%d\n", debug->link->link_params.lane_count);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tbw_code = %d\n", debug->link->link_params.bw_code);
- if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
- goto error;
-
- lclk = drm_dp_bw_code_to_link_rate(
- debug->link->link_params.bw_code) * 1000;
- rc = snprintf(buf + len, max_size,
- "\t\tlclk = %lld\n", lclk);
+ "\tbw_code=%d\n", debug->link->link_params.bw_code);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tv_level = %d\n", debug->link->phy_params.v_level);
+ "\tv_level=%d\n", debug->link->phy_params.v_level);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
rc = snprintf(buf + len, max_size,
- "\t\tp_level = %d\n", debug->link->phy_params.p_level);
+ "\tp_level=%d\n", debug->link->phy_params.p_level);
if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
goto error;
@@ -816,6 +826,90 @@
return rc;
}
+static ssize_t dp_debug_write_sim(struct file *file,
+ const char __user *user_buff, size_t count, loff_t *ppos)
+{
+ struct dp_debug_private *debug = file->private_data;
+ char buf[SZ_8];
+ size_t len = 0;
+ int sim;
+
+ if (!debug)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ /* Leave room for termination char */
+ len = min_t(size_t, count, SZ_8 - 1);
+ if (copy_from_user(buf, user_buff, len))
+ goto end;
+
+ buf[len] = '\0';
+
+ if (kstrtoint(buf, 10, &sim) != 0)
+ goto end;
+
+ if (sim) {
+ if (dp_debug_get_edid_buf(debug))
+ goto end;
+
+ if (dp_debug_get_dpcd_buf(debug))
+ goto error;
+ } else {
+ if (debug->edid) {
+ devm_kfree(debug->dev, debug->edid);
+ debug->edid = NULL;
+ }
+
+ if (debug->dpcd) {
+ devm_kfree(debug->dev, debug->dpcd);
+ debug->dpcd = NULL;
+ }
+ }
+
+ debug->dp_debug.sim_mode = !!sim;
+
+ debug->aux->set_sim_mode(debug->aux, debug->dp_debug.sim_mode,
+ debug->edid, debug->dpcd);
+end:
+ return len;
+error:
+ devm_kfree(debug->dev, debug->edid);
+ return len;
+}
+
+static ssize_t dp_debug_write_attention(struct file *file,
+ const char __user *user_buff, size_t count, loff_t *ppos)
+{
+ struct dp_debug_private *debug = file->private_data;
+ char buf[SZ_8];
+ size_t len = 0;
+ int vdo;
+
+ if (!debug)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ /* Leave room for termination char */
+ len = min_t(size_t, count, SZ_8 - 1);
+ if (copy_from_user(buf, user_buff, len))
+ goto end;
+
+ buf[len] = '\0';
+
+ if (kstrtoint(buf, 10, &vdo) != 0)
+ goto end;
+
+ debug->vdo = vdo;
+
+ schedule_work(&debug->sim_work);
+end:
+ return len;
+}
+
static const struct file_operations dp_debug_fops = {
.open = simple_open,
.read = dp_debug_read_info,
@@ -840,6 +934,7 @@
static const struct file_operations dpcd_fops = {
.open = simple_open,
.write = dp_debug_write_dpcd,
+ .read = dp_debug_read_dpcd,
};
static const struct file_operations connected_fops = {
@@ -865,6 +960,16 @@
.read = dp_debug_read_hdr,
};
+static const struct file_operations sim_fops = {
+ .open = simple_open,
+ .write = dp_debug_write_sim,
+};
+
+static const struct file_operations attention_fops = {
+ .open = simple_open,
+ .write = dp_debug_write_attention,
+};
+
static int dp_debug_init(struct dp_debug *dp_debug)
{
int rc = 0;
@@ -967,6 +1072,26 @@
goto error_remove_dir;
}
+ file = debugfs_create_file("sim", 0644, dir,
+ debug, &sim_fops);
+
+ if (IS_ERR_OR_NULL(file)) {
+ rc = PTR_ERR(file);
+ pr_err("[%s] debugfs sim failed, rc=%d\n",
+ DEBUG_NAME, rc);
+ goto error_remove_dir;
+ }
+
+ file = debugfs_create_file("attention", 0644, dir,
+ debug, &attention_fops);
+
+ if (IS_ERR_OR_NULL(file)) {
+ rc = PTR_ERR(file);
+ pr_err("[%s] debugfs attention failed, rc=%d\n",
+ DEBUG_NAME, rc);
+ goto error_remove_dir;
+ }
+
return 0;
error_remove_dir:
@@ -977,9 +1102,17 @@
return rc;
}
+static void dp_debug_sim_work(struct work_struct *work)
+{
+ struct dp_debug_private *debug =
+ container_of(work, typeof(*debug), sim_work);
+
+ debug->usbpd->simulate_attention(debug->usbpd, debug->vdo);
+}
+
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
- struct drm_connector **connector)
+ struct dp_aux *aux, struct drm_connector **connector)
{
int rc = 0;
struct dp_debug_private *debug;
@@ -997,28 +1130,13 @@
goto error;
}
- debug->edid = devm_kzalloc(dev, SZ_256, GFP_KERNEL);
- if (!debug->edid) {
- rc = -ENOMEM;
- kfree(debug);
- goto error;
- }
-
- debug->edid_size = SZ_256;
-
- debug->dpcd = devm_kzalloc(dev, SZ_16, GFP_KERNEL);
- if (!debug->dpcd) {
- rc = -ENOMEM;
- kfree(debug);
- goto error;
- }
-
- debug->dpcd_size = SZ_16;
+ INIT_WORK(&debug->sim_work, dp_debug_sim_work);
debug->dp_debug.debug_en = false;
debug->usbpd = usbpd;
debug->link = link;
debug->panel = panel;
+ debug->aux = aux;
debug->dev = dev;
debug->connector = connector;
@@ -1063,7 +1181,11 @@
dp_debug_deinit(dp_debug);
- devm_kfree(debug->dev, debug->edid);
- devm_kfree(debug->dev, debug->dpcd);
+ if (debug->edid)
+ devm_kfree(debug->dev, debug->edid);
+
+ if (debug->dpcd)
+ devm_kfree(debug->dev, debug->dpcd);
+
devm_kfree(debug->dev, debug);
}
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 3b2d23e..5a5a786 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -18,6 +18,7 @@
#include "dp_panel.h"
#include "dp_link.h"
#include "dp_usbpd.h"
+#include "dp_aux.h"
/**
* struct dp_debug
@@ -29,6 +30,7 @@
*/
struct dp_debug {
bool debug_en;
+ bool sim_mode;
bool psm_enabled;
int aspect_ratio;
int vdisplay;
@@ -52,7 +54,7 @@
*/
struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
struct dp_usbpd *usbpd, struct dp_link *link,
- struct drm_connector **connector);
+ struct dp_aux *aux, struct drm_connector **connector);
/**
* dp_debug_put()
*
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index d19058f..053ee20 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -466,6 +466,7 @@
bool hpd)
{
u32 timeout_sec;
+ int ret = 0;
dp->dp_display.is_connected = hpd;
@@ -474,16 +475,20 @@
else
timeout_sec = 10;
+ dp->aux->state |= DP_STATE_NOTIFICATION_SENT;
+
reinit_completion(&dp->notification_comp);
dp_display_send_hpd_event(dp);
if (!wait_for_completion_timeout(&dp->notification_comp,
HZ * timeout_sec)) {
pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ dp->aux->state &= ~DP_STATE_NOTIFICATION_SENT;
+
+ return ret;
}
static int dp_display_process_hpd_high(struct dp_display_private *dp)
@@ -532,6 +537,7 @@
static void dp_display_host_init(struct dp_display_private *dp)
{
bool flip = false;
+ bool reset;
if (dp->core_initialized) {
pr_debug("DP core already initialized\n");
@@ -541,8 +547,10 @@
if (dp->usbpd->orientation == ORIENTATION_CC2)
flip = true;
+ reset = dp->debug->sim_mode ? false : !dp->usbpd->multi_func;
+
dp->power->init(dp->power, flip);
- dp->ctrl->init(dp->ctrl, flip, dp->usbpd->multi_func);
+ dp->ctrl->init(dp->ctrl, flip, reset);
enable_irq(dp->irq);
dp->core_initialized = true;
}
@@ -558,6 +566,7 @@
dp->power->deinit(dp->power);
disable_irq(dp->irq);
dp->core_initialized = false;
+ dp->aux->state = 0;
}
static int dp_display_process_hpd_low(struct dp_display_private *dp)
@@ -664,6 +673,13 @@
goto end;
}
+ /*
+ * In case cable/dongle is disconnected during adb shell stop,
+ * reset psm_enabled flag to false since it is no more needed
+ */
+ if (dp->dp_display.post_open)
+ dp->debug->psm_enabled = false;
+
if (dp->debug->psm_enabled)
dp->link->psm_config(dp->link, &dp->panel->link_info, true);
@@ -929,7 +945,7 @@
}
dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
- dp->link, &dp->dp_display.connector);
+ dp->link, dp->aux, &dp->dp_display.connector);
if (IS_ERR(dp->debug)) {
rc = PTR_ERR(dp->debug);
pr_err("failed to initialize debug, rc = %d\n", rc);
@@ -1095,6 +1111,7 @@
end:
/* clear framework event notifier */
dp_display->post_open = NULL;
+ dp->aux->state |= DP_STATE_CTRL_POWERED_ON;
complete_all(&dp->notification_comp);
mutex_unlock(&dp->session_lock);
@@ -1127,6 +1144,14 @@
dp->hdcp.ops->off(dp->hdcp.data);
}
+ if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done) {
+ if (dp->audio_supported)
+ dp->audio->off(dp->audio);
+
+ dp->link->psm_config(dp->link, &dp->panel->link_info, true);
+ dp->debug->psm_enabled = true;
+ }
+
dp->ctrl->push_idle(dp->ctrl);
end:
mutex_unlock(&dp->session_lock);
@@ -1167,8 +1192,17 @@
memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
+ /*
+ * In case of framework reboot, the DP off sequence is executed without
+ * any notification from driver. Initialize post_open callback to notify
+ * DP connection once framework restarts.
+ */
+ if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done) {
+ dp_display->post_open = dp_display_post_open;
+ dp->dp_display.is_connected = false;
+ }
dp->power_on = false;
-
+ dp->aux->state = DP_STATE_CTRL_POWERED_OFF;
end:
complete_all(&dp->notification_comp);
mutex_unlock(&dp->session_lock);
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 3ca247c..05629dd 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -724,24 +724,6 @@
return ret;
}
-static char *dp_link_get_test_name(u32 test_requested)
-{
- switch (test_requested) {
- case DP_TEST_LINK_TRAINING:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
- case DP_TEST_LINK_VIDEO_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
- case DP_TEST_LINK_EDID_READ:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
- case DP_TEST_LINK_PHY_TEST_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
- case DP_TEST_LINK_AUDIO_PATTERN:
- return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
- default:
- return "unknown";
- }
-}
-
/**
* dp_link_is_video_audio_test_requested() - checks for audio/video link request
* @link: link requested by the sink
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 6f79b6a..46d30a7 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -83,6 +83,24 @@
u32 bw_code;
};
+static inline char *dp_link_get_test_name(u32 test_requested)
+{
+ switch (test_requested) {
+ case DP_TEST_LINK_TRAINING:
+ return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
+ case DP_TEST_LINK_VIDEO_PATTERN:
+ return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
+ case DP_TEST_LINK_EDID_READ:
+ return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
+ case DP_TEST_LINK_PHY_TEST_PATTERN:
+ return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
+ case DP_TEST_LINK_AUDIO_PATTERN:
+ return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
+ default:
+ return "unknown";
+ }
+}
+
struct dp_link {
u32 sink_request;
u32 test_response;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index e0aedc0..7132699 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -136,9 +136,6 @@
goto end;
}
-
- print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ",
- DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false);
}
rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
@@ -275,35 +272,31 @@
static int dp_panel_read_edid(struct dp_panel *dp_panel,
struct drm_connector *connector)
{
+ int ret = 0;
struct dp_panel_private *panel;
if (!dp_panel) {
pr_err("invalid input\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
if (panel->custom_edid) {
pr_debug("skip edid read in debug mode\n");
- return 0;
+ goto end;
}
sde_get_edid(connector, &panel->aux->drm_aux->ddc,
(void **)&dp_panel->edid_ctrl);
if (!dp_panel->edid_ctrl->edid) {
pr_err("EDID read failed\n");
- } else {
- u8 *buf = (u8 *)dp_panel->edid_ctrl->edid;
- u32 size = buf[0x7E] ? 256 : 128;
-
- print_hex_dump(KERN_DEBUG, "[drm-dp] SINK EDID: ",
- DUMP_PREFIX_NONE, 16, 1, buf, size, false);
-
- return 0;
+ ret = -EINVAL;
+ goto end;
}
-
- return -EINVAL;
+end:
+ return ret;
}
static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 2bd3bd4..42eb9b0 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -426,6 +426,28 @@
return rc;
}
+static int dp_usbpd_simulate_attention(struct dp_usbpd *dp_usbpd, int vdo)
+{
+ int rc = 0;
+ struct dp_usbpd_private *pd;
+
+ if (!dp_usbpd) {
+ pr_err("invalid input\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ pd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd);
+
+ pd->vdo = vdo;
+ dp_usbpd_get_status(pd);
+
+ if (pd->dp_cb && pd->dp_cb->attention)
+ pd->dp_cb->attention(pd->dev);
+error:
+ return rc;
+}
+
struct dp_usbpd *dp_usbpd_get(struct device *dev, struct dp_usbpd_cb *cb)
{
int rc = 0;
@@ -475,6 +497,7 @@
dp_usbpd = &usbpd->dp_usbpd;
dp_usbpd->simulate_connect = dp_usbpd_simulate_connect;
+ dp_usbpd->simulate_attention = dp_usbpd_simulate_attention;
return dp_usbpd;
error:
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.h b/drivers/gpu/drm/msm/dp/dp_usbpd.h
index e70ad7d..0a7efd9 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.h
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -50,6 +50,7 @@
* @alt_mode_cfg_done: bool to specify alt mode status
* @debug_en: bool to specify debug mode
* @simulate_connect: simulate disconnect or connect for debug mode
+ * @simulate_attention: simulate attention messages for debug mode
*/
struct dp_usbpd {
enum dp_usbpd_port port;
@@ -65,6 +66,7 @@
bool debug_en;
int (*simulate_connect)(struct dp_usbpd *dp_usbpd, bool hpd);
+ int (*simulate_attention)(struct dp_usbpd *dp_usbpd, int vdo);
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 42aea7e..3e084d5 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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 as published by
@@ -613,6 +613,7 @@
if (!node)
return;
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_DISABLED) {
ret = sde_core_irq_enable(kms, &irq_idx, 1);
if (ret)
@@ -620,6 +621,7 @@
else
node->state = IRQ_ENABLED;
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
}
static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
@@ -1623,6 +1625,7 @@
struct sde_crtc *crtc;
int i;
int irq_idx, ret;
+ unsigned long flags;
struct sde_cp_node prop_node;
struct sde_crtc_irq_info *node = NULL;
@@ -1673,6 +1676,7 @@
if (!en) {
if (node) {
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_ENABLED) {
ret = sde_core_irq_disable(kms, &irq_idx, 1);
if (ret)
@@ -1683,6 +1687,7 @@
} else {
node->state = IRQ_NOINIT;
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
} else {
DRM_ERROR("failed to get node from crtc event list\n");
}
@@ -1701,6 +1706,7 @@
if (node) {
/* device resume or resume from IPC cases */
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
ret = sde_core_irq_enable(kms, &irq_idx, 1);
if (ret) {
@@ -1712,6 +1718,7 @@
node->state = IRQ_ENABLED;
}
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
} else {
/* request from userspace to register the event
* in this case, node has not been added into the event list
@@ -1807,14 +1814,17 @@
return;
}
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_ENABLED) {
if (sde_core_irq_disable_nolock(kms, irq_idx)) {
DRM_ERROR("failed to disable irq %d, ret %d\n",
irq_idx, ret);
+ spin_unlock_irqrestore(&node->state_lock, flags);
return;
}
node->state = IRQ_DISABLED;
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
/* lock histogram buffer */
for (i = 0; i < crtc->num_mixers; i++) {
@@ -1886,6 +1896,7 @@
struct sde_crtc *crtc;
struct sde_crtc_irq_info *node = NULL;
int i, irq_idx, ret = 0;
+ unsigned long flags;
if (!crtc_drm || !hist_irq) {
DRM_ERROR("invalid crtc %pK irq %pK\n", crtc_drm, hist_irq);
@@ -1928,6 +1939,7 @@
if (!en) {
if (node) {
/* device suspend case or suspend to IPC cases */
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_ENABLED) {
ret = sde_core_irq_disable(kms, &irq_idx, 1);
if (ret)
@@ -1938,6 +1950,7 @@
} else {
node->state = IRQ_NOINIT;
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
} else {
DRM_ERROR("failed to get node from crtc event list\n");
}
@@ -1957,6 +1970,7 @@
if (node) {
/* device resume or resume from IPC cases */
+ spin_lock_irqsave(&node->state_lock, flags);
if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
ret = sde_core_irq_enable(kms, &irq_idx, 1);
if (ret) {
@@ -1968,6 +1982,7 @@
node->state = IRQ_ENABLED;
}
}
+ spin_unlock_irqrestore(&node->state_lock, flags);
} else {
/* request from userspace to register the event
* in this case, node has not been added into the event list
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index df0aad5e..655390b 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -471,8 +471,11 @@
}
c_conn->last_panel_power_mode = mode;
- if (mode != SDE_MODE_DPMS_ON)
+ if (mode != SDE_MODE_DPMS_ON) {
+ mutex_unlock(&c_conn->lock);
sde_connector_schedule_status_work(connector, false);
+ mutex_lock(&c_conn->lock);
+ }
return rc;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 73e2af0..1ee75c4 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -2511,9 +2511,6 @@
SDE_EVTLOG_FUNC_CASE3);
}
- if (fevent->event & SDE_ENCODER_FRAME_EVENT_DONE)
- sde_core_perf_crtc_update(crtc, 0, false);
-
if (fevent->event & (SDE_ENCODER_FRAME_EVENT_DONE
| SDE_ENCODER_FRAME_EVENT_ERROR))
frame_done = true;
@@ -2597,6 +2594,8 @@
SDE_EVT32_VERBOSE(DRMID(crtc));
smmu_state = &sde_crtc->smmu_state;
+ sde_core_perf_crtc_update(crtc, 0, false);
+
/* complete secure transitions if any */
if (smmu_state->transition_type == POST_COMMIT)
sde_crtc_secure_ctrl(crtc, true);
@@ -6134,6 +6133,7 @@
INIT_LIST_HEAD(&node->list);
node->func = custom_events[i].func;
node->event = event;
+ spin_lock_init(&node->state_lock);
break;
}
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 33d2b8fa..78f15ec 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -445,7 +445,8 @@
* @event: event type of the interrupt
* @func: function pointer to enable/disable the interrupt
* @list: list of user customized event in crtc
- * @ref_count: reference count for the interrupt
+ * @state: state of the interrupt
+ * @state_lock: spin lock for interrupt state
*/
struct sde_crtc_irq_info {
struct sde_irq_callback irq;
@@ -454,6 +455,7 @@
struct sde_irq_callback *irq);
struct list_head list;
enum sde_crtc_irq_state state;
+ spinlock_t state_lock;
};
#define to_sde_crtc_state(x) \
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 69dc385..a3f09b6 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -405,7 +405,7 @@
to_sde_encoder_phys_vid(phys_enc);
struct sde_hw_ctl *hw_ctl;
unsigned long lock_flags;
- u32 flush_register = 0;
+ u32 flush_register = ~0;
u32 reset_status = 0;
int new_cnt = -1, old_cnt = -1;
u32 event = 0;
@@ -419,42 +419,45 @@
SDE_ATRACE_BEGIN("vblank_irq");
- /* signal only for master, where there is a pending kickoff */
- if (sde_encoder_phys_vid_is_master(phys_enc)
- && atomic_add_unless(
- &phys_enc->pending_retire_fence_cnt, -1, 0)) {
- event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
- | SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
-
- if (phys_enc->parent_ops.handle_frame_done)
- phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
- phys_enc, event);
- }
-
- if (phys_enc->parent_ops.handle_vblank_virt)
- phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
- phys_enc);
-
- old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
-
/*
* only decrement the pending flush count if we've actually flushed
* hardware. due to sw irq latency, vblank may have already happened
* so we need to double-check with hw that it accepted the flush bits
*/
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+
+ old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
+
if (hw_ctl && hw_ctl->ops.get_flush_register)
flush_register = hw_ctl->ops.get_flush_register(hw_ctl);
- if (flush_register == 0)
- new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt,
- -1, 0);
+ if (flush_register)
+ goto not_flushed;
+ new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
+
+ /* signal only for master, where there is a pending kickoff */
+ if (sde_encoder_phys_vid_is_master(phys_enc)) {
+ if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
+ -1, 0))
+ event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
+ SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
+ }
+
+not_flushed:
if (hw_ctl && hw_ctl->ops.get_reset)
reset_status = hw_ctl->ops.get_reset(hw_ctl);
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
+ if (event && phys_enc->parent_ops.handle_frame_done)
+ phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
+ phys_enc, event);
+
+ if (phys_enc->parent_ops.handle_vblank_virt)
+ phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+ phys_enc);
+
SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0,
flush_register, event);
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index ed1079d..a1898ac 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -3257,7 +3257,8 @@
if (!fb || !old_fb) {
SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
- } else if (fb->pixel_format != old_fb->pixel_format) {
+ } else if ((fb->pixel_format != old_fb->pixel_format) ||
+ pstate->const_alpha_en != old_pstate->const_alpha_en) {
SDE_DEBUG_PLANE(psde, "format change\n");
pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
} else {
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index f9092e2..93304e16 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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
@@ -1129,17 +1129,29 @@
return ret;
}
-/**
- * poll_intr_status - Gets HW interrupt status based on
- * given lookup IRQ index.
- * @intr: HW interrupt handle
- * @irq_idx: Lookup irq index return from irq_idx_lookup
- * @msec: Maximum delay allowed to check intr status
- * return: return zero on success.
- */
-static u32 _sde_rm_poll_intr_status_for_cont_splash
- (struct sde_hw_intr *intr,
- int irq_idx, u32 const msec)
+static void _sde_rm_clear_irq_status(struct sde_hw_intr *hw_intr,
+ int irq_idx_pp_done, int irq_idx_autorefresh)
+{
+ u32 intr_value = 0;
+
+ if ((irq_idx_pp_done >= 0) && (hw_intr->ops.get_intr_status_nomask)) {
+ intr_value = hw_intr->ops.get_intr_status_nomask(hw_intr,
+ irq_idx_pp_done, false);
+ hw_intr->ops.clear_intr_status_force_mask(hw_intr,
+ irq_idx_pp_done, intr_value);
+ }
+
+ if ((irq_idx_autorefresh >= 0) &&
+ (hw_intr->ops.get_intr_status_nomask)) {
+ intr_value = hw_intr->ops.get_intr_status_nomask(hw_intr,
+ irq_idx_autorefresh, false);
+ hw_intr->ops.clear_intr_status_force_mask(hw_intr,
+ irq_idx_autorefresh, intr_value);
+ }
+}
+
+static u32 _sde_rm_poll_intr_status_for_cont_splash(struct sde_hw_intr *intr,
+ int irq_idx_pp_done, int irq_idx_autorefresh, u32 const msec)
{
int i;
u32 status = 0;
@@ -1153,19 +1165,112 @@
for (i = 0; i < loop; i++) {
status = intr->ops.get_intr_status_nomask
- (intr, irq_idx, false);
+ (intr, irq_idx_pp_done, false);
- if (status & BIT(irq_idx)) {
- SDE_DEBUG(" Poll success. i=%d, status=0x%x\n",
+ if (status & BIT(irq_idx_pp_done)) {
+ SDE_DEBUG("pp_done received i=%d, status=0x%x\n",
i, status);
- return 0;
+ SDE_EVT32(status, i, irq_idx_pp_done);
+
+ if (status & BIT(irq_idx_autorefresh))
+ _sde_rm_clear_irq_status(intr,
+ irq_idx_pp_done, irq_idx_autorefresh);
+ else
+ return 0;
}
usleep_range(delay_us, delay_us + 10);
}
+
+ SDE_EVT32(status, irq_idx_pp_done, SDE_EVTLOG_ERROR);
SDE_ERROR("polling timed out. status = 0x%x\n", status);
return -ETIMEDOUT;
}
+static int _sde_rm_autorefresh_disable(struct sde_hw_pingpong *pp,
+ struct sde_hw_intr *hw_intr)
+{
+ u32 const timeout_ms = 35; /* Max two vsyncs delay */
+ int rc = 0, i, loop = 3;
+ struct sde_hw_pp_vsync_info info;
+ int irq_idx_pp_done = -1, irq_idx_autorefresh = -1;
+ struct sde_hw_autorefresh cfg = {0};
+
+ if (!pp->ops.get_autorefresh || !pp->ops.setup_autorefresh ||
+ !pp->ops.connect_external_te || !pp->ops.get_vsync_info) {
+ SDE_ERROR("autorefresh update api not supported\n");
+ return 0;
+ }
+
+ /* read default autorefresh configuration */
+ pp->ops.get_autorefresh(pp, &cfg);
+ if (!cfg.enable) {
+ SDE_DEBUG("autorefresh already disabled\n");
+ SDE_EVT32(pp->idx - PINGPONG_0, SDE_EVTLOG_FUNC_CASE1);
+ return 0;
+ }
+
+ /* disable external TE first */
+ pp->ops.connect_external_te(pp, false);
+
+ /* get all IRQ indexes */
+ if (hw_intr->ops.irq_idx_lookup) {
+ irq_idx_pp_done = hw_intr->ops.irq_idx_lookup(
+ SDE_IRQ_TYPE_PING_PONG_COMP, pp->idx);
+ irq_idx_autorefresh = hw_intr->ops.irq_idx_lookup(
+ SDE_IRQ_TYPE_PING_PONG_AUTO_REF, pp->idx);
+ SDE_DEBUG("pp_done itr_idx = %d autorefresh irq_idx:%d\n",
+ irq_idx_pp_done, irq_idx_autorefresh);
+ }
+
+ /* disable autorefresh */
+ cfg.enable = false;
+ pp->ops.setup_autorefresh(pp, &cfg);
+
+ SDE_EVT32(pp->idx - PINGPONG_0, irq_idx_pp_done, irq_idx_autorefresh);
+ _sde_rm_clear_irq_status(hw_intr, irq_idx_pp_done, irq_idx_autorefresh);
+
+ /*
+ * Check the line count again if
+ * the line count is equal to the active
+ * height to make sure their is no
+ * additional frame updates
+ */
+ for (i = 0; i < loop; i++) {
+ info.wr_ptr_line_count = 0;
+ info.rd_ptr_init_val = 0;
+ pp->ops.get_vsync_info(pp, &info);
+
+ SDE_EVT32(pp->idx - PINGPONG_0, info.wr_ptr_line_count,
+ info.rd_ptr_init_val, SDE_EVTLOG_FUNC_CASE1);
+
+ /* wait for read ptr intr */
+ rc = _sde_rm_poll_intr_status_for_cont_splash(hw_intr,
+ irq_idx_pp_done, irq_idx_autorefresh, timeout_ms);
+
+ info.wr_ptr_line_count = 0;
+ info.rd_ptr_init_val = 0;
+ pp->ops.get_vsync_info(pp, &info);
+ SDE_DEBUG("i=%d, line count=%d\n", i, info.wr_ptr_line_count);
+
+ SDE_EVT32(pp->idx - PINGPONG_0, info.wr_ptr_line_count,
+ info.rd_ptr_init_val, SDE_EVTLOG_FUNC_CASE2);
+
+ /* log line count and return */
+ if (!rc)
+ break;
+ /*
+ * Wait for few milli seconds for line count
+ * to increase if any frame transfer is
+ * pending.
+ */
+ usleep_range(3000, 4000);
+ }
+
+ pp->ops.connect_external_te(pp, true);
+
+ return rc;
+}
+
/**
* sde_rm_get_pp_dsc_for_cont_splash - retrieve the current dsc enabled blocks
* and disable autorefresh if enabled.
@@ -1181,9 +1286,7 @@
{
int index = 0;
int value, dsc_cnt = 0;
- struct sde_hw_autorefresh cfg;
struct sde_rm_hw_iter iter_pp;
- int irq_idx_pp_done = -1;
if (!rm || !sde_kms || !dsc_ids) {
SDE_ERROR("invalid input parameters\n");
@@ -1195,11 +1298,7 @@
while (_sde_rm_get_hw_locked(rm, &iter_pp)) {
struct sde_hw_pingpong *pp =
to_sde_hw_pingpong(iter_pp.blk->hw);
- u32 intr_value = 0;
- u32 const timeout_ms = 35; /* Max two vsyncs delay */
- int rc = 0, i, loop = 2;
struct sde_hw_intr *hw_intr = NULL;
- struct sde_hw_pp_vsync_info info;
if (!pp->ops.get_dsc_status) {
SDE_ERROR("get_dsc_status ops not initialized\n");
@@ -1219,70 +1318,7 @@
}
index++;
- if (!pp->ops.get_autorefresh) {
- SDE_ERROR("get_autorefresh api not supported\n");
- return 0;
- }
- memset(&cfg, 0, sizeof(cfg));
- if (!pp->ops.get_autorefresh(pp, &cfg)
- && (cfg.enable)
- && (pp->ops.setup_autorefresh)) {
- if (hw_intr->ops.irq_idx_lookup) {
- irq_idx_pp_done = hw_intr->ops.irq_idx_lookup
- (SDE_IRQ_TYPE_PING_PONG_COMP,
- pp->idx);
- SDE_DEBUG(" itr_idx = %d\n", irq_idx_pp_done);
- }
-
- if ((irq_idx_pp_done >= 0) &&
- (hw_intr->ops.get_intr_status_nomask)) {
- intr_value = hw_intr->ops.get_intr_status_nomask
- (hw_intr, irq_idx_pp_done, false);
- hw_intr->ops.clear_intr_status_force_mask
- (hw_intr, irq_idx_pp_done, intr_value);
- }
- cfg.enable = false;
- SDE_DEBUG("Disabling autorefresh\n");
- pp->ops.setup_autorefresh(pp, &cfg);
-
- /*
- * Check the line count again if
- * the line count is equal to the active
- * height to make sure their is no
- * additional frame updates
- */
- for (i = 0; i < loop; i++) {
- info.wr_ptr_line_count = 0;
- info.rd_ptr_init_val = 0;
- if (pp->ops.get_vsync_info)
- pp->ops.get_vsync_info(pp, &info);
- /*
- * For cmd-mode using external-TE logic,
- * the rd_ptr_init_val is equal to
- * active-height. Use this init_val to
- * compare that with lane count. Need
- * to implement a different check
- * if external-TE is not used.
- */
- if (info.wr_ptr_line_count
- < info.rd_ptr_init_val) {
- /* wait for read ptr intr */
- rc =
- _sde_rm_poll_intr_status_for_cont_splash
- (hw_intr, irq_idx_pp_done, timeout_ms);
- if (!rc)
- break;
- }
- SDE_DEBUG("i=%d, line count=%d\n",
- i, info.wr_ptr_line_count);
- /*
- * Wait for few milli seconds for line count
- * to increase if any frame transfer is
- * pending.
- */
- usleep_range(3000, 4000);
- }
- }
+ _sde_rm_autorefresh_disable(pp, hw_intr);
}
return dsc_cnt;
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 52d45bb..10446f7 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1638,6 +1638,8 @@
unsigned int fence_mask)
{
unsigned int status, i;
+ struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+ unsigned int reg_offset = gpudev->reg_offsets->offsets[offset];
adreno_writereg(adreno_dev, offset, val);
@@ -1662,6 +1664,6 @@
}
dev_err(adreno_dev->dev.dev,
- "GMU fenced register write timed out: reg %x\n", offset);
+ "GMU fenced register write timed out: reg 0x%x\n", reg_offset);
return -ETIMEDOUT;
}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 4b11bbe..60c56a06 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -165,14 +165,19 @@
}
void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_device *device,
- struct kgsl_memdesc *entry)
+ struct kgsl_memdesc *memdesc)
{
- if (!kgsl_mmu_is_secured(&device->mmu))
+ if (!kgsl_mmu_is_secured(&device->mmu) || memdesc == NULL)
return;
- if (entry != NULL && entry->pagetable->name == KGSL_MMU_SECURE_PT)
- kgsl_mmu_unmap(entry->pagetable, entry);
+ /* Check if an empty memdesc got passed in */
+ if ((memdesc->gpuaddr == 0) || (memdesc->size == 0))
+ return;
+ if (memdesc->pagetable) {
+ if (memdesc->pagetable->name == KGSL_MMU_SECURE_PT)
+ kgsl_mmu_unmap(memdesc->pagetable, memdesc);
+ }
}
int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device,
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index 7ef2710..1393399 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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,17 +23,23 @@
static struct tmc_drvdata *tmcdrvdata;
static void tmc_etr_read_bytes(struct byte_cntr *byte_cntr_data, loff_t *ppos,
- size_t bytes, size_t *len)
+ size_t bytes, size_t *len, char **bufp)
{
- if (*len >= bytes) {
- atomic_dec(&byte_cntr_data->irq_cnt);
+
+ if (*bufp >= (char *)(tmcdrvdata->vaddr + tmcdrvdata->size))
+ *bufp = tmcdrvdata->vaddr;
+
+ if (*len >= bytes)
*len = bytes;
- } else {
- if (((uint32_t)*ppos % bytes) + *len > bytes)
- *len = bytes - ((uint32_t)*ppos % bytes);
- if ((*len + (uint32_t)*ppos) % bytes == 0)
- atomic_dec(&byte_cntr_data->irq_cnt);
- }
+ else if (((uint32_t)*ppos % bytes) + *len > bytes)
+ *len = bytes - ((uint32_t)*ppos % bytes);
+
+ if ((*bufp + *len) > (char *)(tmcdrvdata->vaddr +
+ tmcdrvdata->size))
+ *len = (char *)(tmcdrvdata->vaddr + tmcdrvdata->size) -
+ *bufp;
+ if (*len == bytes || (*len + (uint32_t)*ppos) % bytes == 0)
+ atomic_dec(&byte_cntr_data->irq_cnt);
}
static void tmc_etr_sg_read_pos(loff_t *ppos,
@@ -96,7 +102,7 @@
if (*len >= (bytes - ((uint32_t)*ppos % bytes)))
*len = bytes - ((uint32_t)*ppos % bytes);
- if ((*len + (uint32_t)*ppos) % bytes == 0)
+ if (*len == bytes || (*len + (uint32_t)*ppos) % bytes == 0)
atomic_dec(&tmcdrvdata->byte_cntr->irq_cnt);
}
@@ -153,11 +159,12 @@
if (!byte_cntr_data->read_active)
goto err0;
}
- bufp = (char *)(tmcdrvdata->vaddr + *ppos);
+ bufp = (char *)(tmcdrvdata->buf + *ppos);
if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
tmc_etr_read_bytes(byte_cntr_data, ppos,
- byte_cntr_data->block_size, &len);
+ byte_cntr_data->block_size, &len,
+ &bufp);
else
tmc_etr_sg_read_pos(ppos, byte_cntr_data->block_size, 0,
&len, &bufp);
@@ -179,7 +186,7 @@
if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
tmc_etr_read_bytes(byte_cntr_data, ppos,
byte_cntr_data->block_size,
- &len);
+ &len, &bufp);
else
tmc_etr_sg_read_pos(ppos,
byte_cntr_data->block_size,
diff --git a/drivers/input/touchscreen/synaptics_dsx/Kconfig b/drivers/input/touchscreen/synaptics_dsx/Kconfig
index b2fa115..b54e792 100644
--- a/drivers/input/touchscreen/synaptics_dsx/Kconfig
+++ b/drivers/input/touchscreen/synaptics_dsx/Kconfig
@@ -59,6 +59,16 @@
To compile this driver as a module, choose M here: the
module will be called synaptics_dsx_fw_update.
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+ bool "Synaptics DSX firmware update sysfs attributes"
+ depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+ help
+ Say Y here to enable support for sysfs attributes for
+ performing firmware update in a development environment.
+ This does not affect the core or other subsystem attributes.
+
+ If unsure, say N.
+
config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING
tristate "Synaptics DSX test reporting module"
depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index 7f62e01..395def9 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -137,6 +137,7 @@
static int fwu_recovery_check_status(void);
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count);
@@ -201,6 +202,8 @@
struct device_attribute *attr, char *buf);
#endif
+#endif
+
enum f34_version {
F34_V0 = 0,
F34_V1,
@@ -757,6 +760,7 @@
struct work_struct fwu_work;
};
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static struct bin_attribute dev_attr_data = {
.attr = {
.name = "data",
@@ -766,8 +770,10 @@
.read = fwu_sysfs_show_image,
.write = fwu_sysfs_store_image,
};
+#endif
static struct device_attribute attrs[] = {
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
__ATTR(dorecovery, 0220,
synaptics_rmi4_show_error,
fwu_sysfs_do_recovery_store),
@@ -821,13 +827,16 @@
fwu_sysfs_read_lockdown_code_show,
fwu_sysfs_write_lockdown_code_store),
#endif
+#endif
};
static struct synaptics_rmi4_fwu_handle *fwu;
DECLARE_COMPLETION(fwu_remove_complete);
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
DEFINE_MUTEX(fwu_sysfs_mutex);
+#endif
static void calculate_checksum(unsigned short *data, unsigned long len,
unsigned long *result)
@@ -3061,6 +3070,7 @@
return 0;
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static int fwu_check_pm_configuration_size(void)
{
unsigned short block_count;
@@ -3077,6 +3087,7 @@
return 0;
}
+#endif
static int fwu_check_bl_configuration_size(void)
{
@@ -3444,6 +3455,7 @@
return fwu_write_configuration();
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static int fwu_write_pm_configuration(void)
{
fwu->config_area = PM_CONFIG_AREA;
@@ -3469,6 +3481,7 @@
return 0;
}
#endif
+#endif
static int fwu_write_flash_configuration(void)
{
@@ -3757,6 +3770,7 @@
return retval;
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static int fwu_do_read_config(void)
{
int retval;
@@ -3984,6 +3998,7 @@
return retval;
}
#endif
+#endif
static int fwu_do_lockdown_v7(void)
{
@@ -4134,6 +4149,7 @@
}
#endif
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static int fwu_start_write_guest_code(void)
{
int retval;
@@ -4339,6 +4355,7 @@
return retval;
}
+#endif
static int fwu_start_reflash(void)
{
@@ -4970,6 +4987,7 @@
}
#endif
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
static ssize_t fwu_sysfs_show_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count)
@@ -5566,6 +5584,7 @@
return count;
}
#endif
+#endif
static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
unsigned char intr_mask)
{
@@ -5668,6 +5687,7 @@
if (ENABLE_SYS_REFLASH == false)
return 0;
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
&dev_attr_data);
if (retval < 0) {
@@ -5676,6 +5696,7 @@
__func__);
goto exit_free_mem;
}
+#endif
for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
@@ -5697,7 +5718,9 @@
&attrs[attr_count].attr);
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
exit_free_mem:
kfree(fwu->image_name);
@@ -5739,7 +5762,9 @@
&attrs[attr_count].attr);
}
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
exit:
complete(&fwu_remove_complete);
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
index 8776d4a..7725cd3 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
@@ -402,11 +402,11 @@
struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
struct i2c_msg msg[2];
+ mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1);
if (retval < 0)
- return retval;
-
- mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+ goto exit;
retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
if (retval != PAGE_SELECT_LEN) {
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
index 61cf979..331274e 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
@@ -567,16 +567,22 @@
return -EBADF;
}
- if (count == 0)
- return 0;
+ mutex_lock(&(dev_data->file_mutex));
+
+ if (*f_pos > REG_ADDR_LIMIT) {
+ retval = -EFAULT;
+ goto clean_up;
+ }
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
+ if (count == 0) {
+ retval = 0;
+ goto clean_up;
+ }
address = (unsigned short)(*f_pos);
- mutex_lock(&(dev_data->file_mutex));
-
rmidev_allocate_buffer(count);
retval = synaptics_rmi4_reg_read(rmidev->rmi4_data,
@@ -638,18 +644,26 @@
return -EBADF;
}
- if (count == 0)
- return 0;
+ mutex_lock(&(dev_data->file_mutex));
+
+ if (*f_pos > REG_ADDR_LIMIT) {
+ retval = -EFAULT;
+ goto unlock;
+ }
if (count > (REG_ADDR_LIMIT - *f_pos))
count = REG_ADDR_LIMIT - *f_pos;
- mutex_lock(&(dev_data->file_mutex));
-
+ if (count == 0) {
+ retval = 0;
+ goto unlock;
+ }
rmidev_allocate_buffer(count);
- if (copy_from_user(rmidev->tmpbuf, buf, count))
+ if (copy_from_user(rmidev->tmpbuf, buf, count)) {
return -EFAULT;
+ goto unlock;
+ }
retval = synaptics_rmi4_reg_write(rmidev->rmi4_data,
*f_pos,
@@ -658,6 +672,7 @@
if (retval >= 0)
*f_pos += retval;
+unlock:
mutex_unlock(&(dev_data->file_mutex));
return retval;
diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig
index b892109..0038047 100644
--- a/drivers/irqchip/qcom/Kconfig
+++ b/drivers/irqchip/qcom/Kconfig
@@ -20,3 +20,10 @@
default y if ARCH_SDM670
help
QTI Power Domain Controller for SDM670
+
+config QTI_PDC_SDXPOORWILLS
+ bool "QTI PDC SDxPOORWILLS"
+ select QTI_PDC
+ default y if ARCH_SDXPOORWILLS
+ help
+ QTI Power Domain Controller for SDxPoorwills
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 5e99040..c4ff9ef 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_QTI_PDC) += pdc.o
obj-$(CONFIG_QTI_PDC_SDM845) += pdc-sdm845.o
obj-$(CONFIG_QTI_PDC_SDM670) += pdc-sdm670.o
+obj-$(CONFIG_QTI_PDC_SDXPOORWILLS) += pdc-sdxpoorwills.o
diff --git a/drivers/irqchip/qcom/pdc-sdxpoorwills.c b/drivers/irqchip/qcom/pdc-sdxpoorwills.c
new file mode 100644
index 0000000..5bbca03
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc-sdxpoorwills.c
@@ -0,0 +1,76 @@
+/* Copyright (c) 2017, 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/irqchip.h>
+#include "pdc.h"
+
+static struct pdc_pin sdxpoorwills_data[] = {
+ {0, 179}, /* rpmh_wake */
+ {1, 180}, /* ee0_apps_hlos_spmi_periph_irq */
+ {2, 181}, /* ee1_apps_trustzone_spmi_periph_irq */
+ {3, 182}, /* secure_wdog_expired */
+ {4, 183}, /* secure_wdog_bark_irq */
+ {5, 184}, /* aop_wdog_expired_irq */
+ {8, 187}, /* aoss_pmic_arb_mpu_xpu_summary_irq */
+ {9, 188}, /* rpmh_wake */
+ {12, 191}, /* pdc_apps_epcb_timeout_summary_irq */
+ {13, 192}, /* spmi_protocol_irq */
+ {14, 193}, /* tsense0_tsense_max_min_int */
+ {15, 194}, /* apps_pdc_irq_in_15 */
+ {16, 195}, /* tsense0_upper_lower_intr */
+ {17, 196}, /* apps_pdc_irq_in_17 */
+ {18, 197}, /* tsense0_critical_intr */
+ {19, 198}, /* apps_pdc_irq_in_19 */
+ {20, 199}, /* apps_pdc.gp_irq_mux[0] */
+ {21, 200}, /* apps_pdc.gp_irq_mux[1] */
+ {22, 201}, /* apps_pdc.gp_irq_mux[2] */
+ {23, 202}, /* apps_pdc.gp_irq_mux[3] */
+ {24, 203}, /* apps_pdc.gp_irq_mux[4] */
+ {25, 204}, /* apps_pdc.gp_irq_mux[5] */
+ {26, 205}, /* apps_pdc.gp_irq_mux[6] */
+ {27, 206}, /* apps_pdc.gp_irq_mux[7] */
+ {28, 207}, /* apps_pdc.gp_irq_mux[8] */
+ {29, 208}, /* apps_pdc.gp_irq_mux[9] */
+ {30, 209}, /* apps_pdc.gp_irq_mux[10] */
+ {31, 210}, /* apps_pdc.gp_irq_mux[11] */
+ {32, 211}, /* apps_pdc.gp_irq_mux[12] */
+ {33, 212}, /* apps_pdc.gp_irq_mux[13] */
+ {34, 213}, /* apps_pdc.gp_irq_mux[14] */
+ {35, 214}, /* apps_pdc.gp_irq_mux[15] */
+ {36, 215}, /* apps_pdc.gp_irq_mux[16] */
+ {37, 216}, /* apps_pdc.gp_irq_mux[17] */
+ {38, 217}, /* apps_pdc.gp_irq_mux[18] */
+ {39, 218}, /* apps_pdc.gp_irq_mux[19] */
+ {40, 219}, /* apps_pdc.gp_irq_mux[20] */
+ {41, 220}, /* apps_pdc.gp_irq_mux[21] */
+ {42, 221}, /* apps_pdc.gp_irq_mux[22] */
+ {43, 222}, /* apps_pdc.gp_irq_mux[23] */
+ {44, 223}, /* apps_pdc.gp_irq_mux[24] */
+ {45, 224}, /* apps_pdc.gp_irq_mux[25] */
+ {46, 225}, /* apps_pdc.gp_irq_mux[26] */
+ {47, 226}, /* apps_pdc.gp_irq_mux[27] */
+ {48, 227}, /* apps_pdc.gp_irq_mux[28] */
+ {49, 228}, /* apps_pdc.gp_irq_mux[29] */
+ {50, 229}, /* apps_pdc.gp_irq_mux[30] */
+ {51, 230}, /* apps_pdc.gp_irq_mux[31] */
+ {-1}
+};
+
+static int __init qcom_pdc_gic_init(struct device_node *node,
+ struct device_node *parent)
+{
+ pr_info("PDC sdxpoowills initialized\n");
+ return qcom_pdc_init(node, parent, sdxpoorwills_data);
+}
+
+IRQCHIP_DECLARE(pdc_sdxpoorwills, "qcom,pdc-sdxpoorwills", qcom_pdc_gic_init);
diff --git a/drivers/irqchip/qcom/pdc.c b/drivers/irqchip/qcom/pdc.c
index 923552f..f7284bd 100644
--- a/drivers/irqchip/qcom/pdc.c
+++ b/drivers/irqchip/qcom/pdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
+#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -95,6 +96,20 @@
return 0;
}
+static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which, bool *state)
+{
+ return d->parent_data->chip->irq_get_irqchip_state(d,
+ which, state);
+}
+
+static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which, bool value)
+{
+ return d->parent_data->chip->irq_set_irqchip_state(d,
+ which, value);
+}
+
static void qcom_pdc_gic_mask(struct irq_data *d)
{
pdc_enable_intr(d, false);
@@ -220,6 +235,8 @@
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
#endif
+ .irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state,
+ .irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state,
};
static int qcom_pdc_translate(struct irq_domain *d,
diff --git a/drivers/leds/leds-qpnp-haptics.c b/drivers/leds/leds-qpnp-haptics.c
index ebdff87..fad36ea 100644
--- a/drivers/leds/leds-qpnp-haptics.c
+++ b/drivers/leds/leds-qpnp-haptics.c
@@ -1,5 +1,4 @@
-/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation.
- * All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -275,6 +274,7 @@
* @ last_rate_cfg - Last rate config updated
* @ wave_rep_cnt - waveform repeat count
* @ wave_s_rep_cnt - waveform sample repeat count
+ * @ wf_samp_len - waveform sample length
* @ ext_pwm_freq_khz - external pwm frequency in KHz
* @ ext_pwm_dtest_line - DTEST line for external pwm
* @ status_flags - status
@@ -330,6 +330,7 @@
u16 last_rate_cfg;
u32 wave_rep_cnt;
u32 wave_s_rep_cnt;
+ u32 wf_samp_len;
u32 ext_pwm_freq_khz;
u8 ext_pwm_dtest_line;
u32 status_flags;
@@ -445,6 +446,19 @@
return rc;
}
+static inline int get_buffer_mode_duration(struct hap_chip *chip)
+{
+ int sample_count, sample_duration;
+
+ sample_count = chip->wave_rep_cnt * chip->wave_s_rep_cnt *
+ chip->wf_samp_len;
+ sample_duration = sample_count * chip->wave_play_rate_us;
+ pr_debug("sample_count: %d sample_duration: %d\n", sample_count,
+ sample_duration);
+
+ return (sample_duration / 1000);
+}
+
static bool is_sw_lra_auto_resonance_control(struct hap_chip *chip)
{
if (chip->act_type != HAP_LRA)
@@ -735,11 +749,12 @@
goto out;
}
- if (chip->play_mode != HAP_BUFFER)
- hrtimer_start(&chip->stop_timer,
- ktime_set(time_ms / MSEC_PER_SEC,
- (time_ms % MSEC_PER_SEC) * NSEC_PER_MSEC),
- HRTIMER_MODE_REL);
+ if (chip->play_mode == HAP_BUFFER)
+ time_ms = get_buffer_mode_duration(chip);
+ hrtimer_start(&chip->stop_timer,
+ ktime_set(time_ms / MSEC_PER_SEC,
+ (time_ms % MSEC_PER_SEC) * NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
rc = qpnp_haptics_auto_res_enable(chip, true);
if (rc < 0) {
@@ -766,6 +781,9 @@
if (chip->play_mode == HAP_PWM)
pwm_disable(chip->pwm_data.pwm_dev);
+
+ if (chip->play_mode == HAP_BUFFER)
+ chip->wave_samp_idx = 0;
}
out:
@@ -1182,8 +1200,11 @@
if (time_ms <= 20) {
wave_samp[0] = HAP_WF_SAMP_MAX;
wave_samp[1] = HAP_WF_SAMP_MAX;
- if (time_ms > 15)
+ chip->wf_samp_len = 2;
+ if (time_ms > 15) {
wave_samp[2] = HAP_WF_SAMP_MAX;
+ chip->wf_samp_len = 3;
+ }
/* short pattern */
rc = qpnp_haptics_parse_buffer_dt(chip);
@@ -1302,33 +1323,20 @@
chip->wave_samp_idx += HAP_WAVE_SAMP_LEN;
if (chip->wave_samp_idx >= ARRAY_SIZE(chip->wave_samp)) {
pr_debug("Samples over\n");
- /* fall through to stop playing */
} else {
pr_debug("moving to next sample set %d\n",
chip->wave_samp_idx);
+ /* Moving to next set of wave sample */
rc = qpnp_haptics_buffer_config(chip, NULL, false);
if (rc < 0) {
pr_err("Error in configuring buffer, rc=%d\n",
rc);
goto irq_handled;
}
-
- /*
- * Moving to next set of wave sample. No need to stop
- * or change the play control. Just return.
- */
- goto irq_handled;
}
}
- rc = qpnp_haptics_play_control(chip, HAP_STOP);
- if (rc < 0) {
- pr_err("Error in disabling play, rc=%d\n", rc);
- goto irq_handled;
- }
- chip->wave_samp_idx = 0;
-
irq_handled:
return IRQ_HANDLED;
}
@@ -1638,6 +1646,7 @@
pos += bytes_read;
}
+ chip->wf_samp_len = i;
for (i = 0; i < ARRAY_SIZE(chip->wave_samp); i++)
chip->wave_samp[i] = samp[i];
@@ -1986,7 +1995,10 @@
/* Use default values */
for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
chip->wave_samp[i] = HAP_WF_SAMP_MAX;
+
+ wf_samp_len = HAP_WAVE_SAMP_LEN;
}
+ chip->wf_samp_len = wf_samp_len;
return 0;
}
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 7e6d999..d1222aa 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -196,6 +196,30 @@
return rc;
}
+int cam_context_handle_crm_process_evt(struct cam_context *ctx,
+ struct cam_req_mgr_link_evt_data *process_evt)
+{
+ int rc = 0;
+
+ if (!ctx->state_machine) {
+ CAM_ERR(CAM_CORE, "Context is not ready");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctx->ctx_mutex);
+ if (ctx->state_machine[ctx->state].crm_ops.process_evt) {
+ rc = ctx->state_machine[ctx->state].crm_ops.process_evt(ctx,
+ process_evt);
+ } else {
+ /* handling of this message is optional */
+ CAM_DBG(CAM_CORE, "No crm process evt in dev %d, state %d",
+ ctx->dev_hdl, ctx->state);
+ }
+ mutex_unlock(&ctx->ctx_mutex);
+
+ return rc;
+}
+
int cam_context_handle_acquire_dev(struct cam_context *ctx,
struct cam_acquire_dev_cmd *cmd)
{
@@ -257,10 +281,10 @@
int cam_context_handle_flush_dev(struct cam_context *ctx,
struct cam_flush_dev_cmd *cmd)
{
- int rc;
+ int rc = 0;
if (!ctx->state_machine) {
- CAM_ERR(CAM_CORE, "context is not ready");
+ CAM_ERR(CAM_CORE, "Context is not ready");
return -EINVAL;
}
@@ -274,9 +298,8 @@
rc = ctx->state_machine[ctx->state].ioctl_ops.flush_dev(
ctx, cmd);
} else {
- CAM_ERR(CAM_CORE, "No flush device in dev %d, state %d",
+ CAM_WARN(CAM_CORE, "No flush device in dev %d, state %d",
ctx->dev_hdl, ctx->state);
- rc = -EPROTO;
}
mutex_unlock(&ctx->ctx_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index c823b7a..af92b7e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -110,6 +110,7 @@
* @unlink: Unlink the context
* @apply_req: Apply setting for the context
* @flush_req: Flush request to remove request ids
+ * @process_evt: Handle event notification from CRM.(optional)
*
*/
struct cam_ctx_crm_ops {
@@ -123,6 +124,8 @@
struct cam_req_mgr_apply_request *apply);
int (*flush_req)(struct cam_context *ctx,
struct cam_req_mgr_flush_request *flush);
+ int (*process_evt)(struct cam_context *ctx,
+ struct cam_req_mgr_link_evt_data *evt_data);
};
@@ -273,6 +276,18 @@
struct cam_req_mgr_flush_request *apply);
/**
+ * cam_context_handle_crm_process_evt()
+ *
+ * @brief: Handle process event command
+ *
+ * @ctx: Object pointer for cam_context
+ * @process_evt: process event command payload
+ *
+ */
+int cam_context_handle_crm_process_evt(struct cam_context *ctx,
+ struct cam_req_mgr_link_evt_data *process_evt);
+
+/**
* cam_context_handle_acquire_dev()
*
* @brief: Handle acquire device command
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index aab1a1a..8ea920d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -430,6 +430,8 @@
uint32_t i;
int rc = 0;
+ CAM_DBG(CAM_CTXT, "E: NRT flush ctx");
+
/*
* flush pending requests, take the sync lock to synchronize with the
* sync callback thread so that the sync cb thread does not try to
@@ -444,23 +446,33 @@
while (!list_empty(&temp_list)) {
req = list_first_entry(&temp_list,
struct cam_ctx_request, list);
+
list_del_init(&req->list);
req->flushed = 1;
+
flush_args.flush_req_pending[flush_args.num_req_pending++] =
req->req_priv;
for (i = 0; i < req->num_out_map_entries; i++)
- if (req->out_map_entries[i].sync_id != -1)
- cam_sync_signal(req->out_map_entries[i].sync_id,
+ if (req->out_map_entries[i].sync_id != -1) {
+ rc = cam_sync_signal(
+ req->out_map_entries[i].sync_id,
CAM_SYNC_STATE_SIGNALED_ERROR);
+ if (rc == -EALREADY) {
+ CAM_ERR(CAM_CTXT,
+ "Req: %llu already signalled, sync_id:%d",
+ req->request_id,
+ req->out_map_entries[i].
+ sync_id);
+ break;
+ }
+ }
}
mutex_unlock(&ctx->sync_mutex);
if (ctx->hw_mgr_intf->hw_flush) {
flush_args.num_req_active = 0;
spin_lock(&ctx->lock);
- INIT_LIST_HEAD(&temp_list);
- list_splice_init(&ctx->active_req_list, &temp_list);
- list_for_each_entry(req, &temp_list, list) {
+ list_for_each_entry(req, &ctx->active_req_list, list) {
flush_args.flush_req_active[flush_args.num_req_active++]
= req->req_priv;
}
@@ -474,24 +486,42 @@
}
}
+ INIT_LIST_HEAD(&temp_list);
+ spin_lock(&ctx->lock);
+ list_splice_init(&ctx->active_req_list, &temp_list);
+ INIT_LIST_HEAD(&ctx->active_req_list);
+ spin_unlock(&ctx->lock);
+
while (!list_empty(&temp_list)) {
req = list_first_entry(&temp_list,
struct cam_ctx_request, list);
list_del_init(&req->list);
- for (i = 0; i < req->num_out_map_entries; i++)
+ for (i = 0; i < req->num_out_map_entries; i++) {
if (req->out_map_entries[i].sync_id != -1) {
- cam_sync_signal(req->out_map_entries[i].sync_id,
+ rc = cam_sync_signal(
+ req->out_map_entries[i].sync_id,
CAM_SYNC_STATE_SIGNALED_ERROR);
+ if (rc == -EALREADY) {
+ CAM_ERR(CAM_CTXT,
+ "Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d",
+ req->request_id, req->ctx,
+ req->ctx->dev_name,
+ req->ctx->dev_hdl,
+ req->ctx->state);
+ break;
+ }
}
+ }
spin_lock(&ctx->lock);
list_add_tail(&req->list, &ctx->free_req_list);
spin_unlock(&ctx->lock);
req->ctx = NULL;
}
- INIT_LIST_HEAD(&ctx->active_req_list);
- return rc;
+ CAM_DBG(CAM_CTXT, "X: NRT flush ctx");
+
+ return 0;
}
int32_t cam_context_flush_req_to_hw(struct cam_context *ctx,
@@ -502,6 +532,8 @@
uint32_t i;
int rc = 0;
+ CAM_DBG(CAM_CTXT, "E: NRT flush req");
+
flush_args.num_req_pending = 0;
flush_args.num_req_active = 0;
mutex_lock(&ctx->sync_mutex);
@@ -510,7 +542,9 @@
if (req->request_id != cmd->req_id)
continue;
+ list_del_init(&req->list);
req->flushed = 1;
+
flush_args.flush_req_pending[flush_args.num_req_pending++] =
req->req_priv;
break;
@@ -525,6 +559,8 @@
if (req->request_id != cmd->req_id)
continue;
+ list_del_init(&req->list);
+
flush_args.flush_req_active[
flush_args.num_req_active++] =
req->req_priv;
@@ -543,20 +579,31 @@
if (req) {
if (flush_args.num_req_pending || flush_args.num_req_active) {
- list_del_init(&req->list);
for (i = 0; i < req->num_out_map_entries; i++)
- if (req->out_map_entries[i].sync_id != -1)
- cam_sync_signal(
+ if (req->out_map_entries[i].sync_id != -1) {
+ rc = cam_sync_signal(
req->out_map_entries[i].sync_id,
CAM_SYNC_STATE_SIGNALED_ERROR);
- spin_lock(&ctx->lock);
- list_add_tail(&req->list, &ctx->free_req_list);
- spin_unlock(&ctx->lock);
- req->ctx = NULL;
+ if (rc == -EALREADY) {
+ CAM_ERR(CAM_CTXT,
+ "Req: %llu already signalled, sync_id:%d",
+ req->request_id,
+ req->out_map_entries[i].
+ sync_id);
+ break;
+ }
+ }
+ if (flush_args.num_req_active) {
+ spin_lock(&ctx->lock);
+ list_add_tail(&req->list, &ctx->free_req_list);
+ spin_unlock(&ctx->lock);
+ req->ctx = NULL;
+ }
}
}
+ CAM_DBG(CAM_CTXT, "X: NRT flush req");
- return rc;
+ return 0;
}
int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx,
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index a5977b3..4e9034e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -220,7 +220,7 @@
rc = cam_context_handle_flush_dev(ctx, flush);
if (rc)
- CAM_ERR(CAM_CORE, "FLush failure for node %s", node->name);
+ CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name);
return rc;
}
@@ -342,6 +342,25 @@
return cam_context_handle_crm_flush_req(ctx, flush);
}
+static int __cam_node_crm_process_evt(
+ struct cam_req_mgr_link_evt_data *evt_data)
+{
+ struct cam_context *ctx = NULL;
+
+ if (!evt_data) {
+ CAM_ERR(CAM_CORE, "Invalid process event request payload");
+ return -EINVAL;
+ }
+
+ ctx = (struct cam_context *) cam_get_device_priv(evt_data->dev_hdl);
+ if (!ctx) {
+ CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+ evt_data->dev_hdl);
+ return -EINVAL;
+ }
+ return cam_context_handle_crm_process_evt(ctx, evt_data);
+}
+
int cam_node_deinit(struct cam_node *node)
{
if (node)
@@ -394,6 +413,7 @@
node->crm_node_intf.get_dev_info = __cam_node_crm_get_dev_info;
node->crm_node_intf.link_setup = __cam_node_crm_link_setup;
node->crm_node_intf.flush_req = __cam_node_crm_flush_req;
+ node->crm_node_intf.process_evt = __cam_node_crm_process_evt;
mutex_init(&node->list_mutex);
INIT_LIST_HEAD(&node->free_ctx_list);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index 3ebe7a1..b04bc23 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,12 +16,19 @@
#include <linux/msm-bus.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "cam_cpas_hw.h"
#include "cam_cpas_hw_intf.h"
#include "cam_cpas_soc.h"
-#define CAM_CPAS_AXI_MIN_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_MNOC_AB_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_MNOC_IB_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000L)
+
+static uint cam_min_camnoc_ib_bw;
+module_param(cam_min_camnoc_ib_bw, uint, 0644);
int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
@@ -84,11 +91,19 @@
}
static int cam_cpas_util_vote_bus_client_bw(
- struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib)
+ struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib,
+ bool camnoc_bw)
{
struct msm_bus_paths *path;
struct msm_bus_scale_pdata *pdata;
int idx = 0;
+ uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
+
+ if (cam_min_camnoc_ib_bw > 0)
+ min_camnoc_ib_bw = (uint64_t)cam_min_camnoc_ib_bw * 1000000L;
+
+ CAM_DBG(CAM_CPAS, "cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu",
+ cam_min_camnoc_ib_bw, min_camnoc_ib_bw);
if (!bus_client->valid) {
CAM_ERR(CAM_CPAS, "bus client not valid");
@@ -118,11 +133,19 @@
bus_client->curr_vote_level = idx;
mutex_unlock(&bus_client->lock);
- if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_BW))
- ab = CAM_CPAS_AXI_MIN_BW;
+ if (camnoc_bw == true) {
+ if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_CAMNOC_AB_BW))
+ ab = CAM_CPAS_AXI_MIN_CAMNOC_AB_BW;
- if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_BW))
- ib = CAM_CPAS_AXI_MIN_BW;
+ if ((ib > 0) && (ib < min_camnoc_ib_bw))
+ ib = min_camnoc_ib_bw;
+ } else {
+ if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_MNOC_AB_BW))
+ ab = CAM_CPAS_AXI_MIN_MNOC_AB_BW;
+
+ if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_MNOC_IB_BW))
+ ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW;
+ }
pdata = bus_client->pdata;
path = &(pdata->usecase[idx]);
@@ -205,7 +228,7 @@
return -EINVAL;
if (bus_client->dyn_vote)
- cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0);
+ cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false);
else
cam_cpas_util_vote_bus_client_level(bus_client, 0);
@@ -370,7 +393,7 @@
list_for_each_entry_safe(curr_port, temp_port,
&cpas_core->axi_ports_list_head, sibling_port) {
rc = cam_cpas_util_vote_bus_client_bw(&curr_port->mnoc_bus,
- mnoc_bw, mnoc_bw);
+ mnoc_bw, mnoc_bw, false);
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed in mnoc vote, enable=%d, rc=%d",
@@ -380,13 +403,13 @@
if (soc_private->axi_camnoc_based) {
cam_cpas_util_vote_bus_client_bw(
- &curr_port->camnoc_bus, 0, camnoc_bw);
+ &curr_port->camnoc_bus, 0, camnoc_bw, true);
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed in mnoc vote, enable=%d, %d",
enable, rc);
cam_cpas_util_vote_bus_client_bw(
- &curr_port->mnoc_bus, 0, 0);
+ &curr_port->mnoc_bus, 0, 0, false);
goto remove_ahb_vote;
}
}
@@ -571,7 +594,7 @@
camnoc_bw, mnoc_bw);
rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
- mnoc_bw, mnoc_bw);
+ mnoc_bw, mnoc_bw, false);
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
@@ -581,7 +604,7 @@
if (soc_private->axi_camnoc_based) {
rc = cam_cpas_util_vote_bus_client_bw(&axi_port->camnoc_bus,
- 0, camnoc_bw);
+ 0, camnoc_bw, true);
if (rc) {
CAM_ERR(CAM_CPAS,
"Failed camnoc vote ab[%llu] ib[%llu] rc=%d",
@@ -880,9 +903,11 @@
goto done;
if (cpas_core->streamon_clients == 0) {
+ atomic_set(&cpas_core->irq_count, 1);
rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info,
applied_level);
if (rc) {
+ atomic_set(&cpas_core->irq_count, 0);
CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc);
goto done;
}
@@ -890,14 +915,17 @@
if (cpas_core->internal_ops.power_on) {
rc = cpas_core->internal_ops.power_on(cpas_hw);
if (rc) {
+ atomic_set(&cpas_core->irq_count, 0);
cam_cpas_soc_disable_resources(
- &cpas_hw->soc_info);
+ &cpas_hw->soc_info, true, true);
CAM_ERR(CAM_CPAS,
"failed in power_on settings rc=%d",
rc);
goto done;
}
}
+ CAM_DBG(CAM_CPAS, "irq_count=%d\n",
+ atomic_read(&cpas_core->irq_count));
cpas_hw->hw_state = CAM_HW_STATE_POWER_UP;
}
@@ -912,6 +940,10 @@
return rc;
}
+static int _check_irq_count(struct cam_cpas *cpas_core)
+{
+ return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1;
+}
static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
uint32_t arg_size)
@@ -924,6 +956,7 @@
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote;
int rc = 0;
+ long result;
if (!hw_priv || !stop_args) {
CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
@@ -972,11 +1005,29 @@
}
}
- rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+ rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info);
+ if (rc) {
+ CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc);
+ goto done;
+ }
+
+ /* Wait for any IRQs still being handled */
+ atomic_dec(&cpas_core->irq_count);
+ result = wait_event_timeout(cpas_core->irq_count_wq,
+ _check_irq_count(cpas_core), HZ);
+ if (result == 0) {
+ CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d",
+ atomic_read(&cpas_core->irq_count));
+ }
+
+ rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info,
+ true, false);
if (rc) {
CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc);
goto done;
}
+ CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n",
+ atomic_read(&cpas_core->irq_count));
cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
}
@@ -1427,6 +1478,8 @@
soc_private = (struct cam_cpas_private_soc *)
cpas_hw->soc_info.soc_private;
cpas_core->num_clients = soc_private->num_clients;
+ atomic_set(&cpas_core->irq_count, 0);
+ init_waitqueue_head(&cpas_core->irq_count_wq);
if (internal_ops->setup_regbase) {
rc = internal_ops->setup_regbase(&cpas_hw->soc_info,
@@ -1482,7 +1535,7 @@
if (rc)
goto disable_soc_res;
- rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+ rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
if (rc) {
CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
goto remove_default_vote;
@@ -1500,7 +1553,7 @@
return 0;
disable_soc_res:
- cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+ cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
remove_default_vote:
cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
axi_cleanup:
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
index aa3663d..05840bb 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -187,6 +187,8 @@
struct list_head axi_ports_list_head;
struct cam_cpas_internal_ops internal_ops;
struct workqueue_struct *work_queue;
+ atomic_t irq_count;
+ wait_queue_head_t irq_count_wq;
};
int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
index f85f461..b18af0a 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -209,13 +209,26 @@
return rc;
}
-int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info)
+int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
+ bool disable_clocks, bool disble_irq)
{
int rc = 0;
- rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+ rc = cam_soc_util_disable_platform_resource(soc_info,
+ disable_clocks, disble_irq);
if (rc)
CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc);
return rc;
}
+
+int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info)
+{
+ int rc = 0;
+
+ rc = cam_soc_util_irq_disable(soc_info);
+ if (rc)
+ CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc);
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
index d4fc039..fe0187e 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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,5 +61,7 @@
int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info);
int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info,
enum cam_vote_level default_level);
-int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info);
+int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
+ bool disable_clocks, bool disble_irq);
+int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info);
#endif /* _CAM_CPAS_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 0e5ce85..0533ed8 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -354,6 +354,11 @@
cpas_core = (struct cam_cpas *) cpas_hw->core_info;
soc_info = &cpas_hw->soc_info;
+ if (!atomic_inc_not_zero(&cpas_core->irq_count)) {
+ CAM_ERR(CAM_CPAS, "CPAS off");
+ return;
+ }
+
for (i = 0; i < camnoc_info->irq_err_size; i++) {
if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) &&
(camnoc_info->irq_err[i].enable)) {
@@ -398,6 +403,9 @@
~camnoc_info->irq_err[i].sbm_port;
}
}
+ atomic_dec(&cpas_core->irq_count);
+ wake_up(&cpas_core->irq_count_wq);
+ CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count));
if (payload->irq_status)
CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x",
@@ -414,9 +422,14 @@
int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC];
struct cam_cpas_work_payload *payload;
+ if (!atomic_inc_not_zero(&cpas_core->irq_count)) {
+ CAM_ERR(CAM_CPAS, "CPAS off");
+ return IRQ_HANDLED;
+ }
+
payload = kzalloc(sizeof(struct cam_cpas_work_payload), GFP_ATOMIC);
if (!payload)
- return IRQ_HANDLED;
+ goto done;
payload->irq_status = cam_io_r_mb(
soc_info->reg_map[camnoc_index].mem_base +
@@ -433,6 +446,9 @@
cam_cpastop_reset_irq(cpas_hw);
queue_work(cpas_core->work_queue, &payload->work);
+done:
+ atomic_dec(&cpas_core->irq_count);
+ wake_up(&cpas_core->irq_count_wq);
return IRQ_HANDLED;
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
index b7b636c..d2314c4 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -138,9 +138,22 @@
int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info,
uint32_t clk_rate)
{
+ int32_t src_clk_idx;
+
if (!soc_info)
return -EINVAL;
+ src_clk_idx = soc_info->src_clk_idx;
+
+ if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) &&
+ (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
+ (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
+ CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d",
+ clk_rate,
+ soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
+ clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
+ }
+
return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
}
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 0012b34..3bbb8d3 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -116,7 +116,12 @@
if (ctx_data->clk_info.clk_rate[i] >= base_clk)
return i;
- return 0;
+ /*
+ * Caller has to ensure returned index is within array
+ * size bounds while accessing that index.
+ */
+
+ return i;
}
static bool cam_icp_is_over_clk(struct cam_icp_hw_mgr *hw_mgr,
@@ -132,7 +137,7 @@
curr_clk_idx = cam_icp_get_actual_clk_rate_idx(ctx_data,
hw_mgr_clk_info->curr_clk);
- CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %lld %lld",
+ CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %d %d",
base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk,
hw_mgr_clk_info->curr_clk);
@@ -192,9 +197,9 @@
struct cam_hw_info *dev = NULL;
if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
- dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
+ dev_intf = hw_mgr->bps_dev_intf;
else
- dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
+ dev_intf = hw_mgr->ipe0_dev_intf;
if (!dev_intf) {
CAM_ERR(CAM_ICP, "dev_intf is invalid");
@@ -254,9 +259,9 @@
struct cam_hw_intf *dev_intf = NULL;
struct cam_a5_clk_update_cmd clk_upd_cmd;
- ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
- ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
- bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
+ ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+ ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+ bps_dev_intf = hw_mgr->bps_dev_intf;
clk_info->base_clk = 0;
clk_info->curr_clk = 0;
@@ -305,7 +310,120 @@
return 0;
}
-static void cam_icp_timer_cb(unsigned long data)
+static int32_t cam_icp_ctx_timer(void *priv, void *data)
+{
+ struct clk_work_data *task_data = (struct clk_work_data *)data;
+ struct cam_icp_hw_ctx_data *ctx_data =
+ (struct cam_icp_hw_ctx_data *)task_data->data;
+ struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr;
+ uint32_t id;
+ struct cam_hw_intf *ipe0_dev_intf = NULL;
+ struct cam_hw_intf *ipe1_dev_intf = NULL;
+ struct cam_hw_intf *bps_dev_intf = NULL;
+ struct cam_hw_intf *dev_intf = NULL;
+ struct cam_icp_clk_info *clk_info;
+ struct cam_icp_cpas_vote clk_update;
+
+ if (!ctx_data) {
+ CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctx_data->ctx_mutex);
+ if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) ||
+ (ctx_data->watch_dog_reset_counter == 0)) {
+ CAM_DBG(CAM_ICP, "state %d, counter=%d",
+ ctx_data->state, ctx_data->watch_dog_reset_counter);
+ mutex_unlock(&ctx_data->ctx_mutex);
+ return 0;
+ }
+
+ CAM_DBG(CAM_ICP,
+ "E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
+ ctx_data->ctx_id,
+ ctx_data->clk_info.uncompressed_bw,
+ ctx_data->clk_info.compressed_bw,
+ ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk);
+
+ ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+ ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+ bps_dev_intf = hw_mgr->bps_dev_intf;
+
+ if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
+ CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
+ mutex_unlock(&ctx_data->ctx_mutex);
+ return -EINVAL;
+ }
+
+ if (!ctx_data->icp_dev_acquire_info) {
+ CAM_WARN(CAM_ICP, "NULL acquire info");
+ mutex_unlock(&ctx_data->ctx_mutex);
+ return -EINVAL;
+ }
+
+ if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
+ dev_intf = bps_dev_intf;
+ clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
+ id = CAM_ICP_BPS_CMD_VOTE_CPAS;
+ } else {
+ dev_intf = ipe0_dev_intf;
+ clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
+ id = CAM_ICP_IPE_CMD_VOTE_CPAS;
+ }
+
+ clk_info->compressed_bw -= ctx_data->clk_info.compressed_bw;
+ clk_info->uncompressed_bw -= ctx_data->clk_info.uncompressed_bw;
+ ctx_data->clk_info.uncompressed_bw = 0;
+ ctx_data->clk_info.compressed_bw = 0;
+ ctx_data->clk_info.curr_fc = 0;
+ ctx_data->clk_info.base_clk = 0;
+
+ clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC;
+ clk_update.ahb_vote.vote.freq = clk_info->curr_clk;
+ clk_update.ahb_vote_valid = true;
+ clk_update.axi_vote.compressed_bw = clk_info->compressed_bw;
+ clk_update.axi_vote.uncompressed_bw = clk_info->uncompressed_bw;
+ clk_update.axi_vote_valid = true;
+ dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
+ &clk_update, sizeof(clk_update));
+
+ CAM_DBG(CAM_ICP,
+ "X :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
+ ctx_data->ctx_id,
+ ctx_data->clk_info.uncompressed_bw,
+ ctx_data->clk_info.compressed_bw,
+ ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk);
+
+ mutex_unlock(&ctx_data->ctx_mutex);
+
+ return 0;
+}
+
+static void cam_icp_ctx_timer_cb(unsigned long data)
+{
+ unsigned long flags;
+ struct crm_workq_task *task;
+ struct clk_work_data *task_data;
+ struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
+
+ spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags);
+ task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
+ if (!task) {
+ CAM_ERR(CAM_ICP, "no empty task");
+ spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
+ return;
+ }
+
+ task_data = (struct clk_work_data *)task->payload;
+ task_data->data = timer->parent;
+ task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
+ task->process_cb = cam_icp_ctx_timer;
+ cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
+ CRM_TASK_PRIORITY_0);
+ spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
+}
+
+static void cam_icp_device_timer_cb(unsigned long data)
{
unsigned long flags;
struct crm_workq_task *task;
@@ -342,13 +460,29 @@
hw_mgr->clk_info[i].uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
hw_mgr->clk_info[i].compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
hw_mgr->clk_info[i].hw_type = i;
+ hw_mgr->clk_info[i].watch_dog_reset_counter = 0;
}
hw_mgr->icp_default_clk = ICP_CLK_SVS_HZ;
return 0;
}
-static int cam_icp_timer_start(struct cam_icp_hw_mgr *hw_mgr)
+static int cam_icp_ctx_timer_start(struct cam_icp_hw_ctx_data *ctx_data)
+{
+ int rc = 0;
+
+ rc = crm_timer_init(&ctx_data->watch_dog,
+ 2000, ctx_data, &cam_icp_ctx_timer_cb);
+ if (rc)
+ CAM_ERR(CAM_ICP, "Failed to start timer");
+
+ ctx_data->watch_dog_reset_counter = 0;
+
+ CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id);
+ return rc;
+}
+
+static int cam_icp_device_timer_start(struct cam_icp_hw_mgr *hw_mgr)
{
int rc = 0;
int i;
@@ -356,21 +490,70 @@
for (i = 0; i < ICP_CLK_HW_MAX; i++) {
if (!hw_mgr->clk_info[i].watch_dog) {
rc = crm_timer_init(&hw_mgr->clk_info[i].watch_dog,
- 3000, &hw_mgr->clk_info[i], &cam_icp_timer_cb);
+ 3000, &hw_mgr->clk_info[i],
+ &cam_icp_device_timer_cb);
+
if (rc)
CAM_ERR(CAM_ICP, "Failed to start timer %d", i);
+
+ hw_mgr->clk_info[i].watch_dog_reset_counter = 0;
}
}
return rc;
}
-static void cam_icp_timer_stop(struct cam_icp_hw_mgr *hw_mgr)
+static int cam_icp_ctx_timer_stop(struct cam_icp_hw_ctx_data *ctx_data)
{
- if (!hw_mgr->bps_ctxt_cnt)
+ if (ctx_data->watch_dog) {
+ CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id);
+ ctx_data->watch_dog_reset_counter = 0;
+ crm_timer_exit(&ctx_data->watch_dog);
+ ctx_data->watch_dog = NULL;
+ }
+
+ return 0;
+}
+
+static void cam_icp_device_timer_stop(struct cam_icp_hw_mgr *hw_mgr)
+{
+ if (!hw_mgr->bps_ctxt_cnt &&
+ hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog) {
+ hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog_reset_counter = 0;
crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
- else if (!hw_mgr->ipe_ctxt_cnt)
+ hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog = NULL;
+ }
+
+ if (!hw_mgr->ipe_ctxt_cnt &&
+ hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog) {
+ hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog_reset_counter = 0;
crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
+ hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog = NULL;
+ }
+}
+
+static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data)
+{
+ if (ctx_data && ctx_data->watch_dog) {
+ ctx_data->watch_dog_reset_counter++;
+ CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d",
+ ctx_data->ctx_id, ctx_data->watch_dog_reset_counter);
+ crm_timer_reset(ctx_data->watch_dog);
+ }
+
+ return 0;
+}
+
+static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr,
+ int device_index)
+{
+ if ((device_index >= ICP_CLK_HW_MAX) || (!hw_mgr))
+ return;
+
+ if (hw_mgr->clk_info[device_index].watch_dog) {
+ crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog);
+ hw_mgr->clk_info[device_index].watch_dog_reset_counter++;
+ }
}
static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles,
@@ -420,7 +603,9 @@
for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
ctx_data = &hw_mgr->ctx_data[i];
if (ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED &&
- ctx_data->icp_dev_acquire_info->dev_type == dev_type)
+ ICP_DEV_TYPE_TO_CLK_TYPE(
+ ctx_data->icp_dev_acquire_info->dev_type) ==
+ ICP_DEV_TYPE_TO_CLK_TYPE(dev_type))
hw_mgr_clk_info->base_clk +=
ctx_data->clk_info.base_clk;
}
@@ -575,7 +760,8 @@
hw_mgr_clk_info->over_clked = 0;
rc = false;
} else if (hw_mgr_clk_info->curr_clk < hw_mgr_clk_info->base_clk) {
- hw_mgr_clk_info->curr_clk = hw_mgr_clk_info->base_clk;
+ hw_mgr_clk_info->curr_clk = cam_icp_get_actual_clk_rate(hw_mgr,
+ ctx_data, hw_mgr_clk_info->base_clk);
rc = true;
}
mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -633,7 +819,13 @@
* recalculate bandwidth of all contexts of same hardware and update
* voting of bandwidth
*/
- if (clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw)
+ CAM_DBG(CAM_ICP, "ubw ctx = %lld clk_info ubw = %lld busy = %d",
+ ctx_data->clk_info.uncompressed_bw,
+ clk_info->uncompressed_bw, busy);
+
+ if ((clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw) &&
+ (ctx_data->clk_info.uncompressed_bw ==
+ hw_mgr_clk_info->uncompressed_bw))
return false;
if (busy &&
@@ -647,13 +839,18 @@
for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
ctx = &hw_mgr->ctx_data[i];
if (ctx->state == CAM_ICP_CTX_STATE_ACQUIRED &&
- ctx->icp_dev_acquire_info->dev_type ==
- ctx_data->icp_dev_acquire_info->dev_type) {
+ ICP_DEV_TYPE_TO_CLK_TYPE(
+ ctx->icp_dev_acquire_info->dev_type) ==
+ ICP_DEV_TYPE_TO_CLK_TYPE(
+ ctx_data->icp_dev_acquire_info->dev_type)) {
mutex_lock(&hw_mgr->hw_mgr_mutex);
hw_mgr_clk_info->uncompressed_bw +=
ctx->clk_info.uncompressed_bw;
hw_mgr_clk_info->compressed_bw +=
ctx->clk_info.compressed_bw;
+ CAM_DBG(CAM_ICP, "ubw = %lld, cbw = %lld",
+ hw_mgr_clk_info->uncompressed_bw,
+ hw_mgr_clk_info->compressed_bw);
mutex_unlock(&hw_mgr->hw_mgr_mutex);
}
}
@@ -671,12 +868,13 @@
uint64_t req_id;
struct cam_icp_clk_info *hw_mgr_clk_info;
+ cam_icp_ctx_timer_reset(ctx_data);
if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
- crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
+ cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_BPS);
hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
CAM_DBG(CAM_ICP, "Reset bps timer");
} else {
- crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
+ cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_IPE);
hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
CAM_DBG(CAM_ICP, "Reset ipe timer");
}
@@ -827,11 +1025,13 @@
dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
&clk_update, sizeof(clk_update));
- if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS)
- if (ipe1_dev_intf)
- ipe1_dev_intf->hw_ops.process_cmd(
- ipe1_dev_intf->hw_priv, id,
- &clk_update, sizeof(clk_update));
+ /*
+ * Consolidated bw needs to be voted on only one IPE client. Otherwise
+ * total bw that we vote at bus client would be doubled. So either
+ * remove voting on IPE1 or divide the vote for each IPE client
+ * and vote to cpas - cpas will add up and vote full bw to sf client
+ * anyway.
+ */
return 0;
}
@@ -1174,9 +1374,10 @@
clk_type = ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->icp_dev_acquire_info->
dev_type);
- crm_timer_reset(icp_hw_mgr.clk_info[clk_type].watch_dog);
+ cam_icp_device_timer_reset(&icp_hw_mgr, clk_type);
mutex_lock(&ctx_data->ctx_mutex);
+ cam_icp_ctx_timer_reset(ctx_data);
if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) {
CAM_DBG(CAM_ICP, "ctx %u is in %d state",
ctx_data->ctx_id, ctx_data->state);
@@ -2063,6 +2264,7 @@
kfree(hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info);
hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_FREE;
+ cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]);
mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
CAM_DBG(CAM_ICP, "X: ctx_id = %d", ctx_id);
@@ -2386,34 +2588,24 @@
}
a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
rc = cam_icp_allocate_hfi_mem();
- if (rc) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ if (rc)
goto alloc_hfi_mem_failed;
- }
rc = cam_icp_mgr_device_init(hw_mgr);
- if (rc) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ if (rc)
goto dev_init_fail;
- }
rc = cam_icp_mgr_fw_download(hw_mgr);
- if (rc) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ if (rc)
goto fw_download_failed;
- }
rc = cam_icp_mgr_hfi_init(hw_mgr);
- if (rc) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ if (rc)
goto hfi_init_failed;
- }
rc = cam_icp_mgr_send_fw_init(hw_mgr);
- if (rc) {
- mutex_unlock(&hw_mgr->hw_mgr_mutex);
+ if (rc)
goto fw_init_failed;
- }
hw_mgr->ctxt_cnt = 0;
hw_mgr->fw_download = true;
@@ -2444,6 +2636,7 @@
dev_init_fail:
cam_icp_free_hfi_mem();
alloc_hfi_mem_failed:
+ mutex_unlock(&hw_mgr->hw_mgr_mutex);
return rc;
}
@@ -3177,7 +3370,7 @@
mutex_unlock(&hw_mgr->hw_mgr_mutex);
if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
- cam_icp_timer_stop(hw_mgr);
+ cam_icp_device_timer_stop(hw_mgr);
CAM_DBG(CAM_ICP, "Exit");
return rc;
@@ -3464,6 +3657,9 @@
goto get_io_buf_failed;
}
+ if (icp_hw_mgr.a5_debug_q)
+ hfi_set_debug_level(icp_hw_mgr.a5_dbg_lvl);
+
rc = cam_icp_send_ubwc_cfg(hw_mgr);
if (rc) {
mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -3472,7 +3668,9 @@
}
if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
- cam_icp_timer_start(hw_mgr);
+ cam_icp_device_timer_start(hw_mgr);
+
+ cam_icp_ctx_timer_start(ctx_data);
rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
if (rc) {
@@ -3539,6 +3737,7 @@
send_ping_failed:
cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, ctx_data, 0);
ipe_bps_resume_failed:
+ cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]);
ubwc_cfg_failed:
if (!hw_mgr->ctxt_cnt)
cam_icp_mgr_icp_power_collapse(hw_mgr);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 85f5b550..4d181f0 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -183,6 +183,8 @@
* @temp_payload: Payload for destroy handle data
* @ctx_id: Context Id
* @clk_info: Current clock info of a context
+ * @watch_dog: watchdog timer handle
+ * @watch_dog_reset_counter: Counter for watch dog reset
*/
struct cam_icp_hw_ctx_data {
void *context_priv;
@@ -200,6 +202,8 @@
struct ipe_bps_destroy temp_payload;
uint32_t ctx_id;
struct cam_ctx_clk_info clk_info;
+ struct cam_req_mgr_timer *watch_dog;
+ uint32_t watch_dog_reset_counter;
};
/**
@@ -222,6 +226,7 @@
* @compressed_bw: Current compressed bandwidth voting
* @hw_type: IPE/BPS device type
* @watch_dog: watchdog timer handle
+ * @watch_dog_reset_counter: Counter for watch dog reset
*/
struct cam_icp_clk_info {
uint32_t base_clk;
@@ -232,6 +237,7 @@
uint64_t compressed_bw;
uint32_t hw_type;
struct cam_req_mgr_timer *watch_dog;
+ uint32_t watch_dog_reset_counter;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index d2e04ef..771c4ed 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -21,7 +21,7 @@
#define ICP_CLK_TURBO_HZ 600000000
#define ICP_CLK_SVS_HZ 400000000
-#define CAM_ICP_A5_BW_BYTES_VOTE 100000000
+#define CAM_ICP_A5_BW_BYTES_VOTE 40000000
#define CAM_ICP_CTX_MAX 36
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
index 289d7d4..d24305a 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -141,9 +141,22 @@
int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info,
uint32_t clk_rate)
{
+ int32_t src_clk_idx;
+
if (!soc_info)
return -EINVAL;
+ src_clk_idx = soc_info->src_clk_idx;
+
+ if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) &&
+ (soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
+ (clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
+ CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d",
+ clk_rate,
+ soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
+ clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
+ }
+
return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
}
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index d1153ba..46c4c6a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -896,6 +896,29 @@
return rc;
}
+static int __cam_isp_ctx_sof_in_flush(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ int rc = 0;
+ struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
+
+ if (!evt_data) {
+ CAM_ERR(CAM_ISP, "in valid sof event data");
+ return -EINVAL;
+ }
+ ctx_isp->frame_id++;
+ ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+ CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+ ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+ if (--ctx_isp->frame_skip_count == 0)
+ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+ else
+ CAM_ERR(CAM_ISP, "Skip currect SOF");
+
+ return rc;
+}
+
static struct cam_isp_ctx_irq_ops
cam_isp_ctx_activated_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
/* SOF */
@@ -967,6 +990,17 @@
/* HALT */
{
},
+ /* FLUSH */
+ {
+ .irq_ops = {
+ NULL,
+ __cam_isp_ctx_sof_in_flush,
+ NULL,
+ NULL,
+ NULL,
+ __cam_isp_ctx_buf_done_in_applied,
+ },
+ },
};
static int __cam_isp_ctx_apply_req_in_activated_state(
@@ -1170,6 +1204,24 @@
return rc;
}
+static int __cam_isp_ctx_flush_req_in_activated(
+ struct cam_context *ctx,
+ struct cam_req_mgr_flush_request *flush_req)
+{
+ int rc = 0;
+ struct cam_isp_context *ctx_isp;
+
+ ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+ spin_lock_bh(&ctx->lock);
+ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_FLUSH;
+ ctx_isp->frame_skip_count = 2;
+ spin_unlock_bh(&ctx->lock);
+
+ CAM_DBG(CAM_ISP, "Flush request in state %d", ctx->state);
+ rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
+ return rc;
+}
+
static int __cam_isp_ctx_flush_req_in_ready(
struct cam_context *ctx,
struct cam_req_mgr_flush_request *flush_req)
@@ -1230,12 +1282,24 @@
.crm_ops = {},
.irq_ops = NULL,
},
+ /* HW ERROR */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
/* HALT */
{
.ioctl_ops = {},
.crm_ops = {},
.irq_ops = NULL,
},
+ /* FLUSH */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
};
static int __cam_isp_ctx_rdi_only_sof_in_top_state(
@@ -1601,10 +1665,23 @@
__cam_isp_ctx_buf_done_in_bubble_applied,
},
},
-
+ /* HW ERROR */
+ {
+ },
/* HALT */
{
},
+ /* FLUSH */
+ {
+ .irq_ops = {
+ NULL,
+ __cam_isp_ctx_sof_in_flush,
+ NULL,
+ NULL,
+ NULL,
+ __cam_isp_ctx_buf_done_in_applied,
+ },
+ },
};
static int __cam_isp_ctx_rdi_only_apply_req_top_state(
@@ -1660,15 +1737,26 @@
.crm_ops = {},
.irq_ops = NULL,
},
+ /* HW ERROR */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
/* HALT */
{
.ioctl_ops = {},
.crm_ops = {},
.irq_ops = NULL,
},
+ /* FLUSHED */
+ {
+ .ioctl_ops = {},
+ .crm_ops = {},
+ .irq_ops = NULL,
+ },
};
-
/* top level state machine */
static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
struct cam_release_dev_cmd *cmd)
@@ -2212,6 +2300,58 @@
return rc;
}
+static int __cam_isp_ctx_link_pause(struct cam_context *ctx)
+{
+ int rc = 0;
+ struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_isp_context *ctx_isp =
+ (struct cam_isp_context *) ctx->ctx_priv;
+
+ hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW;
+ rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+ &hw_cmd_args);
+
+ return rc;
+}
+
+static int __cam_isp_ctx_link_resume(struct cam_context *ctx)
+{
+ int rc = 0;
+ struct cam_isp_hw_cmd_args hw_cmd_args;
+ struct cam_isp_context *ctx_isp =
+ (struct cam_isp_context *) ctx->ctx_priv;
+
+ hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+ hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW;
+ rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+ &hw_cmd_args);
+
+ return rc;
+}
+
+static int __cam_isp_ctx_process_evt(struct cam_context *ctx,
+ struct cam_req_mgr_link_evt_data *link_evt_data)
+{
+ int rc = 0;
+
+ switch (link_evt_data->evt_type) {
+ case CAM_REQ_MGR_LINK_EVT_ERR:
+ /* No need to handle this message now */
+ break;
+ case CAM_REQ_MGR_LINK_EVT_PAUSE:
+ __cam_isp_ctx_link_pause(ctx);
+ break;
+ case CAM_REQ_MGR_LINK_EVT_RESUME:
+ __cam_isp_ctx_link_resume(ctx);
+ break;
+ default:
+ CAM_WARN(CAM_ISP, "Unknown event from CRM");
+ break;
+ }
+ return rc;
+}
+
static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx,
struct cam_req_mgr_core_dev_link_setup *unlink)
{
@@ -2343,7 +2483,8 @@
.crm_ops = {
.unlink = __cam_isp_ctx_unlink_in_activated,
.apply_req = __cam_isp_ctx_apply_req,
- .flush_req = __cam_isp_ctx_flush_req_in_top_state,
+ .flush_req = __cam_isp_ctx_flush_req_in_activated,
+ .process_evt = __cam_isp_ctx_process_evt,
},
.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
},
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index 88ebc03..b0b7ae9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -52,6 +52,7 @@
CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED,
CAM_ISP_CTX_ACTIVATED_HW_ERROR,
CAM_ISP_CTX_ACTIVATED_HALT,
+ CAM_ISP_CTX_ACTIVATED_FLUSH,
CAM_ISP_CTX_ACTIVATED_MAX,
};
@@ -116,6 +117,7 @@
* @subscribe_event: The irq event mask that CRM subscribes to, IFE will
* invoke CRM cb at those event.
* @last_applied_req_id: Last applied request id
+ * @frame_skip_count: Number of frame to skip before change state
*
*/
struct cam_isp_context {
@@ -135,6 +137,7 @@
int64_t reported_req_id;
uint32_t subscribe_event;
int64_t last_applied_req_id;
+ uint32_t frame_skip_count;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 8d41ae7..fda6427 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -860,10 +860,95 @@
return rc;
}
-static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
+static int cam_ife_mgr_acquire_cid_res(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
- uint32_t cid_res_id)
+ uint32_t *cid_res_id,
+ enum cam_ife_pix_path_res_id csid_path)
+{
+ int rc = -1;
+ int i, j;
+ struct cam_ife_hw_mgr *ife_hw_mgr;
+ struct cam_ife_hw_mgr_res *cid_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_csid_hw_reserve_resource_args csid_acquire;
+
+ ife_hw_mgr = ife_ctx->hw_mgr;
+
+ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+ goto err;
+ }
+ cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
+
+ csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
+ csid_acquire.in_port = in_port;
+ csid_acquire.res_id = csid_path;
+
+ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+ if (!ife_hw_mgr->csid_devices[i])
+ continue;
+
+ hw_intf = ife_hw_mgr->csid_devices[i];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
+ sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else
+ break;
+ }
+
+ if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
+ CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
+ goto err;
+ }
+
+ cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
+ cid_res->res_id = csid_acquire.node_res->res_id;
+ cid_res->is_dual_vfe = in_port->usage_type;
+ cid_res->hw_res[0] = csid_acquire.node_res;
+ cid_res->hw_res[1] = NULL;
+ /* CID(DT_ID) value of acquire device, require for path */
+ *cid_res_id = csid_acquire.node_res->res_id;
+
+ if (cid_res->is_dual_vfe) {
+ csid_acquire.node_res = NULL;
+ csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
+ csid_acquire.in_port = in_port;
+ for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
+ if (!ife_hw_mgr->csid_devices[j])
+ continue;
+
+ hw_intf = ife_hw_mgr->csid_devices[j];
+ rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+ &csid_acquire, sizeof(csid_acquire));
+ if (rc)
+ continue;
+ else
+ break;
+ }
+
+ if (j == CAM_IFE_CSID_HW_NUM_MAX) {
+ CAM_ERR(CAM_ISP,
+ "Can not acquire ife csid rdi resource");
+ goto err;
+ }
+ cid_res->hw_res[1] = csid_acquire.node_res;
+ }
+ cid_res->parent = &ife_ctx->res_list_ife_in;
+ ife_ctx->res_list_ife_in.child[
+ ife_ctx->res_list_ife_in.num_children++] = cid_res;
+
+ return 0;
+err:
+ return rc;
+
+}
+
+static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
+ struct cam_ife_hw_mgr_ctx *ife_ctx,
+ struct cam_isp_in_port_info *in_port)
{
int rc = -1;
int i;
@@ -872,8 +957,17 @@
struct cam_ife_hw_mgr_res *csid_res;
struct cam_ife_hw_mgr_res *cid_res;
struct cam_hw_intf *hw_intf;
+ uint32_t cid_res_id;
struct cam_csid_hw_reserve_resource_args csid_acquire;
+ /* get cid resource */
+ rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+ CAM_IFE_PIX_PATH_RES_IPP);
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+ goto err;
+ }
+
ife_hw_mgr = ife_ctx->hw_mgr;
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res);
@@ -985,8 +1079,7 @@
static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
struct cam_ife_hw_mgr_ctx *ife_ctx,
- struct cam_isp_in_port_info *in_port,
- uint32_t cid_res_id)
+ struct cam_isp_in_port_info *in_port)
{
int rc = -1;
int i, j;
@@ -996,6 +1089,7 @@
struct cam_ife_hw_mgr_res *cid_res;
struct cam_hw_intf *hw_intf;
struct cam_isp_out_port_info *out_port;
+ uint32_t cid_res_id;
struct cam_csid_hw_reserve_resource_args csid_acquire;
ife_hw_mgr = ife_ctx->hw_mgr;
@@ -1005,6 +1099,15 @@
if (!cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
continue;
+ /* get cid resource */
+ rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+ cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+ out_port->res_type));
+ if (rc) {
+ CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+ goto err;
+ }
+
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
&csid_res);
if (rc) {
@@ -1135,91 +1238,6 @@
return 0;
}
-static int cam_ife_mgr_acquire_cid_res(
- struct cam_ife_hw_mgr_ctx *ife_ctx,
- struct cam_isp_in_port_info *in_port,
- uint32_t *cid_res_id,
- int pixel_count)
-{
- int rc = -1;
- int i, j;
- struct cam_ife_hw_mgr *ife_hw_mgr;
- struct cam_ife_hw_mgr_res *cid_res;
- struct cam_hw_intf *hw_intf;
- struct cam_csid_hw_reserve_resource_args csid_acquire;
-
- ife_hw_mgr = ife_ctx->hw_mgr;
-
- rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
- if (rc) {
- CAM_ERR(CAM_ISP, "No more free hw mgr resource");
- goto err;
- }
- cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
-
- csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
- csid_acquire.in_port = in_port;
- csid_acquire.pixel_count = pixel_count;
-
- for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
- if (!ife_hw_mgr->csid_devices[i])
- continue;
-
- hw_intf = ife_hw_mgr->csid_devices[i];
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
- sizeof(csid_acquire));
- if (rc)
- continue;
- else
- break;
- }
-
- if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
- CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
- goto err;
- }
-
- cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
- cid_res->res_id = csid_acquire.node_res->res_id;
- cid_res->is_dual_vfe = in_port->usage_type;
- cid_res->hw_res[0] = csid_acquire.node_res;
- cid_res->hw_res[1] = NULL;
- /* CID(DT_ID) value of acquire device, require for path */
- *cid_res_id = csid_acquire.node_res->res_id;
-
- if (cid_res->is_dual_vfe) {
- csid_acquire.node_res = NULL;
- csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
- csid_acquire.in_port = in_port;
- for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
- if (!ife_hw_mgr->csid_devices[j])
- continue;
-
- hw_intf = ife_hw_mgr->csid_devices[j];
- rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
- &csid_acquire, sizeof(csid_acquire));
- if (rc)
- continue;
- else
- break;
- }
-
- if (j == CAM_IFE_CSID_HW_NUM_MAX) {
- CAM_ERR(CAM_ISP,
- "Can not acquire ife csid rdi resource");
- goto err;
- }
- cid_res->hw_res[1] = csid_acquire.node_res;
- }
- cid_res->parent = &ife_ctx->res_list_ife_in;
- ife_ctx->res_list_ife_in.child[
- ife_ctx->res_list_ife_in.num_children++] = cid_res;
-
- return 0;
-err:
- return rc;
-
-}
static int cam_ife_mgr_acquire_hw_for_ctx(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_info *in_port,
@@ -1229,7 +1247,6 @@
int is_dual_vfe = 0;
int pixel_count = 0;
int rdi_count = 0;
- uint32_t cid_res_id = 0;
is_dual_vfe = in_port->usage_type;
@@ -1248,18 +1265,9 @@
return -EINVAL;
}
- /* get cid resource */
- rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
- pixel_count);
- if (rc) {
- CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
- goto err;
- }
-
if (pixel_count) {
/* get ife csid IPP resrouce */
- rc = cam_ife_hw_mgr_acquire_res_ife_csid_ipp(ife_ctx, in_port,
- cid_res_id);
+ rc = cam_ife_hw_mgr_acquire_res_ife_csid_ipp(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP,
"Acquire IFE CSID IPP resource Failed");
@@ -1269,8 +1277,7 @@
if (rdi_count) {
/* get ife csid rdi resource */
- rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port,
- cid_res_id);
+ rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP,
"Acquire IFE CSID RDI resource Failed");
@@ -2488,6 +2495,53 @@
return rc;
}
+static int cam_ife_mgr_bw_control(struct cam_ife_hw_mgr_ctx *ctx,
+ enum cam_vfe_bw_control_action action)
+{
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_vfe_bw_control_args bw_ctrl_args;
+ int rc = -EINVAL;
+ uint32_t i;
+
+ CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index);
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ if (hw_intf && hw_intf->hw_ops.process_cmd) {
+ bw_ctrl_args.node_res =
+ hw_mgr_res->hw_res[i];
+ bw_ctrl_args.action = action;
+
+ rc = hw_intf->hw_ops.process_cmd(
+ hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_BW_CONTROL,
+ &bw_ctrl_args,
+ sizeof(struct cam_vfe_bw_control_args));
+ if (rc)
+ CAM_ERR(CAM_ISP, "BW Update failed");
+ } else
+ CAM_WARN(CAM_ISP, "NULL hw_intf!");
+ }
+ }
+
+ return rc;
+}
+
+static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx)
+{
+ return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE);
+}
+
+static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx)
+{
+ return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE);
+}
+
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
int rc = 0;
@@ -2513,6 +2567,12 @@
hw_cmd_args->u.is_rdi_only_context = 0;
break;
+ case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
+ cam_ife_mgr_pause_hw(ctx);
+ break;
+ case CAM_ISP_HW_MGR_CMD_RESUME_HW:
+ cam_ife_mgr_resume_hw(ctx);
+ break;
default:
CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
hw_cmd_args->cmd_type);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index cf044eb..56f2d68 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -130,6 +130,8 @@
/* enum cam_isp_hw_mgr_command - Hardware manager command type */
enum cam_isp_hw_mgr_command {
CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT,
+ CAM_ISP_HW_MGR_CMD_PAUSE_HW,
+ CAM_ISP_HW_MGR_CMD_RESUME_HW,
CAM_ISP_HW_MGR_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index bce0374..ff0c91f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -287,7 +287,7 @@
static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
- uint32_t res_type, int pixel_count)
+ uint32_t res_type)
{
int rc = 0;
struct cam_ife_csid_cid_data *cid_data;
@@ -305,8 +305,7 @@
break;
}
} else {
- if (cid_data->vc == vc && cid_data->dt == dt &&
- cid_data->pixel_count == pixel_count) {
+ if (cid_data->vc == vc && cid_data->dt == dt) {
cid_data->cnt++;
*res = &csid_hw->cid_res[i];
break;
@@ -330,7 +329,6 @@
cid_data->vc = vc;
cid_data->dt = dt;
cid_data->cnt = 1;
- cid_data->pixel_count = pixel_count;
csid_hw->cid_res[j].res_state =
CAM_ISP_RESOURCE_STATE_RESERVED;
*res = &csid_hw->cid_res[j];
@@ -570,7 +568,6 @@
struct cam_csid_hw_reserve_resource_args *cid_reserv)
{
int rc = 0;
- uint32_t i;
struct cam_ife_csid_cid_data *cid_data;
CAM_DBG(CAM_ISP,
@@ -728,7 +725,6 @@
cid_data->vc = cid_reserv->in_port->vc;
cid_data->dt = cid_reserv->in_port->dt;
cid_data->cnt = 1;
- cid_data->pixel_count = cid_reserv->pixel_count;
cid_reserv->node_res = &csid_hw->cid_res[0];
csid_hw->csi2_reserve_cnt++;
@@ -737,27 +733,43 @@
csid_hw->hw_intf->hw_idx,
cid_reserv->node_res->res_id);
} else {
- if (cid_reserv->pixel_count > 0) {
- for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
- cid_data = (struct cam_ife_csid_cid_data *)
- csid_hw->cid_res[i].res_priv;
- if ((csid_hw->cid_res[i].res_state >=
- CAM_ISP_RESOURCE_STATE_RESERVED) &&
- cid_data->pixel_count > 0) {
- CAM_DBG(CAM_ISP,
- "CSID:%d IPP resource is full");
- rc = -EINVAL;
- goto end;
- }
+ switch (cid_reserv->res_id) {
+ case CAM_IFE_PIX_PATH_RES_IPP:
+ if (csid_hw->ipp_res.res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_DBG(CAM_ISP,
+ "CSID:%d IPP resource not available",
+ csid_hw->hw_intf->hw_idx);
+ rc = -EINVAL;
+ goto end;
}
+ break;
+ case CAM_IFE_PIX_PATH_RES_RDI_0:
+ case CAM_IFE_PIX_PATH_RES_RDI_1:
+ case CAM_IFE_PIX_PATH_RES_RDI_2:
+ case CAM_IFE_PIX_PATH_RES_RDI_3:
+ if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
+ CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+ CAM_DBG(CAM_ISP,
+ "CSID:%d RDI:%d resource not available",
+ csid_hw->hw_intf->hw_idx,
+ cid_reserv->res_id);
+ rc = -EINVAL;
+ goto end;
+ }
+ break;
+ default:
+ CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
+ csid_hw->hw_intf->hw_idx);
+ rc = -EINVAL;
+ goto end;
}
rc = cam_ife_csid_cid_get(csid_hw,
&cid_reserv->node_res,
cid_reserv->in_port->vc,
cid_reserv->in_port->dt,
- cid_reserv->in_port->res_type,
- cid_reserv->pixel_count);
+ cid_reserv->in_port->res_type);
/* if success then increment the reserve count */
if (!rc) {
if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index b400d14..4b546ea 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -368,7 +368,6 @@
uint32_t dt;
uint32_t cnt;
uint32_t tpg_set;
- int pixel_count;
};
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index df97bd6..ceeacbe 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -75,7 +75,6 @@
* @cid: cid (DT_ID) value for path, this is applicable for CSID path
* reserve
* @node_res : Reserved resource structure pointer
- * @pixel_count: Number of pixel resources
*
*/
struct cam_csid_hw_reserve_resource_args {
@@ -87,7 +86,6 @@
uint32_t master_idx;
uint32_t cid;
struct cam_isp_resource_node *node_res;
- int pixel_count;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 257a5ac..b9f6d77 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -92,6 +92,7 @@
CAM_ISP_HW_CMD_STRIPE_UPDATE,
CAM_ISP_HW_CMD_CLOCK_UPDATE,
CAM_ISP_HW_CMD_BW_UPDATE,
+ CAM_ISP_HW_CMD_BW_CONTROL,
CAM_ISP_HW_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index b771ec6..8927d6a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -185,6 +185,22 @@
uint64_t external_bw_bytes;
};
+enum cam_vfe_bw_control_action {
+ CAM_VFE_BW_CONTROL_EXCLUDE = 0,
+ CAM_VFE_BW_CONTROL_INCLUDE = 1
+};
+
+/*
+ * struct cam_vfe_bw_control_args:
+ *
+ * @node_res: Resource to get the time stamp
+ * @action: Bandwidth control action
+ */
+struct cam_vfe_bw_control_args {
+ struct cam_isp_resource_node *node_res;
+ enum cam_vfe_bw_control_action action;
+};
+
/*
* struct cam_vfe_top_irq_evt_payload:
*
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 02fec28..2c4fe9d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -697,6 +697,7 @@
case CAM_ISP_HW_CMD_GET_REG_UPDATE:
case CAM_ISP_HW_CMD_CLOCK_UPDATE:
case CAM_ISP_HW_CMD_BW_UPDATE:
+ case CAM_ISP_HW_CMD_BW_CONTROL:
rc = core_info->vfe_top->hw_ops.process_cmd(
core_info->vfe_top->top_priv, cmd_type, cmd_args,
arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index f166025..842cfc7 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,9 @@
struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long hw_clk_rate;
struct cam_axi_vote hw_axi_vote;
+ enum cam_vfe_bw_control_action axi_vote_control[
+ CAM_VFE_TOP_VER2_MUX_MAX];
+
struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
};
@@ -134,10 +137,13 @@
}
for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
- sum.uncompressed_bw +=
- top_priv->req_axi_vote[i].uncompressed_bw;
- sum.compressed_bw +=
- top_priv->req_axi_vote[i].compressed_bw;
+ if (top_priv->axi_vote_control[i] ==
+ CAM_VFE_BW_CONTROL_INCLUDE) {
+ sum.uncompressed_bw +=
+ top_priv->req_axi_vote[i].uncompressed_bw;
+ sum.compressed_bw +=
+ top_priv->req_axi_vote[i].compressed_bw;
+ }
}
CAM_DBG(CAM_ISP, "BW Vote: u=%lld c=%lld",
@@ -239,6 +245,8 @@
bw_update->camnoc_bw_bytes;
top_priv->req_axi_vote[i].compressed_bw =
bw_update->external_bw_bytes;
+ top_priv->axi_vote_control[i] =
+ CAM_VFE_BW_CONTROL_INCLUDE;
break;
}
}
@@ -253,6 +261,50 @@
return rc;
}
+static int cam_vfe_top_bw_control(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args, uint32_t arg_size)
+{
+ struct cam_vfe_bw_control_args *bw_ctrl = NULL;
+ struct cam_isp_resource_node *res = NULL;
+ struct cam_hw_info *hw_info = NULL;
+ int rc = 0;
+ int i;
+
+ bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args;
+ res = bw_ctrl->node_res;
+
+ if (!res || !res->hw_intf->hw_priv)
+ return -EINVAL;
+
+ hw_info = res->hw_intf->hw_priv;
+
+ if (res->res_type != CAM_ISP_RESOURCE_VFE_IN ||
+ res->res_id >= CAM_ISP_HW_VFE_IN_MAX) {
+ CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d",
+ res->hw_intf->hw_idx, res->res_type,
+ res->res_id);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+ if (top_priv->mux_rsrc[i].res_id == res->res_id) {
+ top_priv->axi_vote_control[i] = bw_ctrl->action;
+ break;
+ }
+ }
+
+ if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
+ CAM_DBG(CAM_ISP, "VFE:%d Not ready to set BW yet :%d",
+ res->hw_intf->hw_idx,
+ hw_info->hw_state);
+ } else {
+ rc = cam_vfe_top_set_axi_bw_vote(top_priv);
+ }
+
+ return rc;
+}
+
static int cam_vfe_top_mux_get_reg_update(
struct cam_vfe_top_ver2_priv *top_priv,
void *cmd_args, uint32_t arg_size)
@@ -458,6 +510,8 @@
top_priv->req_clk_rate[i] = 0;
top_priv->req_axi_vote[i].compressed_bw = 0;
top_priv->req_axi_vote[i].uncompressed_bw = 0;
+ top_priv->axi_vote_control[i] =
+ CAM_VFE_BW_CONTROL_EXCLUDE;
break;
}
}
@@ -518,6 +572,9 @@
rc = cam_vfe_top_bw_update(top_priv, cmd_args,
arg_size);
break;
+ case CAM_ISP_HW_CMD_BW_CONTROL:
+ rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size);
+ break;
default:
rc = -EINVAL;
CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
@@ -565,6 +622,8 @@
top_priv->req_clk_rate[i] = 0;
top_priv->req_axi_vote[i].compressed_bw = 0;
top_priv->req_axi_vote[i].uncompressed_bw = 0;
+ top_priv->axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE;
+
if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
top_priv->mux_rsrc[i].res_id =
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index bb952e6..21e66a2 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -68,6 +68,10 @@
cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0,
0x1);
+ else if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10)
+ cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
+ hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0,
+ 0x22);
else
CAM_ERR(CAM_LRME, "Unsupported format %d",
io_buf->io_cfg->format);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index d7662f1..92f708b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -2607,9 +2607,12 @@
int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
{
int rc = 0;
- int i;
+ int i, j;
struct cam_req_mgr_core_link *link = NULL;
+ struct cam_req_mgr_connected_device *dev = NULL;
+ struct cam_req_mgr_link_evt_data evt_data;
+
if (!control) {
CAM_ERR(CAM_CRM, "Control command is NULL");
rc = -EINVAL;
@@ -2639,9 +2642,29 @@
link->link_hdl);
rc = -EFAULT;
}
+ /* notify nodes */
+ for (j = 0; j < link->num_devs; j++) {
+ dev = &link->l_dev[j];
+ evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_RESUME;
+ evt_data.link_hdl = link->link_hdl;
+ evt_data.dev_hdl = dev->dev_hdl;
+ evt_data.req_id = 0;
+ if (dev->ops && dev->ops->process_evt)
+ dev->ops->process_evt(&evt_data);
+ }
} else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) {
/* Destroy SOF watchdog timer */
crm_timer_exit(&link->watchdog);
+ /* notify nodes */
+ for (j = 0; j < link->num_devs; j++) {
+ dev = &link->l_dev[j];
+ evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_PAUSE;
+ evt_data.link_hdl = link->link_hdl;
+ evt_data.dev_hdl = dev->dev_hdl;
+ evt_data.req_id = 0;
+ if (dev->ops && dev->ops->process_evt)
+ dev->ops->process_evt(&evt_data);
+ }
} else {
CAM_ERR(CAM_CRM, "Invalid link control command");
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index ce8dfa7..45ebc69 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -81,9 +81,9 @@
* @process_evt : payload to generic event
*/
struct cam_req_mgr_kmd_ops {
- cam_req_mgr_get_dev_info get_dev_info;
- cam_req_mgr_link_setup link_setup;
- cam_req_mgr_apply_req apply_req;
+ cam_req_mgr_get_dev_info get_dev_info;
+ cam_req_mgr_link_setup link_setup;
+ cam_req_mgr_apply_req apply_req;
cam_req_mgr_flush_req flush_req;
cam_req_mgr_process_evt process_evt;
};
@@ -182,6 +182,8 @@
*/
enum cam_req_mgr_link_evt_type {
CAM_REQ_MGR_LINK_EVT_ERR,
+ CAM_REQ_MGR_LINK_EVT_PAUSE,
+ CAM_REQ_MGR_LINK_EVT_RESUME,
CAM_REQ_MGR_LINK_EVT_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 9894ca3..d5bb1b0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -191,14 +191,16 @@
CAM_ERR(CAM_SENSOR,
"Already some pkt in offset req : %lld",
csl_packet->header.request_id);
- rc = delete_request(i2c_reg_settings);
- if (rc < 0) {
- CAM_ERR(CAM_SENSOR,
- "Failed in Deleting the err: %d", rc);
- return rc;
- }
+ /*
+ * Update req mgr even in case of failure.
+ * This will help not to wait indefinitely
+ * and freeze. If this log is triggered then
+ * fix it.
+ */
+ cam_sensor_update_req_mgr(s_ctrl, csl_packet);
+ return 0;
}
- break;
+ break;
}
case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: {
if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) ||
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
index 7a6d7fd..89aad4e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -98,6 +98,11 @@
return -EINVAL;
}
+ if (!write_setting->reg_setting) {
+ CAM_ERR(CAM_SENSOR, "Invalid Register Settings");
+ return -EINVAL;
+ }
+
if (io_master_info->master_type == CCI_MASTER) {
return cam_cci_i2c_write_table(io_master_info,
write_setting);
@@ -125,6 +130,11 @@
return -EINVAL;
}
+ if (!write_setting->reg_setting) {
+ CAM_ERR(CAM_SENSOR, "Invalid Register Settings");
+ return -EINVAL;
+ }
+
if (io_master_info->master_type == CCI_MASTER) {
return cam_cci_i2c_write_continuous_table(io_master_info,
write_setting, cam_sensor_i2c_write_flag);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 72ca737..622dae6 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -26,7 +26,7 @@
#define MAX_REGULATOR 5
#define MAX_POWER_CONFIG 12
-#define MAX_PER_FRAME_ARRAY 8
+#define MAX_PER_FRAME_ARRAY 32
#define CAM_SENSOR_NAME "cam-sensor"
#define CAM_ACTUATOR_NAME "cam-actuator"
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 55ce946..01811d9 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -357,7 +357,7 @@
if (!cq_host->desc_base || !cq_host->trans_desc_base)
return -ENOMEM;
- pr_info("desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n",
+ pr_debug("desc-base: 0x%pK trans-base: 0x%pK\n desc_dma 0x%llx trans_dma: 0x%llx\n",
cq_host->desc_base, cq_host->trans_desc_base,
(unsigned long long)cq_host->desc_dma_base,
(unsigned long long) cq_host->trans_desc_dma_base);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0d6f263..5ed9b72 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -4237,11 +4237,10 @@
group->latency = PM_QOS_DEFAULT_VALUE;
pm_qos_add_request(&group->req, PM_QOS_CPU_DMA_LATENCY,
group->latency);
- pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d (0x%p)\n",
+ pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d\n",
__func__, i,
group->req.cpus_affine.bits[0],
- group->latency,
- &latency[i].latency[SDHCI_PERFORMANCE_MODE]);
+ group->latency);
}
msm_host->pm_qos_prev_cpu = -1;
msm_host->pm_qos_group_enable = true;
@@ -4808,8 +4807,6 @@
goto vreg_deinit;
}
writel_relaxed(readl_relaxed(tlmm_mem) | 0x2, tlmm_mem);
- dev_dbg(&pdev->dev, "tlmm reg %pa value 0x%08x\n",
- &tlmm_memres->start, readl_relaxed(tlmm_mem));
}
/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 566be69..b674b38 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3068,13 +3068,13 @@
struct sdhci_adma2_64_desc *dma_desc = desc;
if (host->flags & SDHCI_USE_64_BIT_DMA)
- DBG("%s: %p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
+ DBG("%s: %pK: DMA 0x%08x%08x, LEN 0x%04x,Attr=0x%02x\n",
name, desc, le32_to_cpu(dma_desc->addr_hi),
le32_to_cpu(dma_desc->addr_lo),
le16_to_cpu(dma_desc->len),
le16_to_cpu(dma_desc->cmd));
else
- DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+ DBG("%s: %pK: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
name, desc, le32_to_cpu(dma_desc->addr_lo),
le16_to_cpu(dma_desc->len),
le16_to_cpu(dma_desc->cmd));
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index ea4bedf..59197d1 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -469,39 +469,43 @@
dev_dbg(&nqx_dev->client->dev,
"gpio_set_value disable: %s: info: %p\n",
__func__, nqx_dev);
- if (gpio_is_valid(nqx_dev->firm_gpio))
+ if (gpio_is_valid(nqx_dev->firm_gpio)) {
gpio_set_value(nqx_dev->firm_gpio, 0);
+ usleep_range(10000, 10100);
+ }
if (gpio_is_valid(nqx_dev->ese_gpio)) {
if (!gpio_get_value(nqx_dev->ese_gpio)) {
dev_dbg(&nqx_dev->client->dev, "disabling en_gpio\n");
gpio_set_value(nqx_dev->en_gpio, 0);
+ usleep_range(10000, 10100);
} else {
dev_dbg(&nqx_dev->client->dev, "keeping en_gpio high\n");
}
} else {
dev_dbg(&nqx_dev->client->dev, "ese_gpio invalid, set en_gpio to low\n");
gpio_set_value(nqx_dev->en_gpio, 0);
+ usleep_range(10000, 10100);
}
r = nqx_clock_deselect(nqx_dev);
if (r < 0)
dev_err(&nqx_dev->client->dev, "unable to disable clock\n");
nqx_dev->nfc_ven_enabled = false;
- /* hardware dependent delay */
- msleep(100);
} else if (arg == 1) {
nqx_enable_irq(nqx_dev);
dev_dbg(&nqx_dev->client->dev,
"gpio_set_value enable: %s: info: %p\n",
__func__, nqx_dev);
- if (gpio_is_valid(nqx_dev->firm_gpio))
+ if (gpio_is_valid(nqx_dev->firm_gpio)) {
gpio_set_value(nqx_dev->firm_gpio, 0);
+ usleep_range(10000, 10100);
+ }
gpio_set_value(nqx_dev->en_gpio, 1);
+ usleep_range(10000, 10100);
r = nqx_clock_select(nqx_dev);
if (r < 0)
dev_err(&nqx_dev->client->dev, "unable to enable clock\n");
nqx_dev->nfc_ven_enabled = true;
- msleep(20);
} else if (arg == 2) {
/*
* We are switching to Dowload Mode, toggle the enable pin
@@ -515,14 +519,15 @@
}
}
gpio_set_value(nqx_dev->en_gpio, 1);
- msleep(20);
- if (gpio_is_valid(nqx_dev->firm_gpio))
+ usleep_range(10000, 10100);
+ if (gpio_is_valid(nqx_dev->firm_gpio)) {
gpio_set_value(nqx_dev->firm_gpio, 1);
- msleep(20);
+ usleep_range(10000, 10100);
+ }
gpio_set_value(nqx_dev->en_gpio, 0);
- msleep(100);
+ usleep_range(10000, 10100);
gpio_set_value(nqx_dev->en_gpio, 1);
- msleep(20);
+ usleep_range(10000, 10100);
} else {
r = -ENOIOCTLCMD;
}
@@ -648,13 +653,14 @@
unsigned char nci_reset_rsp[6];
unsigned char init_rsp_len = 0;
unsigned int enable_gpio = nqx_dev->en_gpio;
+
/* making sure that the NFCC starts in a clean state. */
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
/* hardware dependent delay */
- msleep(20);
+ usleep_range(10000, 10100);
gpio_set_value(enable_gpio, 1);/* HPD : Enable*/
/* hardware dependent delay */
- msleep(20);
+ usleep_range(10000, 10100);
/* send NCI CORE RESET CMD with Keep Config parameters */
ret = i2c_master_send(client, raw_nci_reset_cmd,
@@ -670,21 +676,17 @@
/* Read Response of RESET command */
ret = i2c_master_recv(client, nci_reset_rsp,
sizeof(nci_reset_rsp));
- dev_err(&client->dev,
- "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
- __func__, nci_reset_rsp[0],
- nci_reset_rsp[1], nci_reset_rsp[2]);
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_recv Error\n", __func__);
goto err_nfcc_hw_check;
}
- ret = i2c_master_send(client, raw_nci_init_cmd,
- sizeof(raw_nci_init_cmd));
+ ret = nqx_standby_write(nqx_dev, raw_nci_init_cmd,
+ sizeof(raw_nci_init_cmd));
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_send Error\n", __func__);
- goto err_nfcc_hw_check;
+ goto err_nfcc_core_init_fail;
}
/* hardware dependent delay */
msleep(30);
@@ -694,7 +696,7 @@
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_recv Error\n", __func__);
- goto err_nfcc_hw_check;
+ goto err_nfcc_core_init_fail;
}
init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {
@@ -707,6 +709,11 @@
nqx_dev->nqx_info.info.fw_minor =
nci_init_rsp[init_rsp_len];
}
+ dev_dbg(&client->dev,
+ "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+ __func__, nci_reset_rsp[0],
+ nci_reset_rsp[1], nci_reset_rsp[2]);
+
dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n",
nqx_dev->nqx_info.info.chip_type);
dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n",
@@ -746,6 +753,12 @@
ret = 0;
goto done;
+err_nfcc_core_init_fail:
+ dev_err(&client->dev,
+ "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+ __func__, nci_reset_rsp[0],
+ nci_reset_rsp[1], nci_reset_rsp[2]);
+
err_nfcc_hw_check:
ret = -ENXIO;
dev_err(&client->dev,
@@ -1213,6 +1226,7 @@
.owner = THIS_MODULE,
.name = "nq-nci",
.of_match_table = msm_match_table,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = &nfc_pm_ops,
},
};
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index d39a17f..6515ce4 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -89,6 +89,16 @@
Technologies Inc MSM8953 platform.
If unsure say N.
+config PINCTRL_MSM8937
+ tristate "Qualcomm Technologies Inc MSM8937 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm Technologies Inc TLMM block found on the Qualcomm
+ Technologies Inc MSM8937 platform.
+ If unsure say N.
+
config PINCTRL_SDM845
tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index d92db11..db71677 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -12,6 +12,7 @@
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
obj-$(CONFIG_PINCTRL_MSM8953) += pinctrl-msm8953.o
+obj-$(CONFIG_PINCTRL_MSM8937) += pinctrl-msm8937.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index bf95849..1441678 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013, Sony Mobile Communications AB.
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, 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
@@ -70,6 +70,7 @@
const struct msm_pinctrl_soc_data *soc;
void __iomem *regs;
+ void __iomem *pdc_regs;
};
static int msm_get_groups_count(struct pinctrl_dev *pctldev)
@@ -777,6 +778,102 @@
.irq_set_wake = msm_gpio_irq_set_wake,
};
+static struct irq_chip msm_dirconn_irq_chip;
+
+static void msm_gpio_dirconn_handler(struct irq_desc *desc)
+{
+ struct irq_data *irqd = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+ generic_handle_irq(irqd->irq);
+ chained_irq_exit(chip, desc);
+}
+
+static void setup_pdc_gpio(struct irq_domain *domain,
+ unsigned int parent_irq, unsigned int gpio)
+{
+ int irq;
+
+ if (gpio != 0) {
+ irq = irq_find_mapping(domain, gpio);
+ irq_set_parent(irq, parent_irq);
+ irq_set_chip(irq, &msm_dirconn_irq_chip);
+ irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
+ }
+
+ __irq_set_handler(parent_irq, msm_gpio_dirconn_handler, false, NULL);
+}
+
+static void request_dc_interrupt(struct irq_domain *domain,
+ struct irq_domain *parent, irq_hw_number_t hwirq,
+ unsigned int gpio)
+{
+ struct irq_fwspec fwspec;
+ unsigned int parent_irq;
+
+ fwspec.fwnode = parent->fwnode;
+ fwspec.param[0] = 0; /* SPI */
+ fwspec.param[1] = hwirq;
+ fwspec.param[2] = IRQ_TYPE_NONE;
+ fwspec.param_count = 3;
+
+ parent_irq = irq_create_fwspec_mapping(&fwspec);
+
+ setup_pdc_gpio(domain, parent_irq, gpio);
+}
+
+/**
+ * gpio_muxed_to_pdc: Mux the GPIO to a PDC IRQ
+ *
+ * @pdc_domain: the PDC's domain
+ * @d: the GPIO's IRQ data
+ *
+ * Find a free PDC port for the GPIO and map the GPIO's mux information to the
+ * PDC registers; so the GPIO can be used a wakeup source.
+ */
+static void gpio_muxed_to_pdc(struct irq_domain *pdc_domain, struct irq_data *d)
+{
+ int i, j;
+ unsigned int mux;
+ struct irq_desc *desc = irq_data_to_desc(d);
+ struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ unsigned int gpio = d->hwirq;
+ struct msm_pinctrl *pctrl;
+ unsigned int irq;
+
+ if (!gc || !parent_data)
+ return;
+
+ pctrl = gpiochip_get_data(gc);
+
+ for (i = 0; i < pctrl->soc->n_gpio_mux_in; i++) {
+ if (gpio != pctrl->soc->gpio_mux_in[i].gpio)
+ continue;
+ mux = pctrl->soc->gpio_mux_in[i].mux;
+ for (j = 0; j < pctrl->soc->n_pdc_mux_out; j++) {
+ struct msm_pdc_mux_output *pdc_out =
+ &pctrl->soc->pdc_mux_out[j];
+
+ if (pdc_out->mux == mux)
+ break;
+ if (pdc_out->mux)
+ continue;
+ pdc_out->mux = gpio;
+ irq = irq_find_mapping(pdc_domain, pdc_out->hwirq + 32);
+ /* setup the IRQ parent for the GPIO */
+ setup_pdc_gpio(pctrl->chip.irqdomain, irq, gpio);
+ /* program pdc select grp register */
+ writel_relaxed((mux & 0x3F), pctrl->pdc_regs +
+ (0x14 * j));
+ break;
+ }
+ /* We have no more PDC port available */
+ WARN_ON(j == pctrl->soc->n_pdc_mux_out);
+ }
+}
+
static bool is_gpio_dual_edge(struct irq_data *d, irq_hw_number_t *dir_conn_irq)
{
struct irq_desc *desc = irq_data_to_desc(d);
@@ -797,6 +894,17 @@
return true;
}
}
+
+ for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+ struct msm_pdc_mux_output *dir_conn =
+ &pctrl->soc->pdc_mux_out[i];
+
+ if (dir_conn->mux == d->hwirq && (dir_conn->hwirq + 32)
+ != parent_data->hwirq) {
+ *dir_conn_irq = dir_conn->hwirq + 32;
+ return true;
+ }
+ }
return false;
}
@@ -814,13 +922,48 @@
irq_get_irq_data(irq_find_mapping(parent_data->domain,
dir_conn_irq));
- if (dir_conn_data && dir_conn_data->chip->irq_mask)
+ if (!dir_conn_data)
+ return;
+ if (dir_conn_data->chip->irq_mask)
dir_conn_data->chip->irq_mask(dir_conn_data);
}
+
if (parent_data->chip->irq_mask)
parent_data->chip->irq_mask(parent_data);
}
+static void msm_dirconn_irq_enable(struct irq_data *d)
+{
+ struct irq_desc *desc = irq_data_to_desc(d);
+ struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+ irq_hw_number_t dir_conn_irq = 0;
+
+ if (!parent_data)
+ return;
+
+ if (is_gpio_dual_edge(d, &dir_conn_irq)) {
+ struct irq_data *dir_conn_data =
+ irq_get_irq_data(irq_find_mapping(parent_data->domain,
+ dir_conn_irq));
+
+ if (dir_conn_data &&
+ dir_conn_data->chip->irq_set_irqchip_state)
+ dir_conn_data->chip->irq_set_irqchip_state(
+ dir_conn_data,
+ IRQCHIP_STATE_PENDING, 0);
+
+ if (dir_conn_data && dir_conn_data->chip->irq_unmask)
+ dir_conn_data->chip->irq_unmask(dir_conn_data);
+ }
+
+ if (parent_data->chip->irq_set_irqchip_state)
+ parent_data->chip->irq_set_irqchip_state(parent_data,
+ IRQCHIP_STATE_PENDING, 0);
+
+ if (parent_data->chip->irq_unmask)
+ parent_data->chip->irq_unmask(parent_data);
+}
+
static void msm_dirconn_irq_unmask(struct irq_data *d)
{
struct irq_desc *desc = irq_data_to_desc(d);
@@ -835,7 +978,9 @@
irq_get_irq_data(irq_find_mapping(parent_data->domain,
dir_conn_irq));
- if (dir_conn_data && dir_conn_data->chip->irq_unmask)
+ if (!dir_conn_data)
+ return;
+ if (dir_conn_data->chip->irq_unmask)
dir_conn_data->chip->irq_unmask(dir_conn_data);
}
if (parent_data->chip->irq_unmask)
@@ -1058,6 +1203,7 @@
static struct irq_chip msm_dirconn_irq_chip = {
.name = "msmgpio-dc",
.irq_mask = msm_dirconn_irq_mask,
+ .irq_enable = msm_dirconn_irq_enable,
.irq_unmask = msm_dirconn_irq_unmask,
.irq_eoi = msm_dirconn_irq_eoi,
.irq_ack = msm_dirconn_irq_ack,
@@ -1103,57 +1249,53 @@
chained_irq_exit(chip, desc);
}
-static void msm_gpio_dirconn_handler(struct irq_desc *desc)
-{
- struct irq_data *irqd = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
- generic_handle_irq(irqd->irq);
- chained_irq_exit(chip, desc);
-}
-
static void msm_gpio_setup_dir_connects(struct msm_pinctrl *pctrl)
{
struct device_node *parent_node;
- struct irq_domain *parent_domain;
- struct irq_fwspec fwspec;
+ struct irq_domain *pdc_domain;
unsigned int i;
parent_node = of_irq_find_parent(pctrl->dev->of_node);
-
if (!parent_node)
return;
- parent_domain = irq_find_host(parent_node);
- if (!parent_domain)
+ pdc_domain = irq_find_host(parent_node);
+ if (!pdc_domain)
return;
- fwspec.fwnode = parent_domain->fwnode;
for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i];
- unsigned int parent_irq;
- int irq;
- fwspec.param[0] = 0; /* SPI */
- fwspec.param[1] = dirconn->hwirq;
- fwspec.param[2] = IRQ_TYPE_NONE;
- fwspec.param_count = 3;
- parent_irq = irq_create_fwspec_mapping(&fwspec);
+ request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
+ dirconn->hwirq, dirconn->gpio);
+ }
- if (dirconn->gpio != 0) {
- irq = irq_find_mapping(pctrl->chip.irqdomain,
- dirconn->gpio);
+ for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+ struct msm_pdc_mux_output *pdc_out =
+ &pctrl->soc->pdc_mux_out[i];
- irq_set_parent(irq, parent_irq);
- irq_set_chip(irq, &msm_dirconn_irq_chip);
- __irq_set_handler(parent_irq, msm_gpio_dirconn_handler,
- false, NULL);
- irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
- } else {
- __irq_set_handler(parent_irq, msm_gpio_dirconn_handler,
- false, NULL);
- }
+ request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
+ pdc_out->hwirq, 0);
+ }
+
+ /*
+ * Statically choose the GPIOs for mapping to PDC. Dynamic mux mapping
+ * is very difficult.
+ */
+ for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+ unsigned int irq;
+ struct irq_data *d;
+ struct msm_gpio_mux_input *gpio_in =
+ &pctrl->soc->gpio_mux_in[i];
+ if (!gpio_in->init)
+ continue;
+
+ irq = irq_find_mapping(pctrl->chip.irqdomain, gpio_in->gpio);
+ d = irq_get_irq_data(irq);
+ if (!d)
+ continue;
+
+ gpio_muxed_to_pdc(pdc_domain, d);
}
}
@@ -1263,6 +1405,9 @@
if (IS_ERR(pctrl->regs))
return PTR_ERR(pctrl->regs);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ pctrl->pdc_regs = devm_ioremap_resource(&pdev->dev, res);
+
msm_pinctrl_setup_pm_reset(pctrl);
pctrl->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 1c6df2f..9fc6660 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2013, Sony Mobile Communications AB.
+ * Copyright (c) 2018, 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
@@ -99,13 +100,35 @@
unsigned intr_detection_bit:5;
unsigned intr_detection_width:5;
unsigned dir_conn_en_bit:8;
-}
+};
+
+/**
+ * struct msm_gpio_mux_input - Map GPIO to Mux pin
+ * @mux:: The mux pin to which the GPIO is connected to
+ * @gpio: GPIO pin number
+ * @init: Setup PDC connection at probe
+ */
+struct msm_gpio_mux_input {
+ unsigned int mux;
+ unsigned int gpio;
+ bool init;
+};
+
+/**
+ * struct msm_pdc_mux_output - GPIO mux pin to PDC port
+ * @mux: GPIO mux pin number
+ * @hwirq: The PDC port (hwirq) that GPIO is connected to
+ */
+struct msm_pdc_mux_output {
+ unsigned int mux;
+ irq_hw_number_t hwirq;
+};
/**
* struct msm_dir_conn - Direct GPIO connect configuration
* @gpio: GPIO pin number
* @hwirq: The GIC interrupt that the pin is connected to
- */;
+ */
struct msm_dir_conn {
unsigned int gpio;
irq_hw_number_t hwirq;
@@ -122,8 +145,12 @@
* @ngpio: The number of pingroups the driver should expose as GPIOs.
* @dir_conn: An array describing all the pins directly connected to GIC.
* @ndirconns: The number of pins directly connected to GIC
- * @dir_conn_offsets: Direct connect register offsets for each tile.
* @dir_conn_irq_base: Direct connect interrupt base register for kpss.
+ * @gpio_mux_in: Map of GPIO pin to the hwirq.
+ * @n_gpioc_mux_in: The number of entries in @pdc_mux_in.
+ * @pdc_mux_out: Map of GPIO mux to PDC port.
+ * @n_pdc_mux_out: The number of entries in @pdc_mux_out.
+ * @n_pdc_offset: The offset for the PDC mux pins
*/
struct msm_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
@@ -136,6 +163,11 @@
const struct msm_dir_conn *dir_conn;
unsigned int n_dir_conns;
unsigned int dir_conn_irq_base;
+ struct msm_pdc_mux_output *pdc_mux_out;
+ unsigned int n_pdc_mux_out;
+ struct msm_gpio_mux_input *gpio_mux_in;
+ unsigned int n_gpio_mux_in;
+ unsigned int n_pdc_mux_offset;
};
int msm_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8937.c b/drivers/pinctrl/qcom/pinctrl-msm8937.c
new file mode 100644
index 0000000..2b72c54
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8937.c
@@ -0,0 +1,1479 @@
+/* Copyright (c) 2015, 2018, 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define REG_BASE 0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_BASE + REG_SIZE * id, \
+ .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
+ .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 4, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc msm8937_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "SDC1_CLK"),
+ PINCTRL_PIN(135, "SDC1_CMD"),
+ PINCTRL_PIN(136, "SDC1_DATA"),
+ PINCTRL_PIN(137, "SDC1_RCLK"),
+ PINCTRL_PIN(138, "SDC2_CLK"),
+ PINCTRL_PIN(139, "SDC2_CMD"),
+ PINCTRL_PIN(140, "SDC2_DATA"),
+ PINCTRL_PIN(141, "QDSD_CLK"),
+ PINCTRL_PIN(142, "QDSD_CMD"),
+ PINCTRL_PIN(143, "QDSD_DATA0"),
+ PINCTRL_PIN(144, "QDSD_DATA1"),
+ PINCTRL_PIN(145, "QDSD_DATA2"),
+ PINCTRL_PIN(146, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+
+static const unsigned int sdc1_clk_pins[] = { 134 };
+static const unsigned int sdc1_cmd_pins[] = { 135 };
+static const unsigned int sdc1_data_pins[] = { 136 };
+static const unsigned int sdc1_rclk_pins[] = { 137 };
+static const unsigned int sdc2_clk_pins[] = { 138 };
+static const unsigned int sdc2_cmd_pins[] = { 139 };
+static const unsigned int sdc2_data_pins[] = { 140 };
+static const unsigned int qdsd_clk_pins[] = { 141 };
+static const unsigned int qdsd_cmd_pins[] = { 142 };
+static const unsigned int qdsd_data0_pins[] = { 143 };
+static const unsigned int qdsd_data1_pins[] = { 144 };
+static const unsigned int qdsd_data2_pins[] = { 145 };
+static const unsigned int qdsd_data3_pins[] = { 146 };
+
+enum msm8937_functions {
+ msm_mux_qdss_tracedata_b,
+ msm_mux_blsp_uart1,
+ msm_mux_gpio,
+ msm_mux_blsp_spi1,
+ msm_mux_adsp_ext,
+ msm_mux_blsp_i2c1,
+ msm_mux_prng_rosc,
+ msm_mux_qdss_cti_trig_out_b0,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_pbs0,
+ msm_mux_pbs1,
+ msm_mux_pwr_modem_enabled_b,
+ msm_mux_blsp_i2c3,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_ldo_update,
+ msm_mux_atest_combodac_to_gpio_native,
+ msm_mux_ldo_en,
+ msm_mux_blsp_i2c2,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_pbs2,
+ msm_mux_atest_gpsadc_dtest0_native,
+ msm_mux_blsp_spi3,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_uart4,
+ msm_mux_sec_mi2s,
+ msm_mux_pwr_nav_enabled_b,
+ msm_mux_codec_mad,
+ msm_mux_pwr_crypto_enabled_b,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_uart5,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_atest_bbrx1,
+ msm_mux_m_voc,
+ msm_mux_qdss_cti_trig_in_a0,
+ msm_mux_qdss_cti_trig_in_b0,
+ msm_mux_blsp_i2c6,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_atest_wlan0,
+ msm_mux_atest_wlan1,
+ msm_mux_atest_bbrx0,
+ msm_mux_blsp_i2c5,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_atest_gpsadc_dtest1_native,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_uart6,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_mdp_vsync,
+ msm_mux_pri_mi2s_mclk_a,
+ msm_mux_sec_mi2s_mclk_a,
+ msm_mux_cam_mclk,
+ msm_mux_cci_i2c,
+ msm_mux_pwr_modem_enabled_a,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cam1_standby,
+ msm_mux_pwr_nav_enabled_a,
+ msm_mux_cam1_rst,
+ msm_mux_pwr_crypto_enabled_a,
+ msm_mux_forced_usb,
+ msm_mux_qdss_cti_trig_out_b1,
+ msm_mux_cam2_rst,
+ msm_mux_webcam_standby,
+ msm_mux_cci_async,
+ msm_mux_webcam_rst,
+ msm_mux_ov_ldo,
+ msm_mux_sd_write,
+ msm_mux_accel_int,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_alsp_int,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_mag_int,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_blsp6_spi,
+ msm_mux_fp_int,
+ msm_mux_qdss_cti_trig_in_b1,
+ msm_mux_uim_batt,
+ msm_mux_cam2_standby,
+ msm_mux_uim1_data,
+ msm_mux_uim1_clk,
+ msm_mux_uim1_reset,
+ msm_mux_uim1_present,
+ msm_mux_uim2_data,
+ msm_mux_uim2_clk,
+ msm_mux_uim2_reset,
+ msm_mux_uim2_present,
+ msm_mux_sensor_rst,
+ msm_mux_mipi_dsi0,
+ msm_mux_smb_int,
+ msm_mux_cam0_ldo,
+ msm_mux_us_euro,
+ msm_mux_atest_char3,
+ msm_mux_dbg_out,
+ msm_mux_bimc_dte0,
+ msm_mux_ts_resout,
+ msm_mux_ts_sample,
+ msm_mux_sec_mi2s_mclk_b,
+ msm_mux_pri_mi2s,
+ msm_mux_sdcard_det,
+ msm_mux_atest_char1,
+ msm_mux_ebi_cdc,
+ msm_mux_audio_reset,
+ msm_mux_atest_char0,
+ msm_mux_audio_ref,
+ msm_mux_cdc_pdm0,
+ msm_mux_pri_mi2s_mclk_b,
+ msm_mux_lpass_slimbus,
+ msm_mux_lpass_slimbus0,
+ msm_mux_lpass_slimbus1,
+ msm_mux_codec_int1,
+ msm_mux_codec_int2,
+ msm_mux_wcss_bt,
+ msm_mux_atest_char2,
+ msm_mux_ebi_ch0,
+ msm_mux_wcss_wlan2,
+ msm_mux_wcss_wlan1,
+ msm_mux_wcss_wlan0,
+ msm_mux_wcss_wlan,
+ msm_mux_wcss_fm,
+ msm_mux_ext_lpass,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng1,
+ msm_mux_cri_trng0,
+ msm_mux_blsp_spi7,
+ msm_mux_blsp_uart7,
+ msm_mux_pri_mi2s_ws,
+ msm_mux_blsp_i2c7,
+ msm_mux_gcc_tlmm,
+ msm_mux_dmic0_clk,
+ msm_mux_dmic0_data,
+ msm_mux_key_volp,
+ msm_mux_qdss_cti_trig_in_a1,
+ msm_mux_us_emitter,
+ msm_mux_wsa_irq,
+ msm_mux_wsa_io,
+ msm_mux_wsa_reset,
+ msm_mux_blsp_spi8,
+ msm_mux_blsp_uart8,
+ msm_mux_blsp_i2c8,
+ msm_mux_gcc_plltest,
+ msm_mux_nav_pps_in_a,
+ msm_mux_pa_indicator,
+ msm_mux_modem_tsync,
+ msm_mux_nav_tsync,
+ msm_mux_nav_pps_in_b,
+ msm_mux_nav_pps,
+ msm_mux_gsm0_tx,
+ msm_mux_atest_char,
+ msm_mux_atest_tsens,
+ msm_mux_bimc_dte1,
+ msm_mux_ssbi_wtr1,
+ msm_mux_fp_gpio,
+ msm_mux_coex_uart,
+ msm_mux_key_snapshot,
+ msm_mux_key_focus,
+ msm_mux_nfc_pwr,
+ msm_mux_blsp8_spi,
+ msm_mux_qdss_cti_trig_out_a0,
+ msm_mux_qdss_cti_trig_out_a1,
+ msm_mux_NA,
+};
+
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio0", "gpio1", "gpio6", "gpio7", "gpio12", "gpio13", "gpio23",
+ "gpio42", "gpio43", "gpio44", "gpio47", "gpio66", "gpio86", "gpio87",
+ "gpio88", "gpio92",
+};
+static const char * const blsp_uart1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio1",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio2", "gpio3",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio2",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+ "gpio2",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const pbs0_groups[] = {
+ "gpio8",
+};
+static const char * const pbs1_groups[] = {
+ "gpio9",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+ "gpio9",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+ "gpio10",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio4",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+ "gpio4", "gpio12", "gpio13", "gpio20", "gpio21", "gpio28", "gpio29",
+ "gpio30", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", "gpio44",
+ "gpio45", "gpio46", "gpio47", "gpio48", "gpio67", "gpio115",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+ "gpio6",
+};
+static const char * const pbs2_groups[] = {
+ "gpio7",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+ "gpio7",
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+ "gpio11",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio12", "gpio13", "gpio94", "gpio95",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+ "gpio12",
+};
+static const char * const codec_mad_groups[] = {
+ "gpio13",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+ "gpio13",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio14", "gpio15",
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_uart5_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio16",
+};
+static const char * const atest_bbrx1_groups[] = {
+ "gpio16",
+};
+static const char * const m_voc_groups[] = {
+ "gpio17", "gpio21",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+ "gpio17",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+ "gpio21",
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio22", "gpio23",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio22",
+};
+static const char * const atest_wlan0_groups[] = {
+ "gpio22",
+};
+static const char * const atest_wlan1_groups[] = {
+ "gpio23",
+};
+static const char * const atest_bbrx0_groups[] = {
+ "gpio17",
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio18", "gpio19",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio18",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+ "gpio18",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio19", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31",
+ "gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio38", "gpio39",
+ "gpio40", "gpio50",
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const blsp_uart6_groups[] = {
+ "gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio20",
+};
+static const char * const mdp_vsync_groups[] = {
+ "gpio24", "gpio25",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+ "gpio25",
+};
+static const char * const sec_mi2s_mclk_a_groups[] = {
+ "gpio25",
+};
+static const char * const cam_mclk_groups[] = {
+ "gpio26", "gpio27", "gpio28",
+};
+static const char * const cci_i2c_groups[] = {
+ "gpio29", "gpio30", "gpio31", "gpio32",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+ "gpio29",
+};
+static const char * const cci_timer0_groups[] = {
+ "gpio33",
+};
+static const char * const cci_timer1_groups[] = {
+ "gpio34",
+};
+static const char * const cam1_standby_groups[] = {
+ "gpio35",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+ "gpio35",
+};
+static const char * const cam1_rst_groups[] = {
+ "gpio36",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+ "gpio36",
+};
+static const char * const forced_usb_groups[] = {
+ "gpio37",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+ "gpio37",
+};
+static const char * const cam2_rst_groups[] = {
+ "gpio38",
+};
+static const char * const webcam_standby_groups[] = {
+ "gpio39",
+};
+static const char * const cci_async_groups[] = {
+ "gpio39",
+};
+static const char * const webcam_rst_groups[] = {
+ "gpio40",
+};
+static const char * const ov_ldo_groups[] = {
+ "gpio41",
+};
+static const char * const sd_write_groups[] = {
+ "gpio41",
+};
+static const char * const accel_int_groups[] = {
+ "gpio42",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+ "gpio42",
+};
+static const char * const alsp_int_groups[] = {
+ "gpio43",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+ "gpio43",
+};
+static const char * const mag_int_groups[] = {
+ "gpio44",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+ "gpio44",
+};
+static const char * const blsp6_spi_groups[] = {
+ "gpio47",
+};
+static const char * const fp_int_groups[] = {
+ "gpio48",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+ "gpio48",
+};
+static const char * const uim_batt_groups[] = {
+ "gpio49",
+};
+static const char * const cam2_standby_groups[] = {
+ "gpio50",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio51",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio52",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio53",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio54",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio55",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio56",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio57",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio58",
+};
+static const char * const sensor_rst_groups[] = {
+ "gpio59",
+};
+static const char * const mipi_dsi0_groups[] = {
+ "gpio60",
+};
+static const char * const smb_int_groups[] = {
+ "gpio61",
+};
+static const char * const cam0_ldo_groups[] = {
+ "gpio62",
+};
+static const char * const us_euro_groups[] = {
+ "gpio63",
+};
+static const char * const atest_char3_groups[] = {
+ "gpio63",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio63",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio63", "gpio65",
+};
+static const char * const ts_resout_groups[] = {
+ "gpio64",
+};
+static const char * const ts_sample_groups[] = {
+ "gpio65",
+};
+static const char * const sec_mi2s_mclk_b_groups[] = {
+ "gpio66",
+};
+static const char * const pri_mi2s_groups[] = {
+ "gpio66", "gpio85", "gpio86", "gpio88", "gpio94", "gpio95",
+};
+static const char * const sdcard_det_groups[] = {
+ "gpio67",
+};
+static const char * const atest_char1_groups[] = {
+ "gpio67",
+};
+static const char * const ebi_cdc_groups[] = {
+ "gpio67", "gpio69", "gpio118", "gpio119", "gpio120", "gpio123",
+};
+static const char * const audio_reset_groups[] = {
+ "gpio68",
+};
+static const char * const atest_char0_groups[] = {
+ "gpio68",
+};
+static const char * const audio_ref_groups[] = {
+ "gpio69",
+};
+static const char * const cdc_pdm0_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
+};
+static const char * const pri_mi2s_mclk_b_groups[] = {
+ "gpio69",
+};
+static const char * const lpass_slimbus_groups[] = {
+ "gpio70",
+};
+static const char * const lpass_slimbus0_groups[] = {
+ "gpio71",
+};
+static const char * const lpass_slimbus1_groups[] = {
+ "gpio72",
+};
+static const char * const codec_int1_groups[] = {
+ "gpio73",
+};
+static const char * const codec_int2_groups[] = {
+ "gpio74",
+};
+static const char * const wcss_bt_groups[] = {
+ "gpio75", "gpio83", "gpio84",
+};
+static const char * const atest_char2_groups[] = {
+ "gpio75",
+};
+static const char * const ebi_ch0_groups[] = {
+ "gpio75",
+};
+static const char * const wcss_wlan2_groups[] = {
+ "gpio76",
+};
+static const char * const wcss_wlan1_groups[] = {
+ "gpio77",
+};
+static const char * const wcss_wlan0_groups[] = {
+ "gpio78",
+};
+static const char * const wcss_wlan_groups[] = {
+ "gpio79", "gpio80",
+};
+static const char * const wcss_fm_groups[] = {
+ "gpio81", "gpio82",
+};
+static const char * const ext_lpass_groups[] = {
+ "gpio81",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio82",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio83",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio84",
+};
+static const char * const blsp_spi7_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uart7_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const pri_mi2s_ws_groups[] = {
+ "gpio87",
+};
+static const char * const blsp_i2c7_groups[] = {
+ "gpio87", "gpio88",
+};
+static const char * const gcc_tlmm_groups[] = {
+ "gpio87",
+};
+static const char * const dmic0_clk_groups[] = {
+ "gpio89",
+};
+static const char * const dmic0_data_groups[] = {
+ "gpio90",
+};
+static const char * const key_volp_groups[] = {
+ "gpio91",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+ "gpio91",
+};
+static const char * const us_emitter_groups[] = {
+ "gpio92",
+};
+static const char * const wsa_irq_groups[] = {
+ "gpio93",
+};
+static const char * const wsa_io_groups[] = {
+ "gpio94", "gpio95",
+};
+static const char * const wsa_reset_groups[] = {
+ "gpio96",
+};
+static const char * const blsp_spi8_groups[] = {
+ "gpio96", "gpio97", "gpio98", "gpio99",
+};
+static const char * const blsp_uart8_groups[] = {
+ "gpio96", "gpio97", "gpio98", "gpio99",
+};
+static const char * const blsp_i2c8_groups[] = {
+ "gpio98", "gpio99",
+};
+static const char * const gcc_plltest_groups[] = {
+ "gpio98", "gpio99",
+};
+static const char * const nav_pps_in_a_groups[] = {
+ "gpio115",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio116",
+};
+static const char * const modem_tsync_groups[] = {
+ "gpio117",
+};
+static const char * const nav_tsync_groups[] = {
+ "gpio117",
+};
+static const char * const nav_pps_in_b_groups[] = {
+ "gpio117",
+};
+static const char * const nav_pps_groups[] = {
+ "gpio117",
+};
+static const char * const gsm0_tx_groups[] = {
+ "gpio119",
+};
+static const char * const atest_char_groups[] = {
+ "gpio120",
+};
+static const char * const atest_tsens_groups[] = {
+ "gpio120",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio121", "gpio122",
+};
+static const char * const ssbi_wtr1_groups[] = {
+ "gpio122", "gpio123",
+};
+static const char * const fp_gpio_groups[] = {
+ "gpio124",
+};
+static const char * const coex_uart_groups[] = {
+ "gpio124", "gpio127",
+};
+static const char * const key_snapshot_groups[] = {
+ "gpio127",
+};
+static const char * const key_focus_groups[] = {
+ "gpio128",
+};
+static const char * const nfc_pwr_groups[] = {
+ "gpio129",
+};
+static const char * const blsp8_spi_groups[] = {
+ "gpio130",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+ "gpio132",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+ "gpio133",
+};
+
+static const struct msm_function msm8937_functions[] = {
+ FUNCTION(qdss_tracedata_b),
+ FUNCTION(blsp_uart1),
+ FUNCTION(gpio),
+ FUNCTION(blsp_spi1),
+ FUNCTION(adsp_ext),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(prng_rosc),
+ FUNCTION(qdss_cti_trig_out_b0),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_uart2),
+ FUNCTION(blsp_uart3),
+ FUNCTION(pbs0),
+ FUNCTION(pbs1),
+ FUNCTION(pwr_modem_enabled_b),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(gcc_gp2_clk_b),
+ FUNCTION(ldo_update),
+ FUNCTION(atest_combodac_to_gpio_native),
+ FUNCTION(ldo_en),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(gcc_gp1_clk_b),
+ FUNCTION(pbs2),
+ FUNCTION(atest_gpsadc_dtest0_native),
+ FUNCTION(blsp_spi3),
+ FUNCTION(gcc_gp3_clk_b),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_uart4),
+ FUNCTION(sec_mi2s),
+ FUNCTION(pwr_nav_enabled_b),
+ FUNCTION(codec_mad),
+ FUNCTION(pwr_crypto_enabled_b),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_uart5),
+ FUNCTION(qdss_traceclk_a),
+ FUNCTION(atest_bbrx1),
+ FUNCTION(m_voc),
+ FUNCTION(qdss_cti_trig_in_a0),
+ FUNCTION(qdss_cti_trig_in_b0),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(qdss_traceclk_b),
+ FUNCTION(atest_wlan0),
+ FUNCTION(atest_wlan1),
+ FUNCTION(atest_bbrx0),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(qdss_tracectl_a),
+ FUNCTION(atest_gpsadc_dtest1_native),
+ FUNCTION(qdss_tracedata_a),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_uart6),
+ FUNCTION(qdss_tracectl_b),
+ FUNCTION(mdp_vsync),
+ FUNCTION(pri_mi2s_mclk_a),
+ FUNCTION(sec_mi2s_mclk_a),
+ FUNCTION(cam_mclk),
+ FUNCTION(cci_i2c),
+ FUNCTION(pwr_modem_enabled_a),
+ FUNCTION(cci_timer0),
+ FUNCTION(cci_timer1),
+ FUNCTION(cam1_standby),
+ FUNCTION(pwr_nav_enabled_a),
+ FUNCTION(cam1_rst),
+ FUNCTION(pwr_crypto_enabled_a),
+ FUNCTION(forced_usb),
+ FUNCTION(qdss_cti_trig_out_b1),
+ FUNCTION(cam2_rst),
+ FUNCTION(webcam_standby),
+ FUNCTION(cci_async),
+ FUNCTION(webcam_rst),
+ FUNCTION(ov_ldo),
+ FUNCTION(sd_write),
+ FUNCTION(accel_int),
+ FUNCTION(gcc_gp1_clk_a),
+ FUNCTION(alsp_int),
+ FUNCTION(gcc_gp2_clk_a),
+ FUNCTION(mag_int),
+ FUNCTION(gcc_gp3_clk_a),
+ FUNCTION(blsp6_spi),
+ FUNCTION(fp_int),
+ FUNCTION(qdss_cti_trig_in_b1),
+ FUNCTION(uim_batt),
+ FUNCTION(cam2_standby),
+ FUNCTION(uim1_data),
+ FUNCTION(uim1_clk),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim1_present),
+ FUNCTION(uim2_data),
+ FUNCTION(uim2_clk),
+ FUNCTION(uim2_reset),
+ FUNCTION(uim2_present),
+ FUNCTION(sensor_rst),
+ FUNCTION(mipi_dsi0),
+ FUNCTION(smb_int),
+ FUNCTION(cam0_ldo),
+ FUNCTION(us_euro),
+ FUNCTION(atest_char3),
+ FUNCTION(dbg_out),
+ FUNCTION(bimc_dte0),
+ FUNCTION(ts_resout),
+ FUNCTION(ts_sample),
+ FUNCTION(sec_mi2s_mclk_b),
+ FUNCTION(pri_mi2s),
+ FUNCTION(sdcard_det),
+ FUNCTION(atest_char1),
+ FUNCTION(ebi_cdc),
+ FUNCTION(audio_reset),
+ FUNCTION(atest_char0),
+ FUNCTION(audio_ref),
+ FUNCTION(cdc_pdm0),
+ FUNCTION(pri_mi2s_mclk_b),
+ FUNCTION(lpass_slimbus),
+ FUNCTION(lpass_slimbus0),
+ FUNCTION(lpass_slimbus1),
+ FUNCTION(codec_int1),
+ FUNCTION(codec_int2),
+ FUNCTION(wcss_bt),
+ FUNCTION(atest_char2),
+ FUNCTION(ebi_ch0),
+ FUNCTION(wcss_wlan2),
+ FUNCTION(wcss_wlan1),
+ FUNCTION(wcss_wlan0),
+ FUNCTION(wcss_wlan),
+ FUNCTION(wcss_fm),
+ FUNCTION(ext_lpass),
+ FUNCTION(cri_trng),
+ FUNCTION(cri_trng1),
+ FUNCTION(cri_trng0),
+ FUNCTION(blsp_spi7),
+ FUNCTION(blsp_uart7),
+ FUNCTION(pri_mi2s_ws),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(gcc_tlmm),
+ FUNCTION(dmic0_clk),
+ FUNCTION(dmic0_data),
+ FUNCTION(key_volp),
+ FUNCTION(qdss_cti_trig_in_a1),
+ FUNCTION(us_emitter),
+ FUNCTION(wsa_irq),
+ FUNCTION(wsa_io),
+ FUNCTION(wsa_reset),
+ FUNCTION(blsp_spi8),
+ FUNCTION(blsp_uart8),
+ FUNCTION(blsp_i2c8),
+ FUNCTION(gcc_plltest),
+ FUNCTION(nav_pps_in_a),
+ FUNCTION(pa_indicator),
+ FUNCTION(modem_tsync),
+ FUNCTION(nav_tsync),
+ FUNCTION(nav_pps_in_b),
+ FUNCTION(nav_pps),
+ FUNCTION(gsm0_tx),
+ FUNCTION(atest_char),
+ FUNCTION(atest_tsens),
+ FUNCTION(bimc_dte1),
+ FUNCTION(ssbi_wtr1),
+ FUNCTION(fp_gpio),
+ FUNCTION(coex_uart),
+ FUNCTION(key_snapshot),
+ FUNCTION(key_focus),
+ FUNCTION(nfc_pwr),
+ FUNCTION(blsp8_spi),
+ FUNCTION(qdss_cti_trig_out_a0),
+ FUNCTION(qdss_cti_trig_out_a1),
+};
+
+static const struct msm_pingroup msm8937_groups[] = {
+ PINGROUP(0, blsp_spi1, blsp_uart1, qdss_tracedata_b, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(1, blsp_spi1, blsp_uart1, adsp_ext, NA, NA, NA, NA, NA,
+ qdss_tracedata_b),
+ PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, prng_rosc, NA, NA, NA,
+ NA, NA),
+ PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(4, blsp_spi2, blsp_uart2, ldo_update, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(5, blsp_spi2, blsp_uart2, ldo_en, NA, NA, NA, NA, NA, NA),
+ PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, gcc_gp1_clk_b,
+ qdss_tracedata_b, NA, NA, NA, NA),
+ PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, pbs2, NA,
+ qdss_tracedata_b, NA, atest_gpsadc_dtest0_native, NA),
+ PINGROUP(8, blsp_spi3, blsp_uart3, pbs0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(9, blsp_spi3, blsp_uart3, pbs1, pwr_modem_enabled_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(10, blsp_spi3, blsp_uart3, blsp_i2c3, gcc_gp2_clk_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(11, blsp_spi3, blsp_uart3, blsp_i2c3, gcc_gp3_clk_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(12, blsp_spi4, blsp_uart4, sec_mi2s, pwr_nav_enabled_b, NA,
+ NA, NA, NA, NA),
+ PINGROUP(13, blsp_spi4, blsp_uart4, sec_mi2s, pwr_crypto_enabled_b, NA,
+ NA, NA, NA, NA),
+ PINGROUP(14, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+ PINGROUP(15, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+ PINGROUP(16, blsp_spi5, blsp_uart5, NA, NA, NA, NA, qdss_traceclk_a,
+ NA, atest_bbrx1),
+ PINGROUP(17, blsp_spi5, blsp_uart5, m_voc, qdss_cti_trig_in_a0, NA,
+ atest_bbrx0, NA, NA, NA),
+ PINGROUP(18, blsp_spi5, blsp_uart5, blsp_i2c5, qdss_tracectl_a, NA,
+ atest_gpsadc_dtest1_native, NA, NA, NA),
+ PINGROUP(19, blsp_spi5, blsp_uart5, blsp_i2c5, qdss_tracedata_a, NA,
+ NA, NA, NA, NA),
+ PINGROUP(20, blsp_spi6, blsp_uart6, NA, NA, NA, NA, NA, NA,
+ qdss_tracectl_b),
+ PINGROUP(21, blsp_spi6, blsp_uart6, m_voc, NA, NA, NA, NA, NA,
+ qdss_cti_trig_in_b0),
+ PINGROUP(22, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_b, NA,
+ atest_wlan0, NA, NA, NA),
+ PINGROUP(23, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_tracedata_b, NA,
+ atest_wlan1, NA, NA, NA),
+ PINGROUP(24, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(25, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a, NA, NA, NA,
+ NA, NA, NA),
+ PINGROUP(26, cam_mclk, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA),
+ PINGROUP(27, cam_mclk, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(28, cam_mclk, NA, NA, NA, NA, NA, qdss_tracedata_a, NA,
+ atest_combodac_to_gpio_native),
+ PINGROUP(29, cci_i2c, pwr_modem_enabled_a, NA, NA, NA, NA, NA,
+ qdss_tracedata_a, NA),
+ PINGROUP(30, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(31, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(32, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(33, cci_timer0, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(34, cci_timer1, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+ PINGROUP(35, pwr_nav_enabled_a, NA, NA, NA, NA, NA, NA, NA,
+ qdss_tracedata_a),
+ PINGROUP(36, pwr_crypto_enabled_a, NA, NA, NA, NA, NA, NA, NA,
+ qdss_tracedata_a),
+ PINGROUP(37, NA, NA, NA, NA, NA, qdss_cti_trig_out_b1, NA, NA, NA),
+ PINGROUP(38, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(39, cci_async, NA, NA, NA, NA, NA, qdss_tracedata_a, NA,
+ atest_combodac_to_gpio_native),
+ PINGROUP(40, NA, NA, NA, NA, qdss_tracedata_a, NA,
+ atest_combodac_to_gpio_native, NA, NA),
+ PINGROUP(41, sd_write, NA, NA, NA, NA, NA, NA, NA,
+ atest_combodac_to_gpio_native),
+ PINGROUP(42, gcc_gp1_clk_a, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+ PINGROUP(43, gcc_gp2_clk_a, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+ PINGROUP(44, gcc_gp3_clk_a, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+ PINGROUP(45, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(46, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(47, blsp6_spi, NA, qdss_tracedata_b, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA),
+ PINGROUP(48, NA, qdss_cti_trig_in_b1, NA,
+ atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+ PINGROUP(49, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(50, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(51, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(52, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(53, uim1_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(54, uim1_present, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(55, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(56, uim2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(57, uim2_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(58, uim2_present, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(59, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(60, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(61, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(63, atest_char3, dbg_out, bimc_dte0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(65, bimc_dte0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(66, sec_mi2s_mclk_b, pri_mi2s, NA, qdss_tracedata_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(67, atest_char1, ebi_cdc, NA, atest_combodac_to_gpio_native,
+ NA, NA, NA, NA, NA),
+ PINGROUP(68, atest_char0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(69, audio_ref, cdc_pdm0, pri_mi2s_mclk_b, ebi_cdc, NA, NA, NA,
+ NA, NA),
+ PINGROUP(70, lpass_slimbus, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(71, lpass_slimbus0, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(72, lpass_slimbus1, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(75, wcss_bt, atest_char2, NA, ebi_ch0, NA, NA, NA, NA, NA),
+ PINGROUP(76, wcss_wlan2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(77, wcss_wlan1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(78, wcss_wlan0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, wcss_wlan, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, wcss_wlan, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(81, wcss_fm, ext_lpass, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, wcss_fm, cri_trng, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(83, wcss_bt, cri_trng1, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(84, wcss_bt, cri_trng0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(85, pri_mi2s, blsp_spi7, blsp_uart7, NA, NA, NA, NA, NA, NA),
+ PINGROUP(86, pri_mi2s, blsp_spi7, blsp_uart7, qdss_tracedata_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(87, pri_mi2s_ws, blsp_spi7, blsp_uart7, blsp_i2c7,
+ qdss_tracedata_b, gcc_tlmm, NA, NA, NA),
+ PINGROUP(88, pri_mi2s, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA,
+ NA, NA),
+ PINGROUP(89, dmic0_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(90, dmic0_data, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(91, NA, NA, NA, NA, NA, qdss_cti_trig_in_a1, NA, NA, NA),
+ PINGROUP(92, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, NA),
+ PINGROUP(93, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(94, wsa_io, sec_mi2s, pri_mi2s, NA, NA, NA, NA, NA, NA),
+ PINGROUP(95, wsa_io, sec_mi2s, pri_mi2s, NA, NA, NA, NA, NA, NA),
+ PINGROUP(96, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(97, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, blsp_spi8, blsp_uart8, blsp_i2c8, gcc_plltest, NA, NA, NA,
+ NA, NA),
+ PINGROUP(99, blsp_spi8, blsp_uart8, blsp_i2c8, gcc_plltest, NA, NA, NA,
+ NA, NA),
+ PINGROUP(100, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(101, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(112, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(113, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(114, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(115, NA, NA, nav_pps_in_a, NA, atest_combodac_to_gpio_native,
+ NA, NA, NA, NA),
+ PINGROUP(116, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(117, NA, modem_tsync, nav_tsync, nav_pps_in_b, nav_pps, NA,
+ NA, NA, NA),
+ PINGROUP(118, NA, ebi_cdc, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(119, gsm0_tx, NA, ebi_cdc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(120, NA, atest_char, ebi_cdc, NA, atest_tsens, NA, NA, NA, NA),
+ PINGROUP(121, NA, NA, NA, bimc_dte1, NA, NA, NA, NA, NA),
+ PINGROUP(122, NA, ssbi_wtr1, NA, NA, bimc_dte1, NA, NA, NA, NA),
+ PINGROUP(123, NA, ssbi_wtr1, ebi_cdc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(124, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(127, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(130, blsp8_spi, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(131, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(132, qdss_cti_trig_out_a0, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(133, qdss_cti_trig_out_a1, NA, NA, NA, NA, NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc1_rclk, 0x10a000, 15, 0),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0),
+ SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+ SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+ SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+ SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+ SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+ SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data msm8937_pinctrl = {
+ .pins = msm8937_pins,
+ .npins = ARRAY_SIZE(msm8937_pins),
+ .functions = msm8937_functions,
+ .nfunctions = ARRAY_SIZE(msm8937_functions),
+ .groups = msm8937_groups,
+ .ngroups = ARRAY_SIZE(msm8937_groups),
+ .ngpios = 134,
+};
+
+static int msm8937_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &msm8937_pinctrl);
+}
+
+static const struct of_device_id msm8937_pinctrl_of_match[] = {
+ { .compatible = "qcom,msm8937-pinctrl", },
+ { },
+};
+
+static struct platform_driver msm8937_pinctrl_driver = {
+ .driver = {
+ .name = "msm8937-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = msm8937_pinctrl_of_match,
+ },
+ .probe = msm8937_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init msm8937_pinctrl_init(void)
+{
+ return platform_driver_register(&msm8937_pinctrl_driver);
+}
+arch_initcall(msm8937_pinctrl_init);
+
+static void __exit msm8937_pinctrl_exit(void)
+{
+ platform_driver_unregister(&msm8937_pinctrl_driver);
+}
+module_exit(msm8937_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI msm8937 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8937_pinctrl_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index 6ceb39a..c5f1307 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -1105,6 +1105,97 @@
[106] = SDC_QDSD_PINGROUP(sdc2_data, 0x0, 9, 0),
};
+static struct msm_gpio_mux_input sdxpoorwills_mux_in[] = {
+ {0, 1},
+ {1, 2},
+ {2, 5},
+ {3, 6},
+ {4, 9},
+ {5, 10},
+ {6, 11},
+ {7, 12},
+ {8, 13},
+ {9, 14},
+ {10, 15},
+ {11, 16},
+ {12, 17},
+ {13, 18},
+ {14, 19},
+ {15, 21},
+ {16, 22},
+ {17, 24},
+ {18, 25},
+ {19, 35},
+ {20, 42, 1},
+ {21, 43},
+ {22, 45},
+ {23, 46},
+ {24, 48},
+ {25, 50},
+ {26, 52},
+ {27, 53},
+ {28, 54},
+ {29, 55},
+ {30, 56},
+ {31, 57},
+ {32, 60},
+ {33, 61},
+ {34, 64},
+ {35, 65},
+ {36, 68},
+ {37, 71},
+ {38, 75},
+ {39, 76},
+ {40, 78},
+ {41, 79},
+ {42, 80},
+ {43, 82},
+ {44, 83},
+ {45, 84},
+ {46, 86},
+ {47, 87},
+ {48, 88},
+ {49, 89},
+ {50, 90},
+ {51, 93},
+ {52, 94},
+ {53, 95},
+ {54, 97},
+ {55, 98},
+};
+
+static struct msm_pdc_mux_output sdxpoorwills_mux_out[] = {
+ {0, 167},
+ {0, 168},
+ {0, 169},
+ {0, 170},
+ {0, 171},
+ {0, 172},
+ {0, 173},
+ {0, 174},
+ {0, 175},
+ {0, 176},
+ {0, 177},
+ {0, 178},
+ {0, 179},
+ {0, 180},
+ {0, 181},
+ {0, 182},
+ {0, 183},
+ {0, 184},
+ {0, 185},
+ {0, 186},
+ {0, 187},
+ {0, 188},
+ {0, 189},
+ {0, 190},
+ {0, 191},
+ {0, 192},
+ {0, 193},
+ {0, 194},
+ {0, 195},
+};
+
static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
.pins = sdxpoorwills_pins,
.npins = ARRAY_SIZE(sdxpoorwills_pins),
@@ -1112,6 +1203,11 @@
.nfunctions = ARRAY_SIZE(sdxpoorwills_functions),
.groups = sdxpoorwills_groups,
.ngroups = ARRAY_SIZE(sdxpoorwills_groups),
+ .gpio_mux_in = sdxpoorwills_mux_in,
+ .n_gpio_mux_in = ARRAY_SIZE(sdxpoorwills_mux_in),
+ .pdc_mux_out = sdxpoorwills_mux_out,
+ .n_pdc_mux_out = ARRAY_SIZE(sdxpoorwills_mux_out),
+ .n_pdc_mux_offset = 20,
.ngpios = 100,
};
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index ae24675..01c0736 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -4394,6 +4394,8 @@
/* Prevent consequent calls from trying to load the FW again. */
if (ipa3_ctx->ipa_initialization_complete)
return 0;
+ /* move proxy vote for modem on ipa3_post_init */
+ IPA_ACTIVE_CLIENTS_INC_SPECIAL("PROXY_CLK_VOTE");
/*
* indication whether working in MHI config or non MHI config is given
@@ -4858,7 +4860,6 @@
int result = 0;
int i;
struct ipa3_rt_tbl_set *rset;
- struct ipa_active_client_logging_info log_info;
IPADBG("IPA Driver initialization started\n");
@@ -5049,8 +5050,7 @@
}
mutex_init(&ipa3_ctx->ipa3_active_clients.mutex);
- IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE");
- ipa3_active_clients_log_inc(&log_info, false);
+ /* move proxy vote for modem to ipa3_post_init() */
atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1);
/* Create workqueues for power management */
@@ -5296,6 +5296,8 @@
IPADBG("ipa cdev added successful. major:%d minor:%d\n",
MAJOR(ipa3_ctx->dev_num),
MINOR(ipa3_ctx->dev_num));
+ /* proxy vote for modem is added in ipa3_post_init() phase */
+ IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return 0;
fail_cdev_add:
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 941e489..648db5e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -1209,8 +1209,6 @@
IPADBG("Skipping endpoint configuration.\n");
}
- ipa3_enable_data_path(ipa_ep_idx);
-
out->clnt_hdl = ipa_ep_idx;
if (!ep->skip_ep_cfg && IPA_CLIENT_IS_PROD(in->sys.client))
@@ -1316,6 +1314,7 @@
struct ipa3_ep_context *ep;
union IpaHwWdiCommonChCmdData_t enable;
struct ipa_ep_cfg_holb holb_cfg;
+ struct ipahal_reg_endp_init_rsrc_grp rsrc_grp;
if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
ipa3_ctx->ep[clnt_hdl].valid == 0) {
@@ -1348,6 +1347,20 @@
goto uc_timeout;
}
+ /* Assign the resource group for pipe */
+ memset(&rsrc_grp, 0, sizeof(rsrc_grp));
+ rsrc_grp.rsrc_grp = ipa_get_ep_group(ep->client);
+ if (rsrc_grp.rsrc_grp == -1) {
+ IPAERR("invalid group for client %d\n", ep->client);
+ WARN_ON(1);
+ return -EFAULT;
+ }
+
+ IPADBG("Setting group %d for pipe %d\n",
+ rsrc_grp.rsrc_grp, clnt_hdl);
+ ipahal_write_reg_n_fields(IPA_ENDP_INIT_RSRC_GRP_n, clnt_hdl,
+ &rsrc_grp);
+
if (IPA_CLIENT_IS_CONS(ep->client)) {
memset(&holb_cfg, 0, sizeof(holb_cfg));
holb_cfg.en = IPA_HOLB_TMR_DIS;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 95e3782..dec698f 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, 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
@@ -3139,7 +3139,8 @@
}
dev = &ctx->usb_bam_pdev->dev;
- if (dev && dev->parent && !device_property_present(dev->parent,
+ if (dev && dev->parent && device_property_present(dev->parent, "iommus")
+ && !device_property_present(dev->parent,
"qcom,smmu-s1-bypass")) {
pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
__func__, dev_name(dev));
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 99120f4..a2a35c6 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -170,6 +170,7 @@
FG_SRAM_SYS_TERM_CURR,
FG_SRAM_CHG_TERM_CURR,
FG_SRAM_CHG_TERM_BASE_CURR,
+ FG_SRAM_CUTOFF_CURR,
FG_SRAM_DELTA_MSOC_THR,
FG_SRAM_DELTA_BSOC_THR,
FG_SRAM_RECHARGE_SOC_THR,
@@ -262,6 +263,7 @@
int chg_term_curr_ma;
int chg_term_base_curr_ma;
int sys_term_curr_ma;
+ int cutoff_curr_ma;
int delta_soc_thr;
int recharge_soc_thr;
int recharge_volt_thr_mv;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 2c62218..0894f37 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -35,6 +35,8 @@
#define ESR_PULSE_THRESH_OFFSET 3
#define SLOPE_LIMIT_WORD 3
#define SLOPE_LIMIT_OFFSET 0
+#define CUTOFF_CURR_WORD 4
+#define CUTOFF_CURR_OFFSET 0
#define CUTOFF_VOLT_WORD 5
#define CUTOFF_VOLT_OFFSET 0
#define SYS_TERM_CURR_WORD 6
@@ -208,6 +210,8 @@
1000000, 122070, 0, fg_encode_current, NULL),
PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
100000, 390625, 0, fg_encode_current, NULL),
+ PARAM(CUTOFF_CURR, CUTOFF_CURR_WORD, CUTOFF_CURR_OFFSET, 3,
+ 1000000, 122070, 0, fg_encode_current, NULL),
PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, 1,
2048, 100, 0, fg_encode_default, NULL),
PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, 1,
@@ -284,6 +288,8 @@
PARAM(CHG_TERM_BASE_CURR, CHG_TERM_CURR_v2_WORD,
CHG_TERM_BASE_CURR_v2_OFFSET, 1, 1024, 1000, 0,
fg_encode_current, NULL),
+ PARAM(CUTOFF_CURR, CUTOFF_CURR_WORD, CUTOFF_CURR_OFFSET, 3,
+ 1000000, 122070, 0, fg_encode_current, NULL),
PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_v2_WORD, DELTA_MSOC_THR_v2_OFFSET,
1, 2048, 100, 0, fg_encode_default, NULL),
PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_v2_WORD, DELTA_BSOC_THR_v2_OFFSET,
@@ -3974,6 +3980,16 @@
return rc;
}
+ fg_encode(chip->sp, FG_SRAM_CUTOFF_CURR, chip->dt.cutoff_curr_ma,
+ buf);
+ rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_CURR].addr_word,
+ chip->sp[FG_SRAM_CUTOFF_CURR].addr_byte, buf,
+ chip->sp[FG_SRAM_CUTOFF_CURR].len, FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing cutoff_curr, rc=%d\n", rc);
+ return rc;
+ }
+
if (!(chip->wa_flags & PMI8998_V1_REV_WA)) {
fg_encode(chip->sp, FG_SRAM_CHG_TERM_BASE_CURR,
chip->dt.chg_term_base_curr_ma, buf);
@@ -4697,6 +4713,7 @@
#define DEFAULT_CHG_TERM_CURR_MA 100
#define DEFAULT_CHG_TERM_BASE_CURR_MA 75
#define DEFAULT_SYS_TERM_CURR_MA -125
+#define DEFAULT_CUTOFF_CURR_MA 500
#define DEFAULT_DELTA_SOC_THR 1
#define DEFAULT_RECHARGE_SOC_THR 95
#define DEFAULT_BATT_TEMP_COLD 0
@@ -4860,6 +4877,12 @@
else
chip->dt.chg_term_base_curr_ma = temp;
+ rc = of_property_read_u32(node, "qcom,fg-cutoff-current", &temp);
+ if (rc < 0)
+ chip->dt.cutoff_curr_ma = DEFAULT_CUTOFF_CURR_MA;
+ else
+ chip->dt.cutoff_curr_ma = temp;
+
rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
if (rc < 0)
chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index d8cc2c4..59897ea 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -376,7 +376,7 @@
static struct channel_ctx *ch_name_to_ch_ctx_create(
struct glink_core_xprt_ctx *xprt_ctx,
- const char *name);
+ const char *name, bool local);
static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
uint32_t riid, void *cookie);
@@ -1836,13 +1836,14 @@
* it is not found and get reference of context.
* @xprt_ctx: Transport to search for a matching channel.
* @name: Name of the desired channel.
+ * @local: If called from local open or not
*
* Return: The channel corresponding to @name, NULL if a matching channel was
* not found AND a new channel could not be created.
*/
static struct channel_ctx *ch_name_to_ch_ctx_create(
struct glink_core_xprt_ctx *xprt_ctx,
- const char *name)
+ const char *name, bool local)
{
struct channel_ctx *entry;
struct channel_ctx *ctx;
@@ -1886,10 +1887,23 @@
list_for_each_entry_safe(entry, temp, &xprt_ctx->channels,
port_list_node)
if (!strcmp(entry->name, name) && !entry->pending_delete) {
+ rwref_get(&entry->ch_state_lhb2);
+ /* port already exists */
+ if (entry->local_open_state != GLINK_CHANNEL_CLOSED
+ && local) {
+ /* not ready to be re-opened */
+ GLINK_INFO_CH_XPRT(entry, xprt_ctx,
+ "%s: Ch not ready. State: %u\n",
+ __func__, entry->local_open_state);
+ rwref_put(&entry->ch_state_lhb2);
+ entry = NULL;
+ } else if (local) {
+ entry->local_open_state =
+ GLINK_CHANNEL_OPENING;
+ }
spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1,
flags);
kfree(ctx);
- rwref_get(&entry->ch_state_lhb2);
rwref_write_put(&xprt_ctx->xprt_state_lhb0);
return entry;
}
@@ -1919,6 +1933,8 @@
ctx->transport_ptr = xprt_ctx;
rwref_get(&ctx->ch_state_lhb2);
+ if (local)
+ ctx->local_open_state = GLINK_CHANNEL_OPENING;
list_add_tail(&ctx->port_list_node, &xprt_ctx->channels);
GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx,
@@ -2604,23 +2620,13 @@
* look for an existing port structure which can occur in
* reopen and remote-open-first cases
*/
- ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name);
+ ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name, true);
if (ctx == NULL) {
GLINK_ERR("%s:%s %s: Error - unable to allocate new channel\n",
cfg->transport, cfg->edge, __func__);
return ERR_PTR(-ENOMEM);
}
- /* port already exists */
- if (ctx->local_open_state != GLINK_CHANNEL_CLOSED) {
- /* not ready to be re-opened */
- GLINK_INFO_CH_XPRT(ctx, transport_ptr,
- "%s: Channel not ready to be re-opened. State: %u\n",
- __func__, ctx->local_open_state);
- rwref_put(&ctx->ch_state_lhb2);
- return ERR_PTR(-EBUSY);
- }
-
/* initialize port structure */
ctx->user_priv = cfg->priv;
ctx->rx_intent_req_timeout_jiffies =
@@ -2651,7 +2657,6 @@
ctx->local_xprt_req = best_id;
ctx->no_migrate = cfg->transport &&
!(cfg->options & GLINK_OPT_INITIAL_XPORT);
- ctx->local_open_state = GLINK_CHANNEL_OPENING;
GLINK_INFO_PERF_CH(ctx,
"%s: local:GLINK_CHANNEL_CLOSED->GLINK_CHANNEL_OPENING\n",
__func__);
@@ -4912,7 +4917,7 @@
bool do_migrate;
glink_core_migration_edge_lock(if_ptr->glink_core_priv);
- ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name);
+ ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name, false);
if (ctx == NULL) {
GLINK_ERR_XPRT(if_ptr->glink_core_priv,
"%s: invalid rcid %u received, name '%s'\n",
@@ -5015,6 +5020,7 @@
struct channel_ctx *ctx;
bool is_ch_fully_closed;
struct glink_core_xprt_ctx *xprt_ptr = if_ptr->glink_core_priv;
+ unsigned long flags;
ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
if (!ctx) {
@@ -5032,11 +5038,13 @@
rwref_put(&ctx->ch_state_lhb2);
return;
}
+ spin_lock_irqsave(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
+ ctx->pending_delete = true;
+ spin_unlock_irqrestore(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
GLINK_INFO_CH(ctx, "%s: remote: OPENED->CLOSED\n", __func__);
is_ch_fully_closed = glink_core_remote_close_common(ctx, false);
- ctx->pending_delete = true;
if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, rcid);
if (is_ch_fully_closed) {
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 2fb95fe..e3a50e3 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2354,29 +2354,6 @@
return 0;
}
-static int icnss_call_driver_remove(struct icnss_priv *priv)
-{
- icnss_pr_dbg("Calling driver remove state: 0x%lx\n", priv->state);
-
- clear_bit(ICNSS_FW_READY, &priv->state);
-
- if (!test_bit(ICNSS_DRIVER_PROBED, &penv->state))
- return 0;
-
- if (!priv->ops || !priv->ops->remove)
- return 0;
-
- set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
- penv->ops->remove(&priv->pdev->dev);
-
- clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
- clear_bit(ICNSS_DRIVER_PROBED, &priv->state);
-
- icnss_hw_power_off(penv);
-
- return 0;
-}
-
static int icnss_fw_crashed(struct icnss_priv *priv,
struct icnss_event_pd_service_down_data *event_data)
{
@@ -2416,10 +2393,7 @@
if (priv->force_err_fatal)
ICNSS_ASSERT(0);
- if (event_data->crashed)
- icnss_fw_crashed(priv, event_data);
- else
- icnss_call_driver_remove(priv);
+ icnss_fw_crashed(priv, event_data);
out:
kfree(data);
@@ -3102,6 +3076,12 @@
if (!dev)
return -ENODEV;
+ if (test_bit(ICNSS_FW_DOWN, &penv->state)) {
+ icnss_pr_err("FW down, ignoring fw_log_mode state: 0x%lx\n",
+ penv->state);
+ return -EINVAL;
+ }
+
icnss_pr_dbg("FW log mode: %u\n", fw_log_mode);
ret = wlfw_ini_send_sync_msg(fw_log_mode);
@@ -3195,6 +3175,12 @@
if (!dev)
return -ENODEV;
+ if (test_bit(ICNSS_FW_DOWN, &penv->state)) {
+ icnss_pr_err("FW down, ignoring wlan_enable state: 0x%lx\n",
+ penv->state);
+ return -EINVAL;
+ }
+
icnss_pr_dbg("Mode: %d, config: %p, host_version: %s\n",
mode, config, host_version);
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 1bc9239..3b6c0bd 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -161,7 +161,7 @@
region_info = (struct md_ss_region __iomem *)subsys_segtable_base;
if (!region_info)
return -EINVAL;
- pr_debug("Segments in minidump 0x%x\n", ss_mdump_seg_cnt);
+ pr_info("Minidump : Segments in minidump 0x%x\n", ss_mdump_seg_cnt);
ramdump_segs = kcalloc(ss_mdump_seg_cnt,
sizeof(*ramdump_segs), GFP_KERNEL);
if (!ramdump_segs)
@@ -184,7 +184,7 @@
offset = offset +
sizeof(region_info->region_base_address);
s->size = __raw_readl(offset);
- pr_debug("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
+ pr_info("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
s->name, s->address, (unsigned int)s->size);
} else
ss_valid_seg_cnt--;
@@ -220,15 +220,15 @@
int count = 0, ret;
if (desc->minidump) {
- pr_debug("Minidump : md_ss_toc->md_ss_toc_init is 0x%x\n",
+ pr_info("Minidump : md_ss_toc->md_ss_toc_init is 0x%x\n",
(unsigned int)desc->minidump->md_ss_toc_init);
- pr_debug("Minidump : md_ss_toc->md_ss_enable_status is 0x%x\n",
+ pr_info("Minidump : md_ss_toc->md_ss_enable_status is 0x%x\n",
(unsigned int)desc->minidump->md_ss_enable_status);
- pr_debug("Minidump : md_ss_toc->encryption_status is 0x%x\n",
+ pr_info("Minidump : md_ss_toc->encryption_status is 0x%x\n",
(unsigned int)desc->minidump->encryption_status);
- pr_debug("Minidump : md_ss_toc->ss_region_count is 0x%x\n",
+ pr_info("Minidump : md_ss_toc->ss_region_count is 0x%x\n",
(unsigned int)desc->minidump->ss_region_count);
- pr_debug("Minidump : md_ss_toc->md_ss_smem_regions_baseptr is 0x%x\n",
+ pr_info("Minidump : md_ss_toc->md_ss_smem_regions_baseptr is 0x%x\n",
(unsigned int)
desc->minidump->md_ss_smem_regions_baseptr);
/**
@@ -241,11 +241,11 @@
MD_SS_ENABLED)) {
if (desc->minidump->encryption_status ==
MD_SS_ENCR_DONE) {
- pr_debug("Dumping Minidump for %s\n",
+ pr_info("Minidump : Dumping for %s\n",
desc->name);
return pil_do_minidump(desc, minidump_dev);
}
- pr_debug("Minidump aborted for %s\n", desc->name);
+ pr_info("Minidump : aborted for %s\n", desc->name);
return -EINVAL;
}
}
diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c
index 68ff0f3..bc47a95 100644
--- a/drivers/soc/qcom/pil-msa.c
+++ b/drivers/soc/qcom/pil-msa.c
@@ -557,7 +557,7 @@
{
struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
phys_addr_t start_addr = pil_get_entry_addr(pil);
- u32 debug_val;
+ u32 debug_val = 0;
int ret;
trace_pil_func(__func__);
@@ -576,8 +576,10 @@
if (ret)
goto err_clks;
- /* Save state of modem debug register before full reset */
- debug_val = readl_relaxed(drv->reg_base + QDSP6SS_DBG_CFG);
+ if (!pil->minidump || !pil->modem_ssr) {
+ /* Save state of modem debug register before full reset */
+ debug_val = readl_relaxed(drv->reg_base + QDSP6SS_DBG_CFG);
+ }
/* Assert reset to subsystem */
pil_mss_assert_resets(drv);
@@ -587,9 +589,12 @@
if (ret)
goto err_restart;
- writel_relaxed(debug_val, drv->reg_base + QDSP6SS_DBG_CFG);
- if (modem_dbg_cfg)
- writel_relaxed(modem_dbg_cfg, drv->reg_base + QDSP6SS_DBG_CFG);
+ if (!pil->minidump || !pil->modem_ssr) {
+ writel_relaxed(debug_val, drv->reg_base + QDSP6SS_DBG_CFG);
+ if (modem_dbg_cfg)
+ writel_relaxed(modem_dbg_cfg,
+ drv->reg_base + QDSP6SS_DBG_CFG);
+ }
/* Program Image Address */
if (drv->self_auth) {
@@ -819,8 +824,8 @@
* Need to Wait for timeout for debug reset sequence to
* complete before returning
*/
- pr_debug("Minidump: waiting encryption to complete\n");
- msleep(30000);
+ pr_info("Minidump: waiting encryption to complete\n");
+ msleep(10000);
if (pil->minidump) {
writel_relaxed(0x2, drv->reg_base + QDSP6SS_NMI_CFG);
/* Let write complete before proceeding */
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index 721124c..ac322f8 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -167,6 +167,11 @@
if (ret)
return ret;
+ pil_mss_remove_proxy_votes(&drv->q6->desc);
+ ret = pil_mss_make_proxy_votes(&drv->q6->desc);
+ if (ret)
+ return ret;
+
ret = pil_mss_reset_load_mba(&drv->q6->desc);
if (ret)
return ret;
diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c
index cab7178..fec6f17 100644
--- a/drivers/soc/qcom/scm.c
+++ b/drivers/soc/qcom/scm.c
@@ -185,9 +185,8 @@
case SCM_ENOMEM:
return -ENOMEM;
case SCM_EBUSY:
- return SCM_EBUSY;
case SCM_V2_EBUSY:
- return SCM_V2_EBUSY;
+ return -EBUSY;
}
return -EINVAL;
}
@@ -338,13 +337,13 @@
do {
ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len,
resp_buf, resp_len, cmd, len);
- if (ret == SCM_EBUSY)
+ if (ret == -EBUSY)
msleep(SCM_EBUSY_WAIT_MS);
if (retry_count == 33)
pr_warn("scm: secure world has been busy for 1 second!\n");
- } while (ret == SCM_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
+ } while (ret == -EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
- if (ret == SCM_EBUSY)
+ if (ret == -EBUSY)
pr_err("scm: secure world busy (rc = SCM_EBUSY)\n");
return ret;
@@ -799,7 +798,7 @@
ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,
resp_len, cmd, len);
- if (unlikely(ret == SCM_EBUSY))
+ if (unlikely(ret == -EBUSY))
ret = _scm_call_retry(svc_id, cmd_id, cmd_buf, cmd_len,
resp_buf, resp_len, cmd, PAGE_ALIGN(len));
kfree(cmd);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 41f1a19..83b46d4 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -561,13 +561,15 @@
task_lock(selected);
send_sig(SIGKILL, selected, 0);
- if (selected->mm)
+ if (selected->mm) {
task_set_lmk_waiting(selected);
- if (oom_reaper)
- mark_lmk_victim(selected);
+ if (!test_bit(MMF_OOM_SKIP, &selected->mm->flags) &&
+ oom_reaper) {
+ mark_lmk_victim(selected);
+ wake_oom_reaper(selected);
+ }
+ }
task_unlock(selected);
- if (oom_reaper)
- wake_oom_reaper(selected);
trace_lowmemory_kill(selected, cache_size, cache_limit, free);
lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n"
"to free %ldkB on behalf of '%s' (%d) because\n"
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 5c4a24d..89bf6b7 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1061,6 +1061,8 @@
struct dwc3_trb *trb;
int num_trbs = (dep->direction) ? (2 * (req->num_bufs) + 2)
: (req->num_bufs + 2);
+ struct scatterlist *sg;
+ struct sg_table *sgt;
dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
num_trbs * sizeof(struct dwc3_trb),
@@ -1073,6 +1075,19 @@
}
dep->num_trbs = num_trbs;
+ dma_get_sgtable(dwc->sysdev, &req->sgt_trb_xfer_ring, dep->trb_pool,
+ dep->trb_pool_dma, num_trbs * sizeof(struct dwc3_trb));
+
+ sgt = &req->sgt_trb_xfer_ring;
+ dev_dbg(dwc->dev, "%s(): trb_pool:%pK trb_pool_dma:%lx\n",
+ __func__, dep->trb_pool, (unsigned long)dep->trb_pool_dma);
+
+ for_each_sg(sgt->sgl, sg, sgt->nents, i)
+ dev_dbg(dwc->dev,
+ "%i: page_link:%lx offset:%x length:%x address:%lx\n",
+ i, sg->page_link, sg->offset, sg->length,
+ (unsigned long)sg->dma_address);
+
/* IN direction */
if (dep->direction) {
for (i = 0; i < num_trbs ; i++) {
@@ -1138,11 +1153,13 @@
}
}
- pr_debug("%s: Initialized TRB Ring for %s\n", __func__, dep->name);
+ dev_dbg(dwc->dev, "%s: Initialized TRB Ring for %s\n",
+ __func__, dep->name);
trb = &dep->trb_pool[0];
if (trb) {
for (i = 0; i < num_trbs; i++) {
- pr_debug("TRB(%d): ADDRESS:%lx bpl:%x bph:%x size:%x ctrl:%x\n",
+ dev_dbg(dwc->dev,
+ "TRB %d: ADDR:%lx bpl:%x bph:%x sz:%x ctl:%x\n",
i, (unsigned long)dwc3_trb_dma_offset(dep,
&dep->trb_pool[i]), trb->bpl, trb->bph,
trb->size, trb->ctrl);
@@ -1159,7 +1176,7 @@
* @usb_ep - pointer to usb_ep instance.
*
*/
-static void gsi_free_trbs(struct usb_ep *ep)
+static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
@@ -1176,6 +1193,7 @@
dep->trb_pool = NULL;
dep->trb_pool_dma = 0;
}
+ sg_free_table(&req->sgt_trb_xfer_ring);
}
/*
* Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
@@ -1365,7 +1383,8 @@
break;
case GSI_EP_OP_FREE_TRBS:
dev_dbg(mdwc->dev, "EP_OP_FREE_TRBS for %s\n", ep->name);
- gsi_free_trbs(ep);
+ request = (struct usb_gsi_request *)op_data;
+ gsi_free_trbs(ep, request);
break;
case GSI_EP_OP_CONFIG:
request = (struct usb_gsi_request *)op_data;
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 4911253..1f75b58 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -76,7 +76,7 @@
writel_relaxed(write_val, base + offset - DWC3_GLOBALS_REGS_START);
/* Read back to see if value was written */
- tmp = readl_relaxed(base + offset);
+ tmp = readl_relaxed(base + offset - DWC3_GLOBALS_REGS_START);
dwc3_trace(trace_dwc3_masked_write_readback,
"addr %p readback val %08x",
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 9f7a29a..05a66b2 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -158,6 +158,13 @@
.bInterval = 4, /* poll 1 per millisecond */
};
+static struct usb_ss_ep_comp_descriptor ss_as_in_comp_desc = {
+ .bLength = sizeof(ss_as_in_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ .wBytesPerInterval = cpu_to_le16(IN_EP_MAX_PACKET_SIZE),
+};
+
/* Standard ISO IN Endpoint Descriptor for highspeed */
static struct usb_endpoint_descriptor fs_as_in_ep_desc = {
.bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -198,6 +205,26 @@
NULL,
};
+static struct usb_descriptor_header *ss_audio_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&input_terminal_desc,
+ (struct usb_descriptor_header *)&output_terminal_desc,
+ (struct usb_descriptor_header *)&feature_unit_desc,
+
+ (struct usb_descriptor_header *)&as_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_header_desc,
+
+ (struct usb_descriptor_header *)&as_type_i_desc,
+
+ (struct usb_descriptor_header *)&hs_as_in_ep_desc,
+ (struct usb_descriptor_header *)&ss_as_in_comp_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
+ NULL,
+};
+
static struct usb_descriptor_header *fs_audio_desc[] = {
(struct usb_descriptor_header *)&ac_interface_desc,
(struct usb_descriptor_header *)&ac_header_desc,
@@ -673,6 +700,7 @@
f->fs_descriptors = fs_audio_desc;
f->hs_descriptors = hs_audio_desc;
+ f->ss_descriptors = ss_audio_desc;
for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) {
req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 37903f9..4bdfadf 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -307,6 +307,10 @@
in_params->data_buff_base_len = d_port->in_request.buf_len *
d_port->in_request.num_bufs;
in_params->data_buff_base_addr_iova = d_port->in_request.dma;
+ in_params->sgt_xfer_rings = &d_port->in_request.sgt_trb_xfer_ring;
+ in_params->sgt_data_buff = &d_port->in_request.sgt_data_buff;
+ log_event_dbg("%s(): IN: sgt_xfer_rings:%pK sgt_data_buff:%pK\n",
+ __func__, in_params->sgt_xfer_rings, in_params->sgt_data_buff);
in_params->xfer_scratch.const_buffer_size =
gsi_channel_info.const_buffer_size;
in_params->xfer_scratch.depcmd_low_addr =
@@ -344,6 +348,13 @@
d_port->out_request.num_bufs;
out_params->data_buff_base_addr_iova =
d_port->out_request.dma;
+ out_params->sgt_xfer_rings =
+ &d_port->out_request.sgt_trb_xfer_ring;
+ out_params->sgt_data_buff = &d_port->out_request.sgt_data_buff;
+ log_event_dbg("%s(): OUT: sgt_xfer_rings:%pK sgt_data_buff:%pK\n",
+ __func__, out_params->sgt_xfer_rings,
+ out_params->sgt_data_buff);
+
out_params->xfer_scratch.last_trb_addr_iova =
gsi_channel_info.last_trb_addr;
out_params->xfer_scratch.const_buffer_size =
@@ -497,10 +508,12 @@
gsi->d_port.in_channel_handle = -EINVAL;
gsi->d_port.out_channel_handle = -EINVAL;
- usb_gsi_ep_op(gsi->d_port.in_ep, NULL, GSI_EP_OP_FREE_TRBS);
+ usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
+ GSI_EP_OP_FREE_TRBS);
if (gsi->d_port.out_ep)
- usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS);
+ usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request,
+ GSI_EP_OP_FREE_TRBS);
/* free buffers allocated with each TRB */
gsi_free_trb_buffer(gsi);
@@ -1945,6 +1958,11 @@
ret = -ENOMEM;
goto fail1;
}
+
+ dma_get_sgtable(dev->parent,
+ &gsi->d_port.in_request.sgt_data_buff,
+ gsi->d_port.in_request.buf_base_addr,
+ gsi->d_port.in_request.dma, len_in);
}
if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) {
@@ -1964,6 +1982,11 @@
ret = -ENOMEM;
goto fail;
}
+
+ dma_get_sgtable(dev->parent,
+ &gsi->d_port.out_request.sgt_data_buff,
+ gsi->d_port.out_request.buf_base_addr,
+ gsi->d_port.out_request.dma, len_out);
}
log_event_dbg("finished allocating trb's buffer\n");
@@ -1994,6 +2017,7 @@
gsi->d_port.out_request.buf_base_addr,
gsi->d_port.out_request.dma);
gsi->d_port.out_request.buf_base_addr = NULL;
+ sg_free_table(&gsi->d_port.out_request.sgt_data_buff);
}
if (gsi->d_port.in_ep &&
@@ -2004,6 +2028,7 @@
gsi->d_port.in_request.buf_base_addr,
gsi->d_port.in_request.dma);
gsi->d_port.in_request.buf_base_addr = NULL;
+ sg_free_table(&gsi->d_port.in_request.sgt_data_buff);
}
}
diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c
index cb00ada..9625248 100644
--- a/drivers/usb/gadget/function/f_serial.c
+++ b/drivers/usb/gadget/function/f_serial.c
@@ -31,13 +31,43 @@
struct gserial port;
u8 data_id;
u8 port_num;
+ spinlock_t lock;
+
+ struct usb_ep *notify;
+ struct usb_request *notify_req;
+
+ u8 online;
+ u8 pending;
+ struct usb_cdc_line_coding port_line_coding;
+
+ /* SetControlLineState request */
+ u16 port_handshake_bits;
+#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
+#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
+
+ /* SerialState notification */
+ u16 serial_state;
+#define ACM_CTRL_OVERRUN (1 << 6)
+#define ACM_CTRL_PARITY (1 << 5)
+#define ACM_CTRL_FRAMING (1 << 4)
+#define ACM_CTRL_RI (1 << 3)
+#define ACM_CTRL_BRK (1 << 2)
+#define ACM_CTRL_DSR (1 << 1)
+#define ACM_CTRL_DCD (1 << 0)
};
+static inline struct f_gser *port_to_gser(struct gserial *p)
+{
+ return container_of(p, struct f_gser, port);
+}
+
static inline struct f_gser *func_to_gser(struct usb_function *f)
{
return container_of(f, struct f_gser, port.func);
}
+#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
+#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
/*-------------------------------------------------------------------------*/
/* interface descriptor: */
@@ -46,15 +76,55 @@
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
- .bNumEndpoints = 2,
+ .bNumEndpoints = 3,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
/* .iInterface = DYNAMIC */
};
+static struct usb_cdc_header_desc gser_header_desc = {
+ .bLength = sizeof(gser_header_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+ .bcdCDC = cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor
+gser_call_mgmt_descriptor = {
+ .bLength = sizeof(gser_call_mgmt_descriptor),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
+ .bmCapabilities = 0,
+ /* .bDataInterface = DYNAMIC */
+};
+
+static struct usb_cdc_acm_descriptor gser_descriptor = {
+ .bLength = sizeof(gser_descriptor),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
+ .bmCapabilities = USB_CDC_CAP_LINE,
+};
+
+static struct usb_cdc_union_desc gser_union_desc = {
+ .bLength = sizeof(gser_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
/* full speed support: */
+static struct usb_endpoint_descriptor gser_fs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
+};
+
static struct usb_endpoint_descriptor gser_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -71,12 +141,25 @@
static struct usb_descriptor_header *gser_fs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
+ (struct usb_descriptor_header *) &gser_header_desc,
+ (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &gser_descriptor,
+ (struct usb_descriptor_header *) &gser_union_desc,
+ (struct usb_descriptor_header *) &gser_fs_notify_desc,
(struct usb_descriptor_header *) &gser_fs_in_desc,
(struct usb_descriptor_header *) &gser_fs_out_desc,
NULL,
};
/* high speed support: */
+static struct usb_endpoint_descriptor gser_hs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+};
static struct usb_endpoint_descriptor gser_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -94,6 +177,11 @@
static struct usb_descriptor_header *gser_hs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
+ (struct usb_descriptor_header *) &gser_header_desc,
+ (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &gser_descriptor,
+ (struct usb_descriptor_header *) &gser_union_desc,
+ (struct usb_descriptor_header *) &gser_hs_notify_desc,
(struct usb_descriptor_header *) &gser_hs_in_desc,
(struct usb_descriptor_header *) &gser_hs_out_desc,
NULL,
@@ -118,8 +206,33 @@
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
+static struct usb_endpoint_descriptor gser_ss_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
+ .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_ss_ep_comp_descriptor gser_ss_notify_comp_desc = {
+ .bLength = sizeof(gser_ss_notify_comp_desc),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+ .wBytesPerInterval = cpu_to_le16(GS_NOTIFY_MAXPACKET),
+};
+
static struct usb_descriptor_header *gser_ss_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
+ (struct usb_descriptor_header *) &gser_header_desc,
+ (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &gser_descriptor,
+ (struct usb_descriptor_header *) &gser_union_desc,
+ (struct usb_descriptor_header *) &gser_ss_notify_desc,
+ (struct usb_descriptor_header *) &gser_ss_notify_comp_desc,
(struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &gser_ss_out_desc,
@@ -130,7 +243,7 @@
/* string descriptors: */
static struct usb_string gser_string_defs[] = {
- [0].s = "Generic Serial",
+ [0].s = "DUN over Serial",
{ } /* end of list */
};
@@ -145,13 +258,131 @@
};
/*-------------------------------------------------------------------------*/
+static void gser_complete_set_line_coding(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct f_gser *gser = ep->driver_data;
+ struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+ if (req->status != 0) {
+ dev_dbg(&cdev->gadget->dev, "gser ttyGS%d completion, err %d\n",
+ gser->port_num, req->status);
+ return;
+ }
+
+ /* normal completion */
+ if (req->actual != sizeof(gser->port_line_coding)) {
+ dev_dbg(&cdev->gadget->dev, "gser ttyGS%d short resp, len %d\n",
+ gser->port_num, req->actual);
+ usb_ep_set_halt(ep);
+ } else {
+ struct usb_cdc_line_coding *value = req->buf;
+
+ gser->port_line_coding = *value;
+ }
+}
+
+static int
+gser_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_gser *gser = func_to_gser(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+ /* SET_LINE_CODING ... just read and save what the host sends */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_SET_LINE_CODING:
+ if (w_length != sizeof(struct usb_cdc_line_coding))
+ goto invalid;
+
+ value = w_length;
+ cdev->gadget->ep0->driver_data = gser;
+ req->complete = gser_complete_set_line_coding;
+ break;
+
+ /* GET_LINE_CODING ... return what host sent, or initial value */
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_GET_LINE_CODING:
+ value = min_t(unsigned int, w_length,
+ sizeof(struct usb_cdc_line_coding));
+ memcpy(req->buf, &gser->port_line_coding, value);
+ break;
+
+ /* SET_CONTROL_LINE_STATE ... save what the host sent */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
+
+ value = 0;
+ gser->port_handshake_bits = w_value;
+ pr_debug("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE: DTR:%d RST:%d\n",
+ __func__, w_value & ACM_CTRL_DTR ? 1 : 0,
+ w_value & ACM_CTRL_RTS ? 1 : 0);
+
+ if (gser->port.notify_modem)
+ gser->port.notify_modem(&gser->port, 0, w_value);
+
+ break;
+
+ default:
+invalid:
+ dev_dbg(&cdev->gadget->dev,
+ "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ dev_dbg(&cdev->gadget->dev,
+ "gser ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
+ gser->port_num, ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "gser response on ttyGS%d, err %d\n",
+ gser->port_num, value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_gser *gser = func_to_gser(f);
struct usb_composite_dev *cdev = f->config->cdev;
+ int rc = 0;
/* we know alt == 0, so this is an activation or a reset */
+ if (gser->notify->driver_data) {
+ dev_dbg(&cdev->gadget->dev,
+ "reset generic ctl ttyGS%d\n", gser->port_num);
+ usb_ep_disable(gser->notify);
+ }
+
+ if (!gser->notify->desc) {
+ if (config_ep_by_speed(cdev->gadget, f, gser->notify)) {
+ gser->notify->desc = NULL;
+ return -EINVAL;
+ }
+ }
+
+ rc = usb_ep_enable(gser->notify);
+ if (rc) {
+ ERROR(cdev, "can't enable %s, result %d\n",
+ gser->notify->name, rc);
+ return rc;
+ }
+ gser->notify->driver_data = gser;
if (gser->port.in->enabled) {
dev_dbg(&cdev->gadget->dev,
@@ -169,7 +400,9 @@
}
}
gserial_connect(&gser->port, gser->port_num);
- return 0;
+ gser->online = 1;
+
+ return rc;
}
static void gser_disable(struct usb_function *f)
@@ -180,6 +413,178 @@
dev_dbg(&cdev->gadget->dev,
"generic ttyGS%d deactivated\n", gser->port_num);
gserial_disconnect(&gser->port);
+ usb_ep_disable(gser->notify);
+ gser->notify->driver_data = NULL;
+ gser->online = 0;
+}
+
+static int gser_notify(struct f_gser *gser, u8 type, u16 value,
+ void *data, unsigned int length)
+{
+ struct usb_ep *ep = gser->notify;
+ struct usb_request *req;
+ struct usb_cdc_notification *notify;
+ const unsigned int len = sizeof(*notify) + length;
+ void *buf;
+ int status;
+ struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+ req = gser->notify_req;
+ gser->notify_req = NULL;
+ gser->pending = false;
+
+ req->length = len;
+ notify = req->buf;
+ buf = notify + 1;
+
+ notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+ | USB_RECIP_INTERFACE;
+ notify->bNotificationType = type;
+ notify->wValue = cpu_to_le16(value);
+ notify->wIndex = cpu_to_le16(gser->data_id);
+ notify->wLength = cpu_to_le16(length);
+ memcpy(buf, data, length);
+
+ status = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (status < 0) {
+ ERROR(cdev, "gser ttyGS%d can't notify serial state, %d\n",
+ gser->port_num, status);
+ gser->notify_req = req;
+ }
+
+ return status;
+}
+
+static int gser_notify_serial_state(struct f_gser *gser)
+{
+ int status;
+ unsigned long flags;
+ struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+ spin_lock_irqsave(&gser->lock, flags);
+ if (gser->notify_req) {
+ DBG(cdev, "gser ttyGS%d serial state %04x\n",
+ gser->port_num, gser->serial_state);
+ status = gser_notify(gser, USB_CDC_NOTIFY_SERIAL_STATE,
+ 0, &gser->serial_state,
+ sizeof(gser->serial_state));
+ } else {
+ gser->pending = true;
+ status = 0;
+ }
+
+ spin_unlock_irqrestore(&gser->lock, flags);
+ return status;
+}
+
+static void gser_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_gser *gser = req->context;
+ u8 doit = false;
+ unsigned long flags;
+
+ /* on this call path we do NOT hold the port spinlock,
+ * which is why ACM needs its own spinlock
+ */
+
+ spin_lock_irqsave(&gser->lock, flags);
+ if (req->status != -ESHUTDOWN)
+ doit = gser->pending;
+
+ gser->notify_req = req;
+ spin_unlock_irqrestore(&gser->lock, flags);
+
+ if (doit && gser->online)
+ gser_notify_serial_state(gser);
+}
+
+static void gser_connect(struct gserial *port)
+{
+ struct f_gser *gser = port_to_gser(port);
+
+ gser->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
+ gser_notify_serial_state(gser);
+}
+
+static unsigned int gser_get_dtr(struct gserial *port)
+{
+ struct f_gser *gser = port_to_gser(port);
+
+ if (gser->port_handshake_bits & ACM_CTRL_DTR)
+ return 1;
+ else
+ return 0;
+}
+
+static unsigned int gser_get_rts(struct gserial *port)
+{
+ struct f_gser *gser = port_to_gser(port);
+
+ if (gser->port_handshake_bits & ACM_CTRL_RTS)
+ return 1;
+ else
+ return 0;
+}
+
+static unsigned int gser_send_carrier_detect(struct gserial *port,
+ unsigned int yes)
+{
+ u16 state;
+ struct f_gser *gser = port_to_gser(port);
+
+ state = gser->serial_state;
+ state &= ~ACM_CTRL_DCD;
+ if (yes)
+ state |= ACM_CTRL_DCD;
+
+ gser->serial_state = state;
+ return gser_notify_serial_state(gser);
+}
+
+static unsigned int gser_send_ring_indicator(struct gserial *port,
+ unsigned int yes)
+{
+ u16 state;
+ struct f_gser *gser = port_to_gser(port);
+
+ state = gser->serial_state;
+ state &= ~ACM_CTRL_RI;
+ if (yes)
+ state |= ACM_CTRL_RI;
+
+ gser->serial_state = state;
+ return gser_notify_serial_state(gser);
+}
+
+static void gser_disconnect(struct gserial *port)
+{
+ struct f_gser *gser = port_to_gser(port);
+
+ gser->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
+ gser_notify_serial_state(gser);
+}
+
+static int gser_send_break(struct gserial *port, int duration)
+{
+ u16 state;
+ struct f_gser *gser = port_to_gser(port);
+
+ state = gser->serial_state;
+ state &= ~ACM_CTRL_BRK;
+ if (duration)
+ state |= ACM_CTRL_BRK;
+
+ gser->serial_state = state;
+ return gser_notify_serial_state(gser);
+}
+
+static int gser_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
+{
+ struct f_gser *gser = port_to_gser(port);
+
+ gser->serial_state = ctrl_bits;
+
+ return gser_notify_serial_state(gser);
}
/*-------------------------------------------------------------------------*/
@@ -225,6 +630,21 @@
goto fail;
gser->port.out = ep;
+ ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc);
+ if (!ep)
+ goto fail;
+ gser->notify = ep;
+ ep->driver_data = cdev; /* claim */
+ /* allocate notification */
+ gser->notify_req = gs_alloc_req(ep,
+ sizeof(struct usb_cdc_notification) + 2,
+ GFP_KERNEL);
+ if (!gser->notify_req)
+ goto fail;
+
+ gser->notify_req->complete = gser_notify_complete;
+ gser->notify_req->context = gser;
+
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
@@ -235,6 +655,15 @@
gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ gser_hs_notify_desc.bEndpointAddress =
+ gser_fs_notify_desc.bEndpointAddress;
+ }
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ gser_ss_notify_desc.bEndpointAddress =
+ gser_fs_notify_desc.bEndpointAddress;
+ }
+
status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
gser_ss_function, NULL);
if (status)
@@ -247,6 +676,18 @@
return 0;
fail:
+ if (gser->notify_req)
+ gs_free_req(gser->notify, gser->notify_req);
+
+ /* we might as well release our claims on endpoints */
+ if (gser->notify)
+ gser->notify->driver_data = NULL;
+ /* we might as well release our claims on endpoints */
+ if (gser->port.out)
+ gser->port.out->driver_data = NULL;
+ if (gser->port.in)
+ gser->port.in->driver_data = NULL;
+
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@@ -327,7 +768,10 @@
static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_gser *gser = func_to_gser(f);
+
usb_free_all_descriptors(f);
+ gs_free_req(gser->notify, gser->notify_req);
}
static struct usb_function *gser_alloc(struct usb_function_instance *fi)
@@ -342,6 +786,7 @@
opts = container_of(fi, struct f_serial_opts, func_inst);
+ spin_lock_init(&gser->lock);
gser->port_num = opts->port_num;
gser->port.func.name = "gser";
@@ -351,6 +796,15 @@
gser->port.func.set_alt = gser_set_alt;
gser->port.func.disable = gser_disable;
gser->port.func.free_func = gser_free;
+ gser->port.func.setup = gser_setup;
+ gser->port.connect = gser_connect;
+ gser->port.get_dtr = gser_get_dtr;
+ gser->port.get_rts = gser_get_rts;
+ gser->port.send_carrier_detect = gser_send_carrier_detect;
+ gser->port.send_ring_indicator = gser_send_ring_indicator;
+ gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
+ gser->port.disconnect = gser_disconnect;
+ gser->port.send_break = gser_send_break;
return &gser->port.func;
}
diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h
index c20210c..f367dc5 100644
--- a/drivers/usb/gadget/function/u_serial.h
+++ b/drivers/usb/gadget/function/u_serial.h
@@ -45,11 +45,23 @@
/* REVISIT avoid this CDC-ACM support harder ... */
struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */
+ u16 serial_state;
+
+ /* control signal callbacks*/
+ unsigned int (*get_dtr)(struct gserial *p);
+ unsigned int (*get_rts)(struct gserial *p);
/* notification callbacks */
void (*connect)(struct gserial *p);
void (*disconnect)(struct gserial *p);
int (*send_break)(struct gserial *p, int duration);
+ unsigned int (*send_carrier_detect)(struct gserial *p,
+ unsigned int yes);
+ unsigned int (*send_ring_indicator)(struct gserial *p,
+ unsigned int yes);
+ int (*send_modem_ctrl_bits)(struct gserial *p, int ctrl_bits);
+ /* notification changes to modem */
+ void (*notify_modem)(void *gser, u8 portno, int ctrl_bits);
};
/* utilities to allocate/free request and buffer */
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index cce17e0..cc1a0ea 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, 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
@@ -26,6 +26,7 @@
#include <linux/regulator/machine.h>
#include <linux/usb/phy.h>
#include <linux/reset.h>
+#include <linux/nvmem-consumer.h>
#include <linux/debugfs.h>
#include <linux/hrtimer.h>
@@ -146,8 +147,65 @@
u8 tune[5];
struct hrtimer timer;
+ int soc_min_rev;
};
+#ifdef CONFIG_NVMEM
+/* Parse qfprom data for deciding on errata work-arounds */
+static long qfprom_read(struct device *dev, const char *name)
+{
+ struct nvmem_cell *cell;
+ ssize_t len = 0;
+ u32 *buf, val = 0;
+ long err = 0;
+
+ cell = nvmem_cell_get(dev, name);
+ if (IS_ERR(cell)) {
+ err = PTR_ERR(cell);
+ dev_err(dev, "failed opening nvmem cell err : %ld\n", err);
+ /* If entry does not exist, then that is not an error */
+ if (err == -ENOENT)
+ err = 0;
+ return err;
+ }
+
+ buf = (u32 *)nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf) || !len) {
+ dev_err(dev, "Failed reading nvmem cell, err: %u, bytes fetched: %zd\n",
+ *buf, len);
+ if (!IS_ERR(buf)) {
+ kfree(buf);
+ err = -EINVAL;
+ } else {
+ err = PTR_ERR(buf);
+ }
+ } else {
+ val = *buf;
+ kfree(buf);
+ }
+
+ nvmem_cell_put(cell);
+ return err ? err : (long) val;
+}
+
+/* Reads the SoC version */
+static int qusb_phy_get_socrev(struct device *dev, struct qusb_phy *qphy)
+{
+ qphy->soc_min_rev = qfprom_read(dev, "minor_rev");
+ if (qphy->soc_min_rev < 0)
+ dev_err(dev, "failed getting soc_min_rev, err : %d\n",
+ qphy->soc_min_rev);
+
+ return qphy->soc_min_rev;
+};
+#else
+/* Reads the SoC version */
+static int qusb_phy_get_socrev(struct device *dev, struct qusb_phy *qphy)
+{
+ return 0;
+}
+#endif
+
static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
{
dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n",
@@ -1125,6 +1183,11 @@
return PTR_ERR(qphy->vdda18);
}
+ ret = qusb_phy_get_socrev(&pdev->dev, qphy);
+ if (ret == -EPROBE_DEFER) {
+ dev_err(&pdev->dev, "SoC version rd: fail: defer for now\n");
+ return ret;
+ }
qphy->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(qphy->pinctrl)) {
ret = PTR_ERR(qphy->pinctrl);
@@ -1159,7 +1222,14 @@
qphy->phy.type = USB_PHY_TYPE_USB2;
qphy->phy.notify_connect = qusb_phy_notify_connect;
qphy->phy.notify_disconnect = qusb_phy_notify_disconnect;
- qphy->phy.disable_chirp = qusb_phy_disable_chirp;
+
+ /*
+ * qusb_phy_disable_chirp is not required if soc version is
+ * mentioned and is not base version.
+ */
+ if (qphy->soc_min_rev == 0)
+ qphy->phy.disable_chirp = qusb_phy_disable_chirp;
+
qphy->phy.start_port_reset = qusb_phy_enable_ext_pulldown;
ret = usb_add_phy_dev(&qphy->phy);
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 0d442e3..47f5ba6 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -199,7 +199,7 @@
extern void clockevents_resume(void);
# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-# ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
+# if defined(CONFIG_ARCH_HAS_TICK_BROADCAST) && defined(CONFIG_SMP)
extern void tick_broadcast(const struct cpumask *mask);
# else
# define tick_broadcast NULL
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 972dabc..3fda92f 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -84,6 +84,8 @@
* @db_reg_phs_addr_lsb: IPA channel doorbell register's physical address LSB
* @mapped_db_reg_phs_addr_lsb: doorbell LSB IOVA address mapped with IOMMU
* @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB
+ * @sgt_trb_xfer_ring: USB TRB ring related sgtable entries
+ * @sgt_data_buff: Data buffer related sgtable entries
*/
struct usb_gsi_request {
void *buf_base_addr;
@@ -93,6 +95,8 @@
u32 db_reg_phs_addr_lsb;
dma_addr_t mapped_db_reg_phs_addr_lsb;
u32 db_reg_phs_addr_msb;
+ struct sg_table sgt_trb_xfer_ring;
+ struct sg_table sgt_data_buff;
};
/*
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 5edfe66..64ec233 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -263,6 +263,7 @@
* this case. -DaveM
*/
pr_debug("end of fragment not rounded to 8 bytes.\n");
+ inet_frag_kill(&fq->q, &nf_frags);
return -EPROTO;
}
if (end > fq->q.len) {
diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c
index 8faf7a7..50dd516 100644
--- a/net/rmnet_data/rmnet_data_handlers.c
+++ b/net/rmnet_data/rmnet_data_handlers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, 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
@@ -453,6 +453,13 @@
}
ep = &config->muxed_ep[mux_id];
+ if (!ep->refcount) {
+ LOGD("Packet on %s:%d; has no logical endpoint config",
+ skb->dev->name, mux_id);
+
+ rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP);
+ return RX_HANDLER_CONSUMED;
+ }
skb->dev = ep->egress_dev;
diff --git a/net/rmnet_data/rmnet_data_stats.h b/net/rmnet_data/rmnet_data_stats.h
index 366e486..75ed434 100644
--- a/net/rmnet_data/rmnet_data_stats.h
+++ b/net/rmnet_data/rmnet_data_stats.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 2018 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,6 +39,7 @@
RMNET_STATS_SKBFREE_DEAGG_DATA_LEN_0,
RMNET_STATS_SKBFREE_INGRESS_BAD_MAP_CKSUM,
RMNET_STATS_SKBFREE_MAPC_UNSUPPORTED,
+ RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP,
RMNET_STATS_SKBFREE_MAX
};
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index ff9887f..7fe91b1 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -54,7 +54,8 @@
country AR:
(2402 - 2482 @ 40), (36)
- (5170 - 5330 @ 160), (23)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (36), AUTO-BW
(5490 - 5590 @ 80), (36)
(5650 - 5730 @ 80), (36)
(5735 - 5835 @ 80), (36)
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 7712e2b..4783648 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -122,7 +122,7 @@
case USB_SPEED_SUPER:
case USB_SPEED_SUPER_PLUS:
if (get_endpoint(alts, 0)->bInterval >= 1 &&
- get_endpoint(alts, 0)->bInterval <= 4)
+ get_endpoint(alts, 0)->bInterval <= 16)
return get_endpoint(alts, 0)->bInterval - 1;
break;
default: