Merge "cpufreq: schedutil: Avoid indented labels" into msm-4.9
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 53e4295..fe53218 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -73,9 +73,6 @@
AMBA markee):
- "arm,coresight-replicator"
- "qcom,coresight-csr"
- - "arm,coresight-cti"
- - "qcom,coresight-tpda"
- - "qcom,coresight-tpdm"
- "qcom,coresight-remote-etm"
- "qcom,coresight-hwevent"
- "qcom,coresight-dummy"
@@ -264,7 +261,7 @@
};
tpda_mss: tpda@7043000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "qcom,coresight-tpda", "arm,primecell";
reg = <0x7043000 0x1000>;
reg-names = "tpda-base";
@@ -274,9 +271,8 @@
qcom,dsb-elem-size = <0 32>;
qcom,cmb-elem-size = <0 32>;
- clocks = <&clock_gcc clk_qdss_clk>,
- <&clock_gcc clk_qdss_a_clk>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop clk_qdss_clk>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -345,15 +341,14 @@
};
tpdm_mss: tpdm@7042000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "qcom,coresight-tpdm", "arm,primecell";
reg = <0x7042000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-mss";
- clocks = <&clock_gcc clk_qdss_clk>,
- <&clock_gcc clk_qdss_a_clk>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop qdss_clk>;
+ clock-names = "apb_pclk";
port{
tpdm_mss_out_tpda_mss: endpoint {
@@ -364,15 +359,14 @@
4. CTIs
cti0: cti@6010000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,coresight-cti", "arm,primecell";
reg = <0x6010000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti0";
- clocks = <&clock_gcc clk_qdss_clk>,
- <&clock_gcc clk_qdss_a_clk>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop qdss_clk>;
+ clock-names = "apb_pclk";
};
[1]. There is currently two version of STM: STM32 and STM500. Both
diff --git a/Documentation/devicetree/bindings/arm/msm/imem.txt b/Documentation/devicetree/bindings/arm/msm/imem.txt
index d1f8ce1..eaa7146b 100644
--- a/Documentation/devicetree/bindings/arm/msm/imem.txt
+++ b/Documentation/devicetree/bindings/arm/msm/imem.txt
@@ -57,6 +57,11 @@
-compatible: "qcom,msm-imem-emergency_download_mode"
-reg: start address and size of emergency_download_mode region in imem
+Kaslr Offset:
+------------------------
+-compatible: "qcom,msm-imem-kaslr_offset"
+-reg: start address and size of kaslr_offset region in imem
+
USB Diag Cookies:
-----------------
Memory region used to store USB PID and serial numbers to be used by
@@ -95,6 +100,12 @@
reg = <0x6b0 32>;
};
+ kaslr_offset@6d0 {
+ compatible = "qcom,msm-imem-kaslr_offset";
+ reg = <0x6d0 12>;
+ };
+
+
pil@94c {
compatible = "qcom,msm-imem-pil";
reg = <0x94c 200>;
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index baae281..bf93a2a 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -110,6 +110,9 @@
- MDMCALIFORNIUM
compatible = "qcom,mdmcalifornium"
+- SDXPOORWILLS
+ compatible = "qcom,sdxpoorwills"
+
- VPIPA
compatible = "qcom,msmvpipa"
@@ -302,3 +305,4 @@
compatible = "qcom,mdmcalifornium-mtp"
compatible = "qcom,apq8009-cdp"
compatible = "qcom,apq8009-mtp"
+compatible = "qcom,sdxpoorwills-rumi"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
new file mode 100644
index 0000000..02dab4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
@@ -0,0 +1,33 @@
+* RPM Stats
+
+RPM maintains a counter of the number of times the SoC entered a deeper sleep
+mode involving lowering or powering down the backbone rails - Cx and Mx and
+the oscillator clock, XO.
+
+PROPERTIES
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should be "qcom,rpm-stats".
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: The address on the RPM RAM from where the stats are read
+ should be provided as "phys_addr_base". The offset from
+ which the stats are available should be provided as
+ "offset_addr".
+
+- reg-names:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Provides labels for the reg property.
+
+EXAMPLE:
+
+ qcom,rpm-stats@c000000 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xC000000 0x1000>, <0x3F0000 0x4>;
+ reg-names = "phys_addr_base", "offset_addr";
+ };
diff --git a/Documentation/devicetree/bindings/arm/msm/spss_utils.txt b/Documentation/devicetree/bindings/arm/msm/spss_utils.txt
new file mode 100644
index 0000000..d325574
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spss_utils.txt
@@ -0,0 +1,35 @@
+Qualcomm Technologies, Inc. Secure Processor SubSystem Utilities (spss_utils)
+
+The Secure Processor SubSystem (SPSS) is a dedicated subsystem for security.
+It has its own CPU, memories, and cryptographic engine.
+It shall provide cryptographic services to other subsystems.
+The SPSS firmware is loaded by PIL driver.
+The communication with SPSS is done via spcom driver, using glink.
+
+The spss_utils driver selects the SPSS firmware file,
+according to a dedicated fuse and the platform HW version.
+
+Required properties:
+-compatible : should be "qcom,spss_utils"
+-qcom,spss-fuse1-addr: fuse1 register physical address
+-qcom,spss-fuse1-bit: fuse1 relevant bit
+-qcom,spss-fuse2-addr: fuse2 register physical address
+-qcom,spss-fuse2-bit: fuse2 relevant bit
+-qcom,spss-dev-firmware-name: dev firmware file name
+-qcom,spss-test-firmware-name: test firmware file name
+-qcom,spss-prod-firmware-name: production firmware file name
+-qcom,spss-debug-reg-addr: debug register physical address
+
+Example:
+ qcom,spss_utils {
+ compatible = "qcom,spss-utils";
+
+ qcom,spss-fuse1-addr = <0x007841c4>;
+ qcom,spss-fuse1-bit = <27>;
+ qcom,spss-fuse2-addr = <0x007841c4>;
+ qcom,spss-fuse2-bit = <26>;
+ qcom,spss-dev-firmware-name = "spss1d"; /* 8 chars max */
+ qcom,spss-test-firmware-name = "spss1t"; /* 8 chars max */
+ qcom,spss-prod-firmware-name = "spss1p"; /* 8 chars max */
+ qcom,spss-debug-reg-addr = <0x01886020>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt b/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt
new file mode 100644
index 0000000..231b8a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,aop-qmp.txt
@@ -0,0 +1,17 @@
+Qualcomm Technologies, Inc. Always On Processor Clock controller Binding
+------------------------------------------------------------------------
+
+Required properties :
+- compatible : must be "qcom,aop-qmp-clk"
+- #clock-cells : must contain 1
+- mboxes : list of QMP mailbox phandle and channel identifier tuples.
+- mbox-names: List of identifier strings for each mailbox channel.
+ Must contain "qdss_clk".
+
+Example :
+ clock_qdss: qcom,aopclk {
+ compatible = "qcom,aop-qmp-clk";
+ #clock-cells = <1>;
+ mboxes = <&qmp_aop 0>;
+ mbox-names = "qdss_clk";
+ };
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
index c6626d1..3ad0986 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
@@ -6,8 +6,9 @@
DSI Controller:
Required properties:
- compatible: Should be "qcom,dsi-ctrl-hw-v<version>". Supported
- versions include 1.4 and 2.0.
- eg: qcom,dsi-ctrl-hw-v1.4, qcom,dsi-ctrl-hw-v2.0
+ versions include 1.4, 2.0 and 2.2.
+ eg: qcom,dsi-ctrl-hw-v1.4, qcom,dsi-ctrl-hw-v2.0,
+ qcom,dsi-ctrl-hw-v2.2
And for dsi phy driver:
qcom,dsi-phy-v0.0-hpm, qcom,dsi-phy-v0.0-lpm,
qcom,dsi-phy-v1.0, qcom,dsi-phy-v2.0,
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 6d72e8b..bdc0eba 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -10,6 +10,10 @@
of macroblocks per second. The load is a reflection of hardware capability
rather than a performance guarantee. Performance is guaranteed only up to
advertised capability of the chipset.
+- qcom,max-hq-mbs-per-frame : Max no of mbs per frame beyond which
+ "High Quality" encoding is not supported.
+- qcom,max-hq-frames-per-sec : Max no of frames per second beyond which
+ "High Quality" encoding is not supported.
Optional properties:
- reg : offset and length of the register set for the device.
@@ -157,7 +161,6 @@
Example:
-
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
@@ -182,6 +185,8 @@
qcom,use_dynamic_bw_update;
qcom,fw-bias = <0xe000000>;
qcom,allowed-clock-rates = <200000000 300000000 400000000>;
+ qcom,max-hq-mbs-per-frame = <8160>;
+ qcom,max-hq-frames-per-sec = <60>;
msm_vidc_cb1: msm_vidc_cb1 {
compatible = "qcom,msm-vidc,context-bank";
label = "venus_ns";
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index fd7e140..da9a632 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -68,6 +68,15 @@
command-queueing mode or legacy respectively.
- qcom,core_3_0v_support: an optional property that is used to fake
3.0V support for SDIO devices.
+ - qcom,scaling-lower-bus-speed-mode: specifies the lower bus speed mode to be used
+ during clock scaling. If this property is not
+ defined, then it falls back to the default HS
+ bus speed mode to maintain backward compatibility.
+ - qcom,sdr104-wa: On Certain chipsets, SDR104 mode might be unstable causing CRC errors
+ on the interface. So there is a workaround implemented to skip printing
+ register dumps on CRC errors and also downgrade bus speed mode to
+ SDR50/DDR50 in case of continuous CRC errors. Set this flag to enable
+ this workaround.
In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage).
- qcom,<supply>-always-on - specifies whether supply should be kept "on" always.
@@ -130,6 +139,8 @@
qcom,large-address-bus;
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ qcom,scaling-lower-bus-speed-mode = "DDR52";
+
gpios = <&msmgpio 40 0>, /* CLK */
<&msmgpio 39 0>, /* CMD */
<&msmgpio 38 0>, /* DATA0 */
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdxpoorwill-pinctrl b/Documentation/devicetree/bindings/pinctrl/qcom,sdxpoorwill-pinctrl
new file mode 100644
index 0000000..9a69084
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdxpoorwill-pinctrl
@@ -0,0 +1,186 @@
+Qualcomm Technologies, Inc. SDXPOORWILLS TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+SDXPOORWILLS platform.
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be "qcom,sdxpoorwills-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-gpio149
+ Supports mux, bias and drive-strength
+
+ sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd,
+ sdc2_data sdc1_rclk
+ Supports bias and drive-strength
+
+- 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:
+
+ blsp_uart1, blsp_spi1, blsp_i2c1, blsp_uim1, atest_tsens,
+ bimc_dte1, dac_calib0, blsp_spi8, blsp_uart8, blsp_uim8,
+ qdss_cti_trig_out_b, bimc_dte0, dac_calib1, qdss_cti_trig_in_b,
+ dac_calib2, atest_tsens2, atest_usb1, blsp_spi10, blsp_uart10,
+ blsp_uim10, atest_bbrx1, atest_usb13, atest_bbrx0, atest_usb12,
+ mdp_vsync, edp_lcd, blsp_i2c10, atest_gpsadc1, atest_usb11,
+ atest_gpsadc0, edp_hot, atest_usb10, m_voc, dac_gpio, atest_char,
+ cam_mclk, pll_bypassnl, qdss_stm7, blsp_i2c8, qdss_tracedata_b,
+ pll_reset, qdss_stm6, qdss_stm5, qdss_stm4, atest_usb2, cci_i2c,
+ qdss_stm3, dac_calib3, atest_usb23, atest_char3, dac_calib4,
+ qdss_stm2, atest_usb22, atest_char2, qdss_stm1, dac_calib5,
+ atest_usb21, atest_char1, dbg_out, qdss_stm0, dac_calib6,
+ atest_usb20, atest_char0, dac_calib10, qdss_stm10,
+ qdss_cti_trig_in_a, cci_timer4, blsp_spi6, blsp_uart6, blsp_uim6,
+ blsp2_spi, qdss_stm9, qdss_cti_trig_out_a, dac_calib11,
+ qdss_stm8, cci_timer0, qdss_stm13, dac_calib7, cci_timer1,
+ qdss_stm12, dac_calib8, cci_timer2, blsp1_spi, qdss_stm11,
+ dac_calib9, cci_timer3, cci_async, dac_calib12, blsp_i2c6,
+ qdss_tracectl_a, dac_calib13, qdss_traceclk_a, dac_calib14,
+ dac_calib15, hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem,
+ dac_calib17, hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto,
+ dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pci_e0,
+ dac_calib22, dac_calib23, dac_calib24, tsif1_sync, dac_calib25,
+ sd_write, tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2,
+ qdss_cti, blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3,
+ uim3, blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi, blsp_i2c9,
+ blsp_spi7, blsp_uart7, blsp_uim7, qdss_tracedata_a, blsp_i2c7,
+ qua_mi2s, gcc_gp1_clk_a, ssc_irq, uim4, blsp_spi11, blsp_uart11,
+ blsp_uim11, gcc_gp2_clk_a, gcc_gp3_clk_a, blsp_i2c11, cri_trng0,
+ cri_trng1, cri_trng, qdss_stm18, pri_mi2s, qdss_stm17, blsp_spi4,
+ blsp_uart4, blsp_uim4, qdss_stm16, qdss_stm15, blsp_i2c4,
+ qdss_stm14, dac_calib26, spkr_i2s, audio_ref, lpass_slimbus,
+ isense_dbg, tsense_pwm1, tsense_pwm2, btfm_slimbus, ter_mi2s,
+ qdss_stm22, qdss_stm21, qdss_stm20, qdss_stm19, gcc_gp1_clk_b,
+ sec_mi2s, blsp_spi5, blsp_uart5, blsp_uim5, gcc_gp2_clk_b,
+ gcc_gp3_clk_b, blsp_i2c5, blsp_spi12, blsp_uart12, blsp_uim12,
+ qdss_stm25, qdss_stm31, blsp_i2c12, qdss_stm30, qdss_stm29,
+ tsif1_clk, qdss_stm28, tsif1_en, tsif1_data, sdc4_cmd, qdss_stm27,
+ qdss_traceclk_b, tsif2_error, sdc43, vfr_1, qdss_stm26, tsif2_clk,
+ sdc4_clk, qdss_stm24, tsif2_en, sdc42, qdss_stm23, qdss_tracectl_b,
+ sd_card, tsif2_data, sdc41, tsif2_sync, sdc40, mdp_vsync_p_b,
+ ldo_en, mdp_vsync_s_b, ldo_update, blsp11_uart_tx_b, blsp11_uart_rx_b,
+ blsp11_i2c_sda_b, prng_rosc, blsp11_i2c_scl_b, uim2, uim1, uim_batt,
+ pci_e2, pa_indicator, adsp_ext, ddr_bist, qdss_tracedata_11,
+ qdss_tracedata_12, modem_tsync, nav_dr, nav_pps, pci_e1, gsm_tx,
+ qspi_cs, ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3,
+ gpio
+
+- 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@03900000 {
+ compatible = "qcom,sdxpoorwills-pinctrl";
+ reg = <0x03900000 0x300000>;
+ interrupts = <0 212 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
index 92ef23c..5529e308 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
@@ -22,7 +22,8 @@
Definition: String which indicates the charging mode. Can be one of the
following:
Standalone/Parallel Master - "qcom,smb138x-charger"
- Parallel Slave - "qcom,smb138x-parallel-slave"
+ smb138x Parallel Slave - "qcom,smb138x-parallel-slave"
+ smb1355 Parallel Slave - "qcom,smb1355-parallel-slave",
- qcom,pmic-revid
Usage: required
@@ -35,7 +36,8 @@
Usage: optional
Value type: <u32>
Definition: Specifies parallel charging mode. If not specified, MID-MID
- option is selected by default.
+ option is selected by default. Note that smb1355 can only
+ run in MID-MID configuration.
- qcom,suspend-input
Usage: optional
@@ -125,7 +127,7 @@
=======
smb138x_charger: qcom,smb138x-charger {
- compatible = "qcom,qpnp-smb138x-charger";
+ compatible = "qcom,smb138x-charger";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/prng/msm-rng.txt b/Documentation/devicetree/bindings/prng/msm-rng.txt
new file mode 100644
index 0000000..917c2fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/prng/msm-rng.txt
@@ -0,0 +1,18 @@
+* RNG (Random Number Generator)
+
+Required properties:
+- compatible : Should be "qcom,msm-rng"
+- reg : Offset and length of the register set for the device
+
+Optional property:
+- qcom,msm-rng-iface-clk : If the device uses iface-clk.
+- qcom,no-qrng-config : Flag to decide whether the driver do the hardware configuration or not.
+
+Example:
+
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ qcom,msm-rng-iface-clk;
+ qcom,no-qrng-config;
+ };
diff --git a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
index e53b691..04b624b 100644
--- a/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qcom,msm-geni-uart.txt
@@ -16,6 +16,10 @@
Should be "active" and "sleep" for the pin confuguration when core is active
or when entering sleep state.
+Optional properties:
+- qcom,bus-mas: contains the bus master id needed to put in bus bandwidth votes
+ for inter-connect buses.
+
Example:
qupv3_uart11: qcom,qup_uart@0xa88000 {
compatible = "qcom,msm-geni-uart";
@@ -29,4 +33,5 @@
pinctrl-0 = <&qup_1_uart_3_active>;
pinctrl-1 = <&qup_1_uart_3_sleep>;
interrupts = <0 355 0>;
+ qcom,bus-mas = <MASTER_BLSP_2>;
};
diff --git a/Documentation/devicetree/bindings/soc/qcom/dcc.txt b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
index 0fd4e15..8a9761c 100644
--- a/Documentation/devicetree/bindings/soc/qcom/dcc.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
@@ -14,6 +14,11 @@
of the component.
- reg-names : names corresponding to each reg property value.
+ dcc-base: Base address for DCC configuration reg
+ dcc-ram-base: Start of HLOS address space in SRAM
+ dcc-xpu-base: Base address for XPU configuration reg
+
+- dcc-ram-offset: Address offset from the start of the SRAM address space.
Optional properties:
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
index 080d4da..8bead0d 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-lmh-dcvs.txt
@@ -25,12 +25,18 @@
interrupt generated by the LMH DCVSh hardware. LMH
DCVSh hardware will generate this interrupt whenever
it makes a new cpu DCVS decision.
+- qcom,affinity:
+ Usage: Required
+ Value type: <u32>
+ Definition: Should specify the cluster affinity this hardware
+ corresponds to.
Example:
lmh_dcvs0: qcom,limits-dcvs@0 {
compatible = "qcom,msm-hw-limits";
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,affinity = <0>;
};
CPU0: cpu@0 {
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
index 1065456..3e59c43 100644
--- a/Documentation/devicetree/bindings/thermal/tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -21,34 +21,25 @@
The compatible property is used to identify the respective controller to use
for the corresponding SoC.
- reg : offset and length of the TSENS registers with associated property in reg-names
- as "tsens_physical" for TSENS TM physical address region.
+ as "tsens_srot_physical" for TSENS SROT physical address region. TSENS TM
+ physical address region as "tsens_tm_physical".
- reg-names : resource names used for the physical address of the TSENS
- registers. Should be "tsens_physical" for physical address of the TSENS.
+ registers. Should be "tsens_srot_physical" for physical address of the TSENS
+ SROT region and "tsens_tm_physical" for physical address of the TM region.
- interrupts : TSENS interrupt to notify Upper/Lower and Critical temperature threshold.
- interrupt-names: Should be "tsens-upper-lower" for temperature threshold.
Add "tsens-critical" for Critical temperature threshold notification
in addition to "tsens-upper-lower" for 8996 TSENS since
8996 supports Upper/Lower and Critical temperature threshold.
-- qcom,sensors : Total number of available Temperature sensors for TSENS.
-
-Optional properties:
-- qcom,sensor-id : If the flag is present map the TSENS sensors based on the
- remote sensors that are enabled in HW. Ensure the mapping is not
- more than the number of supported sensors.
-- qcom,client-id : If the flag is present use it to identify the SW ID mapping
- used to associate it with the controller and the physical sensor
- mapping within the controller. The physical sensor mapping within
- each controller is done using the qcom,sensor-id property. If the
- property is not present the SW ID mapping with default from 0 to
- total number of supported sensors with each controller instance.
Example:
tsens@fc4a8000 {
compatible = "qcom,msm-tsens";
- reg = <0xfc4a8000 0x2000>;,
- reg-names = "tsens_physical";
+ reg = <0xfc4a8000 0x10>,
+ <0xfc4b8000 0x1ff>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical";
interrupts = <0 184 0>;
interrupt-names = "tsens-upper-lower";
- qcom,sensors = <11>;
};
diff --git a/Documentation/devicetree/bindings/uio/msm_sharedmem.txt b/Documentation/devicetree/bindings/uio/msm_sharedmem.txt
new file mode 100644
index 0000000..749c6e85
--- /dev/null
+++ b/Documentation/devicetree/bindings/uio/msm_sharedmem.txt
@@ -0,0 +1,18 @@
+msm_sharedmem provides the shared memory addresses for various clients in user-space
+
+Required properties:
+- compatible: Must be "qcom,sharedmem-uio"
+- reg : The address and size of the shared memory. The address/sizes may vary.
+ A reg address of Zero indicates that the shared memory is dynamically
+ allocated using dma_alloc_coherent. A non zero reg address is used
+ directly.
+- reg-names : Indicates various client-names.
+- qcom,client-id : The client id for the QMI clients.
+
+Example:
+ qcom,msm_sharedmem@0dc80000 {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x0dc80000 0x00180000>,
+ reg-names = "rmtfs";
+ qcom,client-id = <0x00000001>;
+ };
diff --git a/Makefile b/Makefile
index 51b7f2f..7040118 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 22
+SUBLEVEL = 24
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b174261..d04e168 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -550,7 +550,7 @@
config ARCH_QCOM
bool "Qualcomm MSM (non-multiplatform)"
- select ARCH_REQUIRE_GPIOLIB
+ select GPIOLIB
select CPU_V7
select AUTO_ZRELADDR
select HAVE_SMP
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 14422e5..7eb0c7f 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -1,4 +1,5 @@
+dtb-$(CONFIG_ARCH_SDXPOORWILLS) += sdxpoorwills-rumi.dtb
ifeq ($(CONFIG_ARM64),y)
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
new file mode 100644
index 0000000..ac02429
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -0,0 +1,35 @@
+/* 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.
+ */
+
+&soc {
+ tlmm: pinctrl@3900000 {
+ compatible = "qcom,sdxpoorwills-pinctrl";
+ reg = <0x3900000 0x300000>;
+ interrupts = <0 212 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ uart2_console_active: uart2_console_active {
+ mux {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ };
+ config {
+ pins = "gpio4", "gpio5";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts
new file mode 100644
index 0000000..967e71f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-rumi.dts
@@ -0,0 +1,29 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+
+#include "sdxpoorwills.dtsi"
+#include "sdxpoorwills-pinctrl.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS RUMI";
+ compatible = "qcom,sdxpoorwills-rumi",
+ "qcom,sdxpoorwills", "qcom,rumi";
+ qcom,board-id = <15 0>;
+};
+
+&blsp1_uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_console_active>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
new file mode 100644
index 0000000..0afa5a8
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -0,0 +1,157 @@
+/* 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 "skeleton.dtsi"
+#include <dt-bindings/clock/qcom,gcc-sdxpoorwills.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDX POORWILLS";
+ compatible = "qcom,sdxpoorwills";
+ qcom,msm-id = <334 0x0>;
+ interrupt-parent = <&intc>;
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ peripheral2_mem: peripheral2_region@8fd00000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0x8fd00000 0x300000>;
+ label = "peripheral2_mem";
+ };
+ };
+
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ CPU0: cpu@0 {
+ device-type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x0>;
+ };
+ };
+
+ soc: soc { };
+};
+
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ intc: interrupt-controller@17800000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x17800000 0x1000>,
+ <0x17802000 0x1000>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 13 0xf08>,
+ <1 12 0xf08>,
+ <1 10 0xf08>,
+ <1 11 0xf08>;
+ clock-frequency = <19200000>;
+ };
+
+ timer@17820000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x17820000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@17821000 {
+ frame-number = <0>;
+ interrupts = <0 7 0x4>,
+ <0 6 0x4>;
+ reg = <0x17821000 0x1000>,
+ <0x17822000 0x1000>;
+ };
+
+ frame@17823000 {
+ frame-number = <1>;
+ interrupts = <0 8 0x4>;
+ reg = <0x17823000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17824000 {
+ frame-number = <2>;
+ interrupts = <0 9 0x4>;
+ reg = <0x17824000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17825000 {
+ frame-number = <3>;
+ interrupts = <0 10 0x4>;
+ reg = <0x17825000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17826000 {
+ frame-number = <4>;
+ interrupts = <0 11 0x4>;
+ reg = <0x17826000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17827000 {
+ frame-number = <5>;
+ interrupts = <0 12 0x4>;
+ reg = <0x17827000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17828000 {
+ frame-number = <6>;
+ interrupts = <0 13 0x4>;
+ reg = <0x17828000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17829000 {
+ frame-number = <7>;
+ interrupts = <0 14 0x4>;
+ reg = <0x17829000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ clock_gcc: qcom,gcc@100000 {
+ compatible = "qcom,dummycc";
+ clock-output-names = "gcc_clocks";
+ #clock-cells = <1>;
+ };
+
+ clock_cpu: qcom,clock-a7@17810008 {
+ compatible = "qcom,dummycc";
+ clock-output-names = "cpu_clocks";
+ #clock-cells = <1>;
+ };
+
+ blsp1_uart2: serial@831000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x831000 0x200>;
+ interrupts = <0 26 0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
new file mode 100644
index 0000000..facbb15
--- /dev/null
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -0,0 +1,287 @@
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDXPOORWILLS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=12
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SOUNDWIRE=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PINCTRL_SDXPOORWILLS=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_MMC=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_GSI=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_SMEM=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_PWM=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
+CONFIG_ANDROID=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
new file mode 100644
index 0000000..2bfcf87
--- /dev/null
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -0,0 +1,294 @@
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDXPOORWILLS=y
+# CONFIG_VDSO is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=12
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_HVC_DCC=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SOUNDWIRE=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SLIMBUS=y
+CONFIG_PINCTRL_SDXPOORWILLS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_MSM_CDC_PINCTRL=y
+CONFIG_MSM_CDC_SUPPLY=y
+CONFIG_FB=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_MMC=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_QCOM_SMEM=y
+CONFIG_QCOM_SMD=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_PWM=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ANDROID=y
+CONFIG_STM=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_XZ_DEC=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 28866e9..f4d7965 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -38,5 +38,18 @@
select CLKSRC_OF
select COMMON_CLK
+config ARCH_SDXPOORWILLS
+ bool "Enable support for SDXPOORWILLS"
+ select CPU_V7
+ select HAVE_ARM_ARCH_TIMER
+ select MSM_CORTEX_A7
+ select COMMON_CLK_MSM
+ select PINCTRL
+ select QCOM_SCM if SMP
+ select MSM_JTAG_MM if CORESIGHT_ETM
+ select PM_DEVFREQ
+ select COMMON_CLK
+ select COMMON_CLK_QCOM
+ select QCOM_GDSC
endmenu
endif
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index e7ffa04..d893b27 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_USE_OF) += board-dt.o
obj-$(CONFIG_SMP) += platsmp.o
+obj-$(CONFIG_ARCH_SDXPOORWILLS) += board-poorwills.o
diff --git a/arch/arm/mach-qcom/board-poorwills.c b/arch/arm/mach-qcom/board-poorwills.c
new file mode 100644
index 0000000..31f5d3e
--- /dev/null
+++ b/arch/arm/mach-qcom/board-poorwills.c
@@ -0,0 +1,32 @@
+/* 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/kernel.h>
+#include "board-dt.h"
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+static const char *sdxpoorwills_dt_match[] __initconst = {
+ "qcom,sdxpoorwills",
+ NULL
+};
+
+static void __init sdxpoorwills_init(void)
+{
+ board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDXPOORWILLS_DT,
+ "Qualcomm Technologies, Inc. SDX POORWILLS (Flattened Device Tree)")
+ .init_machine = sdxpoorwills_init,
+ .dt_compat = sdxpoorwills_dt_match,
+MACHINE_END
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 33f3cc6..19f444e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2401,6 +2401,7 @@
set_dma_ops(dev, dma_ops);
}
+EXPORT_SYMBOL(arch_setup_dma_ops);
void arch_teardown_dma_ops(struct device *dev)
{
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index ba0695b..b861876 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -83,7 +83,6 @@
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_GCC_PLUGINS
select HAVE_GENERIC_DMA_COHERENT
- select HAVE_HW_BREAKPOINT if PERF_EVENTS
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP if NUMA
@@ -687,7 +686,7 @@
config ARM64_DMA_IOMMU_ALIGNMENT
int "Maximum PAGE_SIZE order of alignment for DMA IOMMU buffers"
range 4 9
- default 8
+ default 9
help
DMA mapping framework by default aligns all buffers to the smallest
PAGE_SIZE order which is greater than or equal to the requested buffer
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
index 3766d51..f1501fa 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-sdm845.dtsi
@@ -33,16 +33,12 @@
<GIC_SPI 369 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 370 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 371 IRQ_TYPE_EDGE_RISING>;
- clock-names = "gcc_gpu_cfg_ahb_clk",
- "gcc_ddrss_gpu_axi_clk",
+ clock-names = "gcc_ddrss_gpu_axi_clk",
"gcc_gpu_memnoc_gfx_clk",
- "gcc_gpu_snoc_dvm_gfx_clk",
"gpu_cc_ahb_clk",
"gpu_cc_cx_gmu_clk";
- clocks = <&clock_gcc GCC_GPU_CFG_AHB_CLK>,
- <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
+ clocks = <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>,
<&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>,
- <&clock_gcc GCC_GPU_SNOC_DVM_GFX_CLK>,
<&clock_gpucc GPU_CC_AHB_CLK>,
<&clock_gpucc GPU_CC_CX_GMU_CLK>;
attach-impl-defs =
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index 7c496f1..15db8da 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -136,6 +136,7 @@
interrupt-names = "eoc-int-en-set";
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1875>;
+ #thermal-sensor-cells = <1>;
chan@6 {
label = "die_temp";
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 539685a..923804f 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -232,6 +232,25 @@
<12000 2250>; /* 12V @ 2.25A */
};
+ bcl_sensor: bcl@4200 {
+ compatible = "qcom,msm-bcl-lmh";
+ reg = <0x4200 0xff>,
+ <0x4300 0xff>;
+ reg-names = "fg_user_adc",
+ "fg_lmh";
+ interrupts = <0x2 0x42 0x0 IRQ_TYPE_NONE>,
+ <0x2 0x42 0x1 IRQ_TYPE_NONE>,
+ <0x2 0x42 0x2 IRQ_TYPE_NONE>,
+ <0x2 0x42 0x3 IRQ_TYPE_NONE>,
+ <0x2 0x42 0x4 IRQ_TYPE_NONE>;
+ interrupt-names = "bcl-high-ibat",
+ "bcl-very-high-ibat",
+ "bcl-low-vbat",
+ "bcl-very-low-vbat",
+ "bcl-crit-low-vbat";
+ #thermal-sensor-cells = <1>;
+ };
+
pmi8998_rradc: rradc@4500 {
compatible = "qcom,rradc";
reg = <0x4500 0x100>;
@@ -651,3 +670,130 @@
};
};
};
+
+&thermal_zones {
+ ibat-high {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ thermal-sensors = <&bcl_sensor 0>;
+
+ trips {
+ ibat_high: low-ibat {
+ temperature = <4200>;
+ hysteresis = <200>;
+ type = "passive";
+ };
+ };
+ };
+ ibat-vhigh {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "step_wise";
+ thermal-sensors = <&bcl_sensor 1>;
+
+ trips {
+ ibat_vhigh: ibat_vhigh {
+ temperature = <4300>;
+ hysteresis = <100>;
+ type = "passive";
+ };
+ };
+ };
+ vbat {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 2>;
+ tracks-low;
+
+ trips {
+ low_vbat: low-vbat {
+ temperature = <3300>;
+ hysteresis = <100>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ vbat_cpu4 {
+ trip = <&low_vbat>;
+ cooling-device = <&CPU4 22 22>;
+ };
+ vbat_cpu5 {
+ trip = <&low_vbat>;
+ cooling-device = <&CPU5 22 22>;
+ };
+ vbat_map6 {
+ trip = <&low_vbat>;
+ cooling-device = <&CPU6 22 22>;
+ };
+ vbat_map7 {
+ trip = <&low_vbat>;
+ cooling-device = <&CPU7 22 22>;
+ };
+ };
+ };
+ vbat_low {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 3>;
+ tracks-low;
+
+ trips {
+ low-vbat {
+ temperature = <3100>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+ vbat_too_low {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 4>;
+ tracks-low;
+
+ trips {
+ low-vbat {
+ temperature = <2900>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ };
+ soc {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_cap";
+ thermal-sensors = <&bcl_sensor 5>;
+ tracks-low;
+
+ trips {
+ low_soc: low-soc {
+ temperature = <10>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ soc_cpu4 {
+ trip = <&low_soc>;
+ cooling-device = <&CPU4 22 22>;
+ };
+ soc_cpu5 {
+ trip = <&low_soc>;
+ cooling-device = <&CPU5 22 22>;
+ };
+ soc_map6 {
+ trip = <&low_soc>;
+ cooling-device = <&CPU6 22 22>;
+ };
+ soc_map7 {
+ trip = <&low_soc>;
+ cooling-device = <&CPU7 22 22>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
index b66ca94..9d59a16 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
@@ -18,7 +18,7 @@
&msm_audio_ion {
iommus = <&apps_smmu 0x1821>;
- qcom,smmu-sid-mask = <0xf>;
+ qcom,smmu-sid-mask = /bits/ 64 <0xf>;
};
&soc {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
new file mode 100644
index 0000000..c0189a4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-cdp.dtsi
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016-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.
+ */
+
+&soc {
+ led_flash_rear: qcom,camera-flash@0 {
+ cell-index = <0>;
+ reg = <0x00 0x00>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+ qcom,torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+ qcom,switch-source = <&pmi8998_switch0>;
+ status = "ok";
+ };
+
+ led_flash_front: qcom,camera-flash@1 {
+ cell-index = <1>;
+ reg = <0x01 0x00>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmi8998_flash2>;
+ qcom,torch-source = <&pmi8998_torch2>;
+ qcom,switch-source = <&pmi8998_switch1>;
+ status = "ok";
+ };
+
+ actuator_regulator: gpio-regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0x00 0x00>;
+ regulator-name = "actuator_regulator";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <100>;
+ enable-active-high;
+ gpio = <&tlmm 27 0>;
+ vin-supply = <&pmi8998_bob>;
+ };
+
+ camera_rear_ldo: gpio-regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <0x01 0x00>;
+ regulator-name = "camera_rear_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <135>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 12 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_rear_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+
+ camera_ldo: gpio-regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <0x02 0x00>;
+ regulator-name = "camera_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 9 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+};
+
+&cci {
+ actuator_rear: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ };
+
+ actuator_front: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ };
+
+ ois_rear: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ status = "disabled";
+ };
+
+ eeprom_rear: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 80 0>,
+ <&tlmm 79 0>,
+ <&tlmm 27 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-vaf = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VANA0",
+ "CAM_VAF";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ eeprom_rear_aux: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ eeprom_front: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 8 0>,
+ <&tlmm 27 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-vaf = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VANA2",
+ "CAM_VAF";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@0 {
+ cell-index = <0>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <180>;
+ qcom,led-flash-src = <&led_flash_rear>;
+ qcom,actuator-src = <&actuator_rear>;
+ qcom,ois-src = <&ois_rear>;
+ qcom,eeprom-src = <&eeprom_rear>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 80 0>,
+ <&tlmm 79 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VANA";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <180>;
+ qcom,eeprom-src = <&eeprom_rear_aux>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@2 {
+ cell-index = <2>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <0>;
+ qcom,eeprom-src = <&eeprom_front>;
+ qcom,actuator-src = <&actuator_front>;
+ qcom,led-flash-src = <&led_flash_front>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VANA1";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..c0189a4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-mtp.dtsi
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016-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.
+ */
+
+&soc {
+ led_flash_rear: qcom,camera-flash@0 {
+ cell-index = <0>;
+ reg = <0x00 0x00>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmi8998_flash0 &pmi8998_flash1>;
+ qcom,torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+ qcom,switch-source = <&pmi8998_switch0>;
+ status = "ok";
+ };
+
+ led_flash_front: qcom,camera-flash@1 {
+ cell-index = <1>;
+ reg = <0x01 0x00>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmi8998_flash2>;
+ qcom,torch-source = <&pmi8998_torch2>;
+ qcom,switch-source = <&pmi8998_switch1>;
+ status = "ok";
+ };
+
+ actuator_regulator: gpio-regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0x00 0x00>;
+ regulator-name = "actuator_regulator";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <100>;
+ enable-active-high;
+ gpio = <&tlmm 27 0>;
+ vin-supply = <&pmi8998_bob>;
+ };
+
+ camera_rear_ldo: gpio-regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <0x01 0x00>;
+ regulator-name = "camera_rear_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <135>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 12 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_rear_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+
+ camera_ldo: gpio-regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <0x02 0x00>;
+ regulator-name = "camera_ldo";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&pm8998_gpios 9 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_dvdd_en_default>;
+ vin-supply = <&pm8998_s3>;
+ };
+};
+
+&cci {
+ actuator_rear: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ };
+
+ actuator_front: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ };
+
+ ois_rear: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <2800000>;
+ qcom,cam-vreg-op-mode = <0>;
+ status = "disabled";
+ };
+
+ eeprom_rear: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 80 0>,
+ <&tlmm 79 0>,
+ <&tlmm 27 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-vaf = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VANA0",
+ "CAM_VAF";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ eeprom_rear_aux: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ eeprom_front: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 8 0>,
+ <&tlmm 27 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-vaf = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VANA2",
+ "CAM_VAF";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@0 {
+ cell-index = <0>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <180>;
+ qcom,led-flash-src = <&led_flash_rear>;
+ qcom,actuator-src = <&actuator_rear>;
+ qcom,ois-src = <&ois_rear>;
+ qcom,eeprom-src = <&eeprom_rear>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 80 0>,
+ <&tlmm 79 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VANA";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <180>;
+ qcom,eeprom-src = <&eeprom_rear_aux>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1050000 0 3312000>;
+ qcom,cam-vreg-max-voltage = <1050000 0 3600000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@2 {
+ cell-index = <2>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,sensor-position-roll = <90>;
+ qcom,sensor-position-pitch = <0>;
+ qcom,sensor-position-yaw = <0>;
+ qcom,eeprom-src = <&eeprom_front>;
+ qcom,actuator-src = <&actuator_front>;
+ qcom,led-flash-src = <&led_flash_front>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pmi8998_bob>;
+ cam_vdig-supply = <&camera_ldo>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1050000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1050000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VANA1";
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ qcom,clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index c197d65..cd9c8a8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -16,4 +16,213 @@
compatible = "qcom,cam-req-mgr";
status = "ok";
};
+
+ qcom,csiphy@ac65000 {
+ cell-index = <0>;
+ compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+ reg = <0x0ac65000 0x1000>;
+ reg-names = "csiphy";
+ interrupts = <0 477 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "gdscr";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+ clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&clock_camcc CAM_CC_SOC_AHB_CLK>,
+ <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+ <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSIPHY0_CLK>,
+ <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+ <&clock_camcc CAM_CC_IFE_0_CSID_CLK>,
+ <&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>;
+ clock-names = "camnoc_axi_clk",
+ "soc_ahb_clk",
+ "slow_ahb_src_clk",
+ "cpas_ahb_clk",
+ "cphy_rx_clk_src",
+ "csiphy0_clk",
+ "csi0phytimer_clk_src",
+ "csi0phytimer_clk",
+ "ife_0_csid_clk",
+ "ife_0_csid_clk_src";
+ qcom,clock-rates =
+ <0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+ status = "ok";
+ };
+
+ qcom,csiphy@ac66000{
+ cell-index = <1>;
+ compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+ reg = <0xac66000 0x1000>;
+ reg-names = "csiphy";
+ interrupts = <0 478 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "gdscr";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+ clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&clock_camcc CAM_CC_SOC_AHB_CLK>,
+ <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+ <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSIPHY1_CLK>,
+ <&clock_camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>,
+ <&clock_camcc CAM_CC_IFE_1_CSID_CLK>,
+ <&clock_camcc CAM_CC_IFE_1_CSID_CLK_SRC>;
+ clock-names = "camnoc_axi_clk",
+ "soc_ahb_clk",
+ "slow_ahb_src_clk",
+ "cpas_ahb_clk",
+ "cphy_rx_clk_src",
+ "csiphy1_clk",
+ "csi1phytimer_clk_src",
+ "csi1phytimer_clk",
+ "ife_1_csid_clk",
+ "ife_1_csid_clk_src";
+ qcom,clock-rates =
+ <0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+
+ status = "ok";
+ };
+
+ qcom,csiphy@ac67000 {
+ cell-index = <2>;
+ compatible = "qcom,csiphy-v1.0", "qcom,csiphy";
+ reg = <0xac67000 0x1000>;
+ reg-names = "csiphy";
+ interrupts = <0 479 0>;
+ interrupt-names = "csiphy";
+ gdscr-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "gdscr";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8998_l26>;
+ clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&clock_camcc CAM_CC_SOC_AHB_CLK>,
+ <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+ <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSIPHY2_CLK>,
+ <&clock_camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>,
+ <&clock_camcc CAM_CC_CSI2PHYTIMER_CLK>,
+ <&clock_camcc CAM_CC_IFE_LITE_CSID_CLK>,
+ <&clock_camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>;
+ clock-names = "camnoc_axi_clk",
+ "soc_ahb_clk",
+ "slow_ahb_src_clk",
+ "cpas_ahb_clk",
+ "cphy_rx_clk_src",
+ "csiphy2_clk",
+ "csi2phytimer_clk_src",
+ "csi2phytimer_clk",
+ "ife_lite_csid_clk",
+ "ife_lite_csid_clk_src";
+ qcom,clock-rates =
+ <0 0 80000000 0 320000000 0 269333333 0 0 384000000>;
+ status = "ok";
+ };
+
+ cci: qcom,cci@ac4a000 {
+ cell-index = <0>;
+ compatible = "qcom,cci";
+ reg = <0xac4a000 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "cci";
+ interrupts = <0 460 0>;
+ interrupt-names = "cci";
+ status = "ok";
+ gdscr-supply = <&titan_top_gdsc>;
+ qcom,cam-vreg-name = "gdscr";
+ clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&clock_camcc CAM_CC_SOC_AHB_CLK>,
+ <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&clock_camcc CAM_CC_CPAS_AHB_CLK>,
+ <&clock_camcc CAM_CC_CCI_CLK>,
+ <&clock_camcc CAM_CC_CCI_CLK_SRC>;
+ clock-names = "camnoc_axi_clk",
+ "soc_ahb_clk",
+ "slow_ahb_src_clk",
+ "cpas_ahb_clk",
+ "cci_clk",
+ "cci_clk_src";
+ qcom,clock-rates = <0 0 80000000 0 0 37500000>;
+ pinctrl-names = "cci_default", "cci_suspend";
+ pinctrl-0 = <&cci0_active &cci1_active>;
+ pinctrl-1 = <&cci0_suspend &cci1_suspend>;
+ gpios = <&tlmm 17 0>,
+ <&tlmm 18 0>,
+ <&tlmm 19 0>,
+ <&tlmm 20 0>;
+ qcom,gpio-tbl-num = <0 1 2 3>;
+ qcom,gpio-tbl-flags = <1 1 1 1>;
+ qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+ "CCI_I2C_CLK0",
+ "CCI_I2C_DATA1",
+ "CCI_I2C_CLK1";
+
+ i2c_freq_100Khz: qcom,i2c_standard_mode {
+ qcom,hw-thigh = <201>;
+ qcom,hw-tlow = <174>;
+ qcom,hw-tsu-sto = <204>;
+ qcom,hw-tsu-sta = <231>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <162>;
+ qcom,hw-tbuf = <227>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+ };
+
+ i2c_freq_400Khz: qcom,i2c_fast_mode {
+ qcom,hw-thigh = <38>;
+ qcom,hw-tlow = <56>;
+ qcom,hw-tsu-sto = <40>;
+ qcom,hw-tsu-sta = <40>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <35>;
+ qcom,hw-tbuf = <62>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+ };
+
+ i2c_freq_custom: qcom,i2c_custom_mode {
+ qcom,hw-thigh = <38>;
+ qcom,hw-tlow = <56>;
+ qcom,hw-tsu-sto = <40>;
+ qcom,hw-tsu-sta = <40>;
+ qcom,hw-thd-dat = <22>;
+ qcom,hw-thd-sta = <35>;
+ qcom,hw-tbuf = <62>;
+ qcom,hw-scl-stretch-en = <1>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+ };
+
+ i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+ qcom,hw-thigh = <16>;
+ qcom,hw-tlow = <22>;
+ qcom,hw-tsu-sto = <17>;
+ qcom,hw-tsu-sta = <18>;
+ qcom,hw-thd-dat = <16>;
+ qcom,hw-thd-sta = <15>;
+ qcom,hw-tbuf = <24>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <3>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 7f9351d..6f35bf7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -11,6 +11,30 @@
*/
#include <dt-bindings/gpio/gpio.h>
+#include "sdm845-camera-sensor-cdp.dtsi"
+
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pm8998_s3>;
+ qca,bt-vdd-xtal-supply = <&pm8998_s5>;
+ qca,bt-vdd-core-supply = <&pm8998_l7>;
+ qca,bt-vdd-pa-supply = <&pm8998_l17>;
+ qca,bt-vdd-ldo-supply = <&pm8998_l25>;
+
+ qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+ qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+ qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+ };
+};
&soc {
sound-tavil {
@@ -119,6 +143,26 @@
status = "ok";
};
+&sdhc_2 {
+ vdd-supply = <&pm8998_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm8998_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
&pmi8998_switch1 {
pinctrl-names = "led_enable", "led_disable";
pinctrl-0 = <&flash_led3_front_en>;
@@ -190,3 +234,113 @@
&usb_qmp_phy {
status = "okay";
};
+
+&pm8998_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "pa_therm1";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
+
+&pm8998_adc_tm {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+};
+
+&thermal_zones {
+ xo-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4c>;
+ };
+
+ msm-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4d>;
+ };
+
+ pa-therm1-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4f>;
+ };
+
+ quiet-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x51>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index fa225ef1..434de76 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -21,9 +21,8 @@
coresight-name = "coresight-replicator";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -57,9 +56,8 @@
coresight-name = "coresight-replicator-swao";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -106,9 +104,8 @@
coresight-name = "coresight-tmc-etf-swao";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -143,9 +140,8 @@
coresight-name = "coresight-funnel-swao";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -171,7 +167,8 @@
};
tpda_swao: tpda@6b01000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x6b01000 0x1000>;
reg-names = "tpda-base";
@@ -181,9 +178,8 @@
qcom,dsb-elem-size = <1 32>;
qcom,cmb-elem-size = <0 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -220,16 +216,16 @@
};
tpdm_swao0: tpdm@6b02000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6b02000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-swao-0";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_swao0_out_tpda_swao: endpoint {
@@ -239,15 +235,15 @@
};
tpdm_swao1: tpdm@6b03000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6b03000 0x1000>;
reg-names = "tpdm-base";
coresight-name="coresight-tpdm-swao-1";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_swao1_out_tpda_swao: endpoint {
@@ -265,13 +261,13 @@
reg-names = "tmc-base", "bam-base";
arm,buffer-size = <0x400000>;
+ arm,sg-enable;
coresight-name = "coresight-tmc-etr";
coresight-ctis = <&cti0 &cti8>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tmc_etr_in_replicator: endpoint {
@@ -292,9 +288,8 @@
coresight-ctis = <&cti0 &cti8>;
arm,default-sink;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -329,9 +324,8 @@
coresight-name = "coresight-funnel-merg";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -375,9 +369,8 @@
coresight-name = "coresight-stm";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
stm_out_funnel_in0: endpoint {
@@ -396,9 +389,8 @@
coresight-name = "coresight-funnel-in0";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -449,9 +441,8 @@
coresight-name = "coresight-funnel-in2";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -498,7 +489,8 @@
};
tpda: tpda@6004000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x6004000 0x1000>;
reg-names = "tpda-base";
@@ -511,6 +503,7 @@
qcom,dsb-elem-size = <0 32>,
<2 32>,
<3 32>,
+ <5 32>,
<10 32>,
<11 32>,
<13 32>;
@@ -518,9 +511,8 @@
<7 64>,
<13 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -562,6 +554,15 @@
};
port@4 {
+ reg = <5>;
+ tpda_in_funnel_lpass: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&funnel_lpass_out_tpda>;
+ };
+ };
+
+ port@5 {
reg = <7>;
tpda_in_tpdm_vsense: endpoint {
slave-mode;
@@ -570,7 +571,7 @@
};
};
- port@5 {
+ port@6 {
reg = <10>;
tpda_in_tpdm_qm: endpoint {
slave-mode;
@@ -579,7 +580,7 @@
};
};
- port@6 {
+ port@7 {
reg = <11>;
tpda_in_tpdm_north: endpoint {
slave-mode;
@@ -588,7 +589,7 @@
};
};
- port@7 {
+ port@8 {
reg = <13>;
tpda_in_tpdm_pimem: endpoint {
slave-mode;
@@ -608,9 +609,8 @@
coresight-name = "coresight-funnel-modem";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -636,7 +636,8 @@
};
tpda_modem: tpda@6831000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x6831000 0x1000>;
reg-names = "tpda-base";
@@ -646,9 +647,8 @@
qcom,dsb-elem-size = <0 32>;
qcom,cmb-elem-size = <0 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -673,15 +673,15 @@
};
tpdm_modem: tpdm@6830000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6830000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-modem";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_modem_out_tpda_modem: endpoint {
@@ -690,16 +690,68 @@
};
};
- tpdm_center: tpdm@6c28000 {
+ funnel_lpass: funnel@6845000 {
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b908>;
+
+ reg = <0x6845000 0x1000>;
+ reg-names = "funnel-base";
+
+ coresight-name = "coresight-funnel-lpass";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_lpass_out_tpda: endpoint {
+ remote-endpoint =
+ <&tpda_in_funnel_lpass>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ funnel_lpass_in_tpdm_lpass: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&tpdm_lpass_out_funnel_lpass>;
+ };
+ };
+ };
+ };
+
+ tpdm_lpass: tpdm@6844000 {
compatible = "qcom,coresight-tpdm";
+ reg = <0x6844000 0x1000>;
+ reg-names = "tpdm-base";
+
+ coresight-name = "coresight-tpdm-lpass";
+
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "core_clk";
+
+ port {
+ tpdm_lpass_out_funnel_lpass: endpoint {
+ remote-endpoint = <&funnel_lpass_in_tpdm_lpass>;
+ };
+ };
+ };
+
+ 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_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_center_out_tpda: endpoint {
@@ -709,15 +761,15 @@
};
tpdm_north: tpdm@6a24000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6a24000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-north";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_north_out_tpda: endpoint {
@@ -727,15 +779,15 @@
};
tpdm_qm: tpdm@69d0000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x69d0000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-qm";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_qm_out_tpda: endpoint {
@@ -745,7 +797,8 @@
};
tpda_apss: tpda@7862000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x7862000 0x1000>;
reg-names = "tpda-base";
@@ -754,9 +807,8 @@
qcom,tpda-atid = <66>;
qcom,dsb-elem-size = <0 32>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -781,15 +833,15 @@
};
tpdm_apss: tpdm@7860000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x7860000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-apss";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_apss_out_tpda_apss: endpoint {
@@ -799,7 +851,8 @@
};
tpda_llm_silver: tpda@78c0000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x78c0000 0x1000>;
reg-names = "tpda-base";
@@ -808,9 +861,8 @@
qcom,tpda-atid = <72>;
qcom,cmb-elem-size = <0 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -835,15 +887,15 @@
};
tpdm_llm_silver: tpdm@78a0000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x78a0000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-llm-silver";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_llm_silver_out_tpda_llm_silver: endpoint {
@@ -854,7 +906,8 @@
};
tpda_llm_gold: tpda@78d0000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x78d0000 0x1000>;
reg-names = "tpda-base";
@@ -863,9 +916,8 @@
qcom,tpda-atid = <73>;
qcom,cmb-elem-size = <0 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -890,15 +942,15 @@
};
tpdm_llm_gold: tpdm@78b0000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x78b0000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-llm-gold";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_llm_gold_out_tpda_llm_gold: endpoint {
@@ -917,9 +969,8 @@
coresight-name = "coresight-funnel-dl-mm";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -945,15 +996,15 @@
};
tpdm_mm: tpdm@6c08000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6c08000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-mm";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_mm_out_funnel_dl_mm: endpoint {
@@ -971,9 +1022,8 @@
coresight-name = "coresight-funnel-ddr-0";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -999,15 +1049,15 @@
};
tpdm_ddr: tpdm@69e0000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x69e0000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-ddr";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_ddr_out_funnel_ddr_0: endpoint {
@@ -1017,15 +1067,15 @@
};
tpdm_pimem: tpdm@6850000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6850000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-pimem";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
tpdm_pimem_out_tpda: endpoint {
@@ -1035,15 +1085,15 @@
};
tpdm_vsense: tpdm@6840000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6840000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-vsense";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port{
tpdm_vsense_out_tpda: endpoint {
@@ -1053,7 +1103,8 @@
};
tpda_olc: tpda@7832000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x7832000 0x1000>;
reg-names = "tpda-base";
@@ -1062,9 +1113,8 @@
qcom,tpda-atid = <69>;
qcom,cmb-elem-size = <0 64>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -1088,15 +1138,15 @@
};
tpdm_olc: tpdm@7830000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x7830000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-olc";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port{
tpdm_olc_out_tpda_olc: endpoint {
@@ -1106,7 +1156,8 @@
};
tpda_spss: tpda@6882000 {
- compatible = "qcom,coresight-tpda";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b969>;
reg = <0x6882000 0x1000>;
reg-names = "tpda-base";
@@ -1115,9 +1166,8 @@
qcom,tpda-atid = <70>;
qcom,dsb-elem-size = <0 32>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -1141,16 +1191,15 @@
};
tpdm_spss: tpdm@6880000 {
- compatible = "qcom,coresight-tpdm";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b968>;
reg = <0x6880000 0x1000>;
reg-names = "tpdm-base";
coresight-name = "coresight-tpdm-spss";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
-
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
qcom,msr-fix-req;
port{
@@ -1169,9 +1218,8 @@
coresight-name = "coresight-funnel-spss";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -1205,9 +1253,8 @@
coresight-name = "coresight-funnel-qatb";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -1233,299 +1280,315 @@
};
cti0: cti@6010000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6010000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti0";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti1: cti@6011000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6011000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti1";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti2: cti@6012000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6012000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti2";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti3: cti@6013000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6013000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti3";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti4: cti@6014000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6014000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti4";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti5: cti@6015000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6015000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti5";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti6: cti@6016000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6016000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti6";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti7: cti@6017000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6017000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti7";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti8: cti@6018000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6018000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti8";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti9: cti@6019000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x6019000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti9";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti10: cti@601a000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601a000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti10";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti11: cti@601b000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601b000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti11";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti12: cti@601c000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601c000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti12";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti13: cti@601d000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601d000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti13";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti14: cti@601e000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601e000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti14";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti15: cti@601f000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x601f000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti15";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti_cpu0: cti@7020000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7020000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu0";
cpu = <&CPU0>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
+
};
cti_cpu1: cti@7120000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7120000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu1";
cpu = <&CPU1>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu2: cti@7220000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7220000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu2";
cpu = <&CPU2>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu3: cti@7320000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7320000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu3";
cpu = <&CPU3>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu4: cti@7420000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7420000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu4";
cpu = <&CPU4>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu5: cti@7520000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7520000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu5";
cpu = <&CPU5>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu6: cti@7620000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7620000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu6";
cpu = <&CPU6>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
cti_cpu7: cti@7720000 {
- compatible = "arm,coresight-cti";
+ compatible = "arm,primecell";
+ arm,primecell-periphid = <0x0003b966>;
reg = <0x7720000 0x1000>;
reg-names = "cti-base";
coresight-name = "coresight-cti-cpu7";
cpu = <&CPU7>;
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "core_clk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
};
dummy_eud: dummy_sink {
@@ -1552,9 +1615,8 @@
coresight-name = "coresight-funnel-apss-merg";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
@@ -1624,9 +1686,8 @@
coresight-name = "coresight-etm0";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm0_out_funnel_apss: endpoint {
@@ -1644,9 +1705,8 @@
coresight-name = "coresight-etm1";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm1_out_funnel_apss: endpoint {
@@ -1664,9 +1724,8 @@
coresight-name = "coresight-etm2";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm2_out_funnel_apss: endpoint {
@@ -1684,9 +1743,8 @@
coresight-name = "coresight-etm3";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm3_out_funnel_apss: endpoint {
@@ -1704,9 +1762,8 @@
coresight-name = "coresight-etm4";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm4_out_funnel_apss: endpoint {
@@ -1724,9 +1781,8 @@
coresight-name = "coresight-etm5";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm5_out_funnel_apss: endpoint {
@@ -1744,9 +1800,8 @@
coresight-name = "coresight-etm6";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm6_out_funnel_apss: endpoint {
@@ -1764,9 +1819,8 @@
coresight-name = "coresight-etm7";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
port {
etm7_out_funnel_apss: endpoint {
@@ -1784,9 +1838,8 @@
coresight-name = "coresight-funnel-apss";
- clocks = <&clock_gcc RPMH_QDSS_CLK>,
- <&clock_gcc RPMH_QDSS_A_CLK>;
- clock-names = "apb_pclk", "core_a_clk";
+ clocks = <&clock_aop QDSS_CLK>;
+ clock-names = "apb_pclk";
ports {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
index 3f2317a..bfbaabb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi
@@ -74,6 +74,7 @@
qcom,gpu-qdss-stm = <0x161c0000 0x40000>; // base addr, size
qcom,tsens-name = "tsens_tz_sensor12";
+ #cooling-cells = <2>;
clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK>,
<&clock_gcc GCC_GPU_CFG_AHB_CLK>,
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index f7da384..faa0b5e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -11,6 +11,30 @@
*/
#include <dt-bindings/gpio/gpio.h>
+#include "sdm845-camera-sensor-mtp.dtsi"
+
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pm8998_s3>;
+ qca,bt-vdd-xtal-supply = <&pm8998_s5>;
+ qca,bt-vdd-core-supply = <&pm8998_l7>;
+ qca,bt-vdd-pa-supply = <&pm8998_l17>;
+ qca,bt-vdd-ldo-supply = <&pm8998_l25>;
+
+ qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+ qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+ qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+ };
+};
&soc {
gpio_keys {
@@ -104,6 +128,26 @@
status = "ok";
};
+&sdhc_2 {
+ vdd-supply = <&pm8998_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm8998_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
&pmi8998_switch1 {
pinctrl-names = "led_enable", "led_disable";
pinctrl-0 = <&flash_led3_front_en>;
@@ -168,3 +212,113 @@
&usb_qmp_phy {
status = "okay";
};
+
+&pm8998_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@4f {
+ label = "pa_therm1";
+ reg = <0x4f>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
+ };
+};
+
+&pm8998_adc_tm {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+};
+
+&thermal_zones {
+ xo-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4c>;
+ };
+
+ msm-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4d>;
+ };
+
+ pa-therm1-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x4f>;
+ };
+
+ quiet-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8998_vadc 0x51>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
index a5ed9aa..d6af58b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pinctrl.dtsi
@@ -112,6 +112,54 @@
};
};
+ sdc2_clk_on: sdc2_clk_on {
+ config {
+ pins = "sdc2_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ };
+
+ sdc2_clk_off: sdc2_clk_off {
+ config {
+ pins = "sdc2_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc2_cmd_on: sdc2_cmd_on {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc2_cmd_off: sdc2_cmd_off {
+ config {
+ pins = "sdc2_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc2_data_on: sdc2_data_on {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc2_data_off: sdc2_data_off {
+ config {
+ pins = "sdc2_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
cdc_reset_ctrl {
cdc_reset_sleep: cdc_reset_sleep {
mux {
@@ -2285,6 +2333,231 @@
};
};
};
+
+ cci0_active: cci0_active {
+ mux {
+ /* CLK, DATA */
+ pins = "gpio17","gpio18"; // Only 2
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio17","gpio18";
+ bias-pull-up; /* PULL UP*/
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cci0_suspend: cci0_suspend {
+ mux {
+ /* CLK, DATA */
+ pins = "gpio17","gpio18";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio17","gpio18";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cci1_active: cci1_active {
+ mux {
+ /* CLK, DATA */
+ pins = "gpio19","gpio20";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio19","gpio20";
+ bias-pull-up; /* PULL UP*/
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cci1_suspend: cci1_suspend {
+ mux {
+ /* CLK, DATA */
+ pins = "gpio19","gpio20";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio19","gpio20";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk0_active: cam_sensor_mclk0_active {
+ /* MCLK0 */
+ mux {
+ pins = "gpio13";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio13";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
+ /* MCLK0 */
+ mux {
+ pins = "gpio13";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio13";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear_active: cam_sensor_rear_active {
+ /* RESET, AVDD LDO */
+ mux {
+ pins = "gpio80","gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80","gpio79";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear_suspend: cam_sensor_rear_suspend {
+ /* RESET, AVDD LDO */
+ mux {
+ pins = "gpio80","gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80","gpio79";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk1_active: cam_sensor_mclk1_active {
+ /* MCLK1 */
+ mux {
+ pins = "gpio14";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio14";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
+ /* MCLK1 */
+ mux {
+ pins = "gpio14";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio14";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_front_active: cam_sensor_front_active {
+ /* RESET AVDD_LDO*/
+ mux {
+ pins = "gpio28", "gpio8";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio28", "gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_front_suspend: cam_sensor_front_suspend {
+ /* RESET */
+ mux {
+ pins = "gpio28";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio28";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk2_active: cam_sensor_mclk2_active {
+ /* MCLK1 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio15";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio15";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
+ /* MCLK1 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio15";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio15";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear2_active: cam_sensor_rear2_active {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio9","gpio8";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio9","gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio9","gpio8";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio9","gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
};
};
@@ -2328,6 +2601,24 @@
power-source = <0>;
};
};
+
+ camera_dvdd_en {
+ camera_dvdd_en_default: camera_dvdd_en_default {
+ pins = "gpio9";
+ function = "normal";
+ power-source = <0>;
+ output-low;
+ };
+ };
+
+ camera_rear_dvdd_en {
+ camera_rear_dvdd_en_default: camera_rear_dvdd_en_default {
+ pins = "gpio12";
+ function = "normal";
+ power-source = <0>;
+ output-low;
+ };
+ };
};
&pmi8998_gpios {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
index 21b5659..70e749b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
@@ -139,4 +139,10 @@
};
};
};
+
+ qcom,rpm-stats@c300000 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xC300000 0x1000>, <0xC3F0004 0x4>;
+ reg-names = "phys_addr_base", "offset_addr";
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
index 1c31a7a..dd0d08e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qupv3.dtsi
@@ -10,6 +10,8 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/msm/msm-bus-ids.h>
+
&soc {
/* QUPv3 South instances */
@@ -30,6 +32,7 @@
pinctrl-1 = <&qupv3_se6_4uart_sleep>;
interrupts = <GIC_SPI 607 0>;
status = "disabled";
+ qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
};
qupv3_se7_4uart: qcom,qup_uart@0x89c000 {
@@ -45,6 +48,7 @@
pinctrl-1 = <&qupv3_se7_4uart_sleep>;
interrupts = <GIC_SPI 608 0>;
status = "disabled";
+ qcom,bus-mas = <MSM_BUS_MASTER_BLSP_1>;
};
/* I2C */
@@ -336,6 +340,7 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qupv3_se9_2uart_active>;
pinctrl-1 = <&qupv3_se9_2uart_sleep>;
+ qcom,bus-mas = <MSM_BUS_MASTER_BLSP_2>;
interrupts = <GIC_SPI 354 0>;
status = "disabled";
};
@@ -353,6 +358,7 @@
pinctrl-0 = <&qupv3_se10_2uart_active>;
pinctrl-1 = <&qupv3_se10_2uart_sleep>;
interrupts = <GIC_SPI 355 0>;
+ qcom,bus-mas = <MSM_BUS_MASTER_BLSP_2>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index 9a5cb3b..6989f326 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -28,6 +28,32 @@
};
};
+&spmi_bus {
+ qcom,pm8998@1 {
+ /* PM8998 S12 + S11 + S10 = VDD_APC1 supply */
+ pm8998_s12: regulator@3500 {
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x3500 0x100>;
+ regulator-name = "pm8998_s12";
+ regulator-min-microvolt = <568000>;
+ regulator-max-microvolt = <1056000>;
+ qcom,enable-time = <500>;
+ regulator-always-on;
+ };
+
+ /* PM8998 S13 = VDD_APC0 supply */
+ pm8998_s13: regulator@3800 {
+ compatible = "qcom,qpnp-regulator";
+ reg = <0x3800 0x100>;
+ regulator-name = "pm8998_s13";
+ regulator-min-microvolt = <568000>;
+ regulator-max-microvolt = <928000>;
+ qcom,enable-time = <500>;
+ regulator-always-on;
+ };
+ };
+};
+
&soc {
/* CPR controller regulators */
apc0_cpr: cprh-ctrl@17dc0000 {
@@ -59,7 +85,10 @@
qcom,cpr-saw-use-unit-mV;
qcom,saw-avs-ctrl = <0x101C031>;
- qcom,saw-avs-limit = <0x3A00000>;
+ qcom,saw-avs-limit = <0x3A003A0>;
+
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
qcom,cpr-panic-reg-addr-list =
<0x17dc3a84 0x17dc3a88 0x17840c18>;
@@ -68,6 +97,9 @@
"APSS_SILVER_CPRH_STATUS_1",
"SILVER_SAW4_PMIC_STS";
+ qcom,cpr-aging-ref-voltage = <928000>;
+ vdd-supply = <&pm8998_s13>;
+
thread@1 {
qcom,cpr-thread-id = <1>;
qcom,cpr-consecutive-up = <0>;
@@ -134,6 +166,14 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-max-voltage-adjustment = <15000>;
+ qcom,cpr-aging-ref-corner = <17>;
+ qcom,cpr-aging-ro-scaling-factor = <1620>;
+ qcom,allow-aging-voltage-adjustment =
+ <0 1 1 1 1 1 1 1>;
+ qcom,allow-aging-open-loop-voltage-adjustment =
+ <1>;
};
};
@@ -194,6 +234,14 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-max-voltage-adjustment = <15000>;
+ qcom,cpr-aging-ref-corner = <9>;
+ qcom,cpr-aging-ro-scaling-factor = <1620>;
+ qcom,allow-aging-voltage-adjustment =
+ <0 1 1 1 1 1 1 1>;
+ qcom,allow-aging-open-loop-voltage-adjustment =
+ <1>;
};
};
};
@@ -232,13 +280,19 @@
qcom,cpr-saw-use-unit-mV;
qcom,saw-avs-ctrl = <0x101C031>;
- qcom,saw-avs-limit = <0x4200000>;
+ qcom,saw-avs-limit = <0x4200420>;
+
+ qcom,cpr-enable;
+ qcom,cpr-hw-closed-loop;
qcom,cpr-panic-reg-addr-list =
<0x17db3a84 0x17830c18>;
qcom,cpr-panic-reg-name-list =
"APSS_GOLD_CPRH_STATUS_0", "GOLD_SAW4_PMIC_STS";
+ qcom,cpr-aging-ref-voltage = <1056000>;
+ vdd-supply = <&pm8998_s12>;
+
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
@@ -311,6 +365,14 @@
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-max-voltage-adjustment = <15000>;
+ qcom,cpr-aging-ref-corner = <22>;
+ qcom,cpr-aging-ro-scaling-factor = <1700>;
+ qcom,allow-aging-voltage-adjustment =
+ <0 1 1 1 1 1 1 1>;
+ qcom,allow-aging-open-loop-voltage-adjustment =
+ <1>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
index 3ec83f5..6991b17 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-rumi.dtsi
@@ -44,6 +44,26 @@
status = "ok";
};
+&sdhc_2 {
+ vdd-supply = <&pm8998_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pm8998_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ status = "ok";
+};
+
&soc {
qcom,icnss@18800000 {
compatible = "qcom,icnss";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi
new file mode 100644
index 0000000..168f2a9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi
@@ -0,0 +1,67 @@
+/* Copyright (c) 2016-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.
+ */
+
+&soc {
+ mdss_dsi0_pll: qcom,mdss_dsi_pll@ae94a00 {
+ compatible = "qcom,mdss_dsi_pll_10nm";
+ label = "MDSS DSI 0 PLL";
+ cell-index = <0>;
+ #clock-cells = <1>;
+ reg = <0xae94a00 0x1e0>,
+ <0xae94400 0x800>,
+ <0xaf03000 0x8>;
+ reg-names = "pll_base", "phy_base", "gdsc_base";
+ clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
+ clock-names = "iface_clk";
+ clock-rate = <0>;
+ gdsc-supply = <&mdss_core_gdsc>;
+ qcom,platform-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ qcom,platform-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "gdsc";
+ qcom,supply-min-voltage = <0>;
+ qcom,supply-max-voltage = <0>;
+ qcom,supply-enable-load = <0>;
+ qcom,supply-disable-load = <0>;
+ };
+ };
+ };
+
+ mdss_dsi1_pll: qcom,mdss_dsi_pll@ae96a00 {
+ compatible = "qcom,mdss_dsi_pll_10nm";
+ label = "MDSS DSI 1 PLL";
+ cell-index = <1>;
+ #clock-cells = <1>;
+ reg = <0xae96a00 0x1e0>,
+ <0xae96400 0x800>,
+ <0xaf03000 0x8>;
+ reg-names = "pll_base", "phy_base", "gdsc_base";
+ clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
+ clock-names = "iface_clk";
+ clock-rate = <0>;
+ gdsc-supply = <&mdss_core_gdsc>;
+ qcom,platform-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ qcom,platform-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "gdsc";
+ qcom,supply-min-voltage = <0>;
+ qcom,supply-max-voltage = <0>;
+ qcom,supply-enable-load = <0>;
+ qcom,supply-disable-load = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 3e00577..cb5d924 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -23,15 +23,12 @@
<&clock_gcc GCC_DISP_AXI_CLK>,
<&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
<&clock_dispcc DISP_CC_MDSS_AXI_CLK>,
- <&clock_dispcc DISP_CC_MDSS_MDP_CLK_SRC>,
- <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK_SRC>,
<&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
<&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "gcc_iface", "gcc_bus",
- "iface_clk", "bus_clk", "core_clk_src",
- "vsync_clk_src", "core_clk", "vsync_clk";
- clock-rate = <0 0 0 0 300000000 0 300000000 0 0>;
- clock-max-rate = <0 0 0 0 430000000 0 430000000 0 0>;
+ clock-names = "gcc_iface", "gcc_bus", "iface_clk",
+ "bus_clk", "core_clk", "vsync_clk";
+ clock-rate = <0 0 0 0 300000000 19200000 0>;
+ clock-max-rate = <0 0 0 0 430000000 19200000 0>;
sde-vdd-supply = <&mdss_core_gdsc>;
@@ -276,98 +273,81 @@
};
mdss_dsi0: qcom,mdss_dsi_ctrl0@ae94000 {
- compatible = "qcom,dsi-ctrl-hw-v2.0";
+ compatible = "qcom,dsi-ctrl-hw-v2.2";
label = "dsi-ctrl-0";
- status = "disabled";
cell-index = <0>;
- reg = <0xae94000 0x400>;
- reg-names = "dsi_ctrl";
+ reg = <0xae94000 0x400>,
+ <0xaf08000 0x4>;
+ reg-names = "dsi_ctrl", "disp_cc_base";
interrupt-parent = <&mdss_mdp>;
interrupts = <4 0>;
vdda-1p2-supply = <&pm8998_l26>;
- vdda-0p9-supply = <&pm8998_l1>;
clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK>,
<&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
<&clock_dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK>,
- <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>,
+ <&clock_dispcc DISP_CC_MDSS_ESC0_CLK>;
clock-names = "byte_clk", "byte_clk_rcg", "byte_intf_clk",
- "pixel_clk", "pixel_clk_rcg";
+ "pixel_clk", "pixel_clk_rcg",
+ "esc_clk";
qcom,ctrl-supply-entries {
#address-cells = <1>;
#size-cells = <0>;
+
qcom,ctrl-supply-entry@0 {
reg = <0>;
- qcom,supply-name = "vdda-0p9";
- qcom,supply-min-voltage = <925000>;
- qcom,supply-max-voltage = <925000>;
- qcom,supply-enable-load = <17000>;
- qcom,supply-disable-load = <32>;
- };
-
- qcom,ctrl-supply-entry@1 {
- reg = <0>;
qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1250000>;
- qcom,supply-max-voltage = <1250000>;
- qcom,supply-enable-load = <18160>;
- qcom,supply-disable-load = <1>;
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1200000>;
+ qcom,supply-enable-load = <21800>;
+ qcom,supply-disable-load = <4>;
};
};
};
mdss_dsi1: qcom,mdss_dsi_ctrl1@ae96000 {
- compatible = "qcom,dsi-ctrl-hw-v2.0";
+ compatible = "qcom,dsi-ctrl-hw-v2.2";
label = "dsi-ctrl-1";
- status = "disabled";
cell-index = <1>;
- reg = <0xae96000 0x400>;
- reg-names = "dsi_ctrl";
+ reg = <0xae96000 0x400>,
+ <0xaf08000 0x4>;
+ reg-names = "dsi_ctrl", "disp_cc_base";
interrupt-parent = <&mdss_mdp>;
interrupts = <5 0>;
vdda-1p2-supply = <&pm8998_l26>;
- vdda-0p9-supply = <&pm8998_l1>;
- clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK>,
- <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
- <&clock_dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
- <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK>,
- <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ clocks = <&clock_dispcc DISP_CC_MDSS_BYTE1_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+ <&clock_dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_PCLK1_CLK>,
+ <&clock_dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>,
+ <&clock_dispcc DISP_CC_MDSS_ESC1_CLK>;
clock-names = "byte_clk", "byte_clk_rcg", "byte_intf_clk",
- "pixel_clk", "pixel_clk_rcg";
+ "pixel_clk", "pixel_clk_rcg", "esc_clk";
qcom,ctrl-supply-entries {
#address-cells = <1>;
#size-cells = <0>;
qcom,ctrl-supply-entry@0 {
reg = <0>;
- qcom,supply-name = "vdda-0p9";
- qcom,supply-min-voltage = <925000>;
- qcom,supply-max-voltage = <925000>;
- qcom,supply-enable-load = <17000>;
- qcom,supply-disable-load = <32>;
- };
-
- qcom,ctrl-supply-entry@1 {
- reg = <0>;
qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1250000>;
- qcom,supply-max-voltage = <1250000>;
- qcom,supply-enable-load = <18160>;
- qcom,supply-disable-load = <1>;
+ qcom,supply-min-voltage = <1200000>;
+ qcom,supply-max-voltage = <1200000>;
+ qcom,supply-enable-load = <21800>;
+ qcom,supply-disable-load = <4>;
};
};
};
mdss_dsi_phy0: qcom,mdss_dsi_phy0@ae94400 {
compatible = "qcom,dsi-phy-v3.0";
- status = "disabled";
label = "dsi-phy-0";
cell-index = <0>;
reg = <0xae94400 0x7c0>;
reg-names = "dsi_phy";
gdsc-supply = <&mdss_core_gdsc>;
- vdda-1p2-supply = <&pm8998_l26>;
+ vdda-0p9-supply = <&pm8998_l1>;
qcom,platform-strength-ctrl = [55 03
55 03
55 03
@@ -384,24 +364,23 @@
#size-cells = <0>;
qcom,phy-supply-entry@0 {
reg = <0>;
- qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1250000>;
- qcom,supply-max-voltage = <1250000>;
- qcom,supply-enable-load = <2500>;
- qcom,supply-disable-load = <1>;
+ qcom,supply-name = "vdda-0p9";
+ qcom,supply-min-voltage = <880000>;
+ qcom,supply-max-voltage = <880000>;
+ qcom,supply-enable-load = <36000>;
+ qcom,supply-disable-load = <32>;
};
};
};
mdss_dsi_phy1: qcom,mdss_dsi_phy0@ae96400 {
compatible = "qcom,dsi-phy-v3.0";
- status = "disabled";
label = "dsi-phy-1";
cell-index = <1>;
reg = <0xae96400 0x7c0>;
reg-names = "dsi_phy";
gdsc-supply = <&mdss_core_gdsc>;
- vdda-1p2-supply = <&pm8998_l26>;
+ vdda-0p9-supply = <&pm8998_l1>;
qcom,platform-strength-ctrl = [55 03
55 03
55 03
@@ -418,11 +397,11 @@
#size-cells = <0>;
qcom,phy-supply-entry@0 {
reg = <0>;
- qcom,supply-name = "vdda-1p2";
- qcom,supply-min-voltage = <1250000>;
- qcom,supply-max-voltage = <1250000>;
- qcom,supply-enable-load = <2500>;
- qcom,supply-disable-load = <1>;
+ qcom,supply-name = "vdda-0p9";
+ qcom,supply-min-voltage = <880000>;
+ qcom,supply-max-voltage = <880000>;
+ qcom,supply-enable-load = <36000>;
+ qcom,supply-disable-load = <32>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index e194912..c80343a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -137,7 +137,7 @@
0x29 0x244 /* TUNE2 */
0xca 0x248 /* TUNE3 */
0x04 0x24c /* TUNE4 */
- 0x00 0x250 /* TUNE5 */
+ 0x03 0x250 /* TUNE5 */
0x00 0x23c /* CHG_CTRL2 */
0x22 0x210>; /* PWR_CTRL1 */
@@ -286,10 +286,11 @@
<&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
<&clock_rpmh RPMH_CXO_CLK>,
<&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
- <&clock_gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+ <&clock_gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
clock-names = "aux_clk", "pipe_clk", "ref_clk_src",
- "ref_clk", "com_aux_clk";
+ "ref_clk", "com_aux_clk", "cfg_ahb_clk";
resets = <&clock_gcc GCC_USB3_DP_PHY_PRIM_BCR>,
<&clock_gcc GCC_USB3_PHY_PRIM_BCR>;
@@ -391,7 +392,7 @@
0x29 0x244 /* TUNE2 */
0xca 0x248 /* TUNE3 */
0x04 0x24c /* TUNE4 */
- 0x00 0x250 /* TUNE5 */
+ 0x03 0x250 /* TUNE5 */
0x00 0x23c /* CHG_CTRL2 */
0x22 0x210>; /* PWR_CTRL1 */
@@ -529,10 +530,11 @@
clocks = <&clock_gcc GCC_USB3_SEC_PHY_AUX_CLK>,
<&clock_gcc GCC_USB3_SEC_PHY_PIPE_CLK>,
<&clock_rpmh RPMH_CXO_CLK>,
- <&clock_gcc GCC_USB3_SEC_CLKREF_CLK>;
+ <&clock_gcc GCC_USB3_SEC_CLKREF_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
clock-names = "aux_clk", "pipe_clk", "ref_clk_src",
- "ref_clk";
+ "ref_clk", "cfg_ahb_clk";
resets = <&clock_gcc GCC_USB3_PHY_SEC_BCR>,
<&clock_gcc GCC_USB3PHY_PHY_SEC_BCR>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
index 2d181a4..b9dc816 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-vidc.dtsi
@@ -34,17 +34,23 @@
/* Clocks */
clock-names = "core_clk", "iface_clk", "bus_clk",
- "core0_clk", "core1_clk";
+ "core0_clk", "core0_bus_clk",
+ "core1_clk", "core1_bus_clk";
clocks = <&clock_videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
<&clock_videocc VIDEO_CC_VENUS_AHB_CLK>,
<&clock_videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
<&clock_videocc VIDEO_CC_VCODEC0_CORE_CLK>,
- <&clock_videocc VIDEO_CC_VCODEC1_CORE_CLK>;
+ <&clock_videocc VIDEO_CC_VCODEC0_AXI_CLK>,
+ <&clock_videocc VIDEO_CC_VCODEC1_CORE_CLK>,
+ <&clock_videocc VIDEO_CC_VCODEC1_AXI_CLK>;
qcom,proxy-clock-names = "core_clk", "iface_clk",
- "bus_clk", "core0_clk", "core1_clk";
- qcom,clock-configs = <0x0 0x0 0x0 0x0 0x0>;
+ "bus_clk", "core0_clk", "core0_bus_clk",
+ "core1_clk", "core1_bus_clk";
+ qcom,clock-configs = <0x1 0x0 0x0 0x1 0x0 0x1 0x0>;
qcom,allowed-clock-rates = <200000000 320000000 380000000
444000000 533000000>;
+ qcom,max-hq-mbs-per-frame = <8160>;
+ qcom,max-hq-frames-per-sec = <60>;
qcom,clock-freq-tbl {
qcom,profile-enc {
qcom,codec-mask = <0x55555555>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 259c5b7..3100fe4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -18,10 +18,12 @@
#include <dt-bindings/clock/qcom,videocc-sdm845.h>
#include <dt-bindings/clock/qcom,cpucc-sdm845.h>
#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/clock/qcom,aop-qmp.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/soc/qcom,tcs-mbox.h>
#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
model = "Qualcomm Technologies, Inc. SDM845";
@@ -32,6 +34,7 @@
aliases {
ufshc1 = &ufshc_mem; /* Embedded UFS slot */
ufshc2 = &ufshc_card; /* Removable UFS slot */
+ sdhc2 = &sdhc_2; /* SDC2 SD card slot */
};
cpus {
@@ -46,6 +49,8 @@
efficiency = <1024>;
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_0>;
L2_0: l2-cache {
compatible = "arm,arch-cache";
@@ -77,6 +82,8 @@
efficiency = <1024>;
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_100>;
L2_100: l2-cache {
compatible = "arm,arch-cache";
@@ -102,6 +109,8 @@
efficiency = <1024>;
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_200>;
L2_200: l2-cache {
compatible = "arm,arch-cache";
@@ -127,6 +136,8 @@
efficiency = <1024>;
cache-size = <0x8000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_300>;
L2_300: l2-cache {
compatible = "arm,arch-cache";
@@ -152,6 +163,8 @@
efficiency = <1740>;
cache-size = <0x20000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_400>;
L2_400: l2-cache {
compatible = "arm,arch-cache";
@@ -177,6 +190,8 @@
efficiency = <1740>;
cache-size = <0x20000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_500>;
L2_500: l2-cache {
compatible = "arm,arch-cache";
@@ -202,6 +217,8 @@
efficiency = <1740>;
cache-size = <0x20000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_600>;
L2_600: l2-cache {
compatible = "arm,arch-cache";
@@ -227,6 +244,8 @@
efficiency = <1740>;
cache-size = <0x20000>;
cpu-release-addr = <0x0 0x90000000>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ #cooling-cells = <2>;
next-level-cache = <&L2_700>;
L2_700: l2-cache {
compatible = "arm,arch-cache";
@@ -411,6 +430,7 @@
};
#include "msm-gdsc-sdm845.dtsi"
+#include "sdm845-sde-pll.dtsi"
#include "sdm845-sde.dtsi"
#include "sdm845-sde-display.dtsi"
#include "sdm845-qupv3.dtsi"
@@ -909,7 +929,7 @@
< 652800000 0x401c0422 0x00002020 0x1 5 >,
< 729600000 0x401c0526 0x00002020 0x1 6 >,
< 806400000 0x401c062a 0x00002222 0x1 7 >,
- < 883200000 0x4024072b 0x00002525 0x1 8 >,
+ < 883200000 0x4024072e 0x00002525 0x1 8 >,
< 960000000 0x40240832 0x00002828 0x1 9 >,
< 1036800000 0x40240936 0x00002b2b 0x1 10 >,
< 1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
@@ -993,6 +1013,13 @@
#clock-cells = <1>;
};
+ clock_aop: qcom,aopclk {
+ compatible = "qcom,aop-qmp-clk";
+ #clock-cells = <1>;
+ mboxes = <&qmp_aop 0>;
+ mbox-names = "qdss_clk";
+ };
+
ufsphy_mem: ufsphy_mem@1d87000 {
reg = <0x1d87000 0xda8>; /* PHY regs */
reg-names = "phy_mem";
@@ -1204,6 +1231,57 @@
status = "disabled";
};
+ sdhc_2: sdhci@8804000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0x8804000 0x1000>;
+ reg-names = "hc_mem";
+
+ interrupts = <0 204 0>, <0 222 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <4>;
+ qcom,large-address-bus;
+
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ /* No vote */
+ <81 512 0 0>, <1 608 0 0>,
+ /* 400 KB/s*/
+ <81 512 1046 1600>,
+ <1 608 1600 1600>,
+ /* 20 MB/s */
+ <81 512 52286 80000>,
+ <1 608 80000 80000>,
+ /* 25 MB/s */
+ <81 512 65360 100000>,
+ <1 608 100000 100000>,
+ /* 50 MB/s */
+ <81 512 130718 200000>,
+ <1 608 133320 133320>,
+ /* 100 MB/s */
+ <81 512 261438 200000>,
+ <1 608 150000 150000>,
+ /* 200 MB/s */
+ <81 512 261438 400000>,
+ <1 608 300000 300000>,
+ /* Max. bandwidth */
+ <81 512 1338562 4096000>,
+ <1 608 1338562 4096000>;
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ qcom,sdr104-wa;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+ clocks = <&clock_gcc GCC_SDCC2_AHB_CLK>,
+ <&clock_gcc GCC_SDCC2_APPS_CLK>;
+ clock-names = "iface_clk", "core_clk";
+
+ status = "disabled";
+ };
+
pil_modem: qcom,mss@4080000 {
compatible = "qcom,pil-q6v55-mss";
reg = <0x4080000 0x100>,
@@ -1221,13 +1299,12 @@
<&clock_gcc GCC_BOOT_ROM_AHB_CLK>,
<&clock_gcc GCC_MSS_GPLL0_DIV_CLK_SRC>,
<&clock_gcc GCC_MSS_SNOC_AXI_CLK>,
- <&clock_gcc GCC_MSS_AXIS2_CLK>,
<&clock_gcc GCC_MSS_MFAB_AXIS_CLK>,
<&clock_gcc GCC_PRNG_AHB_CLK>;
clock-names = "xo", "iface_clk", "bus_clk",
"mem_clk", "gpll0_mss_clk", "snoc_axi_clk",
- "axis2_clk","mnoc_axi_clk", "prng_clk";
- qcom,proxy-clock-names = "xo", "axis2_clk", "prng_clk";
+ "mnoc_axi_clk", "prng_clk";
+ qcom,proxy-clock-names = "xo", "prng_clk";
qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk",
"gpll0_mss_clk", "snoc_axi_clk",
"mnoc_axi_clk";
@@ -1256,6 +1333,10 @@
/* GPIO output to mss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ qcom,mba-mem@0 {
+ compatible = "qcom,pil-mba-mem";
+ memory-region = <&pil_mba_mem>;
+ };
};
qcom,lpass@17300000 {
@@ -1423,11 +1504,22 @@
qcom,rtb-size = <0x100000>;
};
+ qcom,mpm2-sleep-counter@0x0c221000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0x0c221000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
qcom,msm-cdsp-loader {
compatible = "qcom,cdsp-loader";
qcom,proc-img-to-load = "cdsp";
};
+ qcom,msm-adsprpc-mem {
+ compatible = "qcom,msm-adsprpc-mem-region";
+ memory-region = <&adsp_mem>;
+ };
+
qcom,msm_fastrpc {
compatible = "qcom,msm-fastrpc-compute";
@@ -1479,6 +1571,32 @@
iommus = <&apps_smmu 0x1408>,
<&apps_smmu 0x1428>;
};
+ qcom,msm_fastrpc_compute_cb9 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ qcom,secure-context-bank;
+ iommus = <&apps_smmu 0x1409>,
+ <&apps_smmu 0x1419>,
+ <&apps_smmu 0x1429>;
+ };
+ qcom,msm_fastrpc_compute_cb10 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "cdsprpc-smd";
+ qcom,secure-context-bank;
+ iommus = <&apps_smmu 0x140A>,
+ <&apps_smmu 0x141A>,
+ <&apps_smmu 0x142A>;
+ };
+ qcom,msm_fastrpc_compute_cb11 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_smmu 0x1823>;
+ };
+ qcom,msm_fastrpc_compute_cb12 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&apps_smmu 0x1824>;
+ };
};
qcom,msm-imem@146bf000 {
@@ -1498,10 +1616,20 @@
reg = <0x65c 4>;
};
+ boot_stats@6b0 {
+ compatible = "qcom,msm-imem-boot_stats";
+ reg = <0x6b0 32>;
+ };
+
pil@94c {
compatible = "qcom,msm-imem-pil";
reg = <0x94c 200>;
};
+
+ kaslr_offset@6d0 {
+ compatible = "qcom,msm-imem-kaslr_offset";
+ reg = <0x6d0 12>;
+ };
};
qcom,venus@aae0000 {
@@ -1879,6 +2007,20 @@
status = "ok";
};
+ spss_utils: qcom,spss_utils {
+ compatible = "qcom,spss-utils";
+ /* spss fuses physical address */
+ qcom,spss-fuse1-addr = <0x007841c4>;
+ qcom,spss-fuse1-bit = <27>;
+ qcom,spss-fuse2-addr = <0x007841c4>;
+ qcom,spss-fuse2-bit = <26>;
+ qcom,spss-dev-firmware-name = "spss1d"; /* 8 chars max */
+ qcom,spss-test-firmware-name = "spss1t"; /* 8 chars max */
+ qcom,spss-prod-firmware-name = "spss1p"; /* 8 chars max */
+ qcom,spss-debug-reg-addr = <0x01886020>;
+ status = "ok";
+ };
+
qcom,glink_pkt {
compatible = "qcom,glinkpkt";
@@ -1944,15 +2086,74 @@
qcom,pipe-attr-ee;
};
+ qcom_seecom: qseecom@86d00000 {
+ compatible = "qcom,qseecom";
+ reg = <0x86d00000 0x2200000>;
+ reg-names = "secapp-region";
+ qcom,hlos-num-ce-hw-instances = <1>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,support-fde;
+ qcom,no-clock-support;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <125 512 0 0>,
+ <125 512 200000 400000>,
+ <125 512 300000 800000>,
+ <125 512 400000 1000000>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_CLK>,
+ <&clock_gcc GCC_CE1_AHB_CLK>,
+ <&clock_gcc GCC_CE1_AXI_CLK>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,qsee-reentrancy-support = <2>;
+ };
+
+ qcom_rng: qrng@793000 {
+ compatible = "qcom,msm-rng";
+ reg = <0x793000 0x1000>;
+ qcom,msm-rng-iface-clk;
+ qcom,no-qrng-config;
+ qcom,msm-bus,name = "msm-rng-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 618 0 0>, /* No vote */
+ <1 618 0 800>; /* 100 KHz */
+ clocks = <&clock_gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "iface_clk";
+ };
+
+ qcom_tzlog: tz-log@146bf720 {
+ compatible = "qcom,tz-log";
+ reg = <0x146bf720 0x3000>;
+ qcom,hyplog-enabled;
+ hyplog-address-offset = <0x410>;
+ hyplog-size-offset = <0x414>;
+ };
+
qcom,msm_gsi {
compatible = "qcom,msm_gsi";
};
+ qcom,rmtfs_sharedmem@0 {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x0 0x200000>;
+ reg-names = "rmtfs";
+ qcom,client-id = <0x00000001>;
+ };
+
qcom,rmnet-ipa {
compatible = "qcom,rmnet-ipa3";
qcom,rmnet-ipa-ssr;
qcom,ipa-loaduC;
qcom,ipa-advertise-sg-support;
+ qcom,ipa-napi-enable;
};
ipa_hw: qcom,ipa@01e00000 {
@@ -1971,6 +2172,8 @@
qcom,modem-cfg-emb-pipe-flt;
qcom,ipa-wdi2;
qcom,use-64-bit-dma-mask;
+ qcom,arm-smmu;
+ qcom,smmu-s1-bypass;
qcom,bandwidth-vote-for-ipa;
qcom,msm-bus,name = "ipa";
qcom,msm-bus,num-cases = <4>;
@@ -2050,26 +2253,28 @@
0x0 /* modem_comp_decomp_ofst; diff */
0x0 /* modem_comp_decomp_size; diff */
0xbd8 /* modem_ofst; */
- 0x1424 /* modem_size; */
- 0x1ffc /* apps_v4_flt_hash_ofst; */
+ 0x1024 /* modem_size; */
+ 0x2000 /* apps_v4_flt_hash_ofst; */
0x0 /* apps_v4_flt_hash_size; */
- 0x1ffc /* apps_v4_flt_nhash_ofst; */
+ 0x2000 /* apps_v4_flt_nhash_ofst; */
0x0 /* apps_v4_flt_nhash_size; */
- 0x1ffc /* apps_v6_flt_hash_ofst; */
+ 0x2000 /* apps_v6_flt_hash_ofst; */
0x0 /* apps_v6_flt_hash_size; */
- 0x1ffc /* apps_v6_flt_nhash_ofst; */
+ 0x2000 /* apps_v6_flt_nhash_ofst; */
0x0 /* apps_v6_flt_nhash_size; */
0x80 /* uc_info_ofst; */
0x200 /* uc_info_size; */
0x2000 /* end_ofst; */
- 0x1ffc /* apps_v4_rt_hash_ofst; */
+ 0x2000 /* apps_v4_rt_hash_ofst; */
0x0 /* apps_v4_rt_hash_size; */
- 0x1ffc /* apps_v4_rt_nhash_ofst; */
+ 0x2000 /* apps_v4_rt_nhash_ofst; */
0x0 /* apps_v4_rt_nhash_size; */
- 0x1ffc /* apps_v6_rt_hash_ofst; */
+ 0x2000 /* apps_v6_rt_hash_ofst; */
0x0 /* apps_v6_rt_hash_size; */
- 0x1ffc /* apps_v6_rt_nhash_ofst; */
+ 0x2000 /* apps_v6_rt_nhash_ofst; */
0x0 /* apps_v6_rt_nhash_size; */
+ 0x1c00 /* uc_event_ring_ofst; */
+ 0x400 /* uc_event_ring_size; */
>;
/* smp2p gpio information */
@@ -2082,6 +2287,23 @@
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 0x720>;
+ qcom,iova-mapping = <0x20000000 0x40000000>;
+ };
+
+ ipa_smmu_wlan: ipa_smmu_wlan {
+ compatible = "qcom,ipa-smmu-wlan-cb";
+ iommus = <&apps_smmu 0x721>;
+ };
+
+ ipa_smmu_uc: ipa_smmu_uc {
+ compatible = "qcom,ipa-smmu-uc-cb";
+ iommus = <&apps_smmu 0x722>;
+ qcom,iova-mapping = <0x40000000 0x20000000>;
+ };
};
qcom,ipa_fws {
@@ -2131,6 +2353,8 @@
reg = <0x10a2000 0x1000>,
<0x10ae000 0x2000>;
reg-names = "dcc-base", "dcc-ram-base";
+
+ dcc-ram-offset = <0x6000>;
};
qcom,msm-core@780000 {
@@ -2160,6 +2384,1045 @@
<0 425 0 /* CE11 */ >;
qcom,wlan-msa-memory = <0x100000>;
};
+
+ thermal_zones: thermal-zones {
+ aoss0-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 0>;
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu0-silver-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 1>;
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu1-silver-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 2>;
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu2-silver-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 3>;
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu3-silver-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 4>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ kryo-l3-0-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 5>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ kryo-l3-1-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 6>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu0-gold-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 7>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu1-gold-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 8>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu2-gold-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 9>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu3-gold-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 10>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu0-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 11>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu1-ts0-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 12>;
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ aoss1-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 0>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-dsp-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 1>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+
+
+ ddr-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 2>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ wlan-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 3>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ compute-hvx-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 4>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 5>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mmss-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 6>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ mdm-core-ts1-h {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 7>;
+ thermal-governor = "user_space";
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu0 {
+ polling-delay-passive = <10>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 11>;
+ thermal-governor = "step_wise";
+ trips {
+ gpu0_trip: gpu0-trip {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ gpu0_cdev {
+ trip = <&gpu0_trip>;
+ cooling-device =
+ <&msm_gpu 1 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ gpu1 {
+ polling-delay-passive = <10>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 12>;
+ thermal-governor = "step_wise";
+ trips {
+ gpu1_trip: gpu1-trip {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ gpu1_cdev {
+ trip = <&gpu1_trip>;
+ cooling-device =
+ <&msm_gpu 1 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ pop-mem {
+ polling-delay-passive = <10>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens1 2>;
+ thermal-governor = "step_wise";
+ trips {
+ pop_trip: pop-trip {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ pop_cdev {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU4 1 THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ aoss0-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 0>;
+ tracks-low;
+ trips {
+ aoss0_trip: aoss0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss0_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu0-silver-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 1>;
+ tracks-low;
+ trips {
+ cpu0_trip: cpu0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpu0_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu1-silver-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 2>;
+ tracks-low;
+ trips {
+ cpu1_trip: cpu1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpu1_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu2-silver-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 3>;
+ tracks-low;
+ trips {
+ cpu2_trip: cpu2-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpu2_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu3-silver-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 4>;
+ tracks-low;
+ trips {
+ cpu3_trip: cpu3-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpu3_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ kryo-l3-0-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 5>;
+ tracks-low;
+ trips {
+ l3_0_trip: l3-0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&l3_0_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ kryo-l3-1-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 6>;
+ tracks-low;
+ trips {
+ l3_1_trip: l3-1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&l3_1_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu0-gold-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 7>;
+ tracks-low;
+ trips {
+ cpug0_trip: cpug0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpug0_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu1-gold-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 8>;
+ tracks-low;
+ trips {
+ cpug1_trip: cpug1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpug1_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu2-gold-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 9>;
+ tracks-low;
+ trips {
+ cpug2_trip: cpug2-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug2_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpug2_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpug2_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ cpu3-gold-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 9>;
+ tracks-low;
+ trips {
+ cpug3_trip: cpug3-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpug3_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&cpug3_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&cpug3_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ gpu0-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 10>;
+ tracks-low;
+ trips {
+ gpu0_trip_l: gpu0-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&gpu0_trip_l>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ gpu1-ts0-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 11>;
+ tracks-low;
+ trips {
+ gpu1_trip_l: gpu1-trip_l {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&gpu1_trip_l>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ aoss1-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 0>;
+ tracks-low;
+ trips {
+ aoss1_trip: aoss1-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&aoss1_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ mdm-dsp-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 1>;
+ tracks-low;
+ trips {
+ dsp_trip: dsp-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&dsp_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ ddr-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 2>;
+ tracks-low;
+ trips {
+ ddr_trip: ddr-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&ddr_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ wlan-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 3>;
+ tracks-low;
+ trips {
+ wlan_trip: wlan-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&wlan_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ compute-hvx-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 4>;
+ tracks-low;
+ trips {
+ hvx_trip: hvx-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&hvx_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ camera-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 5>;
+ tracks-low;
+ trips {
+ camera_trip: camera-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ mmss-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 6>;
+ tracks-low;
+ trips {
+ mmss_trip: mmss-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&mmss_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ mdm-core-ts1-l {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens1 7>;
+ tracks-low;
+ trips {
+ mdm_trip: mdm-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&CPU0 12 12>;
+ };
+ cpu4_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&CPU4 12 12>;
+ };
+ gpu_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&msm_gpu 4 4>;
+ };
+ };
+ };
+
+ lmh-dcvs-01 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&lmh_dcvs1>;
+
+ trips {
+ active-config {
+ temperature = <95000>;
+ hysteresis = <30000>;
+ type = "passive";
+ };
+ };
+ };
+
+ lmh-dcvs-00 {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&lmh_dcvs0>;
+
+ trips {
+ active-config {
+ temperature = <95000>;
+ hysteresis = <30000>;
+ type = "passive";
+ };
+ };
+ };
+
+ };
+
+ tsens0: tsens@c222000 {
+ compatible = "qcom,sdm845-tsens";
+ reg = <0xc222000 0x4>,
+ <0xc263000 0x1ff>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical";
+ interrupts = <0 506 0>, <0 508 0>;
+ interrupt-names = "tsens-upper-lower", "tsens-critical";
+ #thermal-sensor-cells = <1>;
+ };
+
+ tsens1: tsens@c223000 {
+ compatible = "qcom,sdm845-tsens";
+ reg = <0xc223000 0x4>,
+ <0xc265000 0x1ff>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical";
+ interrupts = <0 507 0>, <0 509 0>;
+ interrupt-names = "tsens-upper-lower", "tsens-critical";
+ #thermal-sensor-cells = <1>;
+ };
+};
+
+&clock_cpucc {
+ lmh_dcvs0: qcom,limits-dcvs@0 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,affinity = <0>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ lmh_dcvs1: qcom,limits-dcvs@1 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,affinity = <1>;
+ #thermal-sensor-cells = <0>;
+ };
};
&pcie_0_gdsc {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 59aaff4..9a2ab8c 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -55,6 +55,7 @@
CONFIG_HZ_100=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
@@ -225,6 +226,7 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
CONFIG_MEMORY_STATE_TIME=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
@@ -263,6 +265,7 @@
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
@@ -273,6 +276,7 @@
CONFIG_SERIAL_MSM_GENI=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_ADSPRPC=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QCOM_GENI=y
@@ -299,8 +303,17 @@
CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_WCD934X_CODEC=y
@@ -379,6 +392,7 @@
CONFIG_USB_CONFIGFS_F_GSI=y
CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
CONFIG_MMC_TEST=y
@@ -395,6 +409,7 @@
CONFIG_RTC_DRV_QPNP=y
CONFIG_DMADEVICES=y
CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
@@ -409,6 +424,7 @@
CONFIG_QPNP_COINCELL=y
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
+CONFIG_SEEMP_CORE=y
CONFIG_MSM_GCC_SDM845=y
CONFIG_MSM_VIDEOCC_SDM845=y
CONFIG_MSM_CAMCC_SDM845=y
@@ -417,6 +433,7 @@
CONFIG_MSM_CLK_RPMH=y
CONFIG_CLOCK_CPU_OSM=y
CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
CONFIG_QCOM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MSM_QMP=y
@@ -427,6 +444,7 @@
CONFIG_IOMMU_TESTS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_QCOM_EUD=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
@@ -440,6 +458,7 @@
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
CONFIG_TRACER_PKT=y
CONFIG_QTI_RPMH_API=y
CONFIG_MSM_SMP2P=y
@@ -475,6 +494,7 @@
CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_MSM_TZ_LOG=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 3ccc503..31f8703 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -61,6 +61,7 @@
CONFIG_CLEANCACHE=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
CONFIG_SECCOMP=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
@@ -234,6 +235,7 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
CONFIG_UID_SYS_STATS=y
CONFIG_MEMORY_STATE_TIME=y
CONFIG_SCSI=y
@@ -272,6 +274,7 @@
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
@@ -280,9 +283,8 @@
CONFIG_SERIAL_MSM_GENI=y
CONFIG_SERIAL_MSM_GENI_CONSOLE=y
CONFIG_DIAG_CHAR=y
-CONFIG_HVC_DCC=y
-CONFIG_HVC_DCC_SERIALIZE_SMP=y
CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_ADSPRPC=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QCOM_GENI=y
@@ -309,8 +311,17 @@
CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_WCD934X_CODEC=y
@@ -327,6 +338,7 @@
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SPECTRA_CAMERA=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_VIDC_VMEM=y
CONFIG_MSM_VIDC_GOVERNORS=y
@@ -388,6 +400,7 @@
CONFIG_USB_CONFIGFS_F_GSI=y
CONFIG_USB_CONFIGFS_F_QDSS=y
CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
CONFIG_MMC_TEST=y
@@ -412,6 +425,7 @@
CONFIG_RTC_DRV_QPNP=y
CONFIG_DMADEVICES=y
CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
CONFIG_STAGING=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
@@ -426,6 +440,7 @@
CONFIG_QPNP_COINCELL=y
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
+CONFIG_SEEMP_CORE=y
CONFIG_MSM_GCC_SDM845=y
CONFIG_MSM_VIDEOCC_SDM845=y
CONFIG_MSM_CAMCC_SDM845=y
@@ -434,6 +449,7 @@
CONFIG_MSM_CLK_RPMH=y
CONFIG_CLOCK_CPU_OSM=y
CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
CONFIG_QCOM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MSM_QMP=y
@@ -445,6 +461,7 @@
CONFIG_QCOM_CPUSS_DUMP=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_EUD=y
@@ -460,6 +477,7 @@
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
CONFIG_TRACER_PKT=y
CONFIG_QTI_RPMH_API=y
CONFIG_MSM_SMP2P=y
@@ -498,6 +516,7 @@
CONFIG_PHY_XGENE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_MSM_TZ_LOG=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
@@ -518,10 +537,12 @@
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_SLUB_DEBUG_PANIC_ON=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_PAGE_POISONING=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_FREE=y
CONFIG_DEBUG_OBJECTS_TIMERS=y
@@ -536,7 +557,6 @@
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
@@ -549,7 +569,6 @@
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_LIST=y
-CONFIG_RCU_PANIC_ON_STALL=1
CONFIG_FAULT_INJECTION=y
CONFIG_FAIL_PAGE_ALLOC=y
CONFIG_FAULT_INJECTION_DEBUG_FS=y
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 3b40f26..aaf4bd7 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -394,7 +394,7 @@
{
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL1];
- if (!sge) {
+ if (sched_is_energy_aware() && !sge) {
pr_warn("Invalid sched_group_energy for Cluster%d\n", cpu);
return NULL;
}
@@ -407,7 +407,7 @@
{
struct sched_group_energy *sge = sge_array[cpu][SD_LEVEL0];
- if (!sge) {
+ if (sched_is_energy_aware() && !sge) {
pr_warn("Invalid sched_group_energy for CPU%d\n", cpu);
return NULL;
}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 296e139..0a34644 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -335,7 +335,8 @@
if (is_el0_instruction_abort(esr)) {
vm_flags = VM_EXEC;
- } else if ((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) {
+ } else if (((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) ||
+ ((esr & ESR_ELx_CM) && !(mm_flags & FAULT_FLAG_USER))) {
vm_flags = VM_WRITE;
mm_flags |= FAULT_FLAG_WRITE;
}
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 9a6e11b6..5a4f2eb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -9,6 +9,7 @@
select HAVE_CONTEXT_TRACKING
select HAVE_GENERIC_DMA_COHERENT
select HAVE_IDE
+ select HAVE_IRQ_EXIT_ON_IRQ_STACK
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 6bf10e7..956db6e 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -17,6 +17,18 @@
#include <irq.h>
+#define IRQ_STACK_SIZE THREAD_SIZE
+
+extern void *irq_stack[NR_CPUS];
+
+static inline bool on_irq_stack(int cpu, unsigned long sp)
+{
+ unsigned long low = (unsigned long)irq_stack[cpu];
+ unsigned long high = low + IRQ_STACK_SIZE;
+
+ return (low <= sp && sp <= high);
+}
+
#ifdef CONFIG_I8259
static inline int irq_canonicalize(int irq)
{
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index eebf395..2f182bd 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -216,12 +216,19 @@
LONG_S $25, PT_R25(sp)
LONG_S $28, PT_R28(sp)
LONG_S $31, PT_R31(sp)
+
+ /* Set thread_info if we're coming from user mode */
+ mfc0 k0, CP0_STATUS
+ sll k0, 3 /* extract cu0 bit */
+ bltz k0, 9f
+
ori $28, sp, _THREAD_MASK
xori $28, _THREAD_MASK
#ifdef CONFIG_CPU_CAVIUM_OCTEON
.set mips64
pref 0, 0($28) /* Prefetch the current pointer */
#endif
+9:
.set pop
.endm
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index fae2f94..4be2763 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -102,6 +102,7 @@
OFFSET(TI_REGS, thread_info, regs);
DEFINE(_THREAD_SIZE, THREAD_SIZE);
DEFINE(_THREAD_MASK, THREAD_MASK);
+ DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
BLANK();
}
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 52a4fdf..2ac6c26 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -187,9 +187,44 @@
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
- PTR_LA ra, ret_from_irq
- PTR_LA v0, plat_irq_dispatch
- jr v0
+
+ /*
+ * SAVE_ALL ensures we are using a valid kernel stack for the thread.
+ * Check if we are already using the IRQ stack.
+ */
+ move s1, sp # Preserve the sp
+
+ /* Get IRQ stack for this CPU */
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+ lui k1, %hi(irq_stack)
+#else
+ lui k1, %highest(irq_stack)
+ daddiu k1, %higher(irq_stack)
+ dsll k1, 16
+ daddiu k1, %hi(irq_stack)
+ dsll k1, 16
+#endif
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
+ LONG_ADDU k1, k0
+ LONG_L t0, %lo(irq_stack)(k1)
+
+ # Check if already on IRQ stack
+ PTR_LI t1, ~(_THREAD_SIZE-1)
+ and t1, t1, sp
+ beq t0, t1, 2f
+
+ /* Switch to IRQ stack */
+ li t1, _IRQ_STACK_SIZE
+ PTR_ADD sp, t0, t1
+
+2:
+ jal plat_irq_dispatch
+
+ /* Restore sp */
+ move sp, s1
+
+ j ret_from_irq
#ifdef CONFIG_CPU_MICROMIPS
nop
#endif
@@ -262,8 +297,44 @@
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
- PTR_LA ra, ret_from_irq
- jr v0
+
+ /*
+ * SAVE_ALL ensures we are using a valid kernel stack for the thread.
+ * Check if we are already using the IRQ stack.
+ */
+ move s1, sp # Preserve the sp
+
+ /* Get IRQ stack for this CPU */
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
+#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
+ lui k1, %hi(irq_stack)
+#else
+ lui k1, %highest(irq_stack)
+ daddiu k1, %higher(irq_stack)
+ dsll k1, 16
+ daddiu k1, %hi(irq_stack)
+ dsll k1, 16
+#endif
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
+ LONG_ADDU k1, k0
+ LONG_L t0, %lo(irq_stack)(k1)
+
+ # Check if already on IRQ stack
+ PTR_LI t1, ~(_THREAD_SIZE-1)
+ and t1, t1, sp
+ beq t0, t1, 2f
+
+ /* Switch to IRQ stack */
+ li t1, _IRQ_STACK_SIZE
+ PTR_ADD sp, t0, t1
+
+2:
+ jalr v0
+
+ /* Restore sp */
+ move sp, s1
+
+ j ret_from_irq
END(except_vec_vi_handler)
/*
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index f25f7ea..2b0a371 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -25,6 +25,8 @@
#include <linux/atomic.h>
#include <asm/uaccess.h>
+void *irq_stack[NR_CPUS];
+
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -58,6 +60,15 @@
clear_c0_status(ST0_IM);
arch_init_irq();
+
+ for_each_possible_cpu(i) {
+ int irq_pages = IRQ_STACK_SIZE / PAGE_SIZE;
+ void *s = (void *)__get_free_pages(GFP_KERNEL, irq_pages);
+
+ irq_stack[i] = s;
+ pr_debug("CPU%d IRQ stack at 0x%p - 0x%p\n", i,
+ irq_stack[i], irq_stack[i] + IRQ_STACK_SIZE);
+ }
}
#ifdef CONFIG_DEBUG_STACKOVERFLOW
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 1652f36..fbbf5fc 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -33,6 +33,7 @@
#include <asm/dsemul.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
+#include <asm/irq.h>
#include <asm/msa.h>
#include <asm/pgtable.h>
#include <asm/mipsregs.h>
@@ -556,7 +557,19 @@
unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
unsigned long pc, unsigned long *ra)
{
- unsigned long stack_page = (unsigned long)task_stack_page(task);
+ unsigned long stack_page = 0;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ if (on_irq_stack(cpu, *sp)) {
+ stack_page = (unsigned long)irq_stack[cpu];
+ break;
+ }
+ }
+
+ if (!stack_page)
+ stack_page = (unsigned long)task_stack_page(task);
+
return unwind_stack_by_address(stack_page, sp, pc, ra);
}
#endif
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 0ddf369..8ac0e59 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -269,11 +269,6 @@
DEFINE_HWx_IRQDISPATCH(5)
#endif
-static void ltq_hw_irq_handler(struct irq_desc *desc)
-{
- ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
-}
-
#ifdef CONFIG_MIPS_MT_SMP
void __init arch_init_ipiirq(int irq, struct irqaction *action)
{
@@ -318,19 +313,23 @@
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
- int irq;
+ unsigned int i;
- if (!pending) {
- spurious_interrupt();
- return;
+ if ((MIPS_CPU_TIMER_IRQ == 7) && (pending & CAUSEF_IP7)) {
+ do_IRQ(MIPS_CPU_TIMER_IRQ);
+ goto out;
+ } else {
+ for (i = 0; i < MAX_IM; i++) {
+ if (pending & (CAUSEF_IP2 << i)) {
+ ltq_hw_irqdispatch(i);
+ goto out;
+ }
+ }
}
+ pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
- pending >>= CAUSEB_IP;
- while (pending) {
- irq = fls(pending) - 1;
- do_IRQ(MIPS_CPU_IRQ_BASE + irq);
- pending &= ~BIT(irq);
- }
+out:
+ return;
}
static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
@@ -355,6 +354,11 @@
.map = icu_map,
};
+static struct irqaction cascade = {
+ .handler = no_action,
+ .name = "cascade",
+};
+
int __init icu_of_init(struct device_node *node, struct device_node *parent)
{
struct device_node *eiu_node;
@@ -386,7 +390,7 @@
mips_cpu_irq_init();
for (i = 0; i < MAX_IM; i++)
- irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
+ setup_irq(i + 2, &cascade);
if (cpu_has_vint) {
pr_info("Setting up vectored interrupts\n");
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 7fcf512..0497cec 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -42,10 +42,10 @@
#define get_user __get_user
#if !defined(CONFIG_64BIT)
-#define LDD_USER(ptr) __get_user_asm64(ptr)
+#define LDD_USER(val, ptr) __get_user_asm64(val, ptr)
#define STD_USER(x, ptr) __put_user_asm64(x, ptr)
#else
-#define LDD_USER(ptr) __get_user_asm("ldd", ptr)
+#define LDD_USER(val, ptr) __get_user_asm(val, "ldd", ptr)
#define STD_USER(x, ptr) __put_user_asm("std", x, ptr)
#endif
@@ -100,63 +100,87 @@
" mtsp %0,%%sr2\n\t" \
: : "r"(get_fs()) : )
-#define __get_user(x, ptr) \
-({ \
- register long __gu_err __asm__ ("r8") = 0; \
- register long __gu_val; \
- \
- load_sr2(); \
- switch (sizeof(*(ptr))) { \
- case 1: __get_user_asm("ldb", ptr); break; \
- case 2: __get_user_asm("ldh", ptr); break; \
- case 4: __get_user_asm("ldw", ptr); break; \
- case 8: LDD_USER(ptr); break; \
- default: BUILD_BUG(); break; \
- } \
- \
- (x) = (__force __typeof__(*(ptr))) __gu_val; \
- __gu_err; \
+#define __get_user_internal(val, ptr) \
+({ \
+ register long __gu_err __asm__ ("r8") = 0; \
+ \
+ switch (sizeof(*(ptr))) { \
+ case 1: __get_user_asm(val, "ldb", ptr); break; \
+ case 2: __get_user_asm(val, "ldh", ptr); break; \
+ case 4: __get_user_asm(val, "ldw", ptr); break; \
+ case 8: LDD_USER(val, ptr); break; \
+ default: BUILD_BUG(); \
+ } \
+ \
+ __gu_err; \
})
-#define __get_user_asm(ldx, ptr) \
+#define __get_user(val, ptr) \
+({ \
+ load_sr2(); \
+ __get_user_internal(val, ptr); \
+})
+
+#define __get_user_asm(val, ldx, ptr) \
+{ \
+ register long __gu_val; \
+ \
__asm__("1: " ldx " 0(%%sr2,%2),%0\n" \
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err)); \
+ \
+ (val) = (__force __typeof__(*(ptr))) __gu_val; \
+}
#if !defined(CONFIG_64BIT)
-#define __get_user_asm64(ptr) \
+#define __get_user_asm64(val, ptr) \
+{ \
+ union { \
+ unsigned long long l; \
+ __typeof__(*(ptr)) t; \
+ } __gu_tmp; \
+ \
__asm__(" copy %%r0,%R0\n" \
"1: ldw 0(%%sr2,%2),%0\n" \
"2: ldw 4(%%sr2,%2),%R0\n" \
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
- : "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "=&r"(__gu_tmp.l), "=r"(__gu_err) \
+ : "r"(ptr), "1"(__gu_err)); \
+ \
+ (val) = __gu_tmp.t; \
+}
#endif /* !defined(CONFIG_64BIT) */
-#define __put_user(x, ptr) \
+#define __put_user_internal(x, ptr) \
({ \
register long __pu_err __asm__ ("r8") = 0; \
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
\
- load_sr2(); \
switch (sizeof(*(ptr))) { \
- case 1: __put_user_asm("stb", __x, ptr); break; \
- case 2: __put_user_asm("sth", __x, ptr); break; \
- case 4: __put_user_asm("stw", __x, ptr); break; \
- case 8: STD_USER(__x, ptr); break; \
- default: BUILD_BUG(); break; \
- } \
+ case 1: __put_user_asm("stb", __x, ptr); break; \
+ case 2: __put_user_asm("sth", __x, ptr); break; \
+ case 4: __put_user_asm("stw", __x, ptr); break; \
+ case 8: STD_USER(__x, ptr); break; \
+ default: BUILD_BUG(); \
+ } \
\
__pu_err; \
})
+#define __put_user(x, ptr) \
+({ \
+ load_sr2(); \
+ __put_user_internal(x, ptr); \
+})
+
+
/*
* The "__put_user/kernel_asm()" macros tell gcc they read from memory
* instead of writing. This is because they do not write to any memory
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
index f01188c..85c28bb 100644
--- a/arch/parisc/lib/lusercopy.S
+++ b/arch/parisc/lib/lusercopy.S
@@ -201,7 +201,7 @@
add dst,len,end
/* short copy with less than 16 bytes? */
- cmpib,>>=,n 15,len,.Lbyte_loop
+ cmpib,COND(>>=),n 15,len,.Lbyte_loop
/* same alignment? */
xor src,dst,t0
@@ -216,7 +216,7 @@
/* loop until we are 64-bit aligned */
.Lalign_loop64:
extru dst,31,3,t1
- cmpib,=,n 0,t1,.Lcopy_loop_16
+ cmpib,=,n 0,t1,.Lcopy_loop_16_start
20: ldb,ma 1(srcspc,src),t1
21: stb,ma t1,1(dstspc,dst)
b .Lalign_loop64
@@ -225,6 +225,7 @@
ASM_EXCEPTIONTABLE_ENTRY(20b,.Lcopy_done)
ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done)
+.Lcopy_loop_16_start:
ldi 31,t0
.Lcopy_loop_16:
cmpb,COND(>>=),n t0,len,.Lword_loop
@@ -267,7 +268,7 @@
/* loop until we are 32-bit aligned */
.Lalign_loop32:
extru dst,31,2,t1
- cmpib,=,n 0,t1,.Lcopy_loop_4
+ cmpib,=,n 0,t1,.Lcopy_loop_8
20: ldb,ma 1(srcspc,src),t1
21: stb,ma t1,1(dstspc,dst)
b .Lalign_loop32
@@ -277,7 +278,7 @@
ASM_EXCEPTIONTABLE_ENTRY(21b,.Lcopy_done)
-.Lcopy_loop_4:
+.Lcopy_loop_8:
cmpib,COND(>>=),n 15,len,.Lbyte_loop
10: ldw 0(srcspc,src),t1
@@ -299,7 +300,7 @@
ASM_EXCEPTIONTABLE_ENTRY(16b,.Lcopy_done)
ASM_EXCEPTIONTABLE_ENTRY(17b,.Lcopy_done)
- b .Lcopy_loop_4
+ b .Lcopy_loop_8
ldo -16(len),len
.Lbyte_loop:
@@ -324,7 +325,7 @@
.Lunaligned_copy:
/* align until dst is 32bit-word-aligned */
extru dst,31,2,t1
- cmpib,COND(=),n 0,t1,.Lcopy_dstaligned
+ cmpib,=,n 0,t1,.Lcopy_dstaligned
20: ldb 0(srcspc,src),t1
ldo 1(src),src
21: stb,ma t1,1(dstspc,dst)
@@ -362,7 +363,7 @@
cmpiclr,<> 1,t0,%r0
b,n .Lcase1
.Lcase0:
- cmpb,= %r0,len,.Lcda_finish
+ cmpb,COND(=) %r0,len,.Lcda_finish
nop
1: ldw,ma 4(srcspc,src), a3
@@ -376,7 +377,7 @@
1: ldw,ma 4(srcspc,src), a3
ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault)
ldo -1(len),len
- cmpb,=,n %r0,len,.Ldo0
+ cmpb,COND(=),n %r0,len,.Ldo0
.Ldo4:
1: ldw,ma 4(srcspc,src), a0
ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcda_rdfault)
@@ -402,7 +403,7 @@
1: stw,ma t0, 4(dstspc,dst)
ASM_EXCEPTIONTABLE_ENTRY(1b,.Lcopy_done)
ldo -4(len),len
- cmpb,<> %r0,len,.Ldo4
+ cmpb,COND(<>) %r0,len,.Ldo4
nop
.Ldo0:
shrpw a2, a3, %sar, t0
@@ -436,14 +437,14 @@
/* fault exception fixup handlers: */
#ifdef CONFIG_64BIT
.Lcopy16_fault:
-10: b .Lcopy_done
- std,ma t1,8(dstspc,dst)
+ b .Lcopy_done
+10: std,ma t1,8(dstspc,dst)
ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done)
#endif
.Lcopy8_fault:
-10: b .Lcopy_done
- stw,ma t1,4(dstspc,dst)
+ b .Lcopy_done
+10: stw,ma t1,4(dstspc,dst)
ASM_EXCEPTIONTABLE_ENTRY(10b,.Lcopy_done)
.exit
diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c
index 7853b53..3f9d1a8 100644
--- a/arch/x86/entry/vdso/vdso32-setup.c
+++ b/arch/x86/entry/vdso/vdso32-setup.c
@@ -30,8 +30,10 @@
{
vdso32_enabled = simple_strtoul(s, NULL, 0);
- if (vdso32_enabled > 1)
+ if (vdso32_enabled > 1) {
pr_warn("vdso32 values other than 0 and 1 are no longer allowed; vdso disabled\n");
+ vdso32_enabled = 0;
+ }
return 1;
}
@@ -62,13 +64,18 @@
/* Register vsyscall32 into the ABI table */
#include <linux/sysctl.h>
+static const int zero;
+static const int one = 1;
+
static struct ctl_table abi_table2[] = {
{
.procname = "vsyscall32",
.data = &vdso32_enabled,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = (int *)&zero,
+ .extra2 = (int *)&one,
},
{}
};
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 81b321a..f924629 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -507,6 +507,9 @@
cpuc->lbr_entries[i].to = msr_lastbranch.to;
cpuc->lbr_entries[i].mispred = 0;
cpuc->lbr_entries[i].predicted = 0;
+ cpuc->lbr_entries[i].in_tx = 0;
+ cpuc->lbr_entries[i].abort = 0;
+ cpuc->lbr_entries[i].cycles = 0;
cpuc->lbr_entries[i].reserved = 0;
}
cpuc->lbr_stack.nr = i;
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index e7f155c..94aad63 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -278,7 +278,7 @@
#define ARCH_DLINFO_IA32 \
do { \
- if (vdso32_enabled) { \
+ if (VDSO_CURRENT_BASE) { \
NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
} \
diff --git a/arch/x86/include/asm/pmem.h b/arch/x86/include/asm/pmem.h
index 2c1ebeb..529bb4a 100644
--- a/arch/x86/include/asm/pmem.h
+++ b/arch/x86/include/asm/pmem.h
@@ -55,7 +55,8 @@
* @size: number of bytes to write back
*
* Write back a cache range using the CLWB (cache line write back)
- * instruction.
+ * instruction. Note that @size is internally rounded up to be cache
+ * line size aligned.
*/
static inline void arch_wb_cache_pmem(void *addr, size_t size)
{
@@ -69,15 +70,6 @@
clwb(p);
}
-/*
- * copy_from_iter_nocache() on x86 only uses non-temporal stores for iovec
- * iterators, so for other types (bvec & kvec) we must do a cache write-back.
- */
-static inline bool __iter_needs_pmem_wb(struct iov_iter *i)
-{
- return iter_is_iovec(i) == false;
-}
-
/**
* arch_copy_from_iter_pmem - copy data from an iterator to PMEM
* @addr: PMEM destination address
@@ -94,7 +86,35 @@
/* TODO: skip the write-back by always using non-temporal stores */
len = copy_from_iter_nocache(addr, bytes, i);
- if (__iter_needs_pmem_wb(i))
+ /*
+ * In the iovec case on x86_64 copy_from_iter_nocache() uses
+ * non-temporal stores for the bulk of the transfer, but we need
+ * to manually flush if the transfer is unaligned. A cached
+ * memory copy is used when destination or size is not naturally
+ * aligned. That is:
+ * - Require 8-byte alignment when size is 8 bytes or larger.
+ * - Require 4-byte alignment when size is 4 bytes.
+ *
+ * In the non-iovec case the entire destination needs to be
+ * flushed.
+ */
+ if (iter_is_iovec(i)) {
+ unsigned long flushed, dest = (unsigned long) addr;
+
+ if (bytes < 8) {
+ if (!IS_ALIGNED(dest, 4) || (bytes != 4))
+ arch_wb_cache_pmem(addr, 1);
+ } else {
+ if (!IS_ALIGNED(dest, 8)) {
+ dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
+ arch_wb_cache_pmem(addr, 1);
+ }
+
+ flushed = dest - (unsigned long) addr;
+ if (bytes > flushed && !IS_ALIGNED(bytes - flushed, 8))
+ arch_wb_cache_pmem(addr + bytes - 1, 1);
+ }
+ } else
arch_wb_cache_pmem(addr, bytes);
return len;
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index ec1f756..71beb28 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -151,8 +151,8 @@
if (from->si_signo == SIGSEGV) {
if (from->si_code == SEGV_BNDERR) {
- compat_uptr_t lower = (unsigned long)&to->si_lower;
- compat_uptr_t upper = (unsigned long)&to->si_upper;
+ compat_uptr_t lower = (unsigned long)from->si_lower;
+ compat_uptr_t upper = (unsigned long)from->si_upper;
put_user_ex(lower, &to->si_lower);
put_user_ex(upper, &to->si_upper);
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 69b8f8a..43b55ef 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6925,14 +6925,20 @@
}
page = nested_get_page(vcpu, vmptr);
- if (page == NULL ||
- *(u32 *)kmap(page) != VMCS12_REVISION) {
+ if (page == NULL) {
nested_vmx_failInvalid(vcpu);
+ skip_emulated_instruction(vcpu);
+ return 1;
+ }
+ if (*(u32 *)kmap(page) != VMCS12_REVISION) {
kunmap(page);
+ nested_release_page_clean(page);
+ nested_vmx_failInvalid(vcpu);
skip_emulated_instruction(vcpu);
return 1;
}
kunmap(page);
+ nested_release_page_clean(page);
vmx->nested.vmxon_ptr = vmptr;
break;
case EXIT_REASON_VMCLEAR:
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 22af912..889e761 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -643,21 +643,40 @@
* devmem_is_allowed() checks to see if /dev/mem access to a certain address
* is valid. The argument is a physical page number.
*
- *
- * On x86, access has to be given to the first megabyte of ram because that area
- * contains BIOS code and data regions used by X and dosemu and similar apps.
- * Access has to be given to non-kernel-ram areas as well, these contain the PCI
- * mmio resources as well as potential bios/acpi data regions.
+ * On x86, access has to be given to the first megabyte of RAM because that
+ * area traditionally contains BIOS code and data regions used by X, dosemu,
+ * and similar apps. Since they map the entire memory range, the whole range
+ * must be allowed (for mapping), but any areas that would otherwise be
+ * disallowed are flagged as being "zero filled" instead of rejected.
+ * Access has to be given to non-kernel-ram areas as well, these contain the
+ * PCI mmio resources as well as potential bios/acpi data regions.
*/
int devmem_is_allowed(unsigned long pagenr)
{
- if (pagenr < 256)
- return 1;
- if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ if (page_is_ram(pagenr)) {
+ /*
+ * For disallowed memory regions in the low 1MB range,
+ * request that the page be shown as all zeros.
+ */
+ if (pagenr < 256)
+ return 2;
+
return 0;
- if (!page_is_ram(pagenr))
- return 1;
- return 0;
+ }
+
+ /*
+ * This must follow RAM test, since System RAM is considered a
+ * restricted resource under CONFIG_STRICT_IOMEM.
+ */
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT)) {
+ /* Low 1MB bypasses iomem restrictions. */
+ if (pagenr < 256)
+ return 1;
+
+ return 0;
+ }
+
+ return 1;
}
void free_init_pages(char *what, unsigned long begin, unsigned long end)
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 30031d5..cdfe8c6 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -201,6 +201,10 @@
return;
}
+ /* No need to reserve regions that will never be freed. */
+ if (md.attribute & EFI_MEMORY_RUNTIME)
+ return;
+
size += addr % EFI_PAGE_SIZE;
size = round_up(size, EFI_PAGE_SIZE);
addr = round_down(addr, EFI_PAGE_SIZE);
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
index 44c88ad..bcea81f 100644
--- a/arch/x86/xen/apic.c
+++ b/arch/x86/xen/apic.c
@@ -145,7 +145,7 @@
static int xen_cpu_present_to_apicid(int cpu)
{
if (cpu_present(cpu))
- return xen_get_apic_id(xen_apic_read(APIC_ID));
+ return cpu_data(cpu).apicid;
else
return BAD_APICID;
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ee54ad0..7b597ec 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1474,7 +1474,7 @@
INIT_LIST_HEAD(&tags->page_list);
tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
set->numa_node);
if (!tags->rqs) {
blk_mq_free_tags(tags);
@@ -1500,7 +1500,7 @@
do {
page = alloc_pages_node(set->numa_node,
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
this_order);
if (page)
break;
@@ -1521,7 +1521,7 @@
* Allow kmemleak to scan these pages as they contain pointers
* to additional allocations like via ops->init_request().
*/
- kmemleak_alloc(p, order_to_size(this_order), 1, GFP_KERNEL);
+ kmemleak_alloc(p, order_to_size(this_order), 1, GFP_NOIO);
entries_per_page = order_to_size(this_order) / rq_size;
to_do = min(entries_per_page, set->queue_depth - i);
left -= to_do * rq_size;
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 2ce8bcb..cce0268 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -31,6 +31,7 @@
crypto_completion_t complete;
void *data;
u8 *result;
+ u32 flags;
void *ubuf[] CRYPTO_MINALIGN_ATTR;
};
@@ -252,6 +253,8 @@
priv->result = req->result;
priv->complete = req->base.complete;
priv->data = req->base.data;
+ priv->flags = req->base.flags;
+
/*
* WARNING: We do not backup req->priv here! The req->priv
* is for internal use of the Crypto API and the
@@ -266,38 +269,44 @@
return 0;
}
-static void ahash_restore_req(struct ahash_request *req)
+static void ahash_restore_req(struct ahash_request *req, int err)
{
struct ahash_request_priv *priv = req->priv;
+ if (!err)
+ memcpy(priv->result, req->result,
+ crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
+
/* Restore the original crypto request. */
req->result = priv->result;
- req->base.complete = priv->complete;
- req->base.data = priv->data;
+
+ ahash_request_set_callback(req, priv->flags,
+ priv->complete, priv->data);
req->priv = NULL;
/* Free the req->priv.priv from the ADJUSTED request. */
kzfree(priv);
}
-static void ahash_op_unaligned_finish(struct ahash_request *req, int err)
+static void ahash_notify_einprogress(struct ahash_request *req)
{
struct ahash_request_priv *priv = req->priv;
+ struct crypto_async_request oreq;
- if (err == -EINPROGRESS)
- return;
+ oreq.data = priv->data;
- if (!err)
- memcpy(priv->result, req->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
- ahash_restore_req(req);
+ priv->complete(&oreq, -EINPROGRESS);
}
static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
{
struct ahash_request *areq = req->data;
+ if (err == -EINPROGRESS) {
+ ahash_notify_einprogress(areq);
+ return;
+ }
+
/*
* Restore the original request, see ahash_op_unaligned() for what
* goes where.
@@ -308,7 +317,7 @@
*/
/* First copy req->result into req->priv.result */
- ahash_op_unaligned_finish(areq, err);
+ ahash_restore_req(areq, err);
/* Complete the ORIGINAL request. */
areq->base.complete(&areq->base, err);
@@ -324,7 +333,12 @@
return err;
err = op(req);
- ahash_op_unaligned_finish(req, err);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
+
+ ahash_restore_req(req, err);
return err;
}
@@ -359,25 +373,14 @@
}
EXPORT_SYMBOL_GPL(crypto_ahash_digest);
-static void ahash_def_finup_finish2(struct ahash_request *req, int err)
-{
- struct ahash_request_priv *priv = req->priv;
-
- if (err == -EINPROGRESS)
- return;
-
- if (!err)
- memcpy(priv->result, req->result,
- crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
-
- ahash_restore_req(req);
-}
-
static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
{
struct ahash_request *areq = req->data;
- ahash_def_finup_finish2(areq, err);
+ if (err == -EINPROGRESS)
+ return;
+
+ ahash_restore_req(areq, err);
areq->base.complete(&areq->base, err);
}
@@ -388,11 +391,15 @@
goto out;
req->base.complete = ahash_def_finup_done2;
- req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
err = crypto_ahash_reqtfm(req)->final(req);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
out:
- ahash_def_finup_finish2(req, err);
+ ahash_restore_req(req, err);
return err;
}
@@ -400,7 +407,16 @@
{
struct ahash_request *areq = req->data;
+ if (err == -EINPROGRESS) {
+ ahash_notify_einprogress(areq);
+ return;
+ }
+
+ areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
err = ahash_def_finup_finish1(areq, err);
+ if (areq->priv)
+ return;
areq->base.complete(&areq->base, err);
}
@@ -415,6 +431,11 @@
return err;
err = tfm->update(req);
+ if (err == -EINPROGRESS ||
+ (err == -EBUSY && (ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_BACKLOG)))
+ return err;
+
return ahash_def_finup_finish1(req, err);
}
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index e8817e2..fde8d88 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -39,6 +39,7 @@
struct aead_async_rsgl first_rsgl;
struct list_head list;
struct kiocb *iocb;
+ struct sock *sk;
unsigned int tsgls;
char iv[];
};
@@ -379,12 +380,10 @@
static void aead_async_cb(struct crypto_async_request *_req, int err)
{
- struct sock *sk = _req->data;
- struct alg_sock *ask = alg_sk(sk);
- struct aead_ctx *ctx = ask->private;
- struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
- struct aead_request *req = aead_request_cast(_req);
+ struct aead_request *req = _req->data;
+ struct crypto_aead *tfm = crypto_aead_reqtfm(req);
struct aead_async_req *areq = GET_ASYM_REQ(req, tfm);
+ struct sock *sk = areq->sk;
struct scatterlist *sg = areq->tsgl;
struct aead_async_rsgl *rsgl;
struct kiocb *iocb = areq->iocb;
@@ -447,11 +446,12 @@
memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl));
INIT_LIST_HEAD(&areq->list);
areq->iocb = msg->msg_iocb;
+ areq->sk = sk;
memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm));
aead_request_set_tfm(req, tfm);
aead_request_set_ad(req, ctx->aead_assoclen);
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- aead_async_cb, sk);
+ aead_async_cb, req);
used -= ctx->aead_assoclen;
/* take over all tx sgls from ctx */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 48e19d0..22ca892 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -729,12 +729,12 @@
static int ec_guard(struct acpi_ec *ec)
{
- unsigned long guard = usecs_to_jiffies(ec_polling_guard);
+ unsigned long guard = usecs_to_jiffies(ec->polling_guard);
unsigned long timeout = ec->timestamp + guard;
/* Ensure guarding period before polling EC status */
do {
- if (ec_busy_polling) {
+ if (ec->busy_polling) {
/* Perform busy polling */
if (ec_transaction_completed(ec))
return 0;
@@ -998,6 +998,28 @@
spin_unlock_irqrestore(&ec->lock, flags);
}
+static void acpi_ec_enter_noirq(struct acpi_ec *ec)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ec->lock, flags);
+ ec->busy_polling = true;
+ ec->polling_guard = 0;
+ ec_log_drv("interrupt blocked");
+ spin_unlock_irqrestore(&ec->lock, flags);
+}
+
+static void acpi_ec_leave_noirq(struct acpi_ec *ec)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ec->lock, flags);
+ ec->busy_polling = ec_busy_polling;
+ ec->polling_guard = ec_polling_guard;
+ ec_log_drv("interrupt unblocked");
+ spin_unlock_irqrestore(&ec->lock, flags);
+}
+
void acpi_ec_block_transactions(void)
{
struct acpi_ec *ec = first_ec;
@@ -1278,7 +1300,7 @@
if (function != ACPI_READ && function != ACPI_WRITE)
return AE_BAD_PARAMETER;
- if (ec_busy_polling || bits > 8)
+ if (ec->busy_polling || bits > 8)
acpi_ec_burst_enable(ec);
for (i = 0; i < bytes; ++i, ++address, ++value)
@@ -1286,7 +1308,7 @@
acpi_ec_read(ec, address, value) :
acpi_ec_write(ec, address, *value);
- if (ec_busy_polling || bits > 8)
+ if (ec->busy_polling || bits > 8)
acpi_ec_burst_disable(ec);
switch (result) {
@@ -1329,6 +1351,8 @@
spin_lock_init(&ec->lock);
INIT_WORK(&ec->work, acpi_ec_event_handler);
ec->timestamp = jiffies;
+ ec->busy_polling = true;
+ ec->polling_guard = 0;
return ec;
}
@@ -1390,6 +1414,7 @@
acpi_ec_start(ec, false);
if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+ acpi_ec_enter_noirq(ec);
status = acpi_install_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC,
&acpi_ec_space_handler,
@@ -1429,6 +1454,7 @@
/* This is not fatal as we can poll EC events */
if (ACPI_SUCCESS(status)) {
set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
+ acpi_ec_leave_noirq(ec);
if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
ec->reference_count >= 1)
acpi_ec_enable_gpe(ec, true);
@@ -1839,34 +1865,6 @@
}
#ifdef CONFIG_PM_SLEEP
-static void acpi_ec_enter_noirq(struct acpi_ec *ec)
-{
- unsigned long flags;
-
- if (ec == first_ec) {
- spin_lock_irqsave(&ec->lock, flags);
- ec->saved_busy_polling = ec_busy_polling;
- ec->saved_polling_guard = ec_polling_guard;
- ec_busy_polling = true;
- ec_polling_guard = 0;
- ec_log_drv("interrupt blocked");
- spin_unlock_irqrestore(&ec->lock, flags);
- }
-}
-
-static void acpi_ec_leave_noirq(struct acpi_ec *ec)
-{
- unsigned long flags;
-
- if (ec == first_ec) {
- spin_lock_irqsave(&ec->lock, flags);
- ec_busy_polling = ec->saved_busy_polling;
- ec_polling_guard = ec->saved_polling_guard;
- ec_log_drv("interrupt unblocked");
- spin_unlock_irqrestore(&ec->lock, flags);
- }
-}
-
static int acpi_ec_suspend_noirq(struct device *dev)
{
struct acpi_ec *ec =
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 0c45226..219b90b 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -172,8 +172,8 @@
struct work_struct work;
unsigned long timestamp;
unsigned long nr_pending_queries;
- bool saved_busy_polling;
- unsigned int saved_polling_guard;
+ bool busy_polling;
+ unsigned int polling_guard;
};
extern struct acpi_ec *first_ec;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index d1664df..9ef3941 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1617,7 +1617,11 @@
const struct nfit_set_info_map *map0 = m0;
const struct nfit_set_info_map *map1 = m1;
- return map0->region_offset - map1->region_offset;
+ if (map0->region_offset < map1->region_offset)
+ return -1;
+ else if (map0->region_offset > map1->region_offset)
+ return 1;
+ return 0;
}
/* Retrieve the nth entry referencing this spa */
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5a2fdf1..dd3786a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1827,15 +1827,20 @@
return;
device->flags.match_driver = true;
- if (!ret) {
- ret = device_attach(&device->dev);
- if (ret < 0)
- return;
-
- if (!ret && device->pnp.type.platform_id)
- acpi_default_enumeration(device);
+ if (ret > 0) {
+ acpi_device_set_enumerated(device);
+ goto ok;
}
+ ret = device_attach(&device->dev);
+ if (ret < 0)
+ return;
+
+ if (ret > 0 || !device->pnp.type.platform_id)
+ acpi_device_set_enumerated(device);
+ else
+ acpi_default_enumeration(device);
+
ok:
list_for_each_entry(child, &device->children, node)
acpi_bus_attach(child);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index d7eb419..6485c77 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1765,7 +1765,9 @@
ret = -EBADF;
goto err_fget;
}
+ preempt_enable_no_resched();
ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
+ preempt_disable();
if (ret < 0) {
ret = -EPERM;
goto err_security;
diff --git a/drivers/base/dma-removed.c b/drivers/base/dma-removed.c
index 4281801..09e77d5 100644
--- a/drivers/base/dma-removed.c
+++ b/drivers/base/dma-removed.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
* Copyright (C) 2000-2004 Russell King
*
* This program is free software; you can redistribute it and/or modify
@@ -294,6 +294,7 @@
bool no_kernel_mapping = attrs & DMA_ATTR_NO_KERNEL_MAPPING;
struct removed_region *dma_mem = dev->removed_mem;
+ size = PAGE_ALIGN(size);
if (!no_kernel_mapping)
iounmap(cpu_addr);
mutex_lock(&dma_mem->lock);
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 4e58256..da97163 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -731,6 +731,53 @@
return ret;
}
+static int regcache_sync_block_raw_multi_reg(struct regmap *map, void *block,
+ unsigned long *cache_present,
+ unsigned int block_base,
+ unsigned int start,
+ unsigned int end)
+{
+ unsigned int i, val;
+ unsigned int regtmp = 0;
+ int ret = 0;
+ struct reg_sequence *regs;
+ size_t num_regs = ((end - start) + 1);
+
+ regs = kcalloc(num_regs, sizeof(struct reg_sequence), GFP_KERNEL);
+ if (!regs)
+ return -ENOMEM;
+
+ num_regs = 0;
+ for (i = start; i < end; i++) {
+ regtmp = block_base + (i * map->reg_stride);
+
+ /* skip registers that are not defined/available */
+ if (!regcache_reg_present(cache_present, i))
+ continue;
+
+ val = regcache_get_val(map, block, i);
+
+ /* Is this the hardware default? If so skip. */
+ ret = regcache_lookup_reg(map, regtmp);
+ if (ret >= 0 && val == map->reg_defaults[ret].def) {
+ continue;
+ } else {
+ regs[num_regs].reg = regtmp;
+ regs[num_regs].def = val;
+ regs[num_regs].delay_us = 0;
+ num_regs += 1;
+ }
+ }
+ ret = 0;
+ if (num_regs) {
+ dev_dbg(map->dev, "%s: start: 0x%x - end: 0x%x\n",
+ __func__, regs[0].reg, regs[num_regs-1].reg);
+ ret = _regmap_raw_multi_reg_write(map, regs, num_regs);
+ }
+ kfree(regs);
+ return ret;
+}
+
static int regcache_sync_block_raw(struct regmap *map, void *block,
unsigned long *cache_present,
unsigned int block_base, unsigned int start,
@@ -778,7 +825,12 @@
unsigned int block_base, unsigned int start,
unsigned int end)
{
- if (regmap_can_raw_write(map) && !map->use_single_write)
+ if (regmap_can_raw_write(map) && map->can_multi_write)
+ return regcache_sync_block_raw_multi_reg(map, block,
+ cache_present,
+ block_base, start,
+ end);
+ else if (regmap_can_raw_write(map) && !map->use_single_write)
return regcache_sync_block_raw(map, block, cache_present,
block_base, start, end);
else
diff --git a/drivers/base/regmap/regmap-swr.c b/drivers/base/regmap/regmap-swr.c
index 1a2e09e..be1eb00 100644
--- a/drivers/base/regmap/regmap-swr.c
+++ b/drivers/base/regmap/regmap-swr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -11,6 +11,9 @@
* GNU General Public License for more details.
*/
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/soundwire/soundwire.h>
#include <linux/module.h>
@@ -20,16 +23,22 @@
static int regmap_swr_gather_write(void *context,
const void *reg, size_t reg_size,
- const void *val, size_t val_size)
+ const void *val, size_t val_len)
{
struct device *dev = context;
struct swr_device *swr = to_swr_device(dev);
struct regmap *map = dev_get_regmap(dev, NULL);
- size_t addr_bytes = map->format.reg_bytes;
- int ret = 0;
- int i;
- u32 reg_addr = 0;
+ size_t addr_bytes;
+ size_t val_bytes;
+ int i, ret = 0;
+ u16 reg_addr = 0;
+ u8 *value;
+ if (map == NULL) {
+ dev_err(dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+ addr_bytes = map->format.reg_bytes;
if (swr == NULL) {
dev_err(dev, "%s: swr device is NULL\n", __func__);
return -EINVAL;
@@ -40,29 +49,107 @@
return -EINVAL;
}
reg_addr = *(u16 *)reg;
- for (i = 0; i < val_size; i++) {
- ret = swr_write(swr, swr->dev_num, (reg_addr+i),
- (u32 *)(val+i));
+ val_bytes = map->format.val_bytes;
+ /* val_len = val_bytes * val_count */
+ for (i = 0; i < (val_len / val_bytes); i++) {
+ value = (u8 *)val + (val_bytes * i);
+ ret = swr_write(swr, swr->dev_num, (reg_addr + i), value);
if (ret < 0) {
dev_err(dev, "%s: write reg 0x%x failed, err %d\n",
- __func__, (reg_addr+i), ret);
+ __func__, (reg_addr + i), ret);
break;
}
}
return ret;
}
+static int regmap_swr_raw_multi_reg_write(void *context, const void *data,
+ size_t count)
+{
+ struct device *dev = context;
+ struct swr_device *swr = to_swr_device(dev);
+ struct regmap *map = dev_get_regmap(dev, NULL);
+ size_t addr_bytes;
+ size_t val_bytes;
+ size_t pad_bytes;
+ size_t num_regs;
+ int i = 0;
+ int ret = 0;
+ u16 *reg;
+ u8 *val;
+ u8 *buf;
+
+ if (swr == NULL) {
+ dev_err(dev, "%s: swr device is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (map == NULL) {
+ dev_err(dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ addr_bytes = map->format.reg_bytes;
+ val_bytes = map->format.val_bytes;
+ pad_bytes = map->format.pad_bytes;
+
+ if (addr_bytes + val_bytes + pad_bytes == 0) {
+ dev_err(dev, "%s: sum of addr, value and pad is 0\n", __func__);
+ return -EINVAL;
+ }
+ num_regs = count / (addr_bytes + val_bytes + pad_bytes);
+
+ reg = kcalloc(num_regs, sizeof(u16), GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ val = kcalloc(num_regs, sizeof(u8), GFP_KERNEL);
+ if (!val) {
+ ret = -ENOMEM;
+ goto mem_fail;
+ }
+
+ buf = (u8 *)data;
+ for (i = 0; i < num_regs; i++) {
+ reg[i] = *(u16 *)buf;
+ buf += (map->format.reg_bytes + map->format.pad_bytes);
+ val[i] = *buf;
+ buf += map->format.val_bytes;
+ }
+ ret = swr_bulk_write(swr, swr->dev_num, reg, val, num_regs);
+ if (ret)
+ dev_err(dev, "%s: multi reg write failed\n", __func__);
+
+ kfree(val);
+mem_fail:
+ kfree(reg);
+ return ret;
+}
+
static int regmap_swr_write(void *context, const void *data, size_t count)
{
struct device *dev = context;
struct regmap *map = dev_get_regmap(dev, NULL);
- size_t addr_bytes = map->format.reg_bytes;
+ size_t addr_bytes;
+ size_t val_bytes;
+ size_t pad_bytes;
+
+ if (map == NULL) {
+ dev_err(dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+ addr_bytes = map->format.reg_bytes;
+ val_bytes = map->format.val_bytes;
+ pad_bytes = map->format.pad_bytes;
WARN_ON(count < addr_bytes);
- return regmap_swr_gather_write(context, data, addr_bytes,
- (data + addr_bytes),
- (count - addr_bytes));
+ if (count > (addr_bytes + val_bytes + pad_bytes))
+ return regmap_swr_raw_multi_reg_write(context, data, count);
+ else
+ return regmap_swr_gather_write(context, data, addr_bytes,
+ (data + addr_bytes),
+ (count - addr_bytes));
}
static int regmap_swr_read(void *context,
@@ -72,10 +159,15 @@
struct device *dev = context;
struct swr_device *swr = to_swr_device(dev);
struct regmap *map = dev_get_regmap(dev, NULL);
- size_t addr_bytes = map->format.reg_bytes;
+ size_t addr_bytes;
int ret = 0;
- u32 reg_addr = 0;
+ u16 reg_addr = 0;
+ if (map == NULL) {
+ dev_err(dev, "%s: regmap is NULL\n", __func__);
+ return -EINVAL;
+ }
+ addr_bytes = map->format.reg_bytes;
if (swr == NULL) {
dev_err(dev, "%s: swr is NULL\n", __func__);
return -EINVAL;
@@ -85,7 +177,7 @@
__func__, reg_size);
return -EINVAL;
}
- reg_addr = *(u32 *)reg;
+ reg_addr = *(u16 *)reg;
ret = swr_read(swr, swr->dev_num, reg_addr, val, val_size);
if (ret < 0)
dev_err(dev, "%s: codec reg 0x%x read failed %d\n",
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7a10487..c9441f9 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -54,7 +54,7 @@
struct mutex tx_lock;
struct gendisk *disk;
- int blksize;
+ loff_t blksize;
loff_t bytesize;
/* protects initialization and shutdown of the socket */
@@ -126,7 +126,7 @@
}
static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
- int blocksize, int nr_blocks)
+ loff_t blocksize, loff_t nr_blocks)
{
int ret;
@@ -135,7 +135,7 @@
return ret;
nbd->blksize = blocksize;
- nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
+ nbd->bytesize = blocksize * nr_blocks;
nbd_size_update(nbd, bdev);
@@ -648,7 +648,7 @@
case NBD_SET_SIZE:
return nbd_size_set(nbd, bdev, nbd->blksize,
- arg / nbd->blksize);
+ div_s64(arg, nbd->blksize));
case NBD_SET_SIZE_BLOCKS:
return nbd_size_set(nbd, bdev, nbd->blksize, arg);
@@ -817,7 +817,7 @@
debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout);
- debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
+ debugfs_create_u64("blocksize", 0444, dir, &nbd->blksize);
debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
return 0;
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index d2ef51c..c9914d65 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -582,13 +582,13 @@
if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) {
bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value);
- clear_page(mem);
+ memset(mem, 0, PAGE_SIZE);
return 0;
}
cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO);
if (size == PAGE_SIZE) {
- copy_page(mem, cmem);
+ memcpy(mem, cmem, PAGE_SIZE);
} else {
struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
@@ -780,7 +780,7 @@
if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) {
src = kmap_atomic(page);
- copy_page(cmem, src);
+ memcpy(cmem, src, PAGE_SIZE);
kunmap_atomic(src);
} else {
memcpy(cmem, src, clen);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index bc48a84..3e1367a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -573,9 +573,12 @@
controlling the behavior of this hardware.
config DEVPORT
- bool
+ bool "/dev/port character device"
depends on ISA || PCI
default y
+ help
+ Say Y here if you want to support the /dev/port device. The /dev/port
+ device is similar to /dev/mem, but for I/O ports.
source "drivers/s390/char/Kconfig"
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 9c26f87..e907d0d 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -773,6 +773,7 @@
if (*buf != 0x80) {
list_del(&entry->track);
kfree(entry);
+ entry = NULL;
return 1;
}
@@ -790,6 +791,7 @@
if (delayed_rsp_id == 0) {
list_del(&entry->track);
kfree(entry);
+ entry = NULL;
return 1;
}
@@ -803,6 +805,7 @@
if (rsp_count > 0 && rsp_count < 0x1000) {
list_del(&entry->track);
kfree(entry);
+ entry = NULL;
return 1;
}
@@ -1447,6 +1450,7 @@
dci_ops_tbl[proc].peripheral_status &= ~peripheral_mask;
/* Notify the DCI process that the peripheral DCI Channel is up */
+ mutex_lock(&driver->dci_mutex);
list_for_each_safe(start, temp, &driver->dci_client_list) {
entry = list_entry(start, struct diag_dci_client_tbl, track);
if (entry->client_info.token != proc)
@@ -1469,6 +1473,7 @@
info.si_int, stat);
}
}
+ mutex_unlock(&driver->dci_mutex);
}
static int diag_send_dci_pkt(struct diag_cmd_reg_t *entry,
@@ -1942,6 +1947,7 @@
reg_entry.cmd_code_hi = header->subsys_cmd_code;
reg_entry.cmd_code_lo = header->subsys_cmd_code;
+ mutex_lock(&driver->cmd_reg_mutex);
temp_entry = diag_cmd_search(®_entry, ALL_PROC);
if (temp_entry) {
reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
@@ -1953,6 +1959,7 @@
reg_entry.cmd_code, reg_entry.subsys_id,
reg_entry.cmd_code_hi);
}
+ mutex_unlock(&driver->cmd_reg_mutex);
return ret;
}
@@ -2684,10 +2691,12 @@
err:
pr_err("diag: Could not initialize diag DCI buffers");
kfree(driver->apps_dci_buf);
+ driver->apps_dci_buf = NULL;
if (driver->diag_dci_wq)
destroy_workqueue(driver->diag_dci_wq);
kfree(partial_pkt.data);
+ partial_pkt.data = NULL;
mutex_destroy(&driver->dci_mutex);
mutex_destroy(&dci_log_mask_mutex);
mutex_destroy(&dci_event_mask_mutex);
@@ -2707,7 +2716,9 @@
void diag_dci_exit(void)
{
kfree(partial_pkt.data);
+ partial_pkt.data = NULL;
kfree(driver->apps_dci_buf);
+ driver->apps_dci_buf = NULL;
mutex_destroy(&driver->dci_mutex);
mutex_destroy(&dci_log_mask_mutex);
mutex_destroy(&dci_event_mask_mutex);
@@ -2914,22 +2925,30 @@
mutex_destroy(&proc_buf->health_mutex);
if (proc_buf->buf_primary) {
kfree(proc_buf->buf_primary->data);
+ proc_buf->buf_primary->data = NULL;
mutex_destroy(
&proc_buf->buf_primary->data_mutex);
}
kfree(proc_buf->buf_primary);
+ proc_buf->buf_primary = NULL;
if (proc_buf->buf_cmd) {
kfree(proc_buf->buf_cmd->data);
+ proc_buf->buf_cmd->data = NULL;
mutex_destroy(
&proc_buf->buf_cmd->data_mutex);
}
kfree(proc_buf->buf_cmd);
+ proc_buf->buf_cmd = NULL;
}
}
kfree(new_entry->dci_event_mask);
+ new_entry->dci_event_mask = NULL;
kfree(new_entry->dci_log_mask);
+ new_entry->dci_log_mask = NULL;
kfree(new_entry->buffers);
+ new_entry->buffers = NULL;
kfree(new_entry);
+ new_entry = NULL;
}
mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_NO_REG;
@@ -2960,6 +2979,7 @@
* masks and send the masks to peripherals
*/
kfree(entry->dci_log_mask);
+ entry->dci_log_mask = NULL;
diag_dci_invalidate_cumulative_log_mask(token);
if (token == DCI_LOCAL_PROC)
diag_update_userspace_clients(DCI_LOG_MASKS_TYPE);
@@ -2967,6 +2987,7 @@
if (ret != DIAG_DCI_NO_ERROR)
return ret;
kfree(entry->dci_event_mask);
+ entry->dci_event_mask = NULL;
diag_dci_invalidate_cumulative_event_mask(token);
if (token == DCI_LOCAL_PROC)
diag_update_userspace_clients(DCI_EVENT_MASKS_TYPE);
@@ -2981,6 +3002,7 @@
if (!list_empty(&req_entry->track))
list_del(&req_entry->track);
kfree(req_entry);
+ req_entry = NULL;
}
}
@@ -2996,6 +3018,7 @@
buf_entry->data = NULL;
mutex_unlock(&buf_entry->data_mutex);
kfree(buf_entry);
+ buf_entry = NULL;
} else if (buf_entry->buf_type == DCI_BUF_CMD) {
peripheral = buf_entry->data_source;
if (peripheral == APPS_DATA)
@@ -3022,14 +3045,17 @@
mutex_unlock(&buf_entry->data_mutex);
mutex_destroy(&buf_entry->data_mutex);
kfree(buf_entry);
+ buf_entry = NULL;
}
mutex_lock(&proc_buf->buf_primary->data_mutex);
kfree(proc_buf->buf_primary->data);
+ proc_buf->buf_primary->data = NULL;
mutex_unlock(&proc_buf->buf_primary->data_mutex);
mutex_lock(&proc_buf->buf_cmd->data_mutex);
kfree(proc_buf->buf_cmd->data);
+ proc_buf->buf_cmd->data = NULL;
mutex_unlock(&proc_buf->buf_cmd->data_mutex);
mutex_destroy(&proc_buf->health_mutex);
@@ -3037,13 +3063,17 @@
mutex_destroy(&proc_buf->buf_cmd->data_mutex);
kfree(proc_buf->buf_primary);
+ proc_buf->buf_primary = NULL;
kfree(proc_buf->buf_cmd);
+ proc_buf->buf_cmd = NULL;
mutex_unlock(&proc_buf->buf_mutex);
}
mutex_destroy(&entry->write_buf_mutex);
kfree(entry->buffers);
+ entry->buffers = NULL;
kfree(entry);
+ entry = NULL;
if (driver->num_dci_client == 0) {
diag_update_proc_vote(DIAG_PROC_DCI, VOTE_DOWN, token);
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 558e362..13ad402 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -354,8 +354,8 @@
ch->tbl[j].buf = NULL;
ch->tbl[j].len = 0;
ch->tbl[j].ctx = 0;
- spin_lock_init(&(ch->lock));
}
+ spin_lock_init(&(ch->lock));
}
return 0;
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index ac8a6d0..1cf7f52 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/ratelimit.h>
@@ -218,7 +219,8 @@
if (!ch)
return;
- if (!atomic_read(&ch->connected) && driver->usb_connected)
+ if (!atomic_read(&ch->connected) &&
+ driver->usb_connected && diag_mask_param())
diag_clear_masks(NULL);
if (ch && ch->ops && ch->ops->close)
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index ea380fb..d3dde50 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -505,6 +505,7 @@
int ref_count;
int mask_clear;
struct mutex diag_maskclear_mutex;
+ struct mutex diag_notifier_mutex;
struct mutex diagchar_mutex;
struct mutex diag_file_mutex;
wait_queue_head_t wait_q;
@@ -547,7 +548,7 @@
struct mutex diag_id_mutex;
struct mutex cmd_reg_mutex;
uint32_t cmd_reg_count;
- struct mutex diagfwd_channel_mutex;
+ struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
/* Sizes that reflect memory pool sizes */
unsigned int poolsize;
unsigned int poolsize_hdlc;
@@ -666,6 +667,7 @@
void diag_cmd_remove_reg_by_pid(int pid);
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_record_stats(int type, int flag);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index ac777b0..128d6ce 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -143,6 +143,14 @@
static struct timer_list drain_timer;
static int timer_in_progress;
+/*
+ * Diag Mask clear variable
+ * Used for clearing masks upon
+ * USB disconnection and stopping ODL
+ */
+static int diag_mask_clear_param = 1;
+module_param(diag_mask_clear_param, int, 0644);
+
struct diag_apps_data_t {
void *buf;
uint32_t len;
@@ -388,7 +396,10 @@
return ret;
}
-
+int diag_mask_param(void)
+{
+ return diag_mask_clear_param;
+}
void diag_clear_masks(struct diag_md_session_t *info)
{
int ret;
@@ -421,14 +432,17 @@
if (!session_info)
return;
- diag_clear_masks(session_info);
+ if (diag_mask_clear_param)
+ diag_clear_masks(session_info);
mutex_lock(&driver->diag_maskclear_mutex);
driver->mask_clear = 1;
mutex_unlock(&driver->diag_maskclear_mutex);
+ mutex_lock(&driver->diagchar_mutex);
session_peripheral_mask = session_info->peripheral_mask;
diag_md_session_close(session_info);
+ mutex_unlock(&driver->diagchar_mutex);
for (i = 0; i < NUM_MD_SESSIONS; i++)
if (MD_PERIPHERAL_MASK(i) & session_peripheral_mask)
diag_mux_close_peripheral(DIAG_LOCAL_PROC, i);
@@ -701,6 +715,11 @@
list_for_each_safe(start, temp, &driver->cmd_reg_list) {
item = list_entry(start, struct diag_cmd_reg_t, link);
+ if (&item->entry == NULL) {
+ pr_err("diag: In %s, unable to search command\n",
+ __func__);
+ return NULL;
+ }
temp_entry = &item->entry;
if (temp_entry->cmd_code == entry->cmd_code &&
temp_entry->subsys_id == entry->subsys_id &&
@@ -3397,7 +3416,7 @@
static int __init diagchar_init(void)
{
dev_t dev;
- int ret;
+ int ret, i;
pr_debug("diagfwd initializing ..\n");
ret = 0;
@@ -3440,10 +3459,12 @@
mutex_init(&driver->hdlc_disable_mutex);
mutex_init(&driver->diagchar_mutex);
mutex_init(&driver->diag_maskclear_mutex);
+ mutex_init(&driver->diag_notifier_mutex);
mutex_init(&driver->diag_file_mutex);
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
- mutex_init(&driver->diagfwd_channel_mutex);
+ for (i = 0; i < NUM_PERIPHERALS; i++)
+ mutex_init(&driver->diagfwd_channel_mutex[i]);
init_waitqueue_head(&driver->wait_q);
INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index f9dc670d..cd49f00 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1303,6 +1303,8 @@
static int diagfwd_mux_close(int id, int mode)
{
+ uint8_t i;
+
switch (mode) {
case DIAG_USB_MODE:
driver->usb_connected = 0;
@@ -1323,10 +1325,23 @@
*/
} else {
/*
- * With clearing of masks on ODL exit and
- * USB disconnection, closing of the channel is
- * not needed.This enables read and drop of stale packets.
+ * With sysfs parameter to clear masks set,
+ * peripheral masks are cleared on ODL exit and
+ * USB disconnection and buffers are not marked busy.
+ * This enables read and drop of stale packets.
+ *
+ * With sysfs parameter to clear masks cleared,
+ * masks are not cleared and buffers are to be marked
+ * busy to ensure traffic generated by peripheral
+ * are not read
*/
+ if (!(diag_mask_param())) {
+ for (i = 0; i < NUM_PERIPHERALS; i++) {
+ diagfwd_close(i, TYPE_DATA);
+ diagfwd_close(i, TYPE_CMD);
+ }
+ }
+ /* Re enable HDLC encoding */
pr_debug("diag: In %s, re-enabling HDLC encoding\n",
__func__);
mutex_lock(&driver->hdlc_disable_mutex);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index b262897..e13871e 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -359,6 +359,8 @@
feature_mask_len = FEATURE_MASK_LEN;
}
+ diag_cmd_remove_reg_by_proc(peripheral);
+
driver->feature[peripheral].rcvd_feature_mask = 1;
for (i = 0; i < feature_mask_len && read_len < len; i++) {
@@ -660,7 +662,7 @@
if (!new_item)
return -ENOMEM;
kmemleak_not_leak(new_item);
- new_item->process_name = kzalloc(strlen(process_name), GFP_KERNEL);
+ new_item->process_name = kzalloc(strlen(process_name) + 1, GFP_KERNEL);
if (!new_item->process_name) {
kfree(new_item);
new_item = NULL;
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 4f7c1e0..5a8ef04 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -436,9 +436,9 @@
fwd_info->inited = 1;
fwd_info->read_bytes = 0;
fwd_info->write_bytes = 0;
- spin_lock_init(&fwd_info->buf_lock);
- spin_lock_init(&fwd_info->write_buf_lock);
+ mutex_init(&fwd_info->buf_mutex);
mutex_init(&fwd_info->data_mutex);
+ spin_lock_init(&fwd_info->write_buf_lock);
}
}
@@ -452,8 +452,8 @@
fwd_info->ch_open = 0;
fwd_info->read_bytes = 0;
fwd_info->write_bytes = 0;
- spin_lock_init(&fwd_info->buf_lock);
spin_lock_init(&fwd_info->write_buf_lock);
+ mutex_init(&fwd_info->buf_mutex);
mutex_init(&fwd_info->data_mutex);
/*
* This state shouldn't be set for Control channels
@@ -646,7 +646,7 @@
}
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[peripheral]);
fwd_info = &early_init_info[transport][peripheral];
if (fwd_info->p_ops && fwd_info->p_ops->close)
fwd_info->p_ops->close(fwd_info->ctxt);
@@ -670,7 +670,7 @@
diagfwd_late_open(dest_info);
diagfwd_cntl_open(dest_info);
init_fn(peripheral);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[peripheral]);
diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]);
diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]);
}
@@ -983,8 +983,6 @@
}
if (fwd_info->buf_1 && !atomic_read(&fwd_info->buf_1->in_busy)) {
- temp_buf = fwd_info->buf_1;
- atomic_set(&temp_buf->in_busy, 1);
if (driver->feature[fwd_info->peripheral].encode_hdlc &&
(fwd_info->type == TYPE_DATA ||
fwd_info->type == TYPE_CMD)) {
@@ -994,9 +992,11 @@
read_buf = fwd_info->buf_1->data;
read_len = fwd_info->buf_1->len;
}
+ if (read_buf) {
+ temp_buf = fwd_info->buf_1;
+ atomic_set(&temp_buf->in_busy, 1);
+ }
} else if (fwd_info->buf_2 && !atomic_read(&fwd_info->buf_2->in_busy)) {
- temp_buf = fwd_info->buf_2;
- atomic_set(&temp_buf->in_busy, 1);
if (driver->feature[fwd_info->peripheral].encode_hdlc &&
(fwd_info->type == TYPE_DATA ||
fwd_info->type == TYPE_CMD)) {
@@ -1006,6 +1006,10 @@
read_buf = fwd_info->buf_2->data;
read_len = fwd_info->buf_2->len;
}
+ if (read_buf) {
+ temp_buf = fwd_info->buf_2;
+ atomic_set(&temp_buf->in_busy, 1);
+ }
} else {
pr_debug("diag: In %s, both buffers are empty for p: %d, t: %d\n",
__func__, fwd_info->peripheral, fwd_info->type);
@@ -1061,7 +1065,6 @@
void diagfwd_buffers_init(struct diagfwd_info *fwd_info)
{
- unsigned long flags;
if (!fwd_info)
return;
@@ -1072,10 +1075,10 @@
return;
}
- spin_lock_irqsave(&fwd_info->buf_lock, flags);
+ mutex_lock(&fwd_info->buf_mutex);
if (!fwd_info->buf_1) {
fwd_info->buf_1 = kzalloc(sizeof(struct diagfwd_buf_t),
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_1)
goto err;
kmemleak_not_leak(fwd_info->buf_1);
@@ -1083,7 +1086,7 @@
if (!fwd_info->buf_1->data) {
fwd_info->buf_1->data = kzalloc(PERIPHERAL_BUF_SZ +
APF_DIAG_PADDING,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_1->data)
goto err;
fwd_info->buf_1->len = PERIPHERAL_BUF_SZ;
@@ -1095,7 +1098,7 @@
if (fwd_info->type == TYPE_DATA) {
if (!fwd_info->buf_2) {
fwd_info->buf_2 = kzalloc(sizeof(struct diagfwd_buf_t),
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_2)
goto err;
kmemleak_not_leak(fwd_info->buf_2);
@@ -1104,7 +1107,7 @@
if (!fwd_info->buf_2->data) {
fwd_info->buf_2->data = kzalloc(PERIPHERAL_BUF_SZ +
APF_DIAG_PADDING,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_2->data)
goto err;
fwd_info->buf_2->len = PERIPHERAL_BUF_SZ;
@@ -1120,7 +1123,7 @@
fwd_info->buf_1->data_raw =
kzalloc(PERIPHERAL_BUF_SZ +
APF_DIAG_PADDING,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_1->data_raw)
goto err;
fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
@@ -1130,7 +1133,7 @@
fwd_info->buf_2->data_raw =
kzalloc(PERIPHERAL_BUF_SZ +
APF_DIAG_PADDING,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_2->data_raw)
goto err;
fwd_info->buf_2->len_raw = PERIPHERAL_BUF_SZ;
@@ -1144,7 +1147,7 @@
if (!fwd_info->buf_1->data_raw) {
fwd_info->buf_1->data_raw = kzalloc(PERIPHERAL_BUF_SZ +
APF_DIAG_PADDING,
- GFP_ATOMIC);
+ GFP_KERNEL);
if (!fwd_info->buf_1->data_raw)
goto err;
fwd_info->buf_1->len_raw = PERIPHERAL_BUF_SZ;
@@ -1152,22 +1155,21 @@
}
}
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ mutex_unlock(&fwd_info->buf_mutex);
return;
err:
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ mutex_unlock(&fwd_info->buf_mutex);
diagfwd_buffers_exit(fwd_info);
}
static void diagfwd_buffers_exit(struct diagfwd_info *fwd_info)
{
- unsigned long flags;
if (!fwd_info)
return;
- spin_lock_irqsave(&fwd_info->buf_lock, flags);
+ mutex_lock(&fwd_info->buf_mutex);
if (fwd_info->buf_1) {
kfree(fwd_info->buf_1->data);
fwd_info->buf_1->data = NULL;
@@ -1184,7 +1186,7 @@
kfree(fwd_info->buf_2);
fwd_info->buf_2 = NULL;
}
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ mutex_unlock(&fwd_info->buf_mutex);
}
void diagfwd_write_buffers_init(struct diagfwd_info *fwd_info)
diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h
index b8deb38..5884a12 100644
--- a/drivers/char/diag/diagfwd_peripheral.h
+++ b/drivers/char/diag/diagfwd_peripheral.h
@@ -71,8 +71,8 @@
atomic_t opened;
unsigned long read_bytes;
unsigned long write_bytes;
- spinlock_t buf_lock;
spinlock_t write_buf_lock;
+ struct mutex buf_mutex;
struct mutex data_mutex;
void *ctxt;
struct diagfwd_buf_t *buf_1;
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index 6403abc..af8bf00 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -34,14 +34,17 @@
#include "diagfwd_socket.h"
#include "diag_ipc_logging.h"
+#include <soc/qcom/subsystem_notif.h>
+#include <soc/qcom/subsystem_restart.h>
+
#define DIAG_SVC_ID 0x1001
#define MODEM_INST_BASE 0
#define LPASS_INST_BASE 64
#define WCNSS_INST_BASE 128
#define SENSORS_INST_BASE 192
-#define WDSP_INST_BASE 256
-#define CDSP_INST_BASE 320
+#define CDSP_INST_BASE 256
+#define WDSP_INST_BASE 320
#define INST_ID_CNTL 0
#define INST_ID_CMD 1
@@ -50,6 +53,7 @@
#define INST_ID_DCI 4
struct diag_cntl_socket_info *cntl_socket;
+static uint64_t bootup_req[NUM_SOCKET_SUBSYSTEMS];
struct diag_socket_info socket_data[NUM_PERIPHERALS] = {
{
@@ -287,13 +291,6 @@
spin_unlock_irqrestore(&info->lock, flags);
diag_ws_on_notify();
- /*
- * Initialize read buffers for the servers. The servers must read data
- * first to get the address of its clients.
- */
- if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
- diagfwd_buffers_init(info->fwd_ctxt);
-
queue_work(info->wq, &(info->read_work));
wake_up_interruptible(&info->read_wait_q);
}
@@ -422,7 +419,7 @@
return;
}
__socket_open_channel(info);
- DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s exiting\n", info->name);
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s opened client\n", info->name);
}
static void socket_open_server(struct diag_socket_info *info)
@@ -498,6 +495,13 @@
if (!atomic_read(&info->opened))
return;
+ if (bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s is up, stopping cleanup: bootup_req = %d\n",
+ info->name, (int)bootup_req[info->peripheral]);
+ return;
+ }
+
memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc));
diagfwd_channel_close(info->fwd_ctxt);
@@ -614,7 +618,9 @@
case CNTL_CMD_REMOVE_CLIENT:
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s received remove client\n",
info->name);
+ mutex_lock(&driver->diag_notifier_mutex);
socket_close_channel(info);
+ mutex_unlock(&driver->diag_notifier_mutex);
break;
default:
return -EINVAL;
@@ -623,6 +629,25 @@
return 0;
}
+static int restart_notifier_cb(struct notifier_block *this,
+ unsigned long code,
+ void *data);
+
+struct restart_notifier_block {
+ unsigned int processor;
+ char *name;
+ struct notifier_block nb;
+};
+
+static struct restart_notifier_block restart_notifiers[] = {
+ {SOCKET_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
+ {SOCKET_ADSP, "adsp", .nb.notifier_call = restart_notifier_cb},
+ {SOCKET_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
+ {SOCKET_SLPI, "slpi", .nb.notifier_call = restart_notifier_cb},
+ {SOCKET_CDSP, "cdsp", .nb.notifier_call = restart_notifier_cb},
+};
+
+
static void cntl_socket_read_work_fn(struct work_struct *work)
{
union cntl_port_msg msg;
@@ -630,7 +655,6 @@
struct kvec iov = { 0 };
struct msghdr read_msg = { 0 };
-
if (!cntl_socket)
return;
@@ -679,6 +703,9 @@
if (!info)
return;
+ if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
+ diagfwd_buffers_init(info->fwd_ctxt);
+
diagfwd_channel_read(info->fwd_ctxt);
}
@@ -847,8 +874,11 @@
int diag_socket_init(void)
{
int err = 0;
+ int i;
int peripheral = 0;
+ void *handle;
struct diag_socket_info *info = NULL;
+ struct restart_notifier_block *nb;
for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
info = &socket_cntl[peripheral];
@@ -869,6 +899,17 @@
goto fail;
}
+ for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
+ nb = &restart_notifiers[i];
+ if (nb) {
+ handle = subsys_notif_register_notifier(nb->name,
+ &nb->nb);
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "%s: registering notifier for '%s', handle=%p\n",
+ __func__, nb->name, handle);
+ }
+ }
+
register_ipcrtr_af_init_notifier(&socket_notify);
fail:
return err;
@@ -904,6 +945,65 @@
return 0;
}
+static int restart_notifier_cb(struct notifier_block *this, unsigned long code,
+ void *_cmd)
+{
+ struct restart_notifier_block *notifier;
+
+ notifier = container_of(this,
+ struct restart_notifier_block, nb);
+ if (!notifier) {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: invalid notifier block\n", __func__);
+ return NOTIFY_DONE;
+ }
+
+ mutex_lock(&driver->diag_notifier_mutex);
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "%s: ssr for processor %d ('%s')\n",
+ __func__, notifier->processor, notifier->name);
+
+ switch (code) {
+
+ case SUBSYS_BEFORE_SHUTDOWN:
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: SUBSYS_BEFORE_SHUTDOWN\n", __func__);
+ bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
+ break;
+
+ case SUBSYS_AFTER_SHUTDOWN:
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: SUBSYS_AFTER_SHUTDOWN\n", __func__);
+ break;
+
+ case SUBSYS_BEFORE_POWERUP:
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: SUBSYS_BEFORE_POWERUP\n", __func__);
+ break;
+
+ case SUBSYS_AFTER_POWERUP:
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: SUBSYS_AFTER_POWERUP\n", __func__);
+ if (!bootup_req[notifier->processor]) {
+ bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
+ break;
+ }
+ bootup_req[notifier->processor] = PEPIPHERAL_SSR_UP;
+ break;
+
+ default:
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: code: %lu\n", code);
+ break;
+ }
+ mutex_unlock(&driver->diag_notifier_mutex);
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: bootup_req[%s] = %d\n",
+ notifier->name, (int)bootup_req[notifier->processor]);
+
+ return NOTIFY_DONE;
+}
+
int diag_socket_init_peripheral(uint8_t peripheral)
{
struct diag_socket_info *info = NULL;
@@ -986,9 +1086,9 @@
(info->data_ready > 0) || (!info->hdl) ||
(atomic_read(&info->diag_state) == 0));
if (err) {
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return -ERESTARTSYS;
}
@@ -1000,9 +1100,9 @@
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"%s closing read thread. diag state is closed\n",
info->name);
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return 0;
}
@@ -1069,10 +1169,10 @@
if (total_recd > 0) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n",
info->name, total_recd);
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
err = diagfwd_channel_read_done(info->fwd_ctxt,
buf, total_recd);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
if (err)
goto fail;
} else {
@@ -1085,9 +1185,9 @@
return 0;
fail:
- mutex_lock(&driver->diagfwd_channel_mutex);
+ mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
- mutex_unlock(&driver->diagfwd_channel_mutex);
+ mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
return -EIO;
}
diff --git a/drivers/char/diag/diagfwd_socket.h b/drivers/char/diag/diagfwd_socket.h
index a2b922a..a9487b1 100644
--- a/drivers/char/diag/diagfwd_socket.h
+++ b/drivers/char/diag/diagfwd_socket.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,10 +24,24 @@
#define PORT_TYPE_SERVER 0
#define PORT_TYPE_CLIENT 1
+#define PEPIPHERAL_AFTER_BOOT 0
+#define PEPIPHERAL_SSR_DOWN 1
+#define PEPIPHERAL_SSR_UP 2
+
#define CNTL_CMD_NEW_SERVER 4
#define CNTL_CMD_REMOVE_SERVER 5
#define CNTL_CMD_REMOVE_CLIENT 6
+enum {
+ SOCKET_MODEM,
+ SOCKET_ADSP,
+ SOCKET_WCNSS,
+ SOCKET_SLPI,
+ SOCKET_CDSP,
+ SOCKET_APPS,
+ NUM_SOCKET_SUBSYSTEMS,
+};
+
struct diag_socket_info {
uint8_t peripheral;
uint8_t type;
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 200dab5..18849f4 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -337,7 +337,6 @@
config HW_RANDOM_MSM
tristate "Qualcomm SoCs Random Number Generator support"
depends on HW_RANDOM && ARCH_QCOM
- default HW_RANDOM
---help---
This driver provides kernel-side support for the Random Number
Generator hardware found on Qualcomm SoCs.
@@ -347,6 +346,20 @@
If unsure, say Y.
+config HW_RANDOM_MSM_LEGACY
+ tristate "QTI MSM Random Number Generator support (LEGACY)"
+ depends on HW_RANDOM && ARCH_QCOM
+ select CRYPTO_AES
+ select CRYPTO_ECB
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on QTI MSM SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called msm_rng.
+
+ If unsure, say Y.
+
config HW_RANDOM_ST
tristate "ST Microelectronics HW Random Number Generator support"
depends on HW_RANDOM && ARCH_STI
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5f52b1e..637adb5 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -30,6 +30,7 @@
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o
+obj-$(CONFIG_HW_RANDOM_MSM_LEGACY) += msm_rng.o
obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
new file mode 100644
index 0000000..7641a6a
--- /dev/null
+++ b/drivers/char/hw_random/msm_rng.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2011-2013, 2015, 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <soc/qcom/socinfo.h>
+#include <linux/msm-bus.h>
+#include <linux/qrng.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/crypto.h>
+#include <crypto/internal/rng.h>
+
+#include <linux/platform_data/qcom_crypto_device.h>
+
+
+
+#define DRIVER_NAME "msm_rng"
+
+/* Device specific register offsets */
+#define PRNG_DATA_OUT_OFFSET 0x0000
+#define PRNG_STATUS_OFFSET 0x0004
+#define PRNG_LFSR_CFG_OFFSET 0x0100
+#define PRNG_CONFIG_OFFSET 0x0104
+
+/* Device specific register masks and config values */
+#define PRNG_LFSR_CFG_MASK 0xFFFF0000
+#define PRNG_LFSR_CFG_CLOCKS 0x0000DDDD
+#define PRNG_CONFIG_MASK 0xFFFFFFFD
+#define PRNG_HW_ENABLE 0x00000002
+
+#define MAX_HW_FIFO_DEPTH 16 /* FIFO is 16 words deep */
+#define MAX_HW_FIFO_SIZE (MAX_HW_FIFO_DEPTH * 4) /* FIFO is 32 bits wide */
+
+struct msm_rng_device {
+ struct platform_device *pdev;
+ void __iomem *base;
+ struct clk *prng_clk;
+ uint32_t qrng_perf_client;
+ struct mutex rng_lock;
+};
+
+struct msm_rng_device msm_rng_device_info;
+static struct msm_rng_device *msm_rng_dev_cached;
+struct mutex cached_rng_lock;
+static long msm_rng_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case QRNG_IOCTL_RESET_BUS_BANDWIDTH:
+ pr_info("calling msm_rng_bus_scale(LOW)\n");
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_device_info.qrng_perf_client, 0);
+ if (ret)
+ pr_err("failed qrng_reset_bus_bw, ret = %ld\n", ret);
+ break;
+ default:
+ pr_err("Unsupported IOCTL call");
+ break;
+ }
+ return ret;
+}
+
+/*
+ *
+ * This function calls hardware random bit generator directory and retuns it
+ * back to caller
+ *
+ */
+static int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev,
+ void *data, size_t max)
+{
+ struct platform_device *pdev;
+ void __iomem *base;
+ size_t currsize = 0;
+ u32 val;
+ u32 *retdata = data;
+ int ret;
+ int failed = 0;
+
+ pdev = msm_rng_dev->pdev;
+ base = msm_rng_dev->base;
+
+ /* no room for word data */
+ if (max < 4)
+ return 0;
+
+ mutex_lock(&msm_rng_dev->rng_lock);
+
+ if (msm_rng_dev->qrng_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_dev->qrng_perf_client, 1);
+ if (ret)
+ pr_err("bus_scale_client_update_req failed!\n");
+ }
+ /* enable PRNG clock */
+ ret = clk_prepare_enable(msm_rng_dev->prng_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable clock in callback\n");
+ goto err;
+ }
+ /* read random data from h/w */
+ do {
+ /* check status bit if data is available */
+ while (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
+ & 0x00000001)) {
+ if (failed == 10) {
+ pr_err("Data not available after retry\n");
+ break;
+ }
+ pr_err("msm_rng:Data not available!\n");
+ msleep_interruptible(10);
+ failed++;
+ }
+
+ /* read FIFO */
+ val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
+ if (!val)
+ break; /* no data to read so just bail */
+
+ /* write data back to callers pointer */
+ *(retdata++) = val;
+ currsize += 4;
+ /* make sure we stay on 32bit boundary */
+ if ((max - currsize) < 4)
+ break;
+
+ } while (currsize < max);
+
+ /* vote to turn off clock */
+ clk_disable_unprepare(msm_rng_dev->prng_clk);
+err:
+ if (msm_rng_dev->qrng_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_dev->qrng_perf_client, 0);
+ if (ret)
+ pr_err("bus_scale_client_update_req failed!\n");
+ }
+ mutex_unlock(&msm_rng_dev->rng_lock);
+
+ val = 0L;
+ return currsize;
+}
+static int msm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct msm_rng_device *msm_rng_dev;
+ int rv = 0;
+
+ msm_rng_dev = (struct msm_rng_device *)rng->priv;
+ rv = msm_rng_direct_read(msm_rng_dev, data, max);
+
+ return rv;
+}
+
+
+static struct hwrng msm_rng = {
+ .name = DRIVER_NAME,
+ .read = msm_rng_read,
+ .quality = 700,
+};
+
+static int msm_rng_enable_hw(struct msm_rng_device *msm_rng_dev)
+{
+ unsigned long val = 0;
+ unsigned long reg_val = 0;
+ int ret = 0;
+
+ if (msm_rng_dev->qrng_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_dev->qrng_perf_client, 1);
+ if (ret)
+ pr_err("bus_scale_client_update_req failed!\n");
+ }
+ /* Enable the PRNG CLK */
+ ret = clk_prepare_enable(msm_rng_dev->prng_clk);
+ if (ret) {
+ dev_err(&(msm_rng_dev->pdev)->dev,
+ "failed to enable clock in probe\n");
+ return -EPERM;
+ }
+
+ /* Enable PRNG h/w only if it is NOT ON */
+ val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
+ PRNG_HW_ENABLE;
+ /* PRNG H/W is not ON */
+ if (val != PRNG_HW_ENABLE) {
+ val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+ val &= PRNG_LFSR_CFG_MASK;
+ val |= PRNG_LFSR_CFG_CLOCKS;
+ writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+ /* The PRNG CONFIG register should be first written */
+ mb();
+
+ reg_val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET)
+ & PRNG_CONFIG_MASK;
+ reg_val |= PRNG_HW_ENABLE;
+ writel_relaxed(reg_val, msm_rng_dev->base + PRNG_CONFIG_OFFSET);
+
+ /* The PRNG clk should be disabled only after we enable the
+ * PRNG h/w by writing to the PRNG CONFIG register.
+ */
+ mb();
+ }
+ clk_disable_unprepare(msm_rng_dev->prng_clk);
+
+ if (msm_rng_dev->qrng_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_dev->qrng_perf_client, 0);
+ if (ret)
+ pr_err("bus_scale_client_update_req failed!\n");
+ }
+
+ return 0;
+}
+
+static const struct file_operations msm_rng_fops = {
+ .unlocked_ioctl = msm_rng_ioctl,
+};
+static struct class *msm_rng_class;
+static struct cdev msm_rng_cdev;
+
+static int msm_rng_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct msm_rng_device *msm_rng_dev = NULL;
+ void __iomem *base = NULL;
+ bool configure_qrng = true;
+ int error = 0;
+ int ret = 0;
+ struct device *dev;
+
+ struct msm_bus_scale_pdata *qrng_platform_support = NULL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "invalid address\n");
+ error = -EFAULT;
+ goto err_exit;
+ }
+
+ msm_rng_dev = kzalloc(sizeof(struct msm_rng_device), GFP_KERNEL);
+ if (!msm_rng_dev) {
+ error = -ENOMEM;
+ goto err_exit;
+ }
+
+ base = ioremap(res->start, resource_size(res));
+ if (!base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ error = -ENOMEM;
+ goto err_iomap;
+ }
+ msm_rng_dev->base = base;
+
+ /* create a handle for clock control */
+ if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
+ "qcom,msm-rng-iface-clk")))
+ msm_rng_dev->prng_clk = clk_get(&pdev->dev,
+ "iface_clk");
+ else
+ msm_rng_dev->prng_clk = clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(msm_rng_dev->prng_clk)) {
+ dev_err(&pdev->dev, "failed to register clock source\n");
+ error = -EPERM;
+ goto err_clk_get;
+ }
+
+ /* save away pdev and register driver data */
+ msm_rng_dev->pdev = pdev;
+ platform_set_drvdata(pdev, msm_rng_dev);
+
+ if (pdev->dev.of_node) {
+ /* Register bus client */
+ qrng_platform_support = msm_bus_cl_get_pdata(pdev);
+ msm_rng_dev->qrng_perf_client = msm_bus_scale_register_client(
+ qrng_platform_support);
+ msm_rng_device_info.qrng_perf_client =
+ msm_rng_dev->qrng_perf_client;
+ if (!msm_rng_dev->qrng_perf_client)
+ pr_err("Unable to register bus client\n");
+ }
+
+ /* Enable rng h/w for the targets which can access the entire
+ * address space of PRNG.
+ */
+ if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
+ "qcom,no-qrng-config")))
+ configure_qrng = false;
+ if (configure_qrng) {
+ error = msm_rng_enable_hw(msm_rng_dev);
+ if (error)
+ goto rollback_clk;
+ }
+
+ mutex_init(&msm_rng_dev->rng_lock);
+ mutex_init(&cached_rng_lock);
+
+ /* register with hwrng framework */
+ msm_rng.priv = (unsigned long) msm_rng_dev;
+ error = hwrng_register(&msm_rng);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register hwrng\n");
+ error = -EPERM;
+ goto rollback_clk;
+ }
+ ret = register_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME, &msm_rng_fops);
+
+ msm_rng_class = class_create(THIS_MODULE, "msm-rng");
+ if (IS_ERR(msm_rng_class)) {
+ pr_err("class_create failed\n");
+ return PTR_ERR(msm_rng_class);
+ }
+
+ dev = device_create(msm_rng_class, NULL, MKDEV(QRNG_IOC_MAGIC, 0),
+ NULL, "msm-rng");
+ if (IS_ERR(dev)) {
+ pr_err("Device create failed\n");
+ error = PTR_ERR(dev);
+ goto unregister_chrdev;
+ }
+ cdev_init(&msm_rng_cdev, &msm_rng_fops);
+ msm_rng_dev_cached = msm_rng_dev;
+ return error;
+
+unregister_chrdev:
+ unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
+rollback_clk:
+ clk_put(msm_rng_dev->prng_clk);
+err_clk_get:
+ iounmap(msm_rng_dev->base);
+err_iomap:
+ kzfree(msm_rng_dev);
+err_exit:
+ return error;
+}
+
+static int msm_rng_remove(struct platform_device *pdev)
+{
+ struct msm_rng_device *msm_rng_dev = platform_get_drvdata(pdev);
+
+ unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
+ hwrng_unregister(&msm_rng);
+ clk_put(msm_rng_dev->prng_clk);
+ iounmap(msm_rng_dev->base);
+ platform_set_drvdata(pdev, NULL);
+ if (msm_rng_dev->qrng_perf_client)
+ msm_bus_scale_unregister_client(msm_rng_dev->qrng_perf_client);
+
+ kzfree(msm_rng_dev);
+ msm_rng_dev_cached = NULL;
+ return 0;
+}
+
+static int qrng_get_random(struct crypto_rng *tfm, const u8 *src,
+ unsigned int slen, u8 *rdata,
+ unsigned int dlen)
+{
+ int sizeread = 0;
+ int rv = -EFAULT;
+
+ if (!msm_rng_dev_cached) {
+ pr_err("%s: msm_rng_dev is not initialized.\n", __func__);
+ rv = -ENODEV;
+ goto err_exit;
+ }
+
+ if (!rdata) {
+ pr_err("%s: data buffer is null!\n", __func__);
+ rv = -EINVAL;
+ goto err_exit;
+ }
+
+ if (signal_pending(current) ||
+ mutex_lock_interruptible(&cached_rng_lock)) {
+ pr_err("%s: mutex lock interrupted!\n", __func__);
+ rv = -ERESTARTSYS;
+ goto err_exit;
+ }
+ sizeread = msm_rng_direct_read(msm_rng_dev_cached, rdata, dlen);
+
+ if (sizeread == dlen)
+ rv = 0;
+
+ mutex_unlock(&cached_rng_lock);
+err_exit:
+ return rv;
+
+}
+
+static int qrng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
+{
+ return 0;
+}
+
+static struct rng_alg rng_algs[] = { {
+ .generate = qrng_get_random,
+ .seed = qrng_reset,
+ .seedsize = 0,
+ .base = {
+ .cra_name = "qrng",
+ .cra_driver_name = "fips_hw_qrng",
+ .cra_priority = 300,
+ .cra_ctxsize = 0,
+ .cra_module = THIS_MODULE,
+ }
+} };
+
+static const struct of_device_id qrng_match[] = {
+ { .compatible = "qcom,msm-rng",
+ },
+ {}
+};
+
+static struct platform_driver rng_driver = {
+ .probe = msm_rng_probe,
+ .remove = msm_rng_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = qrng_match,
+ }
+};
+
+static int __init msm_rng_init(void)
+{
+ int ret;
+
+ msm_rng_dev_cached = NULL;
+ ret = platform_driver_register(&rng_driver);
+ if (ret) {
+ pr_err("%s: platform_driver_register error:%d\n",
+ __func__, ret);
+ goto err_exit;
+ }
+ ret = crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
+ if (ret) {
+ pr_err("%s: crypto_register_algs error:%d\n",
+ __func__, ret);
+ goto err_exit;
+ }
+
+err_exit:
+ return ret;
+}
+
+module_init(msm_rng_init);
+
+static void __exit msm_rng_exit(void)
+{
+ crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
+ platform_driver_unregister(&rng_driver);
+}
+
+module_exit(msm_rng_exit);
+
+MODULE_DESCRIPTION("QTI MSM Random Number Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6d9cc2d..7e4a9d1 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -60,6 +60,10 @@
#endif
#ifdef CONFIG_STRICT_DEVMEM
+static inline int page_is_allowed(unsigned long pfn)
+{
+ return devmem_is_allowed(pfn);
+}
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
u64 from = ((u64)pfn) << PAGE_SHIFT;
@@ -75,6 +79,10 @@
return 1;
}
#else
+static inline int page_is_allowed(unsigned long pfn)
+{
+ return 1;
+}
static inline int range_is_allowed(unsigned long pfn, unsigned long size)
{
return 1;
@@ -122,23 +130,31 @@
while (count > 0) {
unsigned long remaining;
+ int allowed;
sz = size_inside_page(p, count);
- if (!range_is_allowed(p >> PAGE_SHIFT, count))
+ allowed = page_is_allowed(p >> PAGE_SHIFT);
+ if (!allowed)
return -EPERM;
+ if (allowed == 2) {
+ /* Show zeros for restricted memory. */
+ remaining = clear_user(buf, sz);
+ } else {
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur.
+ */
+ ptr = xlate_dev_mem_ptr(p);
+ if (!ptr)
+ return -EFAULT;
- /*
- * On ia64 if a page has been mapped somewhere as uncached, then
- * it must also be accessed uncached by the kernel or data
- * corruption may occur.
- */
- ptr = xlate_dev_mem_ptr(p);
- if (!ptr)
- return -EFAULT;
+ remaining = copy_to_user(buf, ptr, sz);
- remaining = copy_to_user(buf, ptr, sz);
- unxlate_dev_mem_ptr(p, ptr);
+ unxlate_dev_mem_ptr(p, ptr);
+ }
+
if (remaining)
return -EFAULT;
@@ -181,30 +197,36 @@
#endif
while (count > 0) {
+ int allowed;
+
sz = size_inside_page(p, count);
- if (!range_is_allowed(p >> PAGE_SHIFT, sz))
+ allowed = page_is_allowed(p >> PAGE_SHIFT);
+ if (!allowed)
return -EPERM;
- /*
- * On ia64 if a page has been mapped somewhere as uncached, then
- * it must also be accessed uncached by the kernel or data
- * corruption may occur.
- */
- ptr = xlate_dev_mem_ptr(p);
- if (!ptr) {
- if (written)
- break;
- return -EFAULT;
- }
+ /* Skip actual writing when a page is marked as restricted. */
+ if (allowed == 1) {
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur.
+ */
+ ptr = xlate_dev_mem_ptr(p);
+ if (!ptr) {
+ if (written)
+ break;
+ return -EFAULT;
+ }
- copied = copy_from_user(ptr, buf, sz);
- unxlate_dev_mem_ptr(p, ptr);
- if (copied) {
- written += sz - copied;
- if (written)
- break;
- return -EFAULT;
+ copied = copy_from_user(ptr, buf, sz);
+ unxlate_dev_mem_ptr(p, ptr);
+ if (copied) {
+ written += sz - copied;
+ if (written)
+ break;
+ return -EFAULT;
+ }
}
buf += sz;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 5649234..471a301 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1136,6 +1136,8 @@
{
struct port *port;
struct scatterlist sg[1];
+ void *data;
+ int ret;
if (unlikely(early_put_chars))
return early_put_chars(vtermno, buf, count);
@@ -1144,8 +1146,14 @@
if (!port)
return -EPIPE;
- sg_init_one(sg, buf, count);
- return __send_to_port(port, sg, 1, count, (void *)buf, false);
+ data = kmemdup(buf, count, GFP_ATOMIC);
+ if (!data)
+ return -ENOMEM;
+
+ sg_init_one(sg, data, count);
+ ret = __send_to_port(port, sg, 1, count, data, false);
+ kfree(data);
+ return ret;
}
/*
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ece2f00..b248b1b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -71,6 +71,8 @@
bool orphan;
unsigned int enable_count;
unsigned int prepare_count;
+ bool need_handoff_enable;
+ bool need_handoff_prepare;
unsigned long min_rate;
unsigned long max_rate;
unsigned long accuracy;
@@ -997,6 +999,19 @@
hlist_for_each_entry(child, &core->children, child_node)
clk_unprepare_unused_subtree(child);
+ /*
+ * setting CLK_ENABLE_HAND_OFF flag triggers this conditional
+ *
+ * need_handoff_prepare implies this clk was already prepared by
+ * __clk_init. now we have a proper user, so unset the flag in our
+ * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h
+ * for details.
+ */
+ if (core->need_handoff_prepare) {
+ core->need_handoff_prepare = false;
+ clk_core_unprepare(core);
+ }
+
if (core->prepare_count)
return;
@@ -1023,6 +1038,21 @@
hlist_for_each_entry(child, &core->children, child_node)
clk_disable_unused_subtree(child);
+ /*
+ * setting CLK_ENABLE_HAND_OFF flag triggers this conditional
+ *
+ * need_handoff_enable implies this clk was already enabled by
+ * __clk_init. now we have a proper user, so unset the flag in our
+ * internal bookkeeping. See CLK_ENABLE_HAND_OFF flag in clk-provider.h
+ * for details.
+ */
+ if (core->need_handoff_enable) {
+ core->need_handoff_enable = false;
+ flags = clk_enable_lock();
+ clk_core_disable(core);
+ clk_enable_unlock(flags);
+ }
+
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_prepare_enable(core->parent);
@@ -3140,6 +3170,37 @@
clk_enable_unlock(flags);
}
+ /*
+ * enable clocks with the CLK_ENABLE_HAND_OFF flag set
+ *
+ * This flag causes the framework to enable the clock at registration
+ * time, which is sometimes necessary for clocks that would cause a
+ * system crash when gated (e.g. cpu, memory, etc). The prepare_count
+ * is migrated over to the first clk consumer to call clk_prepare().
+ * Similarly the clk's enable_count is migrated to the first consumer
+ * to call clk_enable().
+ */
+ if (core->flags & CLK_ENABLE_HAND_OFF) {
+ unsigned long flags;
+
+ /*
+ * Few clocks might have hardware gating which would be
+ * required to be ON before prepare/enabling the clocks. So
+ * check if the clock has been turned ON earlier and we should
+ * prepare/enable those clocks.
+ */
+ if (clk_core_is_enabled(core)) {
+ core->need_handoff_prepare = true;
+ core->need_handoff_enable = true;
+ ret = clk_core_prepare(core);
+ if (ret)
+ goto out;
+ flags = clk_enable_lock();
+ clk_core_enable(core);
+ clk_enable_unlock(flags);
+ }
+ }
+
kref_init(&core->ref);
out:
clk_prepare_unlock();
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7226dd3..46a3d27 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -225,4 +225,13 @@
sdm845 devices.
Say Y if you want to support graphics controller devices.
+config MSM_CLK_AOP_QMP
+ tristate "AOP QMP Clock Driver"
+ depends on COMMON_CLK_QCOM && MSM_QMP
+ help
+ Always On Processor manages few shared clocks on some Qualcomm
+ Technologies, Inc. SoCs. It accepts requests from other hardware
+ subsystems via QMP mailboxes.
+ Say Y to support the clocks managed by AOP on platforms such as sdm845.
+
source "drivers/clk/qcom/mdss/Kconfig"
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 1d042cd..930e281 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -24,6 +24,7 @@
obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
obj-$(CONFIG_MSM_CAMCC_SDM845) += camcc-sdm845.o
+obj-$(CONFIG_MSM_CLK_AOP_QMP) += clk-aop-qmp.o
obj-$(CONFIG_MSM_CLK_RPMH) += clk-rpmh.o
obj-$(CONFIG_MSM_DISPCC_SDM845) += dispcc-sdm845.o
obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
diff --git a/drivers/clk/qcom/camcc-sdm845.c b/drivers/clk/qcom/camcc-sdm845.c
index a274975..6296c40 100644
--- a/drivers/clk/qcom/camcc-sdm845.c
+++ b/drivers/clk/qcom/camcc-sdm845.c
@@ -764,6 +764,7 @@
};
static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
+ F(24000000, P_CAM_CC_PLL3_OUT_EVEN, 16, 0, 0),
F(33333333, P_CAM_CC_PLL0_OUT_EVEN, 2, 1, 9),
F(34285714, P_CAM_CC_PLL2_OUT_EVEN, 14, 0, 0),
{ }
@@ -1114,19 +1115,6 @@
},
};
-static struct clk_branch cam_cc_debug_clk = {
- .halt_reg = 0xc008,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0xc008,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "cam_cc_debug_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch cam_cc_fd_core_clk = {
.halt_reg = 0xb0c8,
.halt_check = BRANCH_HALT,
@@ -1763,7 +1751,6 @@
[CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
[CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
[CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
- [CAM_CC_DEBUG_CLK] = &cam_cc_debug_clk.clkr,
[CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
[CAM_CC_FD_CORE_CLK] = &cam_cc_fd_core_clk.clkr,
[CAM_CC_FD_CORE_CLK_SRC] = &cam_cc_fd_core_clk_src.clkr,
diff --git a/drivers/clk/qcom/clk-aop-qmp.c b/drivers/clk/qcom/clk-aop-qmp.c
new file mode 100644
index 0000000..f698a55
--- /dev/null
+++ b/drivers/clk/qcom/clk-aop-qmp.c
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/mailbox_client.h>
+#include <dt-bindings/clock/qcom,aop-qmp.h>
+
+#define MAX_LEN 96
+#define MBOX_TOUT_MS 1000
+
+struct qmp_pkt {
+ u32 size;
+ void *data;
+};
+
+#define DEFINE_CLK_AOP_QMP(_name, _class, _res, _estate, _dstate) \
+ static struct clk_aop_qmp _name = { \
+ .msg.class = #_class, \
+ .msg.res = #_res, \
+ .enable_state = _estate, \
+ .disable_state = _dstate, \
+ .hw.init = &(struct clk_init_data){ \
+ .ops = &aop_qmp_clk_ops, \
+ .name = #_name, \
+ .num_parents = 0, \
+ .flags = CLK_ENABLE_HAND_OFF, \
+ }, \
+ }
+
+#define to_aop_qmp_clk(hw) container_of(hw, struct clk_aop_qmp, hw)
+
+/*
+ * struct qmp_mbox_msg - mailbox data to QMP
+ * @class: identifies the class.
+ * @res: identifies the resource in the class
+ * @level: identifies the level for the resource.
+ */
+struct qmp_mbox_msg {
+ char class[MAX_LEN];
+ char res[MAX_LEN];
+ int level;
+};
+
+/*
+ * struct clk_aop_qmp - AOP clock
+ * @dev: The device that corresponds to this clock.
+ * @hw: The clock hardware for this clock.
+ * @cl: The client mailbox for this clock.
+ * @mbox: The mbox controller for this clock.
+ * @level: The clock level for this clock.
+ * @enable_state: The clock state when this clock is prepared.
+ * @disable_state: The clock state when this clock is unprepared.
+ * @msg: QMP data associated with this clock.
+ * @enabled: Status of the clock enable.
+ */
+struct clk_aop_qmp {
+ struct device *dev;
+ struct clk_hw hw;
+ struct mbox_client cl;
+ struct mbox_chan *mbox;
+ int level;
+ int enable_state;
+ int disable_state;
+ struct qmp_mbox_msg msg;
+ bool enabled;
+};
+
+static DEFINE_MUTEX(clk_aop_lock);
+
+static unsigned long clk_aop_qmp_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_aop_qmp *clk = to_aop_qmp_clk(hw);
+
+ return clk->level;
+}
+
+static long clk_aop_qmp_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return rate;
+}
+
+static int clk_aop_qmp_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ char mbox_msg[MAX_LEN];
+ struct qmp_pkt pkt;
+ struct clk_aop_qmp *clk = to_aop_qmp_clk(hw);
+ int ret = 0;
+
+ mutex_lock(&clk_aop_lock);
+
+ snprintf(mbox_msg, MAX_LEN, "{class: %s, res: %s, val: %ld}",
+ clk->msg.class, clk->msg.res, rate);
+ pkt.size = MAX_LEN;
+ pkt.data = mbox_msg;
+
+ ret = mbox_send_message(clk->mbox, &pkt);
+ if (ret < 0) {
+ pr_err("Failed to send set rate request of %lu for %s, ret %d\n",
+ rate, clk_hw_get_name(hw), ret);
+ goto err;
+ } else
+ /* Success: update the return value */
+ ret = 0;
+
+ /* update the current clock level once the mailbox message is sent */
+ clk->level = rate;
+err:
+ mutex_unlock(&clk_aop_lock);
+
+ return ret;
+}
+
+static int clk_aop_qmp_prepare(struct clk_hw *hw)
+{
+ char mbox_msg[MAX_LEN];
+ unsigned long rate;
+ int ret = 0;
+ struct qmp_pkt pkt;
+ struct clk_aop_qmp *clk = to_aop_qmp_clk(hw);
+
+ mutex_lock(&clk_aop_lock);
+
+ if (clk->level)
+ rate = clk->level;
+ else
+ rate = clk->enable_state;
+
+ snprintf(mbox_msg, MAX_LEN, "{class: %s, res: %s, val: %ld}",
+ clk->msg.class, clk->msg.res, rate);
+ pkt.size = MAX_LEN;
+ pkt.data = mbox_msg;
+
+ ret = mbox_send_message(clk->mbox, &pkt);
+ if (ret < 0) {
+ pr_err("Failed to send clk prepare request for %s, ret %d\n",
+ clk_hw_get_name(hw), ret);
+ goto err;
+ } else
+ /* Success: update the return value */
+ ret = 0;
+
+ /* update the current clock level once the mailbox message is sent */
+ clk->level = rate;
+
+ clk->enabled = true;
+err:
+ mutex_unlock(&clk_aop_lock);
+
+ return ret;
+}
+
+static void clk_aop_qmp_unprepare(struct clk_hw *hw)
+{
+ char mbox_msg[MAX_LEN];
+ unsigned long rate;
+ int ret = 0;
+ struct qmp_pkt pkt;
+ struct clk_aop_qmp *clk = to_aop_qmp_clk(hw);
+
+ mutex_lock(&clk_aop_lock);
+
+ rate = clk->disable_state;
+
+ snprintf(mbox_msg, MAX_LEN, "{class: %s, res: %s, val: %ld}",
+ clk->msg.class, clk->msg.res, rate);
+ pkt.size = MAX_LEN;
+ pkt.data = mbox_msg;
+
+ ret = mbox_send_message(clk->mbox, &pkt);
+ if (ret < 0) {
+ pr_err("Failed to send clk unprepare request for %s, ret %d\n",
+ clk_hw_get_name(hw), ret);
+ goto err;
+ }
+
+ clk->enabled = false;
+err:
+ mutex_unlock(&clk_aop_lock);
+}
+
+static int clk_aop_qmp_is_enabled(struct clk_hw *hw)
+{
+ struct clk_aop_qmp *clk = to_aop_qmp_clk(hw);
+
+ return clk->enabled;
+}
+
+static const struct clk_ops aop_qmp_clk_ops = {
+ .prepare = clk_aop_qmp_prepare,
+ .unprepare = clk_aop_qmp_unprepare,
+ .recalc_rate = clk_aop_qmp_recalc_rate,
+ .set_rate = clk_aop_qmp_set_rate,
+ .round_rate = clk_aop_qmp_round_rate,
+ .is_enabled = clk_aop_qmp_is_enabled,
+};
+
+DEFINE_CLK_AOP_QMP(qdss_qmp_clk, clock, qdss,
+ QDSS_CLK_LEVEL_DYNAMIC, QDSS_CLK_LEVEL_OFF);
+
+static struct clk_hw *aop_qmp_clk_hws[] = {
+ [QDSS_CLK] = &qdss_qmp_clk.hw,
+};
+
+static int qmp_update_client(struct clk_hw *hw, struct device *dev,
+ struct mbox_chan *mbox)
+{
+ struct clk_aop_qmp *clk_aop = to_aop_qmp_clk(hw);
+
+ /* Use mailbox client with blocking mode */
+ clk_aop->cl.dev = dev;
+ clk_aop->cl.tx_block = true;
+ clk_aop->cl.tx_tout = MBOX_TOUT_MS;
+ clk_aop->cl.knows_txdone = false;
+
+ if (mbox) {
+ clk_aop->mbox = mbox;
+ return 0;
+ }
+
+ /* Allocate mailbox channel */
+ mbox = clk_aop->mbox = mbox_request_channel(&clk_aop->cl, 0);
+ if (IS_ERR(clk_aop->mbox) && PTR_ERR(clk_aop->mbox) != -EPROBE_DEFER) {
+ dev_err(dev, "Failed to get mailbox channel %pK %ld\n",
+ mbox, PTR_ERR(mbox));
+ return PTR_ERR(clk_aop->mbox);
+ }
+
+ return 0;
+}
+
+static int aop_qmp_clk_probe(struct platform_device *pdev)
+{
+ struct clk *clk;
+ struct device_node *np = pdev->dev.of_node;
+ struct mbox_chan *mbox = NULL;
+ int num_clks = ARRAY_SIZE(aop_qmp_clk_hws);
+ int ret = 0, i = 0;
+
+ /*
+ * Allocate mbox channel for the first clock client. The same channel
+ * would be used for the rest of the clock clients.
+ */
+ ret = qmp_update_client(aop_qmp_clk_hws[i], &pdev->dev, mbox);
+ if (ret < 0)
+ return ret;
+
+ for (i = 1; i < num_clks; i++) {
+ ret = qmp_update_client(aop_qmp_clk_hws[i], &pdev->dev, mbox);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to update QMP client %d\n",
+ ret);
+ goto fail;
+ }
+ }
+
+ for (i = 0; i < num_clks; i++) {
+ ret = clk_aop_qmp_prepare(aop_qmp_clk_hws[i]);
+ if (ret < 0)
+ goto fail;
+ }
+
+ for (i = 0; i < num_clks; i++) {
+ clk = devm_clk_register(&pdev->dev, aop_qmp_clk_hws[i]);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto fail;
+ }
+ }
+
+ ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register clock provider\n");
+ goto fail;
+ }
+
+ dev_info(&pdev->dev, "Registered clocks with AOP\n");
+
+ return ret;
+fail:
+ mbox_free_channel(mbox);
+
+ return ret;
+}
+
+static const struct of_device_id aop_qmp_clk_of_match[] = {
+ { .compatible = "qcom,aop-qmp-clk", },
+ {}
+};
+
+static struct platform_driver aop_qmp_clk_driver = {
+ .driver = {
+ .name = "qmp-aop-clk",
+ .of_match_table = aop_qmp_clk_of_match,
+ },
+ .probe = aop_qmp_clk_probe,
+};
+
+static int __init aop_qmp_clk_init(void)
+{
+ return platform_driver_register(&aop_qmp_clk_driver);
+}
+subsys_initcall(aop_qmp_clk_init);
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 8bbf55c..035d337 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -509,34 +509,22 @@
.set_rate = l3_clk_set_rate,
};
-enum {
- P_XO,
-};
-
-static const struct parent_map gcc_parent_map_1[] = {
- { P_XO, 0 },
-};
-
-static const char * const gcc_parent_names_1[] = {
- "xo",
-};
-
static struct clk_init_data osm_clks_init[] = {
[0] = {
.name = "l3_clk",
- .parent_names = (const char *[]){ "bi_tcxo" },
+ .parent_names = (const char *[]){ "bi_tcxo_ao" },
.num_parents = 1,
.ops = &clk_ops_l3_osm,
},
[1] = {
.name = "pwrcl_clk",
- .parent_names = (const char *[]){ "bi_tcxo" },
+ .parent_names = (const char *[]){ "bi_tcxo_ao" },
.num_parents = 1,
.ops = &clk_ops_cpu_osm,
},
[2] = {
.name = "perfcl_clk",
- .parent_names = (const char *[]){ "bi_tcxo" },
+ .parent_names = (const char *[]){ "bi_tcxo_ao" },
.num_parents = 1,
.ops = &clk_ops_cpu_osm,
},
diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
index cb073a8..3b56fa1 100644
--- a/drivers/clk/qcom/dispcc-sdm845.c
+++ b/drivers/clk/qcom/dispcc-sdm845.c
@@ -478,19 +478,6 @@
},
};
-static struct clk_branch disp_cc_debug_clk = {
- .halt_reg = 0x600c,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x600c,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "disp_cc_debug_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch disp_cc_mdss_ahb_clk = {
.halt_reg = 0x4004,
.halt_check = BRANCH_HALT,
@@ -546,7 +533,7 @@
"disp_cc_mdss_byte0_clk_src",
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ .flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_regmap_div_ops,
},
},
@@ -599,7 +586,7 @@
"disp_cc_mdss_byte1_clk_src",
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ .flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_regmap_div_ops,
},
},
@@ -949,7 +936,6 @@
};
static struct clk_regmap *disp_cc_sdm845_clocks[] = {
- [DISP_CC_DEBUG_CLK] = &disp_cc_debug_clk.clkr,
[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
[DISP_CC_MDSS_AXI_CLK] = &disp_cc_mdss_axi_clk.clkr,
[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 8fc2345..4824546 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -151,6 +151,13 @@
"core_bi_pll_test_se",
};
+static const char * const gcc_parent_names_7[] = {
+ "bi_tcxo_ao",
+ "gpll0",
+ "gpll0_out_even",
+ "core_bi_pll_test_se",
+};
+
static struct clk_dummy measure_only_snoc_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
@@ -256,8 +263,6 @@
static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
- F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
- F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
{ }
};
@@ -269,7 +274,7 @@
.freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "gcc_cpuss_ahb_clk_src",
- .parent_names = gcc_parent_names_0,
+ .parent_names = gcc_parent_names_7,
.num_parents = 4,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
@@ -796,7 +801,10 @@
};
static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
+ F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
{ }
@@ -824,8 +832,9 @@
};
static const struct freq_tbl ftbl_gcc_sdcc4_apps_clk_src[] = {
- F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(400000, P_BI_TCXO, 12, 1, 4),
F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(25000000, P_GPLL0_OUT_MAIN, 12, 1, 2),
F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
{ }
@@ -1459,22 +1468,9 @@
},
};
-static struct clk_branch gcc_cxo_tx1_clkref_clk = {
- .halt_reg = 0x8c020,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x8c020,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "gcc_cxo_tx1_clkref_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_ddrss_gpu_axi_clk = {
.halt_reg = 0x44038,
- .halt_check = BRANCH_HALT,
+ .halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x44038,
.enable_mask = BIT(0),
@@ -1661,7 +1657,7 @@
static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
.halt_reg = 0x7100c,
- .halt_check = BRANCH_HALT,
+ .halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x7100c,
.enable_mask = BIT(0),
@@ -2424,32 +2420,6 @@
},
};
-static struct clk_branch gcc_rx1_usb2_clkref_clk = {
- .halt_reg = 0x8c014,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x8c014,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "gcc_rx1_usb2_clkref_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
-static struct clk_branch gcc_rx2_qlink_clkref_clk = {
- .halt_reg = 0x8c018,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x8c018,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "gcc_rx2_qlink_clkref_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gcc_sdcc2_ahb_clk = {
.halt_reg = 0x14008,
.halt_check = BRANCH_HALT,
@@ -3142,7 +3112,6 @@
[GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
[GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr,
[GCC_CPUSS_RBCPR_CLK_SRC] = &gcc_cpuss_rbcpr_clk_src.clkr,
- [GCC_CXO_TX1_CLKREF_CLK] = &gcc_cxo_tx1_clkref_clk.clkr,
[GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
[GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr,
[GCC_DISP_AXI_CLK] = &gcc_disp_axi_clk.clkr,
@@ -3229,8 +3198,6 @@
[GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
[GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr,
[GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr,
- [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
- [GCC_RX2_QLINK_CLKREF_CLK] = &gcc_rx2_qlink_clkref_clk.clkr,
[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
[GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index d9a626e..0115bb1 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -413,19 +413,6 @@
},
};
-static struct clk_branch gpu_cc_debug_clk = {
- .halt_reg = 0x1100,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0x1100,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "gpu_cc_debug_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch gpu_cc_gx_cxo_clk = {
.halt_reg = 0x1060,
.halt_check = BRANCH_HALT,
@@ -544,7 +531,6 @@
[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
- [GPU_CC_DEBUG_CLK] = &gpu_cc_debug_clk.clkr,
[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
[GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr,
[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 6ce0d76..3daefbc 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -40,6 +40,8 @@
#define PLL_CALIBRATION_SETTINGS 0x030
#define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054
#define PLL_FREQ_DETECT_SETTINGS_ONE 0x064
+#define PLL_PFILT 0x07c
+#define PLL_IFILT 0x080
#define PLL_OUTDIV 0x094
#define PLL_CORE_OVERRIDE 0x0a4
#define PLL_CORE_INPUT_OVERRIDE 0x0a8
@@ -63,6 +65,7 @@
#define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164
#define PLL_PLL_LOCK_OVERRIDE 0x180
#define PLL_PLL_LOCK_DELAY 0x184
+#define PLL_CLOCK_INVERTERS 0x18c
#define PLL_COMMON_STATUS_ONE 0x1a0
/* Register Offsets from PHY base address */
@@ -338,7 +341,6 @@
MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_THREE, 0x00);
MDSS_PLL_REG_W(pll_base, PLL_DSM_DIVIDER, 0x00);
MDSS_PLL_REG_W(pll_base, PLL_FEEDBACK_DIVIDER, 0x4e);
- MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x00);
MDSS_PLL_REG_W(pll_base, PLL_CALIBRATION_SETTINGS, 0x40);
MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
@@ -347,9 +349,11 @@
MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x08);
MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SET_RATE_1, 0xc0);
- MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
+ MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa);
MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x80);
+ MDSS_PLL_REG_W(pll_base, PLL_PFILT, 0x29);
+ MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f);
}
static void dsi_pll_commit(struct dsi_pll_10nm *pll,
@@ -367,9 +371,11 @@
reg->frac_div_start_mid);
MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1,
reg->frac_div_start_high);
- MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0xc8);
+ MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40);
MDSS_PLL_REG_W(pll_base, PLL_PLL_OUTDIV_RATE, reg->pll_outdiv_rate);
- MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x0a);
+ MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06);
+ MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x10);
+ MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, 0x0);
}
@@ -450,8 +456,8 @@
{
u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0);
- MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5));
MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0);
+ MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5));
ndelay(250);
}
@@ -464,6 +470,22 @@
ndelay(250);
}
+static void dsi_pll_disable_global_clk(struct mdss_pll_resources *rsc)
+{
+ u32 data;
+
+ data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
+ MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5)));
+}
+
+static void dsi_pll_enable_global_clk(struct mdss_pll_resources *rsc)
+{
+ u32 data;
+
+ data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
+ MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5)));
+}
+
static int dsi_pll_enable(struct dsi_pll_vco_clk *vco)
{
int rc;
@@ -490,6 +512,11 @@
}
rsc->pll_on = true;
+
+ dsi_pll_enable_global_clk(rsc);
+ if (rsc->slave)
+ dsi_pll_enable_global_clk(rsc->slave);
+
MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
if (rsc->slave)
MDSS_PLL_REG_W(rsc->slave->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
@@ -500,8 +527,9 @@
static void dsi_pll_disable_sub(struct mdss_pll_resources *rsc)
{
- dsi_pll_disable_pll_bias(rsc);
+ dsi_pll_disable_global_clk(rsc);
MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0);
+ dsi_pll_disable_pll_bias(rsc);
}
static void dsi_pll_disable(struct dsi_pll_vco_clk *vco)
@@ -613,6 +641,9 @@
u32 outdiv;
u64 pll_freq, tmp64;
+ if (!vco->priv)
+ pr_err("vco priv is null\n");
+
rc = mdss_pll_resource_enable(pll, true);
if (rc) {
pr_err("failed to enable pll(%d) resource, rc=%d\n",
@@ -671,9 +702,11 @@
reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
*div = (reg_val & 0xF0) >> 4;
- if (*div == 0)
- *div = 1;
- else
+ /**
+ * Common clock framework the divider value is interpreted as one less
+ * hence we return one less for all dividers except when zero
+ */
+ if (*div != 0)
*div -= 1;
(void)mdss_pll_resource_enable(pll, false);
@@ -701,13 +734,15 @@
pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
return rc;
}
- /* In common clock framework the divider value provided is one less */
+ /**
+ * In common clock framework the divider value provided is one less and
+ * and hence adjusting the divider value by one prior to writing it to
+ * hardware
+ */
div++;
-
pixel_clk_set_div_sub(pll, div);
if (pll->slave)
pixel_clk_set_div_sub(pll->slave, div);
-
(void)mdss_pll_resource_enable(pll, false);
return 0;
@@ -728,12 +763,12 @@
reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
*div = (reg_val & 0x0F);
- /* Common clock framework will add one to divider value sent */
- if (*div == 0)
- *div = 1;
- else
+ /**
+ *Common clock framework the divider value is interpreted as one less
+ * hence we return one less for all dividers except when zero
+ */
+ if (*div != 0)
*div -= 1;
-
(void)mdss_pll_resource_enable(pll, false);
return rc;
@@ -771,6 +806,12 @@
pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
return rc;
}
+
+ /**
+ * In common clock framework the divider value provided is one less and
+ * and hence adjusting the divider value by one prior to writing it to
+ * hardware
+ */
div++;
bit_clk_set_div_sub(rsc, div);
@@ -806,9 +847,11 @@
else
*div = 1;
- if (*div == 0)
- *div = 1;
- else
+ /**
+ *Common clock framework the divider value is interpreted as one less
+ * hence we return one less for all dividers except when zero
+ */
+ if (*div != 0)
*div -= 1;
(void)mdss_pll_resource_enable(pll, false);
@@ -851,8 +894,12 @@
return rc;
}
+ /**
+ * In common clock framework the divider value provided is one less and
+ * and hence adjusting the divider value by one prior to writing it to
+ * hardware
+ */
div++;
-
rc = post_vco_clk_set_div_sub(pll, div);
if (!rc && pll->slave)
rc = post_vco_clk_set_div_sub(pll->slave, div);
@@ -885,9 +932,11 @@
else
*div = 1;
- if (*div == 0)
- *div = 1;
- else
+ /**
+ *Common clock framework the divider value is interpreted as one less
+ * hence we return one less for all dividers except when zero
+ */
+ if (*div != 0)
*div -= 1;
(void)mdss_pll_resource_enable(pll, false);
@@ -930,8 +979,12 @@
return rc;
}
+ /**
+ * In common clock framework the divider value provided is one less and
+ * and hence adjusting the divider value by one prior to writing it to
+ * hardware
+ */
div++;
-
rc = post_bit_clk_set_div_sub(pll, div);
if (!rc && pll->slave)
rc = post_bit_clk_set_div_sub(pll->slave, div);
@@ -1057,7 +1110,6 @@
};
static struct clk_regmap_div dsi0pll_bitclk_src = {
- .reg = 0x48,
.shift = 0,
.width = 4,
.clkr = {
@@ -1072,7 +1124,6 @@
};
static struct clk_regmap_div dsi1pll_bitclk_src = {
- .reg = 0x48,
.shift = 0,
.width = 4,
.clkr = {
@@ -1087,9 +1138,8 @@
};
static struct clk_regmap_div dsi0pll_post_vco_div = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_vco_div",
@@ -1102,9 +1152,8 @@
};
static struct clk_regmap_div dsi1pll_post_vco_div = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_vco_div",
@@ -1141,9 +1190,8 @@
};
static struct clk_regmap_div dsi0pll_post_bit_div = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 1,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_post_bit_div",
@@ -1156,9 +1204,8 @@
};
static struct clk_regmap_div dsi1pll_post_bit_div = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 1,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_post_bit_div",
@@ -1171,12 +1218,11 @@
};
static struct clk_regmap_mux dsi0pll_byteclk_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
- .name = "dsi0pll_byteclk_mux",
+ .name = "dsi0_phy_pll_out_byteclk",
.parent_names = (const char *[]){"dsi0pll_byteclk_src"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1186,12 +1232,11 @@
};
static struct clk_regmap_mux dsi1pll_byteclk_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
- .name = "dsi1pll_byteclk_mux",
+ .name = "dsi1_phy_pll_out_byteclk",
.parent_names = (const char *[]){"dsi1pll_byteclk_src"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1201,15 +1246,14 @@
};
static struct clk_regmap_mux dsi0pll_pclk_src_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_pclk_src_mux",
.parent_names = (const char *[]){"dsi0pll_post_bit_div",
- "dsi0pll_post_bit_div"},
- .num_parents = 1,
+ "dsi0pll_post_vco_div"},
+ .num_parents = 2,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
@@ -1217,15 +1261,14 @@
};
static struct clk_regmap_mux dsi1pll_pclk_src_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_pclk_src_mux",
.parent_names = (const char *[]){"dsi1pll_post_bit_div",
- "dsi1pll_post_bit_div"},
- .num_parents = 1,
+ "dsi1pll_post_vco_div"},
+ .num_parents = 2,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_mux_closest_ops,
},
@@ -1233,7 +1276,6 @@
};
static struct clk_regmap_div dsi0pll_pclk_src = {
- .reg = 0x48,
.shift = 0,
.width = 4,
.clkr = {
@@ -1249,7 +1291,6 @@
};
static struct clk_regmap_div dsi1pll_pclk_src = {
- .reg = 0x48,
.shift = 0,
.width = 4,
.clkr = {
@@ -1265,12 +1306,11 @@
};
static struct clk_regmap_mux dsi0pll_pclk_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
- .name = "dsi0pll_pclk_mux",
+ .name = "dsi0_phy_pll_out_dsiclk",
.parent_names = (const char *[]){"dsi0pll_pclk_src"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1280,12 +1320,11 @@
};
static struct clk_regmap_mux dsi1pll_pclk_mux = {
- .reg = 0x48,
.shift = 0,
- .width = 4,
+ .width = 0,
.clkr = {
.hw.init = &(struct clk_init_data){
- .name = "dsi1pll_pclk_mux",
+ .name = "dsi1_phy_pll_out_dsiclk",
.parent_names = (const char *[]){"dsi1pll_pclk_src"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1339,8 +1378,8 @@
}
pll_rsc_db[ndx] = pll_res;
- pll_res->priv = &plls[ndx];
plls[ndx].rsc = pll_res;
+ pll_res->priv = &plls[ndx];
pll_res->vco_delay = VCO_DELAY_USEC;
clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
@@ -1386,6 +1425,7 @@
pll_res, &dsi_pll_10nm_config);
dsi0pll_byteclk_mux.clkr.regmap = rmap;
+ dsi0pll_vco_clk.priv = pll_res;
for (i = VCO_CLK_0; i <= PCLK_MUX_0_CLK; i++) {
clk = devm_clk_register(&pdev->dev,
mdss_dsi_pllcc_10nm[i]);
@@ -1431,6 +1471,7 @@
rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi1pll_byteclk_mux.clkr.regmap = rmap;
+ dsi1pll_vco_clk.priv = pll_res;
for (i = VCO_CLK_1; i <= PCLK_MUX_1_CLK; i++) {
clk = devm_clk_register(&pdev->dev,
diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c
index 0a0d303..7f82fda 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.c
+++ b/drivers/clk/qcom/mdss/mdss-pll.c
@@ -150,6 +150,7 @@
switch (pll_res->pll_interface_type) {
case MDSS_DSI_PLL_10NM:
rc = dsi_pll_clock_register_10nm(pdev, pll_res);
+ break;
case MDSS_UNKNOWN_PLL:
default:
rc = -EINVAL;
@@ -370,7 +371,7 @@
return rc;
}
-subsys_initcall(mdss_pll_driver_init);
+fs_initcall(mdss_pll_driver_init);
static void __exit mdss_pll_driver_deinit(void)
{
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index 28b7ca6..eccfcea 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -194,9 +194,7 @@
WARN(1, "gdsc_base register is not defined\n");
return true;
}
-
- return ((readl_relaxed(pll_res->gdsc_base + 0x4) & BIT(31)) &&
- (!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? false : true;
+ return readl_relaxed(pll_res->gdsc_base) & BIT(31) ? false : true;
}
static inline int mdss_pll_div_prepare(struct clk_hw *hw)
diff --git a/drivers/clk/qcom/videocc-sdm845.c b/drivers/clk/qcom/videocc-sdm845.c
index 8b63979..4eb8a04 100644
--- a/drivers/clk/qcom/videocc-sdm845.c
+++ b/drivers/clk/qcom/videocc-sdm845.c
@@ -151,19 +151,6 @@
},
};
-static struct clk_branch video_cc_debug_clk = {
- .halt_reg = 0xa58,
- .halt_check = BRANCH_HALT,
- .clkr = {
- .enable_reg = 0xa58,
- .enable_mask = BIT(0),
- .hw.init = &(struct clk_init_data){
- .name = "video_cc_debug_clk",
- .ops = &clk_branch2_ops,
- },
- },
-};
-
static struct clk_branch video_cc_qdss_trig_clk = {
.halt_reg = 0x970,
.halt_check = BRANCH_HALT,
@@ -299,7 +286,6 @@
static struct clk_regmap *video_cc_sdm845_clocks[] = {
[VIDEO_CC_APB_CLK] = &video_cc_apb_clk.clkr,
[VIDEO_CC_AT_CLK] = &video_cc_at_clk.clkr,
- [VIDEO_CC_DEBUG_CLK] = &video_cc_debug_clk.clkr,
[VIDEO_CC_QDSS_TRIG_CLK] = &video_cc_qdss_trig_clk.clkr,
[VIDEO_CC_QDSS_TSCTR_DIV8_CLK] = &video_cc_qdss_tsctr_div8_clk.clkr,
[VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr,
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 66e604e..b315236 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2480,6 +2480,20 @@
*********************************************************************/
static enum cpuhp_state hp_online;
+static int cpuhp_cpufreq_online(unsigned int cpu)
+{
+ cpufreq_online(cpu);
+
+ return 0;
+}
+
+static int cpuhp_cpufreq_offline(unsigned int cpu)
+{
+ cpufreq_offline(cpu);
+
+ return 0;
+}
+
/**
* cpufreq_register_driver - register a CPU Frequency driver
* @driver_data: A struct cpufreq_driver containing the values#
@@ -2542,8 +2556,8 @@
}
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "cpufreq:online",
- cpufreq_online,
- cpufreq_offline);
+ cpuhp_cpufreq_online,
+ cpuhp_cpufreq_offline);
if (ret < 0)
goto err_if_unreg;
hp_online = ret;
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
index 851015e..354a16a 100644
--- a/drivers/crypto/caam/caampkc.c
+++ b/drivers/crypto/caam/caampkc.c
@@ -506,7 +506,7 @@
ctx->dev = caam_jr_alloc();
if (IS_ERR(ctx->dev)) {
- dev_err(ctx->dev, "Job Ring Device allocation for transform failed\n");
+ pr_err("Job Ring Device allocation for transform failed\n");
return PTR_ERR(ctx->dev);
}
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index e483b78..98468b9 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -282,7 +282,8 @@
/* Try to run it through DECO0 */
ret = run_descriptor_deco0(ctrldev, desc, &status);
- if (ret || status) {
+ if (ret ||
+ (status && status != JRSTA_SSRC_JUMP_HALT_CC)) {
dev_err(ctrldev,
"Failed to deinstantiate RNG4 SH%d\n",
sh_idx);
diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c
index a4a1cfb..cd4fdfb 100644
--- a/drivers/devfreq/bimc-bwmon.c
+++ b/drivers/devfreq/bimc-bwmon.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -65,7 +65,7 @@
void __iomem *base;
void __iomem *global_base;
unsigned int mport;
- unsigned int irq;
+ int irq;
const struct bwmon_spec *spec;
struct device *dev;
struct bw_hwmon hw;
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 5b85b8d..8f582f6 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -70,6 +70,29 @@
}
/**
+ * devfreq_set_freq_limits() - Set min and max frequency from freq_table
+ * @devfreq: the devfreq instance
+ */
+static void devfreq_set_freq_limits(struct devfreq *devfreq)
+{
+ int idx;
+ unsigned long min = ~0, max = 0;
+
+ if (!devfreq->profile->freq_table)
+ return;
+
+ for (idx = 0; idx < devfreq->profile->max_state; idx++) {
+ if (min > devfreq->profile->freq_table[idx])
+ min = devfreq->profile->freq_table[idx];
+ if (max < devfreq->profile->freq_table[idx])
+ max = devfreq->profile->freq_table[idx];
+ }
+
+ devfreq->min_freq = min;
+ devfreq->max_freq = max;
+}
+
+/**
* devfreq_get_freq_level() - Lookup freq_table for the frequency
* @devfreq: the devfreq instance
* @freq: the target frequency
@@ -569,6 +592,7 @@
devfreq_set_freq_table(devfreq);
mutex_lock(&devfreq->lock);
}
+ devfreq_set_freq_limits(devfreq);
dev_set_name(&devfreq->dev, "%s", dev_name(dev));
err = device_register(&devfreq->dev);
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index cf04d24..6b54e02 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -303,6 +303,9 @@
.llseek = dma_buf_llseek,
.poll = dma_buf_poll,
.unlocked_ioctl = dma_buf_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = dma_buf_ioctl,
+#endif
};
/*
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 192080e..13b8b71 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -514,6 +514,17 @@
For debugging issues having to do with stability and overall system
health, you should probably say 'Y' here.
+config EDAC_LLCC_POLL
+ depends on EDAC_QCOM_LLCC
+ bool "Poll on LLCC ECC registers - LLCC"
+ help
+ This option chooses whether or not you want to poll on the LLCC
+ ECC registers. When this is enabled, the polling rate can be set as
+ a module parameter. By default, it will call the polling function
+ every second.
+ This option should only be used if the associated interrupt lines
+ are not enabled.
+
config EDAC_QCOM_LLCC_PANIC_ON_CE
depends on EDAC_QCOM_LLCC
bool "panic on correctable errors - qcom llcc"
diff --git a/drivers/edac/qcom_llcc_edac.c b/drivers/edac/qcom_llcc_edac.c
index 6bec860..4403f86 100644
--- a/drivers/edac/qcom_llcc_edac.c
+++ b/drivers/edac/qcom_llcc_edac.c
@@ -78,10 +78,12 @@
#define DRP_TRP_INT_CLEAR 0x3
#define DRP_TRP_CNT_CLEAR 0x3
+#ifdef CONFIG_EDAC_LLCC_POLL
static int poll_msec = 5000;
module_param(poll_msec, int, 0444);
+#endif
-static int interrupt_mode;
+static int interrupt_mode = 1;
module_param(interrupt_mode, int, 0444);
MODULE_PARM_DESC(interrupt_mode,
"Controls whether to use interrupt or poll mode");
@@ -331,10 +333,12 @@
}
}
+#ifdef CONFIG_EDAC_LLCC_POLL
static void qcom_llcc_poll_cache_errors(struct edac_device_ctl_info *edev_ctl)
{
qcom_llcc_check_cache_errors(edev_ctl);
}
+#endif
static irqreturn_t llcc_ecc_irq_handler
(int irq, void *edev_ctl)
@@ -360,9 +364,11 @@
edev_ctl->mod_name = dev_name(dev);
edev_ctl->dev_name = dev_name(dev);
edev_ctl->ctl_name = "llcc";
+#ifdef CONFIG_EDAC_LLCC_POLL
edev_ctl->poll_msec = poll_msec;
edev_ctl->edac_check = qcom_llcc_poll_cache_errors;
edev_ctl->defer_work = 1;
+#endif
edev_ctl->panic_on_ce = LLCC_ERP_PANIC_ON_CE;
edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
@@ -383,7 +389,7 @@
}
rc = devm_request_irq(dev, drv->ecc_irq, llcc_ecc_irq_handler,
- IRQF_TRIGGER_RISING, "llcc_ecc", edev_ctl);
+ IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
if (rc) {
dev_err(dev, "failed to request ecc irq\n");
goto out;
diff --git a/drivers/firmware/efi/libstub/gop.c b/drivers/firmware/efi/libstub/gop.c
index 932742e..24c461d 100644
--- a/drivers/firmware/efi/libstub/gop.c
+++ b/drivers/firmware/efi/libstub/gop.c
@@ -149,7 +149,8 @@
status = __gop_query32(sys_table_arg, gop32, &info, &size,
¤t_fb_base);
- if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+ if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+ info->pixel_format != PIXEL_BLT_ONLY) {
/*
* Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are
@@ -266,7 +267,8 @@
status = __gop_query64(sys_table_arg, gop64, &info, &size,
¤t_fb_base);
- if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+ if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+ info->pixel_format != PIXEL_BLT_ONLY) {
/*
* Systems that use the UEFI Console Splitter may
* provide multiple GOP devices, not all of which are
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index b87d278..a336754 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1305,7 +1305,7 @@
if (!fence) {
event_free(gpu, event);
ret = -ENOMEM;
- goto out_pm_put;
+ goto out_unlock;
}
gpu->event[event].fence = fence;
@@ -1345,6 +1345,7 @@
hangcheck_timer_reset(gpu);
ret = 0;
+out_unlock:
mutex_unlock(&gpu->lock);
out_pm_put:
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 670beeb..923150d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -240,6 +240,7 @@
case I915_PARAM_IRQ_ACTIVE:
case I915_PARAM_ALLOW_BATCHBUFFER:
case I915_PARAM_LAST_DISPATCH:
+ case I915_PARAM_HAS_EXEC_CONSTANTS:
/* Reject all old ums/dri params. */
return -ENODEV;
case I915_PARAM_CHIPSET_ID:
@@ -266,9 +267,6 @@
case I915_PARAM_HAS_BSD2:
value = intel_engine_initialized(&dev_priv->engine[VCS2]);
break;
- case I915_PARAM_HAS_EXEC_CONSTANTS:
- value = INTEL_GEN(dev_priv) >= 4;
- break;
case I915_PARAM_HAS_LLC:
value = HAS_LLC(dev_priv);
break;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index da832d3..e0d7245 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1225,7 +1225,7 @@
unsigned boosts;
/* manual wa residency calculations */
- struct intel_rps_ei up_ei, down_ei;
+ struct intel_rps_ei ei;
/*
* Protects RPS/RC6 register access and PCU communication.
@@ -1751,8 +1751,6 @@
const struct intel_device_info info;
- int relative_constants_mode;
-
void __iomem *regs;
struct intel_uncore uncore;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 00eb481..7b203092 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4587,8 +4587,6 @@
init_waitqueue_head(&dev_priv->gpu_error.wait_queue);
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
- dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
-
init_waitqueue_head(&dev_priv->pending_flip_queue);
dev_priv->mm.interruptible = true;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 0c400f8..2117f17 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1454,10 +1454,7 @@
struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas)
{
- struct drm_i915_private *dev_priv = params->request->i915;
u64 exec_start, exec_len;
- int instp_mode;
- u32 instp_mask;
int ret;
ret = i915_gem_execbuffer_move_to_gpu(params->request, vmas);
@@ -1468,56 +1465,11 @@
if (ret)
return ret;
- instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
- instp_mask = I915_EXEC_CONSTANTS_MASK;
- switch (instp_mode) {
- case I915_EXEC_CONSTANTS_REL_GENERAL:
- case I915_EXEC_CONSTANTS_ABSOLUTE:
- case I915_EXEC_CONSTANTS_REL_SURFACE:
- if (instp_mode != 0 && params->engine->id != RCS) {
- DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
- return -EINVAL;
- }
-
- if (instp_mode != dev_priv->relative_constants_mode) {
- if (INTEL_INFO(dev_priv)->gen < 4) {
- DRM_DEBUG("no rel constants on pre-gen4\n");
- return -EINVAL;
- }
-
- if (INTEL_INFO(dev_priv)->gen > 5 &&
- instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
- DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
- return -EINVAL;
- }
-
- /* The HW changed the meaning on this bit on gen6 */
- if (INTEL_INFO(dev_priv)->gen >= 6)
- instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
- }
- break;
- default:
- DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
+ if (args->flags & I915_EXEC_CONSTANTS_MASK) {
+ DRM_DEBUG("I915_EXEC_CONSTANTS_* unsupported\n");
return -EINVAL;
}
- if (params->engine->id == RCS &&
- instp_mode != dev_priv->relative_constants_mode) {
- struct intel_ring *ring = params->request->ring;
-
- ret = intel_ring_begin(params->request, 4);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit_reg(ring, INSTPM);
- intel_ring_emit(ring, instp_mask << 16 | instp_mode);
- intel_ring_advance(ring);
-
- dev_priv->relative_constants_mode = instp_mode;
- }
-
if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
ret = i915_reset_gen7_sol_offsets(params->request);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 1c237d0..755d788 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -233,7 +233,7 @@
I915_SHRINK_BOUND |
I915_SHRINK_UNBOUND |
I915_SHRINK_ACTIVE);
- rcu_barrier(); /* wait until our RCU delayed slab frees are completed */
+ synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */
return freed;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 3fc286cd..02908e3 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -990,68 +990,51 @@
ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);
}
-static bool vlv_c0_above(struct drm_i915_private *dev_priv,
- const struct intel_rps_ei *old,
- const struct intel_rps_ei *now,
- int threshold)
-{
- u64 time, c0;
- unsigned int mul = 100;
-
- if (old->cz_clock == 0)
- return false;
-
- if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
- mul <<= 8;
-
- time = now->cz_clock - old->cz_clock;
- time *= threshold * dev_priv->czclk_freq;
-
- /* Workload can be split between render + media, e.g. SwapBuffers
- * being blitted in X after being rendered in mesa. To account for
- * this we need to combine both engines into our activity counter.
- */
- c0 = now->render_c0 - old->render_c0;
- c0 += now->media_c0 - old->media_c0;
- c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC;
-
- return c0 >= time;
-}
-
void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)
{
- vlv_c0_read(dev_priv, &dev_priv->rps.down_ei);
- dev_priv->rps.up_ei = dev_priv->rps.down_ei;
+ memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));
}
static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)
{
+ const struct intel_rps_ei *prev = &dev_priv->rps.ei;
struct intel_rps_ei now;
u32 events = 0;
- if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0)
+ if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)
return 0;
vlv_c0_read(dev_priv, &now);
if (now.cz_clock == 0)
return 0;
- if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) {
- if (!vlv_c0_above(dev_priv,
- &dev_priv->rps.down_ei, &now,
- dev_priv->rps.down_threshold))
- events |= GEN6_PM_RP_DOWN_THRESHOLD;
- dev_priv->rps.down_ei = now;
+ if (prev->cz_clock) {
+ u64 time, c0;
+ unsigned int mul;
+
+ mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */
+ if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH)
+ mul <<= 8;
+
+ time = now.cz_clock - prev->cz_clock;
+ time *= dev_priv->czclk_freq;
+
+ /* Workload can be split between render + media,
+ * e.g. SwapBuffers being blitted in X after being rendered in
+ * mesa. To account for this we need to combine both engines
+ * into our activity counter.
+ */
+ c0 = now.render_c0 - prev->render_c0;
+ c0 += now.media_c0 - prev->media_c0;
+ c0 *= mul;
+
+ if (c0 > time * dev_priv->rps.up_threshold)
+ events = GEN6_PM_RP_UP_THRESHOLD;
+ else if (c0 < time * dev_priv->rps.down_threshold)
+ events = GEN6_PM_RP_DOWN_THRESHOLD;
}
- if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
- if (vlv_c0_above(dev_priv,
- &dev_priv->rps.up_ei, &now,
- dev_priv->rps.up_threshold))
- events |= GEN6_PM_RP_UP_THRESHOLD;
- dev_priv->rps.up_ei = now;
- }
-
+ dev_priv->rps.ei = now;
return events;
}
@@ -4490,7 +4473,7 @@
/* Let's track the enabled rps events */
if (IS_VALLEYVIEW(dev_priv))
/* WaGsvRC0ResidencyMethod:vlv */
- dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED;
+ dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
else
dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
@@ -4531,6 +4514,16 @@
if (!IS_GEN2(dev_priv))
dev->vblank_disable_immediate = true;
+ /* Most platforms treat the display irq block as an always-on
+ * power domain. vlv/chv can disable it at runtime and need
+ * special care to avoid writing any of the display block registers
+ * outside of the power domain. We defer setting up the display irqs
+ * in this case to the runtime pm.
+ */
+ dev_priv->display_irqs_enabled = true;
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+ dev_priv->display_irqs_enabled = false;
+
dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b9be8a6..5dc6082 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3696,10 +3696,6 @@
/* drm_atomic_helper_update_legacy_modeset_state might not be called. */
crtc->base.mode = crtc->base.state->mode;
- DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n",
- old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h,
- pipe_config->pipe_src_w, pipe_config->pipe_src_h);
-
/*
* Update pipe size and adjust fitter if needed: the reason for this is
* that in compute_mode_changes we check the native mode (not the pfit
@@ -4832,23 +4828,17 @@
struct intel_crtc_scaler_state *scaler_state =
&crtc->config->scaler_state;
- DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
-
if (crtc->config->pch_pfit.enabled) {
int id;
- if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
- DRM_ERROR("Requesting pfit without getting a scaler first\n");
+ if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
return;
- }
id = scaler_state->scaler_id;
I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
-
- DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
}
}
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index 334d47b..db3afdf 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -219,7 +219,7 @@
}
}
}
- if (dev_priv->display.hpd_irq_setup)
+ if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup)
dev_priv->display.hpd_irq_setup(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
@@ -425,7 +425,7 @@
}
}
- if (storm_detected)
+ if (storm_detected && dev_priv->display_irqs_enabled)
dev_priv->display.hpd_irq_setup(dev_priv);
spin_unlock(&dev_priv->irq_lock);
@@ -471,10 +471,12 @@
* Interrupt setup is already guaranteed to be single-threaded, this is
* just to make the assert_spin_locked checks happy.
*/
- spin_lock_irq(&dev_priv->irq_lock);
- if (dev_priv->display.hpd_irq_setup)
- dev_priv->display.hpd_irq_setup(dev_priv);
- spin_unlock_irq(&dev_priv->irq_lock);
+ if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup) {
+ spin_lock_irq(&dev_priv->irq_lock);
+ if (dev_priv->display_irqs_enabled)
+ dev_priv->display.hpd_irq_setup(dev_priv);
+ spin_unlock_irq(&dev_priv->irq_lock);
+ }
}
static void i915_hpd_poll_init_work(struct work_struct *work)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 4147e51..67db157 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2152,42 +2152,30 @@
void intel_lr_context_resume(struct drm_i915_private *dev_priv)
{
+ struct i915_gem_context *ctx = dev_priv->kernel_context;
struct intel_engine_cs *engine;
- struct i915_gem_context *ctx;
- /* Because we emit WA_TAIL_DWORDS there may be a disparity
- * between our bookkeeping in ce->ring->head and ce->ring->tail and
- * that stored in context. As we only write new commands from
- * ce->ring->tail onwards, everything before that is junk. If the GPU
- * starts reading from its RING_HEAD from the context, it may try to
- * execute that junk and die.
- *
- * So to avoid that we reset the context images upon resume. For
- * simplicity, we just zero everything out.
- */
- list_for_each_entry(ctx, &dev_priv->context_list, link) {
- for_each_engine(engine, dev_priv) {
- struct intel_context *ce = &ctx->engine[engine->id];
- u32 *reg;
+ for_each_engine(engine, dev_priv) {
+ struct intel_context *ce = &ctx->engine[engine->id];
+ void *vaddr;
+ uint32_t *reg_state;
- if (!ce->state)
- continue;
+ if (!ce->state)
+ continue;
- reg = i915_gem_object_pin_map(ce->state->obj,
- I915_MAP_WB);
- if (WARN_ON(IS_ERR(reg)))
- continue;
+ vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
+ if (WARN_ON(IS_ERR(vaddr)))
+ continue;
- reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg);
- reg[CTX_RING_HEAD+1] = 0;
- reg[CTX_RING_TAIL+1] = 0;
+ reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
- ce->state->obj->dirty = true;
- i915_gem_object_unpin_map(ce->state->obj);
+ reg_state[CTX_RING_HEAD+1] = 0;
+ reg_state[CTX_RING_TAIL+1] = 0;
- ce->ring->head = ce->ring->tail = 0;
- ce->ring->last_retired_head = -1;
- intel_ring_update_space(ce->ring);
- }
+ ce->state->obj->dirty = true;
+ i915_gem_object_unpin_map(ce->state->obj);
+
+ ce->ring->head = 0;
+ ce->ring->tail = 0;
}
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e559a45..2c6d59d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4903,6 +4903,12 @@
break;
}
+ /* When byt can survive without system hang with dynamic
+ * sw freq adjustments, this restriction can be lifted.
+ */
+ if (IS_VALLEYVIEW(dev_priv))
+ goto skip_hw_write;
+
I915_WRITE(GEN6_RP_UP_EI,
GT_INTERVAL_FROM_US(dev_priv, ei_up));
I915_WRITE(GEN6_RP_UP_THRESHOLD,
@@ -4923,6 +4929,7 @@
GEN6_RP_UP_BUSY_AVG |
GEN6_RP_DOWN_IDLE_AVG);
+skip_hw_write:
dev_priv->rps.power = new_power;
dev_priv->rps.up_threshold = threshold_up;
dev_priv->rps.down_threshold = threshold_down;
@@ -4933,8 +4940,9 @@
{
u32 mask = 0;
+ /* We use UP_EI_EXPIRED interupts for both up/down in manual mode */
if (val > dev_priv->rps.min_freq_softlimit)
- mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
+ mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;
if (val < dev_priv->rps.max_freq_softlimit)
mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD;
@@ -5034,7 +5042,7 @@
{
mutex_lock(&dev_priv->rps.hw_lock);
if (dev_priv->rps.enabled) {
- if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED))
+ if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
gen6_rps_reset_ei(dev_priv);
I915_WRITE(GEN6_PMINTRMSK,
gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
@@ -7960,10 +7968,10 @@
* @timeout_base_ms: timeout for polling with preemption enabled
*
* Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
- * reports an error or an overall timeout of @timeout_base_ms+10 ms expires.
+ * reports an error or an overall timeout of @timeout_base_ms+50 ms expires.
* The request is acknowledged once the PCODE reply dword equals @reply after
* applying @reply_mask. Polling is first attempted with preemption enabled
- * for @timeout_base_ms and if this times out for another 10 ms with
+ * for @timeout_base_ms and if this times out for another 50 ms with
* preemption disabled.
*
* Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
@@ -7999,14 +8007,15 @@
* worst case) _and_ PCODE was busy for some reason even after a
* (queued) request and @timeout_base_ms delay. As a workaround retry
* the poll with preemption disabled to maximize the number of
- * requests. Increase the timeout from @timeout_base_ms to 10ms to
+ * requests. Increase the timeout from @timeout_base_ms to 50ms to
* account for interrupts that could reduce the number of these
- * requests.
+ * requests, and for any quirks of the PCODE firmware that delays
+ * the request completion.
*/
DRM_DEBUG_KMS("PCODE timeout, retrying with preemption disabled\n");
WARN_ON_ONCE(timeout_base_ms > 3);
preempt_disable();
- ret = wait_for_atomic(COND, 10);
+ ret = wait_for_atomic(COND, 50);
preempt_enable();
out:
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b5d78b1..4112bef 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -109,6 +109,7 @@
dsi-staging/dsi_ctrl_hw_cmn.o \
dsi-staging/dsi_ctrl_hw_1_4.o \
dsi-staging/dsi_ctrl_hw_2_0.o \
+ dsi-staging/dsi_ctrl_hw_2_2.o \
dsi-staging/dsi_ctrl.o \
dsi-staging/dsi_catalog.o \
dsi-staging/dsi_drm.o \
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 976be99..3625ed0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -83,6 +83,19 @@
ctrl->ops.clamp_enable = NULL;
ctrl->ops.clamp_disable = NULL;
break;
+ case DSI_CTRL_VERSION_2_2:
+ ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config;
+ ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
+ ctrl->ops.wait_for_lane_idle =
+ dsi_ctrl_hw_20_wait_for_lane_idle;
+ ctrl->ops.reg_dump_to_buffer =
+ dsi_ctrl_hw_20_reg_dump_to_buffer;
+ ctrl->ops.ulps_ops.ulps_request = NULL;
+ ctrl->ops.ulps_ops.ulps_exit = NULL;
+ ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL;
+ ctrl->ops.clamp_enable = NULL;
+ ctrl->ops.clamp_disable = NULL;
+ break;
default:
break;
}
@@ -121,6 +134,7 @@
switch (version) {
case DSI_CTRL_VERSION_1_4:
case DSI_CTRL_VERSION_2_0:
+ case DSI_CTRL_VERSION_2_2:
dsi_catalog_cmn_init(ctrl, version);
break;
default:
@@ -167,6 +181,8 @@
dsi_phy_hw_v3_0_ulps_exit;
phy->ops.ulps_ops.get_lanes_in_ulps =
dsi_phy_hw_v3_0_get_lanes_in_ulps;
+ phy->ops.ulps_ops.is_lanes_in_ulps =
+ dsi_phy_hw_v3_0_is_lanes_in_ulps;
phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 4a6a934..5dcdf46 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -97,6 +97,7 @@
void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy,
struct dsi_phy_cfg *cfg, u32 lanes);
u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy);
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
u32 *timing_val, u32 size);
@@ -157,6 +158,8 @@
void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl);
void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl,
bool enable);
+void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+ bool enable);
/* Definitions specific to 1.4 DSI controller hardware */
int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 5df48c3..9a71ea0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -62,6 +62,7 @@
static const enum dsi_ctrl_version dsi_ctrl_v1_4 = DSI_CTRL_VERSION_1_4;
static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0;
+static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2;
static const struct of_device_id msm_dsi_of_match[] = {
{
@@ -72,6 +73,10 @@
.compatible = "qcom,dsi-ctrl-hw-v2.0",
.data = &dsi_ctrl_v2_0,
},
+ {
+ .compatible = "qcom,dsi-ctrl-hw-v2.2",
+ .data = &dsi_ctrl_v2_2,
+ },
{}
};
@@ -428,15 +433,34 @@
pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name,
ctrl->hw.base);
- ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
- if (IS_ERR(ptr)) {
- rc = PTR_ERR(ptr);
- return rc;
+ switch (ctrl->version) {
+ case DSI_CTRL_VERSION_1_4:
+ case DSI_CTRL_VERSION_2_0:
+ ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
+ if (IS_ERR(ptr)) {
+ pr_err("mmss_misc base address not found for [%s]\n",
+ ctrl->name);
+ rc = PTR_ERR(ptr);
+ return rc;
+ }
+ ctrl->hw.mmss_misc_base = ptr;
+ ctrl->hw.disp_cc_base = NULL;
+ break;
+ case DSI_CTRL_VERSION_2_2:
+ ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name);
+ if (IS_ERR(ptr)) {
+ pr_err("disp_cc base address not found for [%s]\n",
+ ctrl->name);
+ rc = PTR_ERR(ptr);
+ return rc;
+ }
+ ctrl->hw.disp_cc_base = ptr;
+ ctrl->hw.mmss_misc_base = NULL;
+ break;
+ default:
+ break;
}
- ctrl->hw.mmss_misc_base = ptr;
- pr_debug("[%s] map mmss_misc registers to %p\n", ctrl->name,
- ctrl->hw.mmss_misc_base);
return rc;
}
@@ -532,7 +556,7 @@
goto fail;
}
- link->esc_clk = devm_clk_get(&pdev->dev, "core_clk");
+ link->esc_clk = devm_clk_get(&pdev->dev, "esc_clk");
if (IS_ERR(link->esc_clk)) {
rc = PTR_ERR(link->esc_clk);
pr_err("failed to get esc_clk, rc=%d\n", rc);
@@ -613,10 +637,8 @@
rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
&ctrl->pwr_info.digital,
"qcom,core-supply-entries");
- if (rc) {
- pr_err("failed to get digital supply, rc = %d\n", rc);
- goto error;
- }
+ if (rc)
+ pr_debug("failed to get digital supply, rc = %d\n", rc);
rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
&ctrl->pwr_info.host_pwr,
@@ -663,10 +685,10 @@
ctrl->pwr_info.host_pwr.vregs = NULL;
ctrl->pwr_info.host_pwr.count = 0;
error_digital:
- devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
+ if (ctrl->pwr_info.digital.vregs)
+ devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
ctrl->pwr_info.digital.vregs = NULL;
ctrl->pwr_info.digital.count = 0;
-error:
return rc;
}
@@ -1204,6 +1226,7 @@
}
dsi_ctrl->cell_index = index;
+ dsi_ctrl->version = version;
dsi_ctrl->name = of_get_property(pdev->dev.of_node, "label", NULL);
if (!dsi_ctrl->name)
@@ -1227,7 +1250,6 @@
goto fail_clks;
}
- dsi_ctrl->version = version;
rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
dsi_ctrl->cell_index);
if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 161024a..859d707 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -41,6 +41,7 @@
DSI_CTRL_VERSION_UNKNOWN,
DSI_CTRL_VERSION_1_4,
DSI_CTRL_VERSION_2_0,
+ DSI_CTRL_VERSION_2_2,
DSI_CTRL_VERSION_MAX
};
@@ -575,18 +576,26 @@
/*
* struct dsi_ctrl_hw - DSI controller hardware object specific to an instance
- * @base: VA for the DSI controller base address.
- * @length: Length of the DSI controller register map.
- * @index: Instance ID of the controller.
- * @feature_map: Features supported by the DSI controller.
- * @ops: Function pointers to the operations supported by the
- * controller.
+ * @base: VA for the DSI controller base address.
+ * @length: Length of the DSI controller register map.
+ * @mmss_misc_base: Base address of mmss_misc register map.
+ * @mmss_misc_length: Length of mmss_misc register map.
+ * @disp_cc_base: Base address of disp_cc register map.
+ * @disp_cc_length: Length of disp_cc register map.
+ * @index: Instance ID of the controller.
+ * @feature_map: Features supported by the DSI controller.
+ * @ops: Function pointers to the operations supported by the
+ * controller.
+ * @supported_interrupts: Number of supported interrupts.
+ * @supported_errors: Number of supported errors.
*/
struct dsi_ctrl_hw {
void __iomem *base;
u32 length;
void __iomem *mmss_misc_base;
u32 mmss_misc_length;
+ void __iomem *disp_cc_base;
+ u32 disp_cc_length;
u32 index;
/* features */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c
new file mode 100644
index 0000000..1b1e811
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "dsi-hw:" fmt
+
+#include "dsi_ctrl_hw.h"
+#include "dsi_ctrl_reg.h"
+#include "dsi_hw.h"
+
+/* Equivalent to register DISP_CC_MISC_CMD */
+#define DISP_CC_CLAMP_REG_OFF 0x00
+
+/**
+ * dsi_ctrl_hw_22_phy_reset_config() - to configure clamp control during ulps
+ * @ctrl: Pointer to the controller host hardware.
+ * @enable: boolean to specify enable/disable.
+ */
+void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+ bool enable)
+{
+ u32 reg = 0;
+
+ reg = DSI_DISP_CC_R32(ctrl, DISP_CC_CLAMP_REG_OFF);
+
+ /* Mask/unmask disable PHY reset bit */
+ if (enable)
+ reg &= ~BIT(ctrl->index);
+ else
+ reg |= BIT(ctrl->index);
+ DSI_DISP_CC_W32(ctrl, DISP_CC_CLAMP_REG_OFF, reg);
+}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 8605338..122a63d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -320,8 +320,8 @@
reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
- /* Enable Timing double buffering */
- DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
+ /* Disable Timing double buffering */
+ DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x0);
pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 2c5bd76..106511c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -260,7 +260,8 @@
return rc;
}
- rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable);
+ rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable,
+ display->clamp_enabled);
if (rc) {
pr_err("Ulps PHY state change(%d) failed\n", enable);
return rc;
@@ -278,7 +279,8 @@
return rc;
}
- rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable);
+ rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable,
+ display->clamp_enabled);
if (rc) {
pr_err("Ulps PHY state change(%d) failed\n", enable);
return rc;
@@ -1365,8 +1367,7 @@
/*
* Enable DSI clamps only if entering idle power collapse.
*/
- if (dsi_panel_initialized(display->panel) &&
- dsi_panel_ulps_feature_enabled(display->panel)) {
+ if (dsi_panel_initialized(display->panel)) {
dsi_display_phy_idle_off(display);
rc = dsi_display_set_clamp(display, true);
if (rc)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
index 447f613..8250da3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
@@ -33,6 +33,15 @@
writel_relaxed((val), (dsi_hw)->mmss_misc_base + (off)); \
} while (0)
+#define DSI_DISP_CC_R32(dsi_hw, off) \
+ readl_relaxed((dsi_hw)->disp_cc_base + (off))
+#define DSI_DISP_CC_W32(dsi_hw, off, val) \
+ do {\
+ pr_err("[DSI_%d][%s] - [0x%08x]\n", \
+ (dsi_hw)->index, #off, val); \
+ writel_relaxed((val), (dsi_hw)->disp_cc_base + (off)); \
+ } while (0)
+
#define DSI_R64(dsi_hw, off) readq_relaxed((dsi_hw)->base + (off))
#define DSI_W64(dsi_hw, off, val) writeq_relaxed((val), (dsi_hw)->base + (off))
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index bda9c2d..8b759f4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -2490,7 +2490,6 @@
panel->name, rc);
goto error;
}
- panel->panel_initialized = false;
error:
mutex_unlock(&panel->panel_lock);
return rc;
@@ -2536,6 +2535,8 @@
panel->name, rc);
goto error;
}
+ panel->panel_initialized = false;
+
error:
mutex_unlock(&panel->panel_lock);
return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index 96a98bd..ebfb40b8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -388,7 +388,7 @@
/** TODO: initialize debugfs */
dsi_phy->pdev = pdev;
platform_set_drvdata(pdev, dsi_phy);
- pr_debug("Probe successful for %s\n", dsi_phy->name);
+ pr_info("Probe successful for %s\n", dsi_phy->name);
return 0;
fail_supplies:
@@ -669,7 +669,7 @@
}
static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy,
- struct dsi_host_config *config)
+ struct dsi_host_config *config, bool clamp_enabled)
{
int rc = 0;
u32 lanes = 0;
@@ -679,17 +679,25 @@
lanes = config->common_config.data_lanes;
lanes |= DSI_CLOCK_LANE;
- rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
- if (rc) {
- pr_err("lanes not entering idle, skip ULPS\n");
- return rc;
+ /*
+ * If DSI clamps are enabled, it means that the DSI lanes are
+ * already in idle state. Checking for lanes to be in idle state
+ * should be skipped during ULPS entry programming while coming
+ * out of idle screen.
+ */
+ if (!clamp_enabled) {
+ rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
+ if (rc) {
+ pr_err("lanes not entering idle, skip ULPS\n");
+ return rc;
+ }
}
phy->hw.ops.ulps_ops.ulps_request(&phy->hw, &phy->cfg, lanes);
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if ((lanes & ulps_lanes) != lanes) {
+ if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n",
lanes, ulps_lanes);
rc = -EIO;
@@ -701,7 +709,6 @@
static int dsi_phy_disable_ulps(struct msm_dsi_phy *phy,
struct dsi_host_config *config)
{
- int rc = 0;
u32 ulps_lanes, lanes = 0;
if (config->panel_mode == DSI_OP_CMD_MODE)
@@ -710,25 +717,27 @@
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if ((lanes & ulps_lanes) != lanes)
- pr_err("Mismatch between lanes in ULPS\n");
-
- lanes &= ulps_lanes;
+ if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
+ pr_err("Mismatch in ULPS: lanes:%d, ulps_lanes:%d\n",
+ lanes, ulps_lanes);
+ return -EIO;
+ }
phy->hw.ops.ulps_ops.ulps_exit(&phy->hw, &phy->cfg, lanes);
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if (ulps_lanes & lanes) {
+
+ if (phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes);
- rc = -EIO;
+ return -EIO;
}
- return rc;
+ return 0;
}
int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config,
- bool enable)
+ bool enable, bool clamp_enabled)
{
int rc = 0;
@@ -738,7 +747,10 @@
}
if (!phy->hw.ops.ulps_ops.ulps_request ||
- !phy->hw.ops.ulps_ops.ulps_exit) {
+ !phy->hw.ops.ulps_ops.ulps_exit ||
+ !phy->hw.ops.ulps_ops.get_lanes_in_ulps ||
+ !phy->hw.ops.ulps_ops.is_lanes_in_ulps ||
+ !phy->hw.ops.ulps_ops.wait_for_lane_idle) {
pr_debug("DSI PHY ULPS ops not present\n");
return 0;
}
@@ -746,7 +758,7 @@
mutex_lock(&phy->phy_lock);
if (enable)
- rc = dsi_phy_enable_ulps(phy, config);
+ rc = dsi_phy_enable_ulps(phy, config, clamp_enabled);
else
rc = dsi_phy_disable_ulps(phy, config);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
index 4a64855..e721486 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
@@ -182,11 +182,12 @@
* @phy: DSI PHY handle
* @config: DSi host configuration information.
* @enable: Enable/Disable
+ * @clamp_enabled: mmss_clamp enabled/disabled
*
* Return: error code.
*/
int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config,
- bool enable);
+ bool enable, bool clamp_enabled);
/**
* dsi_phy_clk_cb_register() - Register PHY clock control callback
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
index daaa78a..51c2f46 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
@@ -143,15 +143,22 @@
* @phy: Pointer to DSI PHY hardware instance.
*
* Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS
- * state. If 0 is returned, all the lanes are active.
+ * state.
*
* Return: List of lanes in ULPS state.
*/
u32 (*get_lanes_in_ulps)(struct dsi_phy_hw *phy);
+
+ /**
+ * is_lanes_in_ulps() - checks if the given lanes are in ulps
+ * @lanes: lanes to be checked.
+ * @ulps_lanes: lanes in ulps currenly.
+ *
+ * Return: true if all the given lanes are in ulps; false otherwise.
+ */
+ bool (*is_lanes_in_ulps)(u32 ulps, u32 ulps_lanes);
};
-
-
/**
* struct dsi_phy_hw_ops - Operations for DSI PHY hardware.
* @regulator_enable: Enable PHY regulators.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
index 96f5c19..371239d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
@@ -159,7 +159,7 @@
struct dsi_phy_cfg *cfg)
{
int i;
- u8 tx_dctrl[] = {0x00, 0x00, 0x00, 0x02, 0x01};
+ u8 tx_dctrl[] = {0x00, 0x00, 0x00, 0x04, 0x01};
/* Strength ctrl settings */
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
@@ -186,6 +186,10 @@
DSI_W32(phy, DSIPHY_LNX_OFFSET_BOT_CTRL(i), 0x0);
DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]);
}
+
+ /* Toggle BIT 0 to release freeze I/0 */
+ DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x05);
+ DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x04);
}
/**
@@ -419,6 +423,14 @@
return lanes;
}
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes)
+{
+ if (lanes & ulps_lanes)
+ return false;
+
+ return true;
+}
+
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
u32 *timing_val, u32 size)
{
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d7b225b..4e0b678 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -356,8 +356,8 @@
{
.compatible = "qcom,sde-kms",
.data = (void *)KMS_SDE,
- /* end node */
- } };
+ },
+ {} };
struct device *dev = &pdev->dev;
const struct of_device_id *match;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 4b263d3..4471d0b 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -138,6 +138,7 @@
CRTC_PROP_MEM_IB,
CRTC_PROP_ROT_PREFILL_BW,
CRTC_PROP_ROT_CLK,
+ CRTC_PROP_ROI_V1,
/* total # of properties */
CRTC_PROP_COUNT
@@ -158,6 +159,7 @@
CONNECTOR_PROP_DST_Y,
CONNECTOR_PROP_DST_W,
CONNECTOR_PROP_DST_H,
+ CONNECTOR_PROP_ROI_V1,
/* enum/bitmask properties */
CONNECTOR_PROP_TOPOLOGY_NAME,
@@ -200,6 +202,38 @@
};
/**
+ * struct msm_roi_alignment - region of interest alignment restrictions
+ * @xstart_pix_align: left x offset alignment restriction
+ * @width_pix_align: width alignment restriction
+ * @ystart_pix_align: top y offset alignment restriction
+ * @height_pix_align: height alignment restriction
+ * @min_width: minimum width restriction
+ * @min_height: minimum height restriction
+ */
+struct msm_roi_alignment {
+ uint32_t xstart_pix_align;
+ uint32_t width_pix_align;
+ uint32_t ystart_pix_align;
+ uint32_t height_pix_align;
+ uint32_t min_width;
+ uint32_t min_height;
+};
+
+/**
+ * struct msm_roi_caps - display's region of interest capabilities
+ * @enabled: true if some region of interest is supported
+ * @merge_rois: merge rois before sending to display
+ * @num_roi: maximum number of rois supported
+ * @align: roi alignment restrictions
+ */
+struct msm_roi_caps {
+ bool enabled;
+ bool merge_rois;
+ uint32_t num_roi;
+ struct msm_roi_alignment align;
+};
+
+/**
* struct msm_display_dsc_info - defines dsc configuration
* @version: DSC version.
* @scr_rev: DSC revision.
@@ -338,6 +372,7 @@
* @vtotal: display vertical total
* @jitter: display jitter configuration
* @comp_info: Compression supported by the display
+ * @roi_caps: Region of interest capability info
*/
struct msm_display_info {
int intf_type;
@@ -361,21 +396,19 @@
uint32_t jitter;
struct msm_compression_info comp_info;
+ struct msm_roi_caps roi_caps;
};
#define MSM_MAX_ROI 4
/**
- * struct msm_roi_mapping - Regions of interest structure for mapping CRTC to
- * Connector output
- * @num_rects: number of valid rectangles in src and dst arrays
- * @src: source roi rectangle
- * @dst: destination roi rectangle
+ * struct msm_roi_list - list of regions of interest for a drm object
+ * @num_rects: number of valid rectangles in the roi array
+ * @roi: list of roi rectangles
*/
-struct msm_roi_mapping {
+struct msm_roi_list {
uint32_t num_rects;
- struct drm_clip_rect src[MSM_MAX_ROI];
- struct drm_clip_rect dst[MSM_MAX_ROI];
+ struct drm_clip_rect roi[MSM_MAX_ROI];
};
/**
@@ -383,7 +416,7 @@
* @rois: Regions of interest structure for mapping CRTC to Connector output
*/
struct msm_display_kickoff_params {
- struct msm_roi_mapping *rois;
+ struct msm_roi_list *rois;
};
/**
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 6e793d9..e3f8261 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -21,6 +21,12 @@
#define BL_NODE_NAME_SIZE 32
+#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
+#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
static const struct drm_prop_enum_list e_topology_name[] = {
{SDE_RM_TOPOLOGY_UNKNOWN, "sde_unknown"},
{SDE_RM_TOPOLOGY_SINGLEPIPE, "sde_singlepipe"},
@@ -78,7 +84,8 @@
.get_brightness = sde_backlight_device_get_brightness,
};
-static int sde_backlight_setup(struct sde_connector *c_conn)
+static int sde_backlight_setup(struct sde_connector *c_conn,
+ struct drm_device *dev)
{
struct backlight_device *bl_device;
struct backlight_properties props;
@@ -87,7 +94,7 @@
static int display_count;
char bl_node_name[BL_NODE_NAME_SIZE];
- if (!c_conn) {
+ if (!c_conn || !dev || !dev->dev) {
SDE_ERROR("invalid param\n");
return -EINVAL;
} else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) {
@@ -104,7 +111,7 @@
props.brightness = bl_config->brightness_max_level;
snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight",
display_count);
- bl_device = backlight_device_register(bl_node_name, c_conn->base.kdev,
+ bl_device = backlight_device_register(bl_node_name, dev->dev,
c_conn, &sde_backlight_device_ops, &props);
if (IS_ERR_OR_NULL(bl_device)) {
SDE_ERROR("Failed to register backlight: %ld\n",
@@ -247,6 +254,25 @@
return rc;
}
+void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
+{
+ struct sde_connector *c_conn;
+ struct dsi_display *display;
+ u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF;
+
+ if (!connector) {
+ SDE_ERROR("invalid connector\n");
+ return;
+ }
+
+ c_conn = to_sde_connector(connector);
+ display = (struct dsi_display *) c_conn->display;
+
+ if (display && c_conn->ops.clk_ctrl)
+ c_conn->ops.clk_ctrl(display->mdp_clk_handle,
+ DSI_ALL_CLKS, state);
+}
+
static void sde_connector_destroy(struct drm_connector *connector)
{
struct sde_connector *c_conn;
@@ -396,6 +422,122 @@
return &c_state->base;
}
+static int _sde_connector_roi_v1_check_roi(
+ struct sde_connector *c_conn,
+ struct drm_clip_rect *roi_conn,
+ const struct msm_roi_caps *caps)
+{
+ const struct msm_roi_alignment *align = &caps->align;
+ int w = roi_conn->x2 - roi_conn->x1;
+ int h = roi_conn->y2 - roi_conn->y1;
+
+ if (w <= 0 || h <= 0) {
+ SDE_ERROR_CONN(c_conn, "invalid conn roi w %d h %d\n", w, h);
+ return -EINVAL;
+ }
+
+ if (w < align->min_width || w % align->width_pix_align) {
+ SDE_ERROR_CONN(c_conn,
+ "invalid conn roi width %d min %d align %d\n",
+ w, align->min_width, align->width_pix_align);
+ return -EINVAL;
+ }
+
+ if (h < align->min_height || h % align->height_pix_align) {
+ SDE_ERROR_CONN(c_conn,
+ "invalid conn roi height %d min %d align %d\n",
+ h, align->min_height, align->height_pix_align);
+ return -EINVAL;
+ }
+
+ if (roi_conn->x1 % align->xstart_pix_align) {
+ SDE_ERROR_CONN(c_conn, "invalid conn roi x1 %d align %d\n",
+ roi_conn->x1, align->xstart_pix_align);
+ return -EINVAL;
+ }
+
+ if (roi_conn->y1 % align->ystart_pix_align) {
+ SDE_ERROR_CONN(c_conn, "invalid conn roi y1 %d align %d\n",
+ roi_conn->y1, align->ystart_pix_align);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _sde_connector_set_roi_v1(
+ struct sde_connector *c_conn,
+ struct sde_connector_state *c_state,
+ void *usr_ptr)
+{
+ struct sde_drm_roi_v1 roi_v1;
+ struct msm_display_info display_info;
+ struct msm_roi_caps *caps;
+ int i, rc;
+
+ if (!c_conn || !c_state) {
+ SDE_ERROR("invalid args\n");
+ return -EINVAL;
+ }
+
+ rc = sde_connector_get_info(&c_conn->base, &display_info);
+ if (rc) {
+ SDE_ERROR_CONN(c_conn, "display get info error: %d\n", rc);
+ return rc;
+ }
+
+ caps = &display_info.roi_caps;
+ if (!caps->enabled) {
+ SDE_ERROR_CONN(c_conn, "display roi capability is disabled\n");
+ return -ENOTSUPP;
+ }
+
+ memset(&c_state->rois, 0, sizeof(c_state->rois));
+
+ if (!usr_ptr) {
+ SDE_DEBUG_CONN(c_conn, "rois cleared\n");
+ return 0;
+ }
+
+ if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
+ SDE_ERROR_CONN(c_conn, "failed to copy roi_v1 data\n");
+ return -EINVAL;
+ }
+
+ SDE_DEBUG_CONN(c_conn, "num_rects %d\n", roi_v1.num_rects);
+
+ if (roi_v1.num_rects == 0) {
+ SDE_DEBUG_CONN(c_conn, "rois cleared\n");
+ return 0;
+ }
+
+ if (roi_v1.num_rects > SDE_MAX_ROI_V1 ||
+ roi_v1.num_rects > caps->num_roi) {
+ SDE_ERROR_CONN(c_conn, "too many rects specified: %d\n",
+ roi_v1.num_rects);
+ return -EINVAL;
+ }
+
+ c_state->rois.num_rects = roi_v1.num_rects;
+ for (i = 0; i < roi_v1.num_rects; ++i) {
+ int rc;
+
+ rc = _sde_connector_roi_v1_check_roi(c_conn, &roi_v1.roi[i],
+ caps);
+ if (rc)
+ return rc;
+
+ c_state->rois.roi[i] = roi_v1.roi[i];
+ SDE_DEBUG_CONN(c_conn, "roi%d: roi 0x%x 0x%x 0x%x 0x%x\n", i,
+ c_state->rois.roi[i].x1,
+ c_state->rois.roi[i].y1,
+ c_state->rois.roi[i].x2,
+ c_state->rois.roi[i].y2);
+ }
+
+ return 0;
+}
+
static int sde_connector_atomic_set_property(struct drm_connector *connector,
struct drm_connector_state *state,
struct drm_property *property,
@@ -461,6 +603,12 @@
SDE_ERROR("invalid topology_control: 0x%llX\n", val);
}
+ if (idx == CONNECTOR_PROP_ROI_V1) {
+ rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
+ if (rc)
+ SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
+ }
+
/* check for custom property handling */
if (!rc && c_conn->ops.set_property) {
rc = c_conn->ops.set_property(connector,
@@ -510,13 +658,7 @@
idx = msm_property_index(&c_conn->property_info, property);
if (idx == CONNECTOR_PROP_RETIRE_FENCE)
- /*
- * Set a fence offset if not a virtual connector, so that the
- * fence signals after one additional commit rather than at the
- * end of the current one.
- */
- rc = sde_fence_create(&c_conn->retire_fence, val,
- c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL);
+ rc = sde_fence_create(&c_conn->retire_fence, val, 0);
else
/* get cached property value */
rc = msm_property_atomic_get(&c_conn->property_info,
@@ -705,6 +847,7 @@
struct sde_kms_info *info;
struct sde_connector *c_conn = NULL;
struct dsi_display *dsi_display;
+ struct msm_display_info display_info;
int rc;
if (!dev || !dev->dev_private || !encoder) {
@@ -779,7 +922,7 @@
goto error_cleanup_fence;
}
- rc = sde_backlight_setup(c_conn);
+ rc = sde_backlight_setup(c_conn, dev);
if (rc) {
SDE_ERROR("failed to setup backlight, rc=%d\n", rc);
goto error_cleanup_fence;
@@ -837,6 +980,13 @@
}
}
+ rc = sde_connector_get_info(&c_conn->base, &display_info);
+ if (!rc && display_info.roi_caps.enabled) {
+ msm_property_install_volatile_range(
+ &c_conn->property_info, "sde_drm_roi_v1", 0x0,
+ 0, ~0, 0, CONNECTOR_PROP_ROI_V1);
+ }
+
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 70d4952..601299e 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -150,6 +150,14 @@
int (*pre_kickoff)(struct drm_connector *connector,
void *display,
struct msm_display_kickoff_params *params);
+
+ /**
+ * clk_ctrl - perform clk enable/disable on the connector
+ * @handle: Pointer to clk handle
+ * @type: Type of clks
+ * @enable: State of clks
+ */
+ int (*clk_ctrl)(void *handle, u32 type, u32 state);
};
/**
@@ -273,7 +281,7 @@
int mmu_id;
uint64_t property_values[CONNECTOR_PROP_COUNT];
- struct msm_roi_mapping rois;
+ struct msm_roi_list rois;
};
/**
@@ -366,6 +374,13 @@
struct msm_display_info *info);
/**
+ * sde_connector_clk_ctrl - enables/disables the connector clks
+ * @connector: Pointer to drm connector object
+ * @enable: true/false to enable/disable
+ */
+void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable);
+
+/**
* sde_connector_trigger_event - indicate that an event has occurred
* Any callbacks that have been registered against this event will
* be called from the same thread context.
@@ -425,5 +440,22 @@
*/
int sde_connector_pre_kickoff(struct drm_connector *connector);
+/**
+ * sde_connector_needs_offset - adjust the output fence offset based on
+ * display type
+ * @connector: Pointer to drm connector object
+ * Returns: true if offset is required, false for all other cases.
+ */
+static inline bool sde_connector_needs_offset(struct drm_connector *connector)
+{
+ struct sde_connector *c_conn;
+
+ if (!connector)
+ return false;
+
+ c_conn = to_sde_connector(connector);
+ return (c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL);
+}
+
#endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index db637ad..6bae083 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -602,10 +602,9 @@
struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer,
struct sde_hw_dim_layer *dim_layer)
{
+ struct sde_crtc_state *cstate;
struct sde_hw_mixer *lm;
- struct sde_rect mixer_rect;
struct sde_hw_dim_layer split_dim_layer;
- u32 mixer_width, mixer_height;
int i;
if (!dim_layer->rect.w || !dim_layer->rect.h) {
@@ -613,9 +612,7 @@
return;
}
- mixer_width = get_crtc_split_width(crtc);
- mixer_height = get_crtc_mixer_height(crtc);
- mixer_rect = (struct sde_rect) {0, 0, mixer_width, mixer_height};
+ cstate = to_sde_crtc_state(crtc->state);
split_dim_layer.stage = dim_layer->stage;
split_dim_layer.color_fill = dim_layer->color_fill;
@@ -626,17 +623,15 @@
*/
for (i = 0; i < sde_crtc->num_mixers; i++) {
split_dim_layer.flags = dim_layer->flags;
- mixer_rect.x = i * mixer_width;
- sde_kms_rect_intersect(&mixer_rect, &dim_layer->rect,
+ sde_kms_rect_intersect(&cstate->lm_bounds[i], &dim_layer->rect,
&split_dim_layer.rect);
- if (!split_dim_layer.rect.w && !split_dim_layer.rect.h) {
+ if (sde_kms_rect_is_null(&split_dim_layer.rect)) {
/*
* no extra programming required for non-intersecting
* layer mixers with INCLUSIVE dim layer
*/
- if (split_dim_layer.flags
- & SDE_DRM_DIM_LAYER_INCLUSIVE)
+ if (split_dim_layer.flags & SDE_DRM_DIM_LAYER_INCLUSIVE)
continue;
/*
@@ -646,12 +641,13 @@
*/
split_dim_layer.flags &= ~SDE_DRM_DIM_LAYER_EXCLUSIVE;
split_dim_layer.flags |= SDE_DRM_DIM_LAYER_INCLUSIVE;
- split_dim_layer.rect = (struct sde_rect) {0, 0,
- mixer_width, mixer_height};
+ memcpy(&split_dim_layer.rect, &cstate->lm_bounds[i],
+ sizeof(split_dim_layer.rect));
} else {
- split_dim_layer.rect.x = split_dim_layer.rect.x
- - (i * mixer_width);
+ split_dim_layer.rect.x =
+ split_dim_layer.rect.x -
+ cstate->lm_bounds[i].w;
}
lm = mixer[i].hw_lm;
@@ -660,6 +656,355 @@
}
}
+void sde_crtc_get_crtc_roi(struct drm_crtc_state *state,
+ const struct sde_rect **crtc_roi)
+{
+ struct sde_crtc_state *crtc_state;
+
+ if (!state || !crtc_roi)
+ return;
+
+ crtc_state = to_sde_crtc_state(state);
+ *crtc_roi = &crtc_state->crtc_roi;
+}
+
+static int _sde_crtc_set_roi_v1(struct drm_crtc_state *state,
+ void *usr_ptr)
+{
+ struct drm_crtc *crtc;
+ struct sde_crtc_state *cstate;
+ struct sde_drm_roi_v1 roi_v1;
+ int i;
+
+ if (!state) {
+ SDE_ERROR("invalid args\n");
+ return -EINVAL;
+ }
+
+ cstate = to_sde_crtc_state(state);
+ crtc = cstate->base.crtc;
+
+ memset(&cstate->user_roi_list, 0, sizeof(cstate->user_roi_list));
+
+ if (!usr_ptr) {
+ SDE_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
+ return 0;
+ }
+
+ if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
+ SDE_ERROR("crtc%d: failed to copy roi_v1 data\n", DRMID(crtc));
+ return -EINVAL;
+ }
+
+ SDE_DEBUG("crtc%d: num_rects %d\n", DRMID(crtc), roi_v1.num_rects);
+
+ if (roi_v1.num_rects == 0) {
+ SDE_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
+ return 0;
+ }
+
+ if (roi_v1.num_rects > SDE_MAX_ROI_V1) {
+ SDE_ERROR("crtc%d: too many rects specified: %d\n", DRMID(crtc),
+ roi_v1.num_rects);
+ return -EINVAL;
+ }
+
+ cstate->user_roi_list.num_rects = roi_v1.num_rects;
+ for (i = 0; i < roi_v1.num_rects; ++i) {
+ cstate->user_roi_list.roi[i] = roi_v1.roi[i];
+ SDE_DEBUG("crtc%d: roi%d: roi (%d,%d) (%d,%d)\n",
+ DRMID(crtc), i,
+ cstate->user_roi_list.roi[i].x1,
+ cstate->user_roi_list.roi[i].y1,
+ cstate->user_roi_list.roi[i].x2,
+ cstate->user_roi_list.roi[i].y2);
+ }
+
+ return 0;
+}
+
+static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct drm_connector *conn;
+ struct drm_connector_state *conn_state;
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ struct sde_rect *crtc_roi;
+ struct drm_clip_rect crtc_clip, *user_rect;
+ int i, num_attached_conns = 0;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+ crtc_roi = &crtc_state->crtc_roi;
+
+ /* init to invalid range maxes */
+ crtc_clip.x1 = ~0;
+ crtc_clip.y1 = ~0;
+ crtc_clip.x2 = 0;
+ crtc_clip.y2 = 0;
+
+ for_each_connector_in_state(state->state, conn, conn_state, i) {
+ struct sde_connector_state *sde_conn_state;
+
+ if (!conn_state || conn_state->crtc != crtc)
+ continue;
+
+ if (num_attached_conns) {
+ SDE_ERROR(
+ "crtc%d: unsupported: roi on crtc w/ >1 connectors\n",
+ DRMID(crtc));
+ return -EINVAL;
+ }
+ ++num_attached_conns;
+
+ sde_conn_state = to_sde_connector_state(conn_state);
+
+ if (memcmp(&sde_conn_state->rois, &crtc_state->user_roi_list,
+ sizeof(crtc_state->user_roi_list))) {
+ SDE_ERROR("%s: crtc -> conn roi scaling unsupported\n",
+ sde_crtc->name);
+ return -EINVAL;
+ }
+ }
+
+ /* aggregate all clipping rectangles together for overall crtc roi */
+ for (i = 0; i < crtc_state->user_roi_list.num_rects; i++) {
+ user_rect = &crtc_state->user_roi_list.roi[i];
+
+ crtc_clip.x1 = min(crtc_clip.x1, user_rect->x1);
+ crtc_clip.y1 = min(crtc_clip.y1, user_rect->y1);
+ crtc_clip.x2 = max(crtc_clip.x2, user_rect->x2);
+ crtc_clip.y2 = max(crtc_clip.y2, user_rect->y2);
+
+ SDE_DEBUG(
+ "%s: conn%d roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n",
+ sde_crtc->name, DRMID(crtc), i,
+ user_rect->x1, user_rect->y1,
+ user_rect->x2, user_rect->y2,
+ crtc_clip.x1, crtc_clip.y1,
+ crtc_clip.x2, crtc_clip.y2);
+
+ }
+
+ if (crtc_clip.x2 && crtc_clip.y2) {
+ crtc_roi->x = crtc_clip.x1;
+ crtc_roi->y = crtc_clip.y1;
+ crtc_roi->w = crtc_clip.x2 - crtc_clip.x1;
+ crtc_roi->h = crtc_clip.y2 - crtc_clip.y1;
+ } else {
+ crtc_roi->x = 0;
+ crtc_roi->y = 0;
+ crtc_roi->w = 0;
+ crtc_roi->h = 0;
+ }
+
+ SDE_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", sde_crtc->name,
+ crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
+
+ return 0;
+}
+
+static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
+ struct drm_crtc_state *state, int lm_idx)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ const struct sde_rect *crtc_roi;
+ const struct sde_rect *lm_bounds;
+ struct sde_rect *lm_roi;
+
+ if (!crtc || !state || lm_idx >= ARRAY_SIZE(crtc_state->lm_bounds))
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+ crtc_roi = &crtc_state->crtc_roi;
+ lm_bounds = &crtc_state->lm_bounds[lm_idx];
+ lm_roi = &crtc_state->lm_roi[lm_idx];
+
+ if (!sde_kms_rect_is_null(crtc_roi)) {
+ sde_kms_rect_intersect(crtc_roi, lm_bounds, lm_roi);
+ if (sde_kms_rect_is_null(lm_roi)) {
+ SDE_ERROR("unsupported R/L only partial update\n");
+ return -EINVAL;
+ }
+ } else {
+ memcpy(lm_roi, lm_bounds, sizeof(*lm_roi));
+ }
+
+ SDE_DEBUG("%s: lm%d roi (%d,%d,%d,%d)\n", sde_crtc->name, lm_idx,
+ lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
+
+ return 0;
+}
+
+static int _sde_crtc_check_rois_centered_and_symmetric(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ const struct sde_rect *roi_prv, *roi_cur;
+ int lm_idx;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ /*
+ * On certain HW, ROIs must be centered on the split between LMs,
+ * and be of equal width.
+ */
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+
+ roi_prv = &crtc_state->lm_roi[0];
+ for (lm_idx = 1; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+ roi_cur = &crtc_state->lm_roi[lm_idx];
+
+ /* check lm rois are equal width & first roi ends at 2nd roi */
+ if (((roi_prv->x + roi_prv->w) != roi_cur->x) ||
+ (roi_prv->w != roi_cur->w)) {
+ SDE_ERROR("%s: roi lm%d x %d w %d lm%d x %d w %d\n",
+ sde_crtc->name,
+ lm_idx-1, roi_prv->x, roi_prv->w,
+ lm_idx, roi_cur->x, roi_cur->w);
+ return -EINVAL;
+ }
+ roi_prv = roi_cur;
+ }
+
+ return 0;
+}
+
+static int _sde_crtc_check_planes_within_crtc_roi(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ const struct sde_rect *crtc_roi;
+ struct drm_plane_state *pstate;
+ struct drm_plane *plane;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ /*
+ * Reject commit if a Plane CRTC destination coordinates fall outside
+ * the partial CRTC ROI. LM output is determined via connector ROIs,
+ * if they are specified, not Plane CRTC ROIs.
+ */
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(state);
+ crtc_roi = &crtc_state->crtc_roi;
+
+ if (sde_kms_rect_is_null(crtc_roi))
+ return 0;
+
+ drm_atomic_crtc_state_for_each_plane(plane, state) {
+ struct sde_rect plane_roi, intersection;
+
+ pstate = drm_atomic_get_plane_state(state->state, plane);
+ if (IS_ERR_OR_NULL(pstate)) {
+ int rc = PTR_ERR(pstate);
+
+ SDE_ERROR("%s: failed to get plane%d state, %d\n",
+ sde_crtc->name, plane->base.id, rc);
+ return rc;
+ }
+
+ plane_roi.x = pstate->crtc_x;
+ plane_roi.y = pstate->crtc_y;
+ plane_roi.w = pstate->crtc_w;
+ plane_roi.h = pstate->crtc_h;
+ sde_kms_rect_intersect(crtc_roi, &plane_roi, &intersection);
+ if (!sde_kms_rect_is_equal(&plane_roi, &intersection)) {
+ SDE_ERROR(
+ "%s: plane%d crtc roi (%d,%d,%d,%d) outside crtc roi (%d,%d,%d,%d)\n",
+ sde_crtc->name, plane->base.id,
+ plane_roi.x, plane_roi.y,
+ plane_roi.w, plane_roi.h,
+ crtc_roi->x, crtc_roi->y,
+ crtc_roi->w, crtc_roi->h);
+ return -E2BIG;
+ }
+ }
+
+ return 0;
+}
+
+static int _sde_crtc_check_rois(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ int lm_idx;
+ int rc;
+
+ if (!crtc || !state)
+ return -EINVAL;
+
+ sde_crtc = to_sde_crtc(crtc);
+
+ rc = _sde_crtc_set_crtc_roi(crtc, state);
+ if (rc)
+ return rc;
+
+ for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+ rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx);
+ if (rc)
+ return rc;
+ }
+
+ rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state);
+ if (rc)
+ return rc;
+
+ rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *crtc_state;
+ const struct sde_rect *lm_roi;
+ struct sde_hw_mixer *hw_lm;
+ int lm_idx, lm_horiz_position;
+
+ if (!crtc)
+ return;
+
+ sde_crtc = to_sde_crtc(crtc);
+ crtc_state = to_sde_crtc_state(crtc->state);
+
+ lm_horiz_position = 0;
+ for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+ struct sde_hw_mixer_cfg cfg;
+
+ lm_roi = &crtc_state->lm_roi[lm_idx];
+ hw_lm = sde_crtc->mixers[lm_idx].hw_lm;
+
+ SDE_EVT32(DRMID(crtc_state->base.crtc), lm_idx,
+ lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
+
+ if (sde_kms_rect_is_null(lm_roi))
+ continue;
+
+ cfg.out_width = lm_roi->w;
+ cfg.out_height = lm_roi->h;
+ cfg.right_mixer = lm_horiz_position++;
+ cfg.flags = 0;
+ hw_lm->ops.setup_mixer_out(hw_lm, &cfg);
+ }
+}
+
static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer)
{
@@ -672,13 +1017,12 @@
struct sde_hw_ctl *ctl;
struct sde_hw_mixer *lm;
struct sde_hw_stage_cfg *stage_cfg;
+ struct sde_rect plane_crtc_roi;
- u32 flush_mask = 0, crtc_split_width;
- uint32_t lm_idx = LEFT_MIXER, idx;
+ u32 flush_mask = 0;
+ uint32_t lm_idx = LEFT_MIXER, stage_idx;
bool bg_alpha_enable[CRTC_DUAL_MIXERS] = {false};
- bool lm_right = false;
- int left_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0};
- int right_crtc_zpos_cnt[SDE_STAGE_MAX + 1] = {0};
+ int zpos_cnt[CRTC_DUAL_MIXERS][SDE_STAGE_MAX + 1] = { {0} };
int i;
bool sbuf_mode = false;
u32 prefill = 0;
@@ -691,13 +1035,18 @@
ctl = mixer->hw_ctl;
lm = mixer->hw_lm;
stage_cfg = &sde_crtc->stage_cfg;
- crtc_split_width = get_crtc_split_width(crtc);
+ cstate = to_sde_crtc_state(crtc->state);
drm_atomic_crtc_for_each_plane(plane, crtc) {
state = plane->state;
if (!state)
continue;
+ plane_crtc_roi.x = state->crtc_x;
+ plane_crtc_roi.y = state->crtc_y;
+ plane_crtc_roi.w = state->crtc_w;
+ plane_crtc_roi.h = state->crtc_h;
+
pstate = to_sde_plane_state(state);
fb = state->fb;
@@ -706,25 +1055,6 @@
sde_plane_get_ctl_flush(plane, ctl, &flush_mask);
- /* always stage plane on either left or right lm */
- if (state->crtc_x >= crtc_split_width) {
- lm_idx = RIGHT_MIXER;
- idx = right_crtc_zpos_cnt[pstate->stage]++;
- } else {
- lm_idx = LEFT_MIXER;
- idx = left_crtc_zpos_cnt[pstate->stage]++;
- }
-
- /* stage plane on right LM if it crosses the boundary */
- lm_right = (lm_idx == LEFT_MIXER) &&
- (state->crtc_x + state->crtc_w > crtc_split_width);
-
- stage_cfg->stage[lm_idx][pstate->stage][idx] =
- sde_plane_pipe(plane);
- stage_cfg->multirect_index
- [lm_idx][pstate->stage][idx] =
- pstate->multirect_index;
- mixer[lm_idx].flush_mask |= flush_mask;
SDE_DEBUG("crtc %d stage:%d - plane %d sspp %d fb %d\n",
crtc->base.id,
@@ -735,50 +1065,52 @@
format = to_sde_format(msm_framebuffer_format(pstate->base.fb));
- SDE_EVT32(DRMID(plane), state->src_x, state->src_y,
- state->src_w >> 16, state->src_h >> 16, state->crtc_x,
- state->crtc_y, state->crtc_w, state->crtc_h);
- SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, lm_right,
- pstate->stage, pstate->multirect_index,
- pstate->multirect_mode, format->base.pixel_format,
- fb ? fb->modifier[0] : 0);
+ SDE_EVT32(DRMID(crtc), DRMID(plane),
+ state->fb ? state->fb->base.id : -1,
+ state->src_x >> 16, state->src_y >> 16,
+ state->src_w >> 16, state->src_h >> 16,
+ state->crtc_x, state->crtc_y,
+ state->crtc_w, state->crtc_h);
- /* blend config update */
- if (pstate->stage != SDE_STAGE_BASE) {
- _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate,
- format);
+ for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+ struct sde_rect intersect;
- if (bg_alpha_enable[lm_idx] && !format->alpha_enable)
- mixer[lm_idx].mixer_op_mode = 0;
- else
- mixer[lm_idx].mixer_op_mode |=
- 1 << pstate->stage;
- } else if (format->alpha_enable) {
- bg_alpha_enable[lm_idx] = true;
- }
+ /* skip if the roi doesn't fall within LM's bounds */
+ sde_kms_rect_intersect(&plane_crtc_roi,
+ &cstate->lm_bounds[lm_idx],
+ &intersect);
+ if (sde_kms_rect_is_null(&intersect))
+ continue;
- if (lm_right) {
- idx = right_crtc_zpos_cnt[pstate->stage]++;
- stage_cfg->stage[RIGHT_MIXER][pstate->stage][idx] =
- sde_plane_pipe(plane);
+ stage_idx = zpos_cnt[lm_idx][pstate->stage]++;
+ stage_cfg->stage[lm_idx][pstate->stage][stage_idx] =
+ sde_plane_pipe(plane);
stage_cfg->multirect_index
- [RIGHT_MIXER][pstate->stage][idx] =
- pstate->multirect_index;
- mixer[RIGHT_MIXER].flush_mask |= flush_mask;
+ [lm_idx][pstate->stage][stage_idx] =
+ pstate->multirect_index;
+
+ mixer[lm_idx].flush_mask |= flush_mask;
+
+
+ SDE_EVT32(DRMID(plane), DRMID(crtc), lm_idx, stage_idx,
+ pstate->stage, pstate->multirect_index,
+ pstate->multirect_mode,
+ format->base.pixel_format,
+ fb ? fb->modifier[0] : 0);
/* blend config update */
if (pstate->stage != SDE_STAGE_BASE) {
- _sde_crtc_setup_blend_cfg(mixer + RIGHT_MIXER,
- pstate, format);
+ _sde_crtc_setup_blend_cfg(mixer + lm_idx,
+ pstate, format);
- if (bg_alpha_enable[RIGHT_MIXER] &&
+ if (bg_alpha_enable[lm_idx] &&
!format->alpha_enable)
- mixer[RIGHT_MIXER].mixer_op_mode = 0;
+ mixer[lm_idx].mixer_op_mode = 0;
else
- mixer[RIGHT_MIXER].mixer_op_mode |=
+ mixer[lm_idx].mixer_op_mode |=
1 << pstate->stage;
} else if (format->alpha_enable) {
- bg_alpha_enable[RIGHT_MIXER] = true;
+ bg_alpha_enable[lm_idx] = true;
}
}
}
@@ -804,6 +1136,8 @@
ctl->ops.setup_sbuf_cfg(ctl, &cstate->sbuf_cfg);
}
+
+ _sde_crtc_program_lm_output_roi(crtc);
}
/**
@@ -869,6 +1203,8 @@
ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
&sde_crtc->stage_cfg, i);
}
+
+ _sde_crtc_program_lm_output_roi(crtc);
}
void sde_crtc_prepare_commit(struct drm_crtc *crtc,
@@ -1296,9 +1632,48 @@
_sde_crtc_setup_mixer_for_encoder(crtc, enc);
}
+
mutex_unlock(&sde_crtc->crtc_lock);
}
+static void _sde_crtc_setup_lm_bounds(struct drm_crtc *crtc,
+ struct drm_crtc_state *state)
+{
+ struct sde_crtc *sde_crtc;
+ struct sde_crtc_state *cstate;
+ struct drm_display_mode *adj_mode;
+ u32 crtc_split_width;
+ int i;
+
+ if (!crtc || !state) {
+ SDE_ERROR("invalid args\n");
+ return;
+ }
+
+ sde_crtc = to_sde_crtc(crtc);
+ cstate = to_sde_crtc_state(state);
+
+ adj_mode = &state->adjusted_mode;
+ crtc_split_width = sde_crtc_mixer_width(sde_crtc, adj_mode);
+
+ for (i = 0; i < sde_crtc->num_mixers; i++) {
+ cstate->lm_bounds[i].x = crtc_split_width * i;
+ cstate->lm_bounds[i].y = 0;
+ cstate->lm_bounds[i].w = crtc_split_width;
+ cstate->lm_bounds[i].h = adj_mode->vdisplay;
+ memcpy(&cstate->lm_roi[i], &cstate->lm_bounds[i],
+ sizeof(cstate->lm_roi[i]));
+ SDE_EVT32(DRMID(crtc), i,
+ cstate->lm_bounds[i].x, cstate->lm_bounds[i].y,
+ cstate->lm_bounds[i].w, cstate->lm_bounds[i].h);
+ SDE_DEBUG("%s: lm%d bnd&roi (%d,%d,%d,%d)\n", sde_crtc->name, i,
+ cstate->lm_roi[i].x, cstate->lm_roi[i].y,
+ cstate->lm_roi[i].w, cstate->lm_roi[i].h);
+ }
+
+ drm_mode_debug_printmodeline(adj_mode);
+}
+
static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -1323,8 +1698,10 @@
sde_crtc = to_sde_crtc(crtc);
dev = crtc->dev;
- if (!sde_crtc->num_mixers)
+ if (!sde_crtc->num_mixers) {
_sde_crtc_setup_mixers(crtc);
+ _sde_crtc_setup_lm_bounds(crtc, crtc->state);
+ }
if (sde_crtc->event) {
WARN_ON(sde_crtc->event);
@@ -1414,7 +1791,7 @@
continue;
cstate->rsc_client =
- sde_encoder_update_rsc_client(encoder, true);
+ sde_encoder_get_rsc_client(encoder);
}
cstate->rsc_update = true;
}
@@ -1751,7 +2128,6 @@
if (encoder->crtc != crtc)
continue;
sde_encoder_register_frame_event_callback(encoder, NULL, NULL);
- sde_encoder_update_rsc_client(encoder, false);
cstate->rsc_client = NULL;
cstate->rsc_update = false;
}
@@ -1776,13 +2152,10 @@
static void sde_crtc_enable(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc;
- struct sde_crtc_mixer *mixer;
- struct sde_hw_mixer *lm;
- struct drm_display_mode *mode;
struct drm_encoder *encoder;
unsigned long flags;
struct sde_crtc_irq_info *node = NULL;
- int i, ret;
+ int ret;
if (!crtc) {
SDE_ERROR("invalid crtc\n");
@@ -1791,16 +2164,7 @@
SDE_DEBUG("crtc%d\n", crtc->base.id);
SDE_EVT32(DRMID(crtc));
-
sde_crtc = to_sde_crtc(crtc);
- mixer = sde_crtc->mixers;
-
- if (WARN_ON(!crtc->state))
- return;
-
- mode = &crtc->state->adjusted_mode;
-
- drm_mode_debug_printmodeline(mode);
drm_for_each_encoder(encoder, crtc->dev) {
if (encoder->crtc != crtc)
@@ -1809,15 +2173,6 @@
sde_crtc_frame_event_cb, (void *)crtc);
}
- for (i = 0; i < sde_crtc->num_mixers; i++) {
- lm = mixer[i].hw_lm;
- lm->cfg.out_width = sde_crtc_mixer_width(sde_crtc, mode);
- lm->cfg.out_height = mode->vdisplay;
- lm->cfg.right_mixer = (i == 0) ? false : true;
- lm->cfg.flags = 0;
- lm->ops.setup_mixer_out(lm, &lm->cfg);
- }
-
spin_lock_irqsave(&sde_crtc->spin_lock, flags);
list_for_each_entry(node, &sde_crtc->user_event_list, list) {
ret = 0;
@@ -1894,6 +2249,8 @@
mixer_width = sde_crtc_mixer_width(sde_crtc, mode);
+ _sde_crtc_setup_lm_bounds(crtc, state);
+
/* get plane state for all drm planes associated with crtc state */
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
if (IS_ERR_OR_NULL(pstate)) {
@@ -2092,6 +2449,11 @@
}
}
+ rc = _sde_crtc_check_rois(crtc, state);
+ if (rc) {
+ SDE_ERROR("crtc%d failed roi check %d\n", crtc->base.id, rc);
+ goto end;
+ }
end:
_sde_crtc_rp_free_unused(&cstate->rp);
@@ -2218,6 +2580,9 @@
"dim_layer_v1", 0x0, 0, ~0, 0, CRTC_PROP_DIM_LAYER_V1);
}
+ msm_property_install_volatile_range(&sde_crtc->property_info,
+ "sde_drm_roi_v1", 0x0, 0, ~0, 0, CRTC_PROP_ROI_V1);
+
sde_kms_info_reset(info);
sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion);
@@ -2290,6 +2655,9 @@
case CRTC_PROP_DIM_LAYER_V1:
_sde_crtc_set_dim_layer_v1(cstate, (void *)val);
break;
+ case CRTC_PROP_ROI_V1:
+ ret = _sde_crtc_set_roi_v1(state, (void *)val);
+ break;
default:
/* nothing to do */
break;
@@ -2339,19 +2707,28 @@
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
int i, ret = -EINVAL;
+ bool conn_offset = 0;
if (!crtc || !state) {
SDE_ERROR("invalid argument(s)\n");
} else {
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(state);
+
+ for (i = 0; i < cstate->num_connectors; ++i) {
+ conn_offset = sde_connector_needs_offset(
+ cstate->connectors[i]);
+ if (conn_offset)
+ break;
+ }
+
i = msm_property_index(&sde_crtc->property_info, property);
if (i == CRTC_PROP_OUTPUT_FENCE) {
uint32_t offset = sde_crtc_get_property(cstate,
CRTC_PROP_OUTPUT_FENCE_OFFSET);
- ret = sde_fence_create(
- &sde_crtc->output_fence, val, offset);
+ ret = sde_fence_create(&sde_crtc->output_fence, val,
+ offset + conn_offset);
if (ret)
SDE_ERROR("fence create failed\n");
} else {
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 19ae27f..7ad0955 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -108,7 +108,7 @@
* @name : ASCII description of this crtc
* @num_ctls : Number of ctl paths in use
* @num_mixers : Number of mixers in use
- * @mixer : List of active mixers
+ * @mixers : List of active mixers
* @event : Pointer to last received drm vblank event. If there is a
* pending vblank event, this will be non-null.
* @vsync_count : Running count of received vsync events
@@ -248,6 +248,13 @@
* @num_connectors: Number of associated drm connectors
* @intf_mode : Interface mode of the primary connector
* @rsc_client : sde rsc client when mode is valid
+ * @lm_bounds : LM boundaries based on current mode full resolution, no ROI.
+ * Origin top left of CRTC.
+ * @crtc_roi : Current CRTC ROI. Possibly sub-rectangle of mode.
+ * Origin top left of CRTC.
+ * @lm_roi : Current LM ROI, possibly sub-rectangle of mode.
+ * Origin top left of CRTC.
+ * @user_roi_list : List of user's requested ROIs as from set property
* @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns
* @property_blobs: Reference pointers for blob properties
@@ -267,6 +274,11 @@
struct sde_rsc_client *rsc_client;
bool rsc_update;
+ struct sde_rect lm_bounds[CRTC_DUAL_MIXERS];
+ struct sde_rect crtc_roi;
+ struct sde_rect lm_roi[CRTC_DUAL_MIXERS];
+ struct msm_roi_list user_roi_list;
+
uint64_t property_values[CRTC_PROP_COUNT];
uint64_t input_fence_timeout_ns;
struct drm_property_blob *property_blobs[CRTC_PROP_COUNT];
@@ -303,30 +315,6 @@
mode->hdisplay / CRTC_DUAL_MIXERS : mode->hdisplay;
}
-static inline uint32_t get_crtc_split_width(struct drm_crtc *crtc)
-{
- struct drm_display_mode *mode;
- struct sde_crtc *sde_crtc;
-
- if (!crtc || !crtc->state)
- return 0;
-
- sde_crtc = to_sde_crtc(crtc);
- mode = &crtc->state->adjusted_mode;
- return sde_crtc_mixer_width(sde_crtc, mode);
-}
-
-static inline uint32_t get_crtc_mixer_height(struct drm_crtc *crtc)
-{
- struct drm_display_mode *mode;
-
- if (!crtc || !crtc->state)
- return 0;
-
- mode = &crtc->state->adjusted_mode;
- return mode->vdisplay;
-}
-
/**
* sde_crtc_vblank - enable or disable vblanks for this crtc
* @crtc: Pointer to drm crtc object
@@ -453,4 +441,14 @@
*/
void sde_crtc_res_put(struct drm_crtc_state *state, u32 type, u64 tag);
+/**
+ * sde_crtc_get_crtc_roi - retrieve the crtc_roi from the given state object
+ * used to allow the planes to adjust their final lm out_xy value in the
+ * case of partial update
+ * @crtc_state: Pointer to crtc state
+ * @crtc_roi: Output pointer to crtc roi in the given state
+ */
+void sde_crtc_get_crtc_roi(struct drm_crtc_state *state,
+ const struct sde_rect **crtc_roi);
+
#endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 67fb783..742ea20 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -284,6 +284,24 @@
}
}
+static void _sde_encoder_adjust_mode(struct drm_connector *connector,
+ struct drm_display_mode *adj_mode)
+{
+ struct drm_display_mode *cur_mode;
+
+ if (!connector || !adj_mode)
+ return;
+
+ list_for_each_entry(cur_mode, &connector->modes, head) {
+ if (cur_mode->vdisplay == adj_mode->vdisplay &&
+ cur_mode->hdisplay == adj_mode->hdisplay &&
+ cur_mode->vrefresh == adj_mode->vrefresh) {
+ adj_mode->private = cur_mode->private;
+ adj_mode->private_flags = cur_mode->private_flags;
+ }
+ }
+}
+
static int sde_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
@@ -312,6 +330,15 @@
adj_mode = &crtc_state->adjusted_mode;
SDE_EVT32(DRMID(drm_enc));
+ /*
+ * display drivers may populate private fields of the drm display mode
+ * structure while registering possible modes of a connector with DRM.
+ * These private fields are not populated back while DRM invokes
+ * the mode_set callbacks. This module retrieves and populates the
+ * private fields of the given mode.
+ */
+ _sde_encoder_adjust_mode(conn_state->connector, adj_mode);
+
/* perform atomic check on the first physical encoder (master) */
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
@@ -656,6 +683,71 @@
return ret;
}
+static int sde_encoder_update_rsc_client(
+ struct drm_encoder *drm_enc, bool enable)
+{
+ struct sde_encoder_virt *sde_enc;
+ enum sde_rsc_state rsc_state;
+ struct sde_rsc_cmd_config rsc_config;
+ int ret;
+ struct msm_display_info *disp_info;
+
+ if (!drm_enc) {
+ SDE_ERROR("invalid encoder\n");
+ return -EINVAL;
+ }
+
+ sde_enc = to_sde_encoder_virt(drm_enc);
+ disp_info = &sde_enc->disp_info;
+
+ /**
+ * only primary command mode panel can request CMD state.
+ * all other panels/displays can request for VID state including
+ * secondary command mode panel.
+ */
+ rsc_state = enable ?
+ (((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) &&
+ disp_info->is_primary) ? SDE_RSC_CMD_STATE :
+ SDE_RSC_VID_STATE) : SDE_RSC_IDLE_STATE;
+
+ if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_update
+ && disp_info->is_primary) {
+ rsc_config.fps = disp_info->frame_rate;
+ rsc_config.vtotal = disp_info->vtotal;
+ rsc_config.prefill_lines = disp_info->prefill_lines;
+ rsc_config.jitter = disp_info->jitter;
+ /* update it only once */
+ sde_enc->rsc_state_update = true;
+
+ ret = sde_rsc_client_state_update(sde_enc->rsc_client,
+ rsc_state, &rsc_config,
+ drm_enc->crtc ? drm_enc->crtc->index : -1);
+ } else {
+ ret = sde_rsc_client_state_update(sde_enc->rsc_client,
+ rsc_state, NULL,
+ drm_enc->crtc ? drm_enc->crtc->index : -1);
+ }
+
+ if (ret)
+ SDE_ERROR("sde rsc client update failed ret:%d\n", ret);
+
+ return ret;
+}
+
+struct sde_rsc_client *sde_encoder_get_rsc_client(struct drm_encoder *drm_enc)
+{
+ struct sde_encoder_virt *sde_enc;
+ struct msm_display_info *disp_info;
+
+ if (!drm_enc)
+ return NULL;
+
+ sde_enc = to_sde_encoder_virt(drm_enc);
+ disp_info = &sde_enc->disp_info;
+
+ return disp_info->is_primary ? sde_enc->rsc_client : NULL;
+}
+
static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
@@ -778,6 +870,8 @@
}
}
+ sde_encoder_update_rsc_client(drm_enc, true);
+
if (!sde_enc->cur_master)
SDE_ERROR("virt encoder has no master! num_phys %d\n", i);
else if (sde_enc->cur_master->ops.enable)
@@ -833,6 +927,8 @@
del_timer_sync(&sde_enc->frame_done_timer);
}
+ sde_encoder_update_rsc_client(drm_enc, false);
+
if (sde_enc->cur_master && sde_enc->cur_master->ops.disable)
sde_enc->cur_master->ops.disable(sde_enc->cur_master);
@@ -927,57 +1023,6 @@
}
}
-struct sde_rsc_client *sde_encoder_update_rsc_client(
- struct drm_encoder *drm_enc, bool enable)
-{
- struct sde_encoder_virt *sde_enc;
- enum sde_rsc_state rsc_state;
- struct sde_rsc_cmd_config rsc_config;
- int ret;
- struct msm_display_info *disp_info;
-
- if (!drm_enc) {
- SDE_ERROR("invalid encoder\n");
- return NULL;
- }
-
- sde_enc = to_sde_encoder_virt(drm_enc);
- disp_info = &sde_enc->disp_info;
-
- /**
- * only primary command mode panel can request CMD state.
- * all other panels/displays can request for VID state including
- * secondary command mode panel.
- */
- rsc_state = enable ?
- (((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) &&
- disp_info->is_primary) ? SDE_RSC_CMD_STATE :
- SDE_RSC_VID_STATE) : SDE_RSC_IDLE_STATE;
-
- if (rsc_state != SDE_RSC_IDLE_STATE && !sde_enc->rsc_state_update
- && disp_info->is_primary) {
- rsc_config.fps = disp_info->frame_rate;
- rsc_config.vtotal = disp_info->vtotal;
- rsc_config.prefill_lines = disp_info->prefill_lines;
- rsc_config.jitter = disp_info->jitter;
- /* update it only once */
- sde_enc->rsc_state_update = true;
-
- ret = sde_rsc_client_state_update(sde_enc->rsc_client,
- rsc_state, &rsc_config,
- drm_enc->crtc ? drm_enc->crtc->index : -1);
- } else {
- ret = sde_rsc_client_state_update(sde_enc->rsc_client,
- rsc_state, NULL,
- drm_enc->crtc ? drm_enc->crtc->index : -1);
- }
-
- if (ret)
- SDE_ERROR("sde rsc client update failed ret:%d\n", ret);
-
- return sde_enc->disp_info.is_primary ? sde_enc->rsc_client : NULL;
-}
-
void sde_encoder_register_frame_event_callback(struct drm_encoder *drm_enc,
void (*frame_event_cb)(void *, u32 event),
void *frame_event_cb_data)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index cdecd08..5795e04 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -83,13 +83,11 @@
void (*cb)(void *, u32), void *data);
/**
- * sde_encoder_update_rsc_client - updates the rsc client state for primary
+ * sde_encoder_get_rsc_client - gets the rsc client state for primary
* for primary display.
* @encoder: encoder pointer
- * @enable: enable/disable the client
*/
-struct sde_rsc_client *sde_encoder_update_rsc_client(
- struct drm_encoder *encoder, bool enable);
+struct sde_rsc_client *sde_encoder_get_rsc_client(struct drm_encoder *encoder);
/**
* sde_encoder_prepare_for_kickoff - schedule double buffer flip of the ctl
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 11cca1f..cfa3b5e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -490,8 +490,8 @@
return 0;
for (i = 0, cur_pos = dst_list_pos;
- (cur_pos < (dst_list_size - 1)) && src_list[i].fourcc_format
- && (i < src_list_size); ++i, ++cur_pos)
+ (cur_pos < (dst_list_size - 1)) && (i < src_list_size)
+ && src_list[i].fourcc_format; ++i, ++cur_pos)
dst_list[cur_pos] = src_list[i];
dst_list[cur_pos].fourcc_format = 0;
@@ -565,7 +565,7 @@
rc = -EINVAL;
}
*off_count = 0;
- memset(prop_count, 0, sizeof(int *) * prop_size);
+ memset(prop_count, 0, sizeof(int) * prop_size);
return rc;
}
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_hwio.h b/drivers/gpu/drm/msm/sde/sde_hw_hwio.h
deleted file mode 100644
index e69de29..0000000
--- a/drivers/gpu/drm/msm/sde/sde_hw_hwio.h
+++ /dev/null
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 98c59c3..4a5479d 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -348,9 +348,16 @@
static void sde_kms_prepare_commit(struct msm_kms *kms,
struct drm_atomic_state *state)
{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- struct drm_device *dev = sde_kms->dev;
- struct msm_drm_private *priv = dev->dev_private;
+ struct sde_kms *sde_kms;
+ struct msm_drm_private *priv;
+
+ if (!kms)
+ return;
+ sde_kms = to_sde_kms(kms);
+
+ if (!sde_kms->dev || !sde_kms->dev->dev_private)
+ return;
+ priv = sde_kms->dev->dev_private;
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
}
@@ -373,13 +380,20 @@
static void sde_kms_complete_commit(struct msm_kms *kms,
struct drm_atomic_state *old_state)
{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- struct drm_device *dev = sde_kms->dev;
- struct msm_drm_private *priv = dev->dev_private;
+ struct sde_kms *sde_kms;
+ struct msm_drm_private *priv;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
+ if (!kms || !old_state)
+ return;
+ sde_kms = to_sde_kms(kms);
+
+ if (!sde_kms->dev || !sde_kms->dev->dev_private)
+ return;
+ priv = sde_kms->dev->dev_private;
+
for_each_crtc_in_state(old_state, crtc, old_crtc_state, i)
sde_crtc_complete_commit(crtc, old_crtc_state);
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
@@ -552,7 +566,8 @@
.get_info = dsi_display_get_info,
.set_backlight = dsi_display_set_backlight,
.soft_reset = dsi_display_soft_reset,
- .pre_kickoff = dsi_conn_pre_kickoff
+ .pre_kickoff = dsi_conn_pre_kickoff,
+ .clk_ctrl = dsi_display_clk_ctrl
};
static const struct sde_connector_ops wb_ops = {
.post_init = sde_wb_connector_post_init,
@@ -1515,7 +1530,7 @@
}
rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
- &priv->phandle, priv->pclient, "core_clk_src");
+ &priv->phandle, priv->pclient, "core_clk");
if (rc) {
SDE_ERROR("failed to init perf %d\n", rc);
goto perf_err;
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index bd6b302..8662207 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2204,6 +2204,7 @@
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct sde_rect src, dst;
+ const struct sde_rect *crtc_roi;
bool q16_data = true;
int idx;
@@ -2283,6 +2284,11 @@
}
}
+ /* re-program the output rects always in the case of partial update */
+ sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
+ if (!sde_kms_rect_is_null(crtc_roi))
+ pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+
if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
@@ -2320,6 +2326,13 @@
src.y &= ~0x1;
}
+ /*
+ * adjust layer mixer position of the sspp in the presence
+ * of a partial update to the active lm origin
+ */
+ dst.x -= crtc_roi->x;
+ dst.y -= crtc_roi->y;
+
psde->pipe_cfg.src_rect = src;
psde->pipe_cfg.dst_rect = dst;
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 62efe8e..9a68dbe 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -25,10 +25,44 @@
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <linux/sde_io_util.h>
+#include <linux/sde_rsc.h>
#include "sde_power_handle.h"
#include "sde_trace.h"
+static void sde_power_event_trigger_locked(struct sde_power_handle *phandle,
+ u32 event_type)
+{
+ struct sde_power_event *event;
+
+ list_for_each_entry(event, &phandle->event_list, list) {
+ if (event->event_type & event_type)
+ event->cb_fnc(event_type, event->usr);
+ }
+}
+
+static int sde_power_rsc_update(struct sde_power_handle *phandle, bool enable)
+{
+ u32 rsc_state;
+
+ /* creates the rsc client on the first enable */
+ if (!phandle->rsc_client_init) {
+ phandle->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX,
+ "sde_power_handle", false);
+ if (IS_ERR_OR_NULL(phandle->rsc_client)) {
+ pr_debug("sde rsc client create failed :%ld\n",
+ PTR_ERR(phandle->rsc_client));
+ phandle->rsc_client = NULL;
+ }
+ phandle->rsc_client_init = true;
+ }
+
+ rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE;
+
+ return sde_rsc_client_state_update(phandle->rsc_client,
+ rsc_state, NULL, -1);
+}
+
struct sde_power_client *sde_power_client_create(
struct sde_power_handle *phandle, char *client_name)
{
@@ -48,6 +82,7 @@
strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
client->usecase_ndx = VOTE_INDEX_DISABLE;
client->id = id;
+ client->active = true;
pr_debug("client %s created:%pK id :%d\n", client_name,
client, id);
id++;
@@ -62,6 +97,9 @@
{
if (!client || !phandle) {
pr_err("reg bus vote: invalid client handle\n");
+ } else if (!client->active) {
+ pr_err("sde power deinit already done\n");
+ kfree(client);
} else {
pr_debug("bus vote client %s destroyed:%pK id:%u\n",
client->name, client, client->id);
@@ -661,6 +699,11 @@
}
INIT_LIST_HEAD(&phandle->power_client_clist);
+ INIT_LIST_HEAD(&phandle->event_list);
+
+ phandle->rsc_client = NULL;
+ phandle->rsc_client_init = false;
+
mutex_init(&phandle->phandle_lock);
return rc;
@@ -672,10 +715,12 @@
clk_err:
msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0);
vreg_err:
- devm_kfree(&pdev->dev, mp->vreg_config);
+ if (mp->vreg_config)
+ devm_kfree(&pdev->dev, mp->vreg_config);
mp->num_vreg = 0;
parse_vreg_err:
- devm_kfree(&pdev->dev, mp->clk_config);
+ if (mp->clk_config)
+ devm_kfree(&pdev->dev, mp->clk_config);
mp->num_clk = 0;
end:
return rc;
@@ -685,6 +730,8 @@
struct sde_power_handle *phandle)
{
struct dss_module_power *mp;
+ struct sde_power_client *curr_client, *next_client;
+ struct sde_power_event *curr_event, *next_event;
if (!phandle || !pdev) {
pr_err("invalid input param\n");
@@ -692,6 +739,26 @@
}
mp = &phandle->mp;
+ mutex_lock(&phandle->phandle_lock);
+ list_for_each_entry_safe(curr_client, next_client,
+ &phandle->power_client_clist, list) {
+ pr_err("cliend:%s-%d still registered with refcount:%d\n",
+ curr_client->name, curr_client->id,
+ curr_client->refcount);
+ curr_client->active = false;
+ list_del(&curr_client->list);
+ }
+
+ list_for_each_entry_safe(curr_event, next_event,
+ &phandle->event_list, list) {
+ pr_err("event:%d, client:%s still registered\n",
+ curr_event->event_type,
+ curr_event->client_name);
+ curr_event->active = false;
+ list_del(&curr_event->list);
+ }
+ mutex_unlock(&phandle->phandle_lock);
+
sde_power_data_bus_unregister(&phandle->data_bus_handle);
sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
@@ -708,6 +775,9 @@
mp->num_vreg = 0;
mp->num_clk = 0;
+
+ if (phandle->rsc_client)
+ sde_rsc_client_destroy(phandle->rsc_client);
}
int sde_power_resource_enable(struct sde_power_handle *phandle,
@@ -757,6 +827,9 @@
goto end;
if (enable) {
+ sde_power_event_trigger_locked(phandle,
+ SDE_POWER_EVENT_PRE_ENABLE);
+
rc = sde_power_data_bus_update(&phandle->data_bus_handle,
enable);
if (rc) {
@@ -764,10 +837,13 @@
goto data_bus_hdl_err;
}
- rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
- if (rc) {
- pr_err("failed to enable vregs rc=%d\n", rc);
- goto vreg_err;
+ if (!phandle->rsc_client_init) {
+ rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
+ enable);
+ if (rc) {
+ pr_err("failed to enable vregs rc=%d\n", rc);
+ goto vreg_err;
+ }
}
rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
@@ -777,20 +853,39 @@
goto reg_bus_hdl_err;
}
+ rc = sde_power_rsc_update(phandle, true);
+ if (rc) {
+ pr_err("failed to update rsc\n");
+ goto rsc_err;
+ }
+
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
if (rc) {
pr_err("clock enable failed rc:%d\n", rc);
goto clk_err;
}
+
+ sde_power_event_trigger_locked(phandle,
+ SDE_POWER_EVENT_POST_ENABLE);
+
} else {
+ sde_power_event_trigger_locked(phandle,
+ SDE_POWER_EVENT_PRE_DISABLE);
+
msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
+ sde_power_rsc_update(phandle, false);
+
sde_power_reg_bus_update(phandle->reg_bus_hdl,
max_usecase_ndx);
- msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
-
+ if (!phandle->rsc_client_init)
+ msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
+ enable);
sde_power_data_bus_update(&phandle->data_bus_handle, enable);
+
+ sde_power_event_trigger_locked(phandle,
+ SDE_POWER_EVENT_POST_DISABLE);
}
end:
@@ -798,9 +893,12 @@
return rc;
clk_err:
+ sde_power_rsc_update(phandle, false);
+rsc_err:
sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx);
reg_bus_hdl_err:
- msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
+ if (!phandle->rsc_client_init)
+ msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
vreg_err:
sde_power_data_bus_update(&phandle->data_bus_handle, 0);
data_bus_hdl_err:
@@ -903,3 +1001,52 @@
return clk;
}
+
+struct sde_power_event *sde_power_handle_register_event(
+ struct sde_power_handle *phandle,
+ u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
+ void *usr, char *client_name)
+{
+ struct sde_power_event *event;
+
+ if (!phandle) {
+ pr_err("invalid power handle\n");
+ return ERR_PTR(-EINVAL);
+ } else if (!cb_fnc || !event_type) {
+ pr_err("no callback fnc or event type\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ event = kzalloc(sizeof(struct sde_power_event), GFP_KERNEL);
+ if (!event)
+ return ERR_PTR(-ENOMEM);
+
+ event->event_type = event_type;
+ event->cb_fnc = cb_fnc;
+ event->usr = usr;
+ strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
+ event->active = true;
+
+ mutex_lock(&phandle->phandle_lock);
+ list_add(&event->list, &phandle->event_list);
+ mutex_unlock(&phandle->phandle_lock);
+
+ return event;
+}
+
+void sde_power_handle_unregister_event(
+ struct sde_power_handle *phandle,
+ struct sde_power_event *event)
+{
+ if (!phandle || !event) {
+ pr_err("invalid phandle or event\n");
+ } else if (!event->active) {
+ pr_err("power handle deinit already done\n");
+ kfree(event);
+ } else {
+ mutex_lock(&phandle->phandle_lock);
+ list_del_init(&event->list);
+ mutex_unlock(&phandle->phandle_lock);
+ kfree(event);
+ }
+}
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index 4e262a3..b26ef9f 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -23,6 +23,18 @@
#include <linux/sde_io_util.h>
+/* event will be triggered before power handler disable */
+#define SDE_POWER_EVENT_PRE_DISABLE 0x1
+
+/* event will be triggered after power handler disable */
+#define SDE_POWER_EVENT_POST_DISABLE 0x2
+
+/* event will be triggered before power handler enable */
+#define SDE_POWER_EVENT_PRE_ENABLE 0x4
+
+/* event will be triggered after power handler enable */
+#define SDE_POWER_EVENT_POST_ENABLE 0x8
+
/**
* mdss_bus_vote_type: register bus vote type
* VOTE_INDEX_DISABLE: removes the client vote
@@ -59,6 +71,7 @@
* @list: list to attach power handle master list
* @ab: arbitrated bandwidth for each bus client
* @ib: instantaneous bandwidth for each bus client
+ * @active: inidcates the state of sde power handle
*/
struct sde_power_client {
char name[MAX_CLIENT_NAME_LEN];
@@ -68,6 +81,7 @@
struct list_head list;
u64 ab[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
u64 ib[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
+ bool active;
};
/**
@@ -90,6 +104,24 @@
u32 ao_bw_uc_idx;
};
+/*
+ * struct sde_power_event - local event registration structure
+ * @client_name: name of the client registering
+ * @cb_fnc: pointer to desired callback function
+ * @usr: user pointer to pass to callback event trigger
+ * @event: refer to SDE_POWER_HANDLE_EVENT_*
+ * @list: list to attach event master list
+ * @active: indicates the state of sde power handle
+ */
+struct sde_power_event {
+ char client_name[MAX_CLIENT_NAME_LEN];
+ void (*cb_fnc)(u32 event_type, void *usr);
+ void *usr;
+ u32 event_type;
+ struct list_head list;
+ bool active;
+};
+
/**
* struct sde_power_handle: power handle main struct
* @mp: module power for clock and regulator
@@ -99,6 +131,9 @@
* @usecase_ndx: current usecase index
* @reg_bus_hdl: current register bus handle
* @data_bus_handle: context structure for data bus control
+ * @event_list: current power handle event list
+ * @rsc_client: sde rsc client pointer
+ * @rsc_client_init: boolean to control rsc client create
*/
struct sde_power_handle {
struct dss_module_power mp;
@@ -108,6 +143,9 @@
u32 current_usecase_ndx;
u32 reg_bus_hdl;
struct sde_power_data_bus_handle data_bus_handle;
+ struct list_head event_list;
+ struct sde_rsc_client *rsc_client;
+ bool rsc_client_init;
};
/**
@@ -226,4 +264,28 @@
void sde_power_data_bus_bandwidth_ctrl(struct sde_power_handle *phandle,
struct sde_power_client *pclient, int enable);
+/**
+ * sde_power_handle_register_event - register a callback function for an event.
+ * Clients can register for multiple events with a single register.
+ * Any block with access to phandle can register for the event
+ * notification.
+ * @phandle: power handle containing the resources
+ * @event_type: event type to register; refer SDE_POWER_HANDLE_EVENT_*
+ * @cb_fnc: pointer to desired callback function
+ * @usr: user pointer to pass to callback on event trigger
+ *
+ * Return: event pointer if success, or error code otherwise
+ */
+struct sde_power_event *sde_power_handle_register_event(
+ struct sde_power_handle *phandle,
+ u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
+ void *usr, char *client_name);
+/**
+ * sde_power_handle_unregister_event - unregister callback for event(s)
+ * @phandle: power handle containing the resources
+ * @event: event pointer returned after power handle register
+ */
+void sde_power_handle_unregister_event(struct sde_power_handle *phandle,
+ struct sde_power_event *event);
+
#endif /* _SDE_POWER_HANDLE_H_ */
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index e0d7f84..d741ff8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -714,7 +714,7 @@
.i2c = nv04_i2c_new,
.imem = nv40_instmem_new,
.mc = nv44_mc_new,
- .mmu = nv44_mmu_new,
+ .mmu = nv04_mmu_new,
.pci = nv40_pci_new,
.therm = nv40_therm_new,
.timer = nv41_timer_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index fbb8c7d..0d65e7f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -433,8 +433,6 @@
case 0x94:
case 0x96:
case 0x98:
- case 0xaa:
- case 0xac:
return true;
default:
break;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
index 003ac91..8a88952 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
@@ -198,7 +198,7 @@
}
if (type == 0x00000010) {
- if (!nv31_mpeg_mthd(mpeg, mthd, data))
+ if (nv31_mpeg_mthd(mpeg, mthd, data))
show &= ~0x01000000;
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
index e536f37..c3cf02e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
@@ -172,7 +172,7 @@
}
if (type == 0x00000010) {
- if (!nv44_mpeg_mthd(subdev->device, mthd, data))
+ if (nv44_mpeg_mthd(subdev->device, mthd, data))
show &= ~0x01000000;
}
}
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index fddfb2c..28d93a9 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -718,9 +718,9 @@
#define A6XX_GMU_GENERAL_7 0x1F9CC
#define A6XX_GMU_AO_INTERRUPT_EN 0x23B03
-#define A6XX_GMU_HOST_INTERRUPT_CLR 0x23B04
-#define A6XX_GMU_HOST_INTERRUPT_STATUS 0x23B05
-#define A6XX_GMU_HOST_INTERRUPT_MASK 0x23B06
+#define A6XX_GMU_AO_HOST_INTERRUPT_CLR 0x23B04
+#define A6XX_GMU_AO_HOST_INTERRUPT_STATUS 0x23B05
+#define A6XX_GMU_AO_HOST_INTERRUPT_MASK 0x23B06
#define A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS 0x23B0C
#define A6XX_GMU_AHB_FENCE_STATUS 0x23B13
#define A6XX_GMU_RBBM_INT_UNMASKED_STATUS 0x23B15
@@ -764,7 +764,6 @@
#define PDC_GPU_TCS1_CMD0_MSGID 0x21575
#define PDC_GPU_TCS1_CMD0_ADDR 0x21576
#define PDC_GPU_TCS1_CMD0_DATA 0x21577
-#define PDC_GPU_TIMESTAMP_UNIT1_EN_DRV0 0x23489
#define PDC_GPU_SEQ_MEM_0 0xA0000
#endif /* _A6XX_REG_H */
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 75d5587..530529f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -618,9 +618,9 @@
ADRENO_REG_VBIF_XIN_HALT_CTRL1,
ADRENO_REG_VBIF_VERSION,
ADRENO_REG_GMU_AO_INTERRUPT_EN,
- ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
- ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
- ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
+ ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+ ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
+ ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
ADRENO_REG_GMU_AHB_FENCE_STATUS,
ADRENO_REG_GMU_RPMH_POWER_STATE,
@@ -629,6 +629,7 @@
ADRENO_REG_GMU_HFI_SFR_ADDR,
ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
+ ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
ADRENO_REG_GMU_HOST2GMU_INTR_SET,
ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
ADRENO_REG_GMU_HOST2GMU_INTR_RAW_INFO,
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 944faa3..c721065 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -504,15 +504,6 @@
__raw_writel(value, reg);
}
-static void _gmu_regrmw(struct kgsl_device *device,
- unsigned int offsetwords, unsigned int mask)
-{
- unsigned int value;
-
- kgsl_gmu_regread(device, offsetwords, &value);
- kgsl_gmu_regwrite(device, offsetwords, value | mask);
-}
-
/*
* _load_gmu_rpmh_ucode() - Load the ucode into the GPU PDC/RSC blocks
* PDC and RSC execute GPU power on/off RPMh sequence
@@ -651,22 +642,25 @@
/* Configure registers for idle setting. The setting is cumulative */
switch (gmu->idle_level) {
case GPU_HW_MIN_VOLT:
- _gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, MIN_BW_ENABLE_MASK);
- _gmu_regrmw(device, A6XX_GMU_RPMH_HYST_CTRL, MIN_BW_HYST);
+ kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, 0,
+ MIN_BW_ENABLE_MASK);
+ kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_HYST_CTRL, 0,
+ MIN_BW_HYST);
/* fall through */
case GPU_HW_NAP:
- _gmu_regrmw(device, A6XX_GMU_GPU_NAP_CTRL, HW_NAP_ENABLE_MASK);
+ kgsl_gmu_regrmw(device, A6XX_GMU_GPU_NAP_CTRL, 0,
+ HW_NAP_ENABLE_MASK);
/* fall through */
case GPU_HW_IFPC:
kgsl_gmu_regwrite(device, A6XX_GMU_PWR_COL_INTER_FRAME_HYST,
0x000A0080);
- _gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL,
+ kgsl_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0,
IFPC_ENABLE_MASK);
/* fall through */
case GPU_HW_SPTP_PC:
kgsl_gmu_regwrite(device, A6XX_GMU_PWR_COL_SPTPRAC_HYST,
0x000A0080);
- _gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL,
+ kgsl_gmu_regrmw(device, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0,
SPTP_ENABLE_MASK);
/* fall through */
default:
@@ -675,11 +669,13 @@
/* ACD feature enablement */
if (ADRENO_FEATURE(adreno_dev, ADRENO_LM))
- _gmu_regrmw(device, A6XX_GMU_BOOT_KMD_LM_HANDSHAKE, BIT(10));
+ kgsl_gmu_regrmw(device, A6XX_GMU_BOOT_KMD_LM_HANDSHAKE, 0,
+ BIT(10));
/* Enable RPMh GPU client */
if (ADRENO_FEATURE(adreno_dev, ADRENO_RPMH))
- _gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, RPMH_ENABLE_MASK);
+ kgsl_gmu_regrmw(device, A6XX_GMU_RPMH_CTRL, 0,
+ RPMH_ENABLE_MASK);
/* Disable reference bandgap voltage */
kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 1);
@@ -721,9 +717,8 @@
{
struct gmu_device *gmu = &device->gmu;
- kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_MASK,
- (HFI_IRQ_MASK & (~HFI_IRQ_MSGQ_MASK)));
-
+ kgsl_gmu_regrmw(device, A6XX_GMU_GMU2HOST_INTR_MASK,
+ HFI_IRQ_MSGQ_MASK, 0);
kgsl_gmu_regwrite(device, A6XX_GMU_HFI_CTRL_INIT, 1);
if (timed_poll_check(device,
@@ -862,13 +857,14 @@
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct gmu_device *gmu = &device->gmu;
- if (!IS_ERR_OR_NULL(gmu->gx_gdsc)) {
- ret = regulator_enable(gmu->gx_gdsc);
- if (ret) {
- dev_err(&gmu->pdev->dev,
- "Failed to turn on GPU HM HS\n");
- return ret;
- }
+ if (regulator_is_enabled(gmu->gx_gdsc))
+ return 0;
+
+ ret = regulator_enable(gmu->gx_gdsc);
+ if (ret) {
+ dev_err(&gmu->pdev->dev,
+ "Failed to turn on GPU HM HS\n");
+ return ret;
}
ret = clk_set_rate(pwr->grp_clks[0],
@@ -890,15 +886,15 @@
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct gmu_device *gmu = &device->gmu;
+ if (!regulator_is_enabled(gmu->gx_gdsc))
+ return 0;
+
clk_disable_unprepare(pwr->grp_clks[0]);
clk_set_rate(pwr->grp_clks[0],
pwr->pwrlevels[pwr->num_pwrlevels - 1].
gpu_freq);
- if (IS_ERR_OR_NULL(gmu->gx_gdsc))
- return 0;
-
return regulator_disable(gmu->gx_gdsc);
}
@@ -1092,7 +1088,7 @@
ret = a6xx_hm_sptprac_control(device, false);
/* RSC sleep sequence */
- _regwrite(gmu->pdc_reg_virt, PDC_GPU_TIMESTAMP_UNIT1_EN_DRV0, 1);
+ kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 1);
wmb();
@@ -2053,12 +2049,12 @@
A6XX_GMU_ALWAYS_ON_COUNTER_H),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_INTERRUPT_EN,
A6XX_GMU_AO_INTERRUPT_EN),
- ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
- A6XX_GMU_HOST_INTERRUPT_CLR),
- ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
- A6XX_GMU_HOST_INTERRUPT_STATUS),
- ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
- A6XX_GMU_HOST_INTERRUPT_MASK),
+ ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+ A6XX_GMU_AO_HOST_INTERRUPT_CLR),
+ ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
+ A6XX_GMU_AO_HOST_INTERRUPT_STATUS),
+ ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+ A6XX_GMU_AO_HOST_INTERRUPT_MASK),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
A6XX_GMU_GMU_PWR_COL_KEEPALIVE),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_AHB_FENCE_STATUS,
@@ -2075,6 +2071,8 @@
A6XX_GMU_GMU2HOST_INTR_CLR),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
A6XX_GMU_GMU2HOST_INTR_INFO),
+ ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+ A6XX_GMU_GMU2HOST_INTR_MASK),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_SET,
A6XX_GMU_HOST2GMU_INTR_SET),
ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index e501a68..ba83cd7 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -126,31 +126,31 @@
ARRAY_SIZE(a6xx_sp_vs_hlsq_cluster) / 2 },
{ CP_CLUSTER_SP_VS, 0x0002A000, 0x21, a6xx_sp_vs_sp_cluster,
ARRAY_SIZE(a6xx_sp_vs_sp_cluster) / 2 },
- { CP_CLUSTER_SP_VS, 0x0002EC00, 0x41, a6xx_hlsq_duplicate_cluster,
+ { CP_CLUSTER_SP_VS, 0x0002E000, 0x41, a6xx_hlsq_duplicate_cluster,
ARRAY_SIZE(a6xx_hlsq_duplicate_cluster) / 2 },
{ CP_CLUSTER_SP_VS, 0x0002F000, 0x45, a6xx_hlsq_2d_duplicate_cluster,
ARRAY_SIZE(a6xx_hlsq_2d_duplicate_cluster) / 2 },
- { CP_CLUSTER_SP_VS, 0x0002AC00, 0x21, a6xx_sp_duplicate_cluster,
+ { CP_CLUSTER_SP_VS, 0x0002A000, 0x21, a6xx_sp_duplicate_cluster,
ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
- { CP_CLUSTER_SP_VS, 0x0002CC00, 0x1, a6xx_tp_duplicate_cluster,
+ { CP_CLUSTER_SP_VS, 0x0002C000, 0x1, a6xx_tp_duplicate_cluster,
ARRAY_SIZE(a6xx_tp_duplicate_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002E600, 0x42, a6xx_sp_ps_hlsq_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002E000, 0x42, a6xx_sp_ps_hlsq_cluster,
ARRAY_SIZE(a6xx_sp_ps_hlsq_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002F300, 0x46, a6xx_sp_ps_hlsq_2d_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002F000, 0x46, a6xx_sp_ps_hlsq_2d_cluster,
ARRAY_SIZE(a6xx_sp_ps_hlsq_2d_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002A600, 0x22, a6xx_sp_ps_sp_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002A000, 0x22, a6xx_sp_ps_sp_cluster,
ARRAY_SIZE(a6xx_sp_ps_sp_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002B300, 0x26, a6xx_sp_ps_sp_2d_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002B000, 0x26, a6xx_sp_ps_sp_2d_cluster,
ARRAY_SIZE(a6xx_sp_ps_sp_2d_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002C600, 0x2, a6xx_sp_ps_tp_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002C000, 0x2, a6xx_sp_ps_tp_cluster,
ARRAY_SIZE(a6xx_sp_ps_tp_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002D300, 0x6, a6xx_sp_ps_tp_2d_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002D000, 0x6, a6xx_sp_ps_tp_2d_cluster,
ARRAY_SIZE(a6xx_sp_ps_tp_2d_cluster) / 2 },
- { CP_CLUSTER_SP_PS, 0x0002EC00, 0x42, a6xx_hlsq_duplicate_cluster,
+ { CP_CLUSTER_SP_PS, 0x0002E000, 0x42, a6xx_hlsq_duplicate_cluster,
ARRAY_SIZE(a6xx_hlsq_duplicate_cluster) / 2 },
- { CP_CLUSTER_SP_VS, 0x0002AC00, 0x22, a6xx_sp_duplicate_cluster,
+ { CP_CLUSTER_SP_VS, 0x0002A000, 0x22, a6xx_sp_duplicate_cluster,
ARRAY_SIZE(a6xx_sp_duplicate_cluster) / 2 },
- { CP_CLUSTER_SP_VS, 0x0002CC00, 0x2, a6xx_tp_duplicate_cluster,
+ { CP_CLUSTER_SP_VS, 0x0002C000, 0x2, a6xx_tp_duplicate_cluster,
ARRAY_SIZE(a6xx_tp_duplicate_cluster) / 2 },
};
@@ -221,12 +221,12 @@
static const unsigned int a6xx_registers[] = {
/* RBBM */
- 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0014, 0x0014,
- 0x0018, 0x001B, 0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042,
- 0x0044, 0x0044, 0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE,
- 0x00B0, 0x00FB, 0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213,
- 0x0218, 0x023D, 0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B,
- 0x050E, 0x0511, 0x0533, 0x0533, 0x0540, 0x0555,
+ 0x0000, 0x0002, 0x0010, 0x0010, 0x0012, 0x0012, 0x0018, 0x001B,
+ 0x001e, 0x0032, 0x0038, 0x003C, 0x0042, 0x0042, 0x0044, 0x0044,
+ 0x0047, 0x0047, 0x0056, 0x0056, 0x00AD, 0x00AE, 0x00B0, 0x00FB,
+ 0x0100, 0x011D, 0x0200, 0x020D, 0x0210, 0x0213, 0x0218, 0x023D,
+ 0x0400, 0x04F9, 0x0500, 0x0500, 0x0505, 0x050B, 0x050E, 0x0511,
+ 0x0533, 0x0533, 0x0540, 0x0555,
/* CP */
0x0800, 0x0808, 0x0810, 0x0813, 0x0820, 0x0821, 0x0823, 0x0827,
0x0830, 0x0833, 0x0840, 0x0843, 0x084F, 0x086F, 0x0880, 0x088A,
@@ -240,8 +240,8 @@
0x0E10, 0x0E13, 0x0E17, 0x0E19, 0x0E1C, 0x0E2B, 0x0E30, 0x0E32,
0x0E38, 0x0E39,
/* GRAS */
- 0x8600, 0x8601, 0x8604, 0x8605, 0x8610, 0x861B, 0x8620, 0x8620,
- 0x8628, 0x862B, 0x8630, 0x8637,
+ 0x8600, 0x8601, 0x8610, 0x861B, 0x8620, 0x8620, 0x8628, 0x862B,
+ 0x8630, 0x8637,
/* RB */
0x8E01, 0x8E01, 0x8E04, 0x8E05, 0x8E07, 0x8E08, 0x8E0C, 0x8E0C,
0x8E10, 0x8E1C, 0x8E20, 0x8E25, 0x8E28, 0x8E28, 0x8E2C, 0x8E2F,
@@ -254,7 +254,7 @@
0x9E70, 0x9E72, 0x9E78, 0x9E79, 0x9E80, 0x9FFF,
/* VFD */
0xA600, 0xA601, 0xA603, 0xA603, 0xA60A, 0xA60A, 0xA610, 0xA617,
- 0xA630, 0xA630, 0xD200, 0xD263,
+ 0xA630, 0xA630,
};
enum a6xx_debugbus_id {
@@ -275,11 +275,12 @@
A6XX_DBGBUS_LRZ = 0x10,
A6XX_DBGBUS_A2D = 0x11,
A6XX_DBGBUS_CCUFCHE = 0x12,
- A6XX_DBGBUS_GMU = 0x13,
+ A6XX_DBGBUS_GMU_CX = 0x13,
A6XX_DBGBUS_RBP = 0x14,
A6XX_DBGBUS_DCS = 0x15,
A6XX_DBGBUS_RBBM_CFG = 0x16,
A6XX_DBGBUS_CX = 0x17,
+ A6XX_DBGBUS_GMU_GX = 0x18,
A6XX_DBGBUS_TPFCHE = 0x19,
A6XX_DBGBUS_GPC = 0x1d,
A6XX_DBGBUS_LARC = 0x1e,
@@ -321,6 +322,7 @@
{ A6XX_DBGBUS_RBP, 0x100, },
{ A6XX_DBGBUS_DCS, 0x100, },
{ A6XX_DBGBUS_RBBM_CFG, 0x100, },
+ { A6XX_DBGBUS_GMU_GX, 0x100, },
{ A6XX_DBGBUS_TPFCHE, 0x100, },
{ A6XX_DBGBUS_GPC, 0x100, },
{ A6XX_DBGBUS_LARC, 0x100, },
@@ -345,7 +347,7 @@
static void __iomem *a6xx_cx_dbgc;
static const struct adreno_debugbus_block a6xx_cx_dbgc_debugbus_blocks[] = {
{ A6XX_DBGBUS_VBIF, 0x100, },
- { A6XX_DBGBUS_GMU, 0x100, },
+ { A6XX_DBGBUS_GMU_CX, 0x100, },
{ A6XX_DBGBUS_CX, 0x100, },
};
@@ -581,8 +583,9 @@
struct kgsl_snapshot *snapshot)
{
unsigned int pool_size;
+ u8 *buf = snapshot->ptr;
- /* Save the mempool size to 0 to stabilize it while dumping */
+ /* Set the mempool size to 0 to stabilize it while dumping */
kgsl_regread(device, A6XX_CP_MEM_POOL_SIZE, &pool_size);
kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, 0);
@@ -590,6 +593,22 @@
A6XX_CP_MEM_POOL_DBG_ADDR, A6XX_CP_MEM_POOL_DBG_DATA,
0, 0x2060);
+ /*
+ * Data at offset 0x2000 in the mempool section is the mempool size.
+ * Since we set it to 0, patch in the original size so that the data
+ * is consistent.
+ */
+ if (buf < snapshot->ptr) {
+ unsigned int *data;
+
+ /* Skip over the headers */
+ buf += sizeof(struct kgsl_snapshot_section_header) +
+ sizeof(struct kgsl_snapshot_indexed_regs);
+
+ data = (unsigned int *)buf + 0x2000;
+ *data = pool_size;
+ }
+
/* Restore the saved mempool size */
kgsl_regwrite(device, A6XX_CP_MEM_POOL_SIZE, pool_size);
}
@@ -883,12 +902,14 @@
static size_t a6xx_snapshot_dbgc_debugbus_block(struct kgsl_device *device,
u8 *buf, size_t remain, void *priv)
{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_snapshot_debugbus *header =
(struct kgsl_snapshot_debugbus *)buf;
struct adreno_debugbus_block *block = priv;
int i;
unsigned int *data = (unsigned int *)(buf + sizeof(*header));
unsigned int dwords;
+ unsigned int block_id;
size_t size;
dwords = block->dwords;
@@ -904,9 +925,14 @@
header->id = block->block_id;
header->count = dwords * 2;
+ block_id = block->block_id;
+ /* GMU_GX data is read using the GMU_CX block id on A630 */
+ if (adreno_is_a630(adreno_dev) &&
+ (block_id == A6XX_DBGBUS_GMU_GX))
+ block_id = A6XX_DBGBUS_GMU_CX;
+
for (i = 0; i < dwords; i++)
- a6xx_dbgc_debug_bus_read(device, block->block_id, i,
- &data[i*2]);
+ a6xx_dbgc_debug_bus_read(device, block_id, i, &data[i*2]);
return size;
}
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index b1f832f..2a1d352 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -137,11 +137,8 @@
break;
}
case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
- char fence_str[128];
-
- kgsl_dump_fence(sync_event->handle,
- fence_str, sizeof(fence_str));
- seq_printf(s, "sync: [%pK] %s", sync_event->handle, fence_str);
+ seq_printf(s, "sync: [%pK] %s", sync_event->handle,
+ sync_event->fence_name);
break;
}
default:
@@ -241,6 +238,9 @@
static void drawobj_print(struct seq_file *s,
struct kgsl_drawobj *drawobj)
{
+ if (!kref_get_unless_zero(&drawobj->refcount))
+ return;
+
if (drawobj->type == SYNCOBJ_TYPE)
syncobj_print(s, SYNCOBJ(drawobj));
else if ((drawobj->type == CMDOBJ_TYPE) ||
@@ -251,6 +251,7 @@
print_flags(s, drawobj_flags, ARRAY_SIZE(drawobj_flags),
drawobj->flags);
+ kgsl_drawobj_put(drawobj);
seq_puts(s, "\n");
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 9f4e185..f77d438 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -95,6 +95,9 @@
goto stats;
}
+ if (!kref_get_unless_zero(&drawobj->refcount))
+ goto stats;
+
if (drawobj->type == SYNCOBJ_TYPE) {
struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
@@ -106,6 +109,8 @@
kgsl_dump_syncpoints(device, syncobj);
}
}
+
+ kgsl_drawobj_put(drawobj);
}
stats:
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2283096..15f68bf 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1955,7 +1955,7 @@
}
handle = kgsl_sync_fence_async_wait(event.fd,
- gpuobj_free_fence_func, entry);
+ gpuobj_free_fence_func, entry, NULL, 0);
/* if handle is NULL the fence has already signaled */
if (handle == NULL)
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index bf31c00..d955aa0 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -569,6 +569,17 @@
device->ftbl->regwrite(device, offsetwords, val | bits);
}
+static inline void kgsl_gmu_regrmw(struct kgsl_device *device,
+ unsigned int offsetwords,
+ unsigned int mask, unsigned int bits)
+{
+ unsigned int val = 0;
+
+ kgsl_gmu_regread(device, offsetwords, &val);
+ val &= ~mask;
+ kgsl_gmu_regwrite(device, offsetwords, val | bits);
+}
+
static inline int kgsl_idle(struct kgsl_device *device)
{
return device->ftbl->idle(device);
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index 3a87e6e..bca3d57 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -44,7 +44,7 @@
static struct kmem_cache *sparseobjs_cache;
-static void drawobj_destroy_object(struct kref *kref)
+void kgsl_drawobj_destroy_object(struct kref *kref)
{
struct kgsl_drawobj *drawobj = container_of(kref,
struct kgsl_drawobj, refcount);
@@ -68,12 +68,6 @@
}
}
-static inline void drawobj_put(struct kgsl_drawobj *drawobj)
-{
- if (drawobj)
- kref_put(&drawobj->refcount, drawobj_destroy_object);
-}
-
void kgsl_dump_syncpoints(struct kgsl_device *device,
struct kgsl_drawobj_sync *syncobj)
{
@@ -100,16 +94,11 @@
retired);
break;
}
- case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
- char fence_str[128];
-
- kgsl_dump_fence(event->handle,
- fence_str, sizeof(fence_str));
- dev_err(device->dev,
- " fence: %s\n", fence_str);
+ case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
+ dev_err(device->dev, " fence: %s\n",
+ event->fence_name);
break;
}
- }
}
}
@@ -117,13 +106,23 @@
{
struct kgsl_device *device;
struct kgsl_drawobj_sync *syncobj = (struct kgsl_drawobj_sync *) data;
- struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj);
+ struct kgsl_drawobj *drawobj;
struct kgsl_drawobj_sync_event *event;
unsigned int i;
- if (syncobj == NULL || drawobj->context == NULL)
+ if (syncobj == NULL)
return;
+ drawobj = DRAWOBJ(syncobj);
+
+ if (!kref_get_unless_zero(&drawobj->refcount))
+ return;
+
+ if (drawobj->context == NULL) {
+ kgsl_drawobj_put(drawobj);
+ return;
+ }
+
device = drawobj->context->device;
dev_err(device->dev,
@@ -147,18 +146,14 @@
dev_err(device->dev, " [%d] TIMESTAMP %d:%d\n",
i, event->context->id, event->timestamp);
break;
- case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
- char fence_str[128];
-
- kgsl_dump_fence(event->handle,
- fence_str, sizeof(fence_str));
+ case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
dev_err(device->dev, " [%d] FENCE %s\n",
- i, fence_str);
+ i, event->fence_name);
break;
}
- }
}
+ kgsl_drawobj_put(drawobj);
dev_err(device->dev, "--gpu syncpoint deadlock print end--\n");
}
@@ -204,7 +199,7 @@
drawobj_sync_expire(device, event);
kgsl_context_put(event->context);
- drawobj_put(&event->syncobj->base);
+ kgsl_drawobj_put(&event->syncobj->base);
}
static inline void memobj_list_free(struct list_head *list)
@@ -265,7 +260,7 @@
break;
case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
if (kgsl_sync_fence_async_cancel(event->handle))
- drawobj_put(drawobj);
+ kgsl_drawobj_put(drawobj);
break;
}
}
@@ -321,21 +316,19 @@
else
return;
- drawobj_put(drawobj);
+ kgsl_drawobj_put(drawobj);
}
EXPORT_SYMBOL(kgsl_drawobj_destroy);
static void drawobj_sync_fence_func(void *priv)
{
struct kgsl_drawobj_sync_event *event = priv;
- char fence_str[128];
- kgsl_dump_fence(event->handle, fence_str, sizeof(fence_str));
- trace_syncpoint_fence_expire(event->syncobj, fence_str);
+ trace_syncpoint_fence_expire(event->syncobj, event->fence_name);
drawobj_sync_expire(event->device, event);
- drawobj_put(&event->syncobj->base);
+ kgsl_drawobj_put(&event->syncobj->base);
}
/* drawobj_add_sync_fence() - Add a new sync fence syncpoint
@@ -352,7 +345,6 @@
struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj);
struct kgsl_drawobj_sync_event *event;
unsigned int id;
- char fence_str[128];
kref_get(&drawobj->refcount);
@@ -369,7 +361,8 @@
set_bit(event->id, &syncobj->pending);
event->handle = kgsl_sync_fence_async_wait(sync->fd,
- drawobj_sync_fence_func, event);
+ drawobj_sync_fence_func, event,
+ event->fence_name, sizeof(event->fence_name));
if (IS_ERR_OR_NULL(event->handle)) {
int ret = PTR_ERR(event->handle);
@@ -377,7 +370,7 @@
clear_bit(event->id, &syncobj->pending);
event->handle = NULL;
- drawobj_put(drawobj);
+ kgsl_drawobj_put(drawobj);
/*
* If ret == 0 the fence was already signaled - print a trace
@@ -389,8 +382,7 @@
return ret;
}
- kgsl_dump_fence(event->handle, fence_str, sizeof(fence_str));
- trace_syncpoint_fence(syncobj, fence_str);
+ trace_syncpoint_fence(syncobj, event->fence_name);
return 0;
}
@@ -457,7 +449,7 @@
if (ret) {
clear_bit(event->id, &syncobj->pending);
- drawobj_put(drawobj);
+ kgsl_drawobj_put(drawobj);
} else {
trace_syncpoint_timestamp(syncobj, context, sync->timestamp);
}
diff --git a/drivers/gpu/msm/kgsl_drawobj.h b/drivers/gpu/msm/kgsl_drawobj.h
index 5ec98ed..06eef7f 100644
--- a/drivers/gpu/msm/kgsl_drawobj.h
+++ b/drivers/gpu/msm/kgsl_drawobj.h
@@ -105,6 +105,8 @@
unsigned long timeout_jiffies;
};
+#define KGSL_FENCE_NAME_LEN 74
+
/**
* struct kgsl_drawobj_sync_event
* @id: identifer (positiion within the pending bitmap)
@@ -114,6 +116,7 @@
* register this event
* @timestamp: Pending timestamp for the event
* @handle: Pointer to a sync fence handle
+ * @fence_name: A fence name string to describe the fence
* @device: Pointer to the KGSL device
*/
struct kgsl_drawobj_sync_event {
@@ -123,6 +126,7 @@
struct kgsl_context *context;
unsigned int timestamp;
struct kgsl_sync_fence_cb *handle;
+ char fence_name[KGSL_FENCE_NAME_LEN];
struct kgsl_device *device;
};
@@ -206,6 +210,8 @@
void kgsl_drawobj_destroy(struct kgsl_drawobj *drawobj);
+void kgsl_drawobj_destroy_object(struct kref *kref);
+
static inline bool kgsl_drawobj_events_pending(
struct kgsl_drawobj_sync *syncobj)
{
@@ -220,4 +226,11 @@
return test_bit(bit, &syncobj->pending);
}
+
+static inline void kgsl_drawobj_put(struct kgsl_drawobj *drawobj)
+{
+ if (drawobj)
+ kref_put(&drawobj->refcount, kgsl_drawobj_destroy_object);
+}
+
#endif /* __KGSL_DRAWOBJ_H */
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 97e4b6f..416085f 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -748,44 +748,49 @@
{
struct gmu_device *gmu = data;
struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
- struct kgsl_hfi *hfi = &gmu->hfi;
unsigned int status = 0;
- if (irq == gmu->gmu_interrupt_num) {
- adreno_read_gmureg(ADRENO_DEVICE(device),
- ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
- &status);
+ adreno_read_gmureg(ADRENO_DEVICE(device),
+ ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS, &status);
+ adreno_write_gmureg(ADRENO_DEVICE(device),
+ ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, status);
- /* Ignore GMU_INT_RSCC_COMP interrupts */
- if (status & GMU_INT_WDOG_BITE)
- dev_err_ratelimited(&gmu->pdev->dev,
- "GMU watchdog expired interrupt\n");
- if (status & GMU_INT_DBD_WAKEUP)
- dev_err_ratelimited(&gmu->pdev->dev,
- "GMU doorbell interrupt received\n");
- if (status & GMU_INT_HOST_AHB_BUS_ERR)
- dev_err_ratelimited(&gmu->pdev->dev,
- "AHB bus error interrupt received\n");
+ /* Ignore GMU_INT_RSCC_COMP and GMU_INT_DBD WAKEUP interrupts */
+ if (status & GMU_INT_WDOG_BITE)
+ dev_err_ratelimited(&gmu->pdev->dev,
+ "GMU watchdog expired interrupt received\n");
+ if (status & GMU_INT_HOST_AHB_BUS_ERR)
+ dev_err_ratelimited(&gmu->pdev->dev,
+ "AHB bus error interrupt received\n");
+ if (status & ~GMU_AO_INT_MASK)
+ dev_err_ratelimited(&gmu->pdev->dev,
+ "Unhandled GMU interrupts 0x%lx\n",
+ status & ~GMU_AO_INT_MASK);
- adreno_write_gmureg(ADRENO_DEVICE(device),
- ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
- status);
- } else {
- adreno_read_gmureg(ADRENO_DEVICE(device),
- ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
- &status);
- adreno_write_gmureg(ADRENO_DEVICE(device),
- ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
- status);
+ return IRQ_HANDLED;
+}
- if (status & HFI_IRQ_MASK) {
- if (status & HFI_IRQ_MSGQ_MASK)
- tasklet_hi_schedule(&hfi->tasklet);
- } else
- dev_err_ratelimited(&gmu->pdev->dev,
- "Unhandled GMU interrupts %x\n",
- status);
- }
+static irqreturn_t hfi_irq_handler(int irq, void *data)
+{
+ struct kgsl_hfi *hfi = data;
+ struct gmu_device *gmu = container_of(hfi, struct gmu_device, hfi);
+ struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
+ unsigned int status = 0;
+
+ adreno_read_gmureg(ADRENO_DEVICE(device),
+ ADRENO_REG_GMU_GMU2HOST_INTR_INFO, &status);
+ adreno_write_gmureg(ADRENO_DEVICE(device),
+ ADRENO_REG_GMU_GMU2HOST_INTR_CLR, status);
+
+ if (status & HFI_IRQ_MSGQ_MASK)
+ tasklet_hi_schedule(&hfi->tasklet);
+ if (status & HFI_IRQ_CM3_FAULT_MASK)
+ dev_err_ratelimited(&gmu->pdev->dev,
+ "GMU CM3 fault interrupt received\n");
+ if (status & ~HFI_IRQ_MASK)
+ dev_err_ratelimited(&gmu->pdev->dev,
+ "Unhandled HFI interrupts 0x%lx\n",
+ status & ~HFI_IRQ_MASK);
return IRQ_HANDLED;
}
@@ -978,6 +983,82 @@
return 0;
}
+static int gmu_irq_probe(struct gmu_device *gmu)
+{
+ int ret;
+ struct kgsl_hfi *hfi = &gmu->hfi;
+
+ hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
+ "kgsl_hfi_irq");
+ ret = devm_request_irq(&gmu->pdev->dev,
+ hfi->hfi_interrupt_num,
+ hfi_irq_handler, IRQF_TRIGGER_HIGH,
+ "HFI", hfi);
+ if (ret) {
+ dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
+ hfi->hfi_interrupt_num, ret);
+ return ret;
+ }
+
+ gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
+ "kgsl_gmu_irq");
+ ret = devm_request_irq(&gmu->pdev->dev,
+ gmu->gmu_interrupt_num,
+ gmu_irq_handler, IRQF_TRIGGER_HIGH,
+ "GMU", gmu);
+ if (ret)
+ dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
+ gmu->gmu_interrupt_num, ret);
+
+ return ret;
+}
+
+static void gmu_irq_enable(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct gmu_device *gmu = &device->gmu;
+ struct kgsl_hfi *hfi = &gmu->hfi;
+
+ /* Clear any pending IRQs before unmasking on GMU */
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
+ 0xFFFFFFFF);
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+ 0xFFFFFFFF);
+
+ /* Unmask needed IRQs on GMU */
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+ (unsigned int) ~HFI_IRQ_MASK);
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+ (unsigned int) ~GMU_AO_INT_MASK);
+
+ /* Enable all IRQs on host */
+ enable_irq(hfi->hfi_interrupt_num);
+ enable_irq(gmu->gmu_interrupt_num);
+}
+
+static void gmu_irq_disable(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct gmu_device *gmu = &device->gmu;
+ struct kgsl_hfi *hfi = &gmu->hfi;
+
+ /* Disable all IRQs on host */
+ disable_irq(gmu->gmu_interrupt_num);
+ disable_irq(hfi->hfi_interrupt_num);
+
+ /* Mask all IRQs on GMU */
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
+ 0xFFFFFFFF);
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
+ 0xFFFFFFFF);
+
+ /* Clear any pending IRQs before disabling */
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
+ 0xFFFFFFFF);
+ adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
+ 0xFFFFFFFF);
+}
+
/* Do not access any GMU registers in GMU probe function */
int gmu_probe(struct kgsl_device *device)
{
@@ -1024,32 +1105,13 @@
gmu->gmu2gpu_offset = (gmu->reg_phys - device->reg_phys) >> 2;
- /* Initialize HFI GMU interrupts */
- hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
- "kgsl_hfi_irq");
- ret = devm_request_irq(&gmu->pdev->dev,
- hfi->hfi_interrupt_num,
- gmu_irq_handler, IRQF_TRIGGER_HIGH,
- "GMU", gmu);
- if (ret) {
- dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
- hfi->hfi_interrupt_num, ret);
+ /* Initialize HFI and GMU interrupts */
+ ret = gmu_irq_probe(gmu);
+ if (ret)
goto error;
- }
-
- gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
- "kgsl_gmu_irq");
- ret = devm_request_irq(&gmu->pdev->dev,
- gmu->gmu_interrupt_num,
- gmu_irq_handler, IRQF_TRIGGER_HIGH,
- "GMU", gmu);
- if (ret) {
- dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
- gmu->gmu_interrupt_num, ret);
- goto error;
- }
/* Don't enable GMU interrupts until GMU started */
+ /* We cannot use gmu_irq_disable because it writes registers */
disable_irq(gmu->gmu_interrupt_num);
disable_irq(hfi->hfi_interrupt_num);
@@ -1153,7 +1215,6 @@
while ((j < MAX_GMU_CLKS) && gmu->clks[j]) {
clk_disable_unprepare(gmu->clks[j]);
- gmu->clks[j] = NULL;
j++;
}
@@ -1200,7 +1261,6 @@
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct gmu_device *gmu = &device->gmu;
- struct kgsl_hfi *hfi = &gmu->hfi;
int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;
if (!kgsl_gmu_isenabled(device))
@@ -1235,8 +1295,7 @@
if (ret)
goto error_bus;
- enable_irq(hfi->hfi_interrupt_num);
- enable_irq(gmu->gmu_interrupt_num);
+ gmu_irq_enable(device);
ret = hfi_start(gmu, GMU_COLD_BOOT);
if (ret)
@@ -1254,8 +1313,7 @@
if (ret)
goto error_clks;
- enable_irq(hfi->hfi_interrupt_num);
- enable_irq(gmu->gmu_interrupt_num);
+ gmu_irq_enable(device);
ret = hfi_start(gmu, GMU_WARM_BOOT);
if (ret)
@@ -1293,8 +1351,7 @@
error_gpu:
hfi_stop(gmu);
- disable_irq(gmu->gmu_interrupt_num);
- disable_irq(hfi->hfi_interrupt_num);
+ gmu_irq_disable(device);
if (device->state == KGSL_STATE_INIT ||
device->state == KGSL_STATE_SUSPEND) {
if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
@@ -1316,7 +1373,6 @@
void gmu_stop(struct kgsl_device *device)
{
struct gmu_device *gmu = &device->gmu;
- struct kgsl_hfi *hfi = &gmu->hfi;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
@@ -1334,9 +1390,7 @@
/* Pending message in all queues are abandoned */
hfi_stop(gmu);
clear_bit(GMU_HFI_ON, &gmu->flags);
-
- disable_irq(gmu->gmu_interrupt_num);
- disable_irq(hfi->hfi_interrupt_num);
+ gmu_irq_disable(device);
gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
gmu_disable_clks(gmu);
@@ -1351,7 +1405,7 @@
{
struct gmu_device *gmu = &device->gmu;
struct kgsl_hfi *hfi = &gmu->hfi;
- int i;
+ int i = 0;
if (!device->gmu.pdev)
return;
@@ -1359,16 +1413,20 @@
tasklet_kill(&hfi->tasklet);
gmu_stop(device);
+ gmu_irq_disable(device);
+
+ while ((i < MAX_GMU_CLKS) && gmu->clks[i]) {
+ gmu->clks[i] = NULL;
+ i++;
+ }
if (gmu->gmu_interrupt_num) {
- disable_irq(gmu->gmu_interrupt_num);
devm_free_irq(&gmu->pdev->dev,
gmu->gmu_interrupt_num, gmu);
gmu->gmu_interrupt_num = 0;
}
if (hfi->hfi_interrupt_num) {
- disable_irq(hfi->hfi_interrupt_num);
devm_free_irq(&gmu->pdev->dev,
hfi->hfi_interrupt_num, gmu);
hfi->hfi_interrupt_num = 0;
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index ac2c151..a2ca67c 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -26,7 +26,6 @@
#define GMU_INT_HOST_AHB_BUS_ERR BIT(5)
#define GMU_AO_INT_MASK \
(GMU_INT_WDOG_BITE | \
- GMU_INT_DBD_WAKEUP | \
GMU_INT_HOST_AHB_BUS_ERR)
#define MAX_GMUFW_SIZE 0x2000 /* in dwords */
diff --git a/drivers/gpu/msm/kgsl_hfi.h b/drivers/gpu/msm/kgsl_hfi.h
index 39b513e..83abec4 100644
--- a/drivers/gpu/msm/kgsl_hfi.h
+++ b/drivers/gpu/msm/kgsl_hfi.h
@@ -38,16 +38,15 @@
#define GMU_QUEUE_START_ADDR(hfi_mem, i) \
((hfi_mem)->gmuaddr + HFI_QUEUE_OFFSET(i))
-#define HFI_IRQ_MSGQ_MASK 0x1
-#define HFI_IRQ_DBGQ_MASK 0x2
-#define HFI_IRQ_BLOCKED_MSG_MASK 0x4
-#define HFI_IRQ_GMU_ERR_MASK 0xFF0000
-#define HFI_IRQ_OOB_MASK 0xFF000000
-#define HFI_IRQ_MASK (HFI_IRQ_MSGQ_MASK |\
- HFI_IRQ_DBGQ_MASK |\
- HFI_IRQ_BLOCKED_MSG_MASK |\
- HFI_IRQ_GMU_ERR_MASK |\
- HFI_IRQ_OOB_MASK)
+#define HFI_IRQ_MSGQ_MASK BIT(0)
+#define HFI_IRQ_DBGQ_MASK BIT(1)
+#define HFI_IRQ_BLOCKED_MSG_MASK BIT(2)
+#define HFI_IRQ_CM3_FAULT_MASK BIT(23)
+#define HFI_IRQ_GMU_ERR_MASK GENMASK(22, 16)
+#define HFI_IRQ_OOB_MASK GENMASK(31, 24)
+#define HFI_IRQ_MASK (HFI_IRQ_MSGQ_MASK |\
+ HFI_IRQ_CM3_FAULT_MASK)
+
/**
* struct hfi_queue_table_header - HFI queue table structure
* @version: HFI protocol version
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 3b57b73..973a2ff 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -152,6 +152,17 @@
return ret;
}
+/* Only to be used if creating a related event failed */
+static void kgsl_sync_cancel(struct kgsl_sync_fence *kfence)
+{
+ spin_lock(&kfence->parent->lock);
+ if (!list_empty(&kfence->child_list)) {
+ list_del_init(&kfence->child_list);
+ fence_put(&kfence->fence);
+ }
+ spin_unlock(&kfence->parent->lock);
+}
+
/**
* kgsl_add_fence_event - Create a new fence event
* @device - KGSL device to create the event on
@@ -235,6 +246,7 @@
put_unused_fd(priv.fence_fd);
if (kfence) {
+ kgsl_sync_cancel(kfence);
/*
* Put the refcount of sync file. This will release
* kfence->fence as well.
@@ -366,7 +378,7 @@
list_for_each_entry_safe(kfence, next, &ktimeline->child_list_head,
child_list) {
if (fence_is_signaled_locked(&kfence->fence)) {
- list_del(&kfence->child_list);
+ list_del_init(&kfence->child_list);
fence_put(&kfence->fence);
}
}
@@ -419,8 +431,27 @@
kfree(kcb);
}
+static void kgsl_get_fence_name(struct fence *fence,
+ char *fence_name, int name_len)
+{
+ char *ptr = fence_name;
+ char *last = fence_name + name_len;
+
+ ptr += snprintf(ptr, last - ptr, "%s %s",
+ fence->ops->get_driver_name(fence),
+ fence->ops->get_timeline_name(fence));
+
+ if ((ptr + 2) >= last)
+ return;
+
+ if (fence->ops->fence_value_str) {
+ ptr += snprintf(ptr, last - ptr, ": ");
+ fence->ops->fence_value_str(fence, ptr, last - ptr);
+ }
+}
+
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
- void (*func)(void *priv), void *priv)
+ void (*func)(void *priv), void *priv, char *fence_name, int name_len)
{
struct kgsl_sync_fence_cb *kcb;
struct fence *fence;
@@ -441,13 +472,16 @@
kcb->priv = priv;
kcb->func = func;
+ if (fence_name)
+ kgsl_get_fence_name(fence, fence_name, name_len);
+
/* if status then error or signaled */
status = fence_add_callback(fence, &kcb->fence_cb,
kgsl_sync_fence_callback);
if (status) {
kfree(kcb);
- if (fence_is_signaled(fence))
+ if (!fence_is_signaled(fence))
kcb = ERR_PTR(status);
else
kcb = NULL;
@@ -777,43 +811,3 @@
.release = kgsl_syncsource_fence_release,
};
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
- char *fence_str, int len)
-{
- struct fence *fence;
- char *ptr = fence_str;
- char *last = fence_str + len;
-
- if (!handle || !handle->fence) {
- snprintf(fence_str, len, "NULL");
- return;
- }
-
- fence = handle->fence;
-
- ptr += snprintf(ptr, last - ptr, "%s %s",
- fence->ops->get_timeline_name(fence),
- fence->ops->get_driver_name(fence));
- if (ptr >= last)
- return;
-
- if (fence->ops->timeline_value_str &&
- fence->ops->fence_value_str) {
- char value[64];
- bool success;
-
- fence->ops->fence_value_str(fence, value, sizeof(value));
- success = !!strlen(value);
-
- if (success) {
- ptr += snprintf(ptr, last - ptr, ": %s", value);
- if (ptr >= last)
- return;
-
- fence->ops->timeline_value_str(fence, value,
- sizeof(value));
- ptr += snprintf(ptr, last - ptr, " / %s", value);
- }
- }
-}
-
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index dc84c54..99fe0e1 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -91,7 +91,8 @@
void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline);
struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
- void (*func)(void *priv), void *priv);
+ void (*func)(void *priv), void *priv,
+ char *fence_name, int name_len);
int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
@@ -109,8 +110,8 @@
void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
struct kgsl_syncsource *syncsource);
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
- char *fence_str, int len);
+void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
+ char *fence_str, int len);
#else
static inline int kgsl_add_fence_event(struct kgsl_device *device,
@@ -134,8 +135,10 @@
{
}
-static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
- void (*func)(void *priv), void *priv)
+
+struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
+ void (*func)(void *priv), void *priv,
+ char *fence_name, int name_len)
{
return NULL;
}
@@ -185,8 +188,8 @@
}
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
- char *fence_str, int len)
+void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
+ char *fence_str, int len)
{
}
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 33b760f..d883483 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -392,78 +392,78 @@
/* Voltage to temperature */
static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
- {1758, -40},
- {1742, -35},
- {1719, -30},
- {1691, -25},
- {1654, -20},
- {1608, -15},
- {1551, -10},
- {1483, -5},
+ {1758, -40000},
+ {1742, -35000},
+ {1719, -30000},
+ {1691, -25000},
+ {1654, -20000},
+ {1608, -15000},
+ {1551, -10000},
+ {1483, -5000},
{1404, 0},
- {1315, 5},
- {1218, 10},
- {1114, 15},
- {1007, 20},
- {900, 25},
- {795, 30},
- {696, 35},
- {605, 40},
- {522, 45},
- {448, 50},
- {383, 55},
- {327, 60},
- {278, 65},
- {237, 70},
- {202, 75},
- {172, 80},
- {146, 85},
- {125, 90},
- {107, 95},
- {92, 100},
- {79, 105},
- {68, 110},
- {59, 115},
- {51, 120},
- {44, 125}
+ {1315, 5000},
+ {1218, 10000},
+ {1114, 15000},
+ {1007, 20000},
+ {900, 25000},
+ {795, 30000},
+ {696, 35000},
+ {605, 40000},
+ {522, 45000},
+ {448, 50000},
+ {383, 55000},
+ {327, 60000},
+ {278, 65000},
+ {237, 70000},
+ {202, 75000},
+ {172, 80000},
+ {146, 85000},
+ {125, 90000},
+ {107, 95000},
+ {92, 100000},
+ {79, 105000},
+ {68, 110000},
+ {59, 115000},
+ {51, 120000},
+ {44, 125000}
};
/* Voltage to temperature */
static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
- {1738, -40},
- {1714, -35},
- {1682, -30},
- {1641, -25},
- {1589, -20},
- {1526, -15},
- {1451, -10},
- {1363, -5},
+ {1738, -40000},
+ {1714, -35000},
+ {1682, -30000},
+ {1641, -25000},
+ {1589, -20000},
+ {1526, -15000},
+ {1451, -10000},
+ {1363, -5000},
{1266, 0},
- {1159, 5},
- {1048, 10},
- {936, 15},
- {825, 20},
- {720, 25},
- {622, 30},
- {533, 35},
- {454, 40},
- {385, 45},
- {326, 50},
- {275, 55},
- {232, 60},
- {195, 65},
- {165, 70},
- {139, 75},
- {118, 80},
- {100, 85},
- {85, 90},
- {73, 95},
- {62, 100},
- {53, 105},
- {46, 110},
- {40, 115},
- {34, 120},
- {30, 125}
+ {1159, 5000},
+ {1048, 10000},
+ {936, 15000},
+ {825, 20000},
+ {720, 25000},
+ {622, 30000},
+ {533, 35000},
+ {454, 40000},
+ {385, 45000},
+ {326, 50000},
+ {275, 55000},
+ {232, 60000},
+ {195, 65000},
+ {165, 70000},
+ {139, 75000},
+ {118, 80000},
+ {100, 85000},
+ {85, 90000},
+ {73, 95000},
+ {62, 100000},
+ {53, 105000},
+ {46, 110000},
+ {40, 115000},
+ {34, 120000},
+ {30, 125000}
};
static const struct qpnp_vadc_map_pt adcmap_smb_batt_therm[] = {
@@ -595,40 +595,40 @@
* 1.875V reference.
*/
static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
- { 1831, -40 },
- { 1814, -35 },
- { 1791, -30 },
- { 1761, -25 },
- { 1723, -20 },
- { 1675, -15 },
- { 1616, -10 },
- { 1545, -5 },
+ { 1831, -40000 },
+ { 1814, -35000 },
+ { 1791, -30000 },
+ { 1761, -25000 },
+ { 1723, -20000 },
+ { 1675, -15000 },
+ { 1616, -10000 },
+ { 1545, -5000 },
{ 1463, 0 },
- { 1370, 5 },
- { 1268, 10 },
- { 1160, 15 },
- { 1049, 20 },
- { 937, 25 },
- { 828, 30 },
- { 726, 35 },
- { 630, 40 },
- { 544, 45 },
- { 467, 50 },
- { 399, 55 },
- { 340, 60 },
- { 290, 65 },
- { 247, 70 },
- { 209, 75 },
- { 179, 80 },
- { 153, 85 },
- { 130, 90 },
- { 112, 95 },
- { 96, 100 },
- { 82, 105 },
- { 71, 110 },
- { 62, 115 },
- { 53, 120 },
- { 46, 125 },
+ { 1370, 5000 },
+ { 1268, 10000 },
+ { 1160, 15000 },
+ { 1049, 20000 },
+ { 937, 25000 },
+ { 828, 30000 },
+ { 726, 35000 },
+ { 630, 40000 },
+ { 544, 45000 },
+ { 467, 50000 },
+ { 399, 55000 },
+ { 340, 60000 },
+ { 290, 65000 },
+ { 247, 70000 },
+ { 209, 75000 },
+ { 179, 80000 },
+ { 153, 85000 },
+ { 130, 90000 },
+ { 112, 95000 },
+ { 96, 100000 },
+ { 82, 105000 },
+ { 71, 110000 },
+ { 62, 115000 },
+ { 53, 120000 },
+ { 46, 125000 },
};
static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 6cd63b2..4b5e206 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -2562,10 +2562,9 @@
return rc;
}
-static int qpnp_vadc_get_temp(struct thermal_zone_device *thermal,
- int *temp)
+static int qpnp_vadc_get_temp(void *data, int *temp)
{
- struct qpnp_vadc_thermal_data *vadc_therm = thermal->devdata;
+ struct qpnp_vadc_thermal_data *vadc_therm = data;
struct qpnp_vadc_chip *vadc = vadc_therm->vadc_dev;
struct qpnp_vadc_result result;
int rc = 0;
@@ -2583,7 +2582,7 @@
return rc;
}
-static struct thermal_zone_device_ops qpnp_vadc_thermal_ops = {
+static struct thermal_zone_of_device_ops qpnp_vadc_thermal_ops = {
.get_temp = qpnp_vadc_get_temp,
};
@@ -2612,9 +2611,11 @@
vadc->adc->adc_channels[i].name);
vadc->vadc_therm_chan[i].vadc_dev = vadc;
vadc->vadc_therm_chan[i].tz_dev =
- thermal_zone_device_register(name,
- 0, 0, &vadc->vadc_therm_chan[i],
- &qpnp_vadc_thermal_ops, NULL, 0, 0);
+ devm_thermal_zone_of_sensor_register(
+ vadc->dev,
+ vadc->vadc_therm_chan[i].vadc_channel,
+ &vadc->vadc_therm_chan[i],
+ &qpnp_vadc_thermal_ops);
if (IS_ERR(vadc->vadc_therm_chan[i].tz_dev)) {
pr_err("thermal device register failed.\n");
goto thermal_err_sens;
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 5d67089..af94ad7 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -22,5 +22,5 @@
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o
-obj-$(CONFIG_CORESIGHT_SOURCE_DUMMY) += coresight-dummy.o
+obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index a2ce81a..8a57ed2 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -19,7 +19,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/mutex.h>
-#include <linux/clk.h>
+#include <linux/amba/bus.h>
#include <linux/cpu_pm.h>
#include <linux/topology.h>
#include <linux/of.h>
@@ -379,7 +379,7 @@
* within the mutex lock region in addition to within the spinlock.
*/
if (drvdata->refcnt == 0) {
- ret = clk_prepare_enable(drvdata->clk);
+ ret = pm_runtime_get_sync(drvdata->dev);
if (ret)
goto err1;
}
@@ -402,7 +402,7 @@
* adjusting its value.
*/
if (drvdata->refcnt == 0)
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
err1:
cti_trigin_gpio_disable(drvdata);
err0:
@@ -463,7 +463,7 @@
* within the mutex lock region in addition to within the spinlock.
*/
if (drvdata->refcnt == 0) {
- ret = clk_prepare_enable(drvdata->clk);
+ ret = pm_runtime_get_sync(drvdata->dev);
if (ret)
goto err1;
}
@@ -485,7 +485,7 @@
* __cti_map_trigout so it is safe to check it against 0.
*/
if (drvdata->refcnt == 0)
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
err1:
cti_trigout_gpio_disable(drvdata);
err0:
@@ -563,7 +563,7 @@
* within the mutex lock region in addition to within the spinlock.
*/
if (drvdata->refcnt == 0)
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
if (drvdata->gpio_trigin->trig == trig)
cti_trigin_gpio_disable(drvdata);
@@ -632,7 +632,7 @@
* within the mutex lock region in addition to within the spinlock.
*/
if (drvdata->refcnt == 0)
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(drvdata->dev);
if (drvdata->gpio_trigout->trig == trig)
cti_trigout_gpio_disable(drvdata);
@@ -1388,34 +1388,29 @@
.notifier_call = cti_cpu_pm_callback,
};
-static int cti_probe(struct platform_device *pdev)
+static int cti_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
int trig;
- struct device *dev = &pdev->dev;
+ struct device *dev = &adev->dev;
struct coresight_platform_data *pdata;
struct cti_drvdata *drvdata;
- struct resource *res;
struct coresight_desc *desc;
struct device_node *cpu_node;
- pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
- pdev->dev.platform_data = pdata;
+ adev->dev.platform_data = pdata;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
/* Store the driver data pointer for use in exported functions */
- drvdata->dev = &pdev->dev;
- platform_set_drvdata(pdev, drvdata);
+ drvdata->dev = &adev->dev;
+ dev_set_drvdata(dev, drvdata);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cti-base");
- if (!res)
- return -ENODEV;
-
- drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ drvdata->base = devm_ioremap_resource(dev, &adev->res);
if (!drvdata->base)
return -ENOMEM;
@@ -1423,21 +1418,13 @@
mutex_init(&drvdata->mutex);
- drvdata->clk = devm_clk_get(dev, "core_clk");
- if (IS_ERR(drvdata->clk))
- return PTR_ERR(drvdata->clk);
-
- ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
- if (ret)
- return ret;
-
drvdata->gpio_trigin = devm_kzalloc(dev, sizeof(struct cti_pctrl),
GFP_KERNEL);
if (!drvdata->gpio_trigin)
return -ENOMEM;
drvdata->gpio_trigin->trig = -1;
- ret = of_property_read_u32(pdev->dev.of_node,
+ ret = of_property_read_u32(adev->dev.of_node,
"qcom,cti-gpio-trigin", &trig);
if (!ret)
drvdata->gpio_trigin->trig = trig;
@@ -1450,7 +1437,7 @@
return -ENOMEM;
drvdata->gpio_trigout->trig = -1;
- ret = of_property_read_u32(pdev->dev.of_node,
+ ret = of_property_read_u32(adev->dev.of_node,
"qcom,cti-gpio-trigout", &trig);
if (!ret)
drvdata->gpio_trigout->trig = trig;
@@ -1458,7 +1445,7 @@
return ret;
drvdata->cpu = -1;
- cpu_node = of_parse_phandle(pdev->dev.of_node, "cpu", 0);
+ cpu_node = of_parse_phandle(adev->dev.of_node, "cpu", 0);
if (cpu_node) {
drvdata->cpu = pdata ? pdata->cpu : -1;
if (drvdata->cpu == -1) {
@@ -1468,7 +1455,7 @@
}
if (!cti_save_disable)
- drvdata->cti_save = of_property_read_bool(pdev->dev.of_node,
+ drvdata->cti_save = of_property_read_bool(adev->dev.of_node,
"qcom,cti-save");
if (drvdata->cti_save) {
drvdata->state = devm_kzalloc(dev, sizeof(struct cti_state),
@@ -1476,18 +1463,18 @@
if (!drvdata->state)
return -ENOMEM;
- drvdata->cti_hwclk = of_property_read_bool(pdev->dev.of_node,
+ drvdata->cti_hwclk = of_property_read_bool(adev->dev.of_node,
"qcom,cti-hwclk");
}
if (drvdata->cti_save && !drvdata->cti_hwclk) {
- ret = clk_prepare_enable(drvdata->clk);
+ ret = pm_runtime_get_sync(drvdata->dev);
if (ret)
return ret;
}
mutex_lock(&cti_lock);
drvdata->cti.name = ((struct coresight_platform_data *)
- (pdev->dev.platform_data))->name;
+ (adev->dev.platform_data))->name;
list_add_tail(&drvdata->cti.link, &cti_list);
mutex_unlock(&cti_lock);
@@ -1497,8 +1484,8 @@
goto err;
}
desc->type = CORESIGHT_DEV_TYPE_NONE;
- desc->pdata = pdev->dev.platform_data;
- desc->dev = &pdev->dev;
+ desc->pdata = adev->dev.platform_data;
+ desc->dev = &adev->dev;
desc->groups = cti_attr_grps;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
@@ -1511,56 +1498,35 @@
cpu_pm_register_notifier(&cti_cpu_pm_notifier);
registered++;
}
-
+ pm_runtime_put(&adev->dev);
dev_dbg(dev, "CTI initialized\n");
return 0;
err:
if (drvdata->cti_save && !drvdata->cti_hwclk)
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
return ret;
}
-static int cti_remove(struct platform_device *pdev)
-{
- struct cti_drvdata *drvdata = platform_get_drvdata(pdev);
-
- if (drvdata->cti_save) {
- registered--;
- if (!registered)
- cpu_pm_unregister_notifier(&cti_cpu_pm_notifier);
- }
- coresight_unregister(drvdata->csdev);
- if (drvdata->cti_save && !drvdata->cti_hwclk)
- clk_disable_unprepare(drvdata->clk);
- return 0;
-}
-
-static const struct of_device_id cti_match[] = {
- {.compatible = "arm,coresight-cti"},
- {}
+static struct amba_id cti_ids[] = {
+ {
+ .id = 0x0003b966,
+ .mask = 0x0003ffff,
+ .data = "CTI",
+ },
+ { 0, 0},
};
-static struct platform_driver cti_driver = {
- .probe = cti_probe,
- .remove = cti_remove,
- .driver = {
+static struct amba_driver cti_driver = {
+ .drv = {
.name = "coresight-cti",
.owner = THIS_MODULE,
- .of_match_table = cti_match,
+ .suppress_bind_attrs = true,
},
+ .probe = cti_probe,
+ .id_table = cti_ids,
};
-static int __init cti_init(void)
-{
- return platform_driver_register(&cti_driver);
-}
-module_init(cti_init);
-
-static void __exit cti_exit(void)
-{
- platform_driver_unregister(&cti_driver);
-}
-module_exit(cti_exit);
+builtin_amba_driver(cti_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight CTI driver");
diff --git a/drivers/hwtracing/coresight/coresight-replicator-qcom.c b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
index 0bd8b78..98547a9 100644
--- a/drivers/hwtracing/coresight/coresight-replicator-qcom.c
+++ b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
@@ -47,8 +47,6 @@
{
struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent);
- pm_runtime_get_sync(drvdata->dev);
-
CS_UNLOCK(drvdata->base);
/*
@@ -85,7 +83,6 @@
CS_LOCK(drvdata->base);
- pm_runtime_put(drvdata->dev);
dev_info(drvdata->dev, "REPLICATOR disabled\n");
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index f5018fc..10e8da4 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -436,8 +436,11 @@
if (ret)
drvdata->size = SZ_1M;
+ if (of_property_read_bool(np, "arm,sg-enable"))
+ drvdata->memtype = TMC_ETR_MEM_TYPE_SG;
+ else
+ drvdata->memtype = TMC_ETR_MEM_TYPE_CONTIG;
drvdata->mem_size = drvdata->size;
- drvdata->memtype = TMC_ETR_MEM_TYPE_CONTIG;
drvdata->mem_type = drvdata->memtype;
} else {
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index c96087d..5d2d087 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.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
@@ -14,10 +14,10 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/fs.h>
-#include <linux/clk.h>
#include <linux/bitmap.h>
#include <linux/of.h>
#include <linux/coresight.h>
@@ -53,7 +53,6 @@
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
- struct clk *clk;
struct mutex lock;
bool enable;
uint32_t atid;
@@ -183,11 +182,6 @@
static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
mutex_lock(&drvdata->lock);
__tpda_enable(drvdata, inport);
@@ -221,8 +215,6 @@
drvdata->enable = false;
mutex_unlock(&drvdata->lock);
- clk_disable_unprepare(drvdata->clk);
-
dev_info(drvdata->dev, "TPDA inport %d disabled\n", inport);
}
@@ -653,31 +645,27 @@
drvdata->freq_ts = true;
}
-static int tpda_probe(struct platform_device *pdev)
+static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
- struct device *dev = &pdev->dev;
+ struct device *dev = &adev->dev;
struct coresight_platform_data *pdata;
struct tpda_drvdata *drvdata;
- struct resource *res;
struct coresight_desc *desc;
- pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
- pdev->dev.platform_data = pdata;
+ adev->dev.platform_data = pdata;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- drvdata->dev = &pdev->dev;
- platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpda-base");
- if (!res)
- return -ENODEV;
+ drvdata->dev = &adev->dev;
+ dev_set_drvdata(dev, drvdata);
- drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ drvdata->base = devm_ioremap_resource(dev, &adev->res);
if (!drvdata->base)
return -ENOMEM;
@@ -687,22 +675,10 @@
if (ret)
return ret;
- drvdata->clk = devm_clk_get(dev, "core_clk");
- if (IS_ERR(drvdata->clk))
- return PTR_ERR(drvdata->clk);
-
- ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
if (!coresight_authstatus_enabled(drvdata->base))
goto err;
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
tpda_init_default_data(drvdata);
@@ -712,8 +688,8 @@
desc->type = CORESIGHT_DEV_TYPE_LINK;
desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
desc->ops = &tpda_cs_ops;
- desc->pdata = pdev->dev.platform_data;
- desc->dev = &pdev->dev;
+ desc->pdata = adev->dev.platform_data;
+ desc->dev = &adev->dev;
desc->groups = tpda_attr_grps;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev))
@@ -722,44 +698,29 @@
dev_dbg(drvdata->dev, "TPDA initialized\n");
return 0;
err:
- clk_disable_unprepare(drvdata->clk);
return -EPERM;
}
-static int tpda_remove(struct platform_device *pdev)
-{
- struct tpda_drvdata *drvdata = platform_get_drvdata(pdev);
-
- coresight_unregister(drvdata->csdev);
- return 0;
-}
-
-static const struct of_device_id tpda_match[] = {
- {.compatible = "qcom,coresight-tpda"},
- {}
+static struct amba_id tpda_ids[] = {
+ {
+ .id = 0x0003b969,
+ .mask = 0x0003ffff,
+ .data = "TPDA",
+ },
+ { 0, 0},
};
-static struct platform_driver tpda_driver = {
- .probe = tpda_probe,
- .remove = tpda_remove,
- .driver = {
+static struct amba_driver tpda_driver = {
+ .drv = {
.name = "coresight-tpda",
.owner = THIS_MODULE,
- .of_match_table = tpda_match,
+ .suppress_bind_attrs = true,
},
+ .probe = tpda_probe,
+ .id_table = tpda_ids,
};
-static int __init tpda_init(void)
-{
- return platform_driver_register(&tpda_driver);
-}
-module_init(tpda_init);
-
-static void __exit tpda_exit(void)
-{
- platform_driver_unregister(&tpda_driver);
-}
-module_exit(tpda_exit);
+builtin_amba_driver(tpda_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Aggregator driver");
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 673689c..36e3db2 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -13,11 +13,10 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
-#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/fs.h>
-#include <linux/clk.h>
#include <linux/bitmap.h>
#include <linux/of.h>
#include <linux/coresight.h>
@@ -159,11 +158,6 @@
TPDM_SUPPORT_TYPE_NO,
};
-enum tpdm_cmb_mode {
- TPDM_CMB_MODE_CONTINUOUS,
- TPDM_CMB_MODE_TRACE_ON_CHANGE,
-};
-
enum tpdm_cmb_patt_bits {
TPDM_CMB_LSB,
TPDM_CMB_MSB,
@@ -234,7 +228,8 @@
};
struct cmb_dataset {
- enum tpdm_cmb_mode mode;
+ bool trace_mode;
+ uint32_t cycle_acc;
uint32_t patt_val[TPDM_CMB_PATT_CMP];
uint32_t patt_mask[TPDM_CMB_PATT_CMP];
bool patt_ts;
@@ -250,7 +245,6 @@
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
- struct clk *clk;
struct mutex lock;
bool enable;
bool clk_enable;
@@ -528,24 +522,18 @@
static void __tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
{
uint32_t val;
+ int i;
- tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_LSB],
- TPDM_CMB_TPR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_LSB],
- TPDM_CMB_TPMR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_MSB],
- TPDM_CMB_TPR(TPDM_CMB_MSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_MSB],
- TPDM_CMB_TPMR(TPDM_CMB_MSB));
-
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_LSB],
- TPDM_CMB_XPR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB],
- TPDM_CMB_XPMR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_MSB],
- TPDM_CMB_XPR(TPDM_CMB_MSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB],
- TPDM_CMB_XPMR(TPDM_CMB_MSB));
+ for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
+ tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
+ TPDM_CMB_TPR(i));
+ tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
+ TPDM_CMB_TPMR(i));
+ tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
+ TPDM_CMB_XPR(i));
+ tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
+ TPDM_CMB_XPMR(i));
+ }
val = tpdm_readl(drvdata, TPDM_CMB_TIER);
if (drvdata->cmb->patt_ts == true)
@@ -563,10 +551,13 @@
val = tpdm_readl(drvdata, TPDM_CMB_CR);
/* Set the flow control bit */
val = val & ~BIT(2);
- if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
- val = val & ~BIT(1);
- else
+ if (drvdata->cmb->trace_mode)
val = val | BIT(1);
+ else
+ val = val & ~BIT(1);
+
+ val = val & ~BM(8, 9);
+ val = val | BMVAL(drvdata->cmb->cycle_acc, 0, 1) << 8;
tpdm_writel(drvdata, val, TPDM_CMB_CR);
/* Set the enable bit */
val = val | BIT(0);
@@ -577,24 +568,18 @@
{
uint32_t val;
struct mcmb_dataset *mcmb = drvdata->cmb->mcmb;
+ int i;
- tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_LSB],
- TPDM_CMB_TPR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_LSB],
- TPDM_CMB_TPMR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_val[TPDM_CMB_MSB],
- TPDM_CMB_TPR(TPDM_CMB_MSB));
- tpdm_writel(drvdata, drvdata->cmb->patt_mask[TPDM_CMB_MSB],
- TPDM_CMB_TPMR(TPDM_CMB_MSB));
-
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_LSB],
- TPDM_CMB_XPR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_LSB],
- TPDM_CMB_XPMR(TPDM_CMB_LSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[TPDM_CMB_MSB],
- TPDM_CMB_XPR(TPDM_CMB_MSB));
- tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[TPDM_CMB_MSB],
- TPDM_CMB_XPMR(TPDM_CMB_MSB));
+ for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
+ tpdm_writel(drvdata, drvdata->cmb->patt_val[i],
+ TPDM_CMB_TPR(i));
+ tpdm_writel(drvdata, drvdata->cmb->patt_mask[i],
+ TPDM_CMB_TPMR(i));
+ tpdm_writel(drvdata, drvdata->cmb->trig_patt_val[i],
+ TPDM_CMB_XPR(i));
+ tpdm_writel(drvdata, drvdata->cmb->trig_patt_mask[i],
+ TPDM_CMB_XPMR(i));
+ }
val = tpdm_readl(drvdata, TPDM_CMB_TIER);
if (drvdata->cmb->patt_ts == true)
@@ -612,14 +597,17 @@
val = tpdm_readl(drvdata, TPDM_CMB_CR);
/* Set the flow control bit */
val = val & ~BIT(2);
- if (drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS)
- val = val & ~BIT(1);
- else
+ if (drvdata->cmb->trace_mode)
val = val | BIT(1);
+ else
+ val = val & ~BIT(1);
- val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 3) << 18);
-
- val = val | (mcmb->mcmb_lane_select << 10);
+ val = val & ~BM(8, 9);
+ val = val | BMVAL(drvdata->cmb->cycle_acc, 0, 1) << 8;
+ val = val & ~BM(18, 20);
+ val = val | (BMVAL(mcmb->mcmb_trig_lane, 0, 2) << 18);
+ val = val & ~BM(10, 17);
+ val = val | (BMVAL(mcmb->mcmb_lane_select, 0, 7) << 10);
tpdm_writel(drvdata, val, TPDM_CMB_CR);
/* Set the enable bit */
@@ -658,11 +646,6 @@
struct perf_event *event, u32 mode)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- int ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
mutex_lock(&drvdata->lock);
__tpdm_enable(drvdata);
@@ -722,7 +705,8 @@
if (test_bit(TPDM_DS_DSB, drvdata->enable_ds))
__tpdm_disable_dsb(drvdata);
- if (test_bit(TPDM_DS_CMB, drvdata->enable_ds))
+ if (test_bit(TPDM_DS_CMB, drvdata->enable_ds) ||
+ test_bit(TPDM_DS_MCMB, drvdata->enable_ds))
__tpdm_disable_cmb(drvdata);
if (drvdata->clk_enable)
@@ -741,8 +725,6 @@
drvdata->enable = false;
mutex_unlock(&drvdata->lock);
- clk_disable_unprepare(drvdata->clk);
-
dev_info(drvdata->dev, "TPDM tracing disabled\n");
}
@@ -3192,9 +3174,10 @@
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
- return scnprintf(buf, PAGE_SIZE, "%s\n",
- drvdata->cmb->mode == TPDM_CMB_MODE_CONTINUOUS ?
- "continuous" : "trace_on_change");
+ return scnprintf(buf, PAGE_SIZE, "trace_mode: %s cycle_acc: %d\n",
+ drvdata->cmb->trace_mode ?
+ "trace_on_change" : "continuous",
+ drvdata->cmb->cycle_acc);
}
static ssize_t tpdm_store_cmb_mode(struct device *dev,
@@ -3203,180 +3186,118 @@
size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- char str[20] = "";
+ unsigned int trace_mode, cycle_acc;
+ int nval;
- if (strlen(buf) >= 20)
+ nval = sscanf(buf, "%u %u", &trace_mode, &cycle_acc);
+ if (nval != 2)
return -EINVAL;
- if (sscanf(buf, "%s", str) != 1)
- return -EINVAL;
+
if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
mutex_lock(&drvdata->lock);
- if (!strcmp(str, "continuous")) {
- drvdata->cmb->mode = TPDM_CMB_MODE_CONTINUOUS;
- } else if (!strcmp(str, "trace_on_change")) {
- drvdata->cmb->mode = TPDM_CMB_MODE_TRACE_ON_CHANGE;
- } else {
- mutex_unlock(&drvdata->lock);
- return -EINVAL;
- }
+ drvdata->cmb->trace_mode = trace_mode;
+ drvdata->cmb->cycle_acc = cycle_acc;
mutex_unlock(&drvdata->lock);
return size;
}
static DEVICE_ATTR(cmb_mode, 0644,
tpdm_show_cmb_mode, tpdm_store_cmb_mode);
-static ssize_t tpdm_show_cmb_patt_val_lsb(struct device *dev,
+static ssize_t tpdm_show_cmb_patt_val(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
+ ssize_t size = 0;
+ int i;
if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
- val = drvdata->cmb->patt_val[TPDM_CMB_LSB];
-
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->patt_val[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
}
-static ssize_t tpdm_store_cmb_patt_val_lsb(struct device *dev,
+static ssize_t tpdm_store_cmb_patt_val(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
+ unsigned long index, val;
- if (kstrtoul(buf, 16, &val))
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_PATT_CMP)
return -EINVAL;
if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
mutex_lock(&drvdata->lock);
- drvdata->cmb->patt_val[TPDM_CMB_LSB] = val;
+ drvdata->cmb->patt_val[index] = val;
mutex_unlock(&drvdata->lock);
+
return size;
}
-static DEVICE_ATTR(cmb_patt_val_lsb, 0644,
- tpdm_show_cmb_patt_val_lsb,
- tpdm_store_cmb_patt_val_lsb);
+static DEVICE_ATTR(cmb_patt_val, 0644,
+ tpdm_show_cmb_patt_val,
+ tpdm_store_cmb_patt_val);
-static ssize_t tpdm_show_cmb_patt_mask_lsb(struct device *dev,
+static ssize_t tpdm_show_cmb_patt_mask(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
+ ssize_t size = 0;
+ int i;
if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
- val = drvdata->cmb->patt_mask[TPDM_CMB_LSB];
+ mutex_lock(&drvdata->lock);
+ for (i = 0; i < TPDM_CMB_PATT_CMP; i++) {
+ size += scnprintf(buf + size, PAGE_SIZE - size,
+ "Index: 0x%x Value: 0x%x\n", i,
+ drvdata->cmb->patt_mask[i]);
+ }
+ mutex_unlock(&drvdata->lock);
+ return size;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
-static ssize_t tpdm_store_cmb_patt_mask_lsb(struct device *dev,
+static ssize_t tpdm_store_cmb_patt_mask(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
+ unsigned long index, val;
- if (kstrtoul(buf, 16, &val))
+ if (sscanf(buf, "%lx %lx", &index, &val) != 2)
+ return -EINVAL;
+ if (index >= TPDM_CMB_PATT_CMP)
return -EINVAL;
if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
test_bit(TPDM_DS_MCMB, drvdata->datasets)))
return -EPERM;
mutex_lock(&drvdata->lock);
- drvdata->cmb->patt_mask[TPDM_CMB_LSB] = val;
+ drvdata->cmb->patt_mask[index] = val;
mutex_unlock(&drvdata->lock);
return size;
}
-static DEVICE_ATTR(cmb_patt_mask_lsb, 0644,
- tpdm_show_cmb_patt_mask_lsb, tpdm_store_cmb_patt_mask_lsb);
-
-static ssize_t tpdm_show_cmb_patt_val_msb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
-
- if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
- test_bit(TPDM_DS_MCMB, drvdata->datasets)))
- return -EPERM;
-
- val = drvdata->cmb->patt_val[TPDM_CMB_MSB];
-
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t tpdm_store_cmb_patt_val_msb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
-
- if (kstrtoul(buf, 16, &val))
- return -EINVAL;
- if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
- test_bit(TPDM_DS_MCMB, drvdata->datasets)))
- return -EPERM;
-
- mutex_lock(&drvdata->lock);
- drvdata->cmb->patt_val[TPDM_CMB_MSB] = val;
- mutex_unlock(&drvdata->lock);
- return size;
-}
-static DEVICE_ATTR(cmb_patt_val_msb, 0644,
- tpdm_show_cmb_patt_val_msb,
- tpdm_store_cmb_patt_val_msb);
-
-static ssize_t tpdm_show_cmb_patt_mask_msb(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
-
- if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
- test_bit(TPDM_DS_MCMB, drvdata->datasets)))
- return -EPERM;
-
- val = drvdata->cmb->patt_mask[TPDM_CMB_MSB];
-
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t tpdm_store_cmb_patt_mask_msb(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- unsigned long val;
-
- if (kstrtoul(buf, 16, &val))
- return -EINVAL;
- if (!(test_bit(TPDM_DS_CMB, drvdata->datasets) ||
- test_bit(TPDM_DS_MCMB, drvdata->datasets)))
- return -EPERM;
-
- mutex_lock(&drvdata->lock);
- drvdata->cmb->patt_mask[TPDM_CMB_MSB] = val;
- mutex_unlock(&drvdata->lock);
- return size;
-}
-static DEVICE_ATTR(cmb_patt_mask_msb, 0644,
- tpdm_show_cmb_patt_mask_msb, tpdm_store_cmb_patt_mask_msb);
+static DEVICE_ATTR(cmb_patt_mask, 0644,
+ tpdm_show_cmb_patt_mask, tpdm_store_cmb_patt_mask);
static ssize_t tpdm_show_cmb_patt_ts(struct device *dev,
struct device_attribute *attr,
@@ -3896,10 +3817,8 @@
static struct attribute *tpdm_cmb_attrs[] = {
&dev_attr_cmb_available_modes.attr,
&dev_attr_cmb_mode.attr,
- &dev_attr_cmb_patt_val_lsb.attr,
- &dev_attr_cmb_patt_mask_lsb.attr,
- &dev_attr_cmb_patt_val_msb.attr,
- &dev_attr_cmb_patt_mask_msb.attr,
+ &dev_attr_cmb_patt_val.attr,
+ &dev_attr_cmb_patt_mask.attr,
&dev_attr_cmb_patt_ts.attr,
&dev_attr_cmb_trig_patt_val_lsb.attr,
&dev_attr_cmb_trig_patt_mask_lsb.attr,
@@ -4011,57 +3930,40 @@
drvdata->cmb->trig_ts = true;
}
-static int tpdm_probe(struct platform_device *pdev)
+static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret, i;
uint32_t pidr, devid;
- struct device *dev = &pdev->dev;
+ struct device *dev = &adev->dev;
struct coresight_platform_data *pdata;
struct tpdm_drvdata *drvdata;
- struct resource *res;
struct coresight_desc *desc;
static int traceid = TPDM_TRACE_ID_START;
uint32_t version;
- pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
- pdev->dev.platform_data = pdata;
+ adev->dev.platform_data = pdata;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- drvdata->dev = &pdev->dev;
- platform_set_drvdata(pdev, drvdata);
+ drvdata->dev = &adev->dev;
+ dev_set_drvdata(dev, drvdata);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
- if (!res)
- return -ENODEV;
-
- drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ drvdata->base = devm_ioremap_resource(dev, &adev->res);
if (!drvdata->base)
return -ENOMEM;
- drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
+ drvdata->clk_enable = of_property_read_bool(adev->dev.of_node,
"qcom,clk-enable");
- drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
+ drvdata->msr_fix_req = of_property_read_bool(adev->dev.of_node,
"qcom,msr-fix-req");
mutex_init(&drvdata->lock);
- drvdata->clk = devm_clk_get(dev, "core_clk");
- if (IS_ERR(drvdata->clk))
- return PTR_ERR(drvdata->clk);
-
- ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- return ret;
-
version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
drvdata->version = BMVAL(version, 4, 7);
@@ -4089,7 +3991,7 @@
drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
- clk_disable_unprepare(drvdata->clk);
+ pm_runtime_put(&adev->dev);
drvdata->traceid = traceid++;
@@ -4099,8 +4001,8 @@
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &tpdm_cs_ops;
- desc->pdata = pdev->dev.platform_data;
- desc->dev = &pdev->dev;
+ desc->pdata = adev->dev.platform_data;
+ desc->dev = &adev->dev;
desc->groups = tpdm_attr_grps;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev))
@@ -4114,40 +4016,26 @@
return 0;
}
-static int tpdm_remove(struct platform_device *pdev)
-{
- struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
-
- coresight_unregister(drvdata->csdev);
- return 0;
-}
-
-static const struct of_device_id tpdm_match[] = {
- {.compatible = "qcom,coresight-tpdm"},
- {}
+static struct amba_id tpdm_ids[] = {
+ {
+ .id = 0x0003b968,
+ .mask = 0x0003ffff,
+ .data = "TPDM",
+ },
+ { 0, 0},
};
-static struct platform_driver tpdm_driver = {
- .probe = tpdm_probe,
- .remove = tpdm_remove,
- .driver = {
+static struct amba_driver tpdm_driver = {
+ .drv = {
.name = "coresight-tpdm",
.owner = THIS_MODULE,
- .of_match_table = tpdm_match,
+ .suppress_bind_attrs = true,
},
+ .probe = tpdm_probe,
+ .id_table = tpdm_ids,
};
-static int __init tpdm_init(void)
-{
- return platform_driver_register(&tpdm_driver);
-}
-module_init(tpdm_init);
-
-static void __exit tpdm_exit(void)
-{
- platform_driver_unregister(&tpdm_driver);
-}
-module_exit(tpdm_exit);
+builtin_amba_driver(tpdm_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index d4f3239..f283b71 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -64,6 +64,7 @@
int irq;
struct i2c_adapter adapter;
struct completion completion;
+ struct i2c_msg *curr_msg;
u32 msg_err;
u8 *msg_buf;
size_t msg_buf_remaining;
@@ -126,14 +127,13 @@
return IRQ_HANDLED;
}
- if (val & BCM2835_I2C_S_RXD) {
- bcm2835_drain_rxfifo(i2c_dev);
- if (!(val & BCM2835_I2C_S_DONE))
- return IRQ_HANDLED;
- }
-
if (val & BCM2835_I2C_S_DONE) {
- if (i2c_dev->msg_buf_remaining)
+ if (i2c_dev->curr_msg->flags & I2C_M_RD) {
+ bcm2835_drain_rxfifo(i2c_dev);
+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+ }
+
+ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining)
i2c_dev->msg_err = BCM2835_I2C_S_LEN;
else
i2c_dev->msg_err = 0;
@@ -141,11 +141,16 @@
return IRQ_HANDLED;
}
- if (val & BCM2835_I2C_S_TXD) {
+ if (val & BCM2835_I2C_S_TXW) {
bcm2835_fill_txfifo(i2c_dev);
return IRQ_HANDLED;
}
+ if (val & BCM2835_I2C_S_RXR) {
+ bcm2835_drain_rxfifo(i2c_dev);
+ return IRQ_HANDLED;
+ }
+
return IRQ_NONE;
}
@@ -155,6 +160,7 @@
u32 c;
unsigned long time_left;
+ i2c_dev->curr_msg = msg;
i2c_dev->msg_buf = msg->buf;
i2c_dev->msg_buf_remaining = msg->len;
reinit_completion(&i2c_dev->completion);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index bbe1524..f397a5b 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -201,6 +201,7 @@
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
{ 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+ { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
{ 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
{ 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
{ 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
@@ -329,6 +330,7 @@
XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */
+ XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */
XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
{ }
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1e37af3..dd96670 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -828,26 +828,26 @@
return 0;
}
- ret = regulator_bulk_enable(pwr->num_gdscs, pwr->gdscs);
+ ret = arm_smmu_request_bus(pwr);
if (ret)
goto out_unlock;
- ret = arm_smmu_request_bus(pwr);
+ ret = regulator_bulk_enable(pwr->num_gdscs, pwr->gdscs);
if (ret)
- goto out_disable_regulators;
+ goto out_disable_bus;
ret = arm_smmu_prepare_clocks(pwr);
if (ret)
- goto out_disable_bus;
+ goto out_disable_regulators;
pwr->power_count = 1;
mutex_unlock(&pwr->power_lock);
return 0;
-out_disable_bus:
- arm_smmu_unrequest_bus(pwr);
out_disable_regulators:
regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs);
+out_disable_bus:
+ arm_smmu_unrequest_bus(pwr);
out_unlock:
mutex_unlock(&pwr->power_lock);
return ret;
@@ -868,8 +868,8 @@
}
arm_smmu_unprepare_clocks(pwr);
- arm_smmu_unrequest_bus(pwr);
regulator_bulk_disable(pwr->num_gdscs, pwr->gdscs);
+ arm_smmu_unrequest_bus(pwr);
pwr->power_count = 0;
mutex_unlock(&pwr->power_lock);
}
@@ -3341,7 +3341,7 @@
i = 0;
of_property_for_each_string(dev->of_node, "qcom,regulator-names",
prop, cname)
- pwr->gdscs[i].supply = cname;
+ pwr->gdscs[i++].supply = cname;
ret = devm_regulator_bulk_get(dev, pwr->num_gdscs, pwr->gdscs);
return ret;
@@ -4375,7 +4375,7 @@
/* Attempt to register child devices */
ret = device_for_each_child(dev, smmu, qsmmuv500_tbu_register);
if (ret)
- return -EINVAL;
+ return -EPROBE_DEFER;
return 0;
}
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index c90fbf0..261c125 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1750,3 +1750,23 @@
return 0;
}
EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids);
+
+/*
+ * Return the id asoociated with a pci device.
+ */
+int iommu_fwspec_get_id(struct device *dev, u32 *id)
+{
+ struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+ if (!fwspec)
+ return -EINVAL;
+
+ if (!dev_is_pci(dev))
+ return -EINVAL;
+
+ if (fwspec->num_ids != 1)
+ return -EINVAL;
+
+ *id = fwspec->ids[0];
+ return 0;
+}
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index 15af9a9..2d203b4 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -230,6 +230,8 @@
return -ENOMEM;
}
+ raw_spin_lock_init(&cd->rlock);
+
cd->gpc_base = of_iomap(node, 0);
if (!cd->gpc_base) {
pr_err("fsl-gpcv2: unable to map gpc registers\n");
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index 0a802fd..96b4472 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -15,6 +15,7 @@
#include <linux/atomic.h>
#include <linux/bitmap.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
@@ -86,6 +87,7 @@
#define TCS_TYPE_NR 4
#define TCS_MBOX_TOUT_MS 2000
#define MAX_POOL_SIZE (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
+#define TCS_M_INIT 0xFFFF
struct tcs_drv;
@@ -97,10 +99,12 @@
struct tasklet_struct tasklet;
struct delayed_work dwork;
int err;
+ int idx;
+ bool in_use;
};
struct tcs_response_pool {
- struct tcs_response *resp;
+ struct tcs_response resp[MAX_POOL_SIZE];
spinlock_t lock;
DECLARE_BITMAP(avail, MAX_POOL_SIZE);
};
@@ -116,8 +120,6 @@
int ncpt; /* num cmds per tcs */
DECLARE_BITMAP(slots, MAX_TCS_SLOTS);
spinlock_t tcs_lock; /* TCS type lock */
- spinlock_t tcs_m_lock[MAX_TCS_PER_TYPE];
- struct tcs_response *resp[MAX_TCS_PER_TYPE];
};
/* One per MBOX controller */
@@ -148,16 +150,13 @@
if (!pool)
return -ENOMEM;
- pool->resp = devm_kzalloc(&drv->pdev->dev, sizeof(*pool->resp) *
- MAX_POOL_SIZE, GFP_KERNEL);
- if (!pool->resp)
- return -ENOMEM;
-
for (i = 0; i < MAX_POOL_SIZE; i++) {
tasklet_init(&pool->resp[i].tasklet, tcs_notify_tx_done,
(unsigned long) &pool->resp[i]);
- INIT_DELAYED_WORK(&pool->resp[i].dwork,
- tcs_notify_timeout);
+ INIT_DELAYED_WORK(&pool->resp[i].dwork, tcs_notify_timeout);
+ pool->resp[i].drv = drv;
+ pool->resp[i].idx = i;
+ pool->resp[i].m = TCS_M_INIT;
}
spin_lock_init(&pool->lock);
@@ -166,39 +165,59 @@
return 0;
}
-static struct tcs_response *get_response_from_pool(struct tcs_drv *drv)
+static struct tcs_response *setup_response(struct tcs_drv *drv,
+ struct tcs_mbox_msg *msg, struct mbox_chan *chan,
+ u32 m, int err)
{
struct tcs_response_pool *pool = drv->resp_pool;
struct tcs_response *resp = ERR_PTR(-ENOMEM);
- unsigned long flags;
int pos;
- spin_lock_irqsave(&pool->lock, flags);
+ spin_lock(&pool->lock);
pos = find_first_zero_bit(pool->avail, MAX_POOL_SIZE);
if (pos != MAX_POOL_SIZE) {
bitmap_set(pool->avail, pos, 1);
resp = &pool->resp[pos];
- memset(resp, 0, sizeof(*resp));
- tasklet_init(&resp->tasklet, tcs_notify_tx_done,
- (unsigned long) resp);
- INIT_DELAYED_WORK(&resp->dwork, tcs_notify_timeout);
- resp->drv = drv;
+ resp->chan = chan;
+ resp->msg = msg;
+ resp->m = m;
+ resp->err = err;
+ resp->in_use = false;
}
- spin_unlock_irqrestore(&pool->lock, flags);
+ spin_unlock(&pool->lock);
return resp;
}
-static void free_response_to_pool(struct tcs_response *resp)
+static void free_response(struct tcs_response *resp)
{
struct tcs_response_pool *pool = resp->drv->resp_pool;
- unsigned long flags;
- int i;
- spin_lock_irqsave(&pool->lock, flags);
- i = resp - pool->resp;
- bitmap_clear(pool->avail, i, 1);
- spin_unlock_irqrestore(&pool->lock, flags);
+ spin_lock(&pool->lock);
+ resp->err = -EINVAL;
+ bitmap_clear(pool->avail, resp->idx, 1);
+ spin_unlock(&pool->lock);
+}
+
+static inline struct tcs_response *get_response(struct tcs_drv *drv, u32 m)
+{
+ struct tcs_response_pool *pool = drv->resp_pool;
+ struct tcs_response *resp = NULL;
+ int pos = 0;
+
+ do {
+ pos = find_next_bit(pool->avail, MAX_POOL_SIZE, pos);
+ if (pos == MAX_POOL_SIZE)
+ break;
+ resp = &pool->resp[pos];
+ if (resp->m == m && !resp->in_use) {
+ resp->in_use = true;
+ break;
+ }
+ pos++;
+ } while (1);
+
+ return resp;
}
static inline u32 read_drv_config(void __iomem *base)
@@ -226,7 +245,7 @@
write_tcs_reg(base, reg, m, n, data);
if (data == read_tcs_reg(base, reg, m, n))
break;
- cpu_relax();
+ udelay(1);
} while (1);
}
@@ -311,13 +330,6 @@
return get_tcs_of_type(drv, type);
}
-static inline struct tcs_response *get_tcs_response(struct tcs_drv *drv, int m)
-{
- struct tcs_mbox *tcs = get_tcs_from_index(drv, m);
-
- return tcs ? tcs->resp[m - tcs->tcs_offset] : NULL;
-}
-
static inline void send_tcs_response(struct tcs_response *resp)
{
tasklet_schedule(&resp->tasklet);
@@ -340,7 +352,6 @@
struct tcs_mbox *tcs;
struct tcs_response *resp;
struct tcs_cmd *cmd;
- u32 irq_clear = 0;
u32 data;
/* Know which TCSes were triggered */
@@ -350,8 +361,7 @@
if (!(irq_status & BIT(m)))
continue;
- /* Find the TCS that triggered */
- resp = get_tcs_response(drv, m);
+ resp = get_response(drv, m);
if (!resp) {
pr_err("No resp request for TCS-%d\n", m);
continue;
@@ -397,18 +407,13 @@
write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, 0);
}
- /* Notify the client that this request is completed. */
+ /* Clear the TCS IRQ status */
+ write_tcs_reg(base, TCS_DRV_IRQ_CLEAR, 0, 0, BIT(m));
+
+ /* Clean up response object and notify mbox in tasklet */
send_tcs_response(resp);
- irq_clear |= BIT(m);
- }
- /* Clear the TCS IRQ status */
- write_tcs_reg(base, TCS_DRV_IRQ_CLEAR, 0, 0, irq_clear);
-
- /* Mark the TCS as free */
- for (m = 0; irq_status >= BIT(m); m++) {
- if (!(irq_status & BIT(m)))
- continue;
+ /* Notify the client that this request is completed. */
atomic_set(&drv->tcs_in_use[m], 0);
}
@@ -435,8 +440,8 @@
int err = resp->err;
int m = resp->m;
- free_response_to_pool(resp);
mbox_notify_tx_done(chan, msg, m, err);
+ free_response(resp);
}
/**
@@ -468,7 +473,7 @@
cmd = &msg->payload[i];
addr = read_tcs_reg(drv->reg_base, TCS_DRV_CMD_ADDR,
m, i);
- pending = (cmd->addr == addr);
+ pending |= (cmd->addr == addr);
}
if (pending) {
pr_err("TCS-%d blocked waiting for RPMH to respond.\n",
@@ -481,8 +486,8 @@
}
}
- free_response_to_pool(resp);
mbox_notify_tx_done(chan, msg, -1, -ETIMEDOUT);
+ free_response(resp);
}
static void __tcs_buffer_write(struct tcs_drv *drv, int d, int m, int n,
@@ -525,8 +530,6 @@
write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, cmd_enable);
if (trigger) {
- /* Mark the TCS as busy */
- atomic_set(&drv->tcs_in_use[m], 1);
/* HW req: Clear the DRV_CONTROL and enable TCS again */
write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, 0);
write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
@@ -590,13 +593,14 @@
}
retry:
if (!is_free)
- cpu_relax();
+ udelay(1);
} while (!is_free);
}
static int find_free_tcs(struct tcs_mbox *tcs)
{
int slot, m = 0;
+ u32 irq_status;
/* Loop until we find a free AMC */
do {
@@ -604,9 +608,14 @@
slot = m * tcs->ncpt;
break;
}
- if (++m >= tcs->num_tcs)
+ if (++m >= tcs->num_tcs) {
m = 0;
- cpu_relax();
+ irq_status = read_tcs_reg(tcs->drv->reg_base,
+ TCS_DRV_IRQ_STATUS, 0, 0);
+ WARN((irq_status & tcs->tcs_mask && in_irq()),
+ "TCS busy. Request should not be made from hard IRQ context.");
+ udelay(10);
+ }
} while (1);
return slot;
@@ -663,26 +672,6 @@
return (slot != MAX_TCS_SLOTS) ? slot : -ENOMEM;
}
-static struct tcs_response *setup_response(struct tcs_mbox *tcs,
- struct mbox_chan *chan, struct tcs_mbox_msg *msg, int m)
-{
- struct tcs_response *resp = get_response_from_pool(tcs->drv);
-
- if (IS_ERR(resp))
- return resp;
-
- if (m < tcs->tcs_offset)
- return ERR_PTR(-EINVAL);
-
- tcs->resp[m - tcs->tcs_offset] = resp;
- resp->msg = msg;
- resp->chan = chan;
- resp->m = m;
- resp->err = 0;
-
- return resp;
-}
-
static int tcs_mbox_write(struct mbox_chan *chan, struct tcs_mbox_msg *msg,
bool trigger)
{
@@ -697,14 +686,20 @@
if (IS_ERR(tcs))
return PTR_ERR(tcs);
+ if (trigger)
+ resp = setup_response(drv, msg, chan, TCS_M_INIT, 0);
+
/* Identify the sequential slots that we can write to */
spin_lock(&tcs->tcs_lock);
slot = find_slots(tcs, msg);
if (slot < 0) {
dev_err(dev, "No TCS slot found.\n");
spin_unlock(&tcs->tcs_lock);
+ if (resp)
+ free_response(resp);
return slot;
}
+
/* Mark the slots as in-use, before we unlock */
if (tcs->type == SLEEP_TCS || tcs->type == WAKE_TCS)
bitmap_set(tcs->slots, slot, msg->num_payload);
@@ -713,27 +708,16 @@
for (i = 0; tcs->cmd_addr && i < msg->num_payload; i++)
tcs->cmd_addr[slot + i] = msg->payload[i].addr;
- if (trigger)
- resp = setup_response(tcs, chan, msg,
- slot / tcs->ncpt + tcs->tcs_offset);
-
- spin_unlock(&tcs->tcs_lock);
-
- /*
- * Find the TCS corresponding to the slot and start writing.
- * Break down 'slot' into a 'n' position in the 'm'th TCS.
- */
offset = slot / tcs->ncpt;
m = offset + tcs->tcs_offset;
n = slot % tcs->ncpt;
- spin_lock(&tcs->tcs_m_lock[offset]);
+ /* Block, if we have an address from the msg in flight */
if (trigger) {
- /* Block, if we have an address from the msg in flight */
+ resp->m = m;
+ /* Mark the TCS as busy */
+ atomic_set(&drv->tcs_in_use[m], 1);
wait_for_req_inflight(drv, tcs, msg);
- /* If the TCS is busy there is nothing to do but spin wait */
- while (!tcs_is_free(drv, m))
- cpu_relax();
}
/* Write to the TCS or AMC */
@@ -743,7 +727,7 @@
if (trigger)
schedule_tcs_err_response(resp);
- spin_unlock(&tcs->tcs_m_lock[offset]);
+ spin_unlock(&tcs->tcs_lock);
return 0;
}
@@ -769,11 +753,9 @@
spin_lock(&tcs->tcs_lock);
for (i = 0; i < tcs->num_tcs; i++) {
m = i + tcs->tcs_offset;
- spin_lock(&tcs->tcs_m_lock[i]);
while (!tcs_is_free(drv, m))
- cpu_relax();
+ udelay(1);
__tcs_buffer_invalidate(drv->reg_base, m);
- spin_unlock(&tcs->tcs_m_lock[i]);
}
/* Mark the TCS as free */
bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
@@ -840,12 +822,9 @@
tx_fail:
if (ret) {
struct tcs_drv *drv = container_of(chan->mbox,
- struct tcs_drv, mbox);
- struct tcs_response *resp = get_response_from_pool(drv);
-
- resp->chan = chan;
- resp->msg = msg;
- resp->err = ret;
+ struct tcs_drv, mbox);
+ struct tcs_response *resp = setup_response(
+ drv, msg, chan, TCS_M_INIT, ret);
dev_err(dev, "Error sending RPMH message %d\n", ret);
send_tcs_response(resp);
@@ -1040,8 +1019,6 @@
tcs->ncpt = (tcs->type == CONTROL_TCS) ? TCS_HIDDEN_MAX_SLOTS
: ncpt;
spin_lock_init(&tcs->tcs_lock);
- for (j = 0; j < ARRAY_SIZE(tcs->tcs_m_lock); j++)
- spin_lock_init(&tcs->tcs_m_lock[j]);
if (tcs->num_tcs <= 0 || tcs->type == CONTROL_TCS)
continue;
@@ -1115,8 +1092,7 @@
if (irq < 0)
return irq;
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
- tcs_irq_handler,
+ ret = devm_request_irq(&pdev->dev, irq, tcs_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND,
"tcs_irq", drv);
if (ret)
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
index 4f75a19..019a775 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
@@ -28,25 +28,34 @@
#endif
static struct cam_req_mgr_util_hdl_tbl *hdl_tbl;
-static struct mutex hdl_tbl_mutex = __MUTEX_INITIALIZER(hdl_tbl_mutex);
+static DEFINE_SPINLOCK(hdl_tbl_lock);
int cam_req_mgr_util_init(void)
{
int rc = 0;
int bitmap_size;
+ static struct cam_req_mgr_util_hdl_tbl *hdl_tbl_local;
- mutex_lock(&hdl_tbl_mutex);
if (hdl_tbl) {
rc = -EINVAL;
pr_err("Hdl_tbl is already present\n");
goto hdl_tbl_check_failed;
}
- hdl_tbl = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL);
- if (!hdl_tbl) {
+ hdl_tbl_local = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL);
+ if (!hdl_tbl_local) {
rc = -ENOMEM;
goto hdl_tbl_alloc_failed;
}
+ spin_lock_bh(&hdl_tbl_lock);
+ if (hdl_tbl) {
+ spin_unlock_bh(&hdl_tbl_lock);
+ rc = -EEXIST;
+ kfree(hdl_tbl_local);
+ goto hdl_tbl_check_failed;
+ }
+ hdl_tbl = hdl_tbl_local;
+ spin_unlock_bh(&hdl_tbl_lock);
bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long);
hdl_tbl->bitmap = kzalloc(sizeof(bitmap_size), GFP_KERNEL);
@@ -55,7 +64,6 @@
goto bitmap_alloc_fail;
}
hdl_tbl->bits = bitmap_size * BITS_PER_BYTE;
- mutex_unlock(&hdl_tbl_mutex);
return rc;
@@ -64,16 +72,15 @@
hdl_tbl = NULL;
hdl_tbl_alloc_failed:
hdl_tbl_check_failed:
- mutex_unlock(&hdl_tbl_mutex);
return rc;
}
int cam_req_mgr_util_deinit(void)
{
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
@@ -81,7 +88,7 @@
hdl_tbl->bitmap = NULL;
kfree(hdl_tbl);
hdl_tbl = NULL;
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return 0;
}
@@ -90,10 +97,10 @@
{
int i = 0;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
@@ -107,7 +114,7 @@
}
}
bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES);
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return 0;
}
@@ -132,17 +139,17 @@
int rand = 0;
int32_t handle = 0;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
idx = cam_get_free_handle_index();
if (idx < 0) {
pr_err("Unable to create session handle\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@@ -154,7 +161,7 @@
hdl_tbl->hdl[idx].state = HDL_ACTIVE;
hdl_tbl->hdl[idx].priv = priv;
hdl_tbl->hdl[idx].ops = NULL;
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return handle;
}
@@ -165,17 +172,17 @@
int rand = 0;
int32_t handle;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
idx = cam_get_free_handle_index();
if (idx < 0) {
pr_err("Unable to create device handle\n");
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@@ -187,7 +194,7 @@
hdl_tbl->hdl[idx].state = HDL_ACTIVE;
hdl_tbl->hdl[idx].priv = hdl_data->priv;
hdl_tbl->hdl[idx].ops = hdl_data->ops;
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return handle;
}
@@ -198,7 +205,7 @@
int type;
void *priv;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
goto device_priv_fail;
@@ -227,12 +234,12 @@
}
priv = hdl_tbl->hdl[idx].priv;
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return priv;
device_priv_fail:
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return NULL;
}
@@ -242,7 +249,7 @@
int type;
void *ops;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
goto device_ops_fail;
@@ -271,12 +278,12 @@
}
ops = hdl_tbl->hdl[idx].ops;
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return ops;
device_ops_fail:
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return NULL;
}
@@ -285,7 +292,7 @@
int idx;
int type;
- mutex_lock(&hdl_tbl_mutex);
+ spin_lock_bh(&hdl_tbl_lock);
if (!hdl_tbl) {
pr_err("Hdl tbl is NULL\n");
goto destroy_hdl_fail;
@@ -315,12 +322,12 @@
hdl_tbl->hdl[idx].state = HDL_FREE;
clear_bit(idx, hdl_tbl->bitmap);
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return 0;
destroy_hdl_fail:
- mutex_unlock(&hdl_tbl_mutex);
+ spin_unlock_bh(&hdl_tbl_lock);
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index e327723..08466b1 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -104,14 +104,14 @@
workq = (struct cam_req_mgr_core_workq *)
container_of(w, struct cam_req_mgr_core_workq, work);
- spin_lock(&workq->task.lock);
list_for_each_entry_safe(task, task_save,
&workq->task.process_head, entry) {
atomic_sub(1, &workq->task.pending_cnt);
+ spin_lock(&workq->task.lock);
list_del_init(&task->entry);
+ spin_unlock(&workq->task.lock);
cam_req_mgr_process_task(task);
}
- spin_unlock(&workq->task.lock);
CRM_DBG("processed task %p free_cnt %d",
task, atomic_read(&workq->task.free_cnt));
}
@@ -138,7 +138,6 @@
goto end;
}
- spin_lock(&workq->task.lock);
if (task->cancel == 1) {
cam_req_mgr_workq_put_task(task);
CRM_WARN("task aborted and queued back to pool");
@@ -146,12 +145,14 @@
spin_unlock(&workq->task.lock);
goto end;
}
+ spin_lock(&workq->task.lock);
list_add_tail(&task->entry,
&workq->task.process_head);
+ spin_unlock(&workq->task.lock);
atomic_add(1, &workq->task.pending_cnt);
CRM_DBG("enq task %p pending_cnt %d",
task, atomic_read(&workq->task.pending_cnt));
- spin_unlock(&workq->task.lock);
+
queue_work(workq->job, &workq->work);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index a0b53bb..3bf6ce0 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -140,6 +140,18 @@
int domain;
};
+/*
+ * struct sde_rot_debug_bus: rotator debugbus header structure
+ * @wr_addr: write address for debugbus controller
+ * @block_id: rotator debugbus block id
+ * @test_id: rotator debugbus test id
+ */
+struct sde_rot_debug_bus {
+ u32 wr_addr;
+ u32 block_id;
+ u32 test_id;
+};
+
struct sde_rot_vbif_debug_bus {
u32 disable_bus_addr;
u32 block_bus_addr;
@@ -191,6 +203,8 @@
struct sde_rot_vbif_debug_bus *nrt_vbif_dbg_bus;
u32 nrt_vbif_dbg_bus_size;
+ struct sde_rot_debug_bus *rot_dbg_bus;
+ u32 rot_dbg_bus_size;
struct sde_rot_regdump *regdump;
u32 regdump_size;
@@ -199,6 +213,8 @@
int sec_cam_en;
struct ion_client *iclient;
+
+ bool clk_always_on;
};
int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index e56c70a..e9ff67c 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -30,6 +30,7 @@
#define SDE_EVTLOG_DEFAULT_PANIC 1
#define SDE_EVTLOG_DEFAULT_REGDUMP SDE_ROT_DBG_DUMP_IN_MEM
#define SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
+#define SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
/*
* evtlog will print this number of entries when it is called through
@@ -53,6 +54,8 @@
#define GROUP_BYTES 4
#define ROW_BYTES 16
+#define SDE_ROT_TEST_MASK(id, tp) ((id << 4) | (tp << 1) | BIT(0))
+
static DEFINE_SPINLOCK(sde_rot_xlock);
/*
@@ -86,11 +89,14 @@
* @panic_on_err - boolean indicates issue panic after EVTLOG dump
* @enable_reg_dump - control in-log/memory dump for rotator registers
* @enable_vbif_dbgbus_dump - control in-log/memory dump for VBIF debug bus
+ * @enable_rot_dbgbus_dump - control in-log/memroy dump for rotator debug bus
* @evtlog_dump_work - schedule work strucutre for timeout handler
* @work_dump_reg - storage for register dump control in schedule work
* @work_panic - storage for panic control in schedule work
* @work_vbif_dbgbus - storage for VBIF debug bus control in schedule work
+ * @work_rot_dbgbus - storage for rotator debug bus control in schedule work
* @nrt_vbif_dbgbus_dump - memory buffer for VBIF debug bus dumping
+ * @rot_dbgbus_dump - memory buffer for rotator debug bus dumping
* @reg_dump_array - memory buffer for rotator registers dumping
*/
struct sde_rot_dbg_evtlog {
@@ -103,14 +109,88 @@
u32 panic_on_err;
u32 enable_reg_dump;
u32 enable_vbif_dbgbus_dump;
+ u32 enable_rot_dbgbus_dump;
struct work_struct evtlog_dump_work;
bool work_dump_reg;
bool work_panic;
bool work_vbif_dbgbus;
+ bool work_rot_dbgbus;
u32 *nrt_vbif_dbgbus_dump; /* address for the nrt vbif debug bus dump */
+ u32 *rot_dbgbus_dump;
u32 *reg_dump_array[SDE_ROT_DEBUG_BASE_MAX];
} sde_rot_dbg_evtlog;
+static void sde_rot_dump_debug_bus(u32 bus_dump_flag, u32 **dump_mem)
+{
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+ bool in_log, in_mem;
+ u32 *dump_addr = NULL;
+ u32 status = 0;
+ struct sde_rot_debug_bus *head;
+ phys_addr_t phys = 0;
+ int i;
+ u32 offset;
+ void __iomem *base;
+
+ in_log = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
+ in_mem = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
+ base = mdata->sde_io.base;
+
+ if (!base || !mdata->rot_dbg_bus || !mdata->rot_dbg_bus_size)
+ return;
+
+ pr_info("======== SDE Rotator Debug bus DUMP =========\n");
+
+ if (in_mem) {
+ if (!(*dump_mem))
+ *dump_mem = dma_alloc_coherent(&mdata->pdev->dev,
+ mdata->rot_dbg_bus_size * 4 * sizeof(u32),
+ &phys, GFP_KERNEL);
+
+ if (*dump_mem) {
+ dump_addr = *dump_mem;
+ pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
+ __func__, dump_addr,
+ dump_addr + (u32)mdata->rot_dbg_bus_size * 16);
+ } else {
+ in_mem = false;
+ pr_err("dump_mem: allocation fails\n");
+ }
+ }
+
+ sde_smmu_ctrl(1);
+
+ for (i = 0; i < mdata->rot_dbg_bus_size; i++) {
+ head = mdata->rot_dbg_bus + i;
+ writel_relaxed(SDE_ROT_TEST_MASK(head->block_id, head->test_id),
+ base + head->wr_addr);
+ wmb(); /* make sure test bits were written */
+
+ offset = head->wr_addr + 0x4;
+
+ status = readl_relaxed(base + offset);
+
+ if (in_log)
+ pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
+ head->wr_addr, head->block_id, head->test_id,
+ status);
+
+ if (dump_addr && in_mem) {
+ dump_addr[i*4] = head->wr_addr;
+ dump_addr[i*4 + 1] = head->block_id;
+ dump_addr[i*4 + 2] = head->test_id;
+ dump_addr[i*4 + 3] = status;
+ }
+
+ /* Disable debug bus once we are done */
+ writel_relaxed(0, base + head->wr_addr);
+ }
+
+ sde_smmu_ctrl(0);
+
+ pr_info("========End Debug bus=========\n");
+}
+
/*
* sde_rot_evtlog_is_enabled - helper function for checking EVTLOG
* enable/disable
@@ -518,18 +598,26 @@
* @dump_vbif_debug_bus: boolean indicates VBIF debug bus dump
*/
static void sde_rot_evtlog_dump_helper(bool dead, const char *panic_name,
- bool dump_rot, bool dump_vbif_debug_bus)
+ bool dump_rot, bool dump_vbif_debug_bus, bool dump_rot_debug_bus)
{
sde_rot_evtlog_dump_all();
- if (dump_rot)
- sde_rot_dump_reg_all();
+ if (dump_rot_debug_bus)
+ sde_rot_dump_debug_bus(
+ sde_rot_dbg_evtlog.enable_rot_dbgbus_dump,
+ &sde_rot_dbg_evtlog.rot_dbgbus_dump);
if (dump_vbif_debug_bus)
sde_rot_dump_vbif_debug_bus(
sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump,
&sde_rot_dbg_evtlog.nrt_vbif_dbgbus_dump);
+ /*
+ * Rotator registers always dump last
+ */
+ if (dump_rot)
+ sde_rot_dump_reg_all();
+
if (dead)
panic(panic_name);
}
@@ -544,7 +632,8 @@
sde_rot_dbg_evtlog.work_panic,
"evtlog_workitem",
sde_rot_dbg_evtlog.work_dump_reg,
- sde_rot_dbg_evtlog.work_vbif_dbgbus);
+ sde_rot_dbg_evtlog.work_vbif_dbgbus,
+ sde_rot_dbg_evtlog.work_rot_dbgbus);
}
/*
@@ -569,6 +658,7 @@
bool dead = false;
bool dump_rot = false;
bool dump_vbif_dbgbus = false;
+ bool dump_rot_dbgbus = false;
char *blk_name = NULL;
va_list args;
@@ -590,6 +680,9 @@
if (!strcmp(blk_name, "vbif_dbg_bus"))
dump_vbif_dbgbus = true;
+ if (!strcmp(blk_name, "rot_dbg_bus"))
+ dump_rot_dbgbus = true;
+
if (!strcmp(blk_name, "panic"))
dead = true;
}
@@ -600,10 +693,11 @@
sde_rot_dbg_evtlog.work_panic = dead;
sde_rot_dbg_evtlog.work_dump_reg = dump_rot;
sde_rot_dbg_evtlog.work_vbif_dbgbus = dump_vbif_dbgbus;
+ sde_rot_dbg_evtlog.work_rot_dbgbus = dump_rot_dbgbus;
schedule_work(&sde_rot_dbg_evtlog.evtlog_dump_work);
} else {
sde_rot_evtlog_dump_helper(dead, name, dump_rot,
- dump_vbif_dbgbus);
+ dump_vbif_dbgbus, dump_rot_dbgbus);
}
}
@@ -836,6 +930,13 @@
return -EINVAL;
}
+ mdata->clk_always_on = false;
+ if (!debugfs_create_bool("clk_always_on", 0644,
+ debugfs_root, &mdata->clk_always_on)) {
+ SDEROT_WARN("failed to create debugfs clk_always_on\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -919,12 +1020,16 @@
&sde_rot_dbg_evtlog.enable_reg_dump);
debugfs_create_u32("vbif_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
&sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump);
+ debugfs_create_u32("rot_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
+ &sde_rot_dbg_evtlog.enable_rot_dbgbus_dump);
sde_rot_dbg_evtlog.evtlog_enable = SDE_EVTLOG_DEFAULT_ENABLE;
sde_rot_dbg_evtlog.panic_on_err = SDE_EVTLOG_DEFAULT_PANIC;
sde_rot_dbg_evtlog.enable_reg_dump = SDE_EVTLOG_DEFAULT_REGDUMP;
sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump =
SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP;
+ sde_rot_dbg_evtlog.enable_rot_dbgbus_dump =
+ SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP;
pr_info("evtlog_status: enable:%d, panic:%d, dump:%d\n",
sde_rot_dbg_evtlog.evtlog_enable,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index a152573..8f2746d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -385,11 +385,95 @@
};
static struct sde_rot_vbif_debug_bus nrt_vbif_dbg_bus_r3[] = {
- {0x214, 0x21c, 16, 1, 0x10}, /* arb clients */
+ {0x214, 0x21c, 16, 1, 0x200}, /* arb clients main */
{0x214, 0x21c, 0, 12, 0x13}, /* xin blocks - axi side */
{0x21c, 0x214, 0, 12, 0xc}, /* xin blocks - clock side */
};
+static struct sde_rot_debug_bus rot_dbgbus_r3[] = {
+ /*
+ * rottop - 0xA8850
+ */
+ /* REGDMA */
+ { 0XA8850, 0, 0 },
+ { 0XA8850, 0, 1 },
+ { 0XA8850, 0, 2 },
+ { 0XA8850, 0, 3 },
+ { 0XA8850, 0, 4 },
+
+ /* ROT_WB */
+ { 0XA8850, 1, 0 },
+ { 0XA8850, 1, 1 },
+ { 0XA8850, 1, 2 },
+ { 0XA8850, 1, 3 },
+ { 0XA8850, 1, 4 },
+ { 0XA8850, 1, 5 },
+ { 0XA8850, 1, 6 },
+ { 0XA8850, 1, 7 },
+
+ /* UBWC_DEC */
+ { 0XA8850, 2, 0 },
+
+ /* UBWC_ENC */
+ { 0XA8850, 3, 0 },
+
+ /* ROT_FETCH_0 */
+ { 0XA8850, 4, 0 },
+ { 0XA8850, 4, 1 },
+ { 0XA8850, 4, 2 },
+ { 0XA8850, 4, 3 },
+ { 0XA8850, 4, 4 },
+ { 0XA8850, 4, 5 },
+ { 0XA8850, 4, 6 },
+ { 0XA8850, 4, 7 },
+
+ /* ROT_FETCH_1 */
+ { 0XA8850, 5, 0 },
+ { 0XA8850, 5, 1 },
+ { 0XA8850, 5, 2 },
+ { 0XA8850, 5, 3 },
+ { 0XA8850, 5, 4 },
+ { 0XA8850, 5, 5 },
+ { 0XA8850, 5, 6 },
+ { 0XA8850, 5, 7 },
+
+ /* ROT_FETCH_2 */
+ { 0XA8850, 6, 0 },
+ { 0XA8850, 6, 1 },
+ { 0XA8850, 6, 2 },
+ { 0XA8850, 6, 3 },
+ { 0XA8850, 6, 4 },
+ { 0XA8850, 6, 5 },
+ { 0XA8850, 6, 6 },
+ { 0XA8850, 6, 7 },
+
+ /* ROT_FETCH_3 */
+ { 0XA8850, 7, 0 },
+ { 0XA8850, 7, 1 },
+ { 0XA8850, 7, 2 },
+ { 0XA8850, 7, 3 },
+ { 0XA8850, 7, 4 },
+ { 0XA8850, 7, 5 },
+ { 0XA8850, 7, 6 },
+ { 0XA8850, 7, 7 },
+
+ /* ROT_FETCH_4 */
+ { 0XA8850, 8, 0 },
+ { 0XA8850, 8, 1 },
+ { 0XA8850, 8, 2 },
+ { 0XA8850, 8, 3 },
+ { 0XA8850, 8, 4 },
+ { 0XA8850, 8, 5 },
+ { 0XA8850, 8, 6 },
+ { 0XA8850, 8, 7 },
+
+ /* ROT_UNPACK_0*/
+ { 0XA8850, 9, 0 },
+ { 0XA8850, 9, 1 },
+ { 0XA8850, 9, 2 },
+ { 0XA8850, 9, 3 },
+};
+
static struct sde_rot_regdump sde_rot_r3_regdump[] = {
{ "SDEROT_ROTTOP", SDE_ROT_ROTTOP_OFFSET, 0x100, SDE_ROT_REGDUMP_READ },
{ "SDEROT_SSPP", SDE_ROT_SSPP_OFFSET, 0x200, SDE_ROT_REGDUMP_READ },
@@ -1430,7 +1514,8 @@
sts = (status & ROT_ERROR_BIT) ? -ENODEV : 0;
if (status & ROT_ERROR_BIT)
- SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus", "panic");
+ SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
+ "vbif_dbg_bus", "panic");
return sts;
}
@@ -1614,8 +1699,8 @@
SDEROT_ERR(
"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
swts, hwts, regdmasts, rotsts);
- SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus",
- "panic");
+ SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
+ "vbif_dbg_bus", "panic");
}
/* Turn off rotator clock after checking rotator registers */
@@ -2134,6 +2219,17 @@
SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN,
BIT(XIN_WRITEBACK));
+ /*
+ * For debug purpose, disable clock gating, i.e. Clocks always on
+ */
+ if (mdata->clk_always_on) {
+ SDE_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 0x3);
+ SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0, 0x3);
+ SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL1,
+ 0xFFFF);
+ SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_CLK_CTRL, 1);
+ }
+
return 0;
error:
@@ -2260,6 +2356,9 @@
mdata->nrt_vbif_dbg_bus_size =
ARRAY_SIZE(nrt_vbif_dbg_bus_r3);
+ mdata->rot_dbg_bus = rot_dbgbus_r3;
+ mdata->rot_dbg_bus_size = ARRAY_SIZE(rot_dbgbus_r3);
+
mdata->regdump = sde_rot_r3_regdump;
mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 709f1d8..ac6ded0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1115,6 +1115,14 @@
pkt->size += sizeof(u32) * 2;
break;
}
+ case HAL_PARAM_SECURE:
+ {
+ create_pkt_enable(pkt->rg_property_data,
+ HFI_PROPERTY_PARAM_SECURE_SESSION,
+ ((struct hal_enable *)pdata)->enable);
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
{
create_pkt_enable(pkt->rg_property_data,
@@ -1799,6 +1807,34 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
break;
}
+ case HAL_PARAM_VIDEO_CORES_USAGE:
+ {
+ struct hal_videocores_usage_info *hal = pdata;
+ struct hfi_videocores_usage_type *core_info =
+ (struct hfi_videocores_usage_type *)
+ &pkt->rg_property_data[1];
+
+ core_info->video_core_enable_mask = hal->video_core_enable_mask;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
+ pkt->size += sizeof(u32) + sizeof(*core_info);
+ break;
+ }
+ case HAL_PARAM_VIDEO_WORK_MODE:
+ {
+ struct hal_video_work_mode *hal = pdata;
+ struct hfi_video_work_mode *work_mode =
+ (struct hfi_video_work_mode *)
+ &pkt->rg_property_data[1];
+
+ work_mode->video_work_mode = hal->video_work_mode;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_WORK_MODE;
+ pkt->size += sizeof(u32) + sizeof(*work_mode);
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 3378ff0..b424fbb 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -300,8 +300,8 @@
cmd_done.device_id = device_id;
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
cmd_done.status = hfi_map_err_status(pkt->event_data1);
- dprintk(VIDC_INFO, "Received: SESSION_ERROR with event id : %d\n",
- pkt->event_data1);
+ dprintk(VIDC_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
+ pkt->event_data1, pkt->event_data2);
switch (pkt->event_data1) {
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
@@ -313,7 +313,9 @@
info->response.cmd = cmd_done;
return 0;
default:
- dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR\n");
+ dprintk(VIDC_ERR,
+ "HFI_EVENT_SESSION_ERROR: data1 %#x, data2 %#x\n",
+ pkt->event_data1, pkt->event_data2);
info->response_type = HAL_SESSION_ERROR;
info->response.cmd = cmd_done;
return 0;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index b211175..3d3b7e9 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -564,6 +564,8 @@
inst->bufq[CAPTURE_PORT].plane_sizes[i] =
f->fmt.pix_mp.plane_fmt[i].sizeimage;
}
+
+ rc = msm_comm_try_get_bufreqs(inst);
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
@@ -776,7 +778,10 @@
msm_dcvs_try_enable(inst);
break;
case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
+ property_id = HAL_PARAM_SECURE;
inst->flags |= VIDC_SECURE;
+ property_val = !!(inst->flags & VIDC_SECURE);
+ pdata = &property_val;
dprintk(VIDC_DBG, "Setting secure mode to: %d\n",
!!(inst->flags & VIDC_SECURE));
break;
@@ -890,6 +895,7 @@
"Failed setting OUTPUT2 size : %d\n",
rc);
+ rc = msm_comm_try_get_bufreqs(inst);
break;
default:
dprintk(VIDC_ERR,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index dccfe74..e198d8e 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -808,7 +808,7 @@
.name = "Layer ID for different settings",
.type = V4L2_CTRL_TYPE_INTEGER,
.minimum = 0,
- .maximum = 6,
+ .maximum = MSM_VIDC_ALL_LAYER_ID,
.default_value = 0,
.step = 1,
.qmenu = NULL,
@@ -1095,49 +1095,6 @@
return rc;
}
-static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst)
-{
- u32 rc = 0;
- u32 prop_id = 0, power_save_min = 0, power_save_max = 0, inst_load = 0;
- void *pdata = NULL;
- struct hfi_device *hdev = NULL;
- enum hal_perf_mode venc_mode;
- enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD |
- LOAD_CALC_IGNORE_THUMBNAIL_LOAD;
-
- if (!inst || !inst->core || !inst->core->device) {
- dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
- return -EINVAL;
- }
-
- inst_load = msm_comm_get_inst_load(inst, quirks);
- power_save_min = inst->capability.mbs_per_sec_power_save.min;
- power_save_max = inst->capability.mbs_per_sec_power_save.max;
-
- if (!power_save_min || !power_save_max)
- return rc;
-
- hdev = inst->core->device;
- if (inst_load >= power_save_min && inst_load <= power_save_max) {
- prop_id = HAL_CONFIG_VENC_PERF_MODE;
- venc_mode = HAL_PERF_MODE_POWER_SAVE;
- pdata = &venc_mode;
- rc = call_hfi_op(hdev, session_set_property,
- (void *)inst->session, prop_id, pdata);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed to set power save mode for inst: %pK\n",
- __func__, inst);
- goto fail_power_mode_set;
- }
- inst->flags |= VIDC_LOW_POWER;
- dprintk(VIDC_INFO, "Power Save Mode set for inst: %pK\n", inst);
- }
-
-fail_power_mode_set:
- return rc;
-}
-
static struct v4l2_ctrl *get_ctrl_from_cluster(int id,
struct v4l2_ctrl **cluster, int ncontrols)
{
@@ -1265,7 +1222,7 @@
{
property_id = HAL_CONFIG_VENC_TARGET_BITRATE;
bitrate.bit_rate = ctrl->val;
- bitrate.layer_id = MSM_VIDC_ALL_LAYER_ID;
+ bitrate.layer_id = 0;
pdata = &bitrate;
inst->bitrate = ctrl->val;
break;
@@ -1544,6 +1501,9 @@
break;
case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
inst->flags |= VIDC_SECURE;
+ property_id = HAL_PARAM_SECURE;
+ property_val = !!(inst->flags & VIDC_SECURE);
+ pdata = &property_val;
dprintk(VIDC_INFO, "Setting secure mode to: %d\n",
!!(inst->flags & VIDC_SECURE));
break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index d3af24e..e071037 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1018,12 +1018,6 @@
b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
b->m.planes[i].reserved[0] = buffer_info->fd[i];
b->m.planes[i].reserved[1] = buffer_info->buff_off[i];
- if (!b->m.planes[i].m.userptr) {
- dprintk(VIDC_ERR,
- "%s: Failed to find user virtual address, %#lx, %d, %d\n",
- __func__, b->m.planes[i].m.userptr, b->type, i);
- return -EINVAL;
- }
}
if (!buffer_info) {
@@ -1296,14 +1290,6 @@
return rc;
}
-static inline int msm_vidc_decide_core_and_power_mode(
- struct msm_vidc_inst *inst)
-{
- dprintk(VIDC_DBG,
- "Core selection is not yet implemented for inst = %pK\n",
- inst);
- return 0;
-}
static inline int msm_vidc_verify_buffer_counts(struct msm_vidc_inst *inst)
{
int rc = 0, i = 0;
@@ -1364,15 +1350,22 @@
goto fail_start;
}
+ /* Decide work mode for current session */
+ rc = msm_vidc_decide_work_mode(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to decide work mode for session %pK\n", inst);
+ goto fail_start;
+ }
+
/* Assign Core and LP mode for current session */
rc = msm_vidc_decide_core_and_power_mode(inst);
if (rc) {
dprintk(VIDC_ERR,
- "This session can't be submitted to HW%pK\n", inst);
+ "This session can't be submitted to HW %pK\n", inst);
goto fail_start;
}
-
if (msm_comm_get_stream_output_mode(inst) ==
HAL_VIDEO_DECODER_SECONDARY) {
b.buffer_type = HAL_BUFFER_OUTPUT2;
@@ -1387,7 +1380,7 @@
rc = msm_comm_try_get_bufreqs(inst);
- /* Check if current session is under HW capability */
+ /* Verify if buffer counts are correct */
rc = msm_vidc_verify_buffer_counts(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -1428,18 +1421,9 @@
* - v4l2 client issues CONTINUE to firmware to resume decoding of
* submitted ETBs.
*/
- if (inst->in_reconfig) {
- dprintk(VIDC_DBG, "send session_continue after reconfig\n");
- rc = call_hfi_op(hdev, session_continue,
- (void *) inst->session);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s - failed to send session_continue\n",
- __func__);
- goto fail_start;
- }
- }
- inst->in_reconfig = false;
+ rc = msm_comm_session_continue(inst);
+ if (rc)
+ goto fail_start;
msm_comm_scale_clocks_and_bus(inst);
@@ -1475,7 +1459,6 @@
return rc;
}
-
static int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct msm_vidc_inst *inst;
@@ -1989,6 +1972,7 @@
inst->state = MSM_VIDC_CORE_UNINIT_DONE;
inst->core = core;
inst->freq = 0;
+ inst->core_id = VIDC_CORE_ID_DEFAULT;
inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
inst->bitrate = 0;
inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 1c78a45..d43ae5a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -589,4 +589,288 @@
inst->dcvs.extra_capture_buffer_count;
}
+int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst)
+{
+ int rc = 0;
+ bool low_latency_mode;
+ struct hfi_device *hdev;
+ struct hal_video_work_mode pdata;
+ struct hal_enable latency;
+
+ hdev = inst->core->device;
+
+ low_latency_mode = msm_comm_g_ctrl_for_id(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_LOWLATENCY_MODE);
+ if (low_latency_mode) {
+ pdata.video_work_mode = VIDC_WORK_MODE_1;
+ goto decision_done;
+ }
+
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ pdata.video_work_mode = VIDC_WORK_MODE_2;
+ switch (inst->fmts[OUTPUT_PORT].fourcc) {
+ case V4L2_PIX_FMT_MPEG2:
+ pdata.video_work_mode = VIDC_WORK_MODE_1;
+ break;
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_HEVC:
+ if (inst->prop.height[OUTPUT_PORT] *
+ inst->prop.width[OUTPUT_PORT] <=
+ 1280 * 720)
+ pdata.video_work_mode = VIDC_WORK_MODE_1;
+ break;
+ }
+ } else if (inst->session_type == MSM_VIDC_ENCODER) {
+ u32 rc_mode = 0;
+
+ pdata.video_work_mode = VIDC_WORK_MODE_1;
+ rc_mode = msm_comm_g_ctrl_for_id(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
+ if (rc_mode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR ||
+ rc_mode ==
+ V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR)
+ pdata.video_work_mode = VIDC_WORK_MODE_2;
+ } else {
+ return -EINVAL;
+ }
+
+decision_done:
+
+ inst->work_mode = pdata.video_work_mode;
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session, HAL_PARAM_VIDEO_WORK_MODE,
+ (void *)&pdata);
+ if (rc)
+ dprintk(VIDC_WARN,
+ " Failed to configure Work Mode %pK\n", inst);
+
+ /* For WORK_MODE_1, set Low Latency mode by default to HW. */
+
+ if (inst->work_mode == VIDC_WORK_MODE_1) {
+ latency.enable = 1;
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session, HAL_PARAM_VENC_LOW_LATENCY,
+ (void *)&latency);
+ }
+
+ rc = msm_comm_scale_clocks_and_bus(inst);
+
+ return rc;
+}
+
+static inline int msm_vidc_power_save_mode_enable(struct msm_vidc_inst *inst,
+ bool enable)
+{
+ u32 rc = 0, mbs_per_frame;
+ u32 prop_id = 0;
+ void *pdata = NULL;
+ struct hfi_device *hdev = NULL;
+ enum hal_perf_mode venc_mode;
+
+ hdev = inst->core->device;
+ if (inst->session_type != MSM_VIDC_ENCODER) {
+ dprintk(VIDC_DBG,
+ "%s : Not an encoder session. Nothing to do\n",
+ __func__);
+ return 0;
+ }
+ mbs_per_frame = msm_dcvs_get_mbs_per_frame(inst);
+ if (inst->core->resources.max_hq_mbs_per_frame > mbs_per_frame ||
+ inst->core->resources.max_hq_fps > inst->prop.fps) {
+ enable = true;
+ }
+
+ prop_id = HAL_CONFIG_VENC_PERF_MODE;
+ venc_mode = enable ? HAL_PERF_MODE_POWER_SAVE :
+ HAL_PERF_MODE_POWER_MAX_QUALITY;
+ pdata = &venc_mode;
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session, prop_id, pdata);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: Failed to set power save mode for inst: %pK\n",
+ __func__, inst);
+ goto fail_power_mode_set;
+ }
+ inst->flags |= VIDC_LOW_POWER;
+ dprintk(VIDC_PROF, "Power Save Mode set for inst: %pK\n", inst);
+
+fail_power_mode_set:
+ return rc;
+}
+
+static int msm_vidc_move_core_to_power_save_mode(struct msm_vidc_core *core,
+ u32 core_id)
+{
+ struct msm_vidc_inst *inst = NULL;
+
+ if (!core) {
+ dprintk(VIDC_ERR, "Invalid args: %pK\n", core);
+ return -EINVAL;
+ }
+
+ dprintk(VIDC_PROF, "Core %d : Moving all inst to LP mode\n", core_id);
+ mutex_lock(&core->lock);
+ list_for_each_entry(inst, &core->instances, list) {
+ if (inst->core_id == core_id &&
+ inst->session_type == MSM_VIDC_ENCODER)
+ msm_vidc_power_save_mode_enable(inst, true);
+ }
+ mutex_unlock(&core->lock);
+
+ return 0;
+}
+
+static u32 get_core_load(struct msm_vidc_core *core,
+ u32 core_id, bool lp_mode)
+{
+ struct msm_vidc_inst *inst = NULL;
+ u32 current_inst_mbs_per_sec = 0, load = 0;
+
+ mutex_lock(&core->lock);
+ list_for_each_entry(inst, &core->instances, list) {
+ u32 cycles, lp_cycles;
+
+ if (!inst->core_id && core_id)
+ continue;
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ cycles = lp_cycles = inst->entry->vpp_cycles;
+ } else if (inst->session_type == MSM_VIDC_ENCODER) {
+ lp_mode |= inst->flags & VIDC_LOW_POWER;
+ cycles = lp_mode ?
+ inst->entry->low_power_cycles :
+ inst->entry->vpp_cycles;
+ } else {
+ continue;
+ }
+ if (inst->core_id == 3)
+ cycles = cycles / 2;
+
+ current_inst_mbs_per_sec = msm_comm_get_inst_load(inst,
+ LOAD_CALC_NO_QUIRKS);
+ load += current_inst_mbs_per_sec * cycles;
+ }
+ mutex_unlock(&core->lock);
+
+ return load;
+}
+
+int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst)
+{
+ int rc = 0, hier_mode = 0;
+ struct hfi_device *hdev;
+ struct msm_vidc_core *core;
+ unsigned long max_freq, lp_cycles = 0;
+ struct hal_videocores_usage_info core_info;
+ u32 core0_load = 0, core1_load = 0, core0_lp_load = 0,
+ core1_lp_load = 0;
+ u32 current_inst_load = 0, current_inst_lp_load = 0,
+ min_load = 0, min_lp_load = 0;
+ u32 min_core_id, min_lp_core_id;
+
+ core = inst->core;
+ hdev = core->device;
+ max_freq = msm_vidc_max_freq(inst);
+ inst->core_id = 0;
+
+ core0_load = get_core_load(core, VIDC_CORE_ID_1, false);
+ core1_load = get_core_load(core, VIDC_CORE_ID_2, false);
+ core0_lp_load = get_core_load(core, VIDC_CORE_ID_1, true);
+ core1_lp_load = get_core_load(core, VIDC_CORE_ID_2, true);
+
+ min_load = min(core0_load, core1_load);
+ min_core_id = core0_load < core1_load ?
+ VIDC_CORE_ID_1 : VIDC_CORE_ID_2;
+ min_lp_load = min(core0_lp_load, core1_lp_load);
+ min_lp_core_id = core0_lp_load < core1_lp_load ?
+ VIDC_CORE_ID_1 : VIDC_CORE_ID_2;
+
+ lp_cycles = inst->session_type == MSM_VIDC_ENCODER ?
+ inst->entry->low_power_cycles :
+ inst->entry->vpp_cycles;
+
+ current_inst_load = msm_comm_get_inst_load(inst, LOAD_CALC_NO_QUIRKS) *
+ inst->entry->vpp_cycles;
+
+ current_inst_lp_load = msm_comm_get_inst_load(inst,
+ LOAD_CALC_NO_QUIRKS) * lp_cycles;
+
+ dprintk(VIDC_DBG, "Core 0 Load = %d Core 1 Load = %d\n",
+ core0_load, core1_load);
+ dprintk(VIDC_DBG, "Core 0 LP Load = %d Core 1 LP Load = %d\n",
+ core0_lp_load, core1_lp_load);
+ dprintk(VIDC_DBG, "Max Load = %lu\n", max_freq);
+ dprintk(VIDC_DBG, "Current Load = %d Current LP Load = %d\n",
+ current_inst_load, current_inst_lp_load);
+
+ /* Hier mode can be normal HP or Hybrid HP. */
+
+ hier_mode = msm_comm_g_ctrl_for_id(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS);
+ hier_mode |= msm_comm_g_ctrl_for_id(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE);
+
+ /* Try for preferred core based on settings. */
+ if (inst->session_type == MSM_VIDC_ENCODER && hier_mode) {
+ if (current_inst_load / 2 + core0_load <= max_freq &&
+ current_inst_load / 2 + core1_load <= max_freq) {
+ inst->core_id = VIDC_CORE_ID_3;
+ msm_vidc_power_save_mode_enable(inst, false);
+ goto decision_done;
+ }
+ }
+
+ if (inst->session_type == MSM_VIDC_ENCODER && hier_mode) {
+ if (current_inst_lp_load / 2 +
+ core0_lp_load <= max_freq &&
+ current_inst_lp_load / 2 +
+ core1_lp_load <= max_freq) {
+ inst->core_id = VIDC_CORE_ID_3;
+ msm_vidc_power_save_mode_enable(inst, true);
+ goto decision_done;
+ }
+ }
+
+ if (current_inst_load + min_load < max_freq) {
+ inst->core_id = min_core_id;
+ dprintk(VIDC_DBG,
+ "Selected normally : Core ID = %d\n",
+ inst->core_id);
+ msm_vidc_power_save_mode_enable(inst, false);
+ } else if (current_inst_lp_load + min_load < max_freq) {
+ /* Move current instance to LP and return */
+ inst->core_id = min_core_id;
+ dprintk(VIDC_DBG,
+ "Selected by moving current to LP : Core ID = %d\n",
+ inst->core_id);
+ msm_vidc_power_save_mode_enable(inst, true);
+
+ } else if (current_inst_lp_load + min_lp_load < max_freq) {
+ /* Move all instances to LP mode and return */
+ inst->core_id = min_lp_core_id;
+ dprintk(VIDC_DBG,
+ "Moved all inst's to LP: Core ID = %d\n",
+ inst->core_id);
+ msm_vidc_move_core_to_power_save_mode(core, min_lp_core_id);
+ } else {
+ rc = -EINVAL;
+ dprintk(VIDC_ERR,
+ "Sorry ... Core Can't support this load\n");
+ return rc;
+ }
+
+decision_done:
+ core_info.video_core_enable_mask = inst->core_id;
+
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session,
+ HAL_PARAM_VIDEO_CORES_USAGE, &core_info);
+ if (rc)
+ dprintk(VIDC_WARN,
+ " Failed to configure CORE ID %pK\n", inst);
+
+ rc = msm_comm_scale_clocks_and_bus(inst);
+
+ return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
index 79fd8f6..d01f074 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.h
@@ -38,6 +38,8 @@
int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst);
void msm_comm_free_freq_table(struct msm_vidc_inst *inst);
+int msm_vidc_decide_work_mode(struct msm_vidc_inst *inst);
+int msm_vidc_decide_core_and_power_mode(struct msm_vidc_inst *inst);
void msm_vidc_clear_freq_entry(struct msm_vidc_inst *inst,
ion_phys_addr_t device_addr);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 8f77ebb..853edf5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1167,53 +1167,70 @@
static void msm_vidc_comm_update_ctrl_limits(struct msm_vidc_inst *inst)
{
- msm_vidc_comm_update_ctrl(inst,
- V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
- &inst->capability.hier_p_hybrid);
- msm_vidc_comm_update_ctrl(inst,
- V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
- &inst->capability.hier_b);
- msm_vidc_comm_update_ctrl(inst,
- V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
- &inst->capability.hier_p);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE,
- &inst->capability.bitrate);
- msm_vidc_comm_update_ctrl(inst,
- V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE,
- &inst->capability.bitrate);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- &inst->capability.peakbitrate);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
- &inst->capability.i_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
- &inst->capability.p_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
- &inst->capability.b_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN,
- &inst->capability.i_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN,
- &inst->capability.p_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN,
- &inst->capability.b_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX,
- &inst->capability.i_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX,
- &inst->capability.p_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX,
- &inst->capability.b_qp);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH,
- &inst->capability.blur_width);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT,
- &inst->capability.blur_height);
- msm_vidc_comm_update_ctrl(inst,
- V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
- &inst->capability.slice_bytes);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
- &inst->capability.slice_mbs);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
- &inst->capability.ltr_count);
- msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
- &inst->capability.bframe);
+ if (inst->session_type == MSM_VIDC_ENCODER) {
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE,
+ &inst->capability.hier_p_hybrid);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS,
+ &inst->capability.hier_b);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
+ &inst->capability.hier_p);
+ msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE,
+ &inst->capability.bitrate);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE,
+ &inst->capability.bitrate);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+ &inst->capability.peakbitrate);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP,
+ &inst->capability.i_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP,
+ &inst->capability.p_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP,
+ &inst->capability.b_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN,
+ &inst->capability.i_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN,
+ &inst->capability.p_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN,
+ &inst->capability.b_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX,
+ &inst->capability.i_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX,
+ &inst->capability.p_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX,
+ &inst->capability.b_qp);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH,
+ &inst->capability.blur_width);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT,
+ &inst->capability.blur_height);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
+ &inst->capability.slice_bytes);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+ &inst->capability.slice_mbs);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
+ &inst->capability.ltr_count);
+ msm_vidc_comm_update_ctrl(inst,
+ V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES,
+ &inst->capability.bframe);
+ }
}
static void handle_session_init_done(enum hal_command_response cmd, void *data)
@@ -1361,7 +1378,7 @@
switch (event_notify->hal_event_type) {
case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
- event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+ event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
break;
case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
@@ -1434,18 +1451,17 @@
}
/* Bit depth and pic struct changed event are combined into a single
- * event (insufficient event) for the userspace. Currently bitdepth
- * changes is only for HEVC and interlaced support is for all
- * codecs except HEVC
- * event data is now as follows:
- * u32 *ptr = seq_changed_event.u.data;
- * ptr[0] = height
- * ptr[1] = width
- * ptr[2] = flag to indicate bit depth or/and pic struct changed
- * ptr[3] = bit depth
- * ptr[4] = pic struct (progressive or interlaced)
- * ptr[5] = colour space
- */
+ * event (insufficient event) for the userspace. Currently bitdepth
+ * changes is only for HEVC and interlaced support is for all
+ * codecs except HEVC
+ * event data is now as follows:
+ * u32 *ptr = seq_changed_event.u.data;
+ * ptr[0] = height
+ * ptr[1] = width
+ * ptr[2] = bit depth
+ * ptr[3] = pic struct (progressive or interlaced)
+ * ptr[4] = colour space
+ */
inst->entropy_mode = msm_comm_hal_to_v4l2(
V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
@@ -1458,55 +1474,35 @@
event_notify->level);
ptr = (u32 *)seq_changed_event.u.data;
+ ptr[0] = event_notify->height;
+ ptr[1] = event_notify->width;
+ ptr[2] = event_notify->bit_depth;
+ ptr[3] = event_notify->pic_struct;
+ ptr[4] = event_notify->colour_space;
- if (ptr != NULL) {
- ptr[2] = 0x0;
- ptr[3] = inst->bit_depth;
- ptr[4] = inst->pic_struct;
- ptr[5] = inst->colour_space;
+ dprintk(VIDC_DBG,
+ "Event payload: height = %d width = %d\n",
+ event_notify->height, event_notify->width);
- if (inst->bit_depth != event_notify->bit_depth) {
- inst->bit_depth = event_notify->bit_depth;
- ptr[2] |= V4L2_EVENT_BITDEPTH_FLAG;
- ptr[3] = inst->bit_depth;
- event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
- dprintk(VIDC_DBG,
- "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to bit-depth change\n");
- }
+ dprintk(VIDC_DBG,
+ "Event payload: bit_depth = %d pic_struct = %d colour_space = %d\n",
+ event_notify->bit_depth, event_notify->pic_struct,
+ event_notify->colour_space);
- if (inst->pic_struct != event_notify->pic_struct) {
- inst->pic_struct = event_notify->pic_struct;
- event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
- ptr[2] |= V4L2_EVENT_PICSTRUCT_FLAG;
- ptr[4] = inst->pic_struct;
- dprintk(VIDC_DBG,
- "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to pic-struct change\n");
- }
-
- if (inst->bit_depth == MSM_VIDC_BIT_DEPTH_10
- && inst->colour_space !=
- event_notify->colour_space) {
- inst->colour_space = event_notify->colour_space;
- event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
- ptr[2] |= V4L2_EVENT_COLOUR_SPACE_FLAG;
- ptr[5] = inst->colour_space;
- dprintk(VIDC_DBG,
- "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to colour space change\n");
- }
-
- }
+ mutex_lock(&inst->lock);
+ inst->in_reconfig = true;
+ inst->reconfig_height = event_notify->height;
+ inst->reconfig_width = event_notify->width;
+ mutex_unlock(&inst->lock);
if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
- inst->reconfig_height = event_notify->height;
- inst->reconfig_width = event_notify->width;
- inst->in_reconfig = true;
} else {
dprintk(VIDC_DBG, "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
dprintk(VIDC_DBG,
- "event_notify->height = %d event_notify->width = %d\n",
- event_notify->height,
- event_notify->width);
+ "event_notify->height = %d event_notify->width = %d\n",
+ event_notify->height,
+ event_notify->width);
inst->prop.height[OUTPUT_PORT] = event_notify->height;
inst->prop.width[OUTPUT_PORT] = event_notify->width;
}
@@ -1514,13 +1510,6 @@
rc = msm_vidc_check_session_supported(inst);
if (!rc) {
seq_changed_event.type = event;
- if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
- u32 *ptr = NULL;
-
- ptr = (u32 *)seq_changed_event.u.data;
- ptr[0] = event_notify->height;
- ptr[1] = event_notify->width;
- }
v4l2_event_queue_fh(&inst->event_handler, &seq_changed_event);
} else if (rc == -ENOTSUPP) {
msm_vidc_queue_v4l2_event(inst,
@@ -3651,6 +3640,11 @@
}
break;
}
+ case V4L2_QCOM_CMD_SESSION_CONTINUE:
+ {
+ rc = msm_comm_session_continue(inst);
+ break;
+ }
default:
dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd);
rc = -ENOTSUPP;
@@ -3996,7 +3990,7 @@
static int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst)
{
- int extra_buffers, buffer_type;
+ int extra_buffers;
struct hal_buffer_requirements *bufreq;
bufreq = get_buff_req_buffer(inst,
@@ -4004,7 +3998,7 @@
if (!bufreq) {
dprintk(VIDC_ERR,
"Failed : No buffer requirements : %x\n",
- HAL_BUFFER_INPUT);
+ HAL_BUFFER_INPUT);
return -EINVAL;
}
extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT);
@@ -4012,21 +4006,55 @@
bufreq->buffer_count_min_host = bufreq->buffer_count_min +
extra_buffers;
- buffer_type = msm_comm_get_hal_output_buffer(inst);
- bufreq = get_buff_req_buffer(inst,
- buffer_type);
- if (!bufreq) {
- dprintk(VIDC_ERR,
- "Failed : No buffer requirements : %x\n",
- buffer_type);
- return -EINVAL;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+
+ bufreq = get_buff_req_buffer(inst,
+ HAL_BUFFER_OUTPUT);
+ if (!bufreq) {
+ dprintk(VIDC_ERR,
+ "Failed : No buffer requirements : %x\n",
+ HAL_BUFFER_OUTPUT);
+ return -EINVAL;
+ }
+
+ /* For DPB buffers, no need to add Extra buffers */
+
+ bufreq->buffer_count_actual = bufreq->buffer_count_min_host =
+ bufreq->buffer_count_min;
+
+ bufreq = get_buff_req_buffer(inst,
+ HAL_BUFFER_OUTPUT2);
+ if (!bufreq) {
+ dprintk(VIDC_ERR,
+ "Failed : No buffer requirements : %x\n",
+ HAL_BUFFER_OUTPUT2);
+ return -EINVAL;
+ }
+
+ extra_buffers = msm_vidc_get_extra_buff_count(inst,
+ HAL_BUFFER_OUTPUT);
+
+ bufreq->buffer_count_min_host =
+ bufreq->buffer_count_min + extra_buffers;
+ } else {
+
+ bufreq = get_buff_req_buffer(inst,
+ HAL_BUFFER_OUTPUT);
+ if (!bufreq) {
+ dprintk(VIDC_ERR,
+ "Failed : No buffer requirements : %x\n",
+ HAL_BUFFER_OUTPUT);
+ return -EINVAL;
+ }
+
+ extra_buffers = msm_vidc_get_extra_buff_count(inst,
+ HAL_BUFFER_OUTPUT);
+
+ bufreq->buffer_count_actual = bufreq->buffer_count_min_host =
+ bufreq->buffer_count_min + extra_buffers;
}
- extra_buffers = msm_vidc_get_extra_buff_count(inst, buffer_type);
-
- bufreq->buffer_count_min_host = bufreq->buffer_count_min +
- extra_buffers;
-
return 0;
}
@@ -5351,21 +5379,18 @@
goto exit;
}
- if (inst->prop.fps != fps) {
- dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n",
- inst, inst->prop.fps, fps);
- inst->prop.fps = fps;
+ dprintk(VIDC_PROF, "reported fps changed for %pK: %d->%d\n",
+ inst, inst->prop.fps, fps);
+ inst->prop.fps = fps;
+ if (inst->session_type == MSM_VIDC_ENCODER) {
frame_rate.frame_rate = inst->prop.fps * BIT(16);
frame_rate.buffer_type = HAL_BUFFER_OUTPUT;
pdata = &frame_rate;
- if (inst->session_type == MSM_VIDC_ENCODER) {
- rc = call_hfi_op(hdev, session_set_property,
- inst->session, property_id, pdata);
-
- if (rc)
- dprintk(VIDC_WARN,
- "Failed to set frame rate %d\n", rc);
- }
+ rc = call_hfi_op(hdev, session_set_property,
+ inst->session, property_id, pdata);
+ if (rc)
+ dprintk(VIDC_WARN,
+ "Failed to set frame rate %d\n", rc);
}
exit:
return rc;
@@ -5462,3 +5487,36 @@
}
mutex_unlock(&core->lock);
}
+
+int msm_comm_session_continue(void *instance)
+{
+ struct msm_vidc_inst *inst = instance;
+ int rc = 0;
+ struct hfi_device *hdev;
+
+ if (!inst || !inst->core || !inst->core->device)
+ return -EINVAL;
+ hdev = inst->core->device;
+ mutex_lock(&inst->lock);
+ if (inst->session_type == MSM_VIDC_DECODER && inst->in_reconfig) {
+ dprintk(VIDC_DBG, "send session_continue\n");
+ rc = call_hfi_op(hdev, session_continue,
+ (void *)inst->session);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "failed to send session_continue\n");
+ rc = -EINVAL;
+ goto sess_continue_fail;
+ }
+ inst->in_reconfig = false;
+ } else if (inst->session_type == MSM_VIDC_ENCODER) {
+ dprintk(VIDC_DBG,
+ "session_continue not supported for encoder");
+ } else {
+ dprintk(VIDC_ERR,
+ "session_continue called in wrong state for decoder");
+ }
+sess_continue_fail:
+ mutex_unlock(&inst->lock);
+ return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 39a28b3..9c7eec5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -97,4 +97,5 @@
void msm_comm_print_inst_info(struct msm_vidc_inst *inst);
int msm_comm_v4l2_to_hal(int id, int value);
int msm_comm_hal_to_v4l2(int id, int value);
+int msm_comm_session_continue(void *instance);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 4b91193..53bc068 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -313,6 +313,8 @@
u32 level;
u32 entropy_mode;
struct clock_profile_entry *entry;
+ u32 core_id;
+ enum hal_work_mode work_mode;
};
extern struct msm_vidc_drv *vidc_driver;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 763c41d..0a6de41 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -940,6 +940,24 @@
goto err_load_max_hw_load;
}
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,max-hq-mbs-per-frame",
+ &res->max_hq_mbs_per_frame);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to determine Max HQ mbs per frame: %d\n", rc);
+ goto err_load_HQ_values;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,max-hq-frames-per-sec",
+ &res->max_hq_fps);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to determine Max HQ fps: %d\n", rc);
+ goto err_load_HQ_values;
+ }
+
rc = msm_vidc_populate_legacy_context_bank(res);
if (rc) {
dprintk(VIDC_ERR,
@@ -985,6 +1003,7 @@
return rc;
err_setup_legacy_cb:
+err_load_HQ_values:
err_load_max_hw_load:
msm_vidc_free_allowed_clocks_table(res);
err_load_allowed_clocks_table:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 8fd43006..20b0ffc 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -165,6 +165,8 @@
uint32_t imem_size;
enum imem_type imem_type;
uint32_t max_load;
+ uint32_t max_hq_mbs_per_frame;
+ uint32_t max_hq_fps;
struct platform_device *pdev;
struct regulator_set regulator_set;
struct clock_set clock_set;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index b56fd14..1a1078d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1394,12 +1394,6 @@
__strict_check(device);
- if (!__core_in_valid_state(device)) {
- dprintk(VIDC_DBG, "%s - fw not in init state\n", __func__);
- rc = -EINVAL;
- goto dbg_error_null;
- }
-
if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
q_array.align_virtual_addr == 0) {
dprintk(VIDC_ERR, "cannot read from shared DBG Q's\n");
@@ -1971,6 +1965,8 @@
if (device->res->pm_qos_latency_us &&
pm_qos_request_active(&device->qos))
pm_qos_remove_request(&device->qos);
+
+ __resume(device);
__set_state(device, VENUS_STATE_DEINIT);
__unload_fw(device);
@@ -3386,6 +3382,7 @@
static inline void __disable_unprepare_clks(struct venus_hfi_device *device)
{
struct clock_info *cl;
+ int rc = 0;
if (!device) {
dprintk(VIDC_ERR, "Invalid params: %pK\n", device);
@@ -3395,6 +3392,18 @@
venus_hfi_for_each_clock_reverse(device, cl) {
dprintk(VIDC_DBG, "Clock: %s disable and unprepare\n",
cl->name);
+ rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed set flag NORETAIN_PERIPH %s\n",
+ cl->name);
+ }
+ rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_MEM);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed set flag NORETAIN_MEM %s\n",
+ cl->name);
+ }
clk_disable_unprepare(cl->clk);
}
}
@@ -3418,22 +3427,18 @@
if (cl->has_scaling)
clk_set_rate(cl->clk, clk_round_rate(cl->clk, 0));
- if (cl->has_mem_retention) {
- rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);
- if (rc) {
- dprintk(VIDC_WARN,
- "Failed set flag NORETAIN_PERIPH %s\n",
+ rc = clk_set_flags(cl->clk, CLKFLAG_RETAIN_PERIPH);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed set flag RETAIN_PERIPH %s\n",
cl->name);
- }
-
- rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_MEM);
- if (rc) {
- dprintk(VIDC_WARN,
- "Failed set flag NORETAIN_MEM %s\n",
- cl->name);
- }
}
-
+ rc = clk_set_flags(cl->clk, CLKFLAG_RETAIN_MEM);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed set flag RETAIN_MEM %s\n",
+ cl->name);
+ }
rc = clk_prepare_enable(cl->clk);
if (rc) {
dprintk(VIDC_ERR, "Failed to enable clocks\n");
@@ -4051,6 +4056,8 @@
__venus_power_off(device);
device->resources.fw.cookie = NULL;
__deinit_resources(device);
+
+ dprintk(VIDC_PROF, "Firmware unloaded successfully\n");
}
static int venus_hfi_get_fw_info(void *dev, struct hal_fw_info *fw_info)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 28bb7ab..f8e0a6a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -221,6 +221,9 @@
HAL_PARAM_VENC_H264_TRANSFORM_8x8,
HAL_PARAM_VENC_VIDEO_SIGNAL_INFO,
HAL_PARAM_VENC_IFRAMESIZE_TYPE,
+ HAL_PARAM_VIDEO_CORES_USAGE,
+ HAL_PARAM_VIDEO_WORK_MODE,
+ HAL_PARAM_SECURE,
};
enum hal_domain {
@@ -819,6 +822,28 @@
u32 enable;
};
+enum hal_core_id {
+ VIDC_CORE_ID_DEFAULT = 0,
+ VIDC_CORE_ID_1 = 1, /* 0b01 */
+ VIDC_CORE_ID_2 = 2, /* 0b10 */
+ VIDC_CORE_ID_3 = 3, /* 0b11 */
+ VIDC_CORE_ID_UNUSED = 0x10000000,
+};
+
+struct hal_videocores_usage_info {
+ u32 video_core_enable_mask;
+};
+
+enum hal_work_mode {
+ VIDC_WORK_MODE_1,
+ VIDC_WORK_MODE_2,
+ VIDC_WORK_MODE_UNUSED = 0x10000000,
+};
+
+struct hal_video_work_mode {
+ u32 video_work_mode;
+};
+
struct hal_vpe_color_space_conversion {
u32 csc_matrix[HAL_MAX_MATRIX_COEFFS];
u32 csc_bias[HAL_MAX_BIAS_COEFFS];
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index bc7e8bd..d6c4bcb 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -163,6 +163,9 @@
#define HFI_VENC_PERFMODE_MAX_QUALITY 0x1
#define HFI_VENC_PERFMODE_POWER_SAVE 0x2
+#define HFI_WORKMODE_1 (HFI_COMMON_BASE + 0x1)
+#define HFI_WORKMODE_2 (HFI_COMMON_BASE + 0x2)
+
struct hfi_buffer_info {
u32 buffer_addr;
u32 extra_data_addr;
@@ -215,11 +218,17 @@
(HFI_PROPERTY_PARAM_COMMON_START + 0x00E)
#define HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED \
(HFI_PROPERTY_PARAM_COMMON_START + 0x010)
+#define HFI_PROPERTY_PARAM_SECURE_SESSION \
+ (HFI_PROPERTY_PARAM_COMMON_START + 0x011)
+#define HFI_PROPERTY_PARAM_WORK_MODE \
+ (HFI_PROPERTY_PARAM_COMMON_START + 0x015)
#define HFI_PROPERTY_CONFIG_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x2000)
#define HFI_PROPERTY_CONFIG_FRAME_RATE \
(HFI_PROPERTY_CONFIG_COMMON_START + 0x001)
+#define HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE \
+ (HFI_PROPERTY_CONFIG_COMMON_START + 0x002)
#define HFI_PROPERTY_PARAM_VDEC_COMMON_START \
(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_COMMON_OFFSET + 0x3000)
@@ -561,6 +570,14 @@
u32 height;
};
+struct hfi_videocores_usage_type {
+ u32 video_core_enable_mask;
+};
+
+struct hfi_video_work_mode {
+ u32 video_work_mode;
+};
+
struct hfi_video_signal_metadata {
u32 enable;
u32 video_format;
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index a8e6624..a9bb2dd 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -1013,8 +1013,8 @@
void dvb_usbv2_disconnect(struct usb_interface *intf)
{
struct dvb_usb_device *d = usb_get_intfdata(intf);
- const char *name = d->name;
- struct device dev = d->udev->dev;
+ const char *devname = kstrdup(dev_name(&d->udev->dev), GFP_KERNEL);
+ const char *drvname = d->name;
dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
intf->cur_altsetting->desc.bInterfaceNumber);
@@ -1024,8 +1024,9 @@
dvb_usbv2_exit(d);
- dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n",
- KBUILD_MODNAME, name);
+ pr_info("%s: '%s:%s' successfully deinitialized and disconnected\n",
+ KBUILD_MODNAME, drvname, devname);
+ kfree(devname);
}
EXPORT_SYMBOL(dvb_usbv2_disconnect);
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 2434030..9fd43a3 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -59,23 +59,24 @@
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
struct cxusb_state *st = d->priv;
- int ret, wo;
+ int ret;
if (1 + wlen > MAX_XFER_SIZE) {
warn("i2c wr: len=%d is too big!\n", wlen);
return -EOPNOTSUPP;
}
- wo = (rbuf == NULL || rlen == 0); /* write-only */
+ if (rlen > MAX_XFER_SIZE) {
+ warn("i2c rd: len=%d is too big!\n", rlen);
+ return -EOPNOTSUPP;
+ }
mutex_lock(&d->data_mutex);
st->data[0] = cmd;
memcpy(&st->data[1], wbuf, wlen);
- if (wo)
- ret = dvb_usb_generic_write(d, st->data, 1 + wlen);
- else
- ret = dvb_usb_generic_rw(d, st->data, 1 + wlen,
- rbuf, rlen, 0);
+ ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, st->data, rlen, 0);
+ if (!ret && rbuf && rlen)
+ memcpy(rbuf, st->data, rlen);
mutex_unlock(&d->data_mutex);
return ret;
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
index dd048a7..b8d2ac5 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
@@ -35,42 +35,51 @@
int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
{
- struct hexline hx;
- u8 reset;
- int ret,pos=0;
+ struct hexline *hx;
+ u8 *buf;
+ int ret, pos = 0;
+ u16 cpu_cs_register = cypress[type].cpu_cs_register;
+
+ buf = kmalloc(sizeof(*hx), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ hx = (struct hexline *)buf;
/* stop the CPU */
- reset = 1;
- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+ buf[0] = 1;
+ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1)
err("could not stop the USB controller CPU.");
- while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
- deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
- ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
+ while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) {
+ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n", hx->addr, hx->len, hx->chk);
+ ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
- if (ret != hx.len) {
+ if (ret != hx->len) {
err("error while transferring firmware "
"(transferred size: %d, block size: %d)",
- ret,hx.len);
+ ret, hx->len);
ret = -EINVAL;
break;
}
}
if (ret < 0) {
err("firmware download failed at %d with %d",pos,ret);
+ kfree(buf);
return ret;
}
if (ret == 0) {
/* restart the CPU */
- reset = 0;
- if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
+ buf[0] = 0;
+ if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
} else
ret = -EIO;
+ kfree(buf);
+
return ret;
}
EXPORT_SYMBOL(usb_cypress_load_firmware);
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
index 33fc2b9..3bc7d4e 100644
--- a/drivers/misc/uid_sys_stats.c
+++ b/drivers/misc/uid_sys_stats.c
@@ -238,28 +238,28 @@
io_last->fsync -= task->ioac.syscfs;
}
-static void update_io_stats_locked(void)
+static void update_io_stats_all_locked(void)
{
struct uid_entry *uid_entry;
struct task_struct *task, *temp;
struct io_stats *io_bucket, *io_curr, *io_last;
+ struct user_namespace *user_ns = current_user_ns();
unsigned long bkt;
-
- BUG_ON(!rt_mutex_is_locked(&uid_lock));
+ uid_t uid;
hash_for_each(hash_table, bkt, uid_entry, hash)
memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
sizeof(struct io_stats));
- read_lock(&tasklist_lock);
+ rcu_read_lock();
do_each_thread(temp, task) {
- uid_entry = find_or_register_uid(from_kuid_munged(
- current_user_ns(), task_uid(task)));
+ uid = from_kuid_munged(user_ns, task_uid(task));
+ uid_entry = find_or_register_uid(uid);
if (!uid_entry)
continue;
add_uid_io_curr_stats(uid_entry, task);
} while_each_thread(temp, task);
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
hash_for_each(hash_table, bkt, uid_entry, hash) {
io_bucket = &uid_entry->io[uid_entry->state];
@@ -282,6 +282,47 @@
}
}
+static void update_io_stats_uid_locked(uid_t target_uid)
+{
+ struct uid_entry *uid_entry;
+ struct task_struct *task, *temp;
+ struct io_stats *io_bucket, *io_curr, *io_last;
+ struct user_namespace *user_ns = current_user_ns();
+
+ uid_entry = find_or_register_uid(target_uid);
+ if (!uid_entry)
+ return;
+
+ memset(&uid_entry->io[UID_STATE_TOTAL_CURR], 0,
+ sizeof(struct io_stats));
+
+ rcu_read_lock();
+ do_each_thread(temp, task) {
+ if (from_kuid_munged(user_ns, task_uid(task)) != target_uid)
+ continue;
+ add_uid_io_curr_stats(uid_entry, task);
+ } while_each_thread(temp, task);
+ rcu_read_unlock();
+
+ io_bucket = &uid_entry->io[uid_entry->state];
+ io_curr = &uid_entry->io[UID_STATE_TOTAL_CURR];
+ io_last = &uid_entry->io[UID_STATE_TOTAL_LAST];
+
+ io_bucket->read_bytes +=
+ io_curr->read_bytes - io_last->read_bytes;
+ io_bucket->write_bytes +=
+ io_curr->write_bytes - io_last->write_bytes;
+ io_bucket->rchar += io_curr->rchar - io_last->rchar;
+ io_bucket->wchar += io_curr->wchar - io_last->wchar;
+ io_bucket->fsync += io_curr->fsync - io_last->fsync;
+
+ io_last->read_bytes = io_curr->read_bytes;
+ io_last->write_bytes = io_curr->write_bytes;
+ io_last->rchar = io_curr->rchar;
+ io_last->wchar = io_curr->wchar;
+ io_last->fsync = io_curr->fsync;
+}
+
static int uid_io_show(struct seq_file *m, void *v)
{
struct uid_entry *uid_entry;
@@ -289,7 +330,7 @@
rt_mutex_lock(&uid_lock);
- update_io_stats_locked();
+ update_io_stats_all_locked();
hash_for_each(hash_table, bkt, uid_entry, hash) {
seq_printf(m, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
@@ -364,7 +405,7 @@
return count;
}
- update_io_stats_locked();
+ update_io_stats_uid_locked(uid);
uid_entry->state = state;
@@ -402,7 +443,7 @@
uid_entry->utime += utime;
uid_entry->stime += stime;
- update_io_stats_locked();
+ update_io_stats_uid_locked(uid);
clean_uid_io_last_stats(uid_entry, task);
exit:
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index dba5c41..d8e9599 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2200,6 +2200,17 @@
int need_retune = card->host->need_retune;
int ecc_err = 0, gen_err = 0;
+ if (card->host->sdr104_wa && mmc_card_sd(card) &&
+ (card->host->ios.timing == MMC_TIMING_UHS_SDR104) &&
+ !card->sdr104_blocked &&
+ (brq->data.error == -EILSEQ ||
+ brq->data.error == -EIO ||
+ brq->data.error == -ETIMEDOUT ||
+ brq->cmd.error == -EILSEQ ||
+ brq->cmd.error == -EIO ||
+ brq->cmd.error == -ETIMEDOUT))
+ card->err_in_sdr104 = true;
+
/*
* sbc.error indicates a problem with the set block count
* command. No data will have been transferred.
@@ -3610,6 +3621,9 @@
if (!ctx_info->active_reqs)
wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq);
+ if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs)
+ complete(&mq->cmdq_shutdown_complete);
+
return;
}
@@ -3637,6 +3651,7 @@
struct mmc_async_req *areq;
const u8 packed_nr = 2;
u8 reqs = 0;
+ bool reset = false;
#ifdef CONFIG_MMC_SIMULATE_MAX_SPEED
unsigned long waitfor = jiffies;
#endif
@@ -3682,6 +3697,26 @@
type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
mmc_queue_bounce_post(mq_rq);
+ if (card->err_in_sdr104) {
+ /*
+ * Data CRC/timeout errors will manifest as CMD/DATA
+ * ERR. But we'd like to retry these too.
+ * Moreover, no harm done if this fails too for multiple
+ * times, we anyway reduce the bus-speed and retry the
+ * same request.
+ * If that fails too, we don't override this status.
+ */
+ if (status == MMC_BLK_ABORT ||
+ status == MMC_BLK_CMD_ERR ||
+ status == MMC_BLK_DATA_ERR ||
+ status == MMC_BLK_RETRY)
+ /* reset on all of these errors and retry */
+ reset = true;
+
+ status = MMC_BLK_RETRY;
+ card->err_in_sdr104 = false;
+ }
+
switch (status) {
case MMC_BLK_SUCCESS:
case MMC_BLK_PARTIAL:
@@ -3722,8 +3757,32 @@
break;
case MMC_BLK_RETRY:
retune_retry_done = brq->retune_retry_done;
- if (retry++ < MMC_BLK_MAX_RETRIES)
+ if (retry++ < MMC_BLK_MAX_RETRIES) {
break;
+ } else if (reset) {
+ reset = false;
+ /*
+ * If we exhaust all the retries due to
+ * CRC/timeout errors in SDR140 mode with UHS SD
+ * cards, re-configure the card in SDR50
+ * bus-speed mode.
+ * All subsequent re-init of this card will be
+ * in SDR50 mode, unless it is removed and
+ * re-inserted. When new UHS SD cards are
+ * inserted, it may start at SDR104 mode if
+ * supported by the card.
+ */
+ pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n",
+ req->rq_disk->disk_name);
+ mmc_host_clear_sdr104(card->host);
+ mmc_suspend_clk_scaling(card->host);
+ mmc_blk_reset(md, card->host, type);
+ /* SDR104 mode is blocked from now on */
+ card->sdr104_blocked = true;
+ /* retry 5 times again */
+ retry = 0;
+ break;
+ }
/* Fall through */
case MMC_BLK_ABORT:
if (!mmc_blk_reset(md, card->host, type) &&
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index b2d11b5..ccfd225 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -100,7 +100,8 @@
* 4. cmdq state shouldn't be in error state.
* 5. free tag available to process the new request.
*/
- wait_event(ctx->wait, mmc_peek_request(mq) &&
+ wait_event(ctx->wait, kthread_should_stop()
+ || (mmc_peek_request(mq) &&
!(((req_op(mq->cmdq_req_peeked) == REQ_OP_FLUSH) ||
(req_op(mq->cmdq_req_peeked) == REQ_OP_DISCARD))
&& test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state))
@@ -109,7 +110,7 @@
&& !(!host->card->part_curr && mmc_host_cq_disable(host) &&
!mmc_card_suspended(host->card))
&& !test_bit(CMDQ_STATE_ERR, &ctx->curr_state)
- && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked));
+ && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)));
}
static int mmc_cmdq_thread(void *d)
@@ -127,6 +128,8 @@
int ret = 0;
mmc_cmdq_ready_wait(host, mq);
+ if (kthread_should_stop())
+ break;
ret = mq->cmdq_issue_fn(mq, mq->cmdq_req_peeked);
/*
@@ -668,6 +671,7 @@
blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done);
INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work);
+ init_completion(&mq->cmdq_shutdown_complete);
init_completion(&mq->cmdq_pending_req_done);
blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out);
@@ -724,7 +728,22 @@
goto out;
if (wait) {
- blk_cleanup_queue(q);
+
+ /*
+ * After blk_stop_queue is called, wait for all
+ * active_reqs to complete.
+ * Then wait for cmdq thread to exit before calling
+ * cmdq shutdown to avoid race between issuing
+ * requests and shutdown of cmdq.
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (host->cmdq_ctx.active_reqs)
+ wait_for_completion(
+ &mq->cmdq_shutdown_complete);
+ kthread_stop(mq->thread);
mq->cmdq_shutdown(mq);
} else {
spin_lock_irqsave(q->queue_lock, flags);
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 02917aa..bf7a95b 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -77,6 +77,7 @@
struct work_struct cmdq_err_work;
struct completion cmdq_pending_req_done;
+ struct completion cmdq_shutdown_complete;
struct request *cmdq_req_peeked;
int (*err_check_fn)(struct mmc_card *, struct mmc_async_req *);
void (*packed_test_fn)(struct request_queue *, struct mmc_queue_req *);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c3c888e..220ba6d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -474,6 +474,11 @@
if (!clk_scaling->enable)
goto out;
+ if (*freq == UINT_MAX)
+ *freq = clk_scaling->freq_table[1];
+ else
+ *freq = clk_scaling->freq_table[0];
+
pr_debug("%s: target freq = %lu (%s)\n", mmc_hostname(host),
*freq, current->comm);
@@ -4170,6 +4175,10 @@
if (ret) {
mmc_card_set_removed(host->card);
+ if (host->card->sdr104_blocked) {
+ mmc_host_set_sdr104(host);
+ host->card->sdr104_blocked = false;
+ }
pr_debug("%s: card remove detected\n", mmc_hostname(host));
}
@@ -4276,7 +4285,7 @@
mmc_release_host(host);
goto out;
}
-+ mmc_rescan_try_freq(host, host->f_min);
+ mmc_rescan_try_freq(host, host->f_min);
mmc_release_host(host);
out:
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 3f39058..2adf42c 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -80,7 +80,6 @@
extern bool mmc_can_scale_clk(struct mmc_host *host);
extern int mmc_init_clk_scaling(struct mmc_host *host);
-extern int mmc_suspend_clk_scaling(struct mmc_host *host);
extern int mmc_resume_clk_scaling(struct mmc_host *host);
extern int mmc_exit_clk_scaling(struct mmc_host *host);
extern unsigned long mmc_get_max_frequency(struct mmc_host *host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 7f66ad3..7112f9f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -432,26 +432,26 @@
if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
(card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104) &&
(card->host->f_max > UHS_SDR104_MIN_DTR)) {
- card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
- } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50) &&
- (card->host->f_max > UHS_DDR50_MIN_DTR)) {
- card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
+ card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
SD_MODE_UHS_SDR50) &&
(card->host->f_max > UHS_SDR50_MIN_DTR)) {
- card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
+ card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
+ } else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50) &&
+ (card->host->f_max > UHS_DDR50_MIN_DTR)) {
+ card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
(card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25) &&
(card->host->f_max > UHS_SDR25_MIN_DTR)) {
- card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
+ card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
MMC_CAP_UHS_SDR12)) && (card->sw_caps.sd3_bus_mode &
SD_MODE_UHS_SDR12)) {
- card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
+ card->sd_bus_speed = UHS_SDR12_BUS_SPEED;
}
}
@@ -1313,6 +1313,8 @@
#endif
mmc_card_clr_suspended(host->card);
+ if (host->card->sdr104_blocked)
+ goto out;
err = mmc_resume_clk_scaling(host);
if (err) {
pr_err("%s: %s: fail to resume clock scaling (%d)\n",
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bcf33b8..fe62b69 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1815,6 +1815,7 @@
int clk_table_len;
u32 *clk_table = NULL;
enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
+ const char *lower_bus_speed = NULL;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1845,6 +1846,19 @@
!msm_host->mmc->clk_scaling.freq_table_sz)
dev_err(dev, "bad dts clock scaling frequencies\n");
+ /*
+ * Few hosts can support DDR52 mode at the same lower
+ * system voltage corner as high-speed mode. In such cases,
+ * it is always better to put it in DDR mode which will
+ * improve the performance without any power impact.
+ */
+ if (!of_property_read_string(np, "qcom,scaling-lower-bus-speed-mode",
+ &lower_bus_speed)) {
+ if (!strcmp(lower_bus_speed, "DDR52"))
+ msm_host->mmc->clk_scaling.lower_bus_speed_mode |=
+ MMC_SCALING_LOWER_DDR52_MODE;
+ }
+
if (sdhci_msm_dt_get_array(dev, "qcom,clk-rates",
&clk_table, &clk_table_len, 0)) {
dev_err(dev, "failed parsing supported clock rates\n");
@@ -1925,6 +1939,8 @@
if (of_get_property(np, "qcom,core_3_0v_support", NULL))
pdata->core_3_0v_support = true;
+ pdata->sdr104_wa = of_property_read_bool(np, "qcom,sdr104-wa");
+
return pdata;
out:
return NULL;
@@ -4408,6 +4424,8 @@
if (msm_host->pdata->nonhotplug)
msm_host->mmc->caps2 |= MMC_CAP2_NONHOTPLUG;
+ msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa;
+
init_completion(&msm_host->pwr_irq_completion);
if (gpio_is_valid(msm_host->pdata->status_gpio)) {
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index 533b241..53b1953 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -151,6 +151,7 @@
unsigned char sup_ice_clk_cnt;
struct sdhci_msm_pm_qos_data pm_qos_data;
bool core_3_0v_support;
+ bool sdr104_wa;
};
struct sdhci_msm_bus_vote {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 47096fd..53a6ae8 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1523,7 +1523,7 @@
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
/* Wait max 20 ms */
- timeout = 20000;
+ timeout = 20;
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
& SDHCI_CLOCK_INT_STABLE)) {
if (timeout == 0) {
@@ -1533,9 +1533,7 @@
return;
}
timeout--;
- spin_unlock_irq(&host->lock);
usleep_range(900, 1100);
- spin_lock_irq(&host->lock);
}
clk |= SDHCI_CLOCK_CARD_EN;
@@ -3098,7 +3096,10 @@
mmc_hostname(host->mmc), intmask,
host->data->error, ktime_to_ms(ktime_sub(
ktime_get(), host->data_start_time)));
- sdhci_dumpregs(host);
+
+ if (!host->mmc->sdr104_wa ||
+ (host->mmc->ios.timing != MMC_TIMING_UHS_SDR104))
+ sdhci_dumpregs(host);
}
sdhci_finish_data(host);
} else {
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index 3779475..283ff7e 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -229,12 +229,10 @@
last_trx_part = curr_part - 1;
- /*
- * We have whole TRX scanned, skip to the next part. Use
- * roundown (not roundup), as the loop will increase
- * offset in next step.
- */
- offset = rounddown(offset + trx->length, blocksize);
+ /* Jump to the end of TRX */
+ offset = roundup(offset + trx->length, blocksize);
+ /* Next loop iteration will increase the offset */
+ offset -= blocksize;
continue;
}
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index 368bb07..481895b 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -557,7 +557,7 @@
int work_done = 0;
u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
- u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD);
+ u32 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD);
u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
/* Handle bus state changes */
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c
index a849da9..6b86353 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cq.c
@@ -101,13 +101,19 @@
{
struct mlx4_cq *cq;
+ rcu_read_lock();
cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
cqn & (dev->caps.num_cqs - 1));
+ rcu_read_unlock();
+
if (!cq) {
mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
return;
}
+ /* Acessing the CQ outside of rcu_read_lock is safe, because
+ * the CQ is freed only after interrupt handling is completed.
+ */
++cq->arm_sn;
cq->comp(cq);
@@ -118,23 +124,19 @@
struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
struct mlx4_cq *cq;
- spin_lock(&cq_table->lock);
-
+ rcu_read_lock();
cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
- if (cq)
- atomic_inc(&cq->refcount);
-
- spin_unlock(&cq_table->lock);
+ rcu_read_unlock();
if (!cq) {
- mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+ mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
return;
}
+ /* Acessing the CQ outside of rcu_read_lock is safe, because
+ * the CQ is freed only after interrupt handling is completed.
+ */
cq->event(cq, event_type);
-
- if (atomic_dec_and_test(&cq->refcount))
- complete(&cq->free);
}
static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
@@ -301,9 +303,9 @@
if (err)
return err;
- spin_lock_irq(&cq_table->lock);
+ spin_lock(&cq_table->lock);
err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
- spin_unlock_irq(&cq_table->lock);
+ spin_unlock(&cq_table->lock);
if (err)
goto err_icm;
@@ -349,9 +351,9 @@
return 0;
err_radix:
- spin_lock_irq(&cq_table->lock);
+ spin_lock(&cq_table->lock);
radix_tree_delete(&cq_table->tree, cq->cqn);
- spin_unlock_irq(&cq_table->lock);
+ spin_unlock(&cq_table->lock);
err_icm:
mlx4_cq_free_icm(dev, cq->cqn);
@@ -370,15 +372,15 @@
if (err)
mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
+ spin_lock(&cq_table->lock);
+ radix_tree_delete(&cq_table->tree, cq->cqn);
+ spin_unlock(&cq_table->lock);
+
synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq);
if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq !=
priv->eq_table.eq[MLX4_EQ_ASYNC].irq)
synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
- spin_lock_irq(&cq_table->lock);
- radix_tree_delete(&cq_table->tree, cq->cqn);
- spin_unlock_irq(&cq_table->lock);
-
if (atomic_dec_and_test(&cq->refcount))
complete(&cq->free);
wait_for_completion(&cq->free);
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 4d3ddc2..5d48458 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -444,8 +444,14 @@
ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
ring->stride = stride;
- if (ring->stride <= TXBB_SIZE)
+ if (ring->stride <= TXBB_SIZE) {
+ /* Stamp first unused send wqe */
+ __be32 *ptr = (__be32 *)ring->buf;
+ __be32 stamp = cpu_to_be32(1 << STAMP_SHIFT);
+ *ptr = stamp;
+ /* Move pointer to start of rx section */
ring->buf += TXBB_SIZE;
+ }
ring->log_stride = ffs(ring->stride) - 1;
ring->buf_size = ring->size * ring->stride;
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index c548bea..32f76bf 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -2980,6 +2980,9 @@
put_res(dev, slave, srqn, RES_SRQ);
qp->srq = srq;
}
+
+ /* Save param3 for dynamic changes from VST back to VGT */
+ qp->param3 = qpc->param3;
put_res(dev, slave, rcqn, RES_CQ);
put_res(dev, slave, mtt_base, RES_MTT);
res_end_move(dev, slave, RES_QP, qpn);
@@ -3772,7 +3775,6 @@
int qpn = vhcr->in_modifier & 0x7fffff;
struct res_qp *qp;
u8 orig_sched_queue;
- __be32 orig_param3 = qpc->param3;
u8 orig_vlan_control = qpc->pri_path.vlan_control;
u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
u8 orig_pri_path_fl = qpc->pri_path.fl;
@@ -3814,7 +3816,6 @@
*/
if (!err) {
qp->sched_queue = orig_sched_queue;
- qp->param3 = orig_param3;
qp->vlan_control = orig_vlan_control;
qp->fvl_rx = orig_fvl_rx;
qp->pri_path_fl = orig_pri_path_fl;
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index e2512d5..eedf86b 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -528,6 +528,9 @@
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
return 0;
+ if (!spec_priv->rfs_chan_spec_scan)
+ return 1;
+
/* Output buffers are full, no need to process anything
* since there is no space to put the result anyway
*/
@@ -1072,7 +1075,7 @@
void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
{
- if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS)) {
+ if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) {
relay_close(spec_priv->rfs_chan_spec_scan);
spec_priv->rfs_chan_spec_scan = NULL;
}
@@ -1086,6 +1089,9 @@
debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
NULL);
+ if (!spec_priv->rfs_chan_spec_scan)
+ return;
+
debugfs_create_file("spectral_scan_ctl",
S_IRUSR | S_IWUSR,
debugfs_phy, spec_priv,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 4e0c565..b7273be 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -1422,7 +1422,7 @@
cancel_work_sync(&rt2x00dev->intf_work);
cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
cancel_work_sync(&rt2x00dev->sleep_work);
-#ifdef CONFIG_RT2X00_LIB_USB
+#if IS_ENABLED(CONFIG_RT2X00_LIB_USB)
if (rt2x00_is_usb(rt2x00dev)) {
usb_kill_anchored_urbs(rt2x00dev->anchor);
hrtimer_cancel(&rt2x00dev->txstatus_timer);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index 6005e14..662705e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -319,10 +319,8 @@
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
- usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor);
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
if (status) {
- usb_unanchor_urb(entry_priv->urb);
if (status == -ENODEV)
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
@@ -410,10 +408,8 @@
entry->skb->data, entry->skb->len,
rt2x00usb_interrupt_rxdone, entry);
- usb_anchor_urb(entry_priv->urb, rt2x00dev->anchor);
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
if (status) {
- usb_unanchor_urb(entry_priv->urb);
if (status == -ENODEV)
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
@@ -824,10 +820,6 @@
if (retval)
goto exit_free_device;
- retval = rt2x00lib_probe_dev(rt2x00dev);
- if (retval)
- goto exit_free_reg;
-
rt2x00dev->anchor = devm_kmalloc(&usb_dev->dev,
sizeof(struct usb_anchor),
GFP_KERNEL);
@@ -835,10 +827,17 @@
retval = -ENOMEM;
goto exit_free_reg;
}
-
init_usb_anchor(rt2x00dev->anchor);
+
+ retval = rt2x00lib_probe_dev(rt2x00dev);
+ if (retval)
+ goto exit_free_anchor;
+
return 0;
+exit_free_anchor:
+ usb_kill_anchored_urbs(rt2x00dev->anchor);
+
exit_free_reg:
rt2x00usb_free_reg(rt2x00dev);
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 23d4a17..351bac8 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -934,8 +934,14 @@
rc = nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, NULL);
if (rc < 0)
goto out_unlock;
+ nvdimm_bus_unlock(&nvdimm_bus->dev);
+
if (copy_to_user(p, buf, buf_len))
rc = -EFAULT;
+
+ vfree(buf);
+ return rc;
+
out_unlock:
nvdimm_bus_unlock(&nvdimm_bus->dev);
out:
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index d614493..dcb32f3 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -388,7 +388,7 @@
int alias_dpa_busy(struct device *dev, void *data)
{
- resource_size_t map_end, blk_start, new, busy;
+ resource_size_t map_end, blk_start, new;
struct blk_alloc_info *info = data;
struct nd_mapping *nd_mapping;
struct nd_region *nd_region;
@@ -429,29 +429,19 @@
retry:
/*
* Find the free dpa from the end of the last pmem allocation to
- * the end of the interleave-set mapping that is not already
- * covered by a blk allocation.
+ * the end of the interleave-set mapping.
*/
- busy = 0;
for_each_dpa_resource(ndd, res) {
+ if (strncmp(res->name, "pmem", 4) != 0)
+ continue;
if ((res->start >= blk_start && res->start < map_end)
|| (res->end >= blk_start
&& res->end <= map_end)) {
- if (strncmp(res->name, "pmem", 4) == 0) {
- new = max(blk_start, min(map_end + 1,
- res->end + 1));
- if (new != blk_start) {
- blk_start = new;
- goto retry;
- }
- } else
- busy += min(map_end, res->end)
- - max(nd_mapping->start, res->start) + 1;
- } else if (nd_mapping->start > res->start
- && map_end < res->end) {
- /* total eclipse of the PMEM region mapping */
- busy += nd_mapping->size;
- break;
+ new = max(blk_start, min(map_end + 1, res->end + 1));
+ if (new != blk_start) {
+ blk_start = new;
+ goto retry;
+ }
}
}
@@ -463,52 +453,11 @@
return 1;
}
- info->available -= blk_start - nd_mapping->start + busy;
+ info->available -= blk_start - nd_mapping->start;
return 0;
}
-static int blk_dpa_busy(struct device *dev, void *data)
-{
- struct blk_alloc_info *info = data;
- struct nd_mapping *nd_mapping;
- struct nd_region *nd_region;
- resource_size_t map_end;
- int i;
-
- if (!is_nd_pmem(dev))
- return 0;
-
- nd_region = to_nd_region(dev);
- for (i = 0; i < nd_region->ndr_mappings; i++) {
- nd_mapping = &nd_region->mapping[i];
- if (nd_mapping->nvdimm == info->nd_mapping->nvdimm)
- break;
- }
-
- if (i >= nd_region->ndr_mappings)
- return 0;
-
- map_end = nd_mapping->start + nd_mapping->size - 1;
- if (info->res->start >= nd_mapping->start
- && info->res->start < map_end) {
- if (info->res->end <= map_end) {
- info->busy = 0;
- return 1;
- } else {
- info->busy -= info->res->end - map_end;
- return 0;
- }
- } else if (info->res->end >= nd_mapping->start
- && info->res->end <= map_end) {
- info->busy -= nd_mapping->start - info->res->start;
- return 0;
- } else {
- info->busy -= nd_mapping->size;
- return 0;
- }
-}
-
/**
* nd_blk_available_dpa - account the unused dpa of BLK region
* @nd_mapping: container of dpa-resource-root + labels
@@ -538,11 +487,7 @@
for_each_dpa_resource(ndd, res) {
if (strncmp(res->name, "blk", 3) != 0)
continue;
-
- info.res = res;
- info.busy = resource_size(res);
- device_for_each_child(&nvdimm_bus->dev, &info, blk_dpa_busy);
- info.available -= info.busy;
+ info.available -= resource_size(res);
}
return info.available;
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 1e45c73..6523cb0 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -5819,9 +5819,10 @@
struct msi_msg *msg)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(&pdev->dev);
- int ret, bypass_en = 0;
+ struct iommu_domain_geometry geometry;
+ int ret, fastmap_en = 0, bypass_en = 0;
dma_addr_t iova;
- phys_addr_t pcie_base_addr, gicm_db_offset;
+ phys_addr_t gicm_db_offset;
msg->address_hi = 0;
msg->address_lo = dev->msi_gicm_addr;
@@ -5843,16 +5844,25 @@
if (bypass_en)
return 0;
- gicm_db_offset = dev->msi_gicm_addr -
- rounddown(dev->msi_gicm_addr, PAGE_SIZE);
- /*
- * Use PCIe DBI address as the IOVA since client cannot
- * use this address for their IOMMU mapping. This will
- * prevent any conflicts between PCIe host and
- * client's mapping.
- */
- pcie_base_addr = dev->res[MSM_PCIE_RES_DM_CORE].resource->start;
- iova = rounddown(pcie_base_addr, PAGE_SIZE);
+ iommu_domain_get_attr(domain, DOMAIN_ATTR_FAST, &fastmap_en);
+ if (fastmap_en) {
+ iommu_domain_get_attr(domain, DOMAIN_ATTR_GEOMETRY, &geometry);
+ iova = geometry.aperture_start;
+ PCIE_DBG(dev,
+ "PCIe: RC%d: Use client's IOVA 0x%llx to map QGIC MSI address\n",
+ dev->rc_idx, iova);
+ } else {
+ phys_addr_t pcie_base_addr;
+
+ /*
+ * Use PCIe DBI address as the IOVA since client cannot
+ * use this address for their IOMMU mapping. This will
+ * prevent any conflicts between PCIe host and
+ * client's mapping.
+ */
+ pcie_base_addr = dev->res[MSM_PCIE_RES_DM_CORE].resource->start;
+ iova = rounddown(pcie_base_addr, PAGE_SIZE);
+ }
ret = iommu_map(domain, iova, rounddown(dev->msi_gicm_addr, PAGE_SIZE),
PAGE_SIZE, IOMMU_READ | IOMMU_WRITE);
@@ -5863,6 +5873,8 @@
return -ENOMEM;
}
+ gicm_db_offset = dev->msi_gicm_addr -
+ rounddown(dev->msi_gicm_addr, PAGE_SIZE);
msg->address_lo = iova + gicm_db_offset;
return 0;
@@ -6445,7 +6457,6 @@
}
dev_set_drvdata(&msm_pcie_dev[rc_idx].pdev->dev, &msm_pcie_dev[rc_idx]);
- msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx],
msm_pcie_dev[rc_idx].pdev);
@@ -6496,6 +6507,8 @@
goto decrease_rc_num;
}
+ msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
+
msm_pcie_dev[rc_idx].drv_ready = true;
if (msm_pcie_dev[rc_idx].boot_option &
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index ba6d5ce..304e206 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -97,6 +97,15 @@
Qualcomm Technologies Inc TLMM block found on the Qualcomm
Technologies Inc SDM830 platform.
+config PINCTRL_SDXPOORWILLS
+ tristate "Qualcomm Technologies Inc SDXPOORWILLS 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 SDXPOORWILLS platform.
+
config PINCTRL_MSM8996
tristate "Qualcomm MSM8996 pin controller driver"
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 5e05e897..4786960 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -17,5 +17,6 @@
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
obj-$(CONFIG_PINCTRL_SDM830) += pinctrl-sdm830.o
+obj-$(CONFIG_PINCTRL_SDXPOORWILLS) += pinctrl-sdxpoorwills.o
obj-$(CONFIG_PINCTRL_WCD) += pinctrl-wcd.o
obj-$(CONFIG_PINCTRL_LPI) += pinctrl-lpi.o
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
new file mode 100644
index 0000000..4a21eb6
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -0,0 +1,1205 @@
+/*
+ * 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/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 = 3, \
+ .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_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc sdxpoorwills_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, "SDC1_CLK"),
+ PINCTRL_PIN(101, "SDC1_CMD"),
+ PINCTRL_PIN(102, "SDC1_DATA"),
+ PINCTRL_PIN(103, "SDC2_CLK"),
+ PINCTRL_PIN(104, "SDC2_CMD"),
+ PINCTRL_PIN(105, "SDC2_DATA"),
+};
+
+#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);
+
+static const unsigned int sdc1_clk_pins[] = { 100 };
+static const unsigned int sdc1_cmd_pins[] = { 101 };
+static const unsigned int sdc1_data_pins[] = { 102 };
+static const unsigned int sdc2_clk_pins[] = { 103 };
+static const unsigned int sdc2_cmd_pins[] = { 104 };
+static const unsigned int sdc2_data_pins[] = { 105 };
+
+enum sdxpoorwills_functions {
+ msm_mux_qdss_stm31,
+ msm_mux_blsp_uart1,
+ msm_mux_gpio,
+ msm_mux_uim2_data,
+ msm_mux_ebi0_wrcdc,
+ msm_mux_uim2_present,
+ msm_mux_qdss_stm30,
+ msm_mux_uim2_reset,
+ msm_mux_blsp_i2c1,
+ msm_mux_qdss_stm29,
+ msm_mux_uim2_clk,
+ msm_mux_qdss_stm28,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_uart2,
+ msm_mux_qdss_stm23,
+ msm_mux_qdss3,
+ msm_mux_qdss_stm22,
+ msm_mux_qdss2,
+ msm_mux_blsp_i2c2,
+ msm_mux_qdss_stm21,
+ msm_mux_qdss1,
+ msm_mux_qdss_stm20,
+ msm_mux_qdss0,
+ msm_mux_pri_mi2s,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_uart3,
+ msm_mux_ext_dbg,
+ msm_mux_ldo_en,
+ msm_mux_blsp_i2c3,
+ msm_mux_gcc_gp3,
+ msm_mux_qdss_stm19,
+ msm_mux_qdss12,
+ msm_mux_qdss_stm18,
+ msm_mux_qdss13,
+ msm_mux_qdss_stm17,
+ msm_mux_qdss14,
+ msm_mux_bimc_dte0,
+ msm_mux_native_tsens,
+ msm_mux_vsense_trigger,
+ msm_mux_qdss_stm26,
+ msm_mux_qdss9,
+ msm_mux_blsp_i2c4,
+ msm_mux_gcc_gp1,
+ msm_mux_qdss_stm25,
+ msm_mux_qdss10,
+ msm_mux_jitter_bist,
+ msm_mux_gcc_gp2,
+ msm_mux_qdss_stm24,
+ msm_mux_qdss11,
+ msm_mux_qdss_stm16,
+ msm_mux_qdss15,
+ msm_mux_bimc_dte1,
+ msm_mux_sec_mi2s,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_uart4,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_stm27,
+ msm_mux_qdss8,
+ msm_mux_ebi2_a,
+ msm_mux_qdss_stm3,
+ msm_mux_ebi2_lcd,
+ msm_mux_qdss_stm2,
+ msm_mux_pll_bist,
+ msm_mux_qdss_stm1,
+ msm_mux_qdss_stm0,
+ msm_mux_adsp_ext,
+ msm_mux_epm1,
+ msm_mux_m_voc,
+ msm_mux_native_char,
+ msm_mux_native_char1,
+ msm_mux_pa_indicator,
+ msm_mux_qdss_traceclk,
+ msm_mux_native_char0,
+ msm_mux_qlink_en,
+ msm_mux_qlink_req,
+ msm_mux_pll_test,
+ msm_mux_cri_trng,
+ msm_mux_wmss_reset,
+ msm_mux_native_char3,
+ msm_mux_nav_pps,
+ msm_mux_nav_dr,
+ msm_mux_native_char2,
+ msm_mux_native_tsense,
+ msm_mux_prng_rosc,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_pll_ref,
+ msm_mux_coex_uart,
+ msm_mux_qdss_stm11,
+ msm_mux_qdss_stm10,
+ msm_mux_ddr_pxi0,
+ msm_mux_ap2mdm_status,
+ msm_mux_ddr_bist,
+ msm_mux_mdm2ap_status,
+ msm_mux_ap2mdm_err,
+ msm_mux_mdm2ap_err,
+ msm_mux_ap2mdm_vdd,
+ msm_mux_mdm2ap_vdd,
+ msm_mux_ap2mdm_wake,
+ msm_mux_pciehost_rst,
+ msm_mux_blsp_spi1,
+ msm_mux_qdss_stm14,
+ msm_mux_pcie_wake,
+ msm_mux_mdm2ap_wake,
+ msm_mux_pci_e,
+ msm_mux_qdss_stm13,
+ msm_mux_i2s_mclk,
+ msm_mux_audio_ref,
+ msm_mux_ldo_update,
+ msm_mux_qdss_stm8,
+ msm_mux_qdss_stm7,
+ msm_mux_qdss4,
+ msm_mux_tgu_ch0,
+ msm_mux_pcie_clkreq,
+ msm_mux_qdss_stm9,
+ msm_mux_qdss_stm15,
+ msm_mux_mgpi_clk,
+ msm_mux_qdss_stm12,
+ msm_mux_qdss_tracectl,
+ msm_mux_atest_char,
+ msm_mux_qdss_stm6,
+ msm_mux_qdss5,
+ msm_mux_atest_char3,
+ msm_mux_qdss_stm5,
+ msm_mux_qdss6,
+ msm_mux_atest_char2,
+ msm_mux_qdss_stm4,
+ msm_mux_qdss7,
+ msm_mux_atest_char1,
+ msm_mux_uim1_data,
+ msm_mux_atest_char0,
+ msm_mux_uim1_present,
+ msm_mux_uim1_reset,
+ msm_mux_uim1_clk,
+ msm_mux_dbg_out,
+ msm_mux_gcc_plltest,
+ msm_mux_usb2phy_ac,
+ msm_mux_NA,
+};
+
+static const char * const qdss_stm31_groups[] = {
+ "gpio0",
+};
+static const char * const blsp_uart1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio20", "gpio21", "gpio22",
+ "gpio23",
+};
+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", "gpio26", "gpio27", "gpio28", "gpio29",
+ "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
+ "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
+ "gpio44", "gpio45", "gpio54", "gpio55", "gpio56", "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",
+};
+static const char * const uim2_data_groups[] = {
+ "gpio0",
+};
+static const char * const ebi0_wrcdc_groups[] = {
+ "gpio0", "gpio2",
+};
+static const char * const uim2_present_groups[] = {
+ "gpio1",
+};
+static const char * const qdss_stm30_groups[] = {
+ "gpio1",
+};
+static const char * const uim2_reset_groups[] = {
+ "gpio2",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio2", "gpio3", "gpio74", "gpio75",
+};
+static const char * const qdss_stm29_groups[] = {
+ "gpio2",
+};
+static const char * const uim2_clk_groups[] = {
+ "gpio3",
+};
+static const char * const qdss_stm28_groups[] = {
+ "gpio3",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7", "gpio52", "gpio62", "gpio71",
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7", "gpio63", "gpio64", "gpio65",
+ "gpio66",
+};
+static const char * const qdss_stm23_groups[] = {
+ "gpio4",
+};
+static const char * const qdss3_groups[] = {
+ "gpio4",
+};
+static const char * const qdss_stm22_groups[] = {
+ "gpio5",
+};
+static const char * const qdss2_groups[] = {
+ "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio6", "gpio7", "gpio65", "gpio66",
+};
+static const char * const qdss_stm21_groups[] = {
+ "gpio6",
+};
+static const char * const qdss1_groups[] = {
+ "gpio6",
+};
+static const char * const qdss_stm20_groups[] = {
+ "gpio7",
+};
+static const char * const qdss0_groups[] = {
+ "gpio7",
+};
+static const char * const pri_mi2s_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15",
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio52", "gpio62", "gpio71",
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const ext_dbg_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio8",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const gcc_gp3_groups[] = {
+ "gpio11",
+};
+static const char * const qdss_stm19_groups[] = {
+ "gpio12",
+};
+static const char * const qdss12_groups[] = {
+ "gpio12",
+};
+static const char * const qdss_stm18_groups[] = {
+ "gpio13",
+};
+static const char * const qdss13_groups[] = {
+ "gpio13",
+};
+static const char * const qdss_stm17_groups[] = {
+ "gpio14",
+};
+static const char * const qdss14_groups[] = {
+ "gpio14",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio14", "gpio59",
+};
+static const char * const native_tsens_groups[] = {
+ "gpio14",
+};
+static const char * const vsense_trigger_groups[] = {
+ "gpio14",
+};
+static const char * const qdss_stm26_groups[] = {
+ "gpio17",
+};
+static const char * const qdss9_groups[] = {
+ "gpio17",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio18", "gpio19", "gpio76", "gpio77",
+};
+static const char * const gcc_gp1_groups[] = {
+ "gpio18",
+};
+static const char * const qdss_stm25_groups[] = {
+ "gpio18",
+};
+static const char * const qdss10_groups[] = {
+ "gpio18",
+};
+static const char * const jitter_bist_groups[] = {
+ "gpio19",
+};
+static const char * const gcc_gp2_groups[] = {
+ "gpio19",
+};
+static const char * const qdss_stm24_groups[] = {
+ "gpio19",
+};
+static const char * const qdss11_groups[] = {
+ "gpio19",
+};
+static const char * const qdss_stm16_groups[] = {
+ "gpio15",
+};
+static const char * const qdss15_groups[] = {
+ "gpio15",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio15", "gpio60",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
+ "gpio23",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19", "gpio52", "gpio62", "gpio71",
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22",
+ "gpio23",
+};
+static const char * const qdss_cti_groups[] = {
+ "gpio16", "gpio16", "gpio17", "gpio17", "gpio22", "gpio22", "gpio23",
+ "gpio23", "gpio54", "gpio54", "gpio55", "gpio55", "gpio59", "gpio61",
+ "gpio88", "gpio88", "gpio89", "gpio89",
+};
+static const char * const qdss_stm27_groups[] = {
+ "gpio16",
+};
+static const char * const qdss8_groups[] = {
+ "gpio16",
+};
+static const char * const ebi2_a_groups[] = {
+ "gpio20",
+};
+static const char * const qdss_stm3_groups[] = {
+ "gpio20",
+};
+static const char * const ebi2_lcd_groups[] = {
+ "gpio21", "gpio22", "gpio23",
+};
+static const char * const qdss_stm2_groups[] = {
+ "gpio21",
+};
+static const char * const pll_bist_groups[] = {
+ "gpio22",
+};
+static const char * const qdss_stm1_groups[] = {
+ "gpio22",
+};
+static const char * const qdss_stm0_groups[] = {
+ "gpio23",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio24", "gpio25",
+};
+static const char * const epm1_groups[] = {
+ "gpio25",
+};
+static const char * const m_voc_groups[] = {
+ "gpio25", "gpio46", "gpio59", "gpio61",
+};
+static const char * const native_char_groups[] = {
+ "gpio26",
+};
+static const char * const native_char1_groups[] = {
+ "gpio32",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio33",
+};
+static const char * const qdss_traceclk_groups[] = {
+ "gpio33",
+};
+static const char * const native_char0_groups[] = {
+ "gpio33",
+};
+static const char * const qlink_en_groups[] = {
+ "gpio34",
+};
+static const char * const qlink_req_groups[] = {
+ "gpio35",
+};
+static const char * const pll_test_groups[] = {
+ "gpio35",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio36",
+};
+static const char * const wmss_reset_groups[] = {
+ "gpio28",
+};
+static const char * const native_char3_groups[] = {
+ "gpio28",
+};
+static const char * const nav_pps_groups[] = {
+ "gpio29", "gpio42", "gpio62",
+};
+static const char * const nav_dr_groups[] = {
+ "gpio29", "gpio42", "gpio62",
+};
+static const char * const native_char2_groups[] = {
+ "gpio29",
+};
+static const char * const native_tsense_groups[] = {
+ "gpio29",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio38",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio40",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio41",
+};
+static const char * const pll_ref_groups[] = {
+ "gpio42",
+};
+static const char * const coex_uart_groups[] = {
+ "gpio44", "gpio45",
+};
+static const char * const qdss_stm11_groups[] = {
+ "gpio44",
+};
+static const char * const qdss_stm10_groups[] = {
+ "gpio45",
+};
+static const char * const ddr_pxi0_groups[] = {
+ "gpio45", "gpio46",
+};
+static const char * const ap2mdm_status_groups[] = {
+ "gpio46",
+};
+static const char * const ddr_bist_groups[] = {
+ "gpio46", "gpio47", "gpio48", "gpio49",
+};
+static const char * const mdm2ap_status_groups[] = {
+ "gpio47",
+};
+static const char * const ap2mdm_err_groups[] = {
+ "gpio48",
+};
+static const char * const mdm2ap_err_groups[] = {
+ "gpio49",
+};
+static const char * const ap2mdm_vdd_groups[] = {
+ "gpio50",
+};
+static const char * const mdm2ap_vdd_groups[] = {
+ "gpio51",
+};
+static const char * const ap2mdm_wake_groups[] = {
+ "gpio52",
+};
+static const char * const pciehost_rst_groups[] = {
+ "gpio52",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio52", "gpio62", "gpio71", "gpio72", "gpio73", "gpio74", "gpio75",
+};
+static const char * const qdss_stm14_groups[] = {
+ "gpio52",
+};
+static const char * const pcie_wake_groups[] = {
+ "gpio53",
+};
+static const char * const mdm2ap_wake_groups[] = {
+ "gpio53",
+};
+static const char * const pci_e_groups[] = {
+ "gpio53", "gpio57",
+};
+static const char * const qdss_stm13_groups[] = {
+ "gpio53",
+};
+static const char * const i2s_mclk_groups[] = {
+ "gpio62",
+};
+static const char * const audio_ref_groups[] = {
+ "gpio62",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio62",
+};
+static const char * const qdss_stm8_groups[] = {
+ "gpio62",
+};
+static const char * const qdss_stm7_groups[] = {
+ "gpio63",
+};
+static const char * const qdss4_groups[] = {
+ "gpio63",
+};
+static const char * const tgu_ch0_groups[] = {
+ "gpio55",
+};
+static const char * const pcie_clkreq_groups[] = {
+ "gpio56",
+};
+static const char * const qdss_stm9_groups[] = {
+ "gpio56",
+};
+static const char * const qdss_stm15_groups[] = {
+ "gpio57",
+};
+static const char * const mgpi_clk_groups[] = {
+ "gpio60", "gpio71",
+};
+static const char * const qdss_stm12_groups[] = {
+ "gpio60",
+};
+static const char * const qdss_tracectl_groups[] = {
+ "gpio60",
+};
+static const char * const atest_char_groups[] = {
+ "gpio63",
+};
+static const char * const qdss_stm6_groups[] = {
+ "gpio64",
+};
+static const char * const qdss5_groups[] = {
+ "gpio64",
+};
+static const char * const atest_char3_groups[] = {
+ "gpio64",
+};
+static const char * const qdss_stm5_groups[] = {
+ "gpio65",
+};
+static const char * const qdss6_groups[] = {
+ "gpio65",
+};
+static const char * const atest_char2_groups[] = {
+ "gpio65",
+};
+static const char * const qdss_stm4_groups[] = {
+ "gpio66",
+};
+static const char * const qdss7_groups[] = {
+ "gpio66",
+};
+static const char * const atest_char1_groups[] = {
+ "gpio66",
+};
+static const char * const uim1_data_groups[] = {
+ "gpio67",
+};
+static const char * const atest_char0_groups[] = {
+ "gpio67",
+};
+static const char * const uim1_present_groups[] = {
+ "gpio68",
+};
+static const char * const uim1_reset_groups[] = {
+ "gpio69",
+};
+static const char * const uim1_clk_groups[] = {
+ "gpio70",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio71",
+};
+static const char * const gcc_plltest_groups[] = {
+ "gpio73", "gpio74",
+};
+static const char * const usb2phy_ac_groups[] = {
+ "gpio87",
+};
+
+static const struct msm_function sdxpoorwills_functions[] = {
+ FUNCTION(qdss_stm31),
+ FUNCTION(blsp_uart1),
+ FUNCTION(gpio),
+ FUNCTION(uim2_data),
+ FUNCTION(ebi0_wrcdc),
+ FUNCTION(uim2_present),
+ FUNCTION(qdss_stm30),
+ FUNCTION(uim2_reset),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(qdss_stm29),
+ FUNCTION(uim2_clk),
+ FUNCTION(qdss_stm28),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_uart2),
+ FUNCTION(qdss_stm23),
+ FUNCTION(qdss3),
+ FUNCTION(qdss_stm22),
+ FUNCTION(qdss2),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(qdss_stm21),
+ FUNCTION(qdss1),
+ FUNCTION(qdss_stm20),
+ FUNCTION(qdss0),
+ FUNCTION(pri_mi2s),
+ FUNCTION(blsp_spi3),
+ FUNCTION(blsp_uart3),
+ FUNCTION(ext_dbg),
+ FUNCTION(ldo_en),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(gcc_gp3),
+ FUNCTION(qdss_stm19),
+ FUNCTION(qdss12),
+ FUNCTION(qdss_stm18),
+ FUNCTION(qdss13),
+ FUNCTION(qdss_stm17),
+ FUNCTION(qdss14),
+ FUNCTION(bimc_dte0),
+ FUNCTION(native_tsens),
+ FUNCTION(vsense_trigger),
+ FUNCTION(qdss_stm26),
+ FUNCTION(qdss9),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(gcc_gp1),
+ FUNCTION(qdss_stm25),
+ FUNCTION(qdss10),
+ FUNCTION(jitter_bist),
+ FUNCTION(gcc_gp2),
+ FUNCTION(qdss_stm24),
+ FUNCTION(qdss11),
+ FUNCTION(qdss_stm16),
+ FUNCTION(qdss15),
+ FUNCTION(bimc_dte1),
+ FUNCTION(sec_mi2s),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_uart4),
+ FUNCTION(qdss_cti),
+ FUNCTION(qdss_stm27),
+ FUNCTION(qdss8),
+ FUNCTION(ebi2_a),
+ FUNCTION(qdss_stm3),
+ FUNCTION(ebi2_lcd),
+ FUNCTION(qdss_stm2),
+ FUNCTION(pll_bist),
+ FUNCTION(qdss_stm1),
+ FUNCTION(qdss_stm0),
+ FUNCTION(adsp_ext),
+ FUNCTION(epm1),
+ FUNCTION(m_voc),
+ FUNCTION(native_char),
+ FUNCTION(native_char1),
+ FUNCTION(pa_indicator),
+ FUNCTION(qdss_traceclk),
+ FUNCTION(native_char0),
+ FUNCTION(qlink_en),
+ FUNCTION(qlink_req),
+ FUNCTION(pll_test),
+ FUNCTION(cri_trng),
+ FUNCTION(wmss_reset),
+ FUNCTION(native_char3),
+ FUNCTION(nav_pps),
+ FUNCTION(nav_dr),
+ FUNCTION(native_char2),
+ FUNCTION(native_tsense),
+ FUNCTION(prng_rosc),
+ FUNCTION(cri_trng0),
+ FUNCTION(cri_trng1),
+ FUNCTION(pll_ref),
+ FUNCTION(coex_uart),
+ FUNCTION(qdss_stm11),
+ FUNCTION(qdss_stm10),
+ FUNCTION(ddr_pxi0),
+ FUNCTION(ap2mdm_status),
+ FUNCTION(ddr_bist),
+ FUNCTION(mdm2ap_status),
+ FUNCTION(ap2mdm_err),
+ FUNCTION(mdm2ap_err),
+ FUNCTION(ap2mdm_vdd),
+ FUNCTION(mdm2ap_vdd),
+ FUNCTION(ap2mdm_wake),
+ FUNCTION(pciehost_rst),
+ FUNCTION(blsp_spi1),
+ FUNCTION(qdss_stm14),
+ FUNCTION(pcie_wake),
+ FUNCTION(mdm2ap_wake),
+ FUNCTION(pci_e),
+ FUNCTION(qdss_stm13),
+ FUNCTION(i2s_mclk),
+ FUNCTION(audio_ref),
+ FUNCTION(ldo_update),
+ FUNCTION(qdss_stm8),
+ FUNCTION(qdss_stm7),
+ FUNCTION(qdss4),
+ FUNCTION(tgu_ch0),
+ FUNCTION(pcie_clkreq),
+ FUNCTION(qdss_stm9),
+ FUNCTION(qdss_stm15),
+ FUNCTION(mgpi_clk),
+ FUNCTION(qdss_stm12),
+ FUNCTION(qdss_tracectl),
+ FUNCTION(atest_char),
+ FUNCTION(qdss_stm6),
+ FUNCTION(qdss5),
+ FUNCTION(atest_char3),
+ FUNCTION(qdss_stm5),
+ FUNCTION(qdss6),
+ FUNCTION(atest_char2),
+ FUNCTION(qdss_stm4),
+ FUNCTION(qdss7),
+ FUNCTION(atest_char1),
+ FUNCTION(uim1_data),
+ FUNCTION(atest_char0),
+ FUNCTION(uim1_present),
+ FUNCTION(uim1_reset),
+ FUNCTION(uim1_clk),
+ FUNCTION(dbg_out),
+ FUNCTION(gcc_plltest),
+ FUNCTION(usb2phy_ac),
+};
+
+static const struct msm_pingroup sdxpoorwills_groups[] = {
+ PINGROUP(0, uim2_data, blsp_uart1, qdss_stm31, ebi0_wrcdc, NA, NA, NA,
+ NA, NA),
+ PINGROUP(1, uim2_present, blsp_uart1, qdss_stm30, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(2, uim2_reset, blsp_uart1, blsp_i2c1, qdss_stm29, ebi0_wrcdc,
+ NA, NA, NA, NA),
+ PINGROUP(3, uim2_clk, blsp_uart1, blsp_i2c1, qdss_stm28, NA, NA, NA,
+ NA, NA),
+ PINGROUP(4, blsp_spi2, blsp_uart2, NA, qdss_stm23, qdss3, NA, NA, NA,
+ NA),
+ PINGROUP(5, blsp_spi2, blsp_uart2, NA, qdss_stm22, qdss2, NA, NA, NA,
+ NA),
+ PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, qdss_stm21, qdss1,
+ NA, NA, NA),
+ PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, qdss_stm20, qdss0,
+ NA, NA, NA),
+ PINGROUP(8, pri_mi2s, blsp_spi3, blsp_uart3, ext_dbg, ldo_en, NA, NA,
+ NA, NA),
+ PINGROUP(9, pri_mi2s, blsp_spi3, blsp_uart3, ext_dbg, NA, NA, NA, NA,
+ NA),
+ PINGROUP(10, pri_mi2s, blsp_spi3, blsp_uart3, blsp_i2c3, ext_dbg, NA,
+ NA, NA, NA),
+ PINGROUP(11, pri_mi2s, blsp_spi3, blsp_uart3, blsp_i2c3, ext_dbg,
+ gcc_gp3, NA, NA, NA),
+ PINGROUP(12, pri_mi2s, NA, qdss_stm19, qdss12, NA, NA, NA, NA, NA),
+ PINGROUP(13, pri_mi2s, NA, qdss_stm18, qdss13, NA, NA, NA, NA, NA),
+ PINGROUP(14, pri_mi2s, NA, NA, qdss_stm17, qdss14, bimc_dte0,
+ native_tsens, vsense_trigger, NA),
+ PINGROUP(15, pri_mi2s, NA, NA, qdss_stm16, qdss15, NA, NA, bimc_dte1,
+ NA),
+ PINGROUP(16, sec_mi2s, blsp_spi4, blsp_uart4, qdss_cti, qdss_cti, NA,
+ NA, qdss_stm27, qdss8),
+ PINGROUP(17, sec_mi2s, blsp_spi4, blsp_uart4, qdss_cti, qdss_cti, NA,
+ qdss_stm26, qdss9, NA),
+ PINGROUP(18, sec_mi2s, blsp_spi4, blsp_uart4, blsp_i2c4, gcc_gp1, NA,
+ qdss_stm25, qdss10, NA),
+ PINGROUP(19, sec_mi2s, blsp_spi4, blsp_uart4, blsp_i2c4, jitter_bist,
+ gcc_gp2, NA, qdss_stm24, qdss11),
+ PINGROUP(20, sec_mi2s, ebi2_a, blsp_uart1, blsp_uart4, NA, qdss_stm3,
+ NA, NA, NA),
+ PINGROUP(21, sec_mi2s, ebi2_lcd, blsp_uart1, blsp_uart4, NA, NA,
+ qdss_stm2, NA, NA),
+ PINGROUP(22, sec_mi2s, ebi2_lcd, blsp_uart1, qdss_cti, qdss_cti,
+ blsp_uart4, pll_bist, NA, qdss_stm1),
+ PINGROUP(23, sec_mi2s, ebi2_lcd, qdss_cti, qdss_cti, blsp_uart1,
+ blsp_uart4, NA, qdss_stm0, NA),
+ PINGROUP(24, adsp_ext, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(25, m_voc, adsp_ext, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(26, NA, NA, NA, native_char, NA, NA, NA, NA, NA),
+ PINGROUP(27, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(28, wmss_reset, native_char3, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(29, NA, NA, nav_pps, nav_dr, NA, native_char2, native_tsense,
+ NA, NA),
+ PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(31, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(32, NA, native_char1, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(33, NA, pa_indicator, qdss_traceclk, native_char0, NA, NA, NA,
+ NA, NA),
+ PINGROUP(34, qlink_en, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(35, qlink_req, pll_test, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(36, NA, NA, cri_trng, NA, NA, NA, NA, NA, NA),
+ PINGROUP(37, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(38, NA, NA, prng_rosc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(40, NA, NA, cri_trng0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, NA, NA, cri_trng1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(42, nav_pps, NA, nav_dr, pll_ref, NA, NA, NA, NA, NA),
+ PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(44, coex_uart, NA, qdss_stm11, NA, NA, NA, NA, NA, NA),
+ PINGROUP(45, coex_uart, NA, qdss_stm10, ddr_pxi0, NA, NA, NA, NA, NA),
+ PINGROUP(46, m_voc, ddr_bist, ddr_pxi0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(47, ddr_bist, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(48, ddr_bist, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(49, ddr_bist, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(50, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(51, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(52, blsp_spi2, blsp_spi1, blsp_spi3, blsp_spi4, NA, NA,
+ qdss_stm14, NA, NA),
+ PINGROUP(53, pci_e, NA, NA, qdss_stm13, NA, NA, NA, NA, NA),
+ PINGROUP(54, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(55, qdss_cti, qdss_cti, tgu_ch0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(56, pcie_clkreq, NA, qdss_stm9, NA, NA, NA, NA, NA, NA),
+ PINGROUP(57, NA, qdss_stm15, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(58, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(59, qdss_cti, m_voc, bimc_dte0, NA, NA, NA, NA, NA, NA),
+ PINGROUP(60, mgpi_clk, NA, qdss_stm12, qdss_tracectl, bimc_dte1, NA,
+ NA, NA, NA),
+ PINGROUP(61, qdss_cti, NA, m_voc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(62, i2s_mclk, nav_pps, nav_dr, audio_ref, blsp_spi1,
+ blsp_spi2, blsp_spi3, blsp_spi4, ldo_update),
+ PINGROUP(63, blsp_uart2, NA, qdss_stm7, qdss4, atest_char, NA, NA, NA,
+ NA),
+ PINGROUP(64, blsp_uart2, NA, qdss_stm6, qdss5, atest_char3, NA, NA, NA,
+ NA),
+ PINGROUP(65, blsp_uart2, blsp_i2c2, NA, qdss_stm5, qdss6, atest_char2,
+ NA, NA, NA),
+ PINGROUP(66, blsp_uart2, blsp_i2c2, NA, qdss_stm4, qdss7, atest_char1,
+ NA, NA, NA),
+ PINGROUP(67, uim1_data, atest_char0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(68, uim1_present, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(69, uim1_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(71, mgpi_clk, blsp_spi1, blsp_spi2, blsp_spi3, blsp_spi4,
+ dbg_out, NA, NA, NA),
+ PINGROUP(72, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, NA, blsp_spi1, NA, gcc_plltest, NA, NA, NA, NA, NA),
+ PINGROUP(74, NA, blsp_spi1, NA, blsp_i2c1, gcc_plltest, NA, NA, NA, NA),
+ PINGROUP(75, NA, blsp_spi1, NA, blsp_i2c1, NA, NA, NA, NA, NA),
+ PINGROUP(76, blsp_i2c4, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(77, blsp_i2c4, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(81, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(82, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(83, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(84, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(85, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(87, NA, NA, usb2phy_ac, NA, NA, NA, NA, NA, NA),
+ PINGROUP(88, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(89, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(90, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(91, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(92, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(93, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(94, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(95, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(96, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(97, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(98, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x9a000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x9a000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x9a000, 9, 0),
+};
+
+static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
+ .pins = sdxpoorwills_pins,
+ .npins = ARRAY_SIZE(sdxpoorwills_pins),
+ .functions = sdxpoorwills_functions,
+ .nfunctions = ARRAY_SIZE(sdxpoorwills_functions),
+ .groups = sdxpoorwills_groups,
+ .ngroups = ARRAY_SIZE(sdxpoorwills_groups),
+ .ngpios = 100,
+};
+
+static int sdxpoorwills_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &sdxpoorwills_pinctrl);
+}
+
+static const struct of_device_id sdxpoorwills_pinctrl_of_match[] = {
+ { .compatible = "qcom,sdxpoorwills-pinctrl", },
+ { },
+};
+
+static struct platform_driver sdxpoorwills_pinctrl_driver = {
+ .driver = {
+ .name = "sdxpoorwills-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = sdxpoorwills_pinctrl_of_match,
+ },
+ .probe = sdxpoorwills_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init sdxpoorwills_pinctrl_init(void)
+{
+ return platform_driver_register(&sdxpoorwills_pinctrl_driver);
+}
+arch_initcall(sdxpoorwills_pinctrl_init);
+
+static void __exit sdxpoorwills_pinctrl_exit(void)
+{
+ platform_driver_unregister(&sdxpoorwills_pinctrl_driver);
+}
+module_exit(sdxpoorwills_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI sdxpoorwills pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, sdxpoorwills_pinctrl_of_match);
diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c
index b1d1dfa..f5e23c68 100644
--- a/drivers/platform/msm/gsi/gsi_dbg.c
+++ b/drivers/platform/msm/gsi/gsi_dbg.c
@@ -29,6 +29,7 @@
static struct dentry *dent;
static char dbg_buff[4096];
+static void *gsi_ipc_logbuf_low;
static void gsi_wq_print_dp_stats(struct work_struct *work);
static DECLARE_DELAYED_WORK(gsi_print_dp_stats_work, gsi_wq_print_dp_stats);
@@ -758,22 +759,20 @@
if (kstrtos8(dbg_buff, 0, &option))
return -EFAULT;
+ mutex_lock(&gsi_ctx->mlock);
if (option) {
- if (!gsi_ctx->ipc_logbuf_low) {
- gsi_ctx->ipc_logbuf_low =
+ if (!gsi_ipc_logbuf_low) {
+ gsi_ipc_logbuf_low =
ipc_log_context_create(GSI_IPC_LOG_PAGES,
"gsi_low", 0);
+ if (gsi_ipc_logbuf_low == NULL)
+ TERR("failed to get ipc_logbuf_low\n");
}
-
- if (gsi_ctx->ipc_logbuf_low == NULL) {
- TERR("failed to get ipc_logbuf_low\n");
- return -EFAULT;
- }
+ gsi_ctx->ipc_logbuf_low = gsi_ipc_logbuf_low;
} else {
- if (gsi_ctx->ipc_logbuf_low)
- ipc_log_context_destroy(gsi_ctx->ipc_logbuf_low);
gsi_ctx->ipc_logbuf_low = NULL;
}
+ mutex_unlock(&gsi_ctx->mlock);
return count;
}
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index d45fa51..a37947b 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -126,6 +126,7 @@
__stringify(IPA_CLIENT_Q6_DECOMP_PROD),
__stringify(IPA_CLIENT_Q6_DECOMP2_PROD),
__stringify(IPA_CLIENT_UC_USB_PROD),
+ __stringify(IPA_CLIENT_ETHERNET_PROD),
/* Below PROD client type is only for test purpose */
__stringify(IPA_CLIENT_TEST_PROD),
@@ -164,6 +165,7 @@
__stringify(IPA_CLIENT_Q6_DECOMP_CONS),
__stringify(IPA_CLIENT_Q6_DECOMP2_CONS),
__stringify(IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS),
+ __stringify(IPA_CLIENT_ETHERNET_CONS),
/* Below CONS client type is only for test purpose */
__stringify(IPA_CLIENT_TEST_CONS),
__stringify(IPA_CLIENT_TEST1_CONS),
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 15bb7b4..af4d4c8 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -1584,6 +1584,7 @@
struct ipa_hw_imm_cmd_dma_shared_mem *cmd = NULL;
struct ipa_desc desc;
struct ipa_mem_buffer mem;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
int rc;
if (memory_region_size == 0)
@@ -1603,7 +1604,7 @@
memset(mem.base, 0, mem.size);
cmd = kzalloc(sizeof(*cmd),
- GFP_KERNEL);
+ flag);
if (cmd == NULL) {
IPAERR("Failed to alloc immediate command object\n");
rc = -ENOMEM;
@@ -2166,6 +2167,7 @@
struct ipa_hw_imm_cmd_dma_shared_mem *cmd = NULL;
struct ipa_desc desc = {0};
struct ipa_mem_buffer mem;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
int rc = 0;
phys_addr = ipa_ctx->ipa_wrapper_base +
@@ -2203,7 +2205,7 @@
}
memset(mem.base, 0, mem.size);
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ cmd = kzalloc(sizeof(*cmd), flag);
if (cmd == NULL) {
IPAERR("Failed to alloc immediate command object\n");
rc = -ENOMEM;
@@ -2314,6 +2316,7 @@
struct ipa_desc desc = { 0 };
struct ipa_mem_buffer mem;
struct ipa_hdr_init_local *cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
int rc = 0;
mem.size = IPA_MEM_PART(modem_hdr_size) + IPA_MEM_PART(apps_hdr_size);
@@ -2325,7 +2328,7 @@
}
memset(mem.base, 0, mem.size);
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ cmd = kzalloc(sizeof(*cmd), flag);
if (cmd == NULL) {
IPAERR("Failed to alloc header init command object\n");
rc = -ENOMEM;
@@ -2360,6 +2363,7 @@
struct ipa_mem_buffer mem;
struct ipa_hdr_init_local *cmd = NULL;
struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
mem.size = IPA_MEM_PART(modem_hdr_size) + IPA_MEM_PART(apps_hdr_size);
mem.base = dma_alloc_coherent(ipa_ctx->pdev, mem.size, &mem.phys_base,
@@ -2370,7 +2374,7 @@
}
memset(mem.base, 0, mem.size);
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ cmd = kzalloc(sizeof(*cmd), flag);
if (cmd == NULL) {
IPAERR("Failed to alloc header init command object\n");
dma_free_coherent(ipa_ctx->pdev, mem.size, mem.base,
@@ -2411,7 +2415,7 @@
memset(mem.base, 0, mem.size);
memset(&desc, 0, sizeof(desc));
- dma_cmd = kzalloc(sizeof(*dma_cmd), GFP_KERNEL);
+ dma_cmd = kzalloc(sizeof(*dma_cmd), flag);
if (dma_cmd == NULL) {
IPAERR("Failed to alloc immediate command object\n");
dma_free_coherent(ipa_ctx->pdev,
@@ -2462,6 +2466,7 @@
struct ipa_desc desc = { 0 };
struct ipa_mem_buffer mem;
struct ipa_ip_v4_routing_init *v4_cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
u32 *entry;
int i;
int rc = 0;
@@ -2486,7 +2491,7 @@
entry++;
}
- v4_cmd = kzalloc(sizeof(*v4_cmd), GFP_KERNEL);
+ v4_cmd = kzalloc(sizeof(*v4_cmd), flag);
if (v4_cmd == NULL) {
IPAERR("Failed to alloc v4 routing init command object\n");
rc = -ENOMEM;
@@ -2522,6 +2527,7 @@
struct ipa_desc desc = { 0 };
struct ipa_mem_buffer mem;
struct ipa_ip_v6_routing_init *v6_cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
u32 *entry;
int i;
int rc = 0;
@@ -2546,7 +2552,7 @@
entry++;
}
- v6_cmd = kzalloc(sizeof(*v6_cmd), GFP_KERNEL);
+ v6_cmd = kzalloc(sizeof(*v6_cmd), flag);
if (v6_cmd == NULL) {
IPAERR("Failed to alloc v6 routing init command object\n");
rc = -ENOMEM;
@@ -2582,6 +2588,7 @@
struct ipa_desc desc = { 0 };
struct ipa_mem_buffer mem;
struct ipa_ip_v4_filter_init *v4_cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
u32 *entry;
int i;
int rc = 0;
@@ -2604,7 +2611,7 @@
entry++;
}
- v4_cmd = kzalloc(sizeof(*v4_cmd), GFP_KERNEL);
+ v4_cmd = kzalloc(sizeof(*v4_cmd), flag);
if (v4_cmd == NULL) {
IPAERR("Failed to alloc v4 fliter init command object\n");
rc = -ENOMEM;
@@ -2640,6 +2647,7 @@
struct ipa_desc desc = { 0 };
struct ipa_mem_buffer mem;
struct ipa_ip_v6_filter_init *v6_cmd = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
u32 *entry;
int i;
int rc = 0;
@@ -2662,7 +2670,7 @@
entry++;
}
- v6_cmd = kzalloc(sizeof(*v6_cmd), GFP_KERNEL);
+ v6_cmd = kzalloc(sizeof(*v6_cmd), flag);
if (v6_cmd == NULL) {
IPAERR("Failed to alloc v6 fliter init command object\n");
rc = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 3dca3e6..ff47863 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -322,8 +322,8 @@
dma_address = desc->dma_address;
tx_pkt->no_unmap_dma = true;
}
- if (!dma_address) {
- IPAERR("failed to DMA wrap\n");
+ if (dma_mapping_error(ipa_ctx->pdev, dma_address)) {
+ IPAERR("dma_map_single failed\n");
goto fail_dma_map;
}
@@ -445,7 +445,7 @@
}
dma_addr = dma_map_single(ipa_ctx->pdev,
transfer.iovec, size, DMA_TO_DEVICE);
- if (!dma_addr) {
+ if (dma_mapping_error(ipa_ctx->pdev, dma_addr)) {
IPAERR("dma_map_single failed for sps xfr buff\n");
kfree(transfer.iovec);
return -EFAULT;
@@ -493,6 +493,15 @@
tx_pkt->mem.base,
tx_pkt->mem.size,
DMA_TO_DEVICE);
+
+ if (dma_mapping_error(ipa_ctx->pdev,
+ tx_pkt->mem.phys_base)) {
+ IPAERR("dma_map_single ");
+ IPAERR("failed\n");
+ fail_dma_wrap = 1;
+ goto failure;
+ }
+
} else {
tx_pkt->mem.phys_base = desc[i].dma_address;
tx_pkt->no_unmap_dma = true;
@@ -1873,8 +1882,8 @@
rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
sys->rx_buff_sz,
DMA_FROM_DEVICE);
- if (rx_pkt->data.dma_addr == 0 ||
- rx_pkt->data.dma_addr == ~0) {
+ if (dma_mapping_error(ipa_ctx->pdev,
+ rx_pkt->data.dma_addr)) {
pr_err_ratelimited("%s dma map fail %p for %p sys=%p\n",
__func__, (void *)rx_pkt->data.dma_addr,
ptr, sys);
@@ -2029,8 +2038,8 @@
ptr = skb_put(rx_pkt->data.skb, IPA_WLAN_RX_BUFF_SZ);
rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
IPA_WLAN_RX_BUFF_SZ, DMA_FROM_DEVICE);
- if (rx_pkt->data.dma_addr == 0 ||
- rx_pkt->data.dma_addr == ~0) {
+ if (dma_mapping_error(ipa_ctx->pdev,
+ rx_pkt->data.dma_addr)) {
IPAERR("dma_map_single failure %p for %p\n",
(void *)rx_pkt->data.dma_addr, ptr);
goto fail_dma_mapping;
@@ -2101,8 +2110,8 @@
rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
sys->rx_buff_sz,
DMA_FROM_DEVICE);
- if (rx_pkt->data.dma_addr == 0 ||
- rx_pkt->data.dma_addr == ~0) {
+ if (dma_mapping_error(ipa_ctx->pdev,
+ rx_pkt->data.dma_addr)) {
IPAERR("dma_map_single failure %p for %p\n",
(void *)rx_pkt->data.dma_addr, ptr);
goto fail_dma_mapping;
@@ -2159,9 +2168,10 @@
ptr = skb_put(rx_pkt->data.skb, sys->rx_buff_sz);
rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev,
ptr, sys->rx_buff_sz, DMA_FROM_DEVICE);
- if (rx_pkt->data.dma_addr == 0 ||
- rx_pkt->data.dma_addr == ~0)
+ if (dma_mapping_error(ipa_ctx->pdev, rx_pkt->data.dma_addr)) {
+ IPAERR("dma_map_single failure for rx_pkt\n");
goto fail_dma_mapping;
+ }
list_add_tail(&rx_pkt->link, &sys->head_desc_list);
rx_len_cached = ++sys->len;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 25f8923..046f77f 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -268,6 +268,7 @@
struct ipa_mem_buffer mem;
struct ipa_hdr_init_system *cmd = NULL;
struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd = NULL;
+ gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
int rc = -EFAULT;
if (ipa_generate_hdr_hw_tbl(&mem)) {
@@ -281,7 +282,7 @@
IPA_MEM_PART(apps_hdr_size));
goto fail_send_cmd;
} else {
- dma_cmd = kzalloc(sizeof(*dma_cmd), GFP_ATOMIC);
+ dma_cmd = kzalloc(sizeof(*dma_cmd), flag);
if (dma_cmd == NULL) {
IPAERR("fail to alloc immediate cmd\n");
rc = -ENOMEM;
@@ -303,7 +304,7 @@
IPA_MEM_PART(apps_hdr_size_ddr));
goto fail_send_cmd;
} else {
- cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+ cmd = kzalloc(sizeof(*cmd), flag);
if (cmd == NULL) {
IPAERR("fail to alloc hdr init cmd\n");
rc = -ENOMEM;
@@ -359,6 +360,7 @@
struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd_hdr = NULL;
struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd_ctx = NULL;
struct ipa_register_write *reg_write_cmd = NULL;
+ gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
int rc = -EFAULT;
u32 proc_ctx_size;
u32 proc_ctx_ofst;
@@ -383,7 +385,7 @@
IPA_MEM_PART(apps_hdr_size));
goto fail_send_cmd1;
} else {
- dma_cmd_hdr = kzalloc(sizeof(*dma_cmd_hdr), GFP_ATOMIC);
+ dma_cmd_hdr = kzalloc(sizeof(*dma_cmd_hdr), flag);
if (dma_cmd_hdr == NULL) {
IPAERR("fail to alloc immediate cmd\n");
rc = -ENOMEM;
@@ -406,7 +408,7 @@
goto fail_send_cmd1;
} else {
hdr_init_cmd = kzalloc(sizeof(*hdr_init_cmd),
- GFP_ATOMIC);
+ flag);
if (hdr_init_cmd == NULL) {
IPAERR("fail to alloc immediate cmd\n");
rc = -ENOMEM;
@@ -431,7 +433,7 @@
goto fail_send_cmd1;
} else {
dma_cmd_ctx = kzalloc(sizeof(*dma_cmd_ctx),
- GFP_ATOMIC);
+ flag);
if (dma_cmd_ctx == NULL) {
IPAERR("fail to alloc immediate cmd\n");
rc = -ENOMEM;
@@ -456,7 +458,7 @@
goto fail_send_cmd1;
} else {
reg_write_cmd = kzalloc(sizeof(*reg_write_cmd),
- GFP_ATOMIC);
+ flag);
if (reg_write_cmd == NULL) {
IPAERR("fail to alloc immediate cmd\n");
rc = -ENOMEM;
@@ -722,6 +724,11 @@
entry->hdr,
entry->hdr_len,
DMA_TO_DEVICE);
+ if (dma_mapping_error(ipa_ctx->pdev,
+ entry->phys_base)) {
+ IPAERR("dma_map_single failure for entry\n");
+ goto fail_dma_mapping;
+ }
}
} else {
entry->is_hdr_proc_ctx = false;
@@ -798,6 +805,8 @@
list_del(&entry->link);
dma_unmap_single(ipa_ctx->pdev, entry->phys_base,
entry->hdr_len, DMA_TO_DEVICE);
+fail_dma_mapping:
+ entry->is_hdr_proc_ctx = false;
bad_hdr_len:
entry->cookie = 0;
kmem_cache_free(ipa_ctx->hdr_cache, entry);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 84849a2..21fdec0 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -695,6 +695,7 @@
struct ipa_mem_buffer head;
struct ipa_hw_imm_cmd_dma_shared_mem *cmd1 = NULL;
struct ipa_hw_imm_cmd_dma_shared_mem *cmd2 = NULL;
+ gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
u16 avail;
u32 num_modem_rt_index;
int rc = 0;
@@ -745,7 +746,7 @@
}
cmd1 = kzalloc(sizeof(struct ipa_hw_imm_cmd_dma_shared_mem),
- GFP_KERNEL);
+ flag);
if (cmd1 == NULL) {
IPAERR("Failed to alloc immediate command object\n");
rc = -ENOMEM;
@@ -762,7 +763,7 @@
if (lcl) {
cmd2 = kzalloc(sizeof(struct ipa_hw_imm_cmd_dma_shared_mem),
- GFP_KERNEL);
+ flag);
if (cmd2 == NULL) {
IPAERR("Failed to alloc immediate command object\n");
rc = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index 0af9387..4672233 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -1541,6 +1541,9 @@
memcpy(mux_channel[rmnet_index].vchannel_name,
extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
sizeof(mux_channel[rmnet_index].vchannel_name));
+ mux_channel[rmnet_index].vchannel_name[
+ IFNAMSIZ - 1] = '\0';
+
IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n",
mux_channel[rmnet_index].vchannel_name,
mux_channel[rmnet_index].mux_id,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 5fd6dcc..83fd2b2 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2268,6 +2268,36 @@
desc[num_descs].len = cmd_pyld->len;
num_descs++;
}
+
+ /* disable statuses for modem producers */
+ if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
+ ipa_assert_on(num_descs >= ipa3_ctx->ipa_num_pipes);
+
+ reg_write.skip_pipeline_clear = false;
+ reg_write.pipeline_clear_options =
+ IPAHAL_HPS_CLEAR;
+ reg_write.offset =
+ ipahal_get_reg_n_ofst(IPA_ENDP_STATUS_n,
+ ep_idx);
+ reg_write.value = 0;
+ reg_write.value_mask = ~0;
+ cmd_pyld = ipahal_construct_imm_cmd(
+ IPA_IMM_CMD_REGISTER_WRITE, ®_write, false);
+ if (!cmd_pyld) {
+ IPAERR("fail construct register_write cmd\n");
+ ipa_assert();
+ return -EFAULT;
+ }
+
+ desc[num_descs].opcode = ipahal_imm_cmd_get_opcode(
+ IPA_IMM_CMD_REGISTER_WRITE);
+ desc[num_descs].type = IPA_IMM_CMD_DESC;
+ desc[num_descs].callback = ipa3_destroy_imm;
+ desc[num_descs].user1 = cmd_pyld;
+ desc[num_descs].pyld = cmd_pyld->data;
+ desc[num_descs].len = cmd_pyld->len;
+ num_descs++;
+ }
}
/* Will wait 500msecs for IPA tag process completion */
@@ -2367,11 +2397,11 @@
}
/**
- * _ipa_init_sram_v3_0() - Initialize IPA local SRAM.
+ * _ipa_init_sram_v3() - Initialize IPA local SRAM.
*
* Return codes: 0 for success, negative value for failure
*/
-int _ipa_init_sram_v3_0(void)
+int _ipa_init_sram_v3(void)
{
u32 *ipa_sram_mmio;
unsigned long phys_addr;
@@ -2414,7 +2444,10 @@
IPA_MEM_PART(modem_hdr_proc_ctx_ofst));
ipa3_sram_set_canary(ipa_sram_mmio, IPA_MEM_PART(modem_ofst) - 4);
ipa3_sram_set_canary(ipa_sram_mmio, IPA_MEM_PART(modem_ofst));
- ipa3_sram_set_canary(ipa_sram_mmio, IPA_MEM_PART(end_ofst));
+ ipa3_sram_set_canary(ipa_sram_mmio,
+ (ipa_get_hw_type() >= IPA_HW_v3_5) ?
+ IPA_MEM_PART(uc_event_ring_ofst) :
+ IPA_MEM_PART(end_ofst));
iounmap(ipa_sram_mmio);
@@ -4064,6 +4097,7 @@
cdev_del(&ipa3_ctx->cdev);
device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
unregister_chrdev_region(ipa3_ctx->dev_num, 1);
+ ipa3_free_dma_task_for_gsi();
ipa3_destroy_flt_tbl_idrs();
idr_destroy(&ipa3_ctx->ipa_idr);
kmem_cache_destroy(ipa3_ctx->rx_pkt_wrapper_cache);
@@ -4604,6 +4638,13 @@
goto fail_rx_pkt_wrapper_cache;
}
+ /* allocate memory for DMA_TASK workaround */
+ result = ipa3_allocate_dma_task_for_gsi();
+ if (result) {
+ IPAERR("failed to allocate dma task\n");
+ goto fail_dma_task;
+ }
+
/* init the various list heads */
INIT_LIST_HEAD(&ipa3_ctx->hdr_tbl.head_hdr_entry_list);
for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
@@ -4744,6 +4785,8 @@
fail_device_create:
unregister_chrdev_region(ipa3_ctx->dev_num, 1);
fail_alloc_chrdev_region:
+ ipa3_free_dma_task_for_gsi();
+fail_dma_task:
idr_destroy(&ipa3_ctx->ipa_idr);
kmem_cache_destroy(ipa3_ctx->rx_pkt_wrapper_cache);
fail_rx_pkt_wrapper_cache:
@@ -5488,13 +5531,6 @@
return result;
}
- result = of_platform_populate(pdev_p->dev.of_node,
- pdrv_match, NULL, &pdev_p->dev);
- if (result) {
- IPAERR("failed to populate platform\n");
- return result;
- }
-
if (of_property_read_bool(pdev_p->dev.of_node, "qcom,arm-smmu")) {
if (of_property_read_bool(pdev_p->dev.of_node,
"qcom,smmu-s1-bypass"))
@@ -5540,6 +5576,13 @@
}
}
+ result = of_platform_populate(pdev_p->dev.of_node,
+ pdrv_match, NULL, &pdev_p->dev);
+ if (result) {
+ IPAERR("failed to populate platform\n");
+ return result;
+ }
+
return result;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index a414029..ca77be9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -106,6 +106,7 @@
static char *active_clients_buf;
static s8 ep_reg_idx;
+static void *ipa_ipc_low_buff;
static ssize_t ipa3_read_gen_reg(struct file *file, char __user *ubuf,
@@ -1758,22 +1759,20 @@
if (kstrtos8(dbg_buff, 0, &option))
return -EFAULT;
+ mutex_lock(&ipa3_ctx->lock);
if (option) {
- if (!ipa3_ctx->logbuf_low) {
- ipa3_ctx->logbuf_low =
+ if (!ipa_ipc_low_buff) {
+ ipa_ipc_low_buff =
ipc_log_context_create(IPA_IPC_LOG_PAGES,
"ipa_low", 0);
}
-
- if (ipa3_ctx->logbuf_low == NULL) {
- IPAERR("failed to get logbuf_low\n");
- return -EFAULT;
- }
+ if (ipa_ipc_low_buff == NULL)
+ IPAERR("failed to get logbuf_low\n");
+ ipa3_ctx->logbuf_low = ipa_ipc_low_buff;
} else {
- if (ipa3_ctx->logbuf_low)
- ipc_log_context_destroy(ipa3_ctx->logbuf_low);
ipa3_ctx->logbuf_low = NULL;
}
+ mutex_unlock(&ipa3_ctx->lock);
return count;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 8261a26..3af4486 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -997,6 +997,11 @@
u32 size;
};
+struct ipa_dma_task_info {
+ struct ipa_mem_buffer mem;
+ struct ipahal_imm_cmd_pyld *cmd_pyld;
+};
+
/**
* struct ipa3_context - IPA context
* @class: pointer to the struct class
@@ -1206,6 +1211,7 @@
struct ipa3_smp2p_info smp2p_info;
u32 ipa_tz_unlock_reg_num;
struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
+ struct ipa_dma_task_info dma_task_info;
};
struct ipa3_plat_drv_res {
@@ -1240,7 +1246,9 @@
* Order and type of members should not be changed without a suitable change
* to DTS file or the code that reads it.
*
- * IPA v3.0 SRAM memory layout:
+ * IPA SRAM memory layout:
+ * +-------------------------+
+ * | UC MEM |
* +-------------------------+
* | UC INFO |
* +-------------------------+
@@ -1308,10 +1316,14 @@
* +-------------------------+
* | CANARY |
* +-------------------------+
+ * | CANARY |
+ * +-------------------------+
* | MODEM MEM |
* +-------------------------+
* | CANARY |
* +-------------------------+
+ * | UC EVENT RING | From IPA 3.5
+ * +-------------------------+
*/
struct ipa3_mem_partition {
u32 ofst_start;
@@ -1384,6 +1396,8 @@
u32 apps_v6_rt_hash_size;
u32 apps_v6_rt_nhash_ofst;
u32 apps_v6_rt_nhash_size;
+ u32 uc_event_ring_ofst;
+ u32 uc_event_ring_size;
};
struct ipa3_controller {
@@ -1838,7 +1852,7 @@
int ipa3_teth_bridge_driver_init(void);
void ipa3_lan_rx_cb(void *priv, enum ipa_dp_evt_type evt, unsigned long data);
-int _ipa_init_sram_v3_0(void);
+int _ipa_init_sram_v3(void);
int _ipa_init_hdr_v3_0(void);
int _ipa_init_rt4_v3(void);
int _ipa_init_rt6_v3(void);
@@ -1982,4 +1996,6 @@
void ipa3_enable_dcd(void);
void ipa3_disable_prefetch(enum ipa_client_type client);
int ipa3_alloc_common_event_ring(void);
+int ipa3_allocate_dma_task_for_gsi(void);
+void ipa3_free_dma_task_for_gsi(void);
#endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index db3d6a4..5a38db3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -2909,17 +2909,54 @@
*/
int ipa3_init_mem_partition(struct device_node *node)
{
+ const size_t ram_mmap_v3_0_size = 70;
+ const size_t ram_mmap_v3_5_size = 72;
+ const size_t ram_mmap_current_version_size =
+ sizeof(ipa3_ctx->ctrl->mem_partition) / sizeof(u32);
+ const size_t version = ipa_get_hw_type();
int result;
IPADBG("Reading from DTS as u32 array\n");
- result = of_property_read_u32_array(node,
- "qcom,ipa-ram-mmap", (u32 *)&ipa3_ctx->ctrl->mem_partition,
- sizeof(ipa3_ctx->ctrl->mem_partition) / sizeof(u32));
- if (result) {
+ /*
+ * The size of ipa-ram-mmap array depends on the IPA version. The
+ * actual size can't be assumed because of possible DTS versions
+ * mismatch. The size of the array monotonically increasing because the
+ * obsolete entries are set to zero rather than deleted, so the
+ * possible sizes are in range
+ * [ram_mmap_v3_0_size, ram_mmap_current_version_size]
+ */
+ result = of_property_read_variable_u32_array(node, "qcom,ipa-ram-mmap",
+ (u32 *)&ipa3_ctx->ctrl->mem_partition,
+ ram_mmap_v3_0_size, ram_mmap_current_version_size);
+
+ if (result <= 0) {
IPAERR("Read operation failed\n");
return -ENODEV;
}
+ if (version < IPA_HW_v3_0)
+ ipa_assert();
+ if (version < IPA_HW_v3_5) {
+ if (result != ram_mmap_v3_0_size) {
+ IPAERR("Mismatch at IPA RAM MMAP DTS entry\n");
+ return -ENODEV;
+ }
+ } else {
+ if (result != ram_mmap_v3_5_size) {
+ IPAERR("Mismatch at IPA RAM MMAP DTS entry\n");
+ return -ENODEV;
+ }
+
+ if (IPA_MEM_PART(uc_event_ring_ofst) & 1023) {
+ IPAERR("UC EVENT RING OFST 0x%x is unaligned\n",
+ IPA_MEM_PART(uc_event_ring_ofst));
+ return -ENODEV;
+ }
+
+ IPADBG("UC EVENT RING OFST 0x%x SIZE 0x%x\n",
+ IPA_MEM_PART(uc_event_ring_ofst),
+ IPA_MEM_PART(uc_event_ring_size));
+ }
IPADBG("NAT OFST 0x%x SIZE 0x%x\n", IPA_MEM_PART(nat_ofst),
IPA_MEM_PART(nat_size));
@@ -3167,7 +3204,7 @@
ctrl->clock_scaling_bw_threshold_turbo =
IPA_V3_0_BW_THRESHOLD_TURBO_MBPS;
ctrl->ipa_reg_base_ofst = ipahal_get_reg_base();
- ctrl->ipa_init_sram = _ipa_init_sram_v3_0;
+ ctrl->ipa_init_sram = _ipa_init_sram_v3;
ctrl->ipa_sram_read_settings = _ipa_sram_settings_read_v3_0;
ctrl->ipa_init_hdr = _ipa_init_hdr_v3_0;
@@ -4216,6 +4253,51 @@
}
}
+int ipa3_allocate_dma_task_for_gsi(void)
+{
+ struct ipahal_imm_cmd_dma_task_32b_addr cmd = { 0 };
+
+ IPADBG("Allocate mem\n");
+ ipa3_ctx->dma_task_info.mem.size = IPA_GSI_CHANNEL_STOP_PKT_SIZE;
+ ipa3_ctx->dma_task_info.mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
+ ipa3_ctx->dma_task_info.mem.size,
+ &ipa3_ctx->dma_task_info.mem.phys_base,
+ GFP_KERNEL);
+ if (!ipa3_ctx->dma_task_info.mem.base) {
+ IPAERR("no mem\n");
+ return -EFAULT;
+ }
+
+ cmd.flsh = 1;
+ cmd.size1 = ipa3_ctx->dma_task_info.mem.size;
+ cmd.addr1 = ipa3_ctx->dma_task_info.mem.phys_base;
+ cmd.packet_size = ipa3_ctx->dma_task_info.mem.size;
+ ipa3_ctx->dma_task_info.cmd_pyld = ipahal_construct_imm_cmd(
+ IPA_IMM_CMD_DMA_TASK_32B_ADDR, &cmd, false);
+ if (!ipa3_ctx->dma_task_info.cmd_pyld) {
+ IPAERR("failed to construct dma_task_32b_addr cmd\n");
+ dma_free_coherent(ipa3_ctx->pdev,
+ ipa3_ctx->dma_task_info.mem.size,
+ ipa3_ctx->dma_task_info.mem.base,
+ ipa3_ctx->dma_task_info.mem.phys_base);
+ memset(&ipa3_ctx->dma_task_info, 0,
+ sizeof(ipa3_ctx->dma_task_info));
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+void ipa3_free_dma_task_for_gsi(void)
+{
+ dma_free_coherent(ipa3_ctx->pdev,
+ ipa3_ctx->dma_task_info.mem.size,
+ ipa3_ctx->dma_task_info.mem.base,
+ ipa3_ctx->dma_task_info.mem.phys_base);
+ ipahal_destroy_imm_cmd(ipa3_ctx->dma_task_info.cmd_pyld);
+ memset(&ipa3_ctx->dma_task_info, 0, sizeof(ipa3_ctx->dma_task_info));
+}
+
/**
* ipa3_inject_dma_task_for_gsi()- Send DMA_TASK to IPA for GSI stop channel
*
@@ -4224,41 +4306,12 @@
*/
int ipa3_inject_dma_task_for_gsi(void)
{
- static struct ipa_mem_buffer mem = {0};
- struct ipahal_imm_cmd_dma_task_32b_addr cmd = {0};
- static struct ipahal_imm_cmd_pyld *cmd_pyld;
struct ipa3_desc desc = {0};
- /* allocate the memory only for the very first time */
- if (!mem.base) {
- IPADBG("Allocate mem\n");
- mem.size = IPA_GSI_CHANNEL_STOP_PKT_SIZE;
- mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
- mem.size,
- &mem.phys_base,
- GFP_KERNEL);
- if (!mem.base) {
- IPAERR("no mem\n");
- return -EFAULT;
- }
- }
- if (!cmd_pyld) {
- cmd.flsh = 1;
- cmd.size1 = mem.size;
- cmd.addr1 = mem.phys_base;
- cmd.packet_size = mem.size;
- cmd_pyld = ipahal_construct_imm_cmd(
- IPA_IMM_CMD_DMA_TASK_32B_ADDR, &cmd, false);
- if (!cmd_pyld) {
- IPAERR("failed to construct dma_task_32b_addr cmd\n");
- return -EFAULT;
- }
- }
-
desc.opcode = ipahal_imm_cmd_get_opcode_param(
IPA_IMM_CMD_DMA_TASK_32B_ADDR, 1);
- desc.pyld = cmd_pyld->data;
- desc.len = cmd_pyld->len;
+ desc.pyld = ipa3_ctx->dma_task_info.cmd_pyld->data;
+ desc.len = ipa3_ctx->dma_task_info.cmd_pyld->len;
desc.type = IPA_IMM_CMD_DESC;
IPADBG("sending 1B packet to IPA\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index cb25b09..56e7718 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1655,6 +1655,9 @@
extend_ioctl_data.u.rmnet_mux_val.vchannel_name,
sizeof(mux_channel[rmnet_index]
.vchannel_name));
+ mux_channel[rmnet_index].vchannel_name[
+ IFNAMSIZ - 1] = '\0';
+
IPAWANDBG("cashe device[%s:%d] in IPA_wan[%d]\n",
mux_channel[rmnet_index].vchannel_name,
mux_channel[rmnet_index].mux_id,
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index a66192f..c29b9b6 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1846,11 +1846,24 @@
return status;
}
+#define ACER_WMID_ACCEL_HID "BST0001"
+
static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level,
void *ctx, void **retval)
{
+ struct acpi_device *dev;
+
+ if (!strcmp(ctx, "SENR")) {
+ if (acpi_bus_get_device(ah, &dev))
+ return AE_OK;
+ if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev)))
+ return AE_OK;
+ } else
+ return AE_OK;
+
*(acpi_handle *)retval = ah;
- return AE_OK;
+
+ return AE_CTRL_TERMINATE;
}
static int __init acer_wmi_get_handle(const char *name, const char *prop,
@@ -1877,7 +1890,7 @@
{
int err;
- err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle);
+ err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle);
if (err)
return err;
@@ -2233,10 +2246,11 @@
err = acer_wmi_input_setup();
if (err)
return err;
+ err = acer_wmi_accel_setup();
+ if (err)
+ return err;
}
- acer_wmi_accel_setup();
-
err = platform_driver_register(&acer_platform_driver);
if (err) {
pr_err("Unable to register platform driver\n");
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index efcc4e8..9f04957 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -28,6 +28,7 @@
#include <asm/cacheflush.h>
#include <asm/system_misc.h>
+#include <asm/memory.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/restart.h>
@@ -57,11 +58,17 @@
#ifdef CONFIG_QCOM_DLOAD_MODE
#define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
#define DL_MODE_PROP "qcom,msm-imem-download_mode"
+#ifdef CONFIG_RANDOMIZE_BASE
+#define KASLR_OFFSET_PROP "qcom,msm-imem-kaslr_offset"
+#endif
static int in_panic;
static void *dload_mode_addr;
static bool dload_mode_enabled;
static void *emergency_dload_mode_addr;
+#ifdef CONFIG_RANDOMIZE_BASE
+static void *kaslr_imem_addr;
+#endif
static bool scm_dload_supported;
static int dload_set(const char *val, struct kernel_param *kp);
@@ -420,6 +427,27 @@
pr_err("unable to map imem EDLOAD mode offset\n");
}
+#ifdef CONFIG_RANDOMIZE_BASE
+#define KASLR_OFFSET_BIT_MASK 0x00000000FFFFFFFF
+ np = of_find_compatible_node(NULL, NULL, KASLR_OFFSET_PROP);
+ if (!np) {
+ pr_err("unable to find DT imem KASLR_OFFSET node\n");
+ } else {
+ kaslr_imem_addr = of_iomap(np, 0);
+ if (!kaslr_imem_addr)
+ pr_err("unable to map imem KASLR offset\n");
+ }
+
+ if (kaslr_imem_addr && scm_is_secure_device()) {
+ __raw_writel(0xdead4ead, kaslr_imem_addr);
+ __raw_writel(KASLR_OFFSET_BIT_MASK &
+ (kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
+ __raw_writel(KASLR_OFFSET_BIT_MASK &
+ ((kimage_vaddr - KIMAGE_VADDR) >> 32),
+ kaslr_imem_addr + 8);
+ iounmap(kaslr_imem_addr);
+ }
+#endif
#endif
np = of_find_compatible_node(NULL, NULL,
"qcom,msm-imem-restart_reason");
@@ -484,4 +512,4 @@
{
return platform_driver_register(&msm_restart_driver);
}
-device_initcall(msm_restart_init);
+pure_initcall(msm_restart_init);
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index b985ecd..1f1c2aec 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -511,13 +511,14 @@
return 0;
}
-#define ICL_STEP_UV 25000
+#define ICL_STEP_UA 25000
static int usb_icl_vote_callback(struct votable *votable, void *data,
int icl_ua, const char *client)
{
int rc;
struct pl_data *chip = data;
union power_supply_propval pval = {0, };
+ bool rerun_aicl = false;
if (!chip->main_psy)
return 0;
@@ -543,22 +544,28 @@
}
/* rerun AICL if new ICL is above settled ICL */
- if (icl_ua > pval.intval) {
- /* set a lower ICL */
- pval.intval = max(pval.intval - ICL_STEP_UV, ICL_STEP_UV);
- power_supply_set_property(chip->main_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX,
- &pval);
- /* wait for ICL change */
- msleep(100);
+ if (icl_ua > pval.intval)
+ rerun_aicl = true;
- pval.intval = icl_ua;
+ if (rerun_aicl) {
+ /* set a lower ICL */
+ pval.intval = max(pval.intval - ICL_STEP_UA, ICL_STEP_UA);
power_supply_set_property(chip->main_psy,
POWER_SUPPLY_PROP_CURRENT_MAX,
&pval);
/* wait for ICL change */
msleep(100);
}
+
+ /* set the effective ICL */
+ pval.intval = icl_ua;
+ power_supply_set_property(chip->main_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ &pval);
+ if (rerun_aicl)
+ /* wait for ICL change */
+ msleep(100);
+
vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0);
return 0;
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index c74dc89..eb97eb0 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -89,7 +89,16 @@
#define QNOVO_STRM_CTRL 0xA8
#define QNOVO_IADC_OFFSET_OVR_VAL 0xA9
#define QNOVO_IADC_OFFSET_OVR 0xAA
+
#define QNOVO_DISABLE_CHARGING 0xAB
+#define ERR_SWITCHER_DISABLED BIT(7)
+#define ERR_JEITA_SOFT_CONDITION BIT(6)
+#define ERR_BAT_OV BIT(5)
+#define ERR_CV_MODE BIT(4)
+#define ERR_BATTERY_MISSING BIT(3)
+#define ERR_SAFETY_TIMER_EXPIRED BIT(2)
+#define ERR_CHARGING_DISABLED BIT(1)
+#define ERR_JEITA_HARD_CONDITION BIT(0)
#define QNOVO_TR_IADC_OFFSET_0 0xF1
#define QNOVO_TR_IADC_OFFSET_1 0xF2
@@ -1107,24 +1116,28 @@
{
u8 val = 0;
int rc;
- bool charging;
+ bool ok_to_qnovo;
bool changed = false;
rc = qnovo_read(chip, QNOVO_ERROR_STS2, &val, 1);
if (rc < 0) {
pr_err("Couldn't read error sts rc = %d\n", rc);
- charging = false;
+ ok_to_qnovo = false;
} else {
- charging = !(val & QNOVO_ERROR_CHARGING_DISABLED);
+ /*
+ * For CV mode keep qnovo enabled, userspace is expected to
+ * disable it after few runs
+ */
+ ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ? true : false;
}
- if (chip->ok_to_qnovo ^ charging) {
+ if (chip->ok_to_qnovo ^ ok_to_qnovo) {
- vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !charging, 0);
- if (!charging)
+ vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !ok_to_qnovo, 0);
+ if (!ok_to_qnovo)
vote(chip->disable_votable, USER_VOTER, true, 0);
- chip->ok_to_qnovo = charging;
+ chip->ok_to_qnovo = ok_to_qnovo;
changed = true;
}
@@ -1247,6 +1260,16 @@
chip->v_gain_mega = 1000000000 + (s64)(s8)vadc_gain * GAIN_LSB_FACTOR;
chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000);
+ /* allow charger error conditions to disable qnovo, CV mode excluded */
+ val = ERR_SWITCHER_DISABLED | ERR_JEITA_SOFT_CONDITION | ERR_BAT_OV |
+ ERR_BATTERY_MISSING | ERR_SAFETY_TIMER_EXPIRED |
+ ERR_CHARGING_DISABLED | ERR_JEITA_HARD_CONDITION;
+ rc = qnovo_write(chip, QNOVO_DISABLE_CHARGING, &val, 1);
+ if (rc < 0) {
+ pr_err("Couldn't write QNOVO_DISABLE_CHARGING rc = %d\n", rc);
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 8fd45f18..6f1dee8 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -2233,7 +2233,7 @@
rc = smblib_get_prop_batt_health(chg, &val);
if (rc < 0) {
pr_err("Couldn't get batt health rc=%d\n", rc);
- goto cleanup;
+ val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
}
batt_health = val.intval;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index c8deedd..a0606b8 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -1531,6 +1531,19 @@
break;
}
+ if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
+ return 0;
+
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ if (stat & (BAT_TEMP_STATUS_TOO_HOT_BIT | BAT_TEMP_STATUS_TOO_COLD_BIT))
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+
return 0;
}
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index 167666a..3f260a4 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -1025,4 +1025,14 @@
/* CHGR FREQ Peripheral registers */
#define FREQ_CLK_DIV_REG (CHGR_FREQ_BASE + 0x50)
+/* SMB1355 specific registers */
+#define SMB1355_TEMP_COMP_STATUS_REG (MISC_BASE + 0x07)
+#define SKIN_TEMP_RST_HOT_BIT BIT(6)
+#define SKIN_TEMP_UB_HOT_BIT BIT(5)
+#define SKIN_TEMP_LB_HOT_BIT BIT(4)
+#define DIE_TEMP_TSD_HOT_BIT BIT(3)
+#define DIE_TEMP_RST_HOT_BIT BIT(2)
+#define DIE_TEMP_UB_HOT_BIT BIT(1)
+#define DIE_TEMP_LB_HOT_BIT BIT(0)
+
#endif /* __SMB2_CHARGER_REG_H */
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index 0d1f2a6..b92a482 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -1655,7 +1655,7 @@
switch (prop) {
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
- val->intval = !chip->usb_suspended_status;
+ val->intval = !chip->parallel_charger_suspended;
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
if (!chip->parallel_charger_suspended)
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 83374bb..a29871b 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -104,6 +104,8 @@
struct smb_dt_props dt;
struct power_supply *parallel_psy;
u32 wa_flags;
+ struct pmic_revid_data *pmic_rev_id;
+ char *name;
};
static int __debug_mask;
@@ -167,6 +169,14 @@
if (rc < 0)
chip->dt.pl_mode = POWER_SUPPLY_PL_USBMID_USBMID;
+ /* check that smb1355 is configured to run in mid-mid mode */
+ if (chip->pmic_rev_id->pmic_subtype == SMB1355_SUBTYPE
+ && chip->dt.pl_mode != POWER_SUPPLY_PL_USBMID_USBMID) {
+ pr_err("Smb1355 can only run in MID-MID mode, saw = %d mode\n",
+ chip->dt.pl_mode);
+ return -EINVAL;
+ }
+
chip->dt.suspend_input = of_property_read_bool(node,
"qcom,suspend-input");
@@ -479,6 +489,30 @@
* PARALLEL PSY REGISTRATION *
*****************************/
+static int smb1355_get_prop_connector_health(struct smb138x *chip)
+{
+ struct smb_charger *chg = &chip->chg;
+ u8 temp;
+ int rc;
+
+ rc = smblib_read(chg, SMB1355_TEMP_COMP_STATUS_REG, &temp);
+ if (rc < 0) {
+ pr_err("Couldn't read comp stat reg rc = %d\n", rc);
+ return POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ if (temp & SKIN_TEMP_RST_HOT_BIT)
+ return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+ if (temp & SKIN_TEMP_UB_HOT_BIT)
+ return POWER_SUPPLY_HEALTH_HOT;
+
+ if (temp & SKIN_TEMP_LB_HOT_BIT)
+ return POWER_SUPPLY_HEALTH_WARM;
+
+ return POWER_SUPPLY_HEALTH_COOL;
+}
+
static int smb138x_get_prop_connector_health(struct smb138x *chip)
{
struct smb_charger *chg = &chip->chg;
@@ -536,16 +570,32 @@
POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
- POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
- POWER_SUPPLY_PROP_CURRENT_NOW,
- POWER_SUPPLY_PROP_CHARGER_TEMP,
- POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_PARALLEL_MODE,
POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
POWER_SUPPLY_PROP_SET_SHIP_MODE,
+ POWER_SUPPLY_PROP_CHARGER_TEMP,
+ POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
+static enum power_supply_property smb1355_parallel_props[] = {
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CHARGING_ENABLED,
+ POWER_SUPPLY_PROP_PIN_ENABLED,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_PARALLEL_MODE,
+ POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
+ POWER_SUPPLY_PROP_SET_SHIP_MODE,
+ POWER_SUPPLY_PROP_CHARGER_TEMP,
+ POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
};
static int smb138x_parallel_get_prop(struct power_supply *psy,
@@ -583,14 +633,6 @@
else
val->intval = 0;
break;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
- || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
- rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
- &val->intval);
- else
- val->intval = 0;
- break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
break;
@@ -598,28 +640,46 @@
rc = smblib_get_charge_param(chg, &chg->param.fcc,
&val->intval);
break;
- case POWER_SUPPLY_PROP_CURRENT_NOW:
- rc = smblib_get_prop_slave_current_now(chg, val);
- break;
- case POWER_SUPPLY_PROP_CHARGER_TEMP:
- rc = smb138x_get_prop_charger_temp(chip, val);
- break;
- case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
- rc = smblib_get_prop_charger_temp_max(chg, val);
- break;
case POWER_SUPPLY_PROP_MODEL_NAME:
- val->strval = "smb138x";
+ val->strval = chip->name;
break;
case POWER_SUPPLY_PROP_PARALLEL_MODE:
val->intval = chip->dt.pl_mode;
break;
case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
- val->intval = smb138x_get_prop_connector_health(chip);
+ if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+ val->intval = smb138x_get_prop_connector_health(chip);
+ else
+ val->intval = smb1355_get_prop_connector_health(chip);
break;
case POWER_SUPPLY_PROP_SET_SHIP_MODE:
/* Not in ship mode as long as device is active */
val->intval = 0;
break;
+ case POWER_SUPPLY_PROP_CHARGER_TEMP:
+ if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+ rc = smb138x_get_prop_charger_temp(chip, val);
+ else
+ rc = smblib_get_prop_charger_temp(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
+ rc = smblib_get_prop_charger_temp_max(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+ rc = smblib_get_prop_slave_current_now(chg, val);
+ else
+ rc = -ENODATA;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ if ((chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+ && ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+ || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)))
+ rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
+ &val->intval);
+ else
+ rc = -ENODATA;
+ break;
default:
pr_err("parallel power supply get prop %d not supported\n",
prop);
@@ -703,7 +763,7 @@
return 0;
}
-static const struct power_supply_desc parallel_psy_desc = {
+static struct power_supply_desc parallel_psy_desc = {
.name = "parallel",
.type = POWER_SUPPLY_TYPE_PARALLEL,
.properties = smb138x_parallel_props,
@@ -731,6 +791,28 @@
return 0;
}
+static int smb1355_init_parallel_psy(struct smb138x *chip)
+{
+ struct power_supply_config parallel_cfg = {};
+ struct smb_charger *chg = &chip->chg;
+
+ parallel_cfg.drv_data = chip;
+ parallel_cfg.of_node = chg->dev->of_node;
+
+ /* change to smb1355's property list */
+ parallel_psy_desc.properties = smb1355_parallel_props;
+ parallel_psy_desc.num_properties = ARRAY_SIZE(smb1355_parallel_props);
+ chip->parallel_psy = devm_power_supply_register(chg->dev,
+ ¶llel_psy_desc,
+ ¶llel_cfg);
+ if (IS_ERR(chip->parallel_psy)) {
+ pr_err("Couldn't register parallel power supply\n");
+ return PTR_ERR(chip->parallel_psy);
+ }
+
+ return 0;
+}
+
/******************************
* VBUS REGULATOR REGISTRATION *
******************************/
@@ -1050,7 +1132,6 @@
static int smb138x_setup_wa_flags(struct smb138x *chip)
{
- struct pmic_revid_data *pmic_rev_id;
struct device_node *revid_dev_node;
revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
@@ -1060,8 +1141,8 @@
return -EINVAL;
}
- pmic_rev_id = get_revid_data(revid_dev_node);
- if (IS_ERR_OR_NULL(pmic_rev_id)) {
+ chip->pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
/*
* the revid peripheral must be registered, any failure
* here only indicates that the rev-id module has not
@@ -1070,14 +1151,14 @@
return -EPROBE_DEFER;
}
- switch (pmic_rev_id->pmic_subtype) {
+ switch (chip->pmic_rev_id->pmic_subtype) {
case SMB1381_SUBTYPE:
- if (pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
+ if (chip->pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
chip->wa_flags |= OOB_COMP_WA_BIT;
break;
default:
pr_err("PMIC subtype %d not supported\n",
- pmic_rev_id->pmic_subtype);
+ chip->pmic_rev_id->pmic_subtype);
return -EINVAL;
}
@@ -1375,6 +1456,7 @@
chg->param = v1_params;
+ chip->name = "smb1381";
rc = smblib_init(chg);
if (rc < 0) {
pr_err("Couldn't initialize smblib rc=%d\n", rc);
@@ -1435,7 +1517,7 @@
return rc;
}
-static int smb138x_slave_probe(struct smb138x *chip)
+static int smb1355_slave_probe(struct smb138x *chip)
{
struct smb_charger *chg = &chip->chg;
int rc = 0;
@@ -1448,6 +1530,55 @@
goto cleanup;
}
+ rc = smb138x_parse_dt(chip);
+ if (rc < 0) {
+ pr_err("Couldn't parse device tree rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ rc = smb138x_init_slave_hw(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize hardware rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ rc = smb1355_init_parallel_psy(chip);
+ if (rc < 0) {
+ pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ rc = smb138x_determine_initial_slave_status(chip);
+ if (rc < 0) {
+ pr_err("Couldn't determine initial status rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ rc = smb138x_request_interrupts(chip);
+ if (rc < 0) {
+ pr_err("Couldn't request interrupts rc=%d\n", rc);
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ smblib_deinit(chg);
+ return rc;
+}
+
+static int smb1381_slave_probe(struct smb138x *chip)
+{
+ struct smb_charger *chg = &chip->chg;
+ int rc = 0;
+
+ chg->param = v1_params;
+
+ rc = smblib_init(chg);
+ if (rc < 0) {
+ pr_err("Couldn't initialize smblib rc=%d\n", rc);
+ goto cleanup;
+ }
chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max");
if (IS_ERR(chg->iio.temp_max_chan)) {
rc = PTR_ERR(chg->iio.temp_max_chan);
@@ -1515,25 +1646,71 @@
goto cleanup;
}
- return rc;
+ return 0;
cleanup:
smblib_deinit(chg);
- if (chip->parallel_psy)
- power_supply_unregister(chip->parallel_psy);
- if (chg->vbus_vreg && chg->vbus_vreg->rdev)
- regulator_unregister(chg->vbus_vreg->rdev);
return rc;
}
+static int slave_probe(struct smb138x *chip)
+{
+ struct device_node *revid_dev_node;
+ int rc = 0;
+
+ revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
+ "qcom,pmic-revid", 0);
+ if (!revid_dev_node) {
+ pr_err("Missing qcom,pmic-revid property\n");
+ return -EINVAL;
+ }
+
+ chip->pmic_rev_id = get_revid_data(revid_dev_node);
+ if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
+ /*
+ * the revid peripheral must be registered, any failure
+ * here only indicates that the rev-id module has not
+ * probed yet.
+ */
+ return -EPROBE_DEFER;
+ }
+
+ switch (chip->pmic_rev_id->pmic_subtype) {
+ case SMB1355_SUBTYPE:
+ chip->name = "smb1355";
+ rc = smb1355_slave_probe(chip);
+ break;
+ case SMB1381_SUBTYPE:
+ chip->name = "smb1381";
+ rc = smb1381_slave_probe(chip);
+ break;
+ default:
+ pr_err("Unsupported pmic subtype = 0x%02x\n",
+ chip->pmic_rev_id->pmic_subtype);
+ rc = -EINVAL;
+ }
+
+ if (rc < 0) {
+ if (rc != -EPROBE_DEFER)
+ pr_err("Couldn't probe SMB138X rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static const struct of_device_id match_table[] = {
{
- .compatible = "qcom,smb138x-charger",
- .data = (void *) PARALLEL_MASTER
+ .compatible = "qcom,smb138x-charger",
+ .data = (void *) PARALLEL_MASTER,
},
{
- .compatible = "qcom,smb138x-parallel-slave",
- .data = (void *) PARALLEL_SLAVE
+ .compatible = "qcom,smb138x-parallel-slave",
+ .data = (void *) PARALLEL_SLAVE,
+ },
+ {
+ .compatible = "qcom,smb1355-parallel-slave",
+ .data = (void *) PARALLEL_SLAVE,
},
{ },
};
@@ -1580,7 +1757,7 @@
rc = smb138x_master_probe(chip);
break;
case PARALLEL_SLAVE:
- rc = smb138x_slave_probe(chip);
+ rc = slave_probe(chip);
break;
default:
pr_err("Couldn't find a matching mode %d\n", chip->chg.mode);
@@ -1594,7 +1771,8 @@
goto cleanup;
}
- pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode);
+ pr_info("%s probed successfully mode=%d pl_mode = %d\n",
+ chip->name, chip->chg.mode, chip->dt.pl_mode);
return rc;
cleanup:
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index ef89df1..744d561 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -191,6 +191,28 @@
return 0;
}
+static int rockchip_pwm_enable(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ bool enable,
+ enum pwm_polarity polarity)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ int ret;
+
+ if (enable) {
+ ret = clk_enable(pc->clk);
+ if (ret)
+ return ret;
+ }
+
+ pc->data->set_enable(chip, pwm, enable, polarity);
+
+ if (!enable)
+ clk_disable(pc->clk);
+
+ return 0;
+}
+
static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
@@ -207,22 +229,26 @@
return ret;
if (state->polarity != curstate.polarity && enabled) {
- pc->data->set_enable(chip, pwm, false, state->polarity);
+ ret = rockchip_pwm_enable(chip, pwm, false, state->polarity);
+ if (ret)
+ goto out;
enabled = false;
}
ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period);
if (ret) {
if (enabled != curstate.enabled)
- pc->data->set_enable(chip, pwm, !enabled,
- state->polarity);
-
+ rockchip_pwm_enable(chip, pwm, !enabled,
+ state->polarity);
goto out;
}
- if (state->enabled != enabled)
- pc->data->set_enable(chip, pwm, state->enabled,
- state->polarity);
+ if (state->enabled != enabled) {
+ ret = rockchip_pwm_enable(chip, pwm, state->enabled,
+ state->polarity);
+ if (ret)
+ goto out;
+ }
/*
* Update the state with the real hardware, which can differ a bit
diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c
index 07a0aef..9566e24 100644
--- a/drivers/regulator/cpr3-regulator.c
+++ b/drivers/regulator/cpr3-regulator.c
@@ -1382,6 +1382,11 @@
(ctrl->use_dynamic_step_quot
? CPR4_MARGIN_ADJ_CTL_PER_RO_KV_MARGIN_EN : 0));
+ if (ctrl->thread_count > 1)
+ cpr3_masked_write(ctrl, CPR4_REG_CPR_TIMER_CLAMP,
+ CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN,
+ CPR4_CPR_TIMER_CLAMP_THREAD_AGGREGATION_EN);
+
if (ctrl->voltage_settling_time) {
/*
* Configure the settling timer used to account for
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index a93e7d8..b84d9f0 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -983,6 +983,9 @@
return -EINVAL;
}
+ vreg->fuse_corner_count = fuse_corners;
+ vreg->platform_fuses = fuse;
+
fuse->ro_sel = devm_kcalloc(vreg->thread->ctrl->dev, fuse_corners,
sizeof(*fuse->ro_sel), GFP_KERNEL);
fuse->init_voltage = devm_kcalloc(vreg->thread->ctrl->dev, fuse_corners,
@@ -1037,8 +1040,6 @@
vreg->speed_bin_fuse = fuse->speed_bin;
vreg->cpr_rev_fuse = fuse->cpr_fusing_rev;
- vreg->fuse_corner_count = fuse_corners;
- vreg->platform_fuses = fuse;
return 0;
}
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 3853ba9..19e03d0 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -18,6 +18,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <linux/kernel.h>
+#include <linux/clk.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -59,6 +60,7 @@
struct platform_device *pdev;
struct rtc_device *rtc_dev;
void __iomem *rtc_base; /* NULL if not initialized. */
+ struct clk *clk;
int tegra_rtc_irq; /* alarm and periodic irq */
spinlock_t tegra_rtc_lock;
};
@@ -326,6 +328,14 @@
if (info->tegra_rtc_irq <= 0)
return -EBUSY;
+ info->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(info->clk))
+ return PTR_ERR(info->clk);
+
+ ret = clk_prepare_enable(info->clk);
+ if (ret < 0)
+ return ret;
+
/* set context info. */
info->pdev = pdev;
spin_lock_init(&info->tegra_rtc_lock);
@@ -346,7 +356,7 @@
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Unable to register device (err=%d).\n",
ret);
- return ret;
+ goto disable_clk;
}
ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq,
@@ -356,12 +366,25 @@
dev_err(&pdev->dev,
"Unable to request interrupt for device (err=%d).\n",
ret);
- return ret;
+ goto disable_clk;
}
dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
return 0;
+
+disable_clk:
+ clk_disable_unprepare(info->clk);
+ return ret;
+}
+
+static int tegra_rtc_remove(struct platform_device *pdev)
+{
+ struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(info->clk);
+
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -413,6 +436,7 @@
MODULE_ALIAS("platform:tegra_rtc");
static struct platform_driver tegra_rtc_driver = {
+ .remove = tegra_rtc_remove,
.shutdown = tegra_rtc_shutdown,
.driver = {
.name = "tegra_rtc",
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4f361d8..734e592 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -968,8 +968,13 @@
uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
{
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
- return ((RD_REG_DWORD(®->host_status)) == ISP_REG_DISCONNECT);
+ if (IS_P3P_TYPE(ha))
+ return ((RD_REG_DWORD(®82->host_int)) == ISP_REG_DISCONNECT);
+ else
+ return ((RD_REG_DWORD(®->host_status)) ==
+ ISP_REG_DISCONNECT);
}
/**************************************************************************
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b7889c7..c2ac982 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1982,6 +1982,22 @@
#define READ_CAPACITY_RETRIES_ON_RESET 10
+/*
+ * Ensure that we don't overflow sector_t when CONFIG_LBDAF is not set
+ * and the reported logical block size is bigger than 512 bytes. Note
+ * that last_sector is a u64 and therefore logical_to_sectors() is not
+ * applicable.
+ */
+static bool sd_addressable_capacity(u64 lba, unsigned int sector_size)
+{
+ u64 last_sector = (lba + 1ULL) << (ilog2(sector_size) - 9);
+
+ if (sizeof(sector_t) == 4 && last_sector > U32_MAX)
+ return false;
+
+ return true;
+}
+
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
@@ -2047,7 +2063,7 @@
return -ENODEV;
}
- if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) {
+ if (!sd_addressable_capacity(lba, sector_size)) {
sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
"kernel compiled with support for large block "
"devices.\n");
@@ -2133,7 +2149,7 @@
return sector_size;
}
- if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
+ if (!sd_addressable_capacity(lba, sector_size)) {
sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
"kernel compiled with support for large block "
"devices.\n");
@@ -2780,7 +2796,8 @@
q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
} else
- rw_max = BLK_DEF_MAX_SECTORS;
+ rw_max = min_not_zero(logical_to_sectors(sdp, dev_max),
+ (sector_t)BLK_DEF_MAX_SECTORS);
/* Combine with controller limits */
q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q));
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index bed2bbd..e635973 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -833,6 +833,7 @@
unsigned char *buffer;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
+ unsigned int ms_len = 128;
int rc, n;
static const char *loadmech[] =
@@ -859,10 +860,11 @@
scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
/* ask for mode page 0x2a */
- rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,
+ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len,
SR_TIMEOUT, 3, &data, NULL);
- if (!scsi_status_is_good(rc)) {
+ if (!scsi_status_is_good(rc) || data.length > ms_len ||
+ data.header_length + data.block_descriptor_length > data.length) {
/* failed, drive doesn't have capabilities mode page */
cd->cdi.speed = 1;
cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 82c4acc..602c359 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -9415,10 +9415,11 @@
/* scale up to G3 now */
new_pwr_info.gear_tx = UFS_HS_G3;
new_pwr_info.gear_rx = UFS_HS_G3;
- ret = ufshcd_change_power_mode(hba, &new_pwr_info);
- if (ret)
- goto out;
+ /* now, fall through to set the HS-G3 */
}
+ ret = ufshcd_change_power_mode(hba, &new_pwr_info);
+ if (ret)
+ goto out;
} else {
memcpy(&new_pwr_info, &hba->pwr_info,
sizeof(struct ufs_pa_layer_attr));
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 0f8d9b6..69e3032 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -324,6 +324,17 @@
spcom provides clients/server API, although currently only one client
or server is allowed per logical channel.
+config MSM_SPSS_UTILS
+ depends on MSM_PIL
+ bool "Secure Processor Utilities"
+ help
+ spss-utils driver selects Secure Processor firmware file name.
+ The firmware file name for dev, test or production is selected
+ based on two fuses.
+ Different file name is used for differnt SPSS HW versions,
+ because the SPSS firmware size is too small to support multiple
+ HW versions.
+
config TRACER_PKT
bool "Tracer Packet"
help
@@ -634,3 +645,13 @@
This option enables driver for Data Capture and Compare engine. DCC
driver provides interface to configure DCC block and read back
captured data from DCC's internal SRAM.
+
+config QTI_RPM_STATS_LOG
+ bool "Qualcomm Technologies RPM Stats Driver"
+ depends on DEBUG_FS
+ default n
+ help
+ This option enables a driver which reads RPM messages from a shared
+ memory location. These messages provide statistical information about
+ the low power modes that RPM enters. The drivers outputs the message
+ via a debugfs node.
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 00a1284..ba00ef10 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -31,6 +31,7 @@
obj-$(CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT) += glink_smem_native_xprt.o
obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o
obj-$(CONFIG_MSM_SPCOM) += spcom.o
+obj-$(CONFIG_MSM_SPSS_UTILS) += spss_utils.o
obj-$(CONFIG_TRACER_PKT) += tracer_pkt.o
obj-$(CONFIG_QCOM_BUS_SCALING) += msm_bus/
obj-$(CONFIG_QTI_RPMH_API) += rpmh.o
@@ -67,3 +68,4 @@
obj-$(CONFIG_MSM_IDLE_STATS) += lpm-stats.o
obj-$(CONFIG_APSS_CORE_EA) += msm-core.o debug_core.o
obj-$(CONFIG_QCOM_DCC_V2) += dcc_v2.o
+obj-$(CONFIG_QTI_RPM_STATS_LOG) += rpm_stats.o
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index cb212b2..4d2f54d 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -121,6 +121,7 @@
struct mutex mutex;
void __iomem *ram_base;
uint32_t ram_size;
+ uint32_t ram_offset;
enum dcc_data_sink data_sink;
enum dcc_func_type func_type[DCC_MAX_LINK_LIST];
uint32_t ram_cfg;
@@ -517,9 +518,10 @@
/* 3. If in capture mode program DCC_RAM_CFG reg */
if (drvdata->func_type[list] == DCC_FUNC_TYPE_CAPTURE) {
- dcc_writel(drvdata, ram_cfg_base, DCC_LL_BASE(list));
- dcc_writel(drvdata, drvdata->ram_start,
- DCC_FD_BASE(list));
+ dcc_writel(drvdata, ram_cfg_base +
+ drvdata->ram_offset/4, DCC_LL_BASE(list));
+ dcc_writel(drvdata, drvdata->ram_start +
+ drvdata->ram_offset/4, DCC_FD_BASE(list));
dcc_writel(drvdata, 0, DCC_LL_TIMEOUT(list));
}
@@ -1342,6 +1344,11 @@
if (!drvdata->ram_base)
return -ENOMEM;
+ ret = of_property_read_u32(pdev->dev.of_node, "dcc-ram-offset",
+ &drvdata->ram_offset);
+ if (ret)
+ return -EINVAL;
+
drvdata->save_reg = of_property_read_bool(pdev->dev.of_node,
"qcom,save-reg");
diff --git a/drivers/soc/qcom/lpm-stats.c b/drivers/soc/qcom/lpm-stats.c
index 74a86ec..ee68433 100644
--- a/drivers/soc/qcom/lpm-stats.c
+++ b/drivers/soc/qcom/lpm-stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -425,7 +425,10 @@
uint64_t exit_time = 0;
/* Update time stats only when exit is preceded by enter */
- exit_time = stats->sleep_time;
+ if (stats->sleep_time < 0)
+ success = false;
+ else
+ exit_time = stats->sleep_time;
update_level_stats(&stats->time_stats[index], exit_time,
success);
}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 4167480..91d6349 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -311,7 +311,12 @@
if (list_empty(&cur_bcm_clist[i]))
continue;
list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
- if (cur_bcm->updated) {
+ if (cur_bcm->updated ||
+ (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
+ cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
+ cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
+ cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
+ init_time == true)) {
if (last_tcs != -1 &&
list_is_last(&cur_bcm->link,
&cur_bcm_clist[i])) {
@@ -356,18 +361,19 @@
if (last_tcs != -1 &&
list_is_last(&cur_bcm->link,
&cur_bcm_clist[i])) {
- cmdlist_wake[k].data |=
+ cmdlist_wake[last_tcs].data |=
BCM_TCS_CMD_COMMIT_MASK;
- cmdlist_sleep[k].data |=
+ cmdlist_sleep[last_tcs].data |=
BCM_TCS_CMD_COMMIT_MASK;
- cmdlist_wake[k].complete = true;
- cmdlist_sleep[k].complete = true;
+ cmdlist_wake[last_tcs].complete = true;
+ cmdlist_sleep[last_tcs].complete = true;
idx++;
}
continue;
}
last_tcs = k;
n_sleep[idx]++;
+ n_wake[idx]++;
if (list_is_last(&cur_bcm->link,
&cur_bcm_clist[i])) {
commit = true;
@@ -584,7 +590,11 @@
cmdlist_wake, cmdlist_sleep, cur_bcm_clist);
ret = rpmh_invalidate(cur_mbox);
- ret = rpmh_write_passthru(cur_mbox, cur_rsc->rscdev->req_state,
+ if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE)
+ ret = rpmh_write(cur_mbox, cur_rsc->rscdev->req_state,
+ cmdlist_active, cnt_active);
+ else
+ ret = rpmh_write_passthru(cur_mbox, cur_rsc->rscdev->req_state,
cmdlist_active, n_active);
ret = rpmh_write_passthru(cur_mbox, RPMH_WAKE_ONLY_STATE,
diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c
new file mode 100644
index 0000000..15d8b1b
--- /dev/null
+++ b/drivers/soc/qcom/rpm_stats.c
@@ -0,0 +1,381 @@
+/* Copyright (c) 2011-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/debugfs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/uaccess.h>
+#include <asm/arch_timer.h>
+
+#define RPM_STATS_NUM_REC 2
+#define MSM_ARCH_TIMER_FREQ 19200000
+
+#define GET_PDATA_OF_ATTR(attr) \
+ (container_of(attr, struct msm_rpmstats_kobj_attr, ka)->pd)
+
+struct msm_rpmstats_record {
+ char name[32];
+ u32 id;
+ u32 val;
+};
+
+struct msm_rpmstats_platform_data {
+ phys_addr_t phys_addr_base;
+ u32 phys_size;
+};
+
+struct msm_rpmstats_private_data {
+ void __iomem *reg_base;
+ u32 num_records;
+ u32 read_idx;
+ u32 len;
+ char buf[320];
+ struct msm_rpmstats_platform_data *platform_data;
+};
+
+struct msm_rpm_stats_data {
+ u32 stat_type;
+ u32 count;
+ u64 last_entered_at;
+ u64 last_exited_at;
+ u64 accumulated;
+};
+
+struct msm_rpmstats_kobj_attr {
+ struct kobj_attribute ka;
+ struct msm_rpmstats_platform_data *pd;
+};
+
+static inline u64 get_time_in_sec(u64 counter)
+{
+ do_div(counter, MSM_ARCH_TIMER_FREQ);
+
+ return counter;
+}
+
+static inline u64 get_time_in_msec(u64 counter)
+{
+ do_div(counter, MSM_ARCH_TIMER_FREQ);
+ counter *= MSEC_PER_SEC;
+
+ return counter;
+}
+
+static inline int msm_rpmstats_append_data_to_buf(char *buf,
+ struct msm_rpm_stats_data *data, int buflength)
+{
+ char stat_type[5];
+ u64 time_in_last_mode;
+ u64 time_since_last_mode;
+ u64 actual_last_sleep;
+
+ stat_type[4] = 0;
+ memcpy(stat_type, &data->stat_type, sizeof(u32));
+
+ time_in_last_mode = data->last_exited_at - data->last_entered_at;
+ time_in_last_mode = get_time_in_msec(time_in_last_mode);
+ time_since_last_mode = arch_counter_get_cntvct() - data->last_exited_at;
+ time_since_last_mode = get_time_in_sec(time_since_last_mode);
+ actual_last_sleep = get_time_in_msec(data->accumulated);
+
+ return snprintf(buf, buflength,
+ "RPM Mode:%s\n\t count:%d\ntime in last mode(msec):%llu\n"
+ "time since last mode(sec):%llu\nactual last sleep(msec):%llu\n\n",
+ stat_type, data->count, time_in_last_mode,
+ time_since_last_mode, actual_last_sleep);
+}
+
+static inline u32 msm_rpmstats_read_long_register(void __iomem *regbase,
+ int index, int offset)
+{
+ return readl_relaxed(regbase + offset +
+ index * sizeof(struct msm_rpm_stats_data));
+}
+
+static inline u64 msm_rpmstats_read_quad_register(void __iomem *regbase,
+ int index, int offset)
+{
+ u64 dst;
+
+ memcpy_fromio(&dst,
+ regbase + offset + index * sizeof(struct msm_rpm_stats_data),
+ 8);
+ return dst;
+}
+
+static inline int msm_rpmstats_copy_stats(
+ struct msm_rpmstats_private_data *prvdata)
+{
+ void __iomem *reg;
+ struct msm_rpm_stats_data data;
+ int i, length;
+
+ reg = prvdata->reg_base;
+
+ for (i = 0, length = 0; i < prvdata->num_records; i++) {
+ data.stat_type = msm_rpmstats_read_long_register(reg, i,
+ offsetof(struct msm_rpm_stats_data,
+ stat_type));
+ data.count = msm_rpmstats_read_long_register(reg, i,
+ offsetof(struct msm_rpm_stats_data, count));
+ data.last_entered_at = msm_rpmstats_read_quad_register(reg,
+ i, offsetof(struct msm_rpm_stats_data,
+ last_entered_at));
+ data.last_exited_at = msm_rpmstats_read_quad_register(reg,
+ i, offsetof(struct msm_rpm_stats_data,
+ last_exited_at));
+ data.accumulated = msm_rpmstats_read_quad_register(reg,
+ i, offsetof(struct msm_rpm_stats_data,
+ accumulated));
+ length += msm_rpmstats_append_data_to_buf(prvdata->buf + length,
+ &data, sizeof(prvdata->buf) - length);
+ prvdata->read_idx++;
+ }
+
+ return length;
+}
+
+static inline unsigned long msm_rpmstats_read_register(void __iomem *regbase,
+ int index, int offset)
+{
+ return readl_relaxed(regbase + index * 12 + (offset + 1) * 4);
+}
+
+static ssize_t msm_rpmstats_file_read(struct file *file, char __user *bufu,
+ size_t count, loff_t *ppos)
+{
+ struct msm_rpmstats_private_data *prvdata;
+
+ prvdata = file->private_data;
+ if (!prvdata)
+ return -EINVAL;
+
+ if (!bufu || count == 0)
+ return -EINVAL;
+
+ if ((*ppos >= prvdata->len) &&
+ (prvdata->read_idx < prvdata->num_records)) {
+ prvdata->len = msm_rpmstats_copy_stats(prvdata);
+ *ppos = 0;
+ }
+
+ return simple_read_from_buffer(bufu, count, ppos,
+ prvdata->buf, prvdata->len);
+}
+
+static int msm_rpmstats_file_open(struct inode *inode, struct file *file)
+{
+ struct msm_rpmstats_private_data *prvdata;
+ struct msm_rpmstats_platform_data *pdata;
+
+ pdata = inode->i_private;
+
+ file->private_data = kzalloc(sizeof(*prvdata), GFP_KERNEL);
+ if (!file->private_data)
+ return -ENOMEM;
+
+ prvdata = file->private_data;
+
+ prvdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!prvdata->reg_base) {
+ kfree(file->private_data);
+ prvdata = NULL;
+ pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+
+ prvdata->read_idx = prvdata->len = 0;
+ prvdata->platform_data = pdata;
+ prvdata->num_records = RPM_STATS_NUM_REC;
+
+ return 0;
+}
+
+static int msm_rpmstats_file_close(struct inode *inode, struct file *file)
+{
+ struct msm_rpmstats_private_data *private = file->private_data;
+
+ if (private->reg_base)
+ iounmap(private->reg_base);
+ kfree(file->private_data);
+
+ return 0;
+}
+
+static const struct file_operations msm_rpmstats_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpmstats_file_open,
+ .read = msm_rpmstats_file_read,
+ .release = msm_rpmstats_file_close,
+ .llseek = no_llseek,
+};
+
+static ssize_t rpmstats_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct msm_rpmstats_private_data *prvdata = NULL;
+ struct msm_rpmstats_platform_data *pdata = NULL;
+
+ pdata = GET_PDATA_OF_ATTR(attr);
+
+ prvdata =
+ kmalloc(sizeof(*prvdata), GFP_KERNEL);
+ if (!prvdata)
+ return -ENOMEM;
+
+ prvdata->reg_base = ioremap_nocache(pdata->phys_addr_base,
+ pdata->phys_size);
+ if (!prvdata->reg_base) {
+ kfree(prvdata);
+ pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
+ __func__, &pdata->phys_addr_base,
+ pdata->phys_size);
+ return -EBUSY;
+ }
+
+ prvdata->read_idx = prvdata->len = 0;
+ prvdata->platform_data = pdata;
+ prvdata->num_records = RPM_STATS_NUM_REC;
+
+ if (prvdata->read_idx < prvdata->num_records)
+ prvdata->len = msm_rpmstats_copy_stats(prvdata);
+
+ return snprintf(buf, prvdata->len, prvdata->buf);
+}
+
+static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *rpmstats_kobj = NULL;
+ struct msm_rpmstats_kobj_attr *rpms_ka = NULL;
+ int ret = 0;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: Cannot find module_kset\n", __func__);
+ return -ENODEV;
+ }
+
+ rpmstats_kobj = kobject_create_and_add("rpmstats", module_kobj);
+ if (!rpmstats_kobj) {
+ pr_err("%s: Cannot create rpmstats kobject\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ rpms_ka = kzalloc(sizeof(*rpms_ka), GFP_KERNEL);
+ if (!rpms_ka) {
+ kobject_put(rpmstats_kobj);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ sysfs_attr_init(&rpms_ka->ka.attr);
+ rpms_ka->pd = pd;
+ rpms_ka->ka.attr.mode = 0444;
+ rpms_ka->ka.attr.name = "stats";
+ rpms_ka->ka.show = rpmstats_show;
+ rpms_ka->ka.store = NULL;
+
+ ret = sysfs_create_file(rpmstats_kobj, &rpms_ka->ka.attr);
+
+fail:
+ return ret;
+}
+
+static int msm_rpmstats_probe(struct platform_device *pdev)
+{
+ struct dentry *dent = NULL;
+ struct msm_rpmstats_platform_data *pdata;
+ struct msm_rpmstats_platform_data *pd;
+ struct resource *res = NULL, *offset = NULL;
+ u32 offset_addr = 0;
+ void __iomem *phys_ptr = NULL;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "phys_addr_base");
+ if (!res)
+ return -EINVAL;
+
+ offset = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "offset_addr");
+ if (offset) {
+ /* Remap the rpm-stats pointer */
+ phys_ptr = ioremap_nocache(offset->start, SZ_4);
+ if (!phys_ptr) {
+ pr_err("%s: Failed to ioremap address: %x\n",
+ __func__, offset_addr);
+ return -ENODEV;
+ }
+ offset_addr = readl_relaxed(phys_ptr);
+ iounmap(phys_ptr);
+ }
+
+ pdata->phys_addr_base = res->start + offset_addr;
+ pdata->phys_size = resource_size(res);
+
+ if (pdev->dev.platform_data)
+ pd = pdev->dev.platform_data;
+
+ dent = debugfs_create_file("rpm_stats", 0444, NULL,
+ pdata, &msm_rpmstats_fops);
+ if (!dent) {
+ pr_err("%s: ERROR rpm_stats debugfs_create_file fail\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ msm_rpmstats_create_sysfs(pdata);
+
+ platform_set_drvdata(pdev, dent);
+ return 0;
+}
+
+static int msm_rpmstats_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id rpm_stats_table[] = {
+ { .compatible = "qcom,rpm-stats" },
+ { },
+};
+
+static struct platform_driver msm_rpmstats_driver = {
+ .probe = msm_rpmstats_probe,
+ .remove = msm_rpmstats_remove,
+ .driver = {
+ .name = "msm_rpm_stat",
+ .owner = THIS_MODULE,
+ .of_match_table = rpm_stats_table,
+ },
+};
+builtin_platform_driver(msm_rpmstats_driver);
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 1635bab..b3c1150 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -108,7 +108,7 @@
struct rpmh_msg *rpm_msg = container_of(msg, struct rpmh_msg, msg);
atomic_dec(rpm_msg->wait_count);
- wake_up_interruptible(rpm_msg->waitq);
+ wake_up(rpm_msg->waitq);
}
static void rpmh_tx_done(struct mbox_client *cl, void *msg, int r)
@@ -151,7 +151,7 @@
/* Signal the blocking thread we are done */
if (waitq) {
atomic_dec(wc);
- wake_up_interruptible(waitq);
+ wake_up(waitq);
}
}
@@ -329,9 +329,7 @@
if (ret < 0)
return ret;
- ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
- if (ret)
- return ret;
+ wait_event(waitq, atomic_read(&wait_count) == 0);
return rpm_msg.err;
}
@@ -423,13 +421,11 @@
rpm_msg.msg.num_payload = n;
ret = __rpmh_write(rc, state, &rpm_msg);
- if (ret < 0)
- return ret;
-
- ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
if (ret)
return ret;
+ wait_event(waitq, atomic_read(&wait_count) == 0);
+
return rpm_msg.err;
}
EXPORT_SYMBOL(rpmh_write);
@@ -494,8 +490,6 @@
rpm_msg[i] = __get_rpmh_msg_async(rc, state, cmd, n[i]);
if (IS_ERR_OR_NULL(rpm_msg[i]))
return PTR_ERR(rpm_msg[i]);
- rpm_msg[i]->waitq = &waitq;
- rpm_msg[i]->wait_count = &wait_count;
cmd += n[i];
}
@@ -504,16 +498,18 @@
might_sleep();
atomic_set(&wait_count, count);
for (i = 0; i < count; i++) {
+ rpm_msg[i]->waitq = &waitq;
+ rpm_msg[i]->wait_count = &wait_count;
/* Bypass caching and write to mailbox directly */
ret = mbox_send_message(rc->chan, &rpm_msg[i]->msg);
if (ret < 0)
return ret;
}
- return wait_event_interruptible(waitq,
- atomic_read(&wait_count) == 0);
+ wait_event(waitq, atomic_read(&wait_count) == 0);
} else {
/* Send Sleep requests to the controller, expect no response */
for (i = 0; i < count; i++) {
+ rpm_msg[i]->waitq = NULL;
ret = mbox_send_controller_data(rc->chan,
&rpm_msg[i]->msg);
/* Clean up our call by spoofing tx_done */
@@ -521,6 +517,8 @@
}
return 0;
}
+
+ return 0;
}
EXPORT_SYMBOL(rpmh_write_passthru);
@@ -623,9 +621,7 @@
return ret;
/* Wait until the response is received from RPMH */
- ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
- if (ret)
- return ret;
+ wait_event(waitq, atomic_read(&wait_count) == 0);
/* Read the data back from the tcs_mbox_msg structrure */
*resp = rpm_msg.cmd[0].data;
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 614bfd6..68592fe 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -103,6 +103,7 @@
struct work_struct svc_exit;
struct work_struct svc_rcv_msg;
struct work_struct ind_ack;
+ struct work_struct qmi_handle_free;
struct workqueue_struct *svc_event_wq;
struct qmi_handle *clnt_handle;
struct notifier_block notifier;
@@ -122,6 +123,18 @@
static void root_service_service_arrive(struct work_struct *work);
static void root_service_exit_work(struct work_struct *work);
+static void free_qmi_handle(struct work_struct *work)
+{
+ struct qmi_client_info *data = container_of(work,
+ struct qmi_client_info, qmi_handle_free);
+
+ mutex_lock(&qmi_client_release_lock);
+ data->service_connected = false;
+ qmi_handle_destroy(data->clnt_handle);
+ data->clnt_handle = NULL;
+ mutex_unlock(&qmi_client_release_lock);
+}
+
static struct service_notif_info *_find_service_info(const char *service_path)
{
struct service_notif_info *service_notif;
@@ -425,11 +438,7 @@
* Destroy client handle and try connecting when
* service comes up again.
*/
- mutex_lock(&qmi_client_release_lock);
- data->service_connected = false;
- qmi_handle_destroy(data->clnt_handle);
- data->clnt_handle = NULL;
- mutex_unlock(&qmi_client_release_lock);
+ queue_work(data->svc_event_wq, &data->qmi_handle_free);
}
static void root_service_exit_work(struct work_struct *work)
@@ -485,7 +494,7 @@
info->subsys_state = ROOT_PD_SHUTDOWN;
break;
}
- queue_work(info->svc_event_wq, &info->svc_exit);
+ root_service_service_exit(info, info->subsys_state);
break;
default:
break;
@@ -560,6 +569,7 @@
INIT_WORK(&qmi_data->svc_exit, root_service_exit_work);
INIT_WORK(&qmi_data->svc_rcv_msg, root_service_clnt_recv_msg);
INIT_WORK(&qmi_data->ind_ack, send_ind_ack);
+ INIT_WORK(&qmi_data->qmi_handle_free, free_qmi_handle);
*curr_state = service_notif->curr_state =
SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01;
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 55fa5d2..119ede3 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -550,6 +550,9 @@
/* Bat ID */
[328] = {MSM_CPU_SDM830, "SDM830"},
+ /* sdxpoorwills ID */
+ [334] = {SDX_CPU_SDXPOORWILLS, "SDXPOORWILLS"},
+
/* Uninitialized IDs are not known to run Linux.
* MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
* considered as unknown CPU.
@@ -1256,6 +1259,10 @@
dummy_socinfo.id = 328;
strlcpy(dummy_socinfo.build_id, "sdm830 - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_sdxpoorwills()) {
+ dummy_socinfo.id = 334;
+ strlcpy(dummy_socinfo.build_id, "sdxpoorwills - ",
+ sizeof(dummy_socinfo.build_id));
}
strlcat(dummy_socinfo.build_id, "Dummy socinfo",
diff --git a/drivers/soc/qcom/spss_utils.c b/drivers/soc/qcom/spss_utils.c
new file mode 100644
index 0000000..c70ef3a
--- /dev/null
+++ b/drivers/soc/qcom/spss_utils.c
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2016-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.
+ */
+
+/*
+ * Secure-Processor-SubSystem (SPSS) utilities.
+ *
+ * This driver provides utilities for the Secure Processor (SP).
+ *
+ * The SP daemon needs to load different SPSS images based on:
+ *
+ * 1. Test/Production key used to sign the SPSS image (read fuses).
+ * 2. SPSS HW version (selected via Device Tree).
+ *
+ */
+
+#define pr_fmt(fmt) "spss_utils [%s]: " fmt, __func__
+
+#include <linux/kernel.h> /* min() */
+#include <linux/module.h> /* MODULE_LICENSE */
+#include <linux/device.h> /* class_create() */
+#include <linux/slab.h> /* kzalloc() */
+#include <linux/fs.h> /* file_operations */
+#include <linux/cdev.h> /* cdev_add() */
+#include <linux/errno.h> /* EINVAL, ETIMEDOUT */
+#include <linux/printk.h> /* pr_err() */
+#include <linux/bitops.h> /* BIT(x) */
+#include <linux/platform_device.h> /* platform_driver_register() */
+#include <linux/of.h> /* of_property_count_strings() */
+#include <linux/io.h> /* ioremap_nocache() */
+
+#include <soc/qcom/subsystem_restart.h>
+
+/* driver name */
+#define DEVICE_NAME "spss-utils"
+
+enum spss_firmware_type {
+ SPSS_FW_TYPE_DEV = 'd',
+ SPSS_FW_TYPE_TEST = 't',
+ SPSS_FW_TYPE_PROD = 'p',
+};
+
+static enum spss_firmware_type firmware_type = SPSS_FW_TYPE_TEST;
+static const char *dev_firmware_name;
+static const char *test_firmware_name;
+static const char *prod_firmware_name;
+static const char *firmware_name = "NA";
+static struct device *spss_dev;
+static u32 spss_debug_reg_addr; /* SP_SCSR_MBn_SP2CL_GPm(n,m) */
+
+/*==========================================================================*/
+/* Device Sysfs */
+/*==========================================================================*/
+
+static ssize_t firmware_name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+
+ if (!dev || !attr || !buf) {
+ pr_err("invalid param.\n");
+ return -EINVAL;
+ }
+
+ if (firmware_name == NULL)
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", "unknown");
+ else
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", firmware_name);
+
+ return ret;
+}
+
+static ssize_t firmware_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ pr_err("set firmware name is not allowed.\n");
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(firmware_name, 0444,
+ firmware_name_show, firmware_name_store);
+
+static ssize_t test_fuse_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+
+ if (!dev || !attr || !buf) {
+ pr_err("invalid param.\n");
+ return -EINVAL;
+ }
+
+ switch (firmware_type) {
+ case SPSS_FW_TYPE_DEV:
+ ret = snprintf(buf, PAGE_SIZE, "%s", "dev");
+ break;
+ case SPSS_FW_TYPE_TEST:
+ ret = snprintf(buf, PAGE_SIZE, "%s", "test");
+ break;
+ case SPSS_FW_TYPE_PROD:
+ ret = snprintf(buf, PAGE_SIZE, "%s", "prod");
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static ssize_t test_fuse_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ pr_err("set test fuse state is not allowed.\n");
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(test_fuse_state, 0444,
+ test_fuse_state_show, test_fuse_state_store);
+
+static ssize_t spss_debug_reg_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ret;
+ void __iomem *spss_debug_reg = NULL;
+ u32 val1, val2;
+
+ if (!dev || !attr || !buf) {
+ pr_err("invalid param.\n");
+ return -EINVAL;
+ }
+
+ pr_debug("spss_debug_reg_addr [0x%x].\n", spss_debug_reg_addr);
+
+ spss_debug_reg = ioremap_nocache(spss_debug_reg_addr, sizeof(u32)*2);
+
+ if (!spss_debug_reg) {
+ pr_err("can't map debug reg addr.\n");
+ return -EFAULT;
+ }
+
+ val1 = readl_relaxed(spss_debug_reg);
+ val2 = readl_relaxed(((char *) spss_debug_reg) + sizeof(u32));
+
+ ret = snprintf(buf, PAGE_SIZE, "val1 [0x%x] val2 [0x%x]", val1, val2);
+
+ iounmap(spss_debug_reg);
+
+ return ret;
+}
+
+static ssize_t spss_debug_reg_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ pr_err("set debug reg is not allowed.\n");
+
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(spss_debug_reg, 0444,
+ spss_debug_reg_show, spss_debug_reg_store);
+
+static int spss_create_sysfs(struct device *dev)
+{
+ int ret;
+
+ ret = device_create_file(dev, &dev_attr_firmware_name);
+ if (ret < 0) {
+ pr_err("failed to create sysfs file for firmware_name.\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_test_fuse_state);
+ if (ret < 0) {
+ pr_err("failed to create sysfs file for test_fuse_state.\n");
+ device_remove_file(dev, &dev_attr_firmware_name);
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_spss_debug_reg);
+ if (ret < 0) {
+ pr_err("failed to create sysfs file for spss_debug_reg.\n");
+ device_remove_file(dev, &dev_attr_firmware_name);
+ device_remove_file(dev, &dev_attr_test_fuse_state);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*==========================================================================*/
+/* Device Tree */
+/*==========================================================================*/
+
+/**
+ * spss_parse_dt() - Parse Device Tree info.
+ */
+static int spss_parse_dt(struct device_node *node)
+{
+ int ret;
+ u32 spss_fuse1_addr = 0;
+ u32 spss_fuse1_bit = 0;
+ u32 spss_fuse1_mask = 0;
+ void __iomem *spss_fuse1_reg = NULL;
+ u32 spss_fuse2_addr = 0;
+ u32 spss_fuse2_bit = 0;
+ u32 spss_fuse2_mask = 0;
+ void __iomem *spss_fuse2_reg = NULL;
+ u32 val1 = 0;
+ u32 val2 = 0;
+
+ ret = of_property_read_string(node, "qcom,spss-dev-firmware-name",
+ &dev_firmware_name);
+ if (ret < 0) {
+ pr_err("can't get dev fw name.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_string(node, "qcom,spss-test-firmware-name",
+ &test_firmware_name);
+ if (ret < 0) {
+ pr_err("can't get test fw name.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_string(node, "qcom,spss-prod-firmware-name",
+ &prod_firmware_name);
+ if (ret < 0) {
+ pr_err("can't get prod fw name.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse1-addr",
+ &spss_fuse1_addr);
+ if (ret < 0) {
+ pr_err("can't get fuse1 addr.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse2-addr",
+ &spss_fuse2_addr);
+ if (ret < 0) {
+ pr_err("can't get fuse2 addr.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse1-bit",
+ &spss_fuse1_bit);
+ if (ret < 0) {
+ pr_err("can't get fuse1 bit.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse2-bit",
+ &spss_fuse2_bit);
+ if (ret < 0) {
+ pr_err("can't get fuse2 bit.\n");
+ return -EFAULT;
+ }
+
+
+ spss_fuse1_mask = BIT(spss_fuse1_bit);
+ spss_fuse2_mask = BIT(spss_fuse2_bit);
+
+ pr_debug("spss fuse1 addr [0x%x] bit [%d] .\n",
+ (int) spss_fuse1_addr, (int) spss_fuse1_bit);
+ pr_debug("spss fuse2 addr [0x%x] bit [%d] .\n",
+ (int) spss_fuse2_addr, (int) spss_fuse2_bit);
+
+ spss_fuse1_reg = ioremap_nocache(spss_fuse1_addr, sizeof(u32));
+
+ if (!spss_fuse1_reg) {
+ pr_err("can't map fuse1 addr.\n");
+ return -EFAULT;
+ }
+
+ spss_fuse2_reg = ioremap_nocache(spss_fuse2_addr, sizeof(u32));
+
+ if (!spss_fuse2_reg) {
+ iounmap(spss_fuse1_reg);
+ pr_err("can't map fuse2 addr.\n");
+ return -EFAULT;
+ }
+
+ val1 = readl_relaxed(spss_fuse1_reg);
+ val2 = readl_relaxed(spss_fuse2_reg);
+
+ pr_debug("spss fuse1 value [0x%08x].\n", (int) val1);
+ pr_debug("spss fuse2 value [0x%08x].\n", (int) val2);
+
+ pr_debug("spss fuse1 mask [0x%08x].\n", (int) spss_fuse1_mask);
+ pr_debug("spss fuse2 mask [0x%08x].\n", (int) spss_fuse2_mask);
+
+ /**
+ * Set firmware_type based on fuses:
+ * SPSS_CONFIG_MODE 11: dev
+ * SPSS_CONFIG_MODE 01 or 10: test
+ * SPSS_CONFIG_MODE 00: prod
+ */
+ if ((val1 & spss_fuse1_mask) && (val2 & spss_fuse2_mask))
+ firmware_type = SPSS_FW_TYPE_DEV;
+ else if ((val1 & spss_fuse1_mask) || (val2 & spss_fuse2_mask))
+ firmware_type = SPSS_FW_TYPE_TEST;
+ else
+ firmware_type = SPSS_FW_TYPE_PROD;
+
+ iounmap(spss_fuse1_reg);
+ iounmap(spss_fuse2_reg);
+
+ ret = of_property_read_u32(node, "qcom,spss-debug-reg-addr",
+ &spss_debug_reg_addr);
+ if (ret < 0) {
+ pr_err("can't get debug regs addr.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * spss_probe() - initialization sequence
+ */
+static int spss_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct device_node *np = NULL;
+ struct device *dev = NULL;
+
+ if (!pdev) {
+ pr_err("invalid pdev.\n");
+ return -ENODEV;
+ }
+
+ np = pdev->dev.of_node;
+ if (!np) {
+ pr_err("invalid DT node.\n");
+ return -EINVAL;
+ }
+
+ dev = &pdev->dev;
+ spss_dev = dev;
+
+ if (dev == NULL) {
+ pr_err("invalid dev.\n");
+ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, dev);
+
+ ret = spss_parse_dt(np);
+ if (ret < 0) {
+ pr_err("fail to parse device tree.\n");
+ return -EFAULT;
+ }
+
+ switch (firmware_type) {
+ case SPSS_FW_TYPE_DEV:
+ firmware_name = dev_firmware_name;
+ break;
+ case SPSS_FW_TYPE_TEST:
+ firmware_name = test_firmware_name;
+ break;
+ case SPSS_FW_TYPE_PROD:
+ firmware_name = prod_firmware_name;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = subsystem_set_fwname("spss", firmware_name);
+ if (ret < 0) {
+ pr_err("fail to set fw name.\n");
+ return -EFAULT;
+ }
+
+ ret = spss_create_sysfs(dev);
+ if (ret < 0) {
+ pr_err("fail to create sysfs.\n");
+ return -EFAULT;
+ }
+
+ pr_info("Initialization completed ok, firmware_name [%s].\n",
+ firmware_name);
+
+ return 0;
+}
+
+static const struct of_device_id spss_match_table[] = {
+ { .compatible = "qcom,spss-utils", },
+ { },
+};
+
+static struct platform_driver spss_driver = {
+ .probe = spss_probe,
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(spss_match_table),
+ },
+};
+
+/*==========================================================================*/
+/* Driver Init/Exit */
+/*==========================================================================*/
+static int __init spss_init(void)
+{
+ int ret = 0;
+
+ pr_info("spss-utils driver Ver 2.0 30-Mar-2017.\n");
+
+ ret = platform_driver_register(&spss_driver);
+ if (ret)
+ pr_err("register platform driver failed, ret [%d]\n", ret);
+
+ return ret;
+}
+late_initcall(spss_init); /* start after PIL driver */
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Secure Processor Utilities");
diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c
index 272e70a..6ff39de 100644
--- a/drivers/soc/qcom/subsys-pil-tz.c
+++ b/drivers/soc/qcom/subsys-pil-tz.c
@@ -738,10 +738,21 @@
desc.args[0] = proc = d->pas_id;
desc.arginfo = SCM_ARGS(1);
+ if (d->bus_client) {
+ rc = msm_bus_scale_client_update_request(d->bus_client, 1);
+ if (rc) {
+ dev_err(pil->dev, "bandwidth request failed(rc:%d)\n",
+ rc);
+ return rc;
+ }
+ } else
+ WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
+ d->subsys_desc.name);
+
rc = enable_regulators(d, pil->dev, d->proxy_regs,
d->proxy_reg_count, true);
if (rc)
- return rc;
+ goto err_regulators;
rc = prepare_enable_clocks(pil->dev, d->proxy_clks,
d->proxy_clk_count);
@@ -759,6 +770,11 @@
disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count);
disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false);
+ if (d->bus_client)
+ msm_bus_scale_client_update_request(d->bus_client, 0);
+ else
+ WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
+ d->subsys_desc.name);
if (rc)
return rc;
@@ -767,8 +783,15 @@
disable_regulators(d, d->regs, d->reg_count, false);
return scm_ret;
+
err_clks:
disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false);
+err_regulators:
+ if (d->bus_client)
+ msm_bus_scale_client_update_request(d->bus_client, 0);
+ else
+ WARN(d->enable_bus_scaling, "Bus scaling not set up for %s!\n",
+ d->subsys_desc.name);
return rc;
}
diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c
index f3d6209..7a784aa 100644
--- a/drivers/soc/qcom/watchdog_v2.c
+++ b/drivers/soc/qcom/watchdog_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -30,6 +30,7 @@
#include <soc/qcom/scm.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/watchdog.h>
+#include <linux/dma-mapping.h>
#define MODULE_NAME "msm_watchdog"
#define WDT0_ACCSCSSNBARK_INT 0
@@ -49,6 +50,7 @@
#define SCM_SET_REGSAVE_CMD 0x2
#define SCM_SVC_SEC_WDOG_DIS 0x7
#define MAX_CPU_CTX_SIZE 2048
+#define MAX_CPU_SCANDUMP_SIZE 0x10000
static struct msm_watchdog_data *wdog_data;
@@ -557,6 +559,49 @@
return;
}
+static void configure_scandump(struct msm_watchdog_data *wdog_dd)
+{
+ int ret;
+ struct msm_dump_entry dump_entry;
+ struct msm_dump_data *cpu_data;
+ int cpu;
+ static dma_addr_t dump_addr;
+ static void *dump_vaddr;
+
+ for_each_cpu(cpu, cpu_present_mask) {
+ cpu_data = devm_kzalloc(wdog_dd->dev,
+ sizeof(struct msm_dump_data),
+ GFP_KERNEL);
+ if (!cpu_data)
+ continue;
+
+ dump_vaddr = (void *) dma_alloc_coherent(wdog_dd->dev,
+ MAX_CPU_SCANDUMP_SIZE,
+ &dump_addr,
+ GFP_KERNEL);
+ if (!dump_vaddr) {
+ dev_err(wdog_dd->dev, "Couldn't get memory for dump\n");
+ continue;
+ }
+ memset(dump_vaddr, 0x0, MAX_CPU_SCANDUMP_SIZE);
+
+ cpu_data->addr = dump_addr;
+ cpu_data->len = MAX_CPU_SCANDUMP_SIZE;
+ dump_entry.id = MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu;
+ dump_entry.addr = virt_to_phys(cpu_data);
+ ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS,
+ &dump_entry);
+ if (ret) {
+ dev_err(wdog_dd->dev, "Dump setup failed, id = %d\n",
+ MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu);
+ dma_free_coherent(wdog_dd->dev, MAX_CPU_SCANDUMP_SIZE,
+ dump_vaddr,
+ dump_addr);
+ devm_kfree(wdog_dd->dev, cpu_data);
+ }
+ }
+}
+
static int init_watchdog_sysfs(struct msm_watchdog_data *wdog_dd)
{
int error = 0;
@@ -617,6 +662,7 @@
delay_time = msecs_to_jiffies(wdog_dd->pet_time);
wdog_dd->min_slack_ticks = UINT_MAX;
wdog_dd->min_slack_ns = ULLONG_MAX;
+ configure_scandump(wdog_dd);
configure_bark_dump(wdog_dd);
timeout = (wdog_dd->bark_time * WDT_HZ)/1000;
__raw_writel(timeout, wdog_dd->base + WDT0_BARK_TIME);
diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c
index 7e33e8b..ce2a367 100644
--- a/drivers/soundwire/swr-wcd-ctrl.c
+++ b/drivers/soundwire/swr-wcd-ctrl.c
@@ -524,7 +524,7 @@
{
struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
int ret = 0;
- int val = 0;
+ int val;
u8 *reg_val = (u8 *)buf;
if (!swrm) {
@@ -538,7 +538,9 @@
else
val = swrm->read(swrm->handle, reg_addr);
- *reg_val = (u8)val;
+ if (!ret)
+ *reg_val = (u8)val;
+
pm_runtime_mark_last_busy(&swrm->pdev->dev);
return ret;
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 9435dc5..eb41e84 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -766,10 +766,12 @@
break;
case ASHMEM_SET_SIZE:
ret = -EINVAL;
+ mutex_lock(&ashmem_mutex);
if (!asma->file) {
ret = 0;
asma->size = (size_t)arg;
}
+ mutex_unlock(&ashmem_mutex);
break;
case ASHMEM_GET_SIZE:
ret = asma->size;
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 0efa80b..4a073339a 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -782,22 +782,6 @@
if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
SET_PSTATE_REPLY_OPTIONAL(param);
/*
- * The GlobalSAN iSCSI Initiator for MacOSX does
- * not respond to MaxBurstLength, FirstBurstLength,
- * DefaultTime2Wait or DefaultTime2Retain parameter keys.
- * So, we set them to 'reply optional' here, and assume the
- * the defaults from iscsi_parameters.h if the initiator
- * is not RFC compliant and the keys are not negotiated.
- */
- if (!strcmp(param->name, MAXBURSTLENGTH))
- SET_PSTATE_REPLY_OPTIONAL(param);
- if (!strcmp(param->name, FIRSTBURSTLENGTH))
- SET_PSTATE_REPLY_OPTIONAL(param);
- if (!strcmp(param->name, DEFAULTTIME2WAIT))
- SET_PSTATE_REPLY_OPTIONAL(param);
- if (!strcmp(param->name, DEFAULTTIME2RETAIN))
- SET_PSTATE_REPLY_OPTIONAL(param);
- /*
* Required for gPXE iSCSI boot client
*/
if (!strcmp(param->name, MAXCONNECTIONS))
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 1f38177..da5a5fc 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -735,21 +735,23 @@
{
struct se_cmd *se_cmd = NULL;
int rc;
+ bool op_scsi = false;
/*
* Determine if a struct se_cmd is associated with
* this struct iscsi_cmd.
*/
switch (cmd->iscsi_opcode) {
case ISCSI_OP_SCSI_CMD:
- se_cmd = &cmd->se_cmd;
- __iscsit_free_cmd(cmd, true, shutdown);
+ op_scsi = true;
/*
* Fallthrough
*/
case ISCSI_OP_SCSI_TMFUNC:
- rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
- if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
- __iscsit_free_cmd(cmd, true, shutdown);
+ se_cmd = &cmd->se_cmd;
+ __iscsit_free_cmd(cmd, op_scsi, shutdown);
+ rc = transport_generic_free_cmd(se_cmd, shutdown);
+ if (!rc && shutdown && se_cmd->se_sess) {
+ __iscsit_free_cmd(cmd, op_scsi, shutdown);
target_put_sess_cmd(se_cmd);
}
break;
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 31a096a..6e456de 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -92,6 +92,11 @@
pr_err("Source se_lun->lun_se_dev does not exist\n");
return -EINVAL;
}
+ if (lun->lun_shutdown) {
+ pr_err("Unable to create mappedlun symlink because"
+ " lun->lun_shutdown=true\n");
+ return -EINVAL;
+ }
se_tpg = lun->lun_tpg;
nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 2744251..1949f50 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -640,6 +640,8 @@
*/
struct se_device *dev = rcu_dereference_raw(lun->lun_se_dev);
+ lun->lun_shutdown = true;
+
core_clear_lun_from_tpg(lun, tpg);
/*
* Wait for any active I/O references to percpu se_lun->lun_ref to
@@ -661,6 +663,8 @@
}
if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
hlist_del_rcu(&lun->link);
+
+ lun->lun_shutdown = false;
mutex_unlock(&tpg->tpg_lun_mutex);
percpu_ref_exit(&lun->lun_ref);
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 70c143a..1a83456 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -306,24 +306,50 @@
DATA_BLOCK_BITS);
}
-static void gather_data_area(struct tcmu_dev *udev, unsigned long *cmd_bitmap,
- struct scatterlist *data_sg, unsigned int data_nents)
+static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
+ bool bidi)
{
+ struct se_cmd *se_cmd = cmd->se_cmd;
int i, block;
int block_remaining = 0;
void *from, *to;
size_t copy_bytes, from_offset;
- struct scatterlist *sg;
+ struct scatterlist *sg, *data_sg;
+ unsigned int data_nents;
+ DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS);
+
+ bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS);
+
+ if (!bidi) {
+ data_sg = se_cmd->t_data_sg;
+ data_nents = se_cmd->t_data_nents;
+ } else {
+ uint32_t count;
+
+ /*
+ * For bidi case, the first count blocks are for Data-Out
+ * buffer blocks, and before gathering the Data-In buffer
+ * the Data-Out buffer blocks should be discarded.
+ */
+ count = DIV_ROUND_UP(se_cmd->data_length, DATA_BLOCK_SIZE);
+ while (count--) {
+ block = find_first_bit(bitmap, DATA_BLOCK_BITS);
+ clear_bit(block, bitmap);
+ }
+
+ data_sg = se_cmd->t_bidi_data_sg;
+ data_nents = se_cmd->t_bidi_data_nents;
+ }
for_each_sg(data_sg, sg, data_nents, i) {
int sg_remaining = sg->length;
to = kmap_atomic(sg_page(sg)) + sg->offset;
while (sg_remaining > 0) {
if (block_remaining == 0) {
- block = find_first_bit(cmd_bitmap,
+ block = find_first_bit(bitmap,
DATA_BLOCK_BITS);
block_remaining = DATA_BLOCK_SIZE;
- clear_bit(block, cmd_bitmap);
+ clear_bit(block, bitmap);
}
copy_bytes = min_t(size_t, sg_remaining,
block_remaining);
@@ -389,6 +415,27 @@
return true;
}
+static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd)
+{
+ struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
+ size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE);
+
+ if (se_cmd->se_cmd_flags & SCF_BIDI) {
+ BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
+ data_length += round_up(se_cmd->t_bidi_data_sg->length,
+ DATA_BLOCK_SIZE);
+ }
+
+ return data_length;
+}
+
+static inline uint32_t tcmu_cmd_get_block_cnt(struct tcmu_cmd *tcmu_cmd)
+{
+ size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd);
+
+ return data_length / DATA_BLOCK_SIZE;
+}
+
static sense_reason_t
tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
{
@@ -402,7 +449,7 @@
uint32_t cmd_head;
uint64_t cdb_off;
bool copy_to_data_area;
- size_t data_length;
+ size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd);
DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS);
if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
@@ -416,8 +463,7 @@
* expensive to tell how many regions are freed in the bitmap
*/
base_command_size = max(offsetof(struct tcmu_cmd_entry,
- req.iov[se_cmd->t_bidi_data_nents +
- se_cmd->t_data_nents]),
+ req.iov[tcmu_cmd_get_block_cnt(tcmu_cmd)]),
sizeof(struct tcmu_cmd_entry));
command_size = base_command_size
+ round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE);
@@ -428,11 +474,6 @@
mb = udev->mb_addr;
cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
- data_length = se_cmd->data_length;
- if (se_cmd->se_cmd_flags & SCF_BIDI) {
- BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
- data_length += se_cmd->t_bidi_data_sg->length;
- }
if ((command_size > (udev->cmdr_size / 2)) ||
data_length > udev->data_size) {
pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu "
@@ -502,11 +543,14 @@
entry->req.iov_dif_cnt = 0;
/* Handle BIDI commands */
- iov_cnt = 0;
- alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg,
- se_cmd->t_bidi_data_nents, &iov, &iov_cnt, false);
- entry->req.iov_bidi_cnt = iov_cnt;
-
+ if (se_cmd->se_cmd_flags & SCF_BIDI) {
+ iov_cnt = 0;
+ iov++;
+ alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg,
+ se_cmd->t_bidi_data_nents, &iov, &iov_cnt,
+ false);
+ entry->req.iov_bidi_cnt = iov_cnt;
+ }
/* cmd's data_bitmap is what changed in process */
bitmap_xor(tcmu_cmd->data_bitmap, old_bitmap, udev->data_bitmap,
DATA_BLOCK_BITS);
@@ -582,19 +626,11 @@
se_cmd->scsi_sense_length);
free_data_area(udev, cmd);
} else if (se_cmd->se_cmd_flags & SCF_BIDI) {
- DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS);
-
/* Get Data-In buffer before clean up */
- bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS);
- gather_data_area(udev, bitmap,
- se_cmd->t_bidi_data_sg, se_cmd->t_bidi_data_nents);
+ gather_data_area(udev, cmd, true);
free_data_area(udev, cmd);
} else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
- DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS);
-
- bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS);
- gather_data_area(udev, bitmap,
- se_cmd->t_data_sg, se_cmd->t_data_nents);
+ gather_data_area(udev, cmd, false);
free_data_area(udev, cmd);
} else if (se_cmd->data_direction == DMA_TO_DEVICE) {
free_data_area(udev, cmd);
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 2faed7f..acbd26b 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -52,7 +52,7 @@
obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL) += st/
-obj-$(CONFIG_QCOM_TSENS) += qcom/
+obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index a6245d5..37125c0 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -548,11 +548,29 @@
if (cpufreq_device->cpufreq_floor_state == state)
return 0;
- floor_freq = cpufreq_device->freq_table[state];
cpufreq_device->cpufreq_floor_state = state;
- cpufreq_device->floor_freq = floor_freq;
- cpufreq_update_policy(cpu);
+ /*
+ * Check if the device has a platform mitigation function that
+ * can handle the CPU freq mitigation, if not, notify cpufreq
+ * framework.
+ */
+ if (cpufreq_device->plat_ops &&
+ cpufreq_device->plat_ops->floor_limit) {
+ /*
+ * Last level is core isolation so use the frequency
+ * of previous state.
+ */
+ if (state == cpufreq_device->max_level)
+ state--;
+ floor_freq = cpufreq_device->freq_table[state];
+ cpufreq_device->floor_freq = floor_freq;
+ cpufreq_device->plat_ops->floor_limit(cpu, floor_freq);
+ } else {
+ floor_freq = cpufreq_device->freq_table[state];
+ cpufreq_device->floor_freq = floor_freq;
+ cpufreq_update_policy(cpu);
+ }
return 0;
}
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index 2013e7e..432adbc 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -24,29 +24,28 @@
LIST_HEAD(tsens_device_list);
-static int tsens_get_temp(struct tsens_sensor *s, int *temp)
+static int tsens_get_temp(void *data, int *temp)
{
+ struct tsens_sensor *s = data;
struct tsens_device *tmdev = s->tmdev;
return tmdev->ops->get_temp(s, temp);
}
-static int tsens_set_trip_temp(struct tsens_sensor *s, int trip, int temp)
+static int tsens_set_trip_temp(void *data, int low_temp, int high_temp)
{
+ struct tsens_sensor *s = data;
struct tsens_device *tmdev = s->tmdev;
- if (tmdev->ops->set_trip_temp)
- return tmdev->ops->set_trip_temp(s, trip, temp);
+ if (tmdev->ops->set_trips)
+ return tmdev->ops->set_trips(s, low_temp, high_temp);
return 0;
}
static int tsens_init(struct tsens_device *tmdev)
{
- if (tmdev->ops->hw_init)
- return tmdev->ops->hw_init(tmdev);
-
- return 0;
+ return tmdev->ops->hw_init(tmdev);
}
static int tsens_register_interrupts(struct tsens_device *tmdev)
@@ -85,19 +84,16 @@
static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = {
.get_temp = tsens_get_temp,
- .set_trip_temp = tsens_set_trip_temp,
+ .set_trips = tsens_set_trip_temp,
};
static int get_device_tree_data(struct platform_device *pdev,
struct tsens_device *tmdev)
{
struct device_node *of_node = pdev->dev.of_node;
- u32 *hw_id, *client_id;
- u32 rc = 0, i, tsens_num_sensors = 0;
- int tsens_len;
const struct of_device_id *id;
const struct tsens_data *data;
- struct resource *res_tsens_mem, *res_mem = NULL;
+ struct resource *res_tsens_mem;
if (!of_match_node(tsens_table, of_node)) {
pr_err("Need to read SoC specific fuse map\n");
@@ -111,16 +107,6 @@
}
data = id->data;
- hw_id = devm_kzalloc(&pdev->dev,
- tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!hw_id)
- return -ENOMEM;
-
- client_id = devm_kzalloc(&pdev->dev,
- tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!client_id)
- return -ENOMEM;
-
tmdev->ops = data->ops;
tmdev->ctrl_data = data;
tmdev->pdev = pdev;
@@ -132,49 +118,32 @@
/* TSENS register region */
res_tsens_mem = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "tsens_physical");
+ IORESOURCE_MEM, "tsens_srot_physical");
if (!res_tsens_mem) {
pr_err("Could not get tsens physical address resource\n");
return -EINVAL;
}
- tsens_len = res_tsens_mem->end - res_tsens_mem->start + 1;
+ tmdev->tsens_srot_addr = devm_ioremap_resource(&pdev->dev,
+ res_tsens_mem);
+ if (IS_ERR(tmdev->tsens_srot_addr)) {
+ dev_err(&pdev->dev, "Failed to IO map TSENS registers.\n");
+ return PTR_ERR(tmdev->tsens_srot_addr);
+ }
- res_mem = request_mem_region(res_tsens_mem->start,
- tsens_len, res_tsens_mem->name);
- if (!res_mem) {
- pr_err("Request tsens physical memory region failed\n");
+ /* TSENS TM register region */
+ res_tsens_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "tsens_tm_physical");
+ if (!res_tsens_mem) {
+ pr_err("Could not get tsens physical address resource\n");
return -EINVAL;
}
- tmdev->tsens_addr = ioremap(res_mem->start, tsens_len);
- if (!tmdev->tsens_addr) {
- pr_err("Failed to IO map TSENS registers.\n");
- return -EINVAL;
- }
-
- rc = of_property_read_u32_array(of_node,
- "qcom,sensor-id", hw_id, tsens_num_sensors);
- if (rc) {
- pr_err("Default sensor id mapping\n");
- for (i = 0; i < tsens_num_sensors; i++)
- tmdev->sensor[i].hw_id = i;
- } else {
- pr_err("Use specified sensor id mapping\n");
- for (i = 0; i < tsens_num_sensors; i++)
- tmdev->sensor[i].hw_id = hw_id[i];
- }
-
- rc = of_property_read_u32_array(of_node,
- "qcom,client-id", client_id, tsens_num_sensors);
- if (rc) {
- for (i = 0; i < tsens_num_sensors; i++)
- tmdev->sensor[i].id = i;
- pr_debug("Default client id mapping\n");
- } else {
- for (i = 0; i < tsens_num_sensors; i++)
- tmdev->sensor[i].id = client_id[i];
- pr_debug("Use specified client id mapping\n");
+ tmdev->tsens_tm_addr = devm_ioremap_resource(&pdev->dev,
+ res_tsens_mem);
+ if (IS_ERR(tmdev->tsens_tm_addr)) {
+ dev_err(&pdev->dev, "Failed to IO map TSENS TM registers.\n");
+ return PTR_ERR(tmdev->tsens_tm_addr);
}
return 0;
@@ -182,20 +151,28 @@
static int tsens_thermal_zone_register(struct tsens_device *tmdev)
{
- int rc = 0, i = 0;
+ int i = 0, sensor_missing = 0;
- for (i = 0; i < tmdev->num_sensors; i++) {
+ for (i = 0; i < TSENS_MAX_SENSORS; i++) {
tmdev->sensor[i].tmdev = tmdev;
- tmdev->sensor[i].tzd = devm_thermal_zone_of_sensor_register(
- &tmdev->pdev->dev, i, &tmdev->sensor[i],
- &tsens_tm_thermal_zone_ops);
+ tmdev->sensor[i].hw_id = i;
+ tmdev->sensor[i].tzd =
+ devm_thermal_zone_of_sensor_register(
+ &tmdev->pdev->dev, i,
+ &tmdev->sensor[i], &tsens_tm_thermal_zone_ops);
if (IS_ERR(tmdev->sensor[i].tzd)) {
- pr_err("Error registering sensor:%d\n", i);
+ pr_debug("Error registering sensor:%d\n", i);
+ sensor_missing++;
continue;
}
}
- return rc;
+ if (sensor_missing == TSENS_MAX_SENSORS) {
+ pr_err("No TSENS sensors to register?\n");
+ return -ENODEV;
+ }
+
+ return 0;
}
static int tsens_tm_remove(struct platform_device *pdev)
@@ -207,32 +184,19 @@
int tsens_tm_probe(struct platform_device *pdev)
{
- struct device_node *of_node = pdev->dev.of_node;
struct tsens_device *tmdev = NULL;
- u32 tsens_num_sensors = 0;
int rc;
if (!(pdev->dev.of_node))
return -ENODEV;
- rc = of_property_read_u32(of_node,
- "qcom,sensors", &tsens_num_sensors);
- if (rc || (!tsens_num_sensors)) {
- dev_err(&pdev->dev, "missing sensors\n");
- return -ENODEV;
- }
-
tmdev = devm_kzalloc(&pdev->dev,
sizeof(struct tsens_device) +
- tsens_num_sensors *
+ TSENS_MAX_SENSORS *
sizeof(struct tsens_sensor),
GFP_KERNEL);
- if (tmdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
+ if (tmdev == NULL)
return -ENOMEM;
- }
-
- tmdev->num_sensors = tsens_num_sensors;
rc = get_device_tree_data(pdev, tmdev);
if (rc) {
@@ -241,8 +205,10 @@
}
rc = tsens_init(tmdev);
- if (rc)
+ if (rc) {
+ pr_err("Error initializing TSENS controller\n");
return rc;
+ }
rc = tsens_thermal_zone_register(tmdev);
if (rc) {
diff --git a/drivers/thermal/qcom/bcl_peripheral.c b/drivers/thermal/qcom/bcl_peripheral.c
index 55ff770..75e553f 100644
--- a/drivers/thermal/qcom/bcl_peripheral.c
+++ b/drivers/thermal/qcom/bcl_peripheral.c
@@ -259,7 +259,7 @@
*/
for (vbat_idx = 2; vbat_idx < BCL_STD_VBAT_NR;
vbat_idx++) {
- if (vbat_uv > vbat_low[vbat_idx])
+ if (vbat_uv >= vbat_low[vbat_idx])
continue;
break;
}
@@ -274,7 +274,7 @@
*/
for (vbat_idx = 1; vbat_idx < (BCL_STD_VBAT_NR - 1);
vbat_idx++) {
- if (vbat_uv > vbat_low[vbat_idx])
+ if (vbat_uv >= vbat_low[vbat_idx])
continue;
break;
}
diff --git a/drivers/thermal/qcom/msm_lmh_dcvs.c b/drivers/thermal/qcom/msm_lmh_dcvs.c
index 7b6952f..74f5ce0 100644
--- a/drivers/thermal/qcom/msm_lmh_dcvs.c
+++ b/drivers/thermal/qcom/msm_lmh_dcvs.c
@@ -396,8 +396,6 @@
continue;
lmh_node = of_parse_phandle(cpu_node, "qcom,lmh-dcvs", 0);
if (lmh_node == dn) {
- affinity = MPIDR_AFFINITY_LEVEL(
- cpu_logical_map(cpu), 1);
/*set the cpumask*/
cpumask_set_cpu(cpu, &(mask));
}
@@ -409,7 +407,7 @@
* We return error if none of the CPUs have
* reference to our LMH node
*/
- if (affinity == -1)
+ if (cpumask_empty(&mask))
return -EINVAL;
ret = limits_dcvs_get_freq_limits(cpumask_first(&mask), &max_freq,
@@ -426,6 +424,9 @@
return -ENOMEM;
cpumask_copy(&hw->core_map, &mask);
+ ret = of_property_read_u32(dn, "qcom,affinity", &affinity);
+ if (ret)
+ return -ENODEV;
switch (affinity) {
case 0:
hw->affinity = LIMITS_CLUSTER_0;
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index b9ebb65..3b9b01a 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -23,9 +23,9 @@
#define DEBUG_SIZE 10
#define TSENS_MAX_SENSORS 16
-#define TSENS_CONTROLLER_ID(n) ((n) + 0x1000)
+#define TSENS_CONTROLLER_ID(n) (n)
#define TSENS_CTRL_ADDR(n) (n)
-#define TSENS_TM_SN_STATUS(n) ((n) + 0x10a0)
+#define TSENS_TM_SN_STATUS(n) ((n) + 0xa0)
enum tsens_dbg_type {
TSENS_DBG_POLL,
@@ -87,7 +87,7 @@
struct tsens_ops {
int (*hw_init)(struct tsens_device *);
int (*get_temp)(struct tsens_sensor *, int *);
- int (*set_trip_temp)(struct tsens_sensor *, int, int);
+ int (*set_trips)(struct tsens_sensor *, int, int);
int (*interrupts_reg)(struct tsens_device *);
int (*dbg)(struct tsens_device *, u32, u32, int *);
};
@@ -121,7 +121,8 @@
u32 num_sensors;
struct regmap *map;
struct regmap_field *status_field;
- void *tsens_addr;
+ void __iomem *tsens_srot_addr;
+ void __iomem *tsens_tm_addr;
const struct tsens_ops *ops;
struct tsens_dbg_context tsens_dbg;
spinlock_t tsens_crit_lock;
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index 1f0bee9..13b183d 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.c
@@ -18,19 +18,20 @@
#include <linux/of.h>
#include <linux/vmalloc.h>
#include "tsens.h"
+#include "thermal_core.h"
#define TSENS_DRIVER_NAME "msm-tsens"
-#define TSENS_TM_INT_EN(n) ((n) + 0x1004)
-#define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x1014)
-#define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x1018)
-#define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x101c)
+#define TSENS_TM_INT_EN(n) ((n) + 0x4)
+#define TSENS_TM_CRITICAL_INT_STATUS(n) ((n) + 0x14)
+#define TSENS_TM_CRITICAL_INT_CLEAR(n) ((n) + 0x18)
+#define TSENS_TM_CRITICAL_INT_MASK(n) ((n) + 0x1c)
#define TSENS_TM_CRITICAL_WD_BARK BIT(31)
#define TSENS_TM_CRITICAL_CYCLE_MONITOR BIT(30)
#define TSENS_TM_CRITICAL_INT_EN BIT(2)
#define TSENS_TM_UPPER_INT_EN BIT(1)
#define TSENS_TM_LOWER_INT_EN BIT(0)
-#define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x1020)
+#define TSENS_TM_SN_UPPER_LOWER_THRESHOLD(n) ((n) + 0x20)
#define TSENS_TM_SN_ADDR_OFFSET 0x4
#define TSENS_TM_UPPER_THRESHOLD_SET(n) ((n) << 12)
#define TSENS_TM_UPPER_THRESHOLD_VALUE_SHIFT(n) ((n) >> 12)
@@ -39,13 +40,13 @@
#define TSENS_TM_UPPER_THRESHOLD_MASK 0xfff000
#define TSENS_TM_LOWER_THRESHOLD_MASK 0xfff
#define TSENS_TM_UPPER_THRESHOLD_SHIFT 12
-#define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x1060)
+#define TSENS_TM_SN_CRITICAL_THRESHOLD(n) ((n) + 0x60)
#define TSENS_STATUS_ADDR_OFFSET 2
#define TSENS_TM_UPPER_INT_MASK(n) (((n) & 0xffff0000) >> 16)
#define TSENS_TM_LOWER_INT_MASK(n) ((n) & 0xffff)
-#define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x1008)
-#define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0x100c)
-#define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x1010)
+#define TSENS_TM_UPPER_LOWER_INT_STATUS(n) ((n) + 0x8)
+#define TSENS_TM_UPPER_LOWER_INT_CLEAR(n) ((n) + 0xc)
+#define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10)
#define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16))
#define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff
#define TSENS_TM_SN_STATUS_VALID_BIT BIT(21)
@@ -55,6 +56,7 @@
#define TSENS_TM_SN_LAST_TEMP_MASK 0xfff
#define TSENS_TM_CODE_BIT_MASK 0xfff
#define TSENS_TM_CODE_SIGN_BIT 0x800
+#define TSENS_TM_SCALE_DECI_MILLIDEG 100
#define TSENS_EN BIT(0)
@@ -67,7 +69,7 @@
last_temp |= code_mask;
}
- *temp = last_temp * 100;
+ *temp = last_temp * TSENS_TM_SCALE_DECI_MILLIDEG;
}
static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
@@ -81,7 +83,7 @@
return -EINVAL;
tmdev = sensor->tmdev;
- sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
+ sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_tm_addr);
code = readl_relaxed_no_log(sensor_addr +
(sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
@@ -130,7 +132,6 @@
{
struct tsens_device *tmdev = NULL;
unsigned int reg_cntl, mask;
- unsigned long flags;
int rc = 0;
/* clear the interrupt and unmask */
@@ -141,56 +142,57 @@
if (!tmdev)
return -EINVAL;
- spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
+
mask = (tm_sensor->hw_id);
switch (trip) {
case THERMAL_TRIP_CRITICAL:
tmdev->sensor[tm_sensor->hw_id].
thr_state.crit_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK
- (tmdev->tsens_addr));
+ (tmdev->tsens_tm_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
writel_relaxed(reg_cntl | (1 << mask),
(TSENS_TM_CRITICAL_INT_MASK
- (tmdev->tsens_addr)));
+ (tmdev->tsens_tm_addr)));
else
writel_relaxed(reg_cntl & ~(1 << mask),
(TSENS_TM_CRITICAL_INT_MASK
- (tmdev->tsens_addr)));
+ (tmdev->tsens_tm_addr)));
break;
- case THERMAL_TRIP_ACTIVE:
+ case THERMAL_TRIP_CONFIGURABLE_HI:
tmdev->sensor[tm_sensor->hw_id].
thr_state.high_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
- (tmdev->tsens_addr));
+ (tmdev->tsens_tm_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
writel_relaxed(reg_cntl |
(TSENS_TM_UPPER_INT_SET(mask)),
(TSENS_TM_UPPER_LOWER_INT_MASK
- (tmdev->tsens_addr)));
+ (tmdev->tsens_tm_addr)));
else
writel_relaxed(reg_cntl &
~(TSENS_TM_UPPER_INT_SET(mask)),
(TSENS_TM_UPPER_LOWER_INT_MASK
- (tmdev->tsens_addr)));
+ (tmdev->tsens_tm_addr)));
break;
- case THERMAL_TRIP_PASSIVE:
+ case THERMAL_TRIP_CONFIGURABLE_LOW:
tmdev->sensor[tm_sensor->hw_id].
thr_state.low_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
- (tmdev->tsens_addr));
+ (tmdev->tsens_tm_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
writel_relaxed(reg_cntl | (1 << mask),
- (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr)));
+ (TSENS_TM_UPPER_LOWER_INT_MASK
+ (tmdev->tsens_tm_addr)));
else
writel_relaxed(reg_cntl & ~(1 << mask),
- (TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr)));
+ (TSENS_TM_UPPER_LOWER_INT_MASK
+ (tmdev->tsens_tm_addr)));
break;
default:
rc = -EINVAL;
}
- spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
/* Activate and enable the respective trip threshold setting */
mb();
@@ -198,14 +200,14 @@
}
static int tsens2xxx_set_trip_temp(struct tsens_sensor *tm_sensor,
- int trip, int temp)
+ int low_temp, int high_temp)
{
unsigned int reg_cntl;
unsigned long flags;
struct tsens_device *tmdev = NULL;
int rc = 0;
- if (!tm_sensor || trip < 0)
+ if (!tm_sensor)
return -EINVAL;
tmdev = tm_sensor->tmdev;
@@ -213,56 +215,81 @@
return -EINVAL;
spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
- switch (trip) {
- case THERMAL_TRIP_CRITICAL:
+
+ if (high_temp != INT_MAX) {
tmdev->sensor[tm_sensor->hw_id].
- thr_state.crit_temp = temp;
- temp &= TSENS_TM_SN_CRITICAL_THRESHOLD_MASK;
- writel_relaxed(temp,
- (TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr) +
- (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
- break;
- case THERMAL_TRIP_ACTIVE:
- tmdev->sensor[tm_sensor->hw_id].
- thr_state.high_temp = temp;
+ thr_state.high_temp = high_temp;
reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD
- (tmdev->tsens_addr)) +
+ (tmdev->tsens_tm_addr)) +
(tm_sensor->hw_id *
TSENS_TM_SN_ADDR_OFFSET));
- temp = TSENS_TM_UPPER_THRESHOLD_SET(temp);
- temp &= TSENS_TM_UPPER_THRESHOLD_MASK;
+ high_temp /= TSENS_TM_SCALE_DECI_MILLIDEG;
+ high_temp = TSENS_TM_UPPER_THRESHOLD_SET(high_temp);
+ high_temp &= TSENS_TM_UPPER_THRESHOLD_MASK;
reg_cntl &= ~TSENS_TM_UPPER_THRESHOLD_MASK;
- writel_relaxed(reg_cntl | temp,
- (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) +
+ writel_relaxed(reg_cntl | high_temp,
+ (TSENS_TM_SN_UPPER_LOWER_THRESHOLD
+ (tmdev->tsens_tm_addr) +
(tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
- break;
- case THERMAL_TRIP_PASSIVE:
- tmdev->sensor[tm_sensor->hw_id].
- thr_state.low_temp = temp;
- reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD
- (tmdev->tsens_addr)) +
- (tm_sensor->hw_id *
- TSENS_TM_SN_ADDR_OFFSET));
- temp &= TSENS_TM_LOWER_THRESHOLD_MASK;
- reg_cntl &= ~TSENS_TM_LOWER_THRESHOLD_MASK;
- writel_relaxed(reg_cntl | temp,
- (TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr) +
- (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
- break;
- default:
- pr_err("Invalid trip to TSENS: %d\n", trip);
- rc = -EINVAL;
}
- spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
+ if (low_temp != INT_MIN) {
+ tmdev->sensor[tm_sensor->hw_id].
+ thr_state.low_temp = low_temp;
+ reg_cntl = readl_relaxed((TSENS_TM_SN_UPPER_LOWER_THRESHOLD
+ (tmdev->tsens_tm_addr)) +
+ (tm_sensor->hw_id *
+ TSENS_TM_SN_ADDR_OFFSET));
+ low_temp /= TSENS_TM_SCALE_DECI_MILLIDEG;
+ low_temp &= TSENS_TM_LOWER_THRESHOLD_MASK;
+ reg_cntl &= ~TSENS_TM_LOWER_THRESHOLD_MASK;
+ writel_relaxed(reg_cntl | low_temp,
+ (TSENS_TM_SN_UPPER_LOWER_THRESHOLD
+ (tmdev->tsens_tm_addr) +
+ (tm_sensor->hw_id * TSENS_TM_SN_ADDR_OFFSET)));
+ }
+
/* Set trip temperature thresholds */
mb();
- rc = tsens_tm_activate_trip_type(tm_sensor, trip,
+ if (high_temp != INT_MAX) {
+ rc = tsens_tm_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_HI,
THERMAL_TRIP_ACTIVATION_ENABLED);
- if (rc)
- pr_err("Error during trip activation :%d\n", rc);
+ if (rc) {
+ pr_err("trip high enable error :%d\n", rc);
+ goto fail;
+ }
+ } else {
+ rc = tsens_tm_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_HI,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc) {
+ pr_err("trip high disable error :%d\n", rc);
+ goto fail;
+ }
+ }
+ if (low_temp != INT_MIN) {
+ rc = tsens_tm_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_TRIP_ACTIVATION_ENABLED);
+ if (rc) {
+ pr_err("trip low enable activation error :%d\n", rc);
+ goto fail;
+ }
+ } else {
+ rc = tsens_tm_activate_trip_type(tm_sensor,
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc) {
+ pr_err("trip low disable error :%d\n", rc);
+ goto fail;
+ }
+ }
+
+fail:
+ spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
return rc;
}
@@ -277,13 +304,13 @@
void __iomem *wd_critical_addr;
int wd_mask;
- sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr);
+ sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr);
sensor_int_mask_addr =
- TSENS_TM_CRITICAL_INT_MASK(tm->tsens_addr);
+ TSENS_TM_CRITICAL_INT_MASK(tm->tsens_tm_addr);
sensor_critical_addr =
- TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_addr);
+ TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_tm_addr);
wd_critical_addr =
- TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_addr);
+ TSENS_TM_CRITICAL_INT_STATUS(tm->tsens_tm_addr);
if (tm->ctrl_data->wd_bark) {
wd_mask = readl_relaxed(wd_critical_addr);
@@ -294,19 +321,22 @@
*/
writel_relaxed(wd_mask | TSENS_TM_CRITICAL_WD_BARK,
(TSENS_TM_CRITICAL_INT_CLEAR
- (tm->tsens_addr)));
+ (tm->tsens_tm_addr)));
writel_relaxed(wd_mask & ~(TSENS_TM_CRITICAL_WD_BARK),
(TSENS_TM_CRITICAL_INT_CLEAR
- (tm->tsens_addr)));
+ (tm->tsens_tm_addr)));
tm->tsens_dbg.tsens_critical_wd_cnt++;
return IRQ_HANDLED;
}
}
- for (i = 0; i < tm->num_sensors; i++) {
+ for (i = 0; i < TSENS_MAX_SENSORS; i++) {
int int_mask, int_mask_val;
u32 addr_offset;
+ if (IS_ERR(tm->sensor[i].tzd))
+ continue;
+
spin_lock_irqsave(&tm->tsens_crit_lock, flags);
addr_offset = tm->sensor[i].hw_id *
TSENS_TM_SN_ADDR_OFFSET;
@@ -320,13 +350,14 @@
/* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_CRITICAL_INT_MASK(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
/* Clear the corresponding sensors interrupt */
writel_relaxed(int_mask_val,
- TSENS_TM_CRITICAL_INT_CLEAR(tm->tsens_addr));
+ TSENS_TM_CRITICAL_INT_CLEAR
+ (tm->tsens_tm_addr));
writel_relaxed(0,
TSENS_TM_CRITICAL_INT_CLEAR(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
tm->sensor[i].thr_state.
crit_th_state = THERMAL_DEVICE_DISABLED;
}
@@ -342,22 +373,31 @@
static irqreturn_t tsens_tm_irq_thread(int irq, void *data)
{
struct tsens_device *tm = data;
- unsigned int i, status, threshold;
+ unsigned int i, status, threshold, temp;
unsigned long flags;
void __iomem *sensor_status_addr;
void __iomem *sensor_int_mask_addr;
void __iomem *sensor_upper_lower_addr;
u32 addr_offset = 0;
- sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr);
+ sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_tm_addr);
sensor_int_mask_addr =
- TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_addr);
+ TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_tm_addr);
sensor_upper_lower_addr =
- TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_addr);
+ TSENS_TM_SN_UPPER_LOWER_THRESHOLD(tm->tsens_tm_addr);
- for (i = 0; i < tm->num_sensors; i++) {
+ for (i = 0; i < TSENS_MAX_SENSORS; i++) {
bool upper_thr = false, lower_thr = false;
- int int_mask, int_mask_val = 0;
+ int int_mask, int_mask_val = 0, rc;
+
+ if (IS_ERR(tm->sensor[i].tzd))
+ continue;
+
+ rc = tsens2xxx_get_temp(&tm->sensor[i], &temp);
+ if (rc) {
+ pr_debug("Error:%d reading temp sensor:%d\n", rc, i);
+ continue;
+ }
spin_lock_irqsave(&tm->tsens_upp_low_lock, flags);
addr_offset = tm->sensor[i].hw_id *
@@ -376,17 +416,28 @@
/* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_UPPER_LOWER_INT_MASK(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
/* Clear the corresponding sensors interrupt */
writel_relaxed(int_mask_val,
TSENS_TM_UPPER_LOWER_INT_CLEAR(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
writel_relaxed(0,
TSENS_TM_UPPER_LOWER_INT_CLEAR(
- tm->tsens_addr));
- upper_thr = true;
- tm->sensor[i].thr_state.
+ tm->tsens_tm_addr));
+ if (TSENS_TM_UPPER_THRESHOLD_VALUE(threshold) >
+ (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) {
+ pr_debug("Re-arm high threshold\n");
+ rc = tsens_tm_activate_trip_type(
+ &tm->sensor[i],
+ THERMAL_TRIP_CONFIGURABLE_HI,
+ THERMAL_TRIP_ACTIVATION_ENABLED);
+ if (rc)
+ pr_err("high rearm failed:%d\n", rc);
+ } else {
+ upper_thr = true;
+ tm->sensor[i].thr_state.
high_th_state = THERMAL_DEVICE_DISABLED;
+ }
}
if ((status & TSENS_TM_SN_STATUS_LOWER_STATUS) &&
@@ -397,32 +448,36 @@
/* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_UPPER_LOWER_INT_MASK(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
/* Clear the corresponding sensors interrupt */
writel_relaxed(int_mask_val,
TSENS_TM_UPPER_LOWER_INT_CLEAR(
- tm->tsens_addr));
+ tm->tsens_tm_addr));
writel_relaxed(0,
TSENS_TM_UPPER_LOWER_INT_CLEAR(
- tm->tsens_addr));
- lower_thr = true;
- tm->sensor[i].thr_state.
+ tm->tsens_tm_addr));
+ if (TSENS_TM_LOWER_THRESHOLD_VALUE(threshold)
+ < (temp/TSENS_TM_SCALE_DECI_MILLIDEG)) {
+ pr_debug("Re-arm low threshold\n");
+ rc = tsens_tm_activate_trip_type(
+ &tm->sensor[i],
+ THERMAL_TRIP_CONFIGURABLE_LOW,
+ THERMAL_TRIP_ACTIVATION_ENABLED);
+ if (rc)
+ pr_err("low rearm failed:%d\n", rc);
+ } else {
+ lower_thr = true;
+ tm->sensor[i].thr_state.
low_th_state = THERMAL_DEVICE_DISABLED;
+ }
}
spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags);
if (upper_thr || lower_thr) {
- int temp;
- enum thermal_trip_type trip =
- THERMAL_TRIP_CONFIGURABLE_LOW;
-
- if (upper_thr)
- trip = THERMAL_TRIP_CONFIGURABLE_HI;
- tsens2xxx_get_temp(&tm->sensor[i], &temp);
/* Use id for multiple controllers */
pr_debug("sensor:%d trigger temp (%d degC)\n",
- tm->sensor[i].hw_id,
- (status & TSENS_TM_SN_LAST_TEMP_MASK));
+ tm->sensor[i].hw_id, temp);
+ of_thermal_handle_trip(tm->sensor[i].tzd);
}
}
@@ -442,7 +497,7 @@
unsigned int srot_val;
int crit_mask;
- srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_addr + 0x4);
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
srot_val = readl_relaxed(srot_addr);
if (!(srot_val & TSENS_EN)) {
pr_err("TSENS device is not enabled\n");
@@ -451,18 +506,18 @@
if (tmdev->ctrl_data->cycle_monitor) {
sensor_int_mask_addr =
- TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr);
+ TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_tm_addr);
crit_mask = readl_relaxed(sensor_int_mask_addr);
writel_relaxed(
crit_mask | tmdev->ctrl_data->cycle_compltn_monitor_val,
(TSENS_TM_CRITICAL_INT_MASK
- (tmdev->tsens_addr)));
+ (tmdev->tsens_tm_addr)));
/*Update critical cycle monitoring*/
mb();
}
writel_relaxed(TSENS_TM_CRITICAL_INT_EN |
TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN,
- TSENS_TM_INT_EN(tmdev->tsens_addr));
+ TSENS_TM_INT_EN(tmdev->tsens_tm_addr));
spin_lock_init(&tmdev->tsens_crit_lock);
spin_lock_init(&tmdev->tsens_upp_low_lock);
@@ -513,7 +568,7 @@
static const struct tsens_ops ops_tsens2xxx = {
.hw_init = tsens2xxx_hw_init,
.get_temp = tsens2xxx_get_temp,
- .set_trip_temp = tsens2xxx_set_trip_temp,
+ .set_trips = tsens2xxx_set_trip_temp,
.interrupts_reg = tsens2xxx_register_interrupts,
.dbg = tsens2xxx_dbg,
};
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 9c3b6ff..df9be34 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -27,6 +27,8 @@
#include <linux/serial_core.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/msm-bus.h>
+#include <linux/msm-bus-board.h>
/* UART specific GENI registers */
#define SE_UART_LOOPBACK_CFG (0x22C)
@@ -95,6 +97,10 @@
#define GENI_UART_NR_PORTS (15)
#define DEF_FIFO_DEPTH_WORDS (16)
#define DEF_FIFO_WIDTH_BITS (32)
+#define UART_CORE2X_VOTE (10000)
+#define DEFAULT_SE_CLK (19200000)
+#define DEFAULT_BUS_WIDTH (4)
+
struct msm_geni_serial_port {
struct uart_port uport;
@@ -205,15 +211,17 @@
}
static int msm_geni_serial_poll_bit(struct uart_port *uport,
- int offset, int bit_field)
+ int offset, int bit_field, bool set)
{
int iter = 0;
unsigned int reg;
bool met = false;
+ bool cond = false;
while (iter < 1000) {
reg = geni_read_reg_nolog(uport->membase, offset);
- if (reg & bit_field) {
+ cond = reg & bit_field;
+ if (cond == set) {
met = true;
break;
}
@@ -226,8 +234,11 @@
static void msm_geni_serial_setup_tx(struct uart_port *uport,
unsigned int xmit_size)
{
+ u32 m_cmd = 0;
+
geni_write_reg_nolog(xmit_size, uport->membase, SE_UART_TX_TRANS_LEN);
- geni_setup_m_cmd(uport->membase, UART_START_TX, 0);
+ m_cmd |= (UART_START_TX << M_OPCODE_SHFT);
+ geni_write_reg_nolog(m_cmd, uport->membase, SE_GENI_M_CMD0);
/*
* Writes to enable the primary sequencer should go through before
* exiting this function.
@@ -241,41 +252,36 @@
unsigned int irq_clear = M_CMD_DONE_EN;
done = msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_CMD_DONE_EN);
+ M_CMD_DONE_EN, true);
if (!done) {
- geni_cancel_m_cmd(uport->membase);
+ geni_write_reg_nolog(M_GENI_CMD_CANCEL, uport->membase,
+ SE_GENI_S_CMD_CTRL_REG);
irq_clear |= M_CMD_CANCEL_EN;
if (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_CMD_CANCEL_EN)) {
- geni_abort_m_cmd(uport->membase);
+ M_CMD_CANCEL_EN, true)) {
+ geni_write_reg_nolog(M_GENI_CMD_ABORT, uport->membase,
+ SE_GENI_M_CMD_CTRL_REG);
irq_clear |= M_CMD_ABORT_EN;
msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_CMD_ABORT_EN);
+ M_CMD_ABORT_EN, true);
}
}
geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_M_IRQ_CLEAR);
}
-static void msm_geni_serial_poll_cancel_rx(struct uart_port *uport)
+static void msm_geni_serial_abort_rx(struct uart_port *uport)
{
- int done = 0;
unsigned int irq_clear = S_CMD_DONE_EN;
- done = msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
- S_CMD_DONE_EN);
- if (!done) {
- geni_cancel_s_cmd(uport->membase);
- irq_clear |= S_CMD_CANCEL_EN;
- if (!msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
- S_CMD_CANCEL_EN)) {
- geni_abort_s_cmd(uport->membase);
- irq_clear |= S_CMD_ABORT_EN;
- msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
- S_CMD_ABORT_EN);
- }
- }
+ geni_abort_s_cmd(uport->membase);
+ /* Ensure this goes through before polling. */
+ mb();
+ irq_clear |= S_CMD_ABORT_EN;
+ msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
+ S_GENI_CMD_ABORT, false);
geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR);
}
+
#ifdef CONFIG_CONSOLE_POLL
static int msm_geni_serial_get_char(struct uart_port *uport)
{
@@ -284,7 +290,7 @@
unsigned int s_irq_status;
if (!(msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_SEC_IRQ_EN))) {
+ M_SEC_IRQ_EN, true))) {
dev_err(uport->dev, "%s: Failed waiting for SE\n", __func__);
return -ENXIO;
}
@@ -297,7 +303,7 @@
geni_write_reg_nolog(s_irq_status, uport->membase, SE_GENI_S_IRQ_CLEAR);
if (!(msm_geni_serial_poll_bit(uport, SE_GENI_RX_FIFO_STATUS,
- RX_FIFO_WC_MSK))) {
+ RX_FIFO_WC_MSK, true))) {
dev_err(uport->dev, "%s: Failed waiting for Rx\n", __func__);
return -ENXIO;
}
@@ -323,7 +329,7 @@
SE_GENI_TX_WATERMARK_REG);
msm_geni_serial_setup_tx(uport, 1);
if (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_TX_FIFO_WATERMARK_EN))
+ M_TX_FIFO_WATERMARK_EN, true))
WARN_ON(1);
geni_write_reg_nolog(b, uport->membase, SE_GENI_TX_FIFOn);
geni_write_reg_nolog(M_TX_FIFO_WATERMARK_EN, uport->membase,
@@ -378,7 +384,7 @@
* lost.
*/
while (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_TX_FIFO_WATERMARK_EN))
+ M_TX_FIFO_WATERMARK_EN, true))
break;
chars_to_write = min((unsigned int)(count - i),
avail_fifo_bytes);
@@ -496,10 +502,10 @@
geni_cancel_m_cmd(uport->membase);
if (!msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_CMD_CANCEL_EN)) {
+ M_CMD_CANCEL_EN, true)) {
geni_abort_m_cmd(uport->membase);
msm_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
- M_CMD_ABORT_EN);
+ M_CMD_ABORT_EN, true);
geni_write_reg_nolog(M_CMD_ABORT_EN, uport->membase,
SE_GENI_M_IRQ_CLEAR);
}
@@ -510,11 +516,8 @@
{
unsigned int geni_s_irq_en;
unsigned int geni_m_irq_en;
- unsigned int geni_status;
- geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
- if (geni_status & S_GENI_CMD_ACTIVE)
- msm_geni_serial_poll_cancel_rx(uport);
+ msm_geni_serial_abort_rx(uport);
geni_s_irq_en = geni_read_reg_nolog(uport->membase,
SE_GENI_S_IRQ_EN);
geni_m_irq_en = geni_read_reg_nolog(uport->membase,
@@ -552,11 +555,7 @@
/* Possible stop rx is called multiple times. */
if (!(geni_status & S_GENI_CMD_ACTIVE))
return;
- geni_write_reg_nolog(S_GENI_CMD_CANCEL, uport->membase,
- SE_GENI_S_CMD_CTRL_REG);
- if (!msm_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
- S_CMD_CANCEL_EN))
- WARN_ON(1);
+ msm_geni_serial_abort_rx(uport);
}
static int handle_rx_hs(struct uart_port *uport,
@@ -1264,6 +1263,25 @@
}
uport->dev = &pdev->dev;
+
+ if (!(of_property_read_u32(pdev->dev.of_node, "qcom,bus-mas",
+ &dev_port->serial_rsc.bus_mas))) {
+ dev_port->serial_rsc.bus_bw =
+ msm_bus_scale_register(
+ dev_port->serial_rsc.bus_mas,
+ MSM_BUS_SLAVE_EBI_CH0,
+ (char *)dev_name(&pdev->dev),
+ false);
+ if (IS_ERR_OR_NULL(dev_port->serial_rsc.bus_bw)) {
+ ret = PTR_ERR(dev_port->serial_rsc.bus_bw);
+ goto exit_geni_serial_probe;
+ }
+ dev_port->serial_rsc.ab = UART_CORE2X_VOTE;
+ dev_port->serial_rsc.ib = DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH;
+ } else {
+ dev_info(&pdev->dev, "No bus master specified");
+ }
+
dev_port->serial_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
if (IS_ERR(dev_port->serial_rsc.se_clk)) {
ret = PTR_ERR(dev_port->serial_rsc.se_clk);
@@ -1371,6 +1389,7 @@
(struct uart_driver *)port->uport.private_data;
uart_remove_one_port(drv, &port->uport);
+ msm_bus_scale_unregister(port->serial_rsc.bus_bw);
return 0;
}
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 52c98ce..ee15d7d 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -155,4 +155,11 @@
If you compile this as a module, it will be called uio_mf624.
+config UIO_MSM_SHAREDMEM
+ bool "MSM shared memory driver"
+ default n
+ help
+ Provides the clients with their respective alloted shared memory
+ addresses which are used as transport buffer.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 8560dad..2282a69 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -9,3 +9,4 @@
obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
obj-$(CONFIG_UIO_MF624) += uio_mf624.o
obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o
+obj-$(CONFIG_UIO_MSM_SHAREDMEM) += msm_sharedmem/
diff --git a/drivers/uio/msm_sharedmem/Makefile b/drivers/uio/msm_sharedmem/Makefile
new file mode 100644
index 0000000..e6b8570
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_UIO_MSM_SHAREDMEM) := \
+ msm_sharedmem.o \
+ remote_filesystem_access_v01.o \
+ sharedmem_qmi.o \
diff --git a/drivers/uio/msm_sharedmem/msm_sharedmem.c b/drivers/uio/msm_sharedmem/msm_sharedmem.c
new file mode 100644
index 0000000..b25f55a
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/msm_sharedmem.c
@@ -0,0 +1,240 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define DRIVER_NAME "msm_sharedmem"
+#define pr_fmt(fmt) DRIVER_NAME ": %s: " fmt, __func__
+
+#include <linux/uio_driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+
+#include <soc/qcom/secure_buffer.h>
+
+#include "sharedmem_qmi.h"
+
+#define CLIENT_ID_PROP "qcom,client-id"
+
+#define MPSS_RMTS_CLIENT_ID 1
+
+static int uio_get_mem_index(struct uio_info *info, struct vm_area_struct *vma)
+{
+ if (vma->vm_pgoff >= MAX_UIO_MAPS)
+ return -EINVAL;
+
+ if (info->mem[vma->vm_pgoff].size == 0)
+ return -EINVAL;
+
+ return (int)vma->vm_pgoff;
+}
+
+static int sharedmem_mmap(struct uio_info *info, struct vm_area_struct *vma)
+{
+ int result;
+ struct uio_mem *mem;
+ int mem_index = uio_get_mem_index(info, vma);
+
+ if (mem_index < 0) {
+ pr_err("mem_index is invalid errno %d\n", mem_index);
+ return mem_index;
+ }
+
+ mem = info->mem + mem_index;
+
+ if (vma->vm_end - vma->vm_start > mem->size) {
+ pr_err("vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%pa]\n",
+ vma->vm_end, vma->vm_start,
+ (vma->vm_end - vma->vm_start), &mem->size);
+ return -EINVAL;
+ }
+ pr_debug("Attempting to setup mmap.\n");
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ result = remap_pfn_range(vma,
+ vma->vm_start,
+ mem->addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ if (result != 0)
+ pr_err("mmap Failed with errno %d\n", result);
+ else
+ pr_debug("mmap success\n");
+
+ return result;
+}
+
+/* Setup the shared ram permissions.
+ * This function currently supports the mpss client only.
+ */
+static void setup_shared_ram_perms(u32 client_id, phys_addr_t addr, u32 size)
+{
+ int ret;
+ u32 source_vmlist[1] = {VMID_HLOS};
+ int dest_vmids[2] = {VMID_HLOS, VMID_MSS_MSA};
+ int dest_perms[2] = {PERM_READ|PERM_WRITE,
+ PERM_READ|PERM_WRITE};
+
+ if (client_id != MPSS_RMTS_CLIENT_ID)
+ return;
+
+ ret = hyp_assign_phys(addr, size, source_vmlist, 1, dest_vmids,
+ dest_perms, 2);
+ if (ret != 0) {
+ if (ret == -EINVAL)
+ pr_warn("hyp_assign_phys is not supported!");
+ else
+ pr_err("hyp_assign_phys failed IPA=0x016%pa size=%u err=%d\n",
+ &addr, size, ret);
+ }
+}
+
+static int msm_sharedmem_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct uio_info *info = NULL;
+ struct resource *clnt_res = NULL;
+ u32 client_id = ((u32)~0U);
+ u32 shared_mem_size = 0;
+ void *shared_mem = NULL;
+ phys_addr_t shared_mem_pyhsical = 0;
+ bool is_addr_dynamic = false;
+ struct sharemem_qmi_entry qmi_entry;
+
+ /* Get the addresses from platform-data */
+ if (!pdev->dev.of_node) {
+ pr_err("Node not found\n");
+ ret = -ENODEV;
+ goto out;
+ }
+ clnt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!clnt_res) {
+ pr_err("resource not found\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, CLIENT_ID_PROP,
+ &client_id);
+ if (ret) {
+ client_id = ((u32)~0U);
+ pr_warn("qcom,client-id property not found\n");
+ }
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct uio_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ shared_mem_size = resource_size(clnt_res);
+ shared_mem_pyhsical = clnt_res->start;
+
+ if (shared_mem_size == 0) {
+ pr_err("Shared memory size is zero\n");
+ return -EINVAL;
+ }
+
+ if (shared_mem_pyhsical == 0) {
+ is_addr_dynamic = true;
+ shared_mem = dma_alloc_coherent(&pdev->dev, shared_mem_size,
+ &shared_mem_pyhsical, GFP_KERNEL);
+ if (shared_mem == NULL) {
+ pr_err("Shared mem alloc client=%s, size=%u\n",
+ clnt_res->name, shared_mem_size);
+ return -ENOMEM;
+ }
+ }
+
+ /* Set up the permissions for the shared ram that was allocated. */
+ setup_shared_ram_perms(client_id, shared_mem_pyhsical, shared_mem_size);
+
+ /* Setup device */
+ info->mmap = sharedmem_mmap; /* Custom mmap function. */
+ info->name = clnt_res->name;
+ info->version = "1.0";
+ info->mem[0].addr = shared_mem_pyhsical;
+ info->mem[0].size = shared_mem_size;
+ info->mem[0].memtype = UIO_MEM_PHYS;
+
+ ret = uio_register_device(&pdev->dev, info);
+ if (ret) {
+ pr_err("uio register failed ret=%d\n", ret);
+ goto out;
+ }
+ dev_set_drvdata(&pdev->dev, info);
+
+ qmi_entry.client_id = client_id;
+ qmi_entry.client_name = info->name;
+ qmi_entry.address = info->mem[0].addr;
+ qmi_entry.size = info->mem[0].size;
+ qmi_entry.is_addr_dynamic = is_addr_dynamic;
+
+ sharedmem_qmi_add_entry(&qmi_entry);
+ pr_info("Device created for client '%s'\n", clnt_res->name);
+out:
+ return ret;
+}
+
+static int msm_sharedmem_remove(struct platform_device *pdev)
+{
+ struct uio_info *info = dev_get_drvdata(&pdev->dev);
+
+ uio_unregister_device(info);
+
+ return 0;
+}
+
+static const struct of_device_id msm_sharedmem_of_match[] = {
+ {.compatible = "qcom,sharedmem-uio",},
+ {},
+};
+MODULE_DEVICE_TABLE(of, msm_sharedmem_of_match);
+
+static struct platform_driver msm_sharedmem_driver = {
+ .probe = msm_sharedmem_probe,
+ .remove = msm_sharedmem_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_sharedmem_of_match,
+ },
+};
+
+
+static int __init msm_sharedmem_init(void)
+{
+ int result;
+
+ result = sharedmem_qmi_init();
+ if (result < 0) {
+ pr_err("sharedmem_qmi_init failed result = %d\n", result);
+ return result;
+ }
+
+ result = platform_driver_register(&msm_sharedmem_driver);
+ if (result != 0) {
+ pr_err("Platform driver registration failed\n");
+ return result;
+ }
+ return 0;
+}
+
+static void __exit msm_sharedmem_exit(void)
+{
+ platform_driver_unregister(&msm_sharedmem_driver);
+ sharedmem_qmi_exit();
+}
+
+module_init(msm_sharedmem_init);
+module_exit(msm_sharedmem_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.c b/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.c
new file mode 100644
index 0000000..b04c913
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.c
@@ -0,0 +1,80 @@
+ /* Copyright (c) 2014-2015, 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/qmi_encdec.h>
+
+#include <soc/qcom/msm_qmi_interface.h>
+
+#include "remote_filesystem_access_v01.h"
+
+struct elem_info rfsa_get_buff_addr_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct rfsa_get_buff_addr_req_msg_v01,
+ client_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct rfsa_get_buff_addr_req_msg_v01,
+ size),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info rfsa_get_buff_addr_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct rfsa_get_buff_addr_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct rfsa_get_buff_addr_resp_msg_v01,
+ address_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(uint64_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct rfsa_get_buff_addr_resp_msg_v01,
+ address),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .is_array = QMI_COMMON_TLV_TYPE,
+ },
+};
+
diff --git a/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.h b/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.h
new file mode 100644
index 0000000..7ea8ce6
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/remote_filesystem_access_v01.h
@@ -0,0 +1,39 @@
+ /* Copyright (c) 2014-2015, 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.
+ *
+ */
+#ifndef __REMOTE_FILESYSTEM_ACCESS_V01_H__
+#define __REMOTE_FILESYSTEM_ACCESS_V01_H__
+
+#define RFSA_SERVICE_ID_V01 0x1C
+#define RFSA_SERVICE_VERS_V01 0x01
+
+#define QMI_RFSA_GET_BUFF_ADDR_REQ_MSG_V01 0x0023
+#define QMI_RFSA_GET_BUFF_ADDR_RESP_MSG_V01 0x0023
+
+#define RFSA_GET_BUFF_ADDR_REQ_MSG_MAX_LEN_V01 14
+#define RFSA_GET_BUFF_ADDR_RESP_MSG_MAX_LEN_V01 18
+
+extern struct elem_info rfsa_get_buff_addr_req_msg_v01_ei[];
+extern struct elem_info rfsa_get_buff_addr_resp_msg_v01_ei[];
+
+struct rfsa_get_buff_addr_req_msg_v01 {
+ uint32_t client_id;
+ uint32_t size;
+};
+
+struct rfsa_get_buff_addr_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+ uint8_t address_valid;
+ uint64_t address;
+};
+
+#endif /* __REMOTE_FILESYSTEM_ACCESS_V01_H__ */
diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.c b/drivers/uio/msm_sharedmem/sharedmem_qmi.c
new file mode 100644
index 0000000..fd95dee
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.c
@@ -0,0 +1,453 @@
+/* Copyright (c) 2014-2015, 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.
+ *
+ */
+
+#define DRIVER_NAME "msm_sharedmem"
+#define pr_fmt(fmt) DRIVER_NAME ": %s: " fmt, __func__
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <soc/qcom/msm_qmi_interface.h>
+#include "sharedmem_qmi.h"
+#include "remote_filesystem_access_v01.h"
+
+#define RFSA_SERVICE_INSTANCE_NUM 1
+#define SHARED_ADDR_ENTRY_NAME_MAX_LEN 10
+
+struct shared_addr_entry {
+ u32 id;
+ u64 address;
+ u32 size;
+ u64 request_count;
+ bool is_addr_dynamic;
+ char name[SHARED_ADDR_ENTRY_NAME_MAX_LEN + 1];
+};
+
+struct shared_addr_list {
+ struct list_head node;
+ struct shared_addr_entry entry;
+};
+
+static struct shared_addr_list list;
+
+static struct qmi_handle *sharedmem_qmi_svc_handle;
+static void sharedmem_qmi_svc_recv_msg(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_recv_msg, sharedmem_qmi_svc_recv_msg);
+static struct workqueue_struct *sharedmem_qmi_svc_workqueue;
+static struct dentry *dir_ent;
+
+static u32 rfsa_count;
+static u32 rmts_count;
+
+static DECLARE_RWSEM(sharedmem_list_lock); /* declare list lock semaphore */
+
+static struct work_struct sharedmem_qmi_init_work;
+
+static struct msg_desc rfsa_get_buffer_addr_req_desc = {
+ .max_msg_len = RFSA_GET_BUFF_ADDR_REQ_MSG_MAX_LEN_V01,
+ .msg_id = QMI_RFSA_GET_BUFF_ADDR_REQ_MSG_V01,
+ .ei_array = rfsa_get_buff_addr_req_msg_v01_ei,
+};
+
+static struct msg_desc rfsa_get_buffer_addr_resp_desc = {
+ .max_msg_len = RFSA_GET_BUFF_ADDR_RESP_MSG_MAX_LEN_V01,
+ .msg_id = QMI_RFSA_GET_BUFF_ADDR_RESP_MSG_V01,
+ .ei_array = rfsa_get_buff_addr_resp_msg_v01_ei,
+};
+
+void sharedmem_qmi_add_entry(struct sharemem_qmi_entry *qmi_entry)
+{
+ struct shared_addr_list *list_entry;
+
+ list_entry = kzalloc(sizeof(*list_entry), GFP_KERNEL);
+
+ /* If we cannot add the entry log the failure and bail */
+ if (list_entry == NULL) {
+ pr_err("Alloc of new list entry failed\n");
+ return;
+ }
+
+ /* Copy as much of the client name that can fit in the entry. */
+ strlcpy(list_entry->entry.name, qmi_entry->client_name,
+ sizeof(list_entry->entry.name));
+
+ /* Setup the rest of the entry. */
+ list_entry->entry.id = qmi_entry->client_id;
+ list_entry->entry.address = qmi_entry->address;
+ list_entry->entry.size = qmi_entry->size;
+ list_entry->entry.is_addr_dynamic = qmi_entry->is_addr_dynamic;
+ list_entry->entry.request_count = 0;
+
+ down_write(&sharedmem_list_lock);
+ list_add_tail(&(list_entry->node), &(list.node));
+ up_write(&sharedmem_list_lock);
+ pr_debug("Added new entry to list\n");
+
+}
+
+static int get_buffer_for_client(u32 id, u32 size, u64 *address)
+{
+ int result = -ENOENT;
+ int client_found = 0;
+ struct list_head *curr_node;
+ struct shared_addr_list *list_entry;
+
+ if (size == 0)
+ return -ENOMEM;
+
+ down_read(&sharedmem_list_lock);
+
+ list_for_each(curr_node, &list.node) {
+ list_entry = list_entry(curr_node, struct shared_addr_list,
+ node);
+ if (list_entry->entry.id == id) {
+ if (list_entry->entry.size >= size) {
+ *address = list_entry->entry.address;
+ list_entry->entry.request_count++;
+ result = 0;
+ } else {
+ pr_err("Shared mem req too large for id=%u\n",
+ id);
+ result = -ENOMEM;
+ }
+ client_found = 1;
+ break;
+ }
+ }
+
+ up_read(&sharedmem_list_lock);
+
+ if (client_found != 1) {
+ pr_err("Unknown client id %u\n", id);
+ result = -ENOENT;
+ }
+ return result;
+}
+
+static int sharedmem_qmi_get_buffer(void *conn_h, void *req_handle, void *req)
+{
+ struct rfsa_get_buff_addr_req_msg_v01 *get_buffer_req;
+ struct rfsa_get_buff_addr_resp_msg_v01 get_buffer_resp;
+ int result;
+ u64 address = 0;
+
+ get_buffer_req = (struct rfsa_get_buff_addr_req_msg_v01 *)req;
+ pr_debug("req->client_id = 0x%X and req->size = %d\n",
+ get_buffer_req->client_id, get_buffer_req->size);
+
+ result = get_buffer_for_client(get_buffer_req->client_id,
+ get_buffer_req->size, &address);
+ if (result != 0)
+ return result;
+
+ if (address == 0) {
+ pr_err("Entry found for client id= 0x%X but address is zero\n",
+ get_buffer_req->client_id);
+ return -ENOMEM;
+ }
+
+ memset(&get_buffer_resp, 0, sizeof(get_buffer_resp));
+ get_buffer_resp.address_valid = 1;
+ get_buffer_resp.address = address;
+ get_buffer_resp.resp.result = QMI_RESULT_SUCCESS_V01;
+
+ result = qmi_send_resp_from_cb(sharedmem_qmi_svc_handle, conn_h,
+ req_handle,
+ &rfsa_get_buffer_addr_resp_desc,
+ &get_buffer_resp,
+ sizeof(get_buffer_resp));
+ return result;
+}
+
+
+static int sharedmem_qmi_connect_cb(struct qmi_handle *handle, void *conn_h)
+{
+ if (sharedmem_qmi_svc_handle != handle || !conn_h)
+ return -EINVAL;
+ return 0;
+}
+
+static int sharedmem_qmi_disconnect_cb(struct qmi_handle *handle, void *conn_h)
+{
+ if (sharedmem_qmi_svc_handle != handle || !conn_h)
+ return -EINVAL;
+ return 0;
+}
+
+static int sharedmem_qmi_req_desc_cb(unsigned int msg_id,
+ struct msg_desc **req_desc)
+{
+ int rc;
+
+ switch (msg_id) {
+ case QMI_RFSA_GET_BUFF_ADDR_REQ_MSG_V01:
+ *req_desc = &rfsa_get_buffer_addr_req_desc;
+ rc = sizeof(struct rfsa_get_buff_addr_req_msg_v01);
+ break;
+
+ default:
+ rc = -ENOTSUPP;
+ break;
+ }
+ return rc;
+}
+
+static int sharedmem_qmi_req_cb(struct qmi_handle *handle, void *conn_h,
+ void *req_handle, unsigned int msg_id,
+ void *req)
+{
+ int rc = -ENOTSUPP;
+
+ if (sharedmem_qmi_svc_handle != handle || !conn_h)
+ return -EINVAL;
+
+ if (msg_id == QMI_RFSA_GET_BUFF_ADDR_REQ_MSG_V01)
+ rc = sharedmem_qmi_get_buffer(conn_h, req_handle, req);
+
+ return rc;
+}
+
+#define DEBUG_BUF_SIZE (2048)
+static char *debug_buffer;
+static u32 debug_data_size;
+static struct mutex dbg_buf_lock; /* mutex for debug_buffer */
+
+static ssize_t debug_read(struct file *file, char __user *buf,
+ size_t count, loff_t *file_pos)
+{
+ return simple_read_from_buffer(buf, count, file_pos, debug_buffer,
+ debug_data_size);
+}
+
+static u32 fill_debug_info(char *buffer, u32 buffer_size)
+{
+ u32 size = 0;
+ struct list_head *curr_node;
+ struct shared_addr_list *list_entry;
+
+ memset(buffer, 0, buffer_size);
+ size += scnprintf(buffer + size, buffer_size - size, "\n");
+
+ down_read(&sharedmem_list_lock);
+ list_for_each(curr_node, &list.node) {
+ list_entry = list_entry(curr_node, struct shared_addr_list,
+ node);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Client_name: %s\n", list_entry->entry.name);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Client_id: 0x%08X\n", list_entry->entry.id);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Buffer Size: 0x%08X (%d)\n",
+ list_entry->entry.size,
+ list_entry->entry.size);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Address: 0x%016llX\n",
+ list_entry->entry.address);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Address Allocation: %s\n",
+ (list_entry->entry.is_addr_dynamic ?
+ "Dynamic" : "Static"));
+ size += scnprintf(buffer + size, buffer_size - size,
+ "Request count: %llu\n",
+ list_entry->entry.request_count);
+ size += scnprintf(buffer + size, buffer_size - size, "\n\n");
+ }
+ up_read(&sharedmem_list_lock);
+
+ size += scnprintf(buffer + size, buffer_size - size,
+ "RFSA server start count = %u\n", rfsa_count);
+ size += scnprintf(buffer + size, buffer_size - size,
+ "RMTS server start count = %u\n", rmts_count);
+
+ size += scnprintf(buffer + size, buffer_size - size, "\n");
+ return size;
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+ u32 buffer_size;
+
+ mutex_lock(&dbg_buf_lock);
+ if (debug_buffer != NULL) {
+ mutex_unlock(&dbg_buf_lock);
+ return -EBUSY;
+ }
+ buffer_size = DEBUG_BUF_SIZE;
+ debug_buffer = kzalloc(buffer_size, GFP_KERNEL);
+ if (debug_buffer == NULL) {
+ mutex_unlock(&dbg_buf_lock);
+ return -ENOMEM;
+ }
+ debug_data_size = fill_debug_info(debug_buffer, buffer_size);
+ mutex_unlock(&dbg_buf_lock);
+ return 0;
+}
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+ mutex_lock(&dbg_buf_lock);
+ kfree(debug_buffer);
+ debug_buffer = NULL;
+ debug_data_size = 0;
+ mutex_unlock(&dbg_buf_lock);
+ return 0;
+}
+
+static const struct file_operations debug_ops = {
+ .read = debug_read,
+ .open = debug_open,
+ .release = debug_close,
+};
+
+static int rfsa_increment(void *data, u64 val)
+{
+ if (rfsa_count != ~0)
+ rfsa_count++;
+ return 0;
+}
+
+static int rmts_increment(void *data, u64 val)
+{
+ if (rmts_count != ~0)
+ rmts_count++;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(rfsa_fops, NULL, rfsa_increment, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(rmts_fops, NULL, rmts_increment, "%llu\n");
+
+static void debugfs_init(void)
+{
+ struct dentry *f_ent;
+
+ mutex_init(&dbg_buf_lock);
+ dir_ent = debugfs_create_dir("rmt_storage", NULL);
+ if (IS_ERR(dir_ent)) {
+ pr_err("Failed to create debug_fs directory\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("info", 0400, dir_ent, NULL, &debug_ops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs info file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("rfsa", 0200, dir_ent, NULL, &rfsa_fops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs rfsa file\n");
+ return;
+ }
+
+ f_ent = debugfs_create_file("rmts", 0200, dir_ent, NULL, &rmts_fops);
+ if (IS_ERR(f_ent)) {
+ pr_err("Failed to create debug_fs rmts file\n");
+ return;
+ }
+}
+
+static void debugfs_exit(void)
+{
+ debugfs_remove_recursive(dir_ent);
+ mutex_destroy(&dbg_buf_lock);
+}
+
+static void sharedmem_qmi_svc_recv_msg(struct work_struct *work)
+{
+ int rc;
+
+ do {
+ pr_debug("Notified about a Receive Event\n");
+ } while ((rc = qmi_recv_msg(sharedmem_qmi_svc_handle)) == 0);
+
+ if (rc != -ENOMSG)
+ pr_err("Error receiving message\n");
+}
+
+static void sharedmem_qmi_notify(struct qmi_handle *handle,
+ enum qmi_event_type event, void *priv)
+{
+ switch (event) {
+ case QMI_RECV_MSG:
+ queue_delayed_work(sharedmem_qmi_svc_workqueue,
+ &work_recv_msg, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static struct qmi_svc_ops_options sharedmem_qmi_ops_options = {
+ .version = 1,
+ .service_id = RFSA_SERVICE_ID_V01,
+ .service_vers = RFSA_SERVICE_VERS_V01,
+ .service_ins = RFSA_SERVICE_INSTANCE_NUM,
+ .connect_cb = sharedmem_qmi_connect_cb,
+ .disconnect_cb = sharedmem_qmi_disconnect_cb,
+ .req_desc_cb = sharedmem_qmi_req_desc_cb,
+ .req_cb = sharedmem_qmi_req_cb,
+};
+
+
+static void sharedmem_register_qmi(void)
+{
+ int rc;
+
+ sharedmem_qmi_svc_workqueue =
+ create_singlethread_workqueue("sharedmem_qmi_work");
+ if (!sharedmem_qmi_svc_workqueue)
+ return;
+
+ sharedmem_qmi_svc_handle = qmi_handle_create(sharedmem_qmi_notify,
+ NULL);
+ if (!sharedmem_qmi_svc_handle) {
+ pr_err("Creating sharedmem_qmi qmi handle failed\n");
+ destroy_workqueue(sharedmem_qmi_svc_workqueue);
+ return;
+ }
+ rc = qmi_svc_register(sharedmem_qmi_svc_handle,
+ &sharedmem_qmi_ops_options);
+ if (rc < 0) {
+ pr_err("Registering sharedmem_qmi failed %d\n", rc);
+ qmi_handle_destroy(sharedmem_qmi_svc_handle);
+ destroy_workqueue(sharedmem_qmi_svc_workqueue);
+ return;
+ }
+ pr_info("qmi init successful\n");
+}
+
+static void sharedmem_qmi_init_worker(struct work_struct *work)
+{
+ sharedmem_register_qmi();
+ debugfs_init();
+}
+
+int sharedmem_qmi_init(void)
+{
+ INIT_LIST_HEAD(&list.node);
+ INIT_WORK(&sharedmem_qmi_init_work, sharedmem_qmi_init_worker);
+ schedule_work(&sharedmem_qmi_init_work);
+ return 0;
+}
+
+void sharedmem_qmi_exit(void)
+{
+ qmi_svc_unregister(sharedmem_qmi_svc_handle);
+ flush_workqueue(sharedmem_qmi_svc_workqueue);
+ qmi_handle_destroy(sharedmem_qmi_svc_handle);
+ destroy_workqueue(sharedmem_qmi_svc_workqueue);
+ debugfs_exit();
+}
diff --git a/drivers/uio/msm_sharedmem/sharedmem_qmi.h b/drivers/uio/msm_sharedmem/sharedmem_qmi.h
new file mode 100644
index 0000000..7353916
--- /dev/null
+++ b/drivers/uio/msm_sharedmem/sharedmem_qmi.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2014-2015, 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.
+ *
+ */
+
+#ifndef __SHAREDMEM_QMI_H__
+#define __SHAREDMEM_QMI_H__
+
+#include <linux/module.h>
+
+struct sharemem_qmi_entry {
+ const char *client_name;
+ u32 client_id;
+ u64 address;
+ u32 size;
+ bool is_addr_dynamic;
+};
+
+int sharedmem_qmi_init(void);
+
+void sharedmem_qmi_exit(void);
+
+void sharedmem_qmi_add_entry(struct sharemem_qmi_entry *qmi_entry);
+
+#endif /* __SHAREDMEM_QMI_H__ */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c3d249f..edb7a9a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2661,8 +2661,15 @@
if (ret < 0)
return ret;
- /* The port state is unknown until the reset completes. */
- if (!(portstatus & USB_PORT_STAT_RESET))
+ /*
+ * The port state is unknown until the reset completes.
+ *
+ * On top of that, some chips may require additional time
+ * to re-establish a connection after the reset is complete,
+ * so also wait for the connection to be re-established.
+ */
+ if (!(portstatus & USB_PORT_STAT_RESET) &&
+ (portstatus & USB_PORT_STAT_CONNECTION))
break;
/* switch to the long delay after two short delay failures */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a88b26b..a159011 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -808,7 +808,8 @@
/* Provide physical USB addresses for DEPCMD and GEVENTCNT registers */
ch_info->depcmd_low_addr = (u32)(dwc->reg_phys +
- DWC3_DEPCMD);
+ DWC3_DEP_BASE(dep->number) + DWC3_DEPCMD);
+
ch_info->depcmd_hi_addr = 0;
ch_info->xfer_ring_base_addr = dwc3_trb_dma_offset(dep,
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index b4d4499..0dfe271 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -319,9 +319,6 @@
if (unmap_after_complete)
usb_gadget_unmap_request(&dwc->gadget,
&req->request, req->direction);
-
- if (dep->number > 1)
- pm_runtime_put(dwc->dev);
}
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned cmd, u32 param)
@@ -1241,7 +1238,6 @@
return ret;
}
- pm_runtime_get(dwc->dev);
req->request.actual = 0;
req->request.status = -EINPROGRESS;
req->direction = dep->direction;
diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c
index 51e6104..e908ecf 100644
--- a/drivers/usb/gadget/function/f_diag.c
+++ b/drivers/usb/gadget/function/f_diag.c
@@ -307,21 +307,8 @@
ctxt->dpkts_tolaptop_pending--;
- if (!req->status) {
- if ((req->length >= ep->maxpacket) &&
- ((req->length % ep->maxpacket) == 0)) {
- ctxt->dpkts_tolaptop_pending++;
- req->length = 0;
- d_req->actual = req->actual;
- d_req->status = req->status;
- /* Queue zero length packet */
- if (!usb_ep_queue(ctxt->in, req, GFP_ATOMIC))
- return;
- ctxt->dpkts_tolaptop_pending--;
- } else {
- ctxt->dpkts_tolaptop++;
- }
- }
+ if (!req->status)
+ ctxt->dpkts_tolaptop++;
spin_lock_irqsave(&ctxt->lock, flags);
list_add_tail(&req->list, &ctxt->write_pool);
@@ -481,6 +468,7 @@
goto fail;
kmemleak_not_leak(req);
req->complete = diag_write_complete;
+ req->zero = true;
list_add_tail(&req->list, &ctxt->write_pool);
}
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 54e14b1..cca261e 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2285,16 +2285,15 @@
fsg->bulk_out_enabled = 0;
}
+ /* allow usb LPM after eps are disabled */
+ usb_gadget_autopm_put_async(common->gadget);
common->fsg = NULL;
wake_up(&common->fsg_wait);
}
common->running = 0;
- if (!new_fsg || rc) {
- /* allow usb LPM after eps are disabled */
- usb_gadget_autopm_put_async(common->gadget);
+ if (!new_fsg || rc)
return rc;
- }
common->fsg = new_fsg;
fsg = common->fsg;
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index c6aa884..aaa0fc2 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -587,11 +587,17 @@
struct mtp_dev *dev = fp->private_data;
struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req;
- ssize_t r = count, xfer, len;
+ ssize_t r = count;
+ unsigned xfer;
int ret = 0;
+ size_t len;
DBG(cdev, "mtp_read(%zu) state:%d\n", count, dev->state);
+ len = usb_ep_align_maybe(cdev->gadget, dev->ep_out, count);
+ if (len > MTP_BULK_BUFFER_SIZE)
+ return -EINVAL;
+
/* we will block until we're online */
DBG(cdev, "mtp_read: waiting for online state\n");
ret = wait_event_interruptible(dev->read_wq,
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index 37a37c4..6f2e729 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -10,6 +10,7 @@
#include <linux/efi.h>
#include <linux/errno.h>
#include <linux/fb.h>
+#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
#include <video/vga.h>
@@ -118,6 +119,8 @@
return false;
}
+static bool pci_dev_disabled; /* FB base matches BAR of a disabled device */
+
static int efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
@@ -127,7 +130,7 @@
unsigned int size_total;
char *option = NULL;
- if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || pci_dev_disabled)
return -ENODEV;
if (fb_get_options("efifb", &option))
@@ -327,3 +330,64 @@
};
builtin_platform_driver(efifb_driver);
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_X86)
+
+static bool pci_bar_found; /* did we find a BAR matching the efifb base? */
+
+static void claim_efifb_bar(struct pci_dev *dev, int idx)
+{
+ u16 word;
+
+ pci_bar_found = true;
+
+ pci_read_config_word(dev, PCI_COMMAND, &word);
+ if (!(word & PCI_COMMAND_MEMORY)) {
+ pci_dev_disabled = true;
+ dev_err(&dev->dev,
+ "BAR %d: assigned to efifb but device is disabled!\n",
+ idx);
+ return;
+ }
+
+ if (pci_claim_resource(dev, idx)) {
+ pci_dev_disabled = true;
+ dev_err(&dev->dev,
+ "BAR %d: failed to claim resource for efifb!\n", idx);
+ return;
+ }
+
+ dev_info(&dev->dev, "BAR %d: assigned to efifb\n", idx);
+}
+
+static void efifb_fixup_resources(struct pci_dev *dev)
+{
+ u64 base = screen_info.lfb_base;
+ u64 size = screen_info.lfb_size;
+ int i;
+
+ if (pci_bar_found || screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+ return;
+
+ if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+ base |= (u64)screen_info.ext_lfb_base << 32;
+
+ if (!base)
+ return;
+
+ for (i = 0; i < PCI_STD_RESOURCE_END; i++) {
+ struct resource *res = &dev->resource[i];
+
+ if (!(res->flags & IORESOURCE_MEM))
+ continue;
+
+ if (res->start <= base && res->end >= base + size - 1) {
+ claim_efifb_bar(dev, i);
+ break;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY,
+ 16, efifb_fixup_resources);
+
+#endif
diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
index 0567d51..ea2f19f 100644
--- a/drivers/video/fbdev/xen-fbfront.c
+++ b/drivers/video/fbdev/xen-fbfront.c
@@ -644,7 +644,6 @@
break;
case XenbusStateInitWait:
-InitWait:
xenbus_switch_state(dev, XenbusStateConnected);
break;
@@ -655,7 +654,8 @@
* get Connected twice here.
*/
if (dev->state != XenbusStateConnected)
- goto InitWait; /* no InitWait seen yet, fudge it */
+ /* no InitWait seen yet, fudge it */
+ xenbus_switch_state(dev, XenbusStateConnected);
if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
"request-update", "%d", &val) < 0)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 1cd0e2e..3925758 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2597,7 +2597,7 @@
wdata->credits = credits;
if (!wdata->cfile->invalidHandle ||
- !cifs_reopen_file(wdata->cfile, false))
+ !(rc = cifs_reopen_file(wdata->cfile, false)))
rc = server->ops->async_writev(wdata,
cifs_uncached_writedata_release);
if (rc) {
@@ -3002,7 +3002,7 @@
rdata->credits = credits;
if (!rdata->cfile->invalidHandle ||
- !cifs_reopen_file(rdata->cfile, true))
+ !(rc = cifs_reopen_file(rdata->cfile, true)))
rc = server->ops->async_readv(rdata);
error:
if (rc) {
@@ -3577,7 +3577,7 @@
}
if (!rdata->cfile->invalidHandle ||
- !cifs_reopen_file(rdata->cfile, true))
+ !(rc = cifs_reopen_file(rdata->cfile, true)))
rc = server->ops->async_readv(rdata);
if (rc) {
add_credits_and_wake_if(server, rdata->credits, 0);
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index bdd3292..7080dac 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1987,6 +1987,9 @@
struct cifs_tcon *tcon, *tcon2;
struct list_head tmp_list;
int tcon_exist = false;
+ int rc;
+ int resched = false;
+
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
mutex_lock(&server->reconnect_mutex);
@@ -2014,13 +2017,18 @@
spin_unlock(&cifs_tcp_ses_lock);
list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
- if (!smb2_reconnect(SMB2_INTERNAL_CMD, tcon))
+ rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon);
+ if (!rc)
cifs_reopen_persistent_handles(tcon);
+ else
+ resched = true;
list_del_init(&tcon->rlist);
cifs_put_tcon(tcon);
}
cifs_dbg(FYI, "Reconnecting tcons finished\n");
+ if (resched)
+ queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
mutex_unlock(&server->reconnect_mutex);
/* now we can safely release srv struct */
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a826864..3cb7fa2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -72,10 +72,9 @@
csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum,
csum_size);
offset += csum_size;
- csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
- EXT4_INODE_SIZE(inode->i_sb) -
- offset);
}
+ csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
+ EXT4_INODE_SIZE(inode->i_sb) - offset);
}
return csum;
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index 516ffb4..fe2cbeb 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -208,14 +208,19 @@
continue;
/*
* Skip ops whose filesystem we don't know about unless
- * it is being mounted.
+ * it is being mounted or unmounted. It is possible for
+ * a filesystem we don't know about to be unmounted if
+ * it fails to mount in the kernel after userspace has
+ * been sent the mount request.
*/
/* XXX: is there a better way to detect this? */
} else if (ret == -1 &&
!(op->upcall.type ==
ORANGEFS_VFS_OP_FS_MOUNT ||
op->upcall.type ==
- ORANGEFS_VFS_OP_GETATTR)) {
+ ORANGEFS_VFS_OP_GETATTR ||
+ op->upcall.type ==
+ ORANGEFS_VFS_OP_FS_UMOUNT)) {
gossip_debug(GOSSIP_DEV_DEBUG,
"orangefs: skipping op tag %llu %s\n",
llu(op->tag), get_opname_string(op));
@@ -402,8 +407,9 @@
/* remove the op from the in progress hash table */
op = orangefs_devreq_remove_op(head.tag);
if (!op) {
- gossip_err("WARNING: No one's waiting for tag %llu\n",
- llu(head.tag));
+ gossip_debug(GOSSIP_DEV_DEBUG,
+ "%s: No one's waiting for tag %llu\n",
+ __func__, llu(head.tag));
return ret;
}
diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c
index 38887cc..0748a26 100644
--- a/fs/orangefs/orangefs-debugfs.c
+++ b/fs/orangefs/orangefs-debugfs.c
@@ -671,8 +671,10 @@
*/
cdm_element_count =
orangefs_prepare_cdm_array(client_debug_array_string);
- if (cdm_element_count <= 0)
+ if (cdm_element_count <= 0) {
+ kfree(new);
goto out;
+ }
for (i = 0; i < cdm_element_count; i++) {
strlcat(new, "\t", string_size);
@@ -963,13 +965,13 @@
int ret;
ret = copy_from_user(&client_debug_array_string,
- (void __user *)arg,
- ORANGEFS_MAX_DEBUG_STRING_LEN);
+ (void __user *)arg,
+ ORANGEFS_MAX_DEBUG_STRING_LEN);
if (ret != 0) {
pr_info("%s: CLIENT_STRING: copy_from_user failed\n",
__func__);
- return -EIO;
+ return -EFAULT;
}
/*
@@ -984,17 +986,18 @@
*/
client_debug_array_string[ORANGEFS_MAX_DEBUG_STRING_LEN - 1] =
'\0';
-
+
pr_info("%s: client debug array string has been received.\n",
__func__);
if (!help_string_initialized) {
/* Build a proper debug help string. */
- if (orangefs_prepare_debugfs_help_string(0)) {
+ ret = orangefs_prepare_debugfs_help_string(0);
+ if (ret) {
gossip_err("%s: no debug help string \n",
__func__);
- return -EIO;
+ return ret;
}
}
@@ -1007,7 +1010,7 @@
help_string_initialized++;
- return ret;
+ return 0;
}
int orangefs_debugfs_new_debug(void __user *arg)
diff --git a/fs/orangefs/orangefs-dev-proto.h b/fs/orangefs/orangefs-dev-proto.h
index a3d84ff..f380f9ed 100644
--- a/fs/orangefs/orangefs-dev-proto.h
+++ b/fs/orangefs/orangefs-dev-proto.h
@@ -50,8 +50,7 @@
* Misc constants. Please retain them as multiples of 8!
* Otherwise 32-64 bit interactions will be messed up :)
*/
-#define ORANGEFS_MAX_DEBUG_STRING_LEN 0x00000400
-#define ORANGEFS_MAX_DEBUG_ARRAY_LEN 0x00000800
+#define ORANGEFS_MAX_DEBUG_STRING_LEN 0x00000800
/*
* The maximum number of directory entries in a single request is 96.
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 3bf803d..45dd8f2 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -249,6 +249,7 @@
char devname[ORANGEFS_MAX_SERVER_ADDR_LEN];
struct super_block *sb;
int mount_pending;
+ int no_list;
struct list_head list;
};
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index cd261c8..629d8c9 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -493,7 +493,7 @@
if (ret) {
d = ERR_PTR(ret);
- goto free_op;
+ goto free_sb_and_op;
}
/*
@@ -519,6 +519,9 @@
spin_unlock(&orangefs_superblocks_lock);
op_release(new_op);
+ /* Must be removed from the list now. */
+ ORANGEFS_SB(sb)->no_list = 0;
+
if (orangefs_userspace_version >= 20906) {
new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
if (!new_op)
@@ -533,6 +536,10 @@
return dget(sb->s_root);
+free_sb_and_op:
+ /* Will call orangefs_kill_sb with sb not in list. */
+ ORANGEFS_SB(sb)->no_list = 1;
+ deactivate_locked_super(sb);
free_op:
gossip_err("orangefs_mount: mount request failed with %d\n", ret);
if (ret == -EINVAL) {
@@ -558,12 +565,14 @@
*/
orangefs_unmount_sb(sb);
- /* remove the sb from our list of orangefs specific sb's */
-
- spin_lock(&orangefs_superblocks_lock);
- __list_del_entry(&ORANGEFS_SB(sb)->list); /* not list_del_init */
- ORANGEFS_SB(sb)->list.prev = NULL;
- spin_unlock(&orangefs_superblocks_lock);
+ if (!ORANGEFS_SB(sb)->no_list) {
+ /* remove the sb from our list of orangefs specific sb's */
+ spin_lock(&orangefs_superblocks_lock);
+ /* not list_del_init */
+ __list_del_entry(&ORANGEFS_SB(sb)->list);
+ ORANGEFS_SB(sb)->list.prev = NULL;
+ spin_unlock(&orangefs_superblocks_lock);
+ }
/*
* make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 65d28f9..f998332 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -962,7 +962,14 @@
static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,
unsigned long addr, pmd_t *pmdp)
{
- pmd_t pmd = pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp);
+ pmd_t pmd = *pmdp;
+
+ /* See comment in change_huge_pmd() */
+ pmdp_invalidate(vma, addr, pmdp);
+ if (pmd_dirty(*pmdp))
+ pmd = pmd_mkdirty(pmd);
+ if (pmd_young(*pmdp))
+ pmd = pmd_mkyoung(pmd);
pmd = pmd_wrprotect(pmd);
pmd = pmd_clear_soft_dirty(pmd);
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 14747a8..2964527 100644
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -222,7 +222,7 @@
break;
case PERM_ANDROID_PACKAGE_CACHE:
if (info->d_uid != 0)
- gid = multiuser_get_cache_gid(info->d_uid);
+ gid = multiuser_get_ext_cache_gid(info->d_uid);
else
gid = multiuser_get_uid(info->userid, uid);
break;
@@ -252,7 +252,7 @@
goto retry_deleg;
}
if (error)
- pr_err("sdcardfs: Failed to touch up lower fs gid/uid.\n");
+ pr_debug("sdcardfs: Failed to touch up lower fs gid/uid for %s\n", name);
}
sdcardfs_put_lower_path(dentry, &path);
}
diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c
index f9c0282..19154b7 100644
--- a/fs/sdcardfs/lookup.c
+++ b/fs/sdcardfs/lookup.c
@@ -91,7 +91,9 @@
struct sdcardfs_inode_info *info;
struct inode_data data;
struct inode *inode; /* the new inode to return */
- int err;
+
+ if (!igrab(lower_inode))
+ return ERR_PTR(-ESTALE);
data.id = id;
data.lower_inode = lower_inode;
@@ -106,22 +108,19 @@
sdcardfs_inode_set, /* inode init function */
&data); /* data passed to test+set fxns */
if (!inode) {
- err = -EACCES;
iput(lower_inode);
- return ERR_PTR(err);
+ return ERR_PTR(-ENOMEM);
}
- /* if found a cached inode, then just return it */
- if (!(inode->i_state & I_NEW))
+ /* if found a cached inode, then just return it (after iput) */
+ if (!(inode->i_state & I_NEW)) {
+ iput(lower_inode);
return inode;
+ }
/* initialize new inode */
info = SDCARDFS_I(inode);
inode->i_ino = lower_inode->i_ino;
- if (!igrab(lower_inode)) {
- err = -ESTALE;
- return ERR_PTR(err);
- }
sdcardfs_set_lower_inode(inode, lower_inode);
inode->i_version++;
diff --git a/fs/sdcardfs/multiuser.h b/fs/sdcardfs/multiuser.h
index 2e89b58..d0c925c 100644
--- a/fs/sdcardfs/multiuser.h
+++ b/fs/sdcardfs/multiuser.h
@@ -23,6 +23,8 @@
#define AID_APP_END 19999 /* last app user */
#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
+#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */
+#define AID_EXT_CACHE_GID_END 49999 /* end of gids for apps to mark external cached data */
#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
typedef uid_t userid_t;
@@ -33,9 +35,9 @@
return (user_id * AID_USER_OFFSET) + (app_id % AID_USER_OFFSET);
}
-static inline gid_t multiuser_get_cache_gid(uid_t uid)
+static inline gid_t multiuser_get_ext_cache_gid(uid_t uid)
{
- return uid - AID_APP_START + AID_CACHE_GID_START;
+ return uid - AID_APP_START + AID_EXT_CACHE_GID_START;
}
static inline gid_t multiuser_get_ext_gid(uid_t uid)
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 1d4f365..f6d9af3e 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -166,6 +166,16 @@
return crypto_alloc_instance2(name, alg, ahash_instance_headroom());
}
+static inline void ahash_request_complete(struct ahash_request *req, int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline u32 ahash_request_flags(struct ahash_request *req)
+{
+ return req->base.flags;
+}
+
static inline struct crypto_ahash *crypto_spawn_ahash(
struct crypto_ahash_spawn *spawn)
{
diff --git a/include/dt-bindings/clock/qcom,aop-qmp.h b/include/dt-bindings/clock/qcom,aop-qmp.h
new file mode 100644
index 0000000..b88dc36
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,aop-qmp.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_AOP_QMP_H
+#define _DT_BINDINGS_CLK_QCOM_AOP_QMP_H
+
+#define QDSS_CLK_LEVEL_OFF 0
+#define QDSS_CLK_LEVEL_DYNAMIC 1
+#define QDSS_CLK_LEVEL_TURBO 2
+#define QDSS_CLK_LEVEL_NOMINAL 3
+#define QDSS_CLK_LEVEL_SVS_L1 4
+#define QDSS_CLK_LEVEL_SVS 5
+#define QDSS_CLK_LEVEL_LOW_SVS 6
+#define QDSS_CLK_LEVEL_MIN_SVS 7
+
+/* clocks id */
+#define QDSS_CLK 0
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,camcc-sdm845.h b/include/dt-bindings/clock/qcom,camcc-sdm845.h
index e169172..0d9d9f6 100644
--- a/include/dt-bindings/clock/qcom,camcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,camcc-sdm845.h
@@ -34,71 +34,70 @@
#define CAM_CC_CSIPHY0_CLK 17
#define CAM_CC_CSIPHY1_CLK 18
#define CAM_CC_CSIPHY2_CLK 19
-#define CAM_CC_DEBUG_CLK 20
-#define CAM_CC_FAST_AHB_CLK_SRC 21
-#define CAM_CC_FD_CORE_CLK 22
-#define CAM_CC_FD_CORE_CLK_SRC 23
-#define CAM_CC_FD_CORE_UAR_CLK 24
-#define CAM_CC_ICP_APB_CLK 25
-#define CAM_CC_ICP_ATB_CLK 26
-#define CAM_CC_ICP_CLK 27
-#define CAM_CC_ICP_CLK_SRC 28
-#define CAM_CC_ICP_CTI_CLK 29
-#define CAM_CC_ICP_TS_CLK 30
-#define CAM_CC_IFE_0_AXI_CLK 31
-#define CAM_CC_IFE_0_CLK 32
-#define CAM_CC_IFE_0_CLK_SRC 33
-#define CAM_CC_IFE_0_CPHY_RX_CLK 34
-#define CAM_CC_IFE_0_CSID_CLK 35
-#define CAM_CC_IFE_0_CSID_CLK_SRC 36
-#define CAM_CC_IFE_0_DSP_CLK 37
-#define CAM_CC_IFE_1_AXI_CLK 38
-#define CAM_CC_IFE_1_CLK 39
-#define CAM_CC_IFE_1_CLK_SRC 40
-#define CAM_CC_IFE_1_CPHY_RX_CLK 41
-#define CAM_CC_IFE_1_CSID_CLK 42
-#define CAM_CC_IFE_1_CSID_CLK_SRC 43
-#define CAM_CC_IFE_1_DSP_CLK 44
-#define CAM_CC_IFE_LITE_CLK 45
-#define CAM_CC_IFE_LITE_CLK_SRC 46
-#define CAM_CC_IFE_LITE_CPHY_RX_CLK 47
-#define CAM_CC_IFE_LITE_CSID_CLK 48
-#define CAM_CC_IFE_LITE_CSID_CLK_SRC 49
-#define CAM_CC_IPE_0_AHB_CLK 50
-#define CAM_CC_IPE_0_AREG_CLK 51
-#define CAM_CC_IPE_0_AXI_CLK 52
-#define CAM_CC_IPE_0_CLK 53
-#define CAM_CC_IPE_0_CLK_SRC 54
-#define CAM_CC_IPE_1_AHB_CLK 55
-#define CAM_CC_IPE_1_AREG_CLK 56
-#define CAM_CC_IPE_1_AXI_CLK 57
-#define CAM_CC_IPE_1_CLK 58
-#define CAM_CC_IPE_1_CLK_SRC 59
-#define CAM_CC_JPEG_CLK 60
-#define CAM_CC_JPEG_CLK_SRC 61
-#define CAM_CC_LRME_CLK 62
-#define CAM_CC_LRME_CLK_SRC 63
-#define CAM_CC_MCLK0_CLK 64
-#define CAM_CC_MCLK0_CLK_SRC 65
-#define CAM_CC_MCLK1_CLK 66
-#define CAM_CC_MCLK1_CLK_SRC 67
-#define CAM_CC_MCLK2_CLK 68
-#define CAM_CC_MCLK2_CLK_SRC 69
-#define CAM_CC_MCLK3_CLK 70
-#define CAM_CC_MCLK3_CLK_SRC 71
-#define CAM_CC_PLL0 72
-#define CAM_CC_PLL0_OUT_EVEN 73
-#define CAM_CC_PLL1 74
-#define CAM_CC_PLL1_OUT_EVEN 75
-#define CAM_CC_PLL2 76
-#define CAM_CC_PLL2_OUT_EVEN 77
-#define CAM_CC_PLL2_OUT_ODD 78
-#define CAM_CC_PLL3 79
-#define CAM_CC_PLL3_OUT_EVEN 80
-#define CAM_CC_PLL_TEST_CLK 81
-#define CAM_CC_SLOW_AHB_CLK_SRC 82
-#define CAM_CC_SOC_AHB_CLK 83
-#define CAM_CC_SYS_TMR_CLK 84
+#define CAM_CC_FAST_AHB_CLK_SRC 20
+#define CAM_CC_FD_CORE_CLK 21
+#define CAM_CC_FD_CORE_CLK_SRC 22
+#define CAM_CC_FD_CORE_UAR_CLK 23
+#define CAM_CC_ICP_APB_CLK 24
+#define CAM_CC_ICP_ATB_CLK 25
+#define CAM_CC_ICP_CLK 26
+#define CAM_CC_ICP_CLK_SRC 27
+#define CAM_CC_ICP_CTI_CLK 28
+#define CAM_CC_ICP_TS_CLK 29
+#define CAM_CC_IFE_0_AXI_CLK 30
+#define CAM_CC_IFE_0_CLK 31
+#define CAM_CC_IFE_0_CLK_SRC 32
+#define CAM_CC_IFE_0_CPHY_RX_CLK 33
+#define CAM_CC_IFE_0_CSID_CLK 34
+#define CAM_CC_IFE_0_CSID_CLK_SRC 35
+#define CAM_CC_IFE_0_DSP_CLK 36
+#define CAM_CC_IFE_1_AXI_CLK 37
+#define CAM_CC_IFE_1_CLK 38
+#define CAM_CC_IFE_1_CLK_SRC 39
+#define CAM_CC_IFE_1_CPHY_RX_CLK 40
+#define CAM_CC_IFE_1_CSID_CLK 41
+#define CAM_CC_IFE_1_CSID_CLK_SRC 42
+#define CAM_CC_IFE_1_DSP_CLK 43
+#define CAM_CC_IFE_LITE_CLK 44
+#define CAM_CC_IFE_LITE_CLK_SRC 45
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK 46
+#define CAM_CC_IFE_LITE_CSID_CLK 47
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC 48
+#define CAM_CC_IPE_0_AHB_CLK 49
+#define CAM_CC_IPE_0_AREG_CLK 50
+#define CAM_CC_IPE_0_AXI_CLK 51
+#define CAM_CC_IPE_0_CLK 52
+#define CAM_CC_IPE_0_CLK_SRC 53
+#define CAM_CC_IPE_1_AHB_CLK 54
+#define CAM_CC_IPE_1_AREG_CLK 55
+#define CAM_CC_IPE_1_AXI_CLK 56
+#define CAM_CC_IPE_1_CLK 57
+#define CAM_CC_IPE_1_CLK_SRC 58
+#define CAM_CC_JPEG_CLK 59
+#define CAM_CC_JPEG_CLK_SRC 60
+#define CAM_CC_LRME_CLK 61
+#define CAM_CC_LRME_CLK_SRC 62
+#define CAM_CC_MCLK0_CLK 63
+#define CAM_CC_MCLK0_CLK_SRC 64
+#define CAM_CC_MCLK1_CLK 65
+#define CAM_CC_MCLK1_CLK_SRC 66
+#define CAM_CC_MCLK2_CLK 67
+#define CAM_CC_MCLK2_CLK_SRC 68
+#define CAM_CC_MCLK3_CLK 69
+#define CAM_CC_MCLK3_CLK_SRC 70
+#define CAM_CC_PLL0 71
+#define CAM_CC_PLL0_OUT_EVEN 72
+#define CAM_CC_PLL1 73
+#define CAM_CC_PLL1_OUT_EVEN 74
+#define CAM_CC_PLL2 75
+#define CAM_CC_PLL2_OUT_EVEN 76
+#define CAM_CC_PLL2_OUT_ODD 77
+#define CAM_CC_PLL3 78
+#define CAM_CC_PLL3_OUT_EVEN 79
+#define CAM_CC_PLL_TEST_CLK 80
+#define CAM_CC_SLOW_AHB_CLK_SRC 81
+#define CAM_CC_SOC_AHB_CLK 82
+#define CAM_CC_SYS_TMR_CLK 83
#define TITAN_CAM_CC_BPS_BCR 0
#define TITAN_CAM_CC_CAMNOC_BCR 1
diff --git a/include/dt-bindings/clock/qcom,dispcc-sdm845.h b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
index b1988e4..24dd11e 100644
--- a/include/dt-bindings/clock/qcom,dispcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
@@ -14,49 +14,48 @@
#ifndef _DT_BINDINGS_CLK_MSM_DISP_CC_SDM845_H
#define _DT_BINDINGS_CLK_MSM_DISP_CC_SDM845_H
-#define DISP_CC_DEBUG_CLK 0
-#define DISP_CC_MDSS_AHB_CLK 1
-#define DISP_CC_MDSS_AXI_CLK 2
-#define DISP_CC_MDSS_BYTE0_CLK 3
-#define DISP_CC_MDSS_BYTE0_CLK_SRC 4
-#define DISP_CC_MDSS_BYTE0_INTF_CLK 5
-#define DISP_CC_MDSS_BYTE1_CLK 6
-#define DISP_CC_MDSS_BYTE1_CLK_SRC 7
-#define DISP_CC_MDSS_BYTE1_INTF_CLK 8
-#define DISP_CC_MDSS_DP_AUX_CLK 9
-#define DISP_CC_MDSS_DP_AUX_CLK_SRC 10
-#define DISP_CC_MDSS_DP_CRYPTO_CLK 11
-#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC 12
-#define DISP_CC_MDSS_DP_LINK_CLK 13
-#define DISP_CC_MDSS_DP_LINK_CLK_SRC 14
-#define DISP_CC_MDSS_DP_LINK_INTF_CLK 15
-#define DISP_CC_MDSS_DP_PIXEL1_CLK 16
-#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC 17
-#define DISP_CC_MDSS_DP_PIXEL_CLK 18
-#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC 19
-#define DISP_CC_MDSS_ESC0_CLK 20
-#define DISP_CC_MDSS_ESC0_CLK_SRC 21
-#define DISP_CC_MDSS_ESC1_CLK 22
-#define DISP_CC_MDSS_ESC1_CLK_SRC 23
-#define DISP_CC_MDSS_MDP_CLK 24
-#define DISP_CC_MDSS_MDP_CLK_SRC 25
-#define DISP_CC_MDSS_MDP_LUT_CLK 26
-#define DISP_CC_MDSS_PCLK0_CLK 27
-#define DISP_CC_MDSS_PCLK0_CLK_SRC 28
-#define DISP_CC_MDSS_PCLK1_CLK 29
-#define DISP_CC_MDSS_PCLK1_CLK_SRC 30
-#define DISP_CC_MDSS_QDSS_AT_CLK 31
-#define DISP_CC_MDSS_QDSS_TSCTR_DIV8_CLK 32
-#define DISP_CC_MDSS_ROT_CLK 33
-#define DISP_CC_MDSS_ROT_CLK_SRC 34
-#define DISP_CC_MDSS_RSCC_AHB_CLK 35
-#define DISP_CC_MDSS_RSCC_VSYNC_CLK 36
-#define DISP_CC_MDSS_VSYNC_CLK 37
-#define DISP_CC_MDSS_VSYNC_CLK_SRC 38
-#define DISP_CC_PLL0 39
-#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 40
-#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC 41
-#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC 42
+#define DISP_CC_MDSS_AHB_CLK 0
+#define DISP_CC_MDSS_AXI_CLK 1
+#define DISP_CC_MDSS_BYTE0_CLK 2
+#define DISP_CC_MDSS_BYTE0_CLK_SRC 3
+#define DISP_CC_MDSS_BYTE0_INTF_CLK 4
+#define DISP_CC_MDSS_BYTE1_CLK 5
+#define DISP_CC_MDSS_BYTE1_CLK_SRC 6
+#define DISP_CC_MDSS_BYTE1_INTF_CLK 7
+#define DISP_CC_MDSS_DP_AUX_CLK 8
+#define DISP_CC_MDSS_DP_AUX_CLK_SRC 9
+#define DISP_CC_MDSS_DP_CRYPTO_CLK 10
+#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC 11
+#define DISP_CC_MDSS_DP_LINK_CLK 12
+#define DISP_CC_MDSS_DP_LINK_CLK_SRC 13
+#define DISP_CC_MDSS_DP_LINK_INTF_CLK 14
+#define DISP_CC_MDSS_DP_PIXEL1_CLK 15
+#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC 16
+#define DISP_CC_MDSS_DP_PIXEL_CLK 17
+#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC 18
+#define DISP_CC_MDSS_ESC0_CLK 19
+#define DISP_CC_MDSS_ESC0_CLK_SRC 20
+#define DISP_CC_MDSS_ESC1_CLK 21
+#define DISP_CC_MDSS_ESC1_CLK_SRC 22
+#define DISP_CC_MDSS_MDP_CLK 23
+#define DISP_CC_MDSS_MDP_CLK_SRC 24
+#define DISP_CC_MDSS_MDP_LUT_CLK 25
+#define DISP_CC_MDSS_PCLK0_CLK 26
+#define DISP_CC_MDSS_PCLK0_CLK_SRC 27
+#define DISP_CC_MDSS_PCLK1_CLK 28
+#define DISP_CC_MDSS_PCLK1_CLK_SRC 29
+#define DISP_CC_MDSS_QDSS_AT_CLK 30
+#define DISP_CC_MDSS_QDSS_TSCTR_DIV8_CLK 31
+#define DISP_CC_MDSS_ROT_CLK 32
+#define DISP_CC_MDSS_ROT_CLK_SRC 33
+#define DISP_CC_MDSS_RSCC_AHB_CLK 34
+#define DISP_CC_MDSS_RSCC_VSYNC_CLK 35
+#define DISP_CC_MDSS_VSYNC_CLK 36
+#define DISP_CC_MDSS_VSYNC_CLK_SRC 37
+#define DISP_CC_PLL0 38
+#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 39
+#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC 40
+#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC 41
#define DISP_CC_MDSS_CORE_BCR 0
#define DISP_CC_MDSS_GCC_CLOCKS_BCR 1
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index f7a6978..6c62503 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -35,161 +35,158 @@
#define GCC_CPUSS_GNOC_CLK 17
#define GCC_CPUSS_RBCPR_CLK 18
#define GCC_CPUSS_RBCPR_CLK_SRC 19
-#define GCC_CXO_TX1_CLKREF_CLK 20
-#define GCC_DDRSS_GPU_AXI_CLK 21
-#define GCC_DISP_AHB_CLK 22
-#define GCC_DISP_AXI_CLK 23
-#define GCC_DISP_GPLL0_CLK_SRC 24
-#define GCC_DISP_GPLL0_DIV_CLK_SRC 25
-#define GCC_DISP_XO_CLK 26
-#define GCC_GP1_CLK 27
-#define GCC_GP1_CLK_SRC 28
-#define GCC_GP2_CLK 29
-#define GCC_GP2_CLK_SRC 30
-#define GCC_GP3_CLK 31
-#define GCC_GP3_CLK_SRC 32
-#define GCC_GPU_CFG_AHB_CLK 33
-#define GCC_GPU_GPLL0_CLK_SRC 34
-#define GCC_GPU_GPLL0_DIV_CLK_SRC 35
-#define GCC_GPU_MEMNOC_GFX_CLK 36
-#define GCC_GPU_SNOC_DVM_GFX_CLK 37
-#define GCC_MSS_AXIS2_CLK 38
-#define GCC_MSS_CFG_AHB_CLK 39
-#define GCC_MSS_GPLL0_DIV_CLK_SRC 40
-#define GCC_MSS_MFAB_AXIS_CLK 41
-#define GCC_MSS_Q6_MEMNOC_AXI_CLK 42
-#define GCC_MSS_SNOC_AXI_CLK 43
-#define GCC_PCIE_0_AUX_CLK 44
-#define GCC_PCIE_0_AUX_CLK_SRC 45
-#define GCC_PCIE_0_CFG_AHB_CLK 46
-#define GCC_PCIE_0_CLKREF_CLK 47
-#define GCC_PCIE_0_MSTR_AXI_CLK 48
-#define GCC_PCIE_0_PIPE_CLK 49
-#define GCC_PCIE_0_SLV_AXI_CLK 50
-#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 51
-#define GCC_PCIE_1_AUX_CLK 52
-#define GCC_PCIE_1_AUX_CLK_SRC 53
-#define GCC_PCIE_1_CFG_AHB_CLK 54
-#define GCC_PCIE_1_CLKREF_CLK 55
-#define GCC_PCIE_1_MSTR_AXI_CLK 56
-#define GCC_PCIE_1_PIPE_CLK 57
-#define GCC_PCIE_1_SLV_AXI_CLK 58
-#define GCC_PCIE_1_SLV_Q2A_AXI_CLK 59
-#define GCC_PCIE_PHY_AUX_CLK 60
-#define GCC_PCIE_PHY_REFGEN_CLK 61
-#define GCC_PCIE_PHY_REFGEN_CLK_SRC 62
-#define GCC_PDM2_CLK 63
-#define GCC_PDM2_CLK_SRC 64
-#define GCC_PDM_AHB_CLK 65
-#define GCC_PDM_XO4_CLK 66
-#define GCC_PRNG_AHB_CLK 67
-#define GCC_QMIP_CAMERA_AHB_CLK 68
-#define GCC_QMIP_DISP_AHB_CLK 69
-#define GCC_QMIP_VIDEO_AHB_CLK 70
-#define GCC_QUPV3_WRAP0_S0_CLK 71
-#define GCC_QUPV3_WRAP0_S0_CLK_SRC 72
-#define GCC_QUPV3_WRAP0_S1_CLK 73
-#define GCC_QUPV3_WRAP0_S1_CLK_SRC 74
-#define GCC_QUPV3_WRAP0_S2_CLK 75
-#define GCC_QUPV3_WRAP0_S2_CLK_SRC 76
-#define GCC_QUPV3_WRAP0_S3_CLK 77
-#define GCC_QUPV3_WRAP0_S3_CLK_SRC 78
-#define GCC_QUPV3_WRAP0_S4_CLK 79
-#define GCC_QUPV3_WRAP0_S4_CLK_SRC 80
-#define GCC_QUPV3_WRAP0_S5_CLK 81
-#define GCC_QUPV3_WRAP0_S5_CLK_SRC 82
-#define GCC_QUPV3_WRAP0_S6_CLK 83
-#define GCC_QUPV3_WRAP0_S6_CLK_SRC 84
-#define GCC_QUPV3_WRAP0_S7_CLK 85
-#define GCC_QUPV3_WRAP0_S7_CLK_SRC 86
-#define GCC_QUPV3_WRAP1_S0_CLK 87
-#define GCC_QUPV3_WRAP1_S0_CLK_SRC 88
-#define GCC_QUPV3_WRAP1_S1_CLK 89
-#define GCC_QUPV3_WRAP1_S1_CLK_SRC 90
-#define GCC_QUPV3_WRAP1_S2_CLK 91
-#define GCC_QUPV3_WRAP1_S2_CLK_SRC 92
-#define GCC_QUPV3_WRAP1_S3_CLK 93
-#define GCC_QUPV3_WRAP1_S3_CLK_SRC 94
-#define GCC_QUPV3_WRAP1_S4_CLK 95
-#define GCC_QUPV3_WRAP1_S4_CLK_SRC 96
-#define GCC_QUPV3_WRAP1_S5_CLK 97
-#define GCC_QUPV3_WRAP1_S5_CLK_SRC 98
-#define GCC_QUPV3_WRAP1_S6_CLK 99
-#define GCC_QUPV3_WRAP1_S6_CLK_SRC 100
-#define GCC_QUPV3_WRAP1_S7_CLK 101
-#define GCC_QUPV3_WRAP1_S7_CLK_SRC 102
-#define GCC_QUPV3_WRAP_0_M_AHB_CLK 103
-#define GCC_QUPV3_WRAP_0_S_AHB_CLK 104
-#define GCC_QUPV3_WRAP_1_M_AHB_CLK 105
-#define GCC_QUPV3_WRAP_1_S_AHB_CLK 106
-#define GCC_RX1_USB2_CLKREF_CLK 107
-#define GCC_RX2_QLINK_CLKREF_CLK 108
-#define GCC_SDCC2_AHB_CLK 109
-#define GCC_SDCC2_APPS_CLK 110
-#define GCC_SDCC2_APPS_CLK_SRC 111
-#define GCC_SDCC4_AHB_CLK 112
-#define GCC_SDCC4_APPS_CLK 113
-#define GCC_SDCC4_APPS_CLK_SRC 114
-#define GCC_SYS_NOC_CPUSS_AHB_CLK 115
-#define GCC_TSIF_AHB_CLK 116
-#define GCC_TSIF_INACTIVITY_TIMERS_CLK 117
-#define GCC_TSIF_REF_CLK 118
-#define GCC_TSIF_REF_CLK_SRC 119
-#define GCC_UFS_CARD_AHB_CLK 120
-#define GCC_UFS_CARD_AXI_CLK 121
-#define GCC_UFS_CARD_AXI_CLK_SRC 122
-#define GCC_UFS_CARD_CLKREF_CLK 123
-#define GCC_UFS_CARD_ICE_CORE_CLK 124
-#define GCC_UFS_CARD_ICE_CORE_CLK_SRC 125
-#define GCC_UFS_CARD_PHY_AUX_CLK 126
-#define GCC_UFS_CARD_PHY_AUX_CLK_SRC 127
-#define GCC_UFS_CARD_RX_SYMBOL_0_CLK 128
-#define GCC_UFS_CARD_RX_SYMBOL_1_CLK 129
-#define GCC_UFS_CARD_TX_SYMBOL_0_CLK 130
-#define GCC_UFS_CARD_UNIPRO_CORE_CLK 131
-#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC 132
-#define GCC_UFS_MEM_CLKREF_CLK 133
-#define GCC_UFS_PHY_AHB_CLK 134
-#define GCC_UFS_PHY_AXI_CLK 135
-#define GCC_UFS_PHY_AXI_CLK_SRC 136
-#define GCC_UFS_PHY_ICE_CORE_CLK 137
-#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 138
-#define GCC_UFS_PHY_PHY_AUX_CLK 139
-#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 140
-#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 141
-#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 142
-#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 143
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK 144
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 145
-#define GCC_USB30_PRIM_MASTER_CLK 146
-#define GCC_USB30_PRIM_MASTER_CLK_SRC 147
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK 148
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 149
-#define GCC_USB30_PRIM_SLEEP_CLK 150
-#define GCC_USB30_SEC_MASTER_CLK 151
-#define GCC_USB30_SEC_MASTER_CLK_SRC 152
-#define GCC_USB30_SEC_MOCK_UTMI_CLK 153
-#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC 154
-#define GCC_USB30_SEC_SLEEP_CLK 155
-#define GCC_USB3_PRIM_CLKREF_CLK 156
-#define GCC_USB3_PRIM_PHY_AUX_CLK 157
-#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 158
-#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 159
-#define GCC_USB3_PRIM_PHY_PIPE_CLK 160
-#define GCC_USB3_SEC_CLKREF_CLK 161
-#define GCC_USB3_SEC_PHY_AUX_CLK 162
-#define GCC_USB3_SEC_PHY_AUX_CLK_SRC 163
-#define GCC_USB3_SEC_PHY_COM_AUX_CLK 164
-#define GCC_USB3_SEC_PHY_PIPE_CLK 165
-#define GCC_USB_PHY_CFG_AHB2PHY_CLK 166
-#define GCC_VIDEO_AHB_CLK 167
-#define GCC_VIDEO_AXI_CLK 168
-#define GCC_VIDEO_XO_CLK 169
-#define GPLL0 170
-#define GPLL0_OUT_EVEN 171
-#define GPLL0_OUT_MAIN 172
-#define GPLL1 173
-#define GPLL1_OUT_MAIN 174
+#define GCC_DDRSS_GPU_AXI_CLK 20
+#define GCC_DISP_AHB_CLK 21
+#define GCC_DISP_AXI_CLK 22
+#define GCC_DISP_GPLL0_CLK_SRC 23
+#define GCC_DISP_GPLL0_DIV_CLK_SRC 24
+#define GCC_DISP_XO_CLK 25
+#define GCC_GP1_CLK 26
+#define GCC_GP1_CLK_SRC 27
+#define GCC_GP2_CLK 28
+#define GCC_GP2_CLK_SRC 29
+#define GCC_GP3_CLK 30
+#define GCC_GP3_CLK_SRC 31
+#define GCC_GPU_CFG_AHB_CLK 32
+#define GCC_GPU_GPLL0_CLK_SRC 33
+#define GCC_GPU_GPLL0_DIV_CLK_SRC 34
+#define GCC_GPU_MEMNOC_GFX_CLK 35
+#define GCC_GPU_SNOC_DVM_GFX_CLK 36
+#define GCC_MSS_AXIS2_CLK 37
+#define GCC_MSS_CFG_AHB_CLK 38
+#define GCC_MSS_GPLL0_DIV_CLK_SRC 39
+#define GCC_MSS_MFAB_AXIS_CLK 40
+#define GCC_MSS_Q6_MEMNOC_AXI_CLK 41
+#define GCC_MSS_SNOC_AXI_CLK 42
+#define GCC_PCIE_0_AUX_CLK 43
+#define GCC_PCIE_0_AUX_CLK_SRC 44
+#define GCC_PCIE_0_CFG_AHB_CLK 45
+#define GCC_PCIE_0_CLKREF_CLK 46
+#define GCC_PCIE_0_MSTR_AXI_CLK 47
+#define GCC_PCIE_0_PIPE_CLK 48
+#define GCC_PCIE_0_SLV_AXI_CLK 49
+#define GCC_PCIE_0_SLV_Q2A_AXI_CLK 50
+#define GCC_PCIE_1_AUX_CLK 51
+#define GCC_PCIE_1_AUX_CLK_SRC 52
+#define GCC_PCIE_1_CFG_AHB_CLK 53
+#define GCC_PCIE_1_CLKREF_CLK 54
+#define GCC_PCIE_1_MSTR_AXI_CLK 55
+#define GCC_PCIE_1_PIPE_CLK 56
+#define GCC_PCIE_1_SLV_AXI_CLK 57
+#define GCC_PCIE_1_SLV_Q2A_AXI_CLK 58
+#define GCC_PCIE_PHY_AUX_CLK 59
+#define GCC_PCIE_PHY_REFGEN_CLK 60
+#define GCC_PCIE_PHY_REFGEN_CLK_SRC 61
+#define GCC_PDM2_CLK 62
+#define GCC_PDM2_CLK_SRC 63
+#define GCC_PDM_AHB_CLK 64
+#define GCC_PDM_XO4_CLK 65
+#define GCC_PRNG_AHB_CLK 66
+#define GCC_QMIP_CAMERA_AHB_CLK 67
+#define GCC_QMIP_DISP_AHB_CLK 68
+#define GCC_QMIP_VIDEO_AHB_CLK 69
+#define GCC_QUPV3_WRAP0_S0_CLK 70
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC 71
+#define GCC_QUPV3_WRAP0_S1_CLK 72
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC 73
+#define GCC_QUPV3_WRAP0_S2_CLK 74
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC 75
+#define GCC_QUPV3_WRAP0_S3_CLK 76
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC 77
+#define GCC_QUPV3_WRAP0_S4_CLK 78
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC 79
+#define GCC_QUPV3_WRAP0_S5_CLK 80
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC 81
+#define GCC_QUPV3_WRAP0_S6_CLK 82
+#define GCC_QUPV3_WRAP0_S6_CLK_SRC 83
+#define GCC_QUPV3_WRAP0_S7_CLK 84
+#define GCC_QUPV3_WRAP0_S7_CLK_SRC 85
+#define GCC_QUPV3_WRAP1_S0_CLK 86
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC 87
+#define GCC_QUPV3_WRAP1_S1_CLK 88
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC 89
+#define GCC_QUPV3_WRAP1_S2_CLK 90
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC 91
+#define GCC_QUPV3_WRAP1_S3_CLK 92
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC 93
+#define GCC_QUPV3_WRAP1_S4_CLK 94
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC 95
+#define GCC_QUPV3_WRAP1_S5_CLK 96
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC 97
+#define GCC_QUPV3_WRAP1_S6_CLK 98
+#define GCC_QUPV3_WRAP1_S6_CLK_SRC 99
+#define GCC_QUPV3_WRAP1_S7_CLK 100
+#define GCC_QUPV3_WRAP1_S7_CLK_SRC 101
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK 102
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK 103
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK 104
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK 105
+#define GCC_SDCC2_AHB_CLK 106
+#define GCC_SDCC2_APPS_CLK 107
+#define GCC_SDCC2_APPS_CLK_SRC 108
+#define GCC_SDCC4_AHB_CLK 109
+#define GCC_SDCC4_APPS_CLK 110
+#define GCC_SDCC4_APPS_CLK_SRC 111
+#define GCC_SYS_NOC_CPUSS_AHB_CLK 112
+#define GCC_TSIF_AHB_CLK 113
+#define GCC_TSIF_INACTIVITY_TIMERS_CLK 114
+#define GCC_TSIF_REF_CLK 115
+#define GCC_TSIF_REF_CLK_SRC 116
+#define GCC_UFS_CARD_AHB_CLK 117
+#define GCC_UFS_CARD_AXI_CLK 118
+#define GCC_UFS_CARD_AXI_CLK_SRC 119
+#define GCC_UFS_CARD_CLKREF_CLK 120
+#define GCC_UFS_CARD_ICE_CORE_CLK 121
+#define GCC_UFS_CARD_ICE_CORE_CLK_SRC 122
+#define GCC_UFS_CARD_PHY_AUX_CLK 123
+#define GCC_UFS_CARD_PHY_AUX_CLK_SRC 124
+#define GCC_UFS_CARD_RX_SYMBOL_0_CLK 125
+#define GCC_UFS_CARD_RX_SYMBOL_1_CLK 126
+#define GCC_UFS_CARD_TX_SYMBOL_0_CLK 127
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK 128
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC 129
+#define GCC_UFS_MEM_CLKREF_CLK 130
+#define GCC_UFS_PHY_AHB_CLK 131
+#define GCC_UFS_PHY_AXI_CLK 132
+#define GCC_UFS_PHY_AXI_CLK_SRC 133
+#define GCC_UFS_PHY_ICE_CORE_CLK 134
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC 135
+#define GCC_UFS_PHY_PHY_AUX_CLK 136
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC 137
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK 138
+#define GCC_UFS_PHY_RX_SYMBOL_1_CLK 139
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK 140
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK 141
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC 142
+#define GCC_USB30_PRIM_MASTER_CLK 143
+#define GCC_USB30_PRIM_MASTER_CLK_SRC 144
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK 145
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC 146
+#define GCC_USB30_PRIM_SLEEP_CLK 147
+#define GCC_USB30_SEC_MASTER_CLK 148
+#define GCC_USB30_SEC_MASTER_CLK_SRC 149
+#define GCC_USB30_SEC_MOCK_UTMI_CLK 150
+#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC 151
+#define GCC_USB30_SEC_SLEEP_CLK 152
+#define GCC_USB3_PRIM_CLKREF_CLK 153
+#define GCC_USB3_PRIM_PHY_AUX_CLK 154
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC 155
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK 156
+#define GCC_USB3_PRIM_PHY_PIPE_CLK 157
+#define GCC_USB3_SEC_CLKREF_CLK 158
+#define GCC_USB3_SEC_PHY_AUX_CLK 159
+#define GCC_USB3_SEC_PHY_AUX_CLK_SRC 160
+#define GCC_USB3_SEC_PHY_COM_AUX_CLK 161
+#define GCC_USB3_SEC_PHY_PIPE_CLK 162
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 163
+#define GCC_VIDEO_AHB_CLK 164
+#define GCC_VIDEO_AXI_CLK 165
+#define GCC_VIDEO_XO_CLK 166
+#define GPLL0 167
+#define GPLL0_OUT_EVEN 168
+#define GPLL0_OUT_MAIN 169
+#define GPLL1 170
+#define GPLL1_OUT_MAIN 171
/* GCC reset clocks */
#define GCC_GPU_BCR 0
diff --git a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
new file mode 100644
index 0000000..6243588
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_SDX24_H
+#define _DT_BINDINGS_CLK_MSM_GCC_SDX24_H
+
+/* GCC clock registers */
+#define GCC_BLSP1_AHB_CLK 0
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 1
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC 2
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 3
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC 4
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 5
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC 6
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 7
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC 8
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 9
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC 10
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 11
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC 12
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 13
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC 14
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 15
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC 16
+#define GCC_BLSP1_SLEEP_CLK 17
+#define GCC_BLSP1_UART1_APPS_CLK 18
+#define GCC_BLSP1_UART1_APPS_CLK_SRC 19
+#define GCC_BLSP1_UART2_APPS_CLK 20
+#define GCC_BLSP1_UART2_APPS_CLK_SRC 21
+#define GCC_BLSP1_UART3_APPS_CLK 22
+#define GCC_BLSP1_UART3_APPS_CLK_SRC 23
+#define GCC_BLSP1_UART4_APPS_CLK 24
+#define GCC_BLSP1_UART4_APPS_CLK_SRC 25
+#define GCC_BOOT_ROM_AHB_CLK 26
+#define GCC_CE1_AHB_CLK 27
+#define GCC_CE1_AXI_CLK 28
+#define GCC_CE1_CLK 29
+#define GCC_CPUSS_AHB_CLK 30
+#define GCC_CPUSS_AHB_CLK_SRC 31
+#define GCC_CPUSS_GNOC_CLK 32
+#define GCC_CPUSS_GPLL0_CLK_SRC 33
+#define GCC_CPUSS_RBCPR_CLK 34
+#define GCC_CPUSS_RBCPR_CLK_SRC 35
+#define GCC_GP1_CLK 36
+#define GCC_GP1_CLK_SRC 37
+#define GCC_GP2_CLK 38
+#define GCC_GP2_CLK_SRC 39
+#define GCC_GP3_CLK 40
+#define GCC_GP3_CLK_SRC 41
+#define GCC_MSS_CFG_AHB_CLK 42
+#define GCC_MSS_GPLL0_DIV_CLK_SRC 43
+#define GCC_MSS_SNOC_AXI_CLK 44
+#define GCC_PCIE_AUX_CLK 45
+#define GCC_PCIE_AUX_PHY_CLK_SRC 46
+#define GCC_PCIE_CFG_AHB_CLK 47
+#define GCC_PCIE_MSTR_AXI_CLK 48
+#define GCC_PCIE_PHY_REFGEN_CLK 49
+#define GCC_PCIE_PHY_REFGEN_CLK_SRC 50
+#define GCC_PCIE_PIPE_CLK 51
+#define GCC_PCIE_SLEEP_CLK 52
+#define GCC_PCIE_SLV_AXI_CLK 53
+#define GCC_PCIE_SLV_Q2A_AXI_CLK 54
+#define GCC_PDM2_CLK 55
+#define GCC_PDM2_CLK_SRC 56
+#define GCC_PDM_AHB_CLK 57
+#define GCC_PDM_XO4_CLK 58
+#define GCC_PRNG_AHB_CLK 59
+#define GCC_SDCC1_AHB_CLK 60
+#define GCC_SDCC1_APPS_CLK 61
+#define GCC_SDCC1_APPS_CLK_SRC 62
+#define GCC_SPMI_FETCHER_AHB_CLK 63
+#define GCC_SPMI_FETCHER_CLK 64
+#define GCC_SPMI_FETCHER_CLK_SRC 65
+#define GCC_SYS_NOC_CPUSS_AHB_CLK 66
+#define GCC_USB30_MASTER_CLK 67
+#define GCC_USB30_MASTER_CLK_SRC 68
+#define GCC_USB30_MOCK_UTMI_CLK 69
+#define GCC_USB30_MOCK_UTMI_CLK_SRC 70
+#define GCC_USB30_SLEEP_CLK 71
+#define GCC_USB3_PHY_AUX_CLK 72
+#define GCC_USB3_PHY_AUX_CLK_SRC 73
+#define GCC_USB3_PHY_PIPE_CLK 74
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK 75
+#define GCC_XO_DIV4_CLK 76
+#define GPLL0 77
+#define GPLL0_OUT_EVEN 78
+
+/* GDSCs */
+#define PCIE_GDSC 0
+#define USB30_GDSC 1
+
+/* CPU clocks */
+#define CLOCK_A7SS 0
+
+/* GCC reset clocks */
+#define GCC_BLSP1_QUP1_BCR 0
+#define GCC_BLSP1_QUP2_BCR 1
+#define GCC_BLSP1_QUP3_BCR 2
+#define GCC_BLSP1_QUP4_BCR 3
+#define GCC_BLSP1_UART2_BCR 4
+#define GCC_BLSP1_UART3_BCR 5
+#define GCC_BLSP1_UART4_BCR 6
+#define GCC_CE1_BCR 7
+#define GCC_PCIE_BCR 8
+#define GCC_PCIE_PHY_BCR 9
+#define GCC_PDM_BCR 10
+#define GCC_PRNG_BCR 11
+#define GCC_SDCC1_BCR 12
+#define GCC_SPMI_FETCHER_BCR 13
+#define GCC_USB30_BCR 14
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR 15
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gpucc-sdm845.h b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
index 13de1e1..c43a9f8 100644
--- a/include/dt-bindings/clock/qcom,gpucc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
@@ -17,37 +17,36 @@
/* GPUCC clock registers */
#define GPU_CC_ACD_AHB_CLK 0
#define GPU_CC_ACD_CXO_CLK 1
-#define GPU_CC_AHB_CLK 2
+#define GPU_CC_AHB_CLK 2
#define GPU_CC_CRC_AHB_CLK 3
#define GPU_CC_CX_APB_CLK 4
#define GPU_CC_CX_GMU_CLK 5
#define GPU_CC_CX_QDSS_AT_CLK 6
#define GPU_CC_CX_QDSS_TRIG_CLK 7
-#define GPU_CC_CX_QDSS_TSCTR_CLK 8
-#define GPU_CC_CX_SNOC_DVM_CLK 9
+#define GPU_CC_CX_QDSS_TSCTR_CLK 8
+#define GPU_CC_CX_SNOC_DVM_CLK 9
#define GPU_CC_CXO_AON_CLK 10
-#define GPU_CC_CXO_CLK 11
-#define GPU_CC_DEBUG_CLK 12
-#define GPU_CC_GX_CXO_CLK 13
-#define GPU_CC_GX_GMU_CLK 14
-#define GPU_CC_GX_QDSS_TSCTR_CLK 15
-#define GPU_CC_GX_VSENSE_CLK 16
-#define GPU_CC_PLL0_OUT_MAIN 17
-#define GPU_CC_PLL0_OUT_ODD 18
-#define GPU_CC_PLL0_OUT_TEST 19
-#define GPU_CC_PLL1 20
-#define GPU_CC_PLL1_OUT_EVEN 21
-#define GPU_CC_PLL1_OUT_MAIN 22
-#define GPU_CC_PLL1_OUT_ODD 23
-#define GPU_CC_PLL1_OUT_TEST 24
-#define GPU_CC_PLL_TEST_CLK 25
-#define GPU_CC_RBCPR_AHB_CLK 26
-#define GPU_CC_RBCPR_CLK 27
-#define GPU_CC_RBCPR_CLK_SRC 28
-#define GPU_CC_SLEEP_CLK 29
-#define GPU_CC_GMU_CLK_SRC 30
-#define GPU_CC_CX_GFX3D_CLK 31
-#define GPU_CC_CX_GFX3D_SLV_CLK 32
+#define GPU_CC_CXO_CLK 11
+#define GPU_CC_GX_CXO_CLK 12
+#define GPU_CC_GX_GMU_CLK 13
+#define GPU_CC_GX_QDSS_TSCTR_CLK 14
+#define GPU_CC_GX_VSENSE_CLK 15
+#define GPU_CC_PLL0_OUT_MAIN 16
+#define GPU_CC_PLL0_OUT_ODD 17
+#define GPU_CC_PLL0_OUT_TEST 18
+#define GPU_CC_PLL1 19
+#define GPU_CC_PLL1_OUT_EVEN 20
+#define GPU_CC_PLL1_OUT_MAIN 21
+#define GPU_CC_PLL1_OUT_ODD 22
+#define GPU_CC_PLL1_OUT_TEST 23
+#define GPU_CC_PLL_TEST_CLK 24
+#define GPU_CC_RBCPR_AHB_CLK 25
+#define GPU_CC_RBCPR_CLK 26
+#define GPU_CC_RBCPR_CLK_SRC 27
+#define GPU_CC_SLEEP_CLK 28
+#define GPU_CC_GMU_CLK_SRC 29
+#define GPU_CC_CX_GFX3D_CLK 30
+#define GPU_CC_CX_GFX3D_SLV_CLK 31
/* GPUCC reset clock registers */
#define GPUCC_GPU_CC_ACD_BCR 0
@@ -63,5 +62,5 @@
#define GPU_CC_PLL0 0
#define GPU_CC_PLL0_OUT_EVEN 1
#define GPU_CC_GX_GFX3D_CLK_SRC 2
-#define GPU_CC_GX_GFX3D_CLK 3
+#define GPU_CC_GX_GFX3D_CLK 3
#endif
diff --git a/include/dt-bindings/clock/qcom,videocc-sdm845.h b/include/dt-bindings/clock/qcom,videocc-sdm845.h
index 723d2e0..b362852d 100644
--- a/include/dt-bindings/clock/qcom,videocc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,videocc-sdm845.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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
@@ -16,18 +16,17 @@
#define VIDEO_CC_APB_CLK 0
#define VIDEO_CC_AT_CLK 1
-#define VIDEO_CC_DEBUG_CLK 2
-#define VIDEO_CC_QDSS_TRIG_CLK 3
-#define VIDEO_CC_QDSS_TSCTR_DIV8_CLK 4
-#define VIDEO_CC_VCODEC0_AXI_CLK 5
-#define VIDEO_CC_VCODEC0_CORE_CLK 6
-#define VIDEO_CC_VCODEC1_AXI_CLK 7
-#define VIDEO_CC_VCODEC1_CORE_CLK 8
-#define VIDEO_CC_VENUS_AHB_CLK 9
-#define VIDEO_CC_VENUS_CLK_SRC 10
-#define VIDEO_CC_VENUS_CTL_AXI_CLK 11
-#define VIDEO_CC_VENUS_CTL_CORE_CLK 12
-#define VIDEO_PLL0 13
+#define VIDEO_CC_QDSS_TRIG_CLK 2
+#define VIDEO_CC_QDSS_TSCTR_DIV8_CLK 3
+#define VIDEO_CC_VCODEC0_AXI_CLK 4
+#define VIDEO_CC_VCODEC0_CORE_CLK 5
+#define VIDEO_CC_VCODEC1_AXI_CLK 6
+#define VIDEO_CC_VCODEC1_CORE_CLK 7
+#define VIDEO_CC_VENUS_AHB_CLK 8
+#define VIDEO_CC_VENUS_CLK_SRC 9
+#define VIDEO_CC_VENUS_CTL_AXI_CLK 10
+#define VIDEO_CC_VENUS_CTL_CORE_CLK 11
+#define VIDEO_PLL0 12
#define VIDEO_CC_INTERFACE_BCR 0
#define VIDEO_CC_VCODEC0_BCR 1
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index af84de6..0353461 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -579,6 +579,24 @@
*/
int subsys_cgroup_allow_attach(struct cgroup_taskset *tset);
+static inline void cgroup_init_kthreadd(void)
+{
+ /*
+ * kthreadd is inherited by all kthreads, keep it in the root so
+ * that the new kthreads are guaranteed to stay in the root until
+ * initialization is finished.
+ */
+ current->no_cgroup_migration = 1;
+}
+
+static inline void cgroup_kthread_ready(void)
+{
+ /*
+ * This kthread finished initialization. The creator should have
+ * set PF_NO_SETAFFINITY if this kthread should stay in the root.
+ */
+ current->no_cgroup_migration = 0;
+}
#else /* !CONFIG_CGROUPS */
@@ -600,6 +618,8 @@
static inline int cgroup_init_early(void) { return 0; }
static inline int cgroup_init(void) { return 0; }
+static inline void cgroup_init_kthreadd(void) {}
+static inline void cgroup_kthread_ready(void) {}
static inline bool task_under_cgroup_hierarchy(struct task_struct *task,
struct cgroup *ancestor)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 8fd5fba..b1f2d00 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -36,7 +36,11 @@
#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
/* parents need enable during gate/ungate, set rate and re-parent */
#define CLK_OPS_PARENT_ENABLE BIT(12)
- /* unused */
+#define CLK_ENABLE_HAND_OFF BIT(13) /* enable clock when registered. */
+ /*
+ * hand-off enable_count & prepare_count
+ * to first consumer that enables clk
+ */
#define CLK_IS_MEASURE BIT(14) /* measure clock */
struct clk;
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 373dbd5..ec9c128 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -855,7 +855,9 @@
struct vm_area_struct *vma, void *cpu_addr,
dma_addr_t dma_addr, size_t size)
{
- return -ENODEV;
+ unsigned long attrs = DMA_ATTR_NON_CONSISTENT;
+
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
}
#if defined(CONFIG_NEED_DMA_MAP_STATE) || defined(CONFIG_DMA_API_DEBUG)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 5d3a4cd..3efd210 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -435,6 +435,7 @@
const struct iommu_ops *ops);
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+int iommu_fwspec_get_id(struct device *dev, u32 *id);
#else /* CONFIG_IOMMU_API */
@@ -705,6 +706,11 @@
return -ENODEV;
}
+int iommu_fwspec_get_id(struct device *dev, u32 *id)
+{
+ return -ENODEV;
+}
+
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d0ec667..72dd7ba 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -439,6 +439,8 @@
u8 *cached_ext_csd;
bool cmdq_init;
struct mmc_bkops_info bkops;
+ bool err_in_sdr104;
+ bool sdr104_blocked;
};
/*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 5d5aff1..959414b 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -179,6 +179,7 @@
extern int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
extern int mmc_set_auto_bkops(struct mmc_card *card, bool enable);
+extern int mmc_suspend_clk_scaling(struct mmc_host *host);
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index ba1e826..ecfc173 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -587,6 +587,8 @@
struct io_latency_state io_lat_s;
#endif
+ bool sdr104_wa;
+
/*
* Set to 1 to just stop the SDCLK to the card without
* actually disabling the clock from it's source.
@@ -751,6 +753,16 @@
MMC_CAP_UHS_DDR50);
}
+static inline void mmc_host_clear_sdr104(struct mmc_host *host)
+{
+ host->caps &= ~MMC_CAP_UHS_SDR104;
+}
+
+static inline void mmc_host_set_sdr104(struct mmc_host *host)
+{
+ host->caps |= MMC_CAP_UHS_SDR104;
+}
+
static inline int mmc_host_packed_wr(struct mmc_host *host)
{
return host->caps2 & MMC_CAP2_PACKED_WR;
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index 6b790c6..cb4387d 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -39,6 +39,7 @@
struct clk *m_ahb_clk;
struct clk *s_ahb_clk;
struct msm_bus_client_handle *bus_bw;
+ unsigned int bus_mas;
unsigned long ab;
unsigned long ib;
struct pinctrl *geni_pinctrl;
@@ -87,6 +88,7 @@
#define SE_GENI_RX_RFR_WATERMARK_REG (0x814)
#define SE_GENI_M_GP_LENGTH (0x910)
#define SE_GENI_S_GP_LENGTH (0x914)
+#define SE_GSI_EVENT_EN (0xE18)
#define SE_IRQ_EN (0xE1C)
#define SE_HW_PARAM_0 (0xE24)
#define SE_HW_PARAM_1 (0xE28)
@@ -220,6 +222,12 @@
#define RX_LAST_BYTE_VALID_SHFT (28)
#define RX_FIFO_WC_MSK (GENMASK(24, 0))
+/* SE_GSI_EVENT_EN fields */
+#define DMA_RX_EVENT_EN (BIT(0))
+#define DMA_TX_EVENT_EN (BIT(1))
+#define GENI_M_EVENT_EN (BIT(2))
+#define GENI_S_EVENT_EN (BIT(3))
+
/* SE_IRQ_EN fields */
#define DMA_RX_IRQ_EN (BIT(0))
#define DMA_TX_IRQ_EN (BIT(1))
@@ -331,9 +339,11 @@
int ret = 0;
unsigned int io_mode = 0;
unsigned int geni_dma_mode = 0;
+ unsigned int gsi_event_en = 0;
io_mode = geni_read_reg(base, SE_IRQ_EN);
geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN);
+ gsi_event_en = geni_read_reg(base, SE_GSI_EVENT_EN);
switch (mode) {
case FIFO_MODE:
@@ -341,15 +351,23 @@
io_mode |= (GENI_M_IRQ_EN | GENI_S_IRQ_EN);
io_mode |= (DMA_TX_IRQ_EN | DMA_RX_IRQ_EN);
geni_dma_mode &= ~GENI_DMA_MODE_EN;
+ gsi_event_en = 0;
break;
}
+ case GSI_DMA:
+ geni_dma_mode |= GENI_DMA_MODE_EN;
+ io_mode &= ~(DMA_TX_IRQ_EN | DMA_RX_IRQ_EN);
+ gsi_event_en |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN |
+ GENI_M_EVENT_EN | GENI_S_EVENT_EN);
+ break;
default:
ret = -ENXIO;
goto exit_set_mode;
}
geni_write_reg(io_mode, base, SE_IRQ_EN);
geni_write_reg(geni_dma_mode, base, SE_GENI_DMA_MODE_EN);
+ geni_write_reg(gsi_event_en, base, SE_GSI_EVENT_EN);
exit_set_mode:
return ret;
}
diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h
index a0e2283..7fca674 100644
--- a/include/linux/qpnp/qpnp-revid.h
+++ b/include/linux/qpnp/qpnp-revid.h
@@ -208,6 +208,12 @@
#define PM660_V1P1_REV3 0x01
#define PM660_V1P1_REV4 0x01
+/* PM660L REV_ID */
+#define PM660L_V1P1_REV1 0x00
+#define PM660L_V1P1_REV2 0x00
+#define PM660L_V1P1_REV3 0x01
+#define PM660L_V1P1_REV4 0x01
+
/* PMI8998 FAB_ID */
#define PMI8998_FAB_ID_SMIC 0x11
#define PMI8998_FAB_ID_GF 0x30
@@ -229,6 +235,9 @@
/* SMB1381 */
#define SMB1381_SUBTYPE 0x17
+/* SMB1355 */
+#define SMB1355_SUBTYPE 0x1C
+
struct pmic_revid_data {
u8 rev1;
u8 rev2;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 867de7d..52524a8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1167,6 +1167,8 @@
struct capacity_state *cap_states; /* ptr to capacity state array */
};
+extern bool sched_is_energy_aware(void);
+
unsigned long capacity_curr_of(int cpu);
struct sched_group;
@@ -1751,6 +1753,10 @@
#ifdef CONFIG_COMPAT_BRK
unsigned brk_randomized:1;
#endif
+#ifdef CONFIG_CGROUPS
+ /* disallow userland-initiated cgroup migration */
+ unsigned no_cgroup_migration:1;
+#endif
unsigned long atomic_flags; /* Flags needing atomic access. */
diff --git a/include/linux/seemp_instrumentation.h b/include/linux/seemp_instrumentation.h
index 2c050cb..21bc436 100644
--- a/include/linux/seemp_instrumentation.h
+++ b/include/linux/seemp_instrumentation.h
@@ -66,91 +66,11 @@
seemp_logk_kernel_end(blck);
}
-
-/*
- * NOTE: only recvfrom is going to be instrumented
- * since recv sys call internally calls recvfrom
- * with 2 extra parameters
- */
-static inline void seemp_logk_recvfrom(int fd, void __user *ubuf,
- size_t size, unsigned int flags, struct sockaddr __user *addr,
- int __user *addr_len)
-{
- char *buf = NULL;
- void *blck = NULL;
-
- /*sets up buf and blck correctly*/
- blck = seemp_setup_buf(&buf);
- if (!blck)
- return;
-
- /*fill the buf*/
- SEEMP_LOGK_RECORD(SEEMP_API_kernel__recvfrom, "size=%u,fd=%d",
- (unsigned int)size, fd);
-
- seemp_logk_kernel_end(blck);
-}
-
-static inline void seemp_logk_oom_adjust_write(pid_t pid,
- kuid_t uid, int oom_adj)
-{
- char *buf = NULL;
- void *blck = NULL;
-
- /*sets up buf and blck correctly*/
- blck = seemp_setup_buf(&buf);
- if (!blck)
- return;
-
- /*fill the buf*/
- SEEMP_LOGK_RECORD(SEEMP_API_kernel__oom_adjust_write,
- "app_uid=%d,app_pid=%d,oom_adj=%d",
- uid.val, pid, oom_adj);
-
- seemp_logk_kernel_end(blck);
-}
-
-static inline void seemp_logk_oom_score_adj_write(pid_t pid, kuid_t uid,
- int oom_adj_score)
-{
- char *buf = NULL;
- void *blck = NULL;
-
- /*sets up buf and blck correctly*/
- blck = seemp_setup_buf(&buf);
- if (!blck)
- return;
-
- /*fill the buf*/
- snprintf(buf, MAX_BUF_SIZE,
- "-1|kernel|oom_score_adj_write|app_uid=%d,app_pid=%d,oom_adj=%d|--end",
- uid.val, pid, oom_adj_score);
-
- seemp_logk_kernel_end(blck);
-}
-
#else
static inline void seemp_logk_sendto(int fd, void __user *buff,
size_t len, unsigned int flags, struct sockaddr __user *addr,
int addr_len)
{
}
-
-static inline void seemp_logk_recvfrom
- (int fd, void __user *ubuf, size_t size,
- unsigned int flags, struct sockaddr __user *addr,
- int __user *addr_len)
-{
-}
-
-static inline void seemp_logk_oom_adjust_write
- (pid_t pid, kuid_t uid, int oom_adj)
-{
-}
-
-static inline void seemp_logk_oom_score_adj_write
- (pid_t pid, kuid_t uid, int oom_adj_score)
-{
-}
#endif
#endif
diff --git a/include/linux/uio.h b/include/linux/uio.h
index 6e22b54..c146ebc 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -39,7 +39,10 @@
};
union {
unsigned long nr_segs;
- int idx;
+ struct {
+ int idx;
+ int start_idx;
+ };
};
};
@@ -81,6 +84,7 @@
size_t iov_iter_copy_from_user_atomic(struct page *page,
struct iov_iter *i, unsigned long offset, size_t bytes);
void iov_iter_advance(struct iov_iter *i, size_t bytes);
+void iov_iter_revert(struct iov_iter *i, size_t bytes);
int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
size_t iov_iter_single_seg_count(const struct iov_iter *i);
size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8ec7c30..931b494 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -260,27 +260,6 @@
#define SCSI_INQ_PQ_NOT_CON 0x01
#define SCSI_INQ_PQ_NOT_CAP 0x03
-
-/*
- * Here are some scsi specific ioctl commands which are sometimes useful.
- *
- * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
- */
-
-/* Used to obtain PUN and LUN info. Conflicts with CDROMAUDIOBUFSIZ */
-#define SCSI_IOCTL_GET_IDLUN 0x5382
-
-/* 0x5383 and 0x5384 were used for SCSI_IOCTL_TAGGED_{ENABLE,DISABLE} */
-
-/* Used to obtain the host number of a device. */
-#define SCSI_IOCTL_PROBE_HOST 0x5385
-
-/* Used to obtain the bus number for a device */
-#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
-
-/* Used to obtain the PCI location of a device */
-#define SCSI_IOCTL_GET_PCI 0x5387
-
/* Pull a u32 out of a SCSI message (using BE SCSI conventions) */
static inline __u32 scsi_to_u32(__u8 *ptr)
{
diff --git a/include/soc/qcom/memory_dump.h b/include/soc/qcom/memory_dump.h
index a7b87aa..dbae8e8 100644
--- a/include/soc/qcom/memory_dump.h
+++ b/include/soc/qcom/memory_dump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -62,7 +62,7 @@
#define MSM_DUMP_MINOR(val) (val & 0xFFFFF)
-#define MAX_NUM_ENTRIES 0x120
+#define MAX_NUM_ENTRIES 0x140
enum msm_dump_data_ids {
MSM_DUMP_DATA_CPU_CTX = 0x00,
@@ -82,10 +82,12 @@
MSM_DUMP_DATA_VSENSE = 0xE9,
MSM_DUMP_DATA_RPM = 0xEA,
MSM_DUMP_DATA_SCANDUMP = 0xEB,
+ MSM_DUMP_DATA_RPMH = 0xEC,
MSM_DUMP_DATA_TMC_ETF = 0xF0,
MSM_DUMP_DATA_TMC_REG = 0x100,
MSM_DUMP_DATA_LOG_BUF = 0x110,
MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111,
+ MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130,
MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES,
};
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index 2656d5d..b54eefc 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-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
@@ -96,6 +96,8 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmhamster")
#define early_machine_is_msmfalcon() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmfalcon")
+#define early_machine_is_sdxpoorwills() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdxpoorwills")
#define early_machine_is_sdm845() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm845")
#define early_machine_is_sdm830() \
@@ -137,6 +139,7 @@
#define early_machine_is_apqcobalt() 0
#define early_machine_is_msmhamster() 0
#define early_machine_is_msmfalcon() 0
+#define early_machine_is_sdxpoorwills() 0
#define early_machine_is_sdm845() 0
#define early_machine_is_sdm830() 0
#endif
@@ -198,6 +201,7 @@
MSM_CPU_COBALT,
MSM_CPU_HAMSTER,
MSM_CPU_FALCON,
+ SDX_CPU_SDXPOORWILLS,
MSM_CPU_SDM845,
MSM_CPU_SDM830,
};
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 6233e8f..0383c60 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -705,6 +705,7 @@
u64 unpacked_lun;
#define SE_LUN_LINK_MAGIC 0xffff7771
u32 lun_link_magic;
+ bool lun_shutdown;
bool lun_access_ro;
u32 lun_index;
diff --git a/include/uapi/drm/sde_drm.h b/include/uapi/drm/sde_drm.h
index b1bf6aa..74034c6 100644
--- a/include/uapi/drm/sde_drm.h
+++ b/include/uapi/drm/sde_drm.h
@@ -344,4 +344,16 @@
uint64_t modes;
};
+#define SDE_MAX_ROI_V1 4
+
+/**
+ * struct sde_drm_roi_v1 - list of regions of interest for a drm object
+ * @num_rects: number of valid rectangles in the roi array
+ * @roi: list of roi rectangles
+ */
+struct sde_drm_roi_v1 {
+ uint32_t num_rects;
+ struct drm_clip_rect roi[SDE_MAX_ROI_V1];
+};
+
#endif /* _SDE_DRM_H_ */
diff --git a/include/uapi/linux/seemp_param_id.h b/include/uapi/linux/seemp_param_id.h
index 8f1f05f..c72c579 100644
--- a/include/uapi/linux/seemp_param_id.h
+++ b/include/uapi/linux/seemp_param_id.h
@@ -1,6 +1,9 @@
#ifndef _PARAM_ID_H_
#define _PARAM_ID_H_
+#include <linux/string.h>
+#include <linux/types.h>
+
#define PARAM_ID_LEN 0
#define PARAM_ID_OOM_ADJ 1
#define PARAM_ID_APP_UID 2
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 86cb858..4f1f9e9 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1890,7 +1890,7 @@
#define V4L2_DEC_CMD_RESUME (3)
#define V4L2_QCOM_CMD_FLUSH (4)
#define V4L2_DEC_QCOM_CMD_RECONFIG_HINT (5)
-
+#define V4L2_QCOM_CMD_SESSION_CONTINUE (6)
/* Flags for V4L2_DEC_CMD_START */
#define V4L2_DEC_CMD_START_MUTE_AUDIO (1 << 0)
diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h
index 12afef9..cf56211 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -21,12 +21,13 @@
#define CAM_HANDLE_MEM_HANDLE 2
/**
- * struct cam_control - struct used by ioctl control for camera
+ * struct cam_control - Structure used by ioctl control for camera
+ *
* @op_code: This is the op code for camera control
- * @size: control command size
- * @handle_type: user pointer or shared memory handle
- * @reserved: reserved field for 64 bit alignment
- * @handle: control command payload
+ * @size: Control command size
+ * @handle_type: User pointer or shared memory handle
+ * @reserved: Reserved field for 64 bit alignment
+ * @handle: Control command payload
*/
struct cam_control {
uint32_t op_code;
@@ -46,7 +47,7 @@
* @major : Hardware version major
* @minor : Hardware version minor
* @incr : Hardware version increment
- * @reserved : reserved for 64 bit aligngment
+ * @reserved : Reserved for 64 bit aligngment
*/
struct cam_hw_version {
uint32_t major;
@@ -141,6 +142,7 @@
/* camera buffer direction */
#define CAM_BUF_INPUT 1
#define CAM_BUF_OUTPUT 2
+#define CAM_BUF_IN_OUT 3
/* camera packet device Type */
#define CAM_PACKET_DEV_BASE 0
@@ -168,12 +170,20 @@
#define CAM_PACKET_MAX_PLANES 3
/**
- * struct cam_plane_cfg - plane configuration info
+ * struct cam_plane_cfg - Plane configuration info
*
- * @width: plane width in pixels
- * @height: plane height in lines
- * @plane_stride: plane stride in pixel
- * @slice_height: slice height in line (not used by ISP)
+ * @width: Plane width in pixels
+ * @height: Plane height in lines
+ * @plane_stride: Plane stride in pixel
+ * @slice_height: Slice height in line (not used by ISP)
+ * @meta_stride: UBWC metadata stride
+ * @meta_size: UBWC metadata plane size
+ * @meta_offset: UBWC metadata offset
+ * @packer_config: UBWC packer config
+ * @mode_config: UBWC mode config
+ * @tile_config: UBWC tile config
+ * @h_init: UBWC horizontal initial coordinate in pixels
+ * @v_init: UBWC vertical initial coordinate in lines
*
*/
struct cam_plane_cfg {
@@ -181,60 +191,26 @@
uint32_t height;
uint32_t plane_stride;
uint32_t slice_height;
-};
-
-/**
- * struct cam_buf_io_cfg - Buffer io configuration for buffers
- *
- * @mem_handle: mem_handle array for the buffers.
- * @offsets: offsets for each planes in the buffer
- * @planes: per plane information
- * @width: main plane width in pixel
- * @height: main plane height in lines
- * @format: format of the buffer
- * @color_space: color space for the buffer
- * @color_pattern: color pattern in the buffer
- * @bpp: bit per pixel
- * @rotation: rotation information for the buffer
- * @resource_type: resource type associated with the buffer
- * @fence: fence handle
- * @cmd_buf_index: command buffer index to patch the buffer info
- * @cmd_buf_offset: offset within the command buffer to patch
- * @flag: flags for extra information
- * @direction: buffer direction: input or output
- * @padding: padding for the structure
- *
- */
-struct cam_buf_io_cfg {
- int32_t mem_handle[CAM_PACKET_MAX_PLANES];
- uint32_t offsets[CAM_PACKET_MAX_PLANES];
- struct cam_plane_cfg planes[CAM_PACKET_MAX_PLANES];
- uint32_t width;
- uint32_t height;
- uint32_t format;
- uint32_t color_space;
- uint32_t color_pattern;
- uint32_t bpp;
- uint32_t rotation;
- uint32_t resource_type;
- int32_t fence;
- uint32_t cmd_buf_index;
- uint32_t cmd_buf_offset;
- uint32_t flag;
- uint32_t direction;
- uint32_t padding;
+ uint32_t meta_stride;
+ uint32_t meta_size;
+ uint32_t meta_offset;
+ uint32_t packer_config;
+ uint32_t mode_config;
+ uint32_t tile_config;
+ uint32_t h_init;
+ uint32_t v_init;
};
/**
* struct cam_cmd_buf_desc - Command buffer descriptor
*
- * @mem_handle: command buffer handle
- * @offset: command start offset
- * @size: size of the command buffer in bytes
- * @length: used memory in command buffer in bytes
- * @type: type of the command buffer
- * @meta_data: data type for private command buffer
- * between UMD and KMD
+ * @mem_handle: Command buffer handle
+ * @offset: Command start offset
+ * @size: Size of the command buffer in bytes
+ * @length: Used memory in command buffer in bytes
+ * @type: Type of the command buffer
+ * @meta_data: Data type for private command buffer
+ * Between UMD and KMD
*
*/
struct cam_cmd_buf_desc {
@@ -247,13 +223,69 @@
};
/**
- * struct cam_packet_header - camera packet header
+ * struct cam_buf_io_cfg - Buffer io configuration for buffers
*
- * @op_code: camera packet opcode
- * @size: size of the camera packet in bytes
- * @request_id: request id for this camera packet
- * @flags: flags for the camera packet
- * @dev_type: camera packet device type
+ * @mem_handle: Mem_handle array for the buffers.
+ * @offsets: Offsets for each planes in the buffer
+ * @planes: Per plane information
+ * @width: Main plane width in pixel
+ * @height: Main plane height in lines
+ * @format: Format of the buffer
+ * @color_space: Color space for the buffer
+ * @color_pattern: Color pattern in the buffer
+ * @bpp: Bit per pixel
+ * @rotation: Rotation information for the buffer
+ * @resource_type: Resource type associated with the buffer
+ * @fence: Fence handle
+ * @early_fence: Fence handle for early signal
+ * @aux_cmd_buf: An auxiliary command buffer that may be
+ * used for programming the IO
+ * @direction: Direction of the config
+ * @batch_size: Batch size in HFR mode
+ * @subsample_pattern: Subsample pattern. Used in HFR mode. It
+ * should be consistent with batchSize and
+ * CAMIF programming.
+ * @subsample_period: Subsample period. Used in HFR mode. It
+ * should be consistent with batchSize and
+ * CAMIF programming.
+ * @framedrop_pattern: Framedrop pattern
+ * @framedrop_period: Framedrop period
+ * @flag: Flags for extra information
+ * @direction: Buffer direction: input or output
+ * @padding: Padding for the structure
+ *
+ */
+struct cam_buf_io_cfg {
+ int32_t mem_handle[CAM_PACKET_MAX_PLANES];
+ uint32_t offsets[CAM_PACKET_MAX_PLANES];
+ struct cam_plane_cfg planes[CAM_PACKET_MAX_PLANES];
+ uint32_t format;
+ uint32_t color_space;
+ uint32_t color_pattern;
+ uint32_t bpp;
+ uint32_t rotation;
+ uint32_t resource_type;
+ int32_t fence;
+ int32_t early_fence;
+ struct cam_cmd_buf_desc aux_cmd_buf;
+ uint32_t direction;
+ uint32_t batch_size;
+ uint32_t subsample_pattern;
+ uint32_t subsample_period;
+ uint32_t framedrop_pattern;
+ uint32_t framedrop_period;
+ uint32_t flag;
+ uint32_t padding;
+};
+
+/**
+ * struct cam_packet_header - Camera packet header
+ *
+ * @op_code: Camera packet opcode
+ * @size: Size of the camera packet in bytes
+ * @request_id: Request id for this camera packet
+ * @flags: Flags for the camera packet
+ * @padding: Padding
*
*/
struct cam_packet_header {
@@ -261,16 +293,16 @@
uint32_t size;
uint64_t request_id;
uint32_t flags;
- uint32_t dev_type;
+ uint32_t padding;
};
/**
* struct cam_patch_desc - Patch structure
*
- * @dst_buf_hdl: memory handle for the dest buffer
- * @dst_offset: offset byte in the dest buffer
- * @src_buf_hdl: memory handle for the source buffer
- * @src_offset: offset byte in the source buffer
+ * @dst_buf_hdl: Memory handle for the dest buffer
+ * @dst_offset: Offset byte in the dest buffer
+ * @src_buf_hdl: Memory handle for the source buffer
+ * @src_offset: Offset byte in the source buffer
*
*/
struct cam_patch_desc {
@@ -281,20 +313,20 @@
};
/**
- * struct cam_packet - cam packet structure
+ * struct cam_packet - Camera packet structure
*
- * @header: camera packet header
- * @cmd_buf_offset: command buffer start offset
- * @num_cmd_buf: number of the command buffer in the packet
- * @io_config_offset: buffer io configuration start offset
- * @num_io_configs: number of the buffer io configurations
- * @patch_offset: patch offset for the patch structure
- * @num_patches: number of the patch structure
- * @kmd_cmd_buf_index: command buffer index which contains extra
- * space for the KMD buffer
- * @kmd_cmd_buf_offset: offset from the beginning of the command
- * buffer for KMD usage.
- * @payload: camera packet payload
+ * @header: Camera packet header
+ * @cmd_buf_offset: Command buffer start offset
+ * @num_cmd_buf: Number of the command buffer in the packet
+ * @io_config_offset: Buffer io configuration start offset
+ * @num_io_configs: Number of the buffer io configurations
+ * @patch_offset: Patch offset for the patch structure
+ * @num_patches: Number of the patch structure
+ * @kmd_cmd_buf_index: Command buffer index which contains extra
+ * space for the KMD buffer
+ * @kmd_cmd_buf_offset: Offset from the beginning of the command
+ * buffer for KMD usage.
+ * @payload: Camera packet payload
*
*/
struct cam_packet {
@@ -313,10 +345,10 @@
/* Release Device */
/**
- * struct cam_release_dev_cmd - control payload for release devices
+ * struct cam_release_dev_cmd - Control payload for release devices
*
- * @session_handle: session handle for the release
- * @dev_handle: device handle for the release
+ * @session_handle: Session handle for the release
+ * @dev_handle: Device handle for the release
*/
struct cam_release_dev_cmd {
int32_t session_handle;
@@ -325,10 +357,10 @@
/* Start/Stop device */
/**
- * struct cam_start_stop_dev_cmd - control payload for start/stop device
+ * struct cam_start_stop_dev_cmd - Control payload for start/stop device
*
- * @session_handle: session handle for the start/stop command
- * @dev_handle: device handle for the start/stop command
+ * @session_handle: Session handle for the start/stop command
+ * @dev_handle: Device handle for the start/stop command
*
*/
struct cam_start_stop_dev_cmd {
@@ -338,13 +370,13 @@
/* Configure Device */
/**
- * struct cam_config_dev_cmd - command payload for configure device
+ * struct cam_config_dev_cmd - Command payload for configure device
*
- * @session_handle: session handle for the command
- * @dev_handle: device handle for the command
- * @offset: offset byte in the packet handle.
- * @packet_handle: packet memory handle for the actual packet:
- * struct cam_packet.
+ * @session_handle: Session handle for the command
+ * @dev_handle: Device handle for the command
+ * @offset: Offset byte in the packet handle.
+ * @packet_handle: Packet memory handle for the actual packet:
+ * struct cam_packet.
*
*/
struct cam_config_dev_cmd {
@@ -356,11 +388,11 @@
/* Query Device Caps */
/**
- * struct cam_query_cap_cmd - payload for query device capability
+ * struct cam_query_cap_cmd - Payload for query device capability
*
- * @size: handle size
- * @handle_type: user pointer or shared memory handle
- * @caps_handle: device specific query command payload
+ * @size: Handle size
+ * @handle_type: User pointer or shared memory handle
+ * @caps_handle: Device specific query command payload
*
*/
struct cam_query_cap_cmd {
@@ -371,16 +403,16 @@
/* Acquire Device */
/**
- * struct cam_acquire_dev_cmd - control payload for acquire devices
+ * struct cam_acquire_dev_cmd - Control payload for acquire devices
*
- * @session_handle: session handle for the acquire command
- * @dev_handle: device handle to be returned
- * @handle_type: resource handle type:
- * 1 = user poniter, 2 = mem handle
- * @num_resources: number of the resources to be acquired
- * @resources_hdl: resource handle that refers to the actual
- * resource array. Each item in this
- * array is device specific resource structure
+ * @session_handle: Session handle for the acquire command
+ * @dev_handle: Device handle to be returned
+ * @handle_type: Resource handle type:
+ * 1 = user pointer, 2 = mem handle
+ * @num_resources: Number of the resources to be acquired
+ * @resources_hdl: Resource handle that refers to the actual
+ * resource array. Each item in this
+ * array is device specific resource structure
*
*/
struct cam_acquire_dev_cmd {
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index fea6a70..68db5e1 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -21,6 +21,7 @@
#define CAM_CSIPHY_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 8)
#define CAM_ACTUATOR_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 9)
#define CAM_CCI_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 10)
+#define CAM_FLASH_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 11)
/* cam_req_mgr hdl info */
#define CAM_REQ_MGR_HDL_IDX_POS 8
diff --git a/include/uapi/scsi/scsi_ioctl.h b/include/uapi/scsi/scsi_ioctl.h
index 516c581a..d9ce5cc 100644
--- a/include/uapi/scsi/scsi_ioctl.h
+++ b/include/uapi/scsi/scsi_ioctl.h
@@ -17,9 +17,25 @@
#define SCSI_REMOVAL_PREVENT 1
#define SCSI_REMOVAL_ALLOW 0
-#ifdef __KERNEL__
+/*
+ * Here are some scsi specific ioctl commands which are sometimes useful.
+ *
+ * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
+ */
-struct scsi_device;
+/* Used to obtain PUN and LUN info. Conflicts with CDROMAUDIOBUFSIZ */
+#define SCSI_IOCTL_GET_IDLUN 0x5382
+
+/* 0x5383 and 0x5384 were used for SCSI_IOCTL_TAGGED_{ENABLE,DISABLE} */
+
+/* Used to obtain the host number of a device. */
+#define SCSI_IOCTL_PROBE_HOST 0x5385
+
+/* Used to obtain the bus number for a device */
+#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386
+
+/* Used to obtain the PCI location of a device */
+#define SCSI_IOCTL_GET_PCI 0x5387
/*
* Structures used for scsi_ioctl et al.
@@ -42,9 +58,11 @@
unsigned char host_wwn[8]; // include NULL term.
} Scsi_FCTargAddress;
+#ifdef __KERNEL__
+struct scsi_device;
+
int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
int cmd, bool ndelay);
extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-
#endif /* __KERNEL__ */
#endif /* _SCSI_IOCTL_H */
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index eadd942..9d1ed58 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2941,11 +2941,12 @@
tsk = tsk->group_leader;
/*
- * Workqueue threads may acquire PF_NO_SETAFFINITY and become
- * trapped in a cpuset, or RT worker may be born in a cgroup
- * with no rt_runtime allocated. Just say no.
+ * kthreads may acquire PF_NO_SETAFFINITY during initialization.
+ * If userland migrates such a kthread to a non-root cgroup, it can
+ * become trapped in a cpuset, or RT kthread may be born in a
+ * cgroup with no rt_runtime allocated. Just say no.
*/
- if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
+ if (tsk->no_cgroup_migration || (tsk->flags & PF_NO_SETAFFINITY)) {
ret = -EINVAL;
goto out_unlock_rcu;
}
diff --git a/kernel/kthread.c b/kernel/kthread.c
index be2cc1f..c2c911a 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -18,6 +18,7 @@
#include <linux/freezer.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
+#include <linux/cgroup.h>
#include <trace/events/sched.h>
static DEFINE_SPINLOCK(kthread_create_lock);
@@ -205,6 +206,7 @@
ret = -EINTR;
if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) {
+ cgroup_kthread_ready();
__kthread_parkme(&self);
ret = threadfn(data);
}
@@ -530,6 +532,7 @@
set_mems_allowed(node_states[N_MEMORY]);
current->flags |= PF_NOFREEZE;
+ cgroup_init_kthreadd();
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
index b0656b7..05dd2cb 100644
--- a/kernel/sched/energy.c
+++ b/kernel/sched/energy.c
@@ -56,6 +56,9 @@
int sd_level, i, nstates, cpu;
const __be32 *val;
+ if (!sched_is_energy_aware())
+ return;
+
for_each_possible_cpu(cpu) {
cn = of_get_cpu_node(cpu, NULL);
if (!cn) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 2a8643c..6fb615e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -5343,6 +5343,15 @@
return sched_feat(ENERGY_AWARE);
}
+/*
+ * Externally visible function. Let's keep the one above
+ * so that the check is inlined/optimized in the sched paths.
+ */
+bool sched_is_energy_aware(void)
+{
+ return energy_aware();
+}
+
struct energy_env {
struct sched_group *sg_top;
struct sched_group *sg_cap;
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 4223c4a..b1c7852 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -49,6 +49,7 @@
#include <linux/sched/deadline.h>
#include <linux/timer.h>
#include <linux/freezer.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -1616,20 +1617,41 @@
}
#ifdef CONFIG_HOTPLUG_CPU
-static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
- struct hrtimer_clock_base *new_base,
+static void migrate_hrtimer_list(struct hrtimer_cpu_base *old_base,
+ struct hrtimer_cpu_base *new_base,
+ unsigned int i, bool wait,
bool remove_pinned)
{
struct hrtimer *timer;
struct timerqueue_node *node;
struct timerqueue_head pinned;
int is_pinned;
+ struct hrtimer_clock_base *old_c_base = &old_base->clock_base[i];
+ struct hrtimer_clock_base *new_c_base = &new_base->clock_base[i];
timerqueue_init_head(&pinned);
- while ((node = timerqueue_getnext(&old_base->active))) {
+ while ((node = timerqueue_getnext(&old_c_base->active))) {
timer = container_of(node, struct hrtimer, node);
- BUG_ON(hrtimer_callback_running(timer));
+ if (wait) {
+ /* Ensure timers are done running before continuing */
+ while (hrtimer_callback_running(timer)) {
+ raw_spin_unlock(&old_base->lock);
+ raw_spin_unlock(&new_base->lock);
+ cpu_relax();
+ /*
+ * cpu_relax may just be a barrier. Grant the
+ * run_hrtimer_list code some time to obtain
+ * the spinlock.
+ */
+ udelay(1);
+ raw_spin_lock(&new_base->lock);
+ raw_spin_lock_nested(&old_base->lock,
+ SINGLE_DEPTH_NESTING);
+ }
+ } else {
+ BUG_ON(hrtimer_callback_running(timer));
+ }
debug_deactivate(timer);
/*
@@ -1637,7 +1659,7 @@
* timer could be seen as !active and just vanish away
* under us on another CPU
*/
- __remove_hrtimer(timer, old_base, HRTIMER_STATE_ENQUEUED, 0);
+ __remove_hrtimer(timer, old_c_base, HRTIMER_STATE_ENQUEUED, 0);
is_pinned = timer->state & HRTIMER_STATE_PINNED;
if (!remove_pinned && is_pinned) {
@@ -1645,7 +1667,7 @@
continue;
}
- timer->base = new_base;
+ timer->base = new_c_base;
/*
* Enqueue the timers on the new cpu. This does not
* reprogram the event device in case the timer
@@ -1654,7 +1676,7 @@
* sort out already expired timers and reprogram the
* event device.
*/
- enqueue_hrtimer(timer, new_base);
+ enqueue_hrtimer(timer, new_c_base);
}
/* Re-queue pinned timers for non-hotplug usecase */
@@ -1662,11 +1684,12 @@
timer = container_of(node, struct hrtimer, node);
timerqueue_del(&pinned, &timer->node);
- enqueue_hrtimer(timer, old_base);
+ enqueue_hrtimer(timer, old_c_base);
}
}
-static void __migrate_hrtimers(unsigned int scpu, bool remove_pinned)
+static void
+__migrate_hrtimers(unsigned int scpu, bool wait, bool remove_pinned)
{
struct hrtimer_cpu_base *old_base, *new_base;
unsigned long flags;
@@ -1683,8 +1706,8 @@
raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
- migrate_hrtimer_list(&old_base->clock_base[i],
- &new_base->clock_base[i], remove_pinned);
+ migrate_hrtimer_list(old_base, new_base, i, wait,
+ remove_pinned);
}
raw_spin_unlock(&old_base->lock);
@@ -1700,13 +1723,13 @@
BUG_ON(cpu_online(scpu));
tick_cancel_sched_timer(scpu);
- __migrate_hrtimers(scpu, true);
+ __migrate_hrtimers(scpu, false, true);
return 0;
}
void hrtimer_quiesce_cpu(void *cpup)
{
- __migrate_hrtimers(*(int *)cpup, false);
+ __migrate_hrtimers(*(int *)cpup, true, false);
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 470d966..5463c3b 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1856,7 +1856,8 @@
spin_lock_irqsave(&new_base->lock, flags);
spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
- BUG_ON(old_base->running_timer);
+ if (!cpu_online(cpu))
+ BUG_ON(old_base->running_timer);
for (i = 0; i < WHEEL_SIZE; i++)
migrate_timer_list(new_base, old_base->vectors + i,
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index da87b3c..221eb59 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3736,23 +3736,24 @@
ftrace_probe_registered = 1;
}
-static void __disable_ftrace_function_probe(void)
+static bool __disable_ftrace_function_probe(void)
{
int i;
if (!ftrace_probe_registered)
- return;
+ return false;
for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) {
struct hlist_head *hhd = &ftrace_func_hash[i];
if (hhd->first)
- return;
+ return false;
}
/* no more funcs left */
ftrace_shutdown(&trace_probe_ops, 0);
ftrace_probe_registered = 0;
+ return true;
}
@@ -3882,6 +3883,7 @@
__unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
void *data, int flags)
{
+ struct ftrace_ops_hash old_hash_ops;
struct ftrace_func_entry *rec_entry;
struct ftrace_func_probe *entry;
struct ftrace_func_probe *p;
@@ -3893,6 +3895,7 @@
struct hlist_node *tmp;
char str[KSYM_SYMBOL_LEN];
int i, ret;
+ bool disabled;
if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
func_g.search = NULL;
@@ -3911,6 +3914,10 @@
mutex_lock(&trace_probe_ops.func_hash->regex_lock);
+ old_hash_ops.filter_hash = old_hash;
+ /* Probes only have filters */
+ old_hash_ops.notrace_hash = NULL;
+
hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash);
if (!hash)
/* Hmm, should report this somehow */
@@ -3948,12 +3955,17 @@
}
}
mutex_lock(&ftrace_lock);
- __disable_ftrace_function_probe();
+ disabled = __disable_ftrace_function_probe();
/*
* Remove after the disable is called. Otherwise, if the last
* probe is removed, a null hash means *all enabled*.
*/
ret = ftrace_hash_move(&trace_probe_ops, 1, orig_hash, hash);
+
+ /* still need to update the function call sites */
+ if (ftrace_enabled && !disabled)
+ ftrace_run_modify_code(&trace_probe_ops, FTRACE_UPDATE_CALLS,
+ &old_hash_ops);
synchronize_sched();
if (!ret)
free_ftrace_hash_rcu(old_hash);
@@ -5389,6 +5401,15 @@
trace_free_pid_list(pid_list);
}
+void ftrace_clear_pids(struct trace_array *tr)
+{
+ mutex_lock(&ftrace_lock);
+
+ clear_ftrace_pids(tr);
+
+ mutex_unlock(&ftrace_lock);
+}
+
static void ftrace_pid_reset(struct trace_array *tr)
{
mutex_lock(&ftrace_lock);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index b0c47c2..63c6d28 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7245,6 +7245,7 @@
tracing_set_nop(tr);
event_trace_del_tracer(tr);
+ ftrace_clear_pids(tr);
ftrace_destroy_function_files(tr);
tracefs_remove_recursive(tr->dir);
free_trace_buffers(tr);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 38dbb36..e5d06c9 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -871,6 +871,7 @@
void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer);
void ftrace_init_tracefs_toplevel(struct trace_array *tr,
struct dentry *d_tracer);
+void ftrace_clear_pids(struct trace_array *tr);
#else
static inline int ftrace_trace_task(struct trace_array *tr)
{
@@ -889,6 +890,7 @@
static inline void ftrace_reset_array_ops(struct trace_array *tr) { }
static inline void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d) { }
static inline void ftrace_init_tracefs_toplevel(struct trace_array *tr, struct dentry *d) { }
+static inline void ftrace_clear_pids(struct trace_array *tr) { }
/* ftace_func_t type is not defined, use macro instead of static inline */
#define ftrace_init_array_ops(tr, func) do { } while (0)
#endif /* CONFIG_FUNCTION_TRACER */
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index efb0b4d..a75ea63 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -734,6 +734,68 @@
}
EXPORT_SYMBOL(iov_iter_advance);
+void iov_iter_revert(struct iov_iter *i, size_t unroll)
+{
+ if (!unroll)
+ return;
+ i->count += unroll;
+ if (unlikely(i->type & ITER_PIPE)) {
+ struct pipe_inode_info *pipe = i->pipe;
+ int idx = i->idx;
+ size_t off = i->iov_offset;
+ while (1) {
+ size_t n = off - pipe->bufs[idx].offset;
+ if (unroll < n) {
+ off -= (n - unroll);
+ break;
+ }
+ unroll -= n;
+ if (!unroll && idx == i->start_idx) {
+ off = 0;
+ break;
+ }
+ if (!idx--)
+ idx = pipe->buffers - 1;
+ off = pipe->bufs[idx].offset + pipe->bufs[idx].len;
+ }
+ i->iov_offset = off;
+ i->idx = idx;
+ pipe_truncate(i);
+ return;
+ }
+ if (unroll <= i->iov_offset) {
+ i->iov_offset -= unroll;
+ return;
+ }
+ unroll -= i->iov_offset;
+ if (i->type & ITER_BVEC) {
+ const struct bio_vec *bvec = i->bvec;
+ while (1) {
+ size_t n = (--bvec)->bv_len;
+ i->nr_segs++;
+ if (unroll <= n) {
+ i->bvec = bvec;
+ i->iov_offset = n - unroll;
+ return;
+ }
+ unroll -= n;
+ }
+ } else { /* same logics for iovec and kvec */
+ const struct iovec *iov = i->iov;
+ while (1) {
+ size_t n = (--iov)->iov_len;
+ i->nr_segs++;
+ if (unroll <= n) {
+ i->iov = iov;
+ i->iov_offset = n - unroll;
+ return;
+ }
+ unroll -= n;
+ }
+ }
+}
+EXPORT_SYMBOL(iov_iter_revert);
+
/*
* Return the count of just the current iov_iter segment.
*/
@@ -787,6 +849,7 @@
i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
i->iov_offset = 0;
i->count = count;
+ i->start_idx = i->idx;
}
EXPORT_SYMBOL(iov_iter_pipe);
diff --git a/mm/Kconfig b/mm/Kconfig
index 0183305..eb10c90 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -720,3 +720,13 @@
bool
config ARCH_HAS_PKEYS
bool
+
+config FORCE_ALLOC_FROM_DMA_ZONE
+ bool "Force certain memory allocators to always return ZONE_DMA memory"
+ depends on ZONE_DMA
+ help
+ Ensure certain memory allocators always return memory from ZONE_DMA.
+ This option helps ensure that clients who require ZONE_DMA memory are
+ always using ZONE_DMA memory.
+
+ If unsure, say "n".
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 917555c..d5b2b75 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1380,8 +1380,7 @@
deactivate_page(page);
if (pmd_young(orig_pmd) || pmd_dirty(orig_pmd)) {
- orig_pmd = pmdp_huge_get_and_clear_full(tlb->mm, addr, pmd,
- tlb->fullmm);
+ pmdp_invalidate(vma, addr, pmd);
orig_pmd = pmd_mkold(orig_pmd);
orig_pmd = pmd_mkclean(orig_pmd);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e866ddcc..fdc790a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2152,6 +2152,8 @@
struct work_struct work;
};
+static struct workqueue_struct *memcg_kmem_cache_create_wq;
+
static void memcg_kmem_cache_create_func(struct work_struct *w)
{
struct memcg_kmem_cache_create_work *cw =
@@ -2183,7 +2185,7 @@
cw->cachep = cachep;
INIT_WORK(&cw->work, memcg_kmem_cache_create_func);
- schedule_work(&cw->work);
+ queue_work(memcg_kmem_cache_create_wq, &cw->work);
}
static void memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
@@ -5796,6 +5798,17 @@
{
int cpu, node;
+#ifndef CONFIG_SLOB
+ /*
+ * Kmem cache creation is mostly done with the slab_mutex held,
+ * so use a special workqueue to avoid stalling all worker
+ * threads in case lots of cgroups are created simultaneously.
+ */
+ memcg_kmem_cache_create_wq =
+ alloc_ordered_workqueue("memcg_kmem_cache_create", 0);
+ BUG_ON(!memcg_kmem_cache_create_wq);
+#endif
+
hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
for_each_possible_cpu(cpu)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9d3f6d3..b4d398b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2595,16 +2595,23 @@
sc->nr_scanned - nr_scanned,
node_lru_pages);
+ /*
+ * Record the subtree's reclaim efficiency. The reclaimed
+ * pages from slab is excluded here because the corresponding
+ * scanned pages is not accounted. Moreover, freeing a page
+ * by slab shrinking depends on each slab's object population,
+ * making the cost model (i.e. scan:free) different from that
+ * of LRU.
+ */
+ vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true,
+ sc->nr_scanned - nr_scanned,
+ sc->nr_reclaimed - nr_reclaimed);
+
if (reclaim_state) {
sc->nr_reclaimed += reclaim_state->reclaimed_slab;
reclaim_state->reclaimed_slab = 0;
}
- /* Record the subtree's reclaim efficiency */
- vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true,
- sc->nr_scanned - nr_scanned,
- sc->nr_reclaimed - nr_reclaimed);
-
if (sc->nr_reclaimed - nr_reclaimed)
reclaimable = true;
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index b0bc023..1689bb5 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -280,7 +280,7 @@
struct zspage {
struct {
unsigned int fullness:FULLNESS_BITS;
- unsigned int class:CLASS_BITS;
+ unsigned int class:CLASS_BITS + 1;
unsigned int isolated:ISOLATED_BITS;
unsigned int magic:MAGIC_VAL_BITS;
};
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b7de71f..963732e 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -378,7 +378,7 @@
struct iov_iter *to, int len)
{
int start = skb_headlen(skb);
- int i, copy = start - offset;
+ int i, copy = start - offset, start_off = offset, n;
struct sk_buff *frag_iter;
trace_skb_copy_datagram_iovec(skb, len);
@@ -387,11 +387,12 @@
if (copy > 0) {
if (copy > len)
copy = len;
- if (copy_to_iter(skb->data + offset, copy, to) != copy)
+ n = copy_to_iter(skb->data + offset, copy, to);
+ offset += n;
+ if (n != copy)
goto short_copy;
if ((len -= copy) == 0)
return 0;
- offset += copy;
}
/* Copy paged appendix. Hmm... why does this look so complicated? */
@@ -405,13 +406,14 @@
if ((copy = end - offset) > 0) {
if (copy > len)
copy = len;
- if (copy_page_to_iter(skb_frag_page(frag),
+ n = copy_page_to_iter(skb_frag_page(frag),
frag->page_offset + offset -
- start, copy, to) != copy)
+ start, copy, to);
+ offset += n;
+ if (n != copy)
goto short_copy;
if (!(len -= copy))
return 0;
- offset += copy;
}
start = end;
}
@@ -443,6 +445,7 @@
*/
fault:
+ iov_iter_revert(to, offset - start_off);
return -EFAULT;
short_copy:
@@ -593,7 +596,7 @@
__wsum *csump)
{
int start = skb_headlen(skb);
- int i, copy = start - offset;
+ int i, copy = start - offset, start_off = offset;
struct sk_buff *frag_iter;
int pos = 0;
int n;
@@ -603,11 +606,11 @@
if (copy > len)
copy = len;
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
+ offset += n;
if (n != copy)
goto fault;
if ((len -= copy) == 0)
return 0;
- offset += copy;
pos = copy;
}
@@ -629,12 +632,12 @@
offset - start, copy,
&csum2, to);
kunmap(page);
+ offset += n;
if (n != copy)
goto fault;
*csump = csum_block_add(*csump, csum2, pos);
if (!(len -= copy))
return 0;
- offset += copy;
pos += copy;
}
start = end;
@@ -667,6 +670,7 @@
return 0;
fault:
+ iov_iter_revert(to, offset - start_off);
return -EFAULT;
}
@@ -751,6 +755,7 @@
}
return 0;
csum_error:
+ iov_iter_revert(&msg->msg_iter, chunk);
return -EINVAL;
fault:
return -EFAULT;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f0f462c..8de6707 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -209,6 +209,9 @@
u8 *data;
bool pfmemalloc;
+ if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE))
+ gfp_mask |= GFP_DMA;
+
cache = (flags & SKB_ALLOC_FCLONE)
? skbuff_fclone_cache : skbuff_head_cache;
@@ -367,6 +370,9 @@
unsigned long flags;
void *data;
+ if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE))
+ gfp_mask |= GFP_DMA;
+
local_irq_save(flags);
nc = this_cpu_ptr(&netdev_alloc_cache);
data = __alloc_page_frag(nc, fragsz, gfp_mask);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 873df83..e6acef5 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -798,6 +798,7 @@
struct rtable *rt;
struct flowi4 fl4;
const struct iphdr *iph = (const struct iphdr *) skb->data;
+ struct net *net = dev_net(skb->dev);
int oif = skb->dev->ifindex;
u8 tos = RT_TOS(iph->tos);
u8 prot = iph->protocol;
@@ -805,7 +806,7 @@
rt = (struct rtable *) dst;
- __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
+ __build_flow_key(net, &fl4, sk, iph, oif, tos, prot, mark, 0);
__ip_do_redirect(rt, skb, &fl4, true);
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0cfb91f..7588fa9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -5978,13 +5978,6 @@
.mode = 0644,
.proc_handler = proc_dointvec,
},
- {
- .procname = "accept_ra_rt_table",
- .data = &ipv6_devconf.accept_ra_rt_table,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
{
.procname = "optimistic_dad",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 477600f..73527d8 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2165,6 +2165,8 @@
continue;
if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
continue;
+ if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol)
+ continue;
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f2b04a7..8ab0974 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4235,8 +4235,8 @@
if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
goto out;
if (po->tp_version >= TPACKET_V3 &&
- (int)(req->tp_block_size -
- BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
+ req->tp_block_size <=
+ BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
goto out;
if (unlikely(req->tp_frame_size < po->tp_hdrlen +
po->tp_reserve))
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6cbe5bd..6734420 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4735,6 +4735,12 @@
if (!asoc)
return -EINVAL;
+ /* If there is a thread waiting on more sndbuf space for
+ * sending on this asoc, it cannot be peeled.
+ */
+ if (waitqueue_active(&asoc->wait))
+ return -EBUSY;
+
/* An association cannot be branched off from an already peeled-off
* socket, nor is this supported for tcp style sockets.
*/
@@ -7427,8 +7433,6 @@
*/
release_sock(sk);
current_timeo = schedule_timeout(current_timeo);
- if (sk != asoc->base.sk)
- goto do_error;
lock_sock(sk);
*timeo_p = current_timeo;
diff --git a/net/socket.c b/net/socket.c
index c518841..a4fb472 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -535,7 +535,7 @@
return used;
}
-int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
{
int err = simple_setattr(dentry, iattr);
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index a2fc3a0..449e4a3 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -1,17 +1,1491 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead. It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using. Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
+# This is the world regulatory domain
+country 00:
+ (2402 - 2472 @ 40), (20)
+ # Channel 12 - 13.
+ (2457 - 2482 @ 40), (20), PASSIVE-SCAN, NO-IBSS
+ # Channel 14. Only JP enables this and for 802.11b only
+ (2474 - 2494 @ 20), (20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
+ # Channel 36 - 48
+ (5170 - 5250 @ 80), (20), PASSIVE-SCAN, NO-IBSS
+ (5250 - 5330 @ 80), (20), PASSIVE-SCAN, NO-IBSS
+ (5490 - 5710 @ 80), (20), PASSIVE-SCAN, NO-IBSS
+ # NB: 5260 MHz - 5700 MHz requies DFS
+ # Channel 149 - 165
+ (5735 - 5835 @ 80), (20), PASSIVE-SCAN, NO-IBSS
+ # IEEE 802.11ad (60GHz), channels 1..3
+ (57240 - 63720 @ 2160), (0)
+
+
+country AE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country AI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country AL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5150 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5350 @ 80), (23), DFS, AUTO-BW
+ (5470 - 5710 @ 160), (30), DFS
+
+country AM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (18)
+ (5250 - 5330 @ 20), (18), DFS
+
+country AN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country AR:
+ (2402 - 2482 @ 40), (36)
+ (5170 - 5330 @ 160), (23)
+ (5490 - 5590 @ 80), (36)
+ (5650 - 5730 @ 80), (36)
+ (5735 - 5835 @ 80), (36)
+
+country AS: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5850 @ 80), (30)
+
+country AT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country AU: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5590 @ 80), (24), DFS
+ (5650 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country AW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country AZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18), AUTO-BW
+ (5250 - 5330 @ 80), (18), DFS, AUTO-BW
+
+country BA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country BB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country BD:
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country BE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country BF: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country BH:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 20), (23)
+ (5735 - 5835 @ 20), (33)
+
+country BL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country BM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country BO: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5250 - 5330 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BR: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BS: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country BT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country BY: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country BZ:
+ (2402 - 2482 @ 40), (36)
+ (5170 - 5330 @ 160), (27)
+ (5490 - 5730 @ 160), (36)
+ (5735 - 5835 @ 80), (36)
+
+country CA: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5590 @ 80), (24), DFS
+ (5650 - 5730 @ 80), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CF: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (24)
+ (5250 - 5330 @ 40), (24), DFS
+ (5490 - 5730 @ 40), (24), DFS
+ (5735 - 5835 @ 40), (30)
+
+country CH: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+
+country CI: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CL:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (20)
+ (5735 - 5835 @ 80), (20)
+
+country CN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (33)
+ # 60 gHz band channels 1,4: 28dBm, channels 2,3: 44dBm
+ # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf
+ (57240 - 59400 @ 2160), (28)
+ (59400 - 63720 @ 2160), (44)
+ (63720 - 65880 @ 2160), (28)
+
+country CO: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CR: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (24)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country CX: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country CY: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
+# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
+country CZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
+# For the 5GHz range also see
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
+
+country DE: DFS-ETSI
+ # entries 279004 and 280006
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country DK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country DM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country DO: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country DZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5670 @ 160), (23), DFS
+
+country EC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (24)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country EE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country EG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (23)
+ (5250 - 5330 @ 40), (23), DFS
+
+country ES: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country ET: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country FI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country FM: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country FR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country GB: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country GD: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (18), AUTO-BW
+ (5250 - 5330 @ 80), (18), DFS, AUTO-BW
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country GF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country GH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country GP: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country GR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country GT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country GU: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country GY:
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5835 @ 80), (30)
+
+country HK: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HN:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (24)
+ (5490 - 5730 @ 160), (24)
+ (5735 - 5835 @ 80), (30)
+
+country HR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country HT: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country HU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country ID:
+ # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5815 @ 20), (30)
+
+country IE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country IL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+
+country IN:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (23)
+ (5735 - 5835 @ 80), (30)
+
+country IR:
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country IS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country IT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country JM: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country JO:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5735 - 5835 @ 80), (23)
+
+country JP: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (2474 - 2494 @ 20), (20), NO-OFDM
+ (5170 - 5250 @ 80), (20), AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR
+ (5490 - 5710 @ 160), (20), DFS
+ # 60 GHz band channels 2-4 at 10mW,
+ # ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf
+ (59000 - 66000 @ 2160), (10 mW)
+
+country KE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23)
+ (5490 - 5570 @ 80), (30), DFS
+ (5735 - 5775 @ 40), (23)
+
+country KH: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country KN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country KR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (30)
+ # 60 GHz band channels 1-4,
+ # ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99
+ (57000 - 66000 @ 2160), (43)
+
+country KP: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20)
+ (5250 - 5330 @ 80), (20), DFS
+ (5490 - 5630 @ 80), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country KW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+
+country KY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country KZ:
+ (2402 - 2482 @ 40), (20)
+
+country LB: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country LC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (30), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5815 @ 80), (30)
+
+country LI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+
+country LK: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (24)
+ (5250 - 5330 @ 20), (24), DFS
+ (5490 - 5730 @ 20), (24), DFS
+ (5735 - 5835 @ 20), (30)
+
+country LS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country LT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country LU: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country LV: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country MA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+
+country MC: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MD: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country ME: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MH: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country MN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MO: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MP: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MQ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country MU: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MV: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (20)
+
+country MW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country MX: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country MY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5650 @ 160), (24), DFS
+ (5735 - 5815 @ 80), (24)
+
+country NA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ (5735 - 5835 @ 80), (33)
+
+country NG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5250 - 5330 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
+
+country NI: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country NL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country NO: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country NP:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (20)
+ (5735 - 5835 @ 80), (20)
+
+country NZ: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country OM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country PA:
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (23), AUT0-BW
+ (5250 - 5330 @ 80), (30), AUTO-BW
+ (5735 - 5835 @ 80), (36)
+
+country PE: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country PG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PK:
+ (2402 - 2482 @ 40), (30)
+ (5735 - 5835 @ 80), (30)
+
+country PL: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country PM: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country PR: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+# Public Safety FCCA, FCC4
+# 27dBm [4.9GHz 1/4 rate], 30dBm [1/2 rate], 33dBm [full rate], and 5GHz same as FCC1
+# db.txt cannot express the limitation on 5G so disable all 5G channels for FCC4
+country PS: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (4940 - 4990 @ 40), (33)
+
+country PT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country PW: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country PY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country QA:
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+country RE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country RO: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+# Source:
+# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
+country RS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country RU:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (23)
+ (5490 - 5730 @ 160), (30)
+ (5735 - 5835 @ 80), (30)
+
+country RW: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country SE: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country SG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country SI: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country SK: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 5.9ghz band
+ # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country SN:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (24)
+ (5490 - 5730 @ 160), (24)
+ (5735 - 5835 @ 80), (30)
+
+country SR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country SV: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 20), (23)
+ (5250 - 5330 @ 20), (23), DFS
+ (5735 - 5835 @ 20), (30)
+
+country SY:
+ (2402 - 2482 @ 40), (20)
+
+country TC: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TD: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country TG: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (23)
+ (5250 - 5330 @ 40), (23), DFS
+ (5490 - 5710 @ 40), (30), DFS
+
+country TH: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TN: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+
+country TR: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country TT:
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5330 @ 160), (27)
+ (5490 - 5730 @ 160), (36)
+ (5735 - 5835 @ 80), (36)
+
+country TW: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country TZ:
+ (2402 - 2482 @ 40), (20)
+ (5735 - 5835 @ 80), (30)
+
+# Source:
+# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
+# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
+# (appendix 8)
+# Listed 5GHz range is a lowest common denominator for all related
+# rules in the referenced laws. Such a range is used because of
+# disputable definitions there.
+country UA: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (20), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5490 - 5670 @ 160), (20), DFS
+ (5735 - 5835 @ 80), (20)
+ # 60 gHz band channels 1-4, ref: Etsi En 302 567
+ (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+
+country UG: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country US: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+ # 5.9ghz band
+ # reference: https://apps.fcc.gov/edocs_public/attachmatch/FCC-03-324A1.pdf
+ (5842 - 5863 @ 5), (30)
+ (5850 - 5870 @ 10), (30)
+ (5860 - 5880 @ 10), (30)
+ (5865 - 5885 @ 20), (30)
+ (5870 - 5890 @ 10), (30)
+ (5880 - 5900 @ 10), (30)
+ (5890 - 5910 @ 10), (30)
+ (5895 - 5915 @ 20), (30)
+ (5900 - 5920 @ 10), (30)
+ (5910 - 5930 @ 10), (30)
+ # 60g band
+ # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
+ # channels 1,2,3, EIRP=40dBm(43dBm peak)
+ (57240 - 63720 @ 2160), (40)
+
+country UY: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country UZ: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+
+country VC: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country VE: DFS-FCC
+ (2402 - 2482 @ 40), (30)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5735 - 5835 @ 80), (30)
+
+country VI: DFS-FCC
+ (2402 - 2472 @ 40), (30)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country VN: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country VU: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country WF: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country WS: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (23)
+ (5250 - 5330 @ 40), (23), DFS
+ (5490 - 5710 @ 40), (30), DFS
+
+country XA: DFS-JP
+ (2402 - 2482 @ 40), (20)
+ (2474 - 2494 @ 20), (20), NO-OFDM
+ (5170 - 5250 @ 80), (20), NO-IR, AUTO-BW, NO-OUTDOOR
+ (5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR
+ (5490 - 5710 @ 160), (20), DFS
+ (59000 - 66000 @ 2160), (10 mW)
+
+country YE:
+ (2402 - 2482 @ 40), (20)
+
+country YT: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
+
+country ZA: DFS-FCC
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (24), AUTO-BW
+ (5250 - 5330 @ 80), (24), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (24), DFS
+ (5735 - 5835 @ 80), (30)
+
+country ZW: DFS-ETSI
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5710 @ 160), (30), DFS
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index fd5d1e0..e18fe9d 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -33,11 +33,9 @@
select SND_SOC_INTEL_SST_MATCH if ACPI
depends on (X86 || COMPILE_TEST)
-# firmware stuff depends DW_DMAC_CORE; since there is no depends-on from
-# the reverse selection, each machine driver needs to select
-# SND_SOC_INTEL_SST_FIRMWARE carefully depending on DW_DMAC_CORE
config SND_SOC_INTEL_SST_FIRMWARE
tristate
+ select DW_DMAC_CORE
config SND_SOC_INTEL_SST_ACPI
tristate
@@ -47,16 +45,18 @@
config SND_SOC_INTEL_HASWELL
tristate
+ select SND_SOC_INTEL_SST
select SND_SOC_INTEL_SST_FIRMWARE
config SND_SOC_INTEL_BAYTRAIL
tristate
+ select SND_SOC_INTEL_SST
+ select SND_SOC_INTEL_SST_FIRMWARE
config SND_SOC_INTEL_HASWELL_MACH
tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
- select SND_SOC_INTEL_SST
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5640
help
@@ -99,9 +99,8 @@
config SND_SOC_INTEL_BYT_RT5640_MACH
tristate "ASoC Audio driver for Intel Baytrail with RT5640 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
- select SND_SOC_INTEL_SST
- select SND_SOC_INTEL_SST_FIRMWARE
+ depends on DMADEVICES
+ depends on SND_SST_IPC_ACPI = n
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_RT5640
help
@@ -112,9 +111,8 @@
config SND_SOC_INTEL_BYT_MAX98090_MACH
tristate "ASoC Audio driver for Intel Baytrail with MAX98090 codec"
depends on X86_INTEL_LPSS && I2C
- depends on DW_DMAC_CORE && (SND_SST_IPC_ACPI = n)
- select SND_SOC_INTEL_SST
- select SND_SOC_INTEL_SST_FIRMWARE
+ depends on DMADEVICES
+ depends on SND_SST_IPC_ACPI = n
select SND_SOC_INTEL_BAYTRAIL
select SND_SOC_MAX98090
help
@@ -123,9 +121,8 @@
config SND_SOC_INTEL_BDW_RT5677_MACH
tristate "ASoC Audio driver for Intel Broadwell with RT5677 codec"
- depends on X86_INTEL_LPSS && GPIOLIB && I2C && DW_DMAC
- depends on DW_DMAC_CORE=y
- select SND_SOC_INTEL_SST
+ depends on X86_INTEL_LPSS && GPIOLIB && I2C
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT5677
help
@@ -134,10 +131,8 @@
config SND_SOC_INTEL_BROADWELL_MACH
tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
- depends on X86_INTEL_LPSS && I2C && DW_DMAC && \
- I2C_DESIGNWARE_PLATFORM
- depends on DW_DMAC_CORE
- select SND_SOC_INTEL_SST
+ depends on X86_INTEL_LPSS && I2C && I2C_DESIGNWARE_PLATFORM
+ depends on DMADEVICES
select SND_SOC_INTEL_HASWELL
select SND_SOC_RT286
help
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 51c27b7..b75ba98 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -5247,7 +5247,6 @@
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
.dpcm_playback = 1,
- .dpcm_capture = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 826f566..654806e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -153,27 +153,27 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct msm_voice *voice;
- if (!strcmp("VoLTE", substream->pcm->id)) {
+ if (!strncmp("VoLTE", substream->pcm->id, 5)) {
voice = &voice_info[VOLTE_SESSION_INDEX];
pr_debug("%s: Open VoLTE Substream Id=%s\n",
__func__, substream->pcm->id);
- } else if (!strcmp("Voice2", substream->pcm->id)) {
+ } else if (!strncmp("Voice2", substream->pcm->id, 6)) {
voice = &voice_info[VOICE2_SESSION_INDEX];
pr_debug("%s: Open Voice2 Substream Id=%s\n",
__func__, substream->pcm->id);
- } else if (!strcmp("QCHAT", substream->pcm->id)) {
+ } else if (!strncmp("QCHAT", substream->pcm->id, 5)) {
voice = &voice_info[QCHAT_SESSION_INDEX];
pr_debug("%s: Open QCHAT Substream Id=%s\n",
__func__, substream->pcm->id);
- } else if (!strcmp("VoWLAN", substream->pcm->id)) {
+ } else if (!strncmp("VoWLAN", substream->pcm->id, 6)) {
voice = &voice_info[VOWLAN_SESSION_INDEX];
pr_debug("%s: Open VoWLAN Substream Id=%s\n",
__func__, substream->pcm->id);
- } else if (!strcmp("VoiceMMode1", substream->pcm->id)) {
+ } else if (!strncmp("VoiceMMode1", substream->pcm->id, 11)) {
voice = &voice_info[VOICEMMODE1_INDEX];
pr_debug("%s: Open VoiceMMode1 Substream Id=%s\n",
__func__, substream->pcm->id);
- } else if (!strcmp("VoiceMMode2", substream->pcm->id)) {
+ } else if (!strncmp("VoiceMMode2", substream->pcm->id, 11)) {
voice = &voice_info[VOICEMMODE2_INDEX];
pr_debug("%s: Open VoiceMMode2 Substream Id=%s\n",
__func__, substream->pcm->id);
diff --git a/sound/soc/msm/sdm660-ext-dai-links.c b/sound/soc/msm/sdm660-ext-dai-links.c
index f64074d..1c03d8c 100644
--- a/sound/soc/msm/sdm660-ext-dai-links.c
+++ b/sound/soc/msm/sdm660-ext-dai-links.c
@@ -335,7 +335,6 @@
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
.dpcm_playback = 1,
- .dpcm_capture = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index 6987949..2b8c9c7 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -397,7 +397,8 @@
"KHZ_88P2", "KHZ_96", "KHZ_176P4",
"KHZ_192", "KHZ_352P8", "KHZ_384"};
static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96",
- "KHZ_192"};
+ "KHZ_192", "KHZ_32", "KHZ_44P1",
+ "KHZ_88P2", "KHZ_176P4" };
static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight"};
static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
@@ -508,6 +509,8 @@
.key_code[7] = 0,
.linein_th = 5000,
.moisture_en = true,
+ .anc_micbias = MIC_BIAS_2,
+ .enable_anc_mic_detect = false,
};
static struct snd_soc_dapm_route wcd_audio_paths[] = {
@@ -1464,6 +1467,22 @@
return idx;
switch (ext_disp_rx_cfg[idx].sample_rate) {
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 6;
+ break;
+
+ case SAMPLING_RATE_88P2KHZ:
+ sample_rate_val = 5;
+ break;
+
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 4;
+ break;
+
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 3;
+ break;
+
case SAMPLING_RATE_192KHZ:
sample_rate_val = 2;
break;
@@ -1494,6 +1513,18 @@
return idx;
switch (ucontrol->value.integer.value[0]) {
+ case 6:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 5:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_88P2KHZ;
+ break;
+ case 4:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 3:
+ ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_32KHZ;
+ break;
case 2:
ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ;
break;
@@ -4655,6 +4686,42 @@
},
};
+static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
+ {
+ .name = MSM_DAILINK_NAME(ASM Loopback),
+ .stream_name = "MultiMedia6",
+ .cpu_dai_name = "MultiMedia6",
+ .platform_name = "msm-pcm-loopback",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_pmdown_time = 1,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+ },
+ {
+ .name = "USB Audio Hostless",
+ .stream_name = "USB Audio Hostless",
+ .cpu_dai_name = "USBAUDIO_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+};
+
static struct snd_soc_dai_link msm_common_be_dai_links[] = {
/* Backend AFE DAI Links */
{
@@ -5373,6 +5440,7 @@
static struct snd_soc_dai_link msm_tavil_snd_card_dai_links[
ARRAY_SIZE(msm_common_dai_links) +
ARRAY_SIZE(msm_tavil_fe_dai_links) +
+ ARRAY_SIZE(msm_common_misc_fe_dai_links) +
ARRAY_SIZE(msm_common_be_dai_links) +
ARRAY_SIZE(msm_tavil_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links) +
@@ -5662,7 +5730,7 @@
{
struct snd_soc_card *card = NULL;
struct snd_soc_dai_link *dailink;
- int len_1, len_2, len_3;
+ int len_1, len_2, len_3, len_4;
int total_links;
const struct of_device_id *match;
@@ -5677,8 +5745,9 @@
card = &snd_soc_card_tavil_msm;
len_1 = ARRAY_SIZE(msm_common_dai_links);
len_2 = len_1 + ARRAY_SIZE(msm_tavil_fe_dai_links);
- len_3 = len_2 + ARRAY_SIZE(msm_common_be_dai_links);
- total_links = len_3 + ARRAY_SIZE(msm_tavil_be_dai_links);
+ len_3 = len_2 + ARRAY_SIZE(msm_common_misc_fe_dai_links);
+ len_4 = len_3 + ARRAY_SIZE(msm_common_be_dai_links);
+ total_links = len_4 + ARRAY_SIZE(msm_tavil_be_dai_links);
memcpy(msm_tavil_snd_card_dai_links,
msm_common_dai_links,
sizeof(msm_common_dai_links));
@@ -5686,9 +5755,12 @@
msm_tavil_fe_dai_links,
sizeof(msm_tavil_fe_dai_links));
memcpy(msm_tavil_snd_card_dai_links + len_2,
+ msm_common_misc_fe_dai_links,
+ sizeof(msm_common_misc_fe_dai_links));
+ memcpy(msm_tavil_snd_card_dai_links + len_3,
msm_common_be_dai_links,
sizeof(msm_common_be_dai_links));
- memcpy(msm_tavil_snd_card_dai_links + len_3,
+ memcpy(msm_tavil_snd_card_dai_links + len_4,
msm_tavil_be_dai_links,
sizeof(msm_tavil_be_dai_links));
@@ -6186,14 +6258,19 @@
pdev->dev.of_node->full_name);
dev_dbg(&pdev->dev, "Jack type properties set to default");
} else {
- if (!strcmp(mbhc_audio_jack_type, "4-pole-jack"))
+ if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
+ wcd_mbhc_cfg.enable_anc_mic_detect = false;
dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
- else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack"))
+ } else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack")) {
+ wcd_mbhc_cfg.enable_anc_mic_detect = true;
dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
- else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack"))
+ } else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack")) {
+ wcd_mbhc_cfg.enable_anc_mic_detect = true;
dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
- else
+ } else {
+ wcd_mbhc_cfg.enable_anc_mic_detect = false;
dev_dbg(&pdev->dev, "Unknown value, set to default");
+ }
}
/*
* Parse US-Euro gpio info from DT. Report no error if us-euro