summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/msm/msm_smp2p.txt4
-rw-r--r--Documentation/devicetree/bindings/arm/msm/sleepstate-smp2p.txt4
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-smp2p.txt2
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt2
-rw-r--r--Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt7
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi21
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi937
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi315
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi175
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msmhamster.dtsi16
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm64/configs/msm_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig3
-rw-r--r--arch/arm64/mm/dma-mapping.c2
-rw-r--r--drivers/base/regmap/regmap-swr.c23
-rw-r--r--drivers/clk/msm/clock-gpu-cobalt.c80
-rw-r--r--drivers/clk/msm/clock-mmss-cobalt.c73
-rw-r--r--drivers/clk/msm/reset.c6
-rw-r--r--drivers/firmware/qcom/tz_log.c117
-rw-r--r--drivers/gpio/gpio-msm-smp2p-test.c10
-rw-r--r--drivers/gpu/msm/a5xx_reg.h1
-rw-r--r--drivers/gpu/msm/adreno.c2
-rw-r--r--drivers/gpu/msm/adreno.h2
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c7
-rw-r--r--drivers/gpu/msm/adreno_ringbuffer.c17
-rw-r--r--drivers/gpu/msm/kgsl.c602
-rw-r--r--drivers/gpu/msm/kgsl.h37
-rw-r--r--drivers/gpu/msm/kgsl_compat.c12
-rw-r--r--drivers/gpu/msm/kgsl_debugfs.c81
-rw-r--r--drivers/gpu/msm/kgsl_ioctl.c12
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c165
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c93
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h6
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.h34
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c7
-rw-r--r--drivers/gpu/msm/kgsl_trace.h94
-rw-r--r--drivers/iommu/dma-mapping-fast.c29
-rw-r--r--drivers/iommu/msm_dma_iommu_mapping.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.h13
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c15
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp48.c13
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c3
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c14
-rw-r--r--drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c15
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c45
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c26
-rw-r--r--drivers/media/platform/msm/vidc/Kconfig2
-rw-r--r--drivers/media/platform/msm/vidc/Makefile32
-rw-r--r--drivers/media/platform/msm/vidc/governors/Kconfig2
-rw-r--r--drivers/media/platform/msm/vidc/governors/Makefile10
-rw-r--r--drivers/media/platform/msm/vidc/msm_v4l2_vidc.c2
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c2
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_debug.c4
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_res_parse.c7
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_resources.h1
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c31
-rw-r--r--drivers/media/platform/msm/vidc/vmem/Kconfig2
-rw-r--r--drivers/media/platform/msm/vidc/vmem/Makefile9
-rw-r--r--drivers/media/platform/msm/vidc/vmem/vmem.c40
-rw-r--r--drivers/media/platform/msm/vidc/vmem/vmem.h4
-rw-r--r--drivers/mfd/wcd9xxx-irq.c1
-rw-r--r--drivers/of/fdt.c14
-rw-r--r--drivers/regulator/cprh-kbss-regulator.c48
-rw-r--r--drivers/soc/qcom/icnss.c91
-rw-r--r--drivers/soc/qcom/service-locator.c4
-rw-r--r--drivers/soc/qcom/smp2p.c6
-rw-r--r--drivers/soc/qcom/smp2p_private_api.h4
-rw-r--r--drivers/soc/qcom/smp2p_sleepstate.c3
-rw-r--r--drivers/soc/qcom/smp2p_spinlock_test.c14
-rw-r--r--drivers/soundwire/swr-wcd-ctrl.c5
-rw-r--r--drivers/staging/android/ion/ion_page_pool.c60
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c123
-rw-r--r--drivers/staging/android/ion/ion_system_secure_heap.c3
-rw-r--r--drivers/staging/android/uapi/msm_ion.h3
-rw-r--r--drivers/tty/serial/amba-pl011.c1
-rw-r--r--drivers/tty/serial/arc_uart.c1
-rw-r--r--drivers/tty/serial/earlycon.c10
-rw-r--r--drivers/tty/serial/msm_serial.c300
-rw-r--r--drivers/tty/serial/msm_serial.h184
-rw-r--r--drivers/tty/serial/samsung.c6
-rw-r--r--drivers/tty/serial/sprd_serial.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c69
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c79
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c16
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c24
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/dt-bindings/clock/msm-clocks-cobalt.h4
-rw-r--r--include/dt-bindings/clock/msm-clocks-hwio-cobalt.h2
-rw-r--r--include/linux/serial_core.h22
-rw-r--r--include/soc/qcom/icnss.h3
-rw-r--r--include/soc/qcom/service-locator.h2
-rw-r--r--include/soc/qcom/service-notifier.h2
-rw-r--r--include/soc/qcom/smem.h11
-rw-r--r--include/uapi/linux/msm_kgsl.h99
-rw-r--r--include/uapi/media/msm_cam_sensor.h1
-rw-r--r--include/uapi/media/msmb_isp.h1
-rw-r--r--kernel/sched/fair.c3
-rw-r--r--sound/soc/codecs/wcd9330.c8
-rw-r--r--sound/soc/codecs/wcd9335.c8
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-routing.h5
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c263
-rw-r--r--sound/soc/msm/msm-audio-pinctrl.c26
-rw-r--r--sound/soc/msm/msmcobalt.c40
117 files changed, 4112 insertions, 837 deletions
diff --git a/Documentation/arm/msm/msm_smp2p.txt b/Documentation/arm/msm/msm_smp2p.txt
index 8332cae6be5d..34d22f0e4635 100644
--- a/Documentation/arm/msm/msm_smp2p.txt
+++ b/Documentation/arm/msm/msm_smp2p.txt
@@ -181,7 +181,7 @@ added to the end of the list (Table 3).
-------------------------------------------------
| Wireless processor | 4 |
-------------------------------------------------
- | Modem Fw | 5 |
+ | CDSP processor | 5 |
-------------------------------------------------
| Power processor | 6 |
-------------------------------------------------
@@ -206,6 +206,8 @@ Item ID will be 427 + 1 = 428.
---------------------------------------------------
| Description | SMEM ID value |
---------------------------------------------------
+ | CDSP SMEM Item base | 94 |
+ ---------------------------------------------------
| Apps SMP2P SMEM Item base | 427 |
---------------------------------------------------
| Modem SMP2P SMEM Item base | 435 |
diff --git a/Documentation/devicetree/bindings/arm/msm/sleepstate-smp2p.txt b/Documentation/devicetree/bindings/arm/msm/sleepstate-smp2p.txt
index ad1067232870..adfa94f9d1ff 100644
--- a/Documentation/devicetree/bindings/arm/msm/sleepstate-smp2p.txt
+++ b/Documentation/devicetree/bindings/arm/msm/sleepstate-smp2p.txt
@@ -1,7 +1,9 @@
Qualcomm Technologies, Inc. SMSM Point-to-Point (SMP2P) Sleepstate driver
Required properties:
--compatible : should be "qcom,smp2pgpio_sleepstate_3_out";
+-compatible : should be one of the following:
+- "qcom,smp2pgpio_sleepstate_3_out" - for sensor processor on remote pid 3
+- "qcom,smp2pgpio-sleepstate-out" - for other cases
-gpios : the relevant gpio pins of the entry.
Example:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-smp2p.txt b/Documentation/devicetree/bindings/gpio/gpio-smp2p.txt
index c0a51afe18f1..7f5f939afa2d 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-smp2p.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-smp2p.txt
@@ -31,6 +31,8 @@ Unit test devices ("smp2p" entries):
"qcom,smp2pgpio_test_smp2p_3_in"
"qcom,smp2pgpio_test_smp2p_4_out"
"qcom,smp2pgpio_test_smp2p_4_in"
+ "qcom,smp2pgpio_test_smp2p_5_out"
+ "qcom,smp2pgpio_test_smp2p_5_in"
"qcom,smp2pgpio_test_smp2p_7_out"
"qcom,smp2pgpio_test_smp2p_7_in"
"qcom,smp2pgpio_test_smp2p_15_out"
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 06b8c71effcc..92411011ed7a 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -152,6 +152,8 @@ GPU Quirks:
- qcom,gpu-quirk-fault-detect-mask:
Mask out RB1-3 activity signals from HW hang
detection logic
+- qcom,gpu-quirk-dp2clockgating-disable:
+ Disable RB sampler data path clock gating optimization
The following properties are optional as collecting data via coresight might
not be supported for every chipset. The documentation for coresight
diff --git a/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt b/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
index 833fb645b92a..b286b0838643 100644
--- a/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/cprh-kbss-regulator.txt
@@ -30,7 +30,12 @@ KBSS specific properties:
- compatible
Usage: required
Value type: <string>
- Definition: "qcom,cprh-msmcobalt-kbss-regulator".
+ Definition: should be one of the following:
+ "qcom,cprh-msmcobalt-v1-kbss-regulator",
+ "qcom,cprh-msmcobalt-v2-kbss-regulator",
+ "qcom,cprh-msmcobalt-kbss-regulator".
+ If the SoC revision is not specified, then it is assumed to
+ be the most recent revision of MSMCOBALT, i.e. v2.
- qcom,cpr-controller-id
Usage: required
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index deccd14d5d85..aa973e4ee3d6 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -808,6 +808,7 @@
<&mdss_dsi1_pll clk_dsi1pll_byte_clk_mux>,
<&mdss_hdmi_pll clk_hdmi_vco_clk>;
#clock-cells = <1>;
+ #reset-cells = <1>;
};
clock_gpu: qcom,gpucc@8c0000 {
@@ -2514,6 +2515,8 @@
qcom,use-sw-aes-xts-algo;
qcom,use-sw-aes-ccm-algo;
qcom,use-sw-ahash-algo;
+ qcom,use-sw-hmac-algo;
+ qcom,use-sw-aead-algo;
};
qcom_cedev: qcedev@660000 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
index 86decf438430..edf7e7b9cbb0 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
@@ -131,10 +131,6 @@
clock-names = "bus_clk", "bus_a_clk";
clocks = <&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_gcc clk_mmssnoc_axi_a_clk>;
- clk-mdss-axi-no-rate-supply =
- <&gdsc_mdss>;
- clk-mdss-ahb-no-rate-supply =
- <&gdsc_mdss>;
clk-camss-ahb-no-rate-supply =
<&gdsc_camss_top>;
clk-video-ahb-no-rate-supply =
@@ -145,8 +141,6 @@
clock-names =
"clk-noc-cfg-ahb-no-rate",
"clk-mnoc-ahb-no-rate",
- "clk-mdss-ahb-no-rate",
- "clk-mdss-axi-no-rate",
"clk-camss-ahb-no-rate",
"clk-video-ahb-no-rate",
"clk-video-axi-no-rate";
@@ -154,8 +148,6 @@
<&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_gcc clk_gcc_mmss_noc_cfg_ahb_clk>,
<&clock_mmss clk_mmss_mnoc_ahb_clk>,
- <&clock_mmss clk_mmss_mdss_ahb_clk>,
- <&clock_mmss clk_mmss_mdss_axi_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
<&clock_mmss clk_mmss_video_ahb_clk>,
<&clock_mmss clk_mmss_video_axi_clk>;
@@ -535,6 +527,19 @@
qcom,bus-dev = <&fab_mnoc>;
qcom,vrail-comp = <25>;
qcom,mas-rpm-id = <ICBID_MASTER_MDP0>;
+ clk-mdss-axi-no-rate-supply =
+ <&gdsc_mdss>;
+ clk-mdss-ahb-no-rate-supply =
+ <&gdsc_mdss>;
+ qcom,node-qos-clks {
+ clock-names =
+ "clk-mdss-ahb-no-rate",
+ "clk-mdss-axi-no-rate";
+ clocks =
+ <&clock_mmss clk_mmss_mdss_ahb_clk>,
+ <&clock_mmss clk_mmss_mdss_axi_clk>;
+ };
+
};
mas_mdp_p1: mas-mdp-p1 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
index b11c68ae543e..def8ed6e07a7 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera.dtsi
@@ -373,24 +373,24 @@
camss-vdd-supply = <&gdsc_camss_top>;
vdd-supply = <&gdsc_cpp>;
qcom,vdd-names = "smmu-vdd", "camss-vdd", "vdd";
- clocks = <&clock_mmss clk_mmss_mnoc_maxi_clk>,
+ clocks = <&clock_gcc clk_mmssnoc_axi_clk>,
+ <&clock_mmss clk_mmss_mnoc_maxi_clk>,
<&clock_mmss clk_mmss_mnoc_ahb_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
<&clock_mmss clk_mmss_camss_top_ahb_clk>,
- <&clock_mmss clk_cpp_clk_src>,
+ <&clock_mmss clk_mmss_camss_cpp_clk>,
<&clock_mmss clk_mmss_camss_cpp_ahb_clk>,
<&clock_mmss clk_mmss_camss_cpp_axi_clk>,
- <&clock_mmss clk_mmss_camss_cpp_clk>,
<&clock_mmss clk_mmss_camss_micro_ahb_clk>,
<&clock_mmss clk_mmss_bimc_smmu_axi_clk>,
<&clock_mmss clk_mmss_camss_cpp_vbif_ahb_clk>;
- clock-names = "mnoc_maxi_clk", "mnoc_ahb_clk",
+ clock-names = "mmssnoc_axi_clk",
+ "mnoc_maxi_clk", "mnoc_ahb_clk",
"camss_ahb_clk", "camss_top_ahb_clk",
"cpp_core_clk", "camss_cpp_ahb_clk",
- "camss_cpp_axi_clk", "camss_cpp_clk",
- "micro_iface_clk", "mmss_smmu_axi_clk",
- "cpp_vbif_ahb_clk";
- qcom,clock-rates = <0 0 0 0 200000000 0 0 200000000 0 0 0>;
+ "camss_cpp_axi_clk", "micro_iface_clk",
+ "mmss_smmu_axi_clk", "cpp_vbif_ahb_clk";
+ qcom,clock-rates = <0 0 0 0 0 200000000 0 0 0 0 0>;
qcom,min-clock-rate = <200000000>;
qcom,bus-master = <1>;
qcom,vbif-qos-setting = <0x20 0x10000000>,
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 24e23d00d697..c0f465b0eba5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -1778,5 +1778,942 @@
bias-pull-up;
};
};
+
+ pri_aux_pcm_clk {
+ pri_aux_pcm_clk_sleep: pri_aux_pcm_clk_sleep {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_clk_active: pri_aux_pcm_clk_active {
+ mux {
+ pins = "gpio65";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_aux_pcm_sync {
+ pri_aux_pcm_sync_sleep: pri_aux_pcm_sync_sleep {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_sync_active: pri_aux_pcm_sync_active {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_aux_pcm_din {
+ pri_aux_pcm_din_sleep: pri_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_din_active: pri_aux_pcm_din_active {
+ mux {
+ pins = "gpio67";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_aux_pcm_dout {
+ pri_aux_pcm_dout_sleep: pri_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_dout_active: pri_aux_pcm_dout_active {
+ mux {
+ pins = "gpio68";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm {
+ sec_aux_pcm_sleep: sec_aux_pcm_sleep {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_active: sec_aux_pcm_active {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm_din {
+ sec_aux_pcm_din_sleep: sec_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio82";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_din_active: sec_aux_pcm_din_active {
+ mux {
+ pins = "gpio82";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm_dout {
+ sec_aux_pcm_dout_sleep: sec_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio83";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_dout_active: sec_aux_pcm_dout_active {
+ mux {
+ pins = "gpio83";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_aux_pcm {
+ tert_aux_pcm_sleep: tert_aux_pcm_sleep {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_active: tert_aux_pcm_active {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ tert_aux_pcm_din {
+ tert_aux_pcm_din_sleep: tert_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio77";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_din_active: tert_aux_pcm_din_active {
+ mux {
+ pins = "gpio77";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_aux_pcm_dout {
+ tert_aux_pcm_dout_sleep: tert_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio78";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_dout_active: tert_aux_pcm_dout_active {
+ mux {
+ pins = "gpio78";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_aux_pcm {
+ quat_aux_pcm_sleep: quat_aux_pcm_sleep {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_active: quat_aux_pcm_active {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ quat_aux_pcm_din {
+ quat_aux_pcm_din_sleep: quat_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio60";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_din_active: quat_aux_pcm_din_active {
+ mux {
+ pins = "gpio60";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_aux_pcm_dout {
+ quat_aux_pcm_dout_sleep: quat_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio61";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_dout_active: quat_aux_pcm_dout_active {
+ mux {
+ pins = "gpio61";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_mi2s_mclk {
+ pri_mi2s_mclk_sleep: pri_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_mclk_active: pri_mi2s_mclk_active {
+ mux {
+ pins = "gpio64";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_sck {
+ pri_mi2s_sck_sleep: pri_mi2s_sck_sleep {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sck_active: pri_mi2s_sck_active {
+ mux {
+ pins = "gpio65";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_ws {
+ pri_mi2s_ws_sleep: pri_mi2s_ws_sleep {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_ws_active: pri_mi2s_ws_active {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_sd0 {
+ pri_mi2s_sd0_sleep: pri_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sd0_active: pri_mi2s_sd0_active {
+ mux {
+ pins = "gpio67";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_mi2s_sd1 {
+ pri_mi2s_sd1_sleep: pri_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sd1_active: pri_mi2s_sd1_active {
+ mux {
+ pins = "gpio68";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_mclk {
+ sec_mi2s_mclk_sleep: sec_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_mclk_active: sec_mi2s_mclk_active {
+ mux {
+ pins = "gpio79";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s {
+ sec_mi2s_sleep: sec_mi2s_sleep {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <2>; /* 2 mA */
+ bias-disable; /* NO PULL */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_active: sec_mi2s_active {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_sd0 {
+ sec_mi2s_sd0_sleep: sec_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio82";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_sd0_active: sec_mi2s_sd0_active {
+ mux {
+ pins = "gpio82";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_sd1 {
+ sec_mi2s_sd1_sleep: sec_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio83";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_sd1_active: sec_mi2s_sd1_active {
+ mux {
+ pins = "gpio83";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s_mclk {
+ tert_mi2s_mclk_sleep: tert_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio74";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_mclk_active: tert_mi2s_mclk_active {
+ mux {
+ pins = "gpio74";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s {
+ tert_mi2s_sleep: tert_mi2s_sleep {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_active: tert_mi2s_active {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ tert_mi2s_sd0 {
+ tert_mi2s_sd0_sleep: tert_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio77";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_sd0_active: tert_mi2s_sd0_active {
+ mux {
+ pins = "gpio77";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s_sd1 {
+ tert_mi2s_sd1_sleep: tert_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio78";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_sd1_active: tert_mi2s_sd1_active {
+ mux {
+ pins = "gpio78";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_mclk {
+ quat_mi2s_mclk_sleep: quat_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_mclk_active: quat_mi2s_mclk_active {
+ mux {
+ pins = "gpio57";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s {
+ quat_mi2s_sleep: quat_mi2s_sleep {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_active: quat_mi2s_active {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ quat_mi2s_sd0 {
+ quat_mi2s_sd0_sleep: quat_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio60";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd0_active: quat_mi2s_sd0_active {
+ mux {
+ pins = "gpio60";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd1 {
+ quat_mi2s_sd1_sleep: quat_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio61";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd1_active: quat_mi2s_sd1_active {
+ mux {
+ pins = "gpio61";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd2 {
+ quat_mi2s_sd2_sleep: quat_mi2s_sd2_sleep {
+ mux {
+ pins = "gpio62";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio62";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd2_active: quat_mi2s_sd2_active {
+ mux {
+ pins = "gpio62";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio62";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd3 {
+ quat_mi2s_sd3_sleep: quat_mi2s_sd3_sleep {
+ mux {
+ pins = "gpio63";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd3_active: quat_mi2s_sd3_active {
+ mux {
+ pins = "gpio63";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
index 9f8ecea15568..eaf8f0d6240a 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
@@ -555,7 +555,7 @@
&soc {
/* CPR controller regulators */
apc0_cpr: cprh-ctrl@179c8000 {
- compatible = "qcom,cprh-msmcobalt-kbss-regulator";
+ compatible = "qcom,cprh-msmcobalt-v1-kbss-regulator";
reg = <0x179c8000 0x4000>, <0x00784000 0x1000>;
reg-names = "cpr_ctrl", "fuse_base";
clocks = <&clock_gcc clk_gcc_hmss_rbcpr_clk>;
@@ -717,7 +717,7 @@
};
apc1_cpr: cprh-ctrl@179c4000{
- compatible = "qcom,cprh-msmcobalt-kbss-regulator";
+ compatible = "qcom,cprh-msmcobalt-v1-kbss-regulator";
reg = <0x179c4000 0x4000>, <0x00784000 0x1000>;
reg-names = "cpr_ctrl", "fuse_base";
clocks = <&clock_gcc clk_gcc_hmss_rbcpr_clk>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index b484b94692b5..c909c23774b5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -23,6 +23,132 @@
qcom,msm-id = <292 0x20000>;
};
+&clock_cpu {
+ qcom,pwrcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 >,
+ < 364800000 0x05040013 0x01200020 0x1 >,
+ < 441600000 0x05040017 0x02200020 0x1 >,
+ < 518400000 0x0504001b 0x02200020 0x1 >,
+ < 595200000 0x0504001f 0x02200020 0x1 >,
+ < 672000000 0x05040023 0x03200020 0x1 >,
+ < 748800000 0x05040027 0x03200020 0x1 >,
+ < 825600000 0x0404002b 0x03220022 0x1 >,
+ < 883200000 0x0404002e 0x04250025 0x1 >,
+ < 960000000 0x04040032 0x04280028 0x1 >,
+ < 1036800000 0x04040036 0x042b002b 0x1 >,
+ < 1094400000 0x04040039 0x052e002e 0x2 >,
+ < 1171200000 0x0404003d 0x05310031 0x2 >,
+ < 1248000000 0x04040041 0x05340034 0x2 >,
+ < 1324800000 0x04040045 0x06370037 0x2 >,
+ < 1401600000 0x04040049 0x063a003a 0x2 >,
+ < 1478400000 0x0404004d 0x073e003e 0x2 >,
+ < 1555200000 0x04040051 0x07410041 0x2 >,
+ < 1670400000 0x04040057 0x08460046 0x2 >,
+ < 1747200000 0x0404005b 0x08490049 0x2 >,
+ < 1824000000 0x0404005f 0x084c004c 0x3 >,
+ < 1900800000 0x04040063 0x094f004f 0x3 >;
+
+ qcom,perfcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 >,
+ < 345600000 0x05040012 0x01200020 0x1 >,
+ < 422400000 0x05040016 0x02200020 0x1 >,
+ < 499200000 0x0504001a 0x02200020 0x1 >,
+ < 576000000 0x0504001e 0x02200020 0x1 >,
+ < 652800000 0x05040022 0x03200020 0x1 >,
+ < 729600000 0x05040026 0x03200020 0x1 >,
+ < 806400000 0x0504002a 0x03220022 0x1 >,
+ < 902400000 0x0404002f 0x04260026 0x1 >,
+ < 979200000 0x04040033 0x04290029 0x1 >,
+ < 1056000000 0x04040037 0x052c002c 0x1 >,
+ < 1132800000 0x0404003b 0x052f002f 0x1 >,
+ < 1190400000 0x0404003e 0x05320032 0x2 >,
+ < 1267200000 0x04040042 0x06350035 0x2 >,
+ < 1344000000 0x04040046 0x06380038 0x2 >,
+ < 1420800000 0x0404004a 0x063b003b 0x2 >,
+ < 1497600000 0x0404004e 0x073e003e 0x2 >,
+ < 1574400000 0x04040052 0x07420042 0x2 >,
+ < 1651200000 0x04040056 0x07450045 0x2 >,
+ < 1728000000 0x0404005a 0x08480048 0x2 >,
+ < 1804800000 0x0404005e 0x084b004b 0x2 >,
+ < 1881600000 0x04040062 0x094e004e 0x2 >,
+ < 1958400000 0x04040066 0x09520052 0x2 >,
+ < 2035200000 0x0404006a 0x09550055 0x3 >,
+ < 2112000000 0x0404006e 0x0a580058 0x3 >,
+ < 2188800000 0x04040072 0x0a5b005b 0x3 >,
+ < 2265600000 0x04040076 0x0a5e005e 0x3 >,
+ < 2342400000 0x0404007a 0x0a620062 0x3 >,
+ < 2419200000 0x0404007e 0x0a650065 0x3 >,
+ < 2496000000 0x04040082 0x0a680068 0x3 >;
+};
+
+&msm_cpufreq {
+ qcom,cpufreq-table-0 =
+ < 300000 >,
+ < 364800 >,
+ < 441600 >,
+ < 518400 >,
+ < 595200 >,
+ < 672000 >,
+ < 748800 >,
+ < 825600 >,
+ < 883200 >,
+ < 960000 >,
+ < 1036800 >,
+ < 1094400 >,
+ < 1171200 >,
+ < 1248000 >,
+ < 1324800 >,
+ < 1401600 >,
+ < 1478400 >,
+ < 1555200 >,
+ < 1670400 >,
+ < 1747200 >,
+ < 1824000 >,
+ < 1900800 >;
+
+ qcom,cpufreq-table-4 =
+ < 300000 >,
+ < 345600 >,
+ < 422400 >,
+ < 499200 >,
+ < 576000 >,
+ < 652800 >,
+ < 729600 >,
+ < 806400 >,
+ < 902400 >,
+ < 979200 >,
+ < 1056000 >,
+ < 1132800 >,
+ < 1190400 >,
+ < 1267200 >,
+ < 1344000 >,
+ < 1420800 >,
+ < 1497600 >,
+ < 1574400 >,
+ < 1651200 >,
+ < 1728000 >,
+ < 1804800 >,
+ < 1881600 >,
+ < 1958400 >,
+ < 2035200 >,
+ < 2112000 >,
+ < 2188800 >,
+ < 2265600 >,
+ < 2342400 >,
+ < 2419200 >,
+ < 2496000 >;
+};
+
+&devfreq_cpufreq {
+ mincpubw-cpufreq {
+ cpu-to-dev-map-0 =
+ < 1900800 1525 >;
+ cpu-to-dev-map-4 =
+ < 2419200 1525 >,
+ < 2496000 5195 >;
+ };
+};
+
&clock_gcc {
compatible = "qcom,gcc-cobalt-v2";
};
@@ -39,21 +165,21 @@
compatible = "qcom,gfxcc-cobalt-v2";
qcom,gfxfreq-speedbin0 =
< 0 0 0 >,
- < 189000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 264000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 342000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 414000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 520000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 515000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 596000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
qcom,gfxfreq-mx-speedbin0 =
< 0 0 >,
- < 189000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 264000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 342000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 414000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 520000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 515000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 596000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
@@ -65,3 +191,180 @@
qcom,max-bandwidth-high-kbps = <9400000>;
qcom,max-bandwidth-per-pipe-kbps = <4700000>;
};
+
+&apc0_cpr {
+ compatible = "qcom,cprh-msmcobalt-v2-kbss-regulator";
+};
+
+&apc0_pwrcl_vreg {
+ regulator-max-microvolt = <23>;
+ qcom,cpr-corners = <22>;
+ qcom,cpr-corner-fmax-map = <8 11 18 22>;
+
+ qcom,cpr-voltage-ceiling =
+ <688000 688000 688000 688000 688000
+ 688000 688000 688000 756000 756000
+ 756000 828000 828000 828000 828000
+ 828000 828000 828000 952000 952000
+ 1024000 1024000>;
+
+ qcom,cpr-voltage-floor =
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 632000 632000 632000 632000
+ 632000 632000 632000 712000 712000
+ 756000 756000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>;
+
+ qcom,corner-frequencies =
+ <300000000 364800000 441600000
+ 518400000 595200000 672000000
+ 748800000 825600000 883200000
+ 960000000 1036800000 1094400000
+ 1171200000 1248000000 1324800000
+ 1401600000 1478400000 1555200000
+ 1670400000 1747200000 1824000000
+ 1900800000>;
+
+ qcom,cpr-ro-scaling-factor =
+ <4001 4019 3747 3758 3564 3480 2336
+ 2247 3442 3147 2136 4156 4028 3030
+ 3727 3198>,
+ <4001 4019 3747 3758 3564 3480 2336
+ 2247 3442 3147 2136 4156 4028 3030
+ 3727 3198>,
+ <3704 3601 3465 3567 3356 3473 2686
+ 2773 3049 2932 2235 3816 3800 3097
+ 2966 2808>,
+ <2974 3092 3288 3329 2905 3096 3119
+ 3225 2865 3140 2892 3592 3408 3576
+ 1559 1392>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>,
+ <40000 24000 0 0>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>,
+ <20000 26000 0 0>;
+
+ qcom,allow-voltage-interpolation;
+ qcom,allow-quotient-interpolation;
+ qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+};
+
+&apc1_cpr {
+ compatible = "qcom,cprh-msmcobalt-v2-kbss-regulator";
+};
+
+&apc1_perfcl_vreg {
+ regulator-max-microvolt = <31>;
+ qcom,cpr-corners = <30>;
+ qcom,cpr-corner-fmax-map = <8 12 20 30>;
+
+ qcom,cpr-voltage-ceiling =
+ <688000 688000 688000 688000 688000
+ 688000 688000 688000 756000 756000
+ 756000 756000 828000 828000 828000
+ 828000 828000 828000 828000 828000
+ 952000 952000 952000 1024000 1024000
+ 1024000 1024000 1024000 1024000 1024000>;
+
+ qcom,cpr-voltage-floor =
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 568000 632000 632000 632000
+ 632000 632000 632000 632000 632000
+ 712000 712000 712000 756000 756000
+ 756000 756000 756000 756000 756000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>;
+
+ qcom,corner-frequencies =
+ <300000000 345600000 422400000
+ 499200000 576000000 652800000
+ 729600000 806400000 902400000
+ 979200000 1056000000 1132800000
+ 1190400000 1267200000 1344000000
+ 1420800000 1497600000 1574400000
+ 1651200000 1728000000 1804800000
+ 1881600000 1958400000 2035200000
+ 2112000000 2188800000 2265600000
+ 2342400000 2419200000 2496000000>;
+
+ qcom,cpr-ro-scaling-factor =
+ <4001 4019 3747 3758 3564 3480 2336
+ 2247 3442 3147 2136 4156 4028 3030
+ 3727 3190>,
+ <4001 4019 3747 3758 3564 3480 2336
+ 2247 3442 3147 2136 4156 4028 3030
+ 3727 3198>,
+ <3704 3601 3465 3567 3356 3473 2686
+ 2773 3049 2932 2235 3816 3800 3097
+ 2966 2808>,
+ <2974 3092 3288 3329 2905 3096 3119
+ 3225 2865 3140 2892 3592 3408 3576
+ 1559 1392>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>;
+
+ qcom,allow-voltage-interpolation;
+ qcom,allow-quotient-interpolation;
+ qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+};
+
+&qusb_phy0 {
+ qcom,qusb-phy-init-seq =
+ /* <value reg_offset> */
+ <0x13 0x04
+ 0x7c 0x18c
+ 0x80 0x2c
+ 0x0a 0x184
+ 0x00 0x240
+ 0x19 0xb4>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
index 0860139248d1..637698ff759a 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-vidc.dtsi
@@ -33,7 +33,8 @@
<0x80568 0x01111111>,
<0x80570 0x01111111>,
<0x80580 0x01111111>,
- <0x80588 0x01111111>;
+ <0x80588 0x01111111>,
+ <0xe2010 0x00000000>;
qcom,imem-size = <524288>; /* 512 kB */
qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */
@@ -96,7 +97,7 @@
<&clock_mmss clk_mmss_video_subcore0_clk>,
<&clock_mmss clk_mmss_video_subcore1_clk>;
qcom,clock-configs = <0x0 0x0 0x0 0x0 0x0 0x0
- 0x1 0x0 0x0 0x0 0x1 0x1>;
+ 0x3 0x0 0x2 0x2 0x3 0x3>;
/* Buses */
bus_cnoc {
@@ -233,6 +234,7 @@
<&clock_mmss clk_mmss_vmem_maxi_clk>;
clock-names = "mnoc_ahb","mnoc_maxi",
"ahb", "maxi";
+ clock-config = <0x0 0x0 0x0 0x1>;
qcom,msm-bus,name = "vmem";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 0e2cc7361e1b..683110415d5e 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -2757,13 +2757,15 @@
qcom,icnss@18800000 {
compatible = "qcom,icnss";
reg = <0x18800000 0x800000>,
- <0x10AC000 0x20>;
- reg-names = "membase", "mpm_config";
+ <0x10AC000 0x20>,
+ <0xa0000000 0x10000000>,
+ <0xb0000000 0x10000>;
+ reg-names = "membase", "mpm_config",
+ "smmu_iova_base", "smmu_iova_ipa";
clocks = <&clock_gcc clk_aggre2_noc_clk>;
clock-names = "smmu_aggre2_noc_clk";
iommus = <&anoc2_smmu 0x1900>,
<&anoc2_smmu 0x1901>;
- qcom,wlan-smmu-iova-address = <0xa0000000 0x10000000>;
interrupts = <0 413 0 /* CE0 */ >,
<0 414 0 /* CE1 */ >,
<0 415 0 /* CE2 */ >,
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi
new file mode 100644
index 000000000000..bdbcd9d7b6f9
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi
@@ -0,0 +1,175 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+&soc {
+ qcom,smp2p-modem@17911008 {
+ compatible = "qcom,smp2p";
+ reg = <0x17911008 0x4>;
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 451 1>;
+ };
+
+ qcom,smp2p-adsp@17911008 {
+ compatible = "qcom,smp2p";
+ reg = <0x17911008 0x4>;
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 158 1>;
+ };
+
+ qcom,smp2p-cdsp@17911008 {
+ compatible = "qcom,smp2p";
+ reg = <0x17911008 0x4>;
+ qcom,remote-pid = <5>;
+ qcom,irq-bitmask = <0x40000000>;
+ interrupts = <0 514 1>;
+ };
+
+ smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+ gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <15>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_15_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+ gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ smp2pgpio_sleepstate_2_out: qcom,smp2pgpio-sleepstate-gpio-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "sleepstate";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio-sleepstate-2-out {
+ compatible = "qcom,smp2pgpio-sleepstate-out";
+ gpios = <&smp2pgpio_sleepstate_2_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_5_in: qcom,smp2pgpio-smp2p-5-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <5>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_5_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_5_in";
+ gpios = <&smp2pgpio_smp2p_5_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_5_out: qcom,smp2pgpio-smp2p-5-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <5>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_5_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_5_out";
+ gpios = <&smp2pgpio_smp2p_5_out 0 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 4b3ebd3d1636..e46041cdd501 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -30,6 +30,11 @@
stdout-path = "serial0";
};
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
cpus {
#address-cells = <2>;
#size-cells = <0>;
@@ -194,6 +199,7 @@
};
};
+#include "msmfalcon-smp2p.dtsi"
&soc {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/qcom/msmhamster.dtsi b/arch/arm/boot/dts/qcom/msmhamster.dtsi
index e87cf7c153ea..4669fa519f5d 100644
--- a/arch/arm/boot/dts/qcom/msmhamster.dtsi
+++ b/arch/arm/boot/dts/qcom/msmhamster.dtsi
@@ -39,24 +39,24 @@
compatible = "qcom,gfxcc-hamster";
qcom,gfxfreq-speedbin0 =
< 0 0 0 >,
- < 185000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 285000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 265000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 358000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 434000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 542000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 630000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >,
- < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
- < 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ < 700000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
+ < 750000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
qcom,gfxfreq-mx-speedbin0 =
< 0 0 >,
- < 185000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 285000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 265000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 358000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 434000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 542000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 630000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
- < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
- < 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ < 700000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
+ < 750000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
};
&tsens0 {
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index d41957eae6ef..f5dab4e9fb4b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2078,7 +2078,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size)
mapping->nr_bitmaps = 1;
mapping->extensions = extensions;
mapping->base = base;
- mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->bits = bits;
spin_lock_init(&mapping->lock);
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 3f987b5372c5..f4b10dcd45cb 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -475,6 +475,7 @@ CONFIG_RMNET_IPA=y
CONFIG_GSI=y
CONFIG_IPA3=y
CONFIG_RMNET_IPA3=y
+CONFIG_IPA_UT=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_MSM_MHI=y
CONFIG_MSM_MHI_UCI=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 1f9740b86e43..05f5892831d7 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -537,6 +537,7 @@ CONFIG_IIO=y
CONFIG_QCOM_RRADC=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_SENSORS_SSC=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index ba867a7573e6..d14e49cb5021 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -621,7 +621,8 @@ CONFIG_IPC_LOGGING=y
CONFIG_QCOM_RTB=y
CONFIG_QCOM_RTB_SEPARATE_CPUS=y
CONFIG_FUNCTION_TRACER=y
-CONFIG_TRACER_SNAPSHOT=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_CPU_FREQ_SWITCH_PROFILER=y
CONFIG_MEMTEST=y
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 06f9ffccd562..196c73e2cf9c 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -2064,7 +2064,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
goto err2;
mapping->base = base;
- mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->bits = bits;
spin_lock_init(&mapping->lock);
mapping->domain = iommu_domain_alloc(bus);
diff --git a/drivers/base/regmap/regmap-swr.c b/drivers/base/regmap/regmap-swr.c
index 5ea67421ed85..027cbfc505ab 100644
--- a/drivers/base/regmap/regmap-swr.c
+++ b/drivers/base/regmap/regmap-swr.c
@@ -23,15 +23,15 @@
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 val_bytes;
+ int i, ret = 0;
+ u16 reg_addr = 0;
if (swr == NULL) {
dev_err(dev, "%s: swr device is NULL\n", __func__);
@@ -43,12 +43,15 @@ static int regmap_swr_gather_write(void *context,
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++) {
+ reg_addr = reg_addr + i;
+ val = (u8 *)val + (val_bytes * i);
+ ret = swr_write(swr, swr->dev_num, reg_addr, val);
if (ret < 0) {
dev_err(dev, "%s: write reg 0x%x failed, err %d\n",
- __func__, (reg_addr+i), ret);
+ __func__, reg_addr, ret);
break;
}
}
@@ -153,7 +156,7 @@ static int regmap_swr_read(void *context,
struct regmap *map = dev_get_regmap(dev, NULL);
size_t addr_bytes = map->format.reg_bytes;
int ret = 0;
- u32 reg_addr = 0;
+ u16 reg_addr = 0;
if (swr == NULL) {
dev_err(dev, "%s: swr is NULL\n", __func__);
@@ -164,7 +167,7 @@ static int regmap_swr_read(void *context,
__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/clk/msm/clock-gpu-cobalt.c b/drivers/clk/msm/clock-gpu-cobalt.c
index 7230c7a2bc04..7cec9be1f42c 100644
--- a/drivers/clk/msm/clock-gpu-cobalt.c
+++ b/drivers/clk/msm/clock-gpu-cobalt.c
@@ -39,8 +39,6 @@ static void __iomem *virt_base_gfx;
#define gpucc_gpll0_source_val 5
#define gpu_pll0_pll_out_even_source_val 1
#define gpu_pll0_pll_out_odd_source_val 2
-#define gpu_pll1_pll_out_even_source_val 3
-#define gpu_pll1_pll_out_odd_source_val 4
#define SW_COLLAPSE_MASK BIT(0)
#define GPU_CX_GDSCR_OFFSET 0x1004
@@ -157,65 +155,6 @@ static struct div_clk gpu_pll0_pll_out_odd = {
},
};
-static struct alpha_pll_clk gpu_pll1_pll = {
- .masks = &pll_masks_p,
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL1_PLL_MODE,
- .enable_config = 0x1,
- .is_fabia = true,
- .c = {
- .rate = 0,
- .parent = &gpucc_xo.c,
- .dbg_name = "gpu_pll1_pll",
- .ops = &clk_ops_fabia_alpha_pll,
- VDD_GPU_PLL_FMAX_MAP1(MIN, 1300000500),
- CLK_INIT(gpu_pll1_pll.c),
- },
-};
-
-static struct div_clk gpu_pll1_pll_out_even = {
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL1_USER_CTL_MODE,
- .mask = 0xf,
- .shift = 8,
- .data = {
- .max_div = 8,
- .min_div = 1,
- .skip_odd_div = true,
- .allow_div_one = true,
- .rate_margin = 500,
- },
- .ops = &postdiv_reg_ops,
- .c = {
- .parent = &gpu_pll1_pll.c,
- .dbg_name = "gpu_pll1_pll_out_even",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(gpu_pll1_pll_out_even.c),
- },
-};
-
-static struct div_clk gpu_pll1_pll_out_odd = {
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL0_USER_CTL_MODE,
- .mask = 0xf,
- .shift = 12,
- .data = {
- .max_div = 7,
- .min_div = 3,
- .skip_even_div = true,
- .rate_margin = 500,
- },
- .ops = &postdiv_reg_ops,
- .c = {
- .parent = &gpu_pll1_pll.c,
- .dbg_name = "gpu_pll1_pll_out_odd",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(gpu_pll1_pll_out_odd.c),
- },
-};
-
static struct clk_freq_tbl ftbl_gfx3d_clk_src[] = {
F_SLEW( 171000000, 342000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 251000000, 502000000, gpu_pll0_pll_out_even, 1, 0, 0),
@@ -227,11 +166,11 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src[] = {
};
static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = {
- F_SLEW( 189000000, 378000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 264000000, 528000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 180000000, 360000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 257000000, 514000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 342000000, 684000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 414000000, 828000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 520000000, 1040000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 515000000, 1030000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 596000000, 1192000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 670000000, 1340000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 710000000, 1420000000, gpu_pll0_pll_out_even, 1, 0, 0),
@@ -239,14 +178,14 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = {
};
static struct clk_freq_tbl ftbl_gfx3d_clk_src_vq[] = {
- F_SLEW( 185000000, 370000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 285000000, 570000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 180000000, 360000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 265000000, 530000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 358000000, 716000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 434000000, 868000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 542000000, 1084000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 630000000, 1260000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 670000000, 1340000000, gpu_pll1_pll_out_even, 1, 0, 0),
- F_SLEW( 710000000, 1420000000, gpu_pll1_pll_out_even, 1, 0, 0),
+ F_SLEW( 700000000, 1400000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 750000000, 1500000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_END
};
@@ -659,9 +598,6 @@ static struct clk_lookup msm_clocks_gfxcc_cobalt[] = {
CLK_LIST(gpu_pll0_pll),
CLK_LIST(gpu_pll0_pll_out_even),
CLK_LIST(gpu_pll0_pll_out_odd),
- CLK_LIST(gpu_pll1_pll),
- CLK_LIST(gpu_pll1_pll_out_even),
- CLK_LIST(gpu_pll1_pll_out_odd),
CLK_LIST(gfx3d_clk_src),
CLK_LIST(gpucc_gfx3d_clk),
CLK_LIST(gpucc_mx_clk),
@@ -671,14 +607,12 @@ static struct clk_lookup msm_clocks_gfxcc_cobalt[] = {
static void msm_gfxcc_hamster_fixup(void)
{
gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
- gpu_pll1_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_vq;
}
static void msm_gfxcc_cobalt_v2_fixup(void)
{
gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
- gpu_pll1_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_v2;
}
diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c
index 288abb133743..2da10a2e4780 100644
--- a/drivers/clk/msm/clock-mmss-cobalt.c
+++ b/drivers/clk/msm/clock-mmss-cobalt.c
@@ -274,7 +274,7 @@ static struct rcg_clk csi0_clk_src = {
.c = {
.dbg_name = "csi0_clk_src",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP4(LOWER, 164570000, LOW, 256000000,
+ VDD_DIG_FMAX_MAP4(LOWER, 164571429, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi0_clk_src.c),
},
@@ -292,6 +292,9 @@ static struct clk_freq_tbl ftbl_vfe_clk_src[] = {
static struct clk_freq_tbl ftbl_vfe_clk_src_vq[] = {
F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
+ F_MM( 300000000, mmsscc_gpll0, 2, 0, 0),
+ F_MM( 320000000, mmpll7_pll_out, 3, 0, 0),
+ F_MM( 384000000, mmpll4_pll_out, 2, 0, 0),
F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
@@ -367,16 +370,6 @@ static struct clk_freq_tbl ftbl_maxi_clk_src[] = {
F_END
};
-static struct clk_freq_tbl ftbl_maxi_clk_src_vq[] = {
- F_MM( 19200000, mmsscc_xo, 1, 0, 0),
- F_MM( 75000000, mmsscc_gpll0_div, 4, 0, 0),
- F_MM( 171428571, mmsscc_gpll0, 3.5, 0, 0),
- F_MM( 240000000, mmsscc_gpll0, 2.5, 0, 0),
- F_MM( 323200000, mmpll0_pll_out, 2.5, 0, 0),
- F_MM( 406000000, mmpll1_pll_out, 2, 0, 0),
- F_END
-};
-
static struct rcg_clk maxi_clk_src = {
.cmd_rcgr_reg = MMSS_MAXI_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -592,18 +585,11 @@ static struct clk_freq_tbl ftbl_fd_core_clk_src[] = {
F_END
};
-static struct clk_freq_tbl ftbl_fd_core_clk_src_v2[] = {
- F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
- F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
- F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
- F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
- F_END
-};
-
static struct clk_freq_tbl ftbl_fd_core_clk_src_vq[] = {
F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
- F_MM( 400000000, mmsscc_gpll0, 1.5, 0, 0),
+ F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
+ F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
F_END
};
@@ -2677,60 +2663,81 @@ static void msm_mmsscc_hamster_fixup(void)
vfe1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
csi0_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi1_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi2_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi3_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
cpp_clk_src.freq_tbl = ftbl_cpp_clk_src_vq;
- cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW] = 384000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
jpeg0_clk_src.freq_tbl = ftbl_jpeg0_clk_src_vq;
jpeg0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csiphy_clk_src.freq_tbl = ftbl_csiphy_clk_src_vq;
+ csiphy_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
csiphy_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
fd_core_clk_src.freq_tbl = ftbl_fd_core_clk_src_vq;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 400000000;
+ fd_core_clk_src.c.fmax[VDD_DIG_LOW] = 404000000;
+ fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
csi0phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
csi1phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
csi2phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
mdp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
+ dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 154000000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW] = 312500000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW_L1] = 375000000;
rot_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
- maxi_clk_src.freq_tbl = ftbl_maxi_clk_src_vq;
video_core_clk_src.freq_tbl = ftbl_video_core_clk_src_vq;
video_core_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_core_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_core_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_core_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
video_subcore0_clk_src.freq_tbl = ftbl_video_subcore_clk_src_vq;
video_subcore0_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_subcore0_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_subcore0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_subcore0_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
video_subcore1_clk_src.freq_tbl = ftbl_video_subcore_clk_src_vq;
video_subcore1_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_subcore1_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_subcore1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_subcore1_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
};
static void msm_mmsscc_v2_fixup(void)
{
- fd_core_clk_src.freq_tbl = ftbl_fd_core_clk_src_v2;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW] = 404000000;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csiphy_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+
+ dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 148380000;
+
+ video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
+ video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
+ video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
}
int msm_mmsscc_cobalt_probe(struct platform_device *pdev)
diff --git a/drivers/clk/msm/reset.c b/drivers/clk/msm/reset.c
index 41e0357aea3e..087e245e18f4 100644
--- a/drivers/clk/msm/reset.c
+++ b/drivers/clk/msm/reset.c
@@ -40,6 +40,9 @@ msm_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
regval |= BIT(map->bit);
writel_relaxed(regval, rst->base + map->reg);
+ /* Make sure the reset is asserted */
+ mb();
+
return 0;
}
@@ -57,6 +60,9 @@ msm_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
regval &= ~BIT(map->bit);
writel_relaxed(regval, rst->base + map->reg);
+ /* Make sure the reset is de-asserted */
+ mb();
+
return 0;
}
diff --git a/drivers/firmware/qcom/tz_log.c b/drivers/firmware/qcom/tz_log.c
index 7a45142a66c1..bf3a24b3eb01 100644
--- a/drivers/firmware/qcom/tz_log.c
+++ b/drivers/firmware/qcom/tz_log.c
@@ -54,6 +54,10 @@
*/
#define TZBSP_MAX_INT_DESC 16
/*
+ * TZ 3.X version info
+ */
+#define QSEE_VERSION_TZ_3_X 0x800000
+/*
* VMID Table
*/
struct tzdbg_vmid_t {
@@ -72,6 +76,19 @@ struct tzdbg_boot_info_t {
uint32_t spare; /* Reserved for future use. */
};
/*
+ * Boot Info Table for 64-bit
+ */
+struct tzdbg_boot_info64_t {
+ uint32_t wb_entry_cnt; /* Warmboot entry CPU Counter */
+ uint32_t wb_exit_cnt; /* Warmboot exit CPU Counter */
+ uint32_t pc_entry_cnt; /* Power Collapse entry CPU Counter */
+ uint32_t pc_exit_cnt; /* Power Collapse exit CPU counter */
+ uint32_t psci_entry_cnt;/* PSCI syscall entry CPU Counter */
+ uint32_t psci_exit_cnt; /* PSCI syscall exit CPU Counter */
+ uint64_t warm_jmp_addr; /* Last Warmboot Jump Address */
+ uint32_t warm_jmp_instr; /* Last Warmboot Jump Address Instruction */
+};
+/*
* Reset Info Table
*/
struct tzdbg_reset_info_t {
@@ -318,30 +335,90 @@ static int _disp_tz_boot_stats(void)
{
int i;
int len = 0;
- struct tzdbg_boot_info_t *ptr;
+ struct tzdbg_boot_info_t *ptr = NULL;
+ struct tzdbg_boot_info64_t *ptr_64 = NULL;
+ int ret = 0;
+ uint32_t smc_id = 0;
+ uint32_t feature = 10;
+ struct qseecom_command_scm_resp resp = {};
+ struct scm_desc desc = {0};
- ptr = (struct tzdbg_boot_info_t *)((unsigned char *)tzdbg.diag_buf +
- tzdbg.diag_buf->boot_info_off);
+ if (!is_scm_armv8()) {
+ ret = scm_call(SCM_SVC_INFO, SCM_SVC_UTIL, &feature,
+ sizeof(feature), &resp, sizeof(resp));
+ } else {
+ smc_id = TZ_INFO_GET_FEATURE_VERSION_ID;
+ desc.arginfo = TZ_INFO_GET_FEATURE_VERSION_ID_PARAM_ID;
+ desc.args[0] = feature;
+ ret = scm_call2(smc_id, &desc);
+ resp.result = desc.ret[0];
+ }
- for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
- len += snprintf(tzdbg.disp_buf + len,
- (debug_rw_buf_size - 1) - len,
- " CPU #: %d\n"
- " Warmboot jump address : 0x%x\n"
- " Warmboot entry CPU counter: 0x%x\n"
- " Warmboot exit CPU counter : 0x%x\n"
- " Power Collapse entry CPU counter: 0x%x\n"
- " Power Collapse exit CPU counter : 0x%x\n",
- i, ptr->warm_jmp_addr, ptr->wb_entry_cnt,
- ptr->wb_exit_cnt, ptr->pc_entry_cnt,
- ptr->pc_exit_cnt);
+ if (ret) {
+ pr_err("%s: scm_call to register log buffer failed\n",
+ __func__);
+ return 0;
+ }
+ pr_info("qsee_version = 0x%x\n", resp.result);
- if (len > (debug_rw_buf_size - 1)) {
- pr_warn("%s: Cannot fit all info into the buffer\n",
- __func__);
- break;
+ if (resp.result >= QSEE_VERSION_TZ_3_X) {
+ ptr_64 = (struct tzdbg_boot_info64_t *)((unsigned char *)
+ tzdbg.diag_buf + tzdbg.diag_buf->boot_info_off);
+ } else {
+ ptr = (struct tzdbg_boot_info_t *)((unsigned char *)
+ tzdbg.diag_buf + tzdbg.diag_buf->boot_info_off);
+ }
+
+ for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
+ if (resp.result >= QSEE_VERSION_TZ_3_X) {
+ len += snprintf(tzdbg.disp_buf + len,
+ (debug_rw_buf_size - 1) - len,
+ " CPU #: %d\n"
+ " Warmboot jump address : 0x%llx\n"
+ " Warmboot entry CPU counter : 0x%x\n"
+ " Warmboot exit CPU counter : 0x%x\n"
+ " Power Collapse entry CPU counter : 0x%x\n"
+ " Power Collapse exit CPU counter : 0x%x\n"
+ " Psci entry CPU counter : 0x%x\n"
+ " Psci exit CPU counter : 0x%x\n"
+ " Warmboot Jump Address Instruction : 0x%x\n",
+ i, (uint64_t)ptr_64->warm_jmp_addr,
+ ptr_64->wb_entry_cnt,
+ ptr_64->wb_exit_cnt,
+ ptr_64->pc_entry_cnt,
+ ptr_64->pc_exit_cnt,
+ ptr_64->psci_entry_cnt,
+ ptr_64->psci_exit_cnt,
+ ptr_64->warm_jmp_instr);
+
+ if (len > (debug_rw_buf_size - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+ ptr_64++;
+ } else {
+ len += snprintf(tzdbg.disp_buf + len,
+ (debug_rw_buf_size - 1) - len,
+ " CPU #: %d\n"
+ " Warmboot jump address : 0x%x\n"
+ " Warmboot entry CPU counter: 0x%x\n"
+ " Warmboot exit CPU counter : 0x%x\n"
+ " Power Collapse entry CPU counter: 0x%x\n"
+ " Power Collapse exit CPU counter : 0x%x\n",
+ i, ptr->warm_jmp_addr,
+ ptr->wb_entry_cnt,
+ ptr->wb_exit_cnt,
+ ptr->pc_entry_cnt,
+ ptr->pc_exit_cnt);
+
+ if (len > (debug_rw_buf_size - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+ ptr++;
}
- ptr++;
}
tzdbg.stat[TZDBG_BOOT].data = tzdbg.disp_buf;
return len;
diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c
index 067735b3026f..5907513b43c0 100644
--- a/drivers/gpio/gpio-msm-smp2p-test.c
+++ b/drivers/gpio/gpio-msm-smp2p-test.c
@@ -1,6 +1,6 @@
/* drivers/gpio/gpio-msm-smp2p-test.c
*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -95,6 +95,10 @@ static int smp2p_gpio_test_probe(struct platform_device *pdev)
gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in;
} else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) {
gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out;
+ } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) {
+ gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in;
+ } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) {
+ gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out;
} else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) {
gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in;
} else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) {
@@ -148,6 +152,10 @@ static struct of_device_id msm_smp2p_match_table[] = {
{.compatible = "qcom,smp2pgpio_test_smp2p_4_out", },
{.compatible = "qcom,smp2pgpio_test_smp2p_4_in", },
+ /* CDSP */
+ {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", },
+ {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", },
+
/* TZ */
{.compatible = "qcom,smp2pgpio_test_smp2p_7_out", },
{.compatible = "qcom,smp2pgpio_test_smp2p_7_in", },
diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h
index 207588844931..c6dc9032c0bc 100644
--- a/drivers/gpu/msm/a5xx_reg.h
+++ b/drivers/gpu/msm/a5xx_reg.h
@@ -561,6 +561,7 @@
/* RB registers */
+#define A5XX_RB_DBG_ECO_CNT 0xCC4
#define A5XX_RB_ADDR_MODE_CNTL 0xCC5
#define A5XX_RB_MODE_CNTL 0xCC6
#define A5XX_RB_PERFCTR_RB_SEL_0 0xCD0
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b57fe05b21d5..cbeb1a924cc9 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -825,6 +825,8 @@ static struct {
{ ADRENO_QUIRK_IOMMU_SYNC, "qcom,gpu-quirk-iommu-sync" },
{ ADRENO_QUIRK_CRITICAL_PACKETS, "qcom,gpu-quirk-critical-packets" },
{ ADRENO_QUIRK_FAULT_DETECT_MASK, "qcom,gpu-quirk-fault-detect-mask" },
+ { ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING,
+ "qcom,gpu-quirk-dp2clockgating-disable" },
};
static int adreno_of_get_power(struct adreno_device *adreno_dev,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index f5fb4e48c3ee..cbbfc57e27f4 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -121,6 +121,8 @@
#define ADRENO_QUIRK_CRITICAL_PACKETS BIT(2)
/* Mask out RB1-3 activity signals from HW hang detection logic */
#define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(3)
+/* Disable RB sampler datapath clock gating optimization */
+#define ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING BIT(4)
/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE 0
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 467b385f6d56..61d27ac8061f 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -1836,6 +1836,13 @@ static void a5xx_start(struct adreno_device *adreno_dev)
kgsl_regrmw(device, A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
}
+ if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING)) {
+ /*
+ * Disable RB sampler datapath DP2 clock gating
+ * optimization for 1-SP GPU's, by default it is enabled.
+ */
+ kgsl_regrmw(device, A5XX_RB_DBG_ECO_CNT, 0, (1 << 9));
+ }
/* Set the USE_RETENTION_FLOPS chicken bit */
kgsl_regwrite(device, A5XX_CP_CHICKEN_DBG, 0x02000000);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 0160939e97f9..5ffb0b2513f3 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -158,11 +158,18 @@ unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
return RB_HOSTPTR(rb, ret);
}
- cmds = RB_HOSTPTR(rb, rb->_wptr);
- *cmds = cp_packet(adreno_dev, CP_NOP,
- KGSL_RB_DWORDS - rb->_wptr - 1);
-
- rb->_wptr = 0;
+ /*
+ * There isn't enough space toward the end of ringbuffer. So
+ * look for space from the beginning of ringbuffer upto the
+ * read pointer.
+ */
+ if (dwords < rptr) {
+ cmds = RB_HOSTPTR(rb, rb->_wptr);
+ *cmds = cp_packet(adreno_dev, CP_NOP,
+ KGSL_RB_DWORDS - rb->_wptr - 1);
+ rb->_wptr = dwords;
+ return RB_HOSTPTR(rb, 0);
+ }
}
if (rb->_wptr + dwords < rptr) {
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index c203ac7bfe8c..24005a1fda72 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -78,6 +78,16 @@ struct kgsl_dma_buf_meta {
struct sg_table *table;
};
+static inline struct kgsl_pagetable *_get_memdesc_pagetable(
+ struct kgsl_pagetable *pt, struct kgsl_mem_entry *entry)
+{
+ /* if a secured buffer, map it to secure global pagetable */
+ if (kgsl_memdesc_is_secured(&entry->memdesc))
+ return pt->mmu->securepagetable;
+
+ return pt;
+}
+
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
static const struct file_operations kgsl_fops;
@@ -445,14 +455,17 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
/* map the memory after unlocking if gpuaddr has been assigned */
if (entry->memdesc.gpuaddr) {
- /* if a secured buffer map it to secure global pagetable */
+ pagetable = process->pagetable;
if (kgsl_memdesc_is_secured(&entry->memdesc))
- pagetable = process->pagetable->mmu->securepagetable;
- else
- pagetable = process->pagetable;
+ pagetable = pagetable->mmu->securepagetable;
entry->memdesc.pagetable = pagetable;
- ret = kgsl_mmu_map(pagetable, &entry->memdesc);
+
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT)
+ ret = kgsl_mmu_sparse_dummy_map(pagetable,
+ &entry->memdesc, 0, entry->memdesc.size);
+ else if (entry->memdesc.gpuaddr)
+ ret = kgsl_mmu_map(pagetable, &entry->memdesc);
if (ret)
kgsl_mem_entry_detach_process(entry);
}
@@ -1270,6 +1283,24 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr)
}
EXPORT_SYMBOL(kgsl_sharedmem_find);
+struct kgsl_mem_entry * __must_check
+kgsl_sharedmem_find_id_flags(struct kgsl_process_private *process,
+ unsigned int id, uint64_t flags)
+{
+ int count = 0;
+ struct kgsl_mem_entry *entry;
+
+ spin_lock(&process->mem_lock);
+ entry = idr_find(&process->mem_idr, id);
+ if (entry)
+ if (!entry->pending_free &&
+ (flags & entry->memdesc.flags) == flags)
+ count = kgsl_mem_entry_get(entry);
+ spin_unlock(&process->mem_lock);
+
+ return (count == 0) ? NULL : entry;
+}
+
/**
* kgsl_sharedmem_find_id() - find a memory entry by id
* @process: the owning process
@@ -1283,19 +1314,7 @@ EXPORT_SYMBOL(kgsl_sharedmem_find);
struct kgsl_mem_entry * __must_check
kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id)
{
- int result;
- struct kgsl_mem_entry *entry;
-
- drain_workqueue(kgsl_driver.mem_workqueue);
-
- spin_lock(&process->mem_lock);
- entry = idr_find(&process->mem_idr, id);
- result = kgsl_mem_entry_get(entry);
- spin_unlock(&process->mem_lock);
-
- if (result == 0)
- return NULL;
- return entry;
+ return kgsl_sharedmem_find_id_flags(process, id, 0);
}
/**
@@ -3121,6 +3140,546 @@ long kgsl_ioctl_gpumem_get_info(struct kgsl_device_private *dev_priv,
return result;
}
+static inline int _sparse_alloc_param_sanity_check(uint64_t size,
+ uint64_t pagesize)
+{
+ if (size == 0 || pagesize == 0)
+ return -EINVAL;
+
+ if (pagesize != PAGE_SIZE && pagesize != SZ_64K)
+ return -EINVAL;
+
+ if (pagesize > size || !IS_ALIGNED(size, pagesize))
+ return -EINVAL;
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_phys_alloc *param = data;
+ struct kgsl_mem_entry *entry;
+ int ret;
+ int id;
+
+ ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
+ if (ret)
+ return ret;
+
+ entry = kgsl_mem_entry_create();
+ if (entry == NULL)
+ return -ENOMEM;
+
+ ret = kgsl_process_private_get(process);
+ if (!ret) {
+ ret = -EBADF;
+ goto err_free_entry;
+ }
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&process->mem_lock);
+ /* Allocate the ID but don't attach the pointer just yet */
+ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT);
+ spin_unlock(&process->mem_lock);
+ idr_preload_end();
+
+ if (id < 0) {
+ ret = id;
+ goto err_put_proc_priv;
+ }
+
+ entry->id = id;
+ entry->priv = process;
+
+ entry->memdesc.flags = KGSL_MEMFLAGS_SPARSE_PHYS;
+ kgsl_memdesc_set_align(&entry->memdesc, ilog2(param->pagesize));
+
+ ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc,
+ process->pagetable, param->size, entry->memdesc.flags);
+ if (ret)
+ goto err_remove_idr;
+
+ /* Sanity check to verify we got correct pagesize */
+ if (param->pagesize != PAGE_SIZE && entry->memdesc.sgt != NULL) {
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(entry->memdesc.sgt->sgl, s,
+ entry->memdesc.sgt->nents, i) {
+ if (!IS_ALIGNED(s->length, param->pagesize))
+ goto err_invalid_pages;
+ }
+ }
+
+ param->id = entry->id;
+ param->flags = entry->memdesc.flags;
+
+ trace_sparse_phys_alloc(entry->id, param->size, param->pagesize);
+ kgsl_mem_entry_commit_process(entry);
+
+ return 0;
+
+err_invalid_pages:
+ kgsl_sharedmem_free(&entry->memdesc);
+err_remove_idr:
+ spin_lock(&process->mem_lock);
+ idr_remove(&process->mem_idr, entry->id);
+ spin_unlock(&process->mem_lock);
+err_put_proc_priv:
+ kgsl_process_private_put(process);
+err_free_entry:
+ kfree(entry);
+
+ return ret;
+}
+
+long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_phys_free *param = data;
+ struct kgsl_mem_entry *entry;
+
+ entry = kgsl_sharedmem_find_id_flags(process, param->id,
+ KGSL_MEMFLAGS_SPARSE_PHYS);
+ if (entry == NULL)
+ return -EINVAL;
+
+ if (entry->memdesc.cur_bindings != 0) {
+ kgsl_mem_entry_put(entry);
+ return -EINVAL;
+ }
+
+ trace_sparse_phys_free(entry->id);
+
+ /* One put for find_id(), one put for the kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put(entry);
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_sparse_virt_alloc *param = data;
+ struct kgsl_mem_entry *entry;
+ int ret;
+
+ ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
+ if (ret)
+ return ret;
+
+ entry = kgsl_mem_entry_create();
+ if (entry == NULL)
+ return -ENOMEM;
+
+ entry->memdesc.flags = KGSL_MEMFLAGS_SPARSE_VIRT;
+ entry->memdesc.size = param->size;
+ entry->memdesc.cur_bindings = 0;
+ kgsl_memdesc_set_align(&entry->memdesc, ilog2(param->pagesize));
+
+ spin_lock_init(&entry->bind_lock);
+ entry->bind_tree = RB_ROOT;
+
+ ret = kgsl_mem_entry_attach_process(entry, dev_priv);
+ if (ret) {
+ kfree(entry);
+ return ret;
+ }
+
+ param->id = entry->id;
+ param->gpuaddr = entry->memdesc.gpuaddr;
+ param->flags = entry->memdesc.flags;
+
+ trace_sparse_virt_alloc(entry->id, param->size, param->pagesize);
+ kgsl_mem_entry_commit_process(entry);
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_virt_free *param = data;
+ struct kgsl_mem_entry *entry = NULL;
+
+ entry = kgsl_sharedmem_find_id_flags(process, param->id,
+ KGSL_MEMFLAGS_SPARSE_VIRT);
+ if (entry == NULL)
+ return -EINVAL;
+
+ if (entry->bind_tree.rb_node != NULL) {
+ kgsl_mem_entry_put(entry);
+ return -EINVAL;
+ }
+
+ trace_sparse_virt_free(entry->id);
+
+ /* One put for find_id(), one put for the kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put(entry);
+
+ return 0;
+}
+
+static int _sparse_add_to_bind_tree(struct kgsl_mem_entry *entry,
+ uint64_t v_offset,
+ struct kgsl_memdesc *memdesc,
+ uint64_t p_offset,
+ uint64_t size,
+ uint64_t flags)
+{
+ struct sparse_bind_object *new;
+ struct rb_node **node, *parent = NULL;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return -ENOMEM;
+
+ new->v_off = v_offset;
+ new->p_off = p_offset;
+ new->p_memdesc = memdesc;
+ new->size = size;
+ new->flags = flags;
+
+ node = &entry->bind_tree.rb_node;
+
+ while (*node != NULL) {
+ struct sparse_bind_object *this;
+
+ parent = *node;
+ this = rb_entry(parent, struct sparse_bind_object, node);
+
+ if (new->v_off < this->v_off)
+ node = &parent->rb_left;
+ else if (new->v_off > this->v_off)
+ node = &parent->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, node);
+ rb_insert_color(&new->node, &entry->bind_tree);
+
+ return 0;
+}
+
+static int _sparse_rm_from_bind_tree(struct kgsl_mem_entry *entry,
+ struct sparse_bind_object *obj,
+ uint64_t v_offset, uint64_t size)
+{
+ spin_lock(&entry->bind_lock);
+ if (v_offset == obj->v_off && size >= obj->size) {
+ /*
+ * We are all encompassing, remove the entry and free
+ * things up
+ */
+ rb_erase(&obj->node, &entry->bind_tree);
+ kfree(obj);
+ } else if (v_offset == obj->v_off) {
+ /*
+ * We are the front of the node, adjust the front of
+ * the node
+ */
+ obj->v_off += size;
+ obj->p_off += size;
+ obj->size -= size;
+ } else if ((v_offset + size) == (obj->v_off + obj->size)) {
+ /*
+ * We are at the end of the obj, adjust the beginning
+ * points
+ */
+ obj->size -= size;
+ } else {
+ /*
+ * We are in the middle of a node, split it up and
+ * create a new mini node. Adjust this node's bounds
+ * and add the new node to the list.
+ */
+ uint64_t tmp_size = obj->size;
+ int ret;
+
+ obj->size = v_offset - obj->v_off;
+
+ spin_unlock(&entry->bind_lock);
+ ret = _sparse_add_to_bind_tree(entry, v_offset + size,
+ obj->p_memdesc,
+ obj->p_off + (v_offset - obj->v_off) + size,
+ tmp_size - (v_offset - obj->v_off) - size,
+ obj->flags);
+
+ return ret;
+ }
+
+ spin_unlock(&entry->bind_lock);
+
+ return 0;
+}
+
+static struct sparse_bind_object *_find_containing_bind_obj(
+ struct kgsl_mem_entry *entry,
+ uint64_t offset, uint64_t size)
+{
+ struct sparse_bind_object *obj = NULL;
+ struct rb_node *node = entry->bind_tree.rb_node;
+
+ spin_lock(&entry->bind_lock);
+
+ while (node != NULL) {
+ obj = rb_entry(node, struct sparse_bind_object, node);
+
+ if (offset == obj->v_off) {
+ break;
+ } else if (offset < obj->v_off) {
+ if (offset + size > obj->v_off)
+ break;
+ node = node->rb_left;
+ obj = NULL;
+ } else if (offset > obj->v_off) {
+ if (offset < obj->v_off + obj->size)
+ break;
+ node = node->rb_right;
+ obj = NULL;
+ }
+ }
+
+ spin_unlock(&entry->bind_lock);
+
+ return obj;
+}
+
+static int _sparse_unbind(struct kgsl_mem_entry *entry,
+ struct sparse_bind_object *bind_obj,
+ uint64_t offset, uint64_t size)
+{
+ struct kgsl_memdesc *memdesc = bind_obj->p_memdesc;
+ struct kgsl_pagetable *pt = memdesc->pagetable;
+ int ret;
+
+ if (memdesc->cur_bindings < (size / PAGE_SIZE))
+ return -EINVAL;
+
+ memdesc->cur_bindings -= size / PAGE_SIZE;
+
+ ret = kgsl_mmu_unmap_offset(pt, memdesc,
+ entry->memdesc.gpuaddr, offset, size);
+ if (ret)
+ return ret;
+
+ ret = kgsl_mmu_sparse_dummy_map(pt, &entry->memdesc, offset, size);
+ if (ret)
+ return ret;
+
+ ret = _sparse_rm_from_bind_tree(entry, bind_obj, offset, size);
+ if (ret == 0) {
+ atomic_long_sub(size, &kgsl_driver.stats.mapped);
+ trace_sparse_unbind(entry->id, offset, size);
+ }
+
+ return ret;
+}
+
+static long sparse_unbind_range(struct kgsl_sparse_binding_object *obj,
+ struct kgsl_mem_entry *virt_entry)
+{
+ struct sparse_bind_object *bind_obj;
+ int ret = 0;
+ uint64_t size = obj->size;
+ uint64_t tmp_size = obj->size;
+ uint64_t offset = obj->virtoffset;
+
+ while (size > 0 && ret == 0) {
+ tmp_size = size;
+ bind_obj = _find_containing_bind_obj(virt_entry, offset, size);
+ if (bind_obj == NULL)
+ return 0;
+
+ if (bind_obj->v_off > offset) {
+ tmp_size = size - bind_obj->v_off - offset;
+ if (tmp_size > bind_obj->size)
+ tmp_size = bind_obj->size;
+ offset = bind_obj->v_off;
+ } else if (bind_obj->v_off < offset) {
+ uint64_t diff = offset - bind_obj->v_off;
+
+ if (diff + size > bind_obj->size)
+ tmp_size = bind_obj->size - diff;
+ } else {
+ if (tmp_size > bind_obj->size)
+ tmp_size = bind_obj->size;
+ }
+
+ ret = _sparse_unbind(virt_entry, bind_obj, offset, tmp_size);
+ if (ret == 0) {
+ offset += tmp_size;
+ size -= tmp_size;
+ }
+ }
+
+ return ret;
+}
+
+static inline bool _is_phys_bindable(struct kgsl_mem_entry *phys_entry,
+ uint64_t offset, uint64_t size, uint64_t flags)
+{
+ struct kgsl_memdesc *memdesc = &phys_entry->memdesc;
+
+ if (!IS_ALIGNED(offset | size, kgsl_memdesc_get_pagesize(memdesc)))
+ return false;
+
+ if (!(flags & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS) &&
+ offset + size > memdesc->size)
+ return false;
+
+ return true;
+}
+
+static int _sparse_bind(struct kgsl_process_private *process,
+ struct kgsl_mem_entry *virt_entry, uint64_t v_offset,
+ struct kgsl_mem_entry *phys_entry, uint64_t p_offset,
+ uint64_t size, uint64_t flags)
+{
+ int ret;
+ struct kgsl_pagetable *pagetable;
+ struct kgsl_memdesc *memdesc = &phys_entry->memdesc;
+
+ /* map the memory after unlocking if gpuaddr has been assigned */
+ if (memdesc->gpuaddr)
+ return -EINVAL;
+
+ if (memdesc->useraddr != 0)
+ return -EINVAL;
+
+ pagetable = memdesc->pagetable;
+
+ /* Clear out any mappings */
+ ret = kgsl_mmu_unmap_offset(pagetable, &virt_entry->memdesc,
+ virt_entry->memdesc.gpuaddr, v_offset, size);
+ if (ret)
+ return ret;
+
+ ret = kgsl_mmu_map_offset(pagetable, virt_entry->memdesc.gpuaddr,
+ v_offset, memdesc, p_offset, size, flags);
+ if (ret) {
+ /* Try to clean up, but not the end of the world */
+ kgsl_mmu_sparse_dummy_map(pagetable, &virt_entry->memdesc,
+ v_offset, size);
+ return ret;
+ }
+
+ ret = _sparse_add_to_bind_tree(virt_entry, v_offset, memdesc,
+ p_offset, size, flags);
+ if (ret == 0)
+ memdesc->cur_bindings += size / PAGE_SIZE;
+
+ return ret;
+}
+
+static long sparse_bind_range(struct kgsl_process_private *private,
+ struct kgsl_sparse_binding_object *obj,
+ struct kgsl_mem_entry *virt_entry)
+{
+ struct kgsl_mem_entry *phys_entry;
+ int ret;
+
+ phys_entry = kgsl_sharedmem_find_id_flags(private, obj->id,
+ KGSL_MEMFLAGS_SPARSE_PHYS);
+ if (phys_entry == NULL)
+ return -EINVAL;
+
+ if (!_is_phys_bindable(phys_entry, obj->physoffset, obj->size,
+ obj->flags)) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ if (kgsl_memdesc_get_align(&virt_entry->memdesc) !=
+ kgsl_memdesc_get_align(&phys_entry->memdesc)) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ ret = sparse_unbind_range(obj, virt_entry);
+ if (ret) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ ret = _sparse_bind(private, virt_entry, obj->virtoffset,
+ phys_entry, obj->physoffset, obj->size,
+ obj->flags & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS);
+ if (ret == 0) {
+ KGSL_STATS_ADD(obj->size, &kgsl_driver.stats.mapped,
+ &kgsl_driver.stats.mapped_max);
+
+ trace_sparse_bind(virt_entry->id, obj->virtoffset,
+ phys_entry->id, obj->physoffset,
+ obj->size, obj->flags);
+ }
+
+ kgsl_mem_entry_put(phys_entry);
+
+ return ret;
+}
+
+long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_sparse_bind *param = data;
+ struct kgsl_sparse_binding_object obj;
+ struct kgsl_mem_entry *virt_entry;
+ int pg_sz;
+ void __user *ptr;
+ int ret = 0;
+ int i = 0;
+
+ ptr = (void __user *) (uintptr_t) param->list;
+
+ if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
+ param->count == 0 || ptr == NULL)
+ return -EINVAL;
+
+ virt_entry = kgsl_sharedmem_find_id_flags(private, param->id,
+ KGSL_MEMFLAGS_SPARSE_VIRT);
+ if (virt_entry == NULL)
+ return -EINVAL;
+
+ pg_sz = kgsl_memdesc_get_pagesize(&virt_entry->memdesc);
+
+ for (i = 0; i < param->count; i++) {
+ memset(&obj, 0, sizeof(obj));
+ ret = _copy_from_user(&obj, ptr, sizeof(obj), param->size);
+ if (ret)
+ break;
+
+ /* Sanity check initial range */
+ if (obj.size == 0 ||
+ obj.virtoffset + obj.size > virt_entry->memdesc.size ||
+ !(IS_ALIGNED(obj.virtoffset | obj.size, pg_sz))) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (obj.flags & KGSL_SPARSE_BIND)
+ ret = sparse_bind_range(private, &obj, virt_entry);
+ else if (obj.flags & KGSL_SPARSE_UNBIND)
+ ret = sparse_unbind_range(&obj, virt_entry);
+ else
+ ret = -EINVAL;
+ if (ret)
+ break;
+
+ ptr += sizeof(obj);
+ }
+
+ kgsl_mem_entry_put(virt_entry);
+
+ return ret;
+}
+
long kgsl_ioctl_gpuobj_info(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -3356,6 +3915,13 @@ get_mmap_entry(struct kgsl_process_private *private,
goto err_put;
}
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_PHYS) {
+ if (len != entry->memdesc.size) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+
if (entry->memdesc.useraddr != 0) {
ret = -EBUSY;
goto err_put;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index ee7149e1fd41..25f5de6ce645 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -184,6 +184,7 @@ struct kgsl_memdesc_ops {
* @attrs: dma attributes for this memory
* @pages: An array of pointers to allocated pages
* @page_count: Total number of pages allocated
+ * @cur_bindings: Number of sparse pages actively bound
*/
struct kgsl_memdesc {
struct kgsl_pagetable *pagetable;
@@ -202,6 +203,7 @@ struct kgsl_memdesc {
struct dma_attrs attrs;
struct page **pages;
unsigned int page_count;
+ unsigned int cur_bindings;
};
/*
@@ -235,6 +237,8 @@ struct kgsl_memdesc {
* @dev_priv: back pointer to the device file that created this entry.
* @metadata: String containing user specified metadata for the entry
* @work: Work struct used to schedule a kgsl_mem_entry_put in atomic contexts
+ * @bind_lock: Lock for sparse memory bindings
+ * @bind_tree: RB Tree for sparse memory bindings
*/
struct kgsl_mem_entry {
struct kref refcount;
@@ -246,6 +250,8 @@ struct kgsl_mem_entry {
int pending_free;
char metadata[KGSL_GPUOBJ_ALLOC_METADATA_MAX + 1];
struct work_struct work;
+ spinlock_t bind_lock;
+ struct rb_root bind_tree;
};
struct kgsl_device_private;
@@ -315,6 +321,24 @@ struct kgsl_protected_registers {
int range;
};
+/**
+ * struct sparse_bind_object - Bind metadata
+ * @node: Node for the rb tree
+ * @p_memdesc: Physical memdesc bound to
+ * @v_off: Offset of bind in the virtual entry
+ * @p_off: Offset of bind in the physical memdesc
+ * @size: Size of the bind
+ * @flags: Flags for the bind
+ */
+struct sparse_bind_object {
+ struct rb_node node;
+ struct kgsl_memdesc *p_memdesc;
+ uint64_t v_off;
+ uint64_t p_off;
+ uint64_t size;
+ uint64_t flags;
+};
+
long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,
@@ -377,6 +401,19 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv,
long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+
void kgsl_mem_entry_destroy(struct kref *kref);
struct kgsl_mem_entry * __must_check
diff --git a/drivers/gpu/msm/kgsl_compat.c b/drivers/gpu/msm/kgsl_compat.c
index 248c78b7e5c4..028a9566fa14 100644
--- a/drivers/gpu/msm/kgsl_compat.c
+++ b/drivers/gpu/msm/kgsl_compat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -372,6 +372,16 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = {
kgsl_ioctl_gpu_command),
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
kgsl_ioctl_gpuobj_set_info),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
+ kgsl_ioctl_sparse_phys_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
+ kgsl_ioctl_sparse_phys_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
+ kgsl_ioctl_sparse_virt_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
+ kgsl_ioctl_sparse_virt_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
+ kgsl_ioctl_sparse_bind),
};
long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 93ac790f3a55..df9eb9ebd779 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -129,10 +129,13 @@ static int print_mem_entry(int id, void *ptr, void *data)
{
struct seq_file *s = data;
struct kgsl_mem_entry *entry = ptr;
- char flags[9];
+ char flags[10];
char usage[16];
struct kgsl_memdesc *m = &entry->memdesc;
+ if (m->flags & KGSL_MEMFLAGS_SPARSE_VIRT)
+ return 0;
+
flags[0] = kgsl_memdesc_is_global(m) ? 'g' : '-';
flags[1] = '-';
flags[2] = !(m->flags & KGSL_MEMFLAGS_GPUREADONLY) ? 'w' : '-';
@@ -141,7 +144,8 @@ static int print_mem_entry(int id, void *ptr, void *data)
flags[5] = kgsl_memdesc_use_cpu_map(m) ? 'p' : '-';
flags[6] = (m->useraddr) ? 'Y' : 'N';
flags[7] = kgsl_memdesc_is_secured(m) ? 's' : '-';
- flags[8] = '\0';
+ flags[8] = m->flags & KGSL_MEMFLAGS_SPARSE_PHYS ? 'P' : '-';
+ flags[9] = '\0';
kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
@@ -211,6 +215,70 @@ static const struct file_operations process_mem_fops = {
.release = process_mem_release,
};
+static int print_sparse_mem_entry(int id, void *ptr, void *data)
+{
+ struct seq_file *s = data;
+ struct kgsl_mem_entry *entry = ptr;
+ struct kgsl_memdesc *m = &entry->memdesc;
+ struct rb_node *node;
+
+ if (!(m->flags & KGSL_MEMFLAGS_SPARSE_VIRT))
+ return 0;
+
+ node = rb_first(&entry->bind_tree);
+
+ while (node != NULL) {
+ struct sparse_bind_object *obj = rb_entry(node,
+ struct sparse_bind_object, node);
+ seq_printf(s, "%5d %16llx %16llx %16llx %16llx\n",
+ entry->id, entry->memdesc.gpuaddr,
+ obj->v_off, obj->size, obj->p_off);
+ node = rb_next(node);
+ }
+
+ seq_putc(s, '\n');
+
+ return 0;
+}
+
+static int process_sparse_mem_print(struct seq_file *s, void *unused)
+{
+ struct kgsl_process_private *private = s->private;
+
+ seq_printf(s, "%5s %16s %16s %16s %16s\n",
+ "v_id", "gpuaddr", "v_offset", "v_size", "p_offset");
+
+ spin_lock(&private->mem_lock);
+ idr_for_each(&private->mem_idr, print_sparse_mem_entry, s);
+ spin_unlock(&private->mem_lock);
+
+ return 0;
+}
+
+static int process_sparse_mem_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ pid_t pid = (pid_t) (unsigned long) inode->i_private;
+ struct kgsl_process_private *private = NULL;
+
+ private = kgsl_process_private_find(pid);
+
+ if (!private)
+ return -ENODEV;
+
+ ret = single_open(file, process_sparse_mem_print, private);
+ if (ret)
+ kgsl_process_private_put(private);
+
+ return ret;
+}
+
+static const struct file_operations process_sparse_mem_fops = {
+ .open = process_sparse_mem_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = process_mem_release,
+};
/**
* kgsl_process_init_debugfs() - Initialize debugfs for a process
@@ -251,6 +319,15 @@ void kgsl_process_init_debugfs(struct kgsl_process_private *private)
if (IS_ERR_OR_NULL(dentry))
WARN((dentry == NULL),
"Unable to create 'mem' file for %s\n", name);
+
+ dentry = debugfs_create_file("sparse_mem", 0444, private->debug_root,
+ (void *) ((unsigned long) private->pid),
+ &process_sparse_mem_fops);
+
+ if (IS_ERR_OR_NULL(dentry))
+ WARN((dentry == NULL),
+ "Unable to create 'sparse_mem' file for %s\n", name);
+
}
void kgsl_core_debugfs_init(void)
diff --git a/drivers/gpu/msm/kgsl_ioctl.c b/drivers/gpu/msm/kgsl_ioctl.c
index 0802e94f56ad..894e6a4a146b 100644
--- a/drivers/gpu/msm/kgsl_ioctl.c
+++ b/drivers/gpu/msm/kgsl_ioctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -90,6 +90,16 @@ static const struct kgsl_ioctl kgsl_ioctl_funcs[] = {
kgsl_ioctl_gpu_command),
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
kgsl_ioctl_gpuobj_set_info),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
+ kgsl_ioctl_sparse_phys_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
+ kgsl_ioctl_sparse_phys_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
+ kgsl_ioctl_sparse_virt_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
+ kgsl_ioctl_sparse_virt_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
+ kgsl_ioctl_sparse_bind),
};
long kgsl_ioctl_copy_in(unsigned int kernel_cmd, unsigned int user_cmd,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index b467ef81d257..166bb68e64a1 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -323,8 +323,8 @@ static int _iommu_map_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (ret) {
- KGSL_CORE_ERR("map err: %p, 0x%016llX, 0x%llx, 0x%x, %d\n",
- iommu_pt->domain, gpuaddr, size, flags, ret);
+ KGSL_CORE_ERR("map err: 0x%016llX, 0x%llx, 0x%x, %d\n",
+ gpuaddr, size, flags, ret);
return -ENODEV;
}
@@ -351,8 +351,8 @@ static int _iommu_unmap_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (unmapped != size) {
- KGSL_CORE_ERR("unmap err: %p, 0x%016llx, 0x%llx, %zd\n",
- iommu_pt->domain, addr, size, unmapped);
+ KGSL_CORE_ERR("unmap err: 0x%016llx, 0x%llx, %zd\n",
+ addr, size, unmapped);
return -ENODEV;
}
@@ -421,8 +421,9 @@ static int _iommu_map_sg_offset_sync_pc(struct kgsl_pagetable *pt,
if (size != 0) {
/* Cleanup on error */
_iommu_unmap_sync_pc(pt, memdesc, addr, mapped);
- KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
- iommu_pt->domain, addr, nents, flags, mapped);
+ KGSL_CORE_ERR(
+ "map sg offset err: 0x%016llX, %d, %x, %zd\n",
+ addr, nents, flags, mapped);
return -ENODEV;
}
@@ -451,8 +452,8 @@ static int _iommu_map_sg_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (mapped == 0) {
- KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
- iommu_pt->domain, addr, nents, flags, mapped);
+ KGSL_CORE_ERR("map sg err: 0x%016llX, %d, %x, %zd\n",
+ addr, nents, flags, mapped);
return -ENODEV;
}
@@ -467,6 +468,13 @@ static int _iommu_map_sg_sync_pc(struct kgsl_pagetable *pt,
static struct page *kgsl_guard_page;
static struct kgsl_memdesc kgsl_secure_guard_page_memdesc;
+/*
+ * The dummy page is a placeholder/extra page to be used for sparse mappings.
+ * This page will be mapped to all virtual sparse bindings that are not
+ * physically backed.
+ */
+static struct page *kgsl_dummy_page;
+
/* These functions help find the nearest allocated memory entries on either side
* of a faulting address. If we know the nearby allocations memory we can
* get a better determination of what we think should have been located in the
@@ -1309,6 +1317,11 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
kgsl_guard_page = NULL;
}
+ if (kgsl_dummy_page != NULL) {
+ __free_page(kgsl_dummy_page);
+ kgsl_dummy_page = NULL;
+ }
+
kgsl_iommu_remove_global(mmu, &iommu->setstate);
kgsl_sharedmem_free(&iommu->setstate);
kgsl_cleanup_qdss_desc(mmu);
@@ -1523,6 +1536,8 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc, uint64_t addr,
uint64_t offset, uint64_t size)
{
+ if (size == 0 || (size + offset) > kgsl_memdesc_footprint(memdesc))
+ return -EINVAL;
/*
* All GPU addresses as assigned are page aligned, but some
* functions perturb the gpuaddr with an offset, so apply the
@@ -1530,9 +1545,8 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
*/
addr = PAGE_ALIGN(addr);
-
- if (size == 0 || addr == 0)
- return 0;
+ if (addr == 0)
+ return -EINVAL;
return _iommu_unmap_sync_pc(pt, memdesc, addr + offset, size);
}
@@ -1540,13 +1554,11 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
static int
kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc)
{
- uint64_t size = memdesc->size;
-
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += kgsl_memdesc_guard_page_size(pt->mmu, memdesc);
+ if (memdesc->size == 0 || memdesc->gpuaddr == 0)
+ return -EINVAL;
return kgsl_iommu_unmap_offset(pt, memdesc, memdesc->gpuaddr, 0,
- size);
+ kgsl_memdesc_footprint(memdesc));
}
/**
@@ -1593,7 +1605,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
} else {
if (kgsl_guard_page == NULL) {
kgsl_guard_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
- __GFP_HIGHMEM);
+ __GFP_NORETRY | __GFP_HIGHMEM);
if (kgsl_guard_page == NULL)
return -ENOMEM;
}
@@ -1602,7 +1614,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
}
return _iommu_map_sync_pc(pt, memdesc, gpuaddr, physaddr,
- kgsl_memdesc_guard_page_size(pt->mmu, memdesc),
+ kgsl_memdesc_guard_page_size(memdesc),
protflags & ~IOMMU_WRITE);
}
@@ -1658,6 +1670,100 @@ done:
return ret;
}
+static int kgsl_iommu_sparse_dummy_map(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size)
+{
+ int ret = 0, i;
+ struct page **pages = NULL;
+ struct sg_table sgt;
+ int count = size >> PAGE_SHIFT;
+
+ /* verify the offset is within our range */
+ if (size + offset > memdesc->size)
+ return -EINVAL;
+
+ if (kgsl_dummy_page == NULL) {
+ kgsl_dummy_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
+ __GFP_HIGHMEM);
+ if (kgsl_dummy_page == NULL)
+ return -ENOMEM;
+ }
+
+ pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++)
+ pages[i] = kgsl_dummy_page;
+
+ ret = sg_alloc_table_from_pages(&sgt, pages, count,
+ 0, size, GFP_KERNEL);
+ if (ret == 0) {
+ ret = _iommu_map_sg_sync_pc(pt, memdesc->gpuaddr + offset,
+ memdesc, sgt.sgl, sgt.nents,
+ IOMMU_READ | IOMMU_NOEXEC);
+ sg_free_table(&sgt);
+ }
+
+ kfree(pages);
+
+ return ret;
+}
+
+static int _map_to_one_page(struct kgsl_pagetable *pt, uint64_t addr,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, unsigned int map_flags)
+{
+ int ret = 0, i;
+ int pg_sz = kgsl_memdesc_get_pagesize(memdesc);
+ int count = size >> PAGE_SHIFT;
+ struct page *page = NULL;
+ struct page **pages = NULL;
+ struct sg_page_iter sg_iter;
+ struct sg_table sgt;
+
+ /* Find our physaddr offset addr */
+ if (memdesc->pages != NULL)
+ page = memdesc->pages[physoffset >> PAGE_SHIFT];
+ else {
+ for_each_sg_page(memdesc->sgt->sgl, &sg_iter,
+ memdesc->sgt->nents, physoffset >> PAGE_SHIFT) {
+ page = sg_page_iter_page(&sg_iter);
+ break;
+ }
+ }
+
+ if (page == NULL)
+ return -EINVAL;
+
+ pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ if (pg_sz != PAGE_SIZE) {
+ struct page *tmp_page = page;
+ int j;
+
+ for (j = 0; j < 16; j++, tmp_page += PAGE_SIZE)
+ pages[i++] = tmp_page;
+ } else
+ pages[i] = page;
+ }
+
+ ret = sg_alloc_table_from_pages(&sgt, pages, count,
+ 0, size, GFP_KERNEL);
+ if (ret == 0) {
+ ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, sgt.sgl,
+ sgt.nents, map_flags);
+ sg_free_table(&sgt);
+ }
+
+ kfree(pages);
+
+ return ret;
+}
+
static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
uint64_t virtaddr, uint64_t virtoffset,
struct kgsl_memdesc *memdesc, uint64_t physoffset,
@@ -1668,13 +1774,17 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
int ret;
struct sg_table *sgt = NULL;
- pg_sz = (1 << kgsl_memdesc_get_align(memdesc));
+ pg_sz = kgsl_memdesc_get_pagesize(memdesc);
if (!IS_ALIGNED(virtaddr | virtoffset | physoffset | size, pg_sz))
return -EINVAL;
if (size == 0)
return -EINVAL;
+ if (!(feature_flag & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS) &&
+ size + physoffset > kgsl_memdesc_footprint(memdesc))
+ return -EINVAL;
+
/*
* For paged memory allocated through kgsl, memdesc->pages is not NULL.
* Allocate sgt here just for its map operation. Contiguous memory
@@ -1688,9 +1798,13 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
if (IS_ERR(sgt))
return PTR_ERR(sgt);
- ret = _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
- memdesc, sgt->sgl, sgt->nents,
- physoffset, size, protflags);
+ if (feature_flag & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS)
+ ret = _map_to_one_page(pt, virtaddr + virtoffset,
+ memdesc, physoffset, size, protflags);
+ else
+ ret = _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
+ memdesc, sgt->sgl, sgt->nents,
+ physoffset, size, protflags);
if (memdesc->pages != NULL)
kgsl_free_sgt(sgt);
@@ -2152,8 +2266,7 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
{
struct kgsl_iommu_pt *pt = pagetable->priv;
int ret = 0;
- uint64_t addr, start, end;
- uint64_t size = memdesc->size;
+ uint64_t addr, start, end, size;
unsigned int align;
BUG_ON(kgsl_memdesc_use_cpu_map(memdesc));
@@ -2162,8 +2275,7 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
pagetable->name != KGSL_MMU_SECURE_PT)
return -EINVAL;
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += kgsl_memdesc_guard_page_size(pagetable->mmu, memdesc);
+ size = kgsl_memdesc_footprint(memdesc);
align = 1 << kgsl_memdesc_get_align(memdesc);
@@ -2445,4 +2557,5 @@ static struct kgsl_mmu_pt_ops iommu_pt_ops = {
.addr_in_range = kgsl_iommu_addr_in_range,
.mmu_map_offset = kgsl_iommu_map_offset,
.mmu_unmap_offset = kgsl_iommu_unmap_offset,
+ .mmu_sparse_dummy_map = kgsl_iommu_sparse_dummy_map,
};
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 8b0d93fda32c..10f6b8049d36 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -386,29 +386,24 @@ int
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc)
{
- int ret = 0;
int size;
if (!memdesc->gpuaddr)
return -EINVAL;
- /* Only global mappings should be mapped multiple times */
- if (!kgsl_memdesc_is_global(memdesc) &&
- (KGSL_MEMDESC_MAPPED & memdesc->priv))
- return -EINVAL;
size = kgsl_memdesc_footprint(memdesc);
- if (PT_OP_VALID(pagetable, mmu_map))
- ret = pagetable->pt_ops->mmu_map(pagetable, memdesc);
-
- if (ret)
- return ret;
+ if (PT_OP_VALID(pagetable, mmu_map)) {
+ int ret;
- atomic_inc(&pagetable->stats.entries);
- KGSL_STATS_ADD(size, &pagetable->stats.mapped,
- &pagetable->stats.max_mapped);
+ ret = pagetable->pt_ops->mmu_map(pagetable, memdesc);
+ if (ret)
+ return ret;
- memdesc->priv |= KGSL_MEMDESC_MAPPED;
+ atomic_inc(&pagetable->stats.entries);
+ KGSL_STATS_ADD(size, &pagetable->stats.mapped,
+ &pagetable->stats.max_mapped);
+ }
return 0;
}
@@ -455,22 +450,22 @@ int
kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc)
{
- uint64_t size;
-
- if (memdesc->size == 0 || memdesc->gpuaddr == 0 ||
- !(KGSL_MEMDESC_MAPPED & memdesc->priv))
+ if (memdesc->size == 0)
return -EINVAL;
- size = kgsl_memdesc_footprint(memdesc);
+ if (PT_OP_VALID(pagetable, mmu_unmap)) {
+ int ret;
+ uint64_t size;
- if (PT_OP_VALID(pagetable, mmu_unmap))
- pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
+ size = kgsl_memdesc_footprint(memdesc);
- atomic_dec(&pagetable->stats.entries);
- atomic_long_sub(size, &pagetable->stats.mapped);
+ ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
+ if (ret)
+ return ret;
- if (!kgsl_memdesc_is_global(memdesc))
- memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
return 0;
}
@@ -481,11 +476,20 @@ int kgsl_mmu_map_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t physoffset,
uint64_t size, uint64_t flags)
{
- if (PT_OP_VALID(pagetable, mmu_map_offset))
- return pagetable->pt_ops->mmu_map_offset(pagetable, virtaddr,
+ if (PT_OP_VALID(pagetable, mmu_map_offset)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_map_offset(pagetable, virtaddr,
virtoffset, memdesc, physoffset, size, flags);
+ if (ret)
+ return ret;
+
+ atomic_inc(&pagetable->stats.entries);
+ KGSL_STATS_ADD(size, &pagetable->stats.mapped,
+ &pagetable->stats.max_mapped);
+ }
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL(kgsl_mmu_map_offset);
@@ -493,14 +497,41 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
uint64_t size)
{
- if (PT_OP_VALID(pagetable, mmu_unmap_offset))
- return pagetable->pt_ops->mmu_unmap_offset(pagetable, memdesc,
+ if (PT_OP_VALID(pagetable, mmu_unmap_offset)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_unmap_offset(pagetable, memdesc,
addr, offset, size);
+ if (ret)
+ return ret;
+
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL(kgsl_mmu_unmap_offset);
+int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size)
+{
+ if (PT_OP_VALID(pagetable, mmu_sparse_dummy_map)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_sparse_dummy_map(pagetable,
+ memdesc, offset, size);
+ if (ret)
+ return ret;
+
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_sparse_dummy_map);
+
void kgsl_mmu_remove_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
{
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 588777af353f..53645cc1741c 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -106,6 +106,9 @@ struct kgsl_mmu_pt_ops {
int (*mmu_unmap_offset)(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc, uint64_t addr,
uint64_t offset, uint64_t size);
+ int (*mmu_sparse_dummy_map)(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t offset,
+ uint64_t size);
};
/*
@@ -230,6 +233,9 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device);
+int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size);
+
/*
* Static inline functions of MMU that simply call the SMMU specific
* function using a function pointer. These functions can be thought
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index c05aaecb5284..565ae4c39fdd 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -92,6 +92,18 @@ kgsl_memdesc_get_align(const struct kgsl_memdesc *memdesc)
}
/*
+ * kgsl_memdesc_get_pagesize - Get pagesize based on alignment
+ * @memdesc - the memdesc
+ *
+ * Returns the pagesize based on memdesc alignment
+ */
+static inline int
+kgsl_memdesc_get_pagesize(const struct kgsl_memdesc *memdesc)
+{
+ return (1 << kgsl_memdesc_get_align(memdesc));
+}
+
+/*
* kgsl_memdesc_get_cachemode - Get cache mode of a memdesc
* @memdesc: the memdesc
*
@@ -211,12 +223,19 @@ kgsl_memdesc_has_guard_page(const struct kgsl_memdesc *memdesc)
*
* Returns guard page size
*/
-static inline int
-kgsl_memdesc_guard_page_size(const struct kgsl_mmu *mmu,
- const struct kgsl_memdesc *memdesc)
+static inline uint64_t
+kgsl_memdesc_guard_page_size(const struct kgsl_memdesc *memdesc)
{
- return kgsl_memdesc_is_secured(memdesc) ? mmu->secure_align_mask + 1 :
- PAGE_SIZE;
+ if (!kgsl_memdesc_has_guard_page(memdesc))
+ return 0;
+
+ if (kgsl_memdesc_is_secured(memdesc)) {
+ if (memdesc->pagetable != NULL &&
+ memdesc->pagetable->mmu != NULL)
+ return memdesc->pagetable->mmu->secure_align_mask + 1;
+ }
+
+ return PAGE_SIZE;
}
/*
@@ -241,10 +260,7 @@ kgsl_memdesc_use_cpu_map(const struct kgsl_memdesc *memdesc)
static inline uint64_t
kgsl_memdesc_footprint(const struct kgsl_memdesc *memdesc)
{
- uint64_t size = memdesc->size;
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += SZ_4K;
- return size;
+ return memdesc->size + kgsl_memdesc_guard_page_size(memdesc);
}
/*
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 69ae2e3fd2d7..f9d3ede718ab 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -313,6 +313,13 @@ int kgsl_snapshot_get_object(struct kgsl_snapshot *snapshot,
goto err_put;
}
+ /* Do not save sparse memory */
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT ||
+ entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_PHYS) {
+ ret = 0;
+ goto err_put;
+ }
+
/*
* size indicates the number of bytes in the region to save. This might
* not always be the entire size of the region because some buffers are
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 8988dc12839f..bac09175cf12 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -1102,6 +1102,100 @@ TRACE_EVENT(kgsl_msg,
)
);
+DECLARE_EVENT_CLASS(sparse_alloc_template,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ __field(uint64_t, size)
+ __field(unsigned int, pagesize)
+ ),
+ TP_fast_assign(
+ __entry->id = id;
+ __entry->size = size;
+ __entry->pagesize = pagesize;
+ ),
+ TP_printk("id=%d size=0x%llX pagesize=0x%X",
+ __entry->id, __entry->size, __entry->pagesize)
+);
+
+DEFINE_EVENT(sparse_alloc_template, sparse_phys_alloc,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize)
+);
+
+DEFINE_EVENT(sparse_alloc_template, sparse_virt_alloc,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize)
+);
+
+DECLARE_EVENT_CLASS(sparse_free_template,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ ),
+ TP_fast_assign(
+ __entry->id = id;
+ ),
+ TP_printk("id=%d", __entry->id)
+);
+
+DEFINE_EVENT(sparse_free_template, sparse_phys_free,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id)
+);
+
+DEFINE_EVENT(sparse_free_template, sparse_virt_free,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id)
+);
+
+TRACE_EVENT(sparse_bind,
+ TP_PROTO(unsigned int v_id, uint64_t v_off,
+ unsigned int p_id, uint64_t p_off,
+ uint64_t size, uint64_t flags),
+ TP_ARGS(v_id, v_off, p_id, p_off, size, flags),
+ TP_STRUCT__entry(
+ __field(unsigned int, v_id)
+ __field(uint64_t, v_off)
+ __field(unsigned int, p_id)
+ __field(uint64_t, p_off)
+ __field(uint64_t, size)
+ __field(uint64_t, flags)
+ ),
+ TP_fast_assign(
+ __entry->v_id = v_id;
+ __entry->v_off = v_off;
+ __entry->p_id = p_id;
+ __entry->p_off = p_off;
+ __entry->size = size;
+ __entry->flags = flags;
+ ),
+ TP_printk(
+ "v_id=%d v_off=0x%llX p_id=%d p_off=0x%llX size=0x%llX flags=0x%llX",
+ __entry->v_id, __entry->v_off,
+ __entry->p_id, __entry->p_off,
+ __entry->size, __entry->flags)
+);
+
+TRACE_EVENT(sparse_unbind,
+ TP_PROTO(unsigned int v_id, uint64_t v_off, uint64_t size),
+ TP_ARGS(v_id, v_off, size),
+ TP_STRUCT__entry(
+ __field(unsigned int, v_id)
+ __field(uint64_t, v_off)
+ __field(uint64_t, size)
+ ),
+ TP_fast_assign(
+ __entry->v_id = v_id;
+ __entry->v_off = v_off;
+ __entry->size = size;
+ ),
+ TP_printk("v_id=%d v_off=0x%llX size=0x%llX",
+ __entry->v_id, __entry->v_off, __entry->size)
+);
+
#endif /* _KGSL_TRACE_H */
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index c28b8df4194e..ea8db1a431d0 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -14,6 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/dma-mapping-fast.h>
#include <linux/io-pgtable-fast.h>
+#include <linux/vmalloc.h>
#include <asm/cacheflush.h>
#include <asm/dma-iommu.h>
@@ -512,6 +513,33 @@ static void fast_smmu_free(struct device *dev, size_t size,
__fast_smmu_free_pages(pages, count);
}
+static int fast_smmu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr,
+ size_t size, struct dma_attrs *attrs)
+{
+ struct vm_struct *area;
+ unsigned long uaddr = vma->vm_start;
+ struct page **pages;
+ int i, nr_pages, ret = 0;
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ area = find_vm_area(cpu_addr);
+ if (!area)
+ return -EINVAL;
+
+ pages = area->pages;
+ nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ for (i = vma->vm_pgoff; i < nr_pages && uaddr < vma->vm_end; i++) {
+ ret = vm_insert_page(vma, uaddr, pages[i]);
+ if (ret)
+ break;
+ uaddr += PAGE_SIZE;
+ }
+
+ return ret;
+}
+
static int fast_smmu_dma_supported(struct device *dev, u64 mask)
{
return mask <= 0xffffffff;
@@ -559,6 +587,7 @@ static int fast_smmu_notify(struct notifier_block *self,
static const struct dma_map_ops fast_smmu_dma_ops = {
.alloc = fast_smmu_alloc,
.free = fast_smmu_free,
+ .mmap = fast_smmu_mmap_attrs,
.map_page = fast_smmu_map_page,
.unmap_page = fast_smmu_unmap_page,
.map_sg = fast_smmu_map_sg,
diff --git a/drivers/iommu/msm_dma_iommu_mapping.c b/drivers/iommu/msm_dma_iommu_mapping.c
index b91c7785df0b..e26b79959b13 100644
--- a/drivers/iommu/msm_dma_iommu_mapping.c
+++ b/drivers/iommu/msm_dma_iommu_mapping.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -267,6 +267,7 @@ int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
return ret;
}
+EXPORT_SYMBOL(msm_dma_map_sg_attrs);
static void msm_iommu_meta_destroy(struct kref *kref)
{
@@ -343,6 +344,7 @@ void msm_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nents,
out:
return;
}
+EXPORT_SYMBOL(msm_dma_unmap_sg);
/*
* Only to be called by ION code when a buffer is freed
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
index 7f5e49809a26..8da079d9d0c8 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/msm-bus.h>
+#include <linux/clk/msm-clk.h>
#include "cam_soc_api.h"
struct msm_cam_bus_pscale_data {
@@ -454,6 +455,17 @@ long msm_camera_clk_set_rate(struct device *dev,
}
EXPORT_SYMBOL(msm_camera_clk_set_rate);
+int msm_camera_set_clk_flags(struct clk *clk, unsigned long flags)
+{
+ if (!clk)
+ return -EINVAL;
+
+ CDBG("clk : %p, flags : %ld\n", clk, flags);
+
+ return clk_set_flags(clk, flags);
+}
+EXPORT_SYMBOL(msm_camera_set_clk_flags);
+
/* release memory allocated for clocks */
static int msm_camera_put_clk_info_internal(struct device *dev,
struct msm_cam_clk_info **clk_info,
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
index d1eeab92773f..b4494d4d6bab 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.h
@@ -188,6 +188,18 @@ long msm_camera_clk_set_rate(struct device *dev,
struct clk *clk,
long clk_rate);
/**
+ * @brief : Sets flags of a clock
+ *
+ * This function will set the flags for a specified clock
+ *
+ * @param clk : Pointer to clock to set flags for
+ * @param flags : The flags to set
+ *
+ * @return Status of operation.
+ */
+
+int msm_camera_set_clk_flags(struct clk *clk, unsigned long flags);
+/**
* @brief : Gets regulator info
*
* This function extracts the regulator information for a specific
@@ -200,6 +212,7 @@ long msm_camera_clk_set_rate(struct device *dev,
*
* @return Status of operation. Negative in case of error. Zero otherwise.
*/
+
int msm_camera_get_regulator_info(struct platform_device *pdev,
struct msm_cam_regulator **vdd_info, int *num_reg);
/**
diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
index 98afe4cd3074..a56e42dc1c6f 100644
--- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c
@@ -22,6 +22,7 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/videobuf2-v4l2.h>
+#include <linux/clk/msm-clk.h>
#include "msm_fd_dev.h"
#include "msm_fd_hw.h"
@@ -1203,6 +1204,7 @@ static int fd_probe(struct platform_device *pdev)
{
struct msm_fd_device *fd;
int ret;
+ int i;
/* Face detection device struct */
fd = kzalloc(sizeof(struct msm_fd_device), GFP_KERNEL);
@@ -1237,6 +1239,19 @@ static int fd_probe(struct platform_device *pdev)
goto error_get_clocks;
}
+ /*set memcore and mem periphery logic flags to 0*/
+ for (i = 0; i < fd->clk_num; i++) {
+ if ((strcmp(fd->clk_info[i].clk_name,
+ "mmss_fd_core_clk") == 0) ||
+ (strcmp(fd->clk_info[i].clk_name,
+ "mmss_fd_core_uar_clk") == 0)) {
+ msm_camera_set_clk_flags(fd->clk[i],
+ CLKFLAG_NORETAIN_MEM);
+ msm_camera_set_clk_flags(fd->clk[i],
+ CLKFLAG_NORETAIN_PERIPH);
+ }
+ }
+
ret = msm_camera_register_bus_client(pdev, CAM_BUS_CLIENT_FD);
if (ret < 0) {
dev_err(&pdev->dev, "Fail to get bus\n");
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
index ffcd88dc44f3..a792404c243c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp48.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/ratelimit.h>
+#include <linux/clk/msm-clk.h>
#include "msm_isp_util.h"
#include "msm_isp_axi_util.h"
@@ -198,6 +199,18 @@ static int msm_vfe48_get_clks(struct vfe_device *vfe_dev)
if (strcmp(vfe_dev->vfe_clk_info[i].clk_name,
"mnoc_maxi_clk") == 0)
vfe_dev->vfe_clk_info[i].clk_rate = INIT_RATE;
+ /* set no memory retention */
+ if (strcmp(vfe_dev->vfe_clk_info[i].clk_name,
+ "camss_vfe_clk") == 0 ||
+ strcmp(vfe_dev->vfe_clk_info[i].clk_name,
+ "camss_csi_vfe_clk") == 0 ||
+ strcmp(vfe_dev->vfe_clk_info[i].clk_name,
+ "camss_vfe_vbif_axi_clk") == 0) {
+ msm_camera_set_clk_flags(vfe_dev->vfe_clk[i],
+ CLKFLAG_NORETAIN_MEM);
+ msm_camera_set_clk_flags(vfe_dev->vfe_clk[i],
+ CLKFLAG_NORETAIN_PERIPH);
+ }
}
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 8721fc18eaa8..ac2d508269a4 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -184,6 +184,7 @@ int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data,
case V4L2_PIX_FMT_P16RGGB10:
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_META:
+ case V4L2_PIX_FMT_META10:
case V4L2_PIX_FMT_GREY:
stream_info->num_planes = 1;
stream_info->format_factor = ISP_Q2;
@@ -288,6 +289,7 @@ static uint32_t msm_isp_axi_get_plane_size(
case V4L2_PIX_FMT_QGBRG10:
case V4L2_PIX_FMT_QGRBG10:
case V4L2_PIX_FMT_QRGGB10:
+ case V4L2_PIX_FMT_META10:
/* TODO: fix me */
size = plane_cfg[plane_idx].output_height *
plane_cfg[plane_idx].output_width;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 5e24b146619d..e47a8de30aa9 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1396,6 +1396,7 @@ int msm_isp_cal_word_per_line(uint32_t output_format,
case V4L2_PIX_FMT_SGBRG10DPCM8:
case V4L2_PIX_FMT_SGRBG10DPCM8:
case V4L2_PIX_FMT_SRGGB10DPCM8:
+ case V4L2_PIX_FMT_META10:
val = CAL_WORD(pixel_per_line, 5, 32);
break;
case V4L2_PIX_FMT_SBGGR12:
@@ -1581,6 +1582,8 @@ int msm_isp_get_bit_per_pixel(uint32_t output_format)
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_META10:
+ case MSM_V4L2_PIX_FMT_META10:
return 10;
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_SGBRG12:
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 266a5a6be2a2..d56d246b3c91 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -319,6 +319,7 @@ err_reg_enable:
int msm_jpeg_platform_setup(struct msm_jpeg_device *pgmn_dev)
{
int rc = -1;
+ int i;
struct resource *jpeg_irq_res;
void *jpeg_base, *vbif_base;
struct platform_device *pdev = pgmn_dev->pdev;
@@ -356,6 +357,19 @@ int msm_jpeg_platform_setup(struct msm_jpeg_device *pgmn_dev)
goto err_jpeg_clk;
}
+ /*set memcore and mem periphery logic flags to 0*/
+ for (i = 0; i < pgmn_dev->num_clk; i++) {
+ if ((strcmp(pgmn_dev->jpeg_clk_info[i].clk_name,
+ "core_clk") == 0) ||
+ (strcmp(pgmn_dev->jpeg_clk_info[i].clk_name,
+ "mmss_camss_jpeg_axi_clk") == 0)) {
+ msm_camera_set_clk_flags(pgmn_dev->jpeg_clk[i],
+ CLKFLAG_NORETAIN_MEM);
+ msm_camera_set_clk_flags(pgmn_dev->jpeg_clk[i],
+ CLKFLAG_NORETAIN_PERIPH);
+ }
+ }
+
/* get all the regulators information */
rc = msm_camera_get_regulator_info(pdev, &pgmn_dev->jpeg_vdd,
&pgmn_dev->num_reg);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
index b8840115b674..63d7e715162b 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_dma/msm_jpeg_dma_dev.c
@@ -24,6 +24,7 @@
#include <media/videobuf2-core.h>
#include <media/v4l2-mem2mem.h>
#include <media/msm_jpeg_dma.h>
+#include <linux/clk/msm-clk.h>
#include "msm_jpeg_dma_dev.h"
#include "msm_jpeg_dma_hw.h"
@@ -1258,6 +1259,7 @@ static int jpegdma_probe(struct platform_device *pdev)
{
struct msm_jpegdma_device *jpegdma;
int ret;
+ int i;
dev_dbg(&pdev->dev, "jpeg v4l2 DMA probed\n");
/* Jpeg dma device struct */
@@ -1293,6 +1295,19 @@ static int jpegdma_probe(struct platform_device *pdev)
if (ret < 0)
goto error_get_clocks;
+ /*set memcore and mem periphery logic flags to 0*/
+ for (i = 0; i < jpegdma->num_clk; i++) {
+ if ((strcmp(jpegdma->jpeg_clk_info[i].clk_name,
+ "core_clk") == 0) ||
+ (strcmp(jpegdma->jpeg_clk_info[i].clk_name,
+ "mmss_camss_jpeg_axi_clk") == 0)) {
+ msm_camera_set_clk_flags(jpegdma->clk[i],
+ CLKFLAG_NORETAIN_MEM);
+ msm_camera_set_clk_flags(jpegdma->clk[i],
+ CLKFLAG_NORETAIN_PERIPH);
+ }
+ }
+
ret = msm_jpegdma_hw_get_qos(jpegdma);
if (ret < 0)
goto error_qos_get;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 5a1e99adc7f3..f4add41c85c9 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -25,6 +25,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
+#include <linux/clk/msm-clk.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/msmb_camera.h>
@@ -788,13 +789,6 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)
int rc = 0;
uint32_t vbif_version;
- rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
- CAM_AHB_SVS_VOTE);
- if (rc < 0) {
- pr_err("%s: failed to vote for AHB\n", __func__);
- goto ahb_vote_fail;
- }
-
rc = msm_camera_regulator_enable(cpp_dev->cpp_vdd,
cpp_dev->num_reg, true);
if (rc < 0) {
@@ -817,6 +811,13 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)
goto clk_failed;
}
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ goto ahb_vote_fail;
+ }
+
if (cpp_dev->state != CPP_STATE_BOOT) {
rc = msm_camera_register_irq(cpp_dev->pdev, cpp_dev->irq,
msm_cpp_irq, IRQF_TRIGGER_RISING, "cpp", cpp_dev);
@@ -880,16 +881,16 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev)
pwr_collapse_reset:
msm_cpp_update_gdscr_status(cpp_dev, false);
req_irq_fail:
+ if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
+ CAM_AHB_SUSPEND_VOTE) < 0)
+ pr_err("%s: failed to remove vote for AHB\n", __func__);
+ahb_vote_fail:
msm_camera_clk_enable(&cpp_dev->pdev->dev, cpp_dev->clk_info,
cpp_dev->cpp_clk, cpp_dev->num_clks, false);
clk_failed:
msm_camera_regulator_enable(cpp_dev->cpp_vdd,
cpp_dev->num_reg, false);
reg_enable_failed:
- if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
- CAM_AHB_SUSPEND_VOTE) < 0)
- pr_err("%s: failed to remove vote for AHB\n", __func__);
-ahb_vote_fail:
return rc;
}
@@ -903,6 +904,9 @@ static void cpp_release_hardware(struct cpp_device *cpp_dev)
}
msm_cpp_delete_buff_queue(cpp_dev);
msm_cpp_update_gdscr_status(cpp_dev, false);
+ if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
+ CAM_AHB_SUSPEND_VOTE) < 0)
+ pr_err("%s: failed to remove vote for AHB\n", __func__);
msm_camera_clk_enable(&cpp_dev->pdev->dev, cpp_dev->clk_info,
cpp_dev->cpp_clk, cpp_dev->num_clks, false);
msm_camera_regulator_enable(cpp_dev->cpp_vdd, cpp_dev->num_reg, false);
@@ -912,9 +916,6 @@ static void cpp_release_hardware(struct cpp_device *cpp_dev)
}
cpp_dev->stream_cnt = 0;
- if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
- CAM_AHB_SUSPEND_VOTE) < 0)
- pr_err("%s: failed to remove vote for AHB\n", __func__);
}
static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
@@ -3932,6 +3933,7 @@ static int cpp_probe(struct platform_device *pdev)
{
struct cpp_device *cpp_dev;
int rc = 0;
+ int i = 0;
CPP_DBG("E");
cpp_dev = kzalloc(sizeof(struct cpp_device), GFP_KERNEL);
@@ -4000,6 +4002,21 @@ static int cpp_probe(struct platform_device *pdev)
goto mem_err;
}
+ /* set memcore and mem periphery logic flags to 0 */
+ for (i = 0; i < cpp_dev->num_clks; i++) {
+ if ((strcmp(cpp_dev->clk_info[i].clk_name,
+ "cpp_core_clk") == 0) ||
+ (strcmp(cpp_dev->clk_info[i].clk_name,
+ "camss_cpp_axi_clk") == 0) ||
+ (strcmp(cpp_dev->clk_info[i].clk_name,
+ "micro_iface_clk") == 0)) {
+ msm_camera_set_clk_flags(cpp_dev->cpp_clk[i],
+ CLKFLAG_NORETAIN_MEM);
+ msm_camera_set_clk_flags(cpp_dev->cpp_clk[i],
+ CLKFLAG_NORETAIN_PERIPH);
+ }
+ }
+
rc = msm_camera_get_regulator_info(pdev, &cpp_dev->cpp_vdd,
&cpp_dev->num_reg);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index c12e95d3310a..d0ce1de1162a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -846,9 +846,14 @@ static int32_t msm_flash_get_pmic_source_info(
"qcom,current",
&fctrl->torch_op_current[i]);
if (rc < 0) {
- pr_err("current: read failed\n");
- of_node_put(torch_src_node);
- continue;
+ rc = of_property_read_u32(torch_src_node,
+ "qcom,current-ma",
+ &fctrl->torch_op_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(torch_src_node);
+ continue;
+ }
}
/* Read max-current */
@@ -915,6 +920,14 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
fctrl->flash_driver_type = FLASH_DRIVER_I2C;
}
+ /* Read the flash and torch source info from device tree node */
+ rc = msm_flash_get_pmic_source_info(of_node, fctrl);
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+
/* Read the gpio information from device tree */
rc = msm_sensor_driver_get_gpio_data(
&(fctrl->power_info.gpio_conf), of_node);
@@ -929,13 +942,6 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
fctrl->flash_driver_type);
- /* Read the flash and torch source info from device tree node */
- rc = msm_flash_get_pmic_source_info(of_node, fctrl);
- if (rc < 0) {
- pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n",
- __func__, __LINE__, rc);
- return rc;
- }
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index c9773555165e..ae451ff60c54 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig MSM_VIDC_V4L2
- bool "Qualcomm MSM V4L2 based video driver"
+ tristate "Qualcomm MSM V4L2 based video driver"
depends on ARCH_QCOM && VIDEO_V4L2
select VIDEOBUF2_CORE
diff --git a/drivers/media/platform/msm/vidc/Makefile b/drivers/media/platform/msm/vidc/Makefile
index ff355611c0d0..55c2d2e8d30b 100644
--- a/drivers/media/platform/msm/vidc/Makefile
+++ b/drivers/media/platform/msm/vidc/Makefile
@@ -1,17 +1,21 @@
-obj-$(CONFIG_MSM_VIDC_V4L2) := msm_v4l2_vidc.o \
- msm_vidc_common.o \
- msm_vidc.o \
- msm_vdec.o \
- msm_venc.o \
- msm_smem.o \
- msm_vidc_debug.o \
- msm_vidc_res_parse.o \
- venus_hfi.o \
- hfi_response_handler.o \
- hfi_packetization.o \
- vidc_hfi.o \
- venus_boot.o \
- msm_vidc_dcvs.o
+ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/
+
+msm-vidc-objs := msm_v4l2_vidc.o \
+ msm_vidc_common.o \
+ msm_vidc.o \
+ msm_vdec.o \
+ msm_venc.o \
+ msm_smem.o \
+ msm_vidc_debug.o \
+ msm_vidc_res_parse.o \
+ venus_hfi.o \
+ hfi_response_handler.o \
+ hfi_packetization.o \
+ vidc_hfi.o \
+ venus_boot.o \
+ msm_vidc_dcvs.o
+
+obj-$(CONFIG_MSM_VIDC_V4L2) := msm-vidc.o
obj-$(CONFIG_MSM_VIDC_V4L2) += governors/
diff --git a/drivers/media/platform/msm/vidc/governors/Kconfig b/drivers/media/platform/msm/vidc/governors/Kconfig
index 32362217e0b9..d667d65d5338 100644
--- a/drivers/media/platform/msm/vidc/governors/Kconfig
+++ b/drivers/media/platform/msm/vidc/governors/Kconfig
@@ -1,5 +1,5 @@
menuconfig MSM_VIDC_GOVERNORS
- bool "Clock and bandwidth governors for QTI MSM V4L2 based video driver"
+ tristate "Clock and bandwidth governors for QTI MSM V4L2 based video driver"
depends on MSM_VIDC_V4L2 && PM_DEVFREQ
help
Chooses a set of devfreq governors aimed at providing accurate bandwidth
diff --git a/drivers/media/platform/msm/vidc/governors/Makefile b/drivers/media/platform/msm/vidc/governors/Makefile
index e5b2f9d7a049..06a4d3452f14 100644
--- a/drivers/media/platform/msm/vidc/governors/Makefile
+++ b/drivers/media/platform/msm/vidc/governors/Makefile
@@ -1,5 +1,9 @@
ccflags-y := -I$(srctree)/drivers/devfreq/ \
- -I$(srctree)/drivers/media/platform/msm/vidc/
+ -I$(srctree)/drivers/media/platform/msm/vidc/ \
+ -I$(srctree)/drivers/media/platform/msm/vidc/governors/
-obj-$(CONFIG_MSM_VIDC_GOVERNORS) := msm_vidc_dyn_gov.o \
- msm_vidc_table_gov.o
+msm-vidc-dyn-gov-objs := msm_vidc_dyn_gov.o
+
+msm-vidc-table-gov-objs := msm_vidc_table_gov.o
+
+obj-$(CONFIG_MSM_VIDC_GOVERNORS) := msm-vidc-dyn-gov.o msm-vidc-table-gov.o
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 0d6a0caa86c8..58a7d0d0577a 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -781,3 +781,5 @@ static void __exit msm_vidc_exit(void)
module_init(msm_vidc_init);
module_exit(msm_vidc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index c08084a54e86..55ee7e02973c 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2702,7 +2702,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
(inst->fmts[CAPTURE_PORT]->fourcc == V4L2_PIX_FMT_HEVC);
if (is_cont_intra_supported) {
- if (air_mbs || air_ref || cir_mbs)
+ if (ctrl->val != HAL_INTRA_REFRESH_NONE)
enable.enable = true;
else
enable.enable = false;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 7976d6e8a603..1928327b60db 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -16,7 +16,11 @@
#include "vidc_hfi_api.h"
int msm_vidc_debug = VIDC_ERR | VIDC_WARN;
+EXPORT_SYMBOL(msm_vidc_debug);
+
int msm_vidc_debug_out = VIDC_OUT_PRINTK;
+EXPORT_SYMBOL(msm_vidc_debug_out);
+
int msm_vidc_fw_debug = 0x18;
int msm_vidc_fw_debug_mode = 1;
int msm_vidc_fw_low_power_mode = 1;
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 2bb91ccc6c26..240dc0caf94d 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -25,6 +25,7 @@
enum clock_properties {
CLOCK_PROP_HAS_SCALING = 1 << 0,
+ CLOCK_PROP_HAS_MEM_RETENTION = 1 << 1,
};
static int msm_vidc_populate_legacy_context_bank(
struct msm_vidc_platform_resources *res);
@@ -364,6 +365,7 @@ int msm_vidc_load_u32_table(struct platform_device *pdev,
return rc;
}
+EXPORT_SYMBOL(msm_vidc_load_u32_table);
static int msm_vidc_load_platform_version_table(
struct msm_vidc_platform_resources *res)
@@ -943,6 +945,11 @@ static int msm_vidc_load_clock_table(
vc->has_scaling = false;
}
+ if (clock_props[c] & CLOCK_PROP_HAS_MEM_RETENTION)
+ vc->has_mem_retention = true;
+ else
+ vc->has_mem_retention = false;
+
dprintk(VIDC_DBG, "Found clock %s: scale-able = %s\n", vc->name,
vc->count ? "yes" : "no");
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index c61605c7e405..734586a3f76c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -104,6 +104,7 @@ struct clock_info {
struct load_freq_table *load_freq_tbl;
u32 count;
bool has_scaling;
+ bool has_mem_retention;
};
struct clock_set {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 50c0eb351d4f..217d6a48d17a 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -738,6 +738,7 @@ bool venus_hfi_is_session_supported(unsigned long sessions_supported,
{
return __is_session_supported(sessions_supported, session_type);
}
+EXPORT_SYMBOL(venus_hfi_is_session_supported);
static int __devfreq_target(struct device *devfreq_dev,
unsigned long *freq, u32 flags)
@@ -2191,8 +2192,6 @@ static int venus_hfi_core_init(void *device)
INIT_LIST_HEAD(&dev->sess_head);
- __set_registers(dev);
-
if (!dev->hal_client) {
dev->hal_client = msm_smem_new_client(
SMEM_ION, dev->res, MSM_VIDC_UNKNOWN);
@@ -3788,6 +3787,22 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device)
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",
+ 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_prepare_enable(cl->clk);
if (rc) {
dprintk(VIDC_ERR, "Failed to enable clocks\n");
@@ -4177,6 +4192,13 @@ static int __venus_power_on(struct venus_hfi_device *device)
"Failed to scale clocks, performance might be affected\n");
rc = 0;
}
+
+ /*
+ * Re-program all of the registers that get reset as a result of
+ * regulator_disable() and _enable()
+ */
+ __set_registers(device);
+
__write_register(device, VIDC_WRAPPER_INTR_MASK,
VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK);
device->intr_status = 0;
@@ -4291,11 +4313,6 @@ static inline int __resume(struct venus_hfi_device *device)
goto err_set_video_state;
}
- /*
- * Re-program all of the registers that get reset as a result of
- * regulator_disable() and _enable()
- */
- __set_registers(device);
__setup_ucregion_memory_map(device);
/* Wait for boot completion */
rc = __boot_firmware(device);
diff --git a/drivers/media/platform/msm/vidc/vmem/Kconfig b/drivers/media/platform/msm/vidc/vmem/Kconfig
index e602e52da383..6f54120e2d04 100644
--- a/drivers/media/platform/msm/vidc/vmem/Kconfig
+++ b/drivers/media/platform/msm/vidc/vmem/Kconfig
@@ -1,3 +1,3 @@
menuconfig MSM_VIDC_VMEM
- bool "Qualcomm Technologies Inc MSM VMEM driver"
+ tristate "Qualcomm Technologies Inc MSM VMEM driver"
depends on ARCH_QCOM && MSM_VIDC_V4L2
diff --git a/drivers/media/platform/msm/vidc/vmem/Makefile b/drivers/media/platform/msm/vidc/vmem/Makefile
index 713b92e64544..a56ad95f8b71 100644
--- a/drivers/media/platform/msm/vidc/vmem/Makefile
+++ b/drivers/media/platform/msm/vidc/vmem/Makefile
@@ -1,2 +1,7 @@
-obj-$(CONFIG_MSM_VIDC_VMEM) := vmem.o \
- vmem_debugfs.o
+ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/
+ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/vmem/
+
+msm-vidc-vmem-objs := vmem.o \
+ vmem_debugfs.o
+
+obj-$(CONFIG_MSM_VIDC_VMEM) := msm-vidc-vmem.o
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c
index 3a2ac31c6450..165c5c0b4e4b 100644
--- a/drivers/media/platform/msm/vidc/vmem/vmem.c
+++ b/drivers/media/platform/msm/vidc/vmem/vmem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/clk/msm-clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -111,6 +112,7 @@ struct vmem {
struct {
const char *name;
struct clk *clk;
+ bool has_mem_retention;
} *clocks;
int num_clocks;
struct {
@@ -186,6 +188,21 @@ static inline int __power_on(struct vmem *v)
pr_debug("Enabled regulator vdd\n");
for (c = 0; c < v->num_clocks; ++c) {
+ if (v->clocks[c].has_mem_retention) {
+ rc = clk_set_flags(v->clocks[c].clk,
+ CLKFLAG_NORETAIN_PERIPH);
+ if (rc) {
+ pr_warn("Failed set flag NORETAIN_PERIPH %s\n",
+ v->clocks[c].name);
+ }
+ rc = clk_set_flags(v->clocks[c].clk,
+ CLKFLAG_NORETAIN_MEM);
+ if (rc) {
+ pr_warn("Failed set flag NORETAIN_MEM %s\n",
+ v->clocks[c].name);
+ }
+ }
+
rc = clk_prepare_enable(v->clocks[c].clk);
if (rc) {
pr_err("Failed to enable %s clock (%d)\n",
@@ -355,6 +372,7 @@ int vmem_allocate(size_t size, phys_addr_t *addr)
exit:
return rc;
}
+EXPORT_SYMBOL(vmem_allocate);
/**
* vmem_free: - Frees the memory allocated via vmem_allocate. Undefined
@@ -384,6 +402,7 @@ void vmem_free(phys_addr_t to_free)
__power_off(vmem);
atomic_dec(&vmem->alloc_count);
}
+EXPORT_SYMBOL(vmem_free);
struct vmem_interrupt_cookie {
struct vmem *vmem;
@@ -448,6 +467,7 @@ static inline int __init_resources(struct vmem *v,
struct platform_device *pdev)
{
int rc = 0, c = 0;
+ int *clock_props = NULL;
v->irq = platform_get_irq(pdev, 0);
if (v->irq < 0) {
@@ -504,6 +524,21 @@ static inline int __init_resources(struct vmem *v,
goto exit;
}
+ clock_props = devm_kzalloc(&pdev->dev,
+ v->num_clocks * sizeof(*clock_props),
+ GFP_KERNEL);
+ if (!clock_props) {
+ pr_err("Failed to allocate clock config table\n");
+ goto exit;
+ }
+
+ rc = of_property_read_u32_array(pdev->dev.of_node, "clock-config",
+ clock_props, v->num_clocks);
+ if (rc) {
+ pr_err("Failed to read clock config\n");
+ goto exit;
+ }
+
for (c = 0; c < v->num_clocks; ++c) {
const char *name = NULL;
struct clk *temp = NULL;
@@ -519,6 +554,7 @@ static inline int __init_resources(struct vmem *v,
v->clocks[c].clk = temp;
v->clocks[c].name = name;
+ v->clocks[c].has_mem_retention = clock_props[c];
}
v->vdd = devm_regulator_get(&pdev->dev, "vdd");
@@ -699,3 +735,5 @@ static void __exit vmem_exit(void)
module_init(vmem_init);
module_exit(vmem_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.h b/drivers/media/platform/msm/vidc/vmem/vmem.h
index 751904e00755..2f3a26db086b 100644
--- a/drivers/media/platform/msm/vidc/vmem/vmem.h
+++ b/drivers/media/platform/msm/vidc/vmem/vmem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,7 +14,7 @@
#ifndef __VMEM_H__
#define __VMEM_H__
-#ifdef CONFIG_MSM_VIDC_VMEM
+#if (defined CONFIG_MSM_VIDC_VMEM) || (defined CONFIG_MSM_VIDC_VMEM_MODULE)
int vmem_allocate(size_t size, phys_addr_t *addr);
void vmem_free(phys_addr_t to_free);
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 1b93c83ae98e..0c5754341991 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -741,6 +741,7 @@ static int wcd9xxx_irq_remove(struct platform_device *pdev)
wmb();
irq_domain_remove(data->domain);
kfree(data);
+ domain->host_data = NULL;
return 0;
}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84932513f008..0acebc87ec20 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -796,14 +796,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
#endif /* CONFIG_BLK_DEV_INITRD */
#ifdef CONFIG_SERIAL_EARLYCON
-extern struct of_device_id __earlycon_of_table[];
static int __init early_init_dt_scan_chosen_serial(void)
{
int offset;
const char *p;
int l;
- const struct of_device_id *match = __earlycon_of_table;
+ const struct earlycon_id *match;
const void *fdt = initial_boot_params;
offset = fdt_path_offset(fdt, "/chosen");
@@ -826,19 +825,20 @@ static int __init early_init_dt_scan_chosen_serial(void)
if (offset < 0)
return -ENODEV;
- while (match->compatible[0]) {
+ for (match = __earlycon_table; match < __earlycon_table_end; match++) {
u64 addr;
- if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
- match++;
+ if (!match->compatible[0])
+ continue;
+
+ if (fdt_node_check_compatible(fdt, offset, match->compatible))
continue;
- }
addr = fdt_translate_address(fdt, offset);
if (addr == OF_BAD_ADDR)
return -ENXIO;
- of_setup_earlycon(addr, match->data);
+ of_setup_earlycon(addr, match->setup);
return 0;
}
return -ENODEV;
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index dfdd6921fed5..1c444d6d2607 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -184,13 +184,25 @@ static const struct cpr3_fuse_param msmcobalt_kbss_speed_bin_param[] = {
/*
* Open loop voltage fuse reference voltages in microvolts for MSMCOBALT v1
*/
-static const int msmcobalt_kbss_fuse_ref_volt[MSMCOBALT_KBSS_FUSE_CORNERS] = {
+static const int
+msmcobalt_v1_kbss_fuse_ref_volt[MSMCOBALT_KBSS_FUSE_CORNERS] = {
696000,
768000,
896000,
1112000,
};
+/*
+ * Open loop voltage fuse reference voltages in microvolts for MSMCOBALT v2
+ */
+static const int
+msmcobalt_v2_kbss_fuse_ref_volt[MSMCOBALT_KBSS_FUSE_CORNERS] = {
+ 688000,
+ 756000,
+ 828000,
+ 1056000,
+};
+
#define MSMCOBALT_KBSS_FUSE_STEP_VOLT 10000
#define MSMCOBALT_KBSS_VOLTAGE_FUSE_SIZE 6
#define MSMCOBALT_KBSS_QUOT_OFFSET_SCALE 5
@@ -357,9 +369,10 @@ static int cprh_msmcobalt_kbss_calculate_open_loop_voltages(
{
struct device_node *node = vreg->of_node;
struct cprh_msmcobalt_kbss_fuses *fuse = vreg->platform_fuses;
- int i, j, rc = 0;
+ int i, j, soc_revision, rc = 0;
bool allow_interpolation;
u64 freq_low, volt_low, freq_high, volt_high;
+ const int *ref_volt;
int *fuse_volt;
int *fmax_corner;
@@ -372,9 +385,17 @@ static int cprh_msmcobalt_kbss_calculate_open_loop_voltages(
goto done;
}
+ soc_revision = vreg->thread->ctrl->soc_revision;
+ if (soc_revision == 1)
+ ref_volt = msmcobalt_v1_kbss_fuse_ref_volt;
+ else if (soc_revision == 2)
+ ref_volt = msmcobalt_v2_kbss_fuse_ref_volt;
+ else
+ ref_volt = msmcobalt_v2_kbss_fuse_ref_volt;
+
for (i = 0; i < vreg->fuse_corner_count; i++) {
fuse_volt[i] = cpr3_convert_open_loop_voltage_fuse(
- msmcobalt_kbss_fuse_ref_volt[i],
+ ref_volt[i],
MSMCOBALT_KBSS_FUSE_STEP_VOLT, fuse->init_voltage[i],
MSMCOBALT_KBSS_VOLTAGE_FUSE_SIZE);
@@ -1366,14 +1387,27 @@ static int cprh_kbss_regulator_resume(struct platform_device *pdev)
return cpr3_regulator_resume(ctrl);
}
+/* Data corresponds to the SoC revision */
static struct of_device_id cprh_regulator_match_table[] = {
- { .compatible = "qcom,cprh-msmcobalt-kbss-regulator", },
+ {
+ .compatible = "qcom,cprh-msmcobalt-v1-kbss-regulator",
+ .data = (void *)(uintptr_t)1
+ },
+ {
+ .compatible = "qcom,cprh-msmcobalt-v2-kbss-regulator",
+ .data = (void *)(uintptr_t)2
+ },
+ {
+ .compatible = "qcom,cprh-msmcobalt-kbss-regulator",
+ .data = (void *)(uintptr_t)2
+ },
{}
};
static int cprh_kbss_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ const struct of_device_id *match;
struct cpr3_controller *ctrl;
int rc;
@@ -1397,6 +1431,12 @@ static int cprh_kbss_regulator_probe(struct platform_device *pdev)
return rc;
}
+ match = of_match_node(cprh_regulator_match_table, dev->of_node);
+ if (match)
+ ctrl->soc_revision = (uintptr_t)match->data;
+ else
+ cpr3_err(ctrl, "could not find compatible string match\n");
+
rc = cpr3_map_fuse_base(ctrl, pdev);
if (rc) {
cpr3_err(ctrl, "could not map fuse base address\n");
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index e8a9751fa266..16ca3eaee61b 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -201,6 +201,8 @@ static struct icnss_data {
struct dma_iommu_mapping *smmu_mapping;
dma_addr_t smmu_iova_start;
size_t smmu_iova_len;
+ dma_addr_t smmu_iova_ipa_start;
+ size_t smmu_iova_ipa_len;
struct clk *smmu_clk;
struct qmi_handle *wlfw_clnt;
struct list_head event_list;
@@ -1727,6 +1729,66 @@ int icnss_get_irq(int ce_id)
}
EXPORT_SYMBOL(icnss_get_irq);
+struct dma_iommu_mapping *icnss_smmu_get_mapping(struct device *dev)
+{
+ struct icnss_data *priv = dev_get_drvdata(dev);
+
+ if (!priv) {
+ icnss_pr_err("Invalid drvdata: dev %p, data %p\n",
+ dev, priv);
+ return NULL;
+ }
+
+ return priv->smmu_mapping;
+}
+EXPORT_SYMBOL(icnss_smmu_get_mapping);
+
+int icnss_smmu_map(struct device *dev,
+ phys_addr_t paddr, uint32_t *iova_addr, size_t size)
+{
+ struct icnss_data *priv = dev_get_drvdata(dev);
+ unsigned long iova;
+ size_t len;
+ int ret = 0;
+
+ if (!priv) {
+ icnss_pr_err("Invalid drvdata: dev %p, data %p\n",
+ dev, priv);
+ return -EINVAL;
+ }
+
+ if (!iova_addr) {
+ icnss_pr_err("iova_addr is NULL, paddr %pa, size %zu",
+ &paddr, size);
+ return -EINVAL;
+ }
+
+ len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE);
+ iova = roundup(penv->smmu_iova_ipa_start, PAGE_SIZE);
+
+ if (iova >= priv->smmu_iova_ipa_start + priv->smmu_iova_ipa_len) {
+ icnss_pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu",
+ iova,
+ &priv->smmu_iova_ipa_start,
+ priv->smmu_iova_ipa_len);
+ return -ENOMEM;
+ }
+
+ ret = iommu_map(priv->smmu_mapping->domain, iova,
+ rounddown(paddr, PAGE_SIZE), len,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret) {
+ icnss_pr_err("PA to IOVA mapping failed, ret %d!", ret);
+ return ret;
+ }
+
+ priv->smmu_iova_ipa_start = iova + len;
+ *iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE));
+
+ return 0;
+}
+EXPORT_SYMBOL(icnss_smmu_map);
+
static struct clk *icnss_clock_init(struct device *dev, const char *cname)
{
struct clk *c;
@@ -2272,7 +2334,6 @@ static void icnss_debugfs_destroy(struct icnss_data *priv)
static int icnss_probe(struct platform_device *pdev)
{
int ret = 0;
- u32 smmu_iova_address[2];
struct resource *res;
int i;
struct device *dev = &pdev->dev;
@@ -2367,11 +2428,29 @@ static int icnss_probe(struct platform_device *pdev)
goto unmap_mpm_config;
}
- if (of_property_read_u32_array(pdev->dev.of_node,
- "qcom,wlan-smmu-iova-address",
- smmu_iova_address, 2) == 0) {
- penv->smmu_iova_start = smmu_iova_address[0];
- penv->smmu_iova_len = smmu_iova_address[1];
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "smmu_iova_base");
+ if (!res) {
+ icnss_pr_err("SMMU IOVA base not found\n");
+ } else {
+ penv->smmu_iova_start = res->start;
+ penv->smmu_iova_len = resource_size(res);
+ icnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n",
+ &penv->smmu_iova_start,
+ penv->smmu_iova_len);
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM,
+ "smmu_iova_ipa");
+ if (!res) {
+ icnss_pr_err("SMMU IOVA IPA not found\n");
+ } else {
+ penv->smmu_iova_ipa_start = res->start;
+ penv->smmu_iova_ipa_len = resource_size(res);
+ icnss_pr_dbg("smmu_iova_ipa_start: %pa, smmu_iova_ipa_len: %zu\n",
+ &penv->smmu_iova_ipa_start,
+ penv->smmu_iova_ipa_len);
+ }
ret = icnss_smmu_init(&pdev->dev);
if (ret < 0) {
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 9426e0751c4a..24018c544b06 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -208,8 +208,8 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc,
static int service_locator_send_msg(struct pd_qmi_client_data *pd)
{
struct msg_desc req_desc, resp_desc;
- struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp;
- struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req;
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp = NULL;
+ struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req = NULL;
int rc;
int db_rev_count = 0, domains_read = 0;
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index fc5688b4bc8c..d85046875d7a 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -1,6 +1,6 @@
/* drivers/soc/qcom/smp2p.c
*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -214,6 +214,7 @@ static struct smp2p_interrupt_config smp2p_int_cfgs[SMP2P_NUM_PROCS] = {
[SMP2P_AUDIO_PROC].name = "lpass",
[SMP2P_SENSOR_PROC].name = "dsps",
[SMP2P_WIRELESS_PROC].name = "wcnss",
+ [SMP2P_CDSP_PROC].name = "cdsp",
[SMP2P_TZ_PROC].name = "tz",
[SMP2P_REMOTE_MOCK_PROC].name = "mock",
};
@@ -333,6 +334,9 @@ static int smp2p_get_smem_item_id(int write_pid, int read_pid)
case SMP2P_WIRELESS_PROC:
ret = SMEM_SMP2P_WIRLESS_BASE + read_pid;
break;
+ case SMP2P_CDSP_PROC:
+ ret = SMEM_SMP2P_CDSP_BASE + read_pid;
+ break;
case SMP2P_POWER_PROC:
ret = SMEM_SMP2P_POWER_BASE + read_pid;
break;
diff --git a/drivers/soc/qcom/smp2p_private_api.h b/drivers/soc/qcom/smp2p_private_api.h
index 4223a2e1bc90..5bff32f8c06a 100644
--- a/drivers/soc/qcom/smp2p_private_api.h
+++ b/drivers/soc/qcom/smp2p_private_api.h
@@ -1,6 +1,6 @@
/* drivers/soc/qcom/smp2p_private_api.h
*
- * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,7 +31,7 @@ enum {
SMP2P_AUDIO_PROC = 2,
SMP2P_SENSOR_PROC = 3,
SMP2P_WIRELESS_PROC = 4,
- SMP2P_RESERVED_PROC_2 = 5,
+ SMP2P_CDSP_PROC = 5,
SMP2P_POWER_PROC = 6,
SMP2P_TZ_PROC = 7,
/* add new processors here */
diff --git a/drivers/soc/qcom/smp2p_sleepstate.c b/drivers/soc/qcom/smp2p_sleepstate.c
index dfebd201eeb0..04b043fbd8ec 100644
--- a/drivers/soc/qcom/smp2p_sleepstate.c
+++ b/drivers/soc/qcom/smp2p_sleepstate.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -74,6 +74,7 @@ static int smp2p_sleepstate_probe(struct platform_device *pdev)
static struct of_device_id msm_smp2p_slst_match_table[] = {
{.compatible = "qcom,smp2pgpio_sleepstate_3_out"},
+ {.compatible = "qcom,smp2pgpio-sleepstate-out"},
{},
};
diff --git a/drivers/soc/qcom/smp2p_spinlock_test.c b/drivers/soc/qcom/smp2p_spinlock_test.c
index d188bf0702c5..74aac52b5285 100644
--- a/drivers/soc/qcom/smp2p_spinlock_test.c
+++ b/drivers/soc/qcom/smp2p_spinlock_test.c
@@ -373,6 +373,11 @@ static void smp2p_ut_remote_spinlock_wcnss(struct seq_file *s)
smp2p_ut_remote_spinlock_pid(s, SMP2P_WIRELESS_PROC, false);
}
+static void smp2p_ut_remote_spinlock_cdsp(struct seq_file *s)
+{
+ smp2p_ut_remote_spinlock_pid(s, SMP2P_CDSP_PROC, false);
+}
+
static void smp2p_ut_remote_spinlock_tz(struct seq_file *s)
{
smp2p_ut_remote_spinlock_pid(s, SMP2P_TZ_PROC, false);
@@ -752,6 +757,11 @@ static void smp2p_ut_remote_spinlock_track_wcnss(struct seq_file *s)
smp2p_ut_remote_spinlock_track(s, SMP2P_WIRELESS_PROC);
}
+static void smp2p_ut_remote_spinlock_track_cdsp(struct seq_file *s)
+{
+ smp2p_ut_remote_spinlock_track(s, SMP2P_CDSP_PROC);
+}
+
static void smp2p_ut_remote_spinlock_track_tz(struct seq_file *s)
{
smp2p_ut_remote_spinlock_track(s, SMP2P_TZ_PROC);
@@ -782,6 +792,8 @@ static int __init smp2p_debugfs_init(void)
smp2p_ut_remote_spinlock_dsps);
smp2p_debug_create("ut_remote_spinlock_wcnss",
smp2p_ut_remote_spinlock_wcnss);
+ smp2p_debug_create("ut_remote_spinlock_cdsp",
+ smp2p_ut_remote_spinlock_cdsp);
smp2p_debug_create("ut_remote_spinlock_tz",
smp2p_ut_remote_spinlock_tz);
smp2p_debug_create("ut_remote_spinlock_rpm",
@@ -798,6 +810,8 @@ static int __init smp2p_debugfs_init(void)
&smp2p_ut_remote_spinlock_track_dsps);
smp2p_debug_create("ut_remote_spinlock_track_wcnss",
&smp2p_ut_remote_spinlock_track_wcnss);
+ smp2p_debug_create("ut_remote_spinlock_track_cdsp",
+ &smp2p_ut_remote_spinlock_track_cdsp);
smp2p_debug_create("ut_remote_spinlock_track_tz",
&smp2p_ut_remote_spinlock_track_tz);
return 0;
diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c
index 2cb60c11e212..266091486bf1 100644
--- a/drivers/soundwire/swr-wcd-ctrl.c
+++ b/drivers/soundwire/swr-wcd-ctrl.c
@@ -325,6 +325,7 @@ static int swrm_set_ch_map(struct swr_mstr_ctrl *swrm, void *data)
GFP_KERNEL);
if (!swrm->mstr_port->port) {
kfree(swrm->mstr_port);
+ swrm->mstr_port = NULL;
return -ENOMEM;
}
memcpy(swrm->mstr_port->port, pinfo->port, pinfo->num_port);
@@ -476,7 +477,7 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
{
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) {
@@ -1474,7 +1475,9 @@ static int swrm_remove(struct platform_device *pdev)
swrm, SWR_IRQ_FREE);
if (swrm->mstr_port) {
kfree(swrm->mstr_port->port);
+ swrm->mstr_port->port = NULL;
kfree(swrm->mstr_port);
+ swrm->mstr_port = NULL;
}
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index d549d6271d89..513d015a5ace 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -54,8 +54,7 @@ static void ion_page_pool_free_pages(struct ion_page_pool *pool,
__free_pages(page, pool->order);
}
-static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page,
- bool prefetch)
+static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page)
{
mutex_lock(&pool->mutex);
if (PageHighMem(page)) {
@@ -65,15 +64,11 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page,
list_add_tail(&page->lru, &pool->low_items);
pool->low_count++;
}
- if (!prefetch)
- pool->nr_unreserved++;
-
mutex_unlock(&pool->mutex);
return 0;
}
-static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high,
- bool prefetch)
+static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high)
{
struct page *page;
@@ -87,13 +82,6 @@ static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high,
pool->low_count--;
}
- if (prefetch) {
- BUG_ON(!pool->nr_unreserved);
- pool->nr_unreserved--;
- }
- pool->nr_unreserved = min_t(int, pool->high_count + pool->low_count,
- pool->nr_unreserved);
-
list_del(&page->lru);
return page;
}
@@ -108,9 +96,9 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool)
if (mutex_trylock(&pool->mutex)) {
if (pool->high_count)
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
else if (pool->low_count)
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
mutex_unlock(&pool->mutex);
}
if (!page) {
@@ -120,27 +108,6 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool)
return page;
}
-void *ion_page_pool_prefetch(struct ion_page_pool *pool, bool *from_pool)
-{
- struct page *page = NULL;
-
- BUG_ON(!pool);
-
- *from_pool = true;
-
- if (mutex_trylock(&pool->mutex)) {
- if (pool->high_count && pool->nr_unreserved > 0)
- page = ion_page_pool_remove(pool, true, true);
- else if (pool->low_count && pool->nr_unreserved > 0)
- page = ion_page_pool_remove(pool, false, true);
- mutex_unlock(&pool->mutex);
- }
- if (!page) {
- page = ion_page_pool_alloc_pages(pool);
- *from_pool = false;
- }
- return page;
-}
/*
* Tries to allocate from only the specified Pool and returns NULL otherwise
*/
@@ -152,24 +119,20 @@ void *ion_page_pool_alloc_pool_only(struct ion_page_pool *pool)
if (mutex_trylock(&pool->mutex)) {
if (pool->high_count)
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
else if (pool->low_count)
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
mutex_unlock(&pool->mutex);
}
return page;
}
-void ion_page_pool_free(struct ion_page_pool *pool, struct page *page,
- bool prefetch)
+void ion_page_pool_free(struct ion_page_pool *pool, struct page *page)
{
int ret;
- BUG_ON(pool->order != compound_order(page));
-
- ret = ion_page_pool_add(pool, page, prefetch);
- /* FIXME? For a secure page, not hyp unassigned in this err path */
+ ret = ion_page_pool_add(pool, page);
if (ret)
ion_page_pool_free_pages(pool, page);
}
@@ -208,9 +171,9 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
mutex_lock(&pool->mutex);
if (pool->low_count) {
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
} else if (high && pool->high_count) {
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
} else {
mutex_unlock(&pool->mutex);
break;
@@ -233,10 +196,9 @@ struct ion_page_pool *ion_page_pool_create(struct device *dev, gfp_t gfp_mask,
pool->dev = dev;
pool->high_count = 0;
pool->low_count = 0;
- pool->nr_unreserved = 0;
INIT_LIST_HEAD(&pool->low_items);
INIT_LIST_HEAD(&pool->high_items);
- pool->gfp_mask = gfp_mask | __GFP_COMP;
+ pool->gfp_mask = gfp_mask;
pool->order = order;
mutex_init(&pool->mutex);
plist_node_init(&pool->list, order);
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 4f383661258a..69da287c064f 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -415,8 +415,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
* struct ion_page_pool - pagepool struct
* @high_count: number of highmem items in the pool
* @low_count: number of lowmem items in the pool
- * @nr_unreserved: number of items in the pool which have not been reserved
- * by a prefetch allocation
* @high_items: list of highmem items
* @low_items: list of lowmem items
* @mutex: lock protecting this struct and especially the count
@@ -433,7 +431,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
struct ion_page_pool {
int high_count;
int low_count;
- int nr_unreserved;
struct list_head high_items;
struct list_head low_items;
struct mutex mutex;
@@ -448,10 +445,9 @@ struct ion_page_pool *ion_page_pool_create(struct device *dev, gfp_t gfp_mask,
void ion_page_pool_destroy(struct ion_page_pool *);
void *ion_page_pool_alloc(struct ion_page_pool *, bool *from_pool);
void *ion_page_pool_alloc_pool_only(struct ion_page_pool *);
-void ion_page_pool_free(struct ion_page_pool *, struct page *, bool prefetch);
+void ion_page_pool_free(struct ion_page_pool *, struct page *);
void ion_page_pool_free_immediate(struct ion_page_pool *, struct page *);
int ion_page_pool_total(struct ion_page_pool *pool, bool high);
-void *ion_page_pool_prefetch(struct ion_page_pool *pool, bool *from_pool);
#ifdef CONFIG_ION_POOL_CACHE_POLICY
static inline void ion_page_pool_alloc_set_cache_policy
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index ff75e1690f59..981cb2f622cb 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -63,6 +63,8 @@ struct ion_system_heap {
struct ion_page_pool **uncached_pools;
struct ion_page_pool **cached_pools;
struct ion_page_pool **secure_pools[VMID_LAST];
+ /* Prevents unnecessary page splitting */
+ struct mutex split_page_mutex;
};
struct page_info {
@@ -78,7 +80,6 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
bool *from_pool)
{
bool cached = ion_buffer_cached(buffer);
- bool prefetch = buffer->flags & ION_FLAG_POOL_PREFETCH;
struct page *page;
struct ion_page_pool *pool;
int vmid = get_secure_vmid(buffer->flags);
@@ -92,10 +93,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
else
pool = heap->cached_pools[order_to_index(order)];
- if (prefetch)
- page = ion_page_pool_prefetch(pool, from_pool);
- else
- page = ion_page_pool_alloc(pool, from_pool);
+ page = ion_page_pool_alloc(pool, from_pool);
} else {
gfp_t gfp_mask = low_order_gfp_flags;
if (order)
@@ -119,7 +117,6 @@ static void free_buffer_page(struct ion_system_heap *heap,
unsigned int order)
{
bool cached = ion_buffer_cached(buffer);
- bool prefetch = buffer->flags & ION_FLAG_POOL_PREFETCH;
int vmid = get_secure_vmid(buffer->flags);
if (!(buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)) {
@@ -134,12 +131,65 @@ static void free_buffer_page(struct ion_system_heap *heap,
if (buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)
ion_page_pool_free_immediate(pool, page);
else
- ion_page_pool_free(pool, page, prefetch);
+ ion_page_pool_free(pool, page);
} else {
__free_pages(page, order);
}
}
+static struct page *alloc_from_secure_pool_order(struct ion_system_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long order)
+{
+ int vmid = get_secure_vmid(buffer->flags);
+ struct ion_page_pool *pool;
+
+ if (!is_secure_vmid_valid(vmid))
+ return NULL;
+
+ pool = heap->secure_pools[vmid][order_to_index(order)];
+ return ion_page_pool_alloc_pool_only(pool);
+}
+
+static struct page *split_page_from_secure_pool(struct ion_system_heap *heap,
+ struct ion_buffer *buffer)
+{
+ int i, j;
+ struct page *page;
+ unsigned int order;
+
+ mutex_lock(&heap->split_page_mutex);
+
+ /*
+ * Someone may have just split a page and returned the unused portion
+ * back to the pool, so try allocating from the pool one more time
+ * before splitting. We want to maintain large pages sizes when
+ * possible.
+ */
+ page = alloc_from_secure_pool_order(heap, buffer, 0);
+ if (page)
+ goto got_page;
+
+ for (i = num_orders - 2; i >= 0; i--) {
+ order = orders[i];
+ page = alloc_from_secure_pool_order(heap, buffer, order);
+ if (!page)
+ continue;
+
+ split_page(page, order);
+ break;
+ }
+ /* Return the remaining order-0 pages to the pool */
+ if (page)
+ for (j = 1; j < (1 << order); j++)
+ free_buffer_page(heap, buffer, page + j, 0);
+
+got_page:
+ mutex_unlock(&heap->split_page_mutex);
+
+ return page;
+}
+
static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
struct ion_buffer *buffer,
unsigned long size,
@@ -174,6 +224,49 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
return NULL;
}
+
+static struct page_info *alloc_from_pool_preferred(
+ struct ion_system_heap *heap, struct ion_buffer *buffer,
+ unsigned long size, unsigned int max_order)
+{
+ struct page *page;
+ struct page_info *info;
+ int i;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return NULL;
+
+ for (i = 0; i < num_orders; i++) {
+ if (size < order_to_size(orders[i]))
+ continue;
+ if (max_order < orders[i])
+ continue;
+
+ page = alloc_from_secure_pool_order(heap, buffer, orders[i]);
+ if (!page)
+ continue;
+
+ info->page = page;
+ info->order = orders[i];
+ info->from_pool = true;
+ INIT_LIST_HEAD(&info->list);
+ return info;
+ }
+
+ page = split_page_from_secure_pool(heap, buffer);
+ if (page) {
+ info->page = page;
+ info->order = 0;
+ info->from_pool = true;
+ INIT_LIST_HEAD(&info->list);
+ return info;
+ }
+
+ kfree(info);
+ return alloc_largest_available(heap, buffer, size, max_order);
+}
+
static unsigned int process_info(struct page_info *info,
struct scatterlist *sg,
struct scatterlist *sg_sync,
@@ -236,9 +329,17 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
data.size = 0;
INIT_LIST_HEAD(&pages);
INIT_LIST_HEAD(&pages_from_pool);
+
while (size_remaining > 0) {
- info = alloc_largest_available(sys_heap, buffer, size_remaining,
- max_order);
+ if (is_secure_vmid_valid(vmid))
+ info = alloc_from_pool_preferred(
+ sys_heap, buffer, size_remaining,
+ max_order);
+ else
+ info = alloc_largest_available(
+ sys_heap, buffer, size_remaining,
+ max_order);
+
if (!info)
goto err;
@@ -452,7 +553,7 @@ out1:
/* Restore pages to secure pool */
list_for_each_entry_safe(page, tmp, &pages, lru) {
list_del(&page->lru);
- ion_page_pool_free(pool, page, false);
+ ion_page_pool_free(pool, page);
}
return 0;
out2:
@@ -692,6 +793,8 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *data)
if (ion_system_heap_create_pools(dev, heap->cached_pools))
goto err_create_cached_pools;
+ mutex_init(&heap->split_page_mutex);
+
heap->heap.debug_show = ion_system_heap_debug_show;
return &heap->heap;
diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c
index 5c0225cd4e24..9570ab520ca2 100644
--- a/drivers/staging/android/ion/ion_system_secure_heap.c
+++ b/drivers/staging/android/ion/ion_system_secure_heap.c
@@ -151,8 +151,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work)
/* buffer->heap used by free() */
buffer->heap = &secure_heap->heap;
- buffer->flags = ION_FLAG_POOL_PREFETCH;
- buffer->flags |= vmid_flags;
+ buffer->flags = vmid_flags;
ret = sys_heap->ops->allocate(sys_heap, buffer, size,
PAGE_SIZE, 0);
if (ret) {
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index 73b4d1edcaad..b3c29826834e 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -110,8 +110,6 @@ enum cp_mem_usage {
*/
#define ION_FLAG_POOL_FORCE_ALLOC (1 << 16)
-#define ION_FLAG_POOL_PREFETCH (1 << 27)
-
/**
* Deprecated! Please use the corresponding ION_FLAG_*
*/
@@ -176,7 +174,6 @@ struct ion_prefetch_regions {
struct ion_prefetch_data {
int heap_id;
unsigned long len;
- /* Is unsigned long bad? 32bit compiler vs 64 bit compiler*/
struct ion_prefetch_regions __user *regions;
unsigned int nr_regions;
};
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 899a77187bde..2a2975c352f4 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2227,7 +2227,6 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
device->con->write = pl011_early_write;
return 0;
}
-EARLYCON_DECLARE(pl011, pl011_early_console_setup);
OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
#else
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 03ebe401fff7..3a1de5c87cb4 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -576,7 +576,6 @@ static int __init arc_early_console_setup(struct earlycon_device *dev,
dev->con->write = arc_early_serial_write;
return 0;
}
-EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index b5b2f2be6be7..4d2e3e7a40bb 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/serial_core.h>
#include <linux/sizes.h>
-#include <linux/mod_devicetable.h>
#ifdef CONFIG_FIX_EARLYCON_MEM
#include <asm/fixmap.h>
@@ -37,13 +36,6 @@ static struct earlycon_device early_console_dev = {
.con = &early_con,
};
-extern struct earlycon_id __earlycon_table[];
-static const struct earlycon_id __earlycon_table_sentinel
- __used __section(__earlycon_table_end);
-
-static const struct of_device_id __earlycon_of_table_sentinel
- __used __section(__earlycon_of_table_end);
-
static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
{
void __iomem *base;
@@ -159,7 +151,7 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
- for (match = __earlycon_table; match->name[0]; match++) {
+ for (match = __earlycon_table; match < __earlycon_table_end; match++) {
size_t len = strlen(match->name);
if (strncmp(buf, match->name, len))
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index edd66bb7bd4c..670eda466438 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -19,33 +19,147 @@
# define SUPPORT_SYSRQ
#endif
+#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
-#include <linux/serial.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
-
-#include "msm_serial.h"
-
-#define UARTDM_BURST_SIZE 16 /* in bytes */
-#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
-#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
-#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
+#include <linux/wait.h>
+
+#define UART_MR1 0x0000
+
+#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
+#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
+#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
+#define UART_MR1_RX_RDY_CTL BIT(7)
+#define UART_MR1_CTS_CTL BIT(6)
+
+#define UART_MR2 0x0004
+#define UART_MR2_ERROR_MODE BIT(6)
+#define UART_MR2_BITS_PER_CHAR 0x30
+#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
+#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
+#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
+#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
+#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
+#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
+#define UART_MR2_PARITY_MODE_NONE 0x0
+#define UART_MR2_PARITY_MODE_ODD 0x1
+#define UART_MR2_PARITY_MODE_EVEN 0x2
+#define UART_MR2_PARITY_MODE_SPACE 0x3
+#define UART_MR2_PARITY_MODE 0x3
+
+#define UART_CSR 0x0008
+
+#define UART_TF 0x000C
+#define UARTDM_TF 0x0070
+
+#define UART_CR 0x0010
+#define UART_CR_CMD_NULL (0 << 4)
+#define UART_CR_CMD_RESET_RX (1 << 4)
+#define UART_CR_CMD_RESET_TX (2 << 4)
+#define UART_CR_CMD_RESET_ERR (3 << 4)
+#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
+#define UART_CR_CMD_START_BREAK (5 << 4)
+#define UART_CR_CMD_STOP_BREAK (6 << 4)
+#define UART_CR_CMD_RESET_CTS (7 << 4)
+#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
+#define UART_CR_CMD_PACKET_MODE (9 << 4)
+#define UART_CR_CMD_MODE_RESET (12 << 4)
+#define UART_CR_CMD_SET_RFR (13 << 4)
+#define UART_CR_CMD_RESET_RFR (14 << 4)
+#define UART_CR_CMD_PROTECTION_EN (16 << 4)
+#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
+#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
+#define UART_CR_CMD_FORCE_STALE (4 << 8)
+#define UART_CR_CMD_RESET_TX_READY (3 << 8)
+#define UART_CR_TX_DISABLE BIT(3)
+#define UART_CR_TX_ENABLE BIT(2)
+#define UART_CR_RX_DISABLE BIT(1)
+#define UART_CR_RX_ENABLE BIT(0)
+#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
+
+#define UART_IMR 0x0014
+#define UART_IMR_TXLEV BIT(0)
+#define UART_IMR_RXSTALE BIT(3)
+#define UART_IMR_RXLEV BIT(4)
+#define UART_IMR_DELTA_CTS BIT(5)
+#define UART_IMR_CURRENT_CTS BIT(6)
+#define UART_IMR_RXBREAK_START BIT(10)
+
+#define UART_IPR_RXSTALE_LAST 0x20
+#define UART_IPR_STALE_LSB 0x1F
+#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
+
+#define UART_IPR 0x0018
+#define UART_TFWR 0x001C
+#define UART_RFWR 0x0020
+#define UART_HCR 0x0024
+
+#define UART_MREG 0x0028
+#define UART_NREG 0x002C
+#define UART_DREG 0x0030
+#define UART_MNDREG 0x0034
+#define UART_IRDA 0x0038
+#define UART_MISR_MODE 0x0040
+#define UART_MISR_RESET 0x0044
+#define UART_MISR_EXPORT 0x0048
+#define UART_MISR_VAL 0x004C
+#define UART_TEST_CTRL 0x0050
+
+#define UART_SR 0x0008
+#define UART_SR_HUNT_CHAR BIT(7)
+#define UART_SR_RX_BREAK BIT(6)
+#define UART_SR_PAR_FRAME_ERR BIT(5)
+#define UART_SR_OVERRUN BIT(4)
+#define UART_SR_TX_EMPTY BIT(3)
+#define UART_SR_TX_READY BIT(2)
+#define UART_SR_RX_FULL BIT(1)
+#define UART_SR_RX_READY BIT(0)
+
+#define UART_RF 0x000C
+#define UARTDM_RF 0x0070
+#define UART_MISR 0x0010
+#define UART_ISR 0x0014
+#define UART_ISR_TX_READY BIT(7)
+
+#define UARTDM_RXFS 0x50
+#define UARTDM_RXFS_BUF_SHIFT 0x7
+#define UARTDM_RXFS_BUF_MASK 0x7
+
+#define UARTDM_DMEN 0x3C
+#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
+#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
+
+#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
+#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
+
+#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
+#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
+
+#define UARTDM_DMRX 0x34
+#define UARTDM_NCF_TX 0x40
+#define UARTDM_RX_TOTAL_SNAP 0x38
+
+#define UARTDM_BURST_SIZE 16 /* in bytes */
+#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
+#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
+#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
enum {
UARTDM_1P1 = 1,
@@ -78,10 +192,65 @@ struct msm_port {
struct msm_dma rx_dma;
};
+#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart)
+
+static
+void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
+{
+ writel_relaxed(val, port->membase + off);
+}
+
+static
+unsigned int msm_read(struct uart_port *port, unsigned int off)
+{
+ return readl_relaxed(port->membase + off);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock.
+ */
+static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
+{
+ msm_write(port, 0x06, UART_MREG);
+ msm_write(port, 0xF1, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x1A, UART_MNDREG);
+ port->uartclk = 1843200;
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock divided by 4.
+ */
+static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
+{
+ msm_write(port, 0x18, UART_MREG);
+ msm_write(port, 0xF6, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x0A, UART_MNDREG);
+ port->uartclk = 1843200;
+}
+
+static void msm_serial_set_mnd_regs(struct uart_port *port)
+{
+ struct msm_port *msm_port = UART_TO_MSM(port);
+
+ /*
+ * These registers don't exist so we change the clk input rate
+ * on uartdm hardware instead
+ */
+ if (msm_port->is_uartdm)
+ return;
+
+ if (port->uartclk == 19200000)
+ msm_serial_set_mnd_regs_tcxo(port);
+ else if (port->uartclk == 4800000)
+ msm_serial_set_mnd_regs_tcxoby4(port);
+}
+
static void msm_handle_tx(struct uart_port *port);
static void msm_start_rx_dma(struct msm_port *msm_port);
-void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
+static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
{
struct device *dev = port->dev;
unsigned int mapped;
@@ -388,10 +557,6 @@ static void msm_complete_rx_dma(void *args)
val &= ~dma->enable_bit;
msm_write(port, val, UARTDM_DMEN);
- /* Restore interrupts */
- msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
- msm_write(port, msm_port->imr, UART_IMR);
-
if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
port->icount.overrun++;
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
@@ -726,7 +891,7 @@ static void msm_handle_tx(struct uart_port *port)
return;
}
- pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_min = 1; /* Always DMA */
@@ -861,37 +1026,72 @@ struct msm_baud_map {
};
static const struct msm_baud_map *
-msm_find_best_baud(struct uart_port *port, unsigned int baud)
+msm_find_best_baud(struct uart_port *port, unsigned int baud,
+ unsigned long *rate)
{
- unsigned int i, divisor;
- const struct msm_baud_map *entry;
+ struct msm_port *msm_port = UART_TO_MSM(port);
+ unsigned int divisor, result;
+ unsigned long target, old, best_rate = 0, diff, best_diff = ULONG_MAX;
+ const struct msm_baud_map *entry, *end, *best;
static const struct msm_baud_map table[] = {
- { 1536, 0x00, 1 },
- { 768, 0x11, 1 },
- { 384, 0x22, 1 },
- { 192, 0x33, 1 },
- { 96, 0x44, 1 },
- { 48, 0x55, 1 },
- { 32, 0x66, 1 },
- { 24, 0x77, 1 },
- { 16, 0x88, 1 },
- { 12, 0x99, 6 },
- { 8, 0xaa, 6 },
- { 6, 0xbb, 6 },
- { 4, 0xcc, 6 },
- { 3, 0xdd, 8 },
- { 2, 0xee, 16 },
{ 1, 0xff, 31 },
- { 0, 0xff, 31 },
+ { 2, 0xee, 16 },
+ { 3, 0xdd, 8 },
+ { 4, 0xcc, 6 },
+ { 6, 0xbb, 6 },
+ { 8, 0xaa, 6 },
+ { 12, 0x99, 6 },
+ { 16, 0x88, 1 },
+ { 24, 0x77, 1 },
+ { 32, 0x66, 1 },
+ { 48, 0x55, 1 },
+ { 96, 0x44, 1 },
+ { 192, 0x33, 1 },
+ { 384, 0x22, 1 },
+ { 768, 0x11, 1 },
+ { 1536, 0x00, 1 },
};
- divisor = uart_get_divisor(port, baud);
+ best = table; /* Default to smallest divider */
+ target = clk_round_rate(msm_port->clk, 16 * baud);
+ divisor = DIV_ROUND_CLOSEST(target, 16 * baud);
+
+ end = table + ARRAY_SIZE(table);
+ entry = table;
+ while (entry < end) {
+ if (entry->divisor <= divisor) {
+ result = target / entry->divisor / 16;
+ diff = abs(result - baud);
+
+ /* Keep track of best entry */
+ if (diff < best_diff) {
+ best_diff = diff;
+ best = entry;
+ best_rate = target;
+ }
- for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++)
- if (entry->divisor <= divisor)
- break;
+ if (result == baud)
+ break;
+ } else if (entry->divisor > divisor) {
+ old = target;
+ target = clk_round_rate(msm_port->clk, old + 1);
+ /*
+ * The rate didn't get any faster so we can't do
+ * better at dividing it down
+ */
+ if (target == old)
+ break;
- return entry; /* Default to smallest divider */
+ /* Start the divisor search over at this new rate */
+ entry = table;
+ divisor = DIV_ROUND_CLOSEST(target, 16 * baud);
+ continue;
+ }
+ entry++;
+ }
+
+ *rate = best_rate;
+ return best;
}
static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
@@ -900,22 +1100,20 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
unsigned int rxstale, watermark, mask;
struct msm_port *msm_port = UART_TO_MSM(port);
const struct msm_baud_map *entry;
- unsigned long flags;
-
- entry = msm_find_best_baud(port, baud);
-
- msm_write(port, entry->code, UART_CSR);
-
- if (baud > 460800)
- port->uartclk = baud * 16;
+ unsigned long flags, rate;
flags = *saved_flags;
spin_unlock_irqrestore(&port->lock, flags);
- clk_set_rate(msm_port->clk, port->uartclk);
+ entry = msm_find_best_baud(port, baud, &rate);
+ clk_set_rate(msm_port->clk, rate);
+ baud = rate / 16 / entry->divisor;
spin_lock_irqsave(&port->lock, flags);
*saved_flags = flags;
+ port->uartclk = rate;
+
+ msm_write(port, entry->code, UART_CSR);
/* RX stale watermark */
rxstale = entry->rxstale;
@@ -1480,7 +1678,6 @@ msm_serial_early_console_setup(struct earlycon_device *device, const char *opt)
device->con->write = msm_serial_early_write;
return 0;
}
-EARLYCON_DECLARE(msm_serial, msm_serial_early_console_setup);
OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart",
msm_serial_early_console_setup);
@@ -1502,7 +1699,6 @@ msm_serial_early_console_setup_dm(struct earlycon_device *device,
device->con->write = msm_serial_early_write_dm;
return 0;
}
-EARLYCON_DECLARE(msm_serial_dm, msm_serial_early_console_setup_dm);
OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm",
msm_serial_early_console_setup_dm);
@@ -1581,8 +1777,6 @@ static int msm_serial_probe(struct platform_device *pdev)
msm_port->pclk = devm_clk_get(&pdev->dev, "iface");
if (IS_ERR(msm_port->pclk))
return PTR_ERR(msm_port->pclk);
-
- clk_set_rate(msm_port->clk, 1843200);
}
port->uartclk = clk_get_rate(msm_port->clk);
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
deleted file mode 100644
index dfdf73707e9d..000000000000
--- a/drivers/tty/serial/msm_serial.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 __DRIVERS_SERIAL_MSM_SERIAL_H
-#define __DRIVERS_SERIAL_MSM_SERIAL_H
-
-#define UART_MR1 0x0000
-
-#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
-#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
-#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
-#define UART_MR1_RX_RDY_CTL BIT(7)
-#define UART_MR1_CTS_CTL BIT(6)
-
-#define UART_MR2 0x0004
-#define UART_MR2_ERROR_MODE BIT(6)
-#define UART_MR2_BITS_PER_CHAR 0x30
-#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
-#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
-#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
-#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
-#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
-#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
-#define UART_MR2_PARITY_MODE_NONE 0x0
-#define UART_MR2_PARITY_MODE_ODD 0x1
-#define UART_MR2_PARITY_MODE_EVEN 0x2
-#define UART_MR2_PARITY_MODE_SPACE 0x3
-#define UART_MR2_PARITY_MODE 0x3
-
-#define UART_CSR 0x0008
-
-#define UART_TF 0x000C
-#define UARTDM_TF 0x0070
-
-#define UART_CR 0x0010
-#define UART_CR_CMD_NULL (0 << 4)
-#define UART_CR_CMD_RESET_RX (1 << 4)
-#define UART_CR_CMD_RESET_TX (2 << 4)
-#define UART_CR_CMD_RESET_ERR (3 << 4)
-#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
-#define UART_CR_CMD_START_BREAK (5 << 4)
-#define UART_CR_CMD_STOP_BREAK (6 << 4)
-#define UART_CR_CMD_RESET_CTS (7 << 4)
-#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
-#define UART_CR_CMD_PACKET_MODE (9 << 4)
-#define UART_CR_CMD_MODE_RESET (12 << 4)
-#define UART_CR_CMD_SET_RFR (13 << 4)
-#define UART_CR_CMD_RESET_RFR (14 << 4)
-#define UART_CR_CMD_PROTECTION_EN (16 << 4)
-#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
-#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
-#define UART_CR_CMD_FORCE_STALE (4 << 8)
-#define UART_CR_CMD_RESET_TX_READY (3 << 8)
-#define UART_CR_TX_DISABLE BIT(3)
-#define UART_CR_TX_ENABLE BIT(2)
-#define UART_CR_RX_DISABLE BIT(1)
-#define UART_CR_RX_ENABLE BIT(0)
-#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
-
-#define UART_IMR 0x0014
-#define UART_IMR_TXLEV BIT(0)
-#define UART_IMR_RXSTALE BIT(3)
-#define UART_IMR_RXLEV BIT(4)
-#define UART_IMR_DELTA_CTS BIT(5)
-#define UART_IMR_CURRENT_CTS BIT(6)
-#define UART_IMR_RXBREAK_START BIT(10)
-
-#define UART_IPR_RXSTALE_LAST 0x20
-#define UART_IPR_STALE_LSB 0x1F
-#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
-#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
-
-#define UART_IPR 0x0018
-#define UART_TFWR 0x001C
-#define UART_RFWR 0x0020
-#define UART_HCR 0x0024
-
-#define UART_MREG 0x0028
-#define UART_NREG 0x002C
-#define UART_DREG 0x0030
-#define UART_MNDREG 0x0034
-#define UART_IRDA 0x0038
-#define UART_MISR_MODE 0x0040
-#define UART_MISR_RESET 0x0044
-#define UART_MISR_EXPORT 0x0048
-#define UART_MISR_VAL 0x004C
-#define UART_TEST_CTRL 0x0050
-
-#define UART_SR 0x0008
-#define UART_SR_HUNT_CHAR BIT(7)
-#define UART_SR_RX_BREAK BIT(6)
-#define UART_SR_PAR_FRAME_ERR BIT(5)
-#define UART_SR_OVERRUN BIT(4)
-#define UART_SR_TX_EMPTY BIT(3)
-#define UART_SR_TX_READY BIT(2)
-#define UART_SR_RX_FULL BIT(1)
-#define UART_SR_RX_READY BIT(0)
-
-#define UART_RF 0x000C
-#define UARTDM_RF 0x0070
-#define UART_MISR 0x0010
-#define UART_ISR 0x0014
-#define UART_ISR_TX_READY BIT(7)
-
-#define UARTDM_RXFS 0x50
-#define UARTDM_RXFS_BUF_SHIFT 0x7
-#define UARTDM_RXFS_BUF_MASK 0x7
-
-#define UARTDM_DMEN 0x3C
-#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
-#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
-
-#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
-#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
-
-#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
-#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
-
-#define UARTDM_DMRX 0x34
-#define UARTDM_NCF_TX 0x40
-#define UARTDM_RX_TOTAL_SNAP 0x38
-
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline
-void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
-{
- writel_relaxed_no_log(val, port->membase + off);
-}
-
-static inline
-unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
- return readl_relaxed_no_log(port->membase + off);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock.
- */
-static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
-{
- msm_write(port, 0x06, UART_MREG);
- msm_write(port, 0xF1, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x1A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-/*
- * Setup the MND registers to use the TCXO clock divided by 4.
- */
-static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
-{
- msm_write(port, 0x18, UART_MREG);
- msm_write(port, 0xF6, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x0A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-static inline
-void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
-{
- if (port->uartclk == 19200000)
- msm_serial_set_mnd_regs_tcxo(port);
- else if (port->uartclk == 4800000)
- msm_serial_set_mnd_regs_tcxoby4(port);
-}
-
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-
-#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index d72cd736bdc6..fd9c47f2f29f 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -2451,7 +2451,6 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device,
}
OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
s3c2410_early_console_setup);
-EARLYCON_DECLARE(s3c2410, s3c2410_early_console_setup);
/* S3C2412, S3C2440, S3C64xx */
static struct samsung_early_console_data s3c2440_early_console_data = {
@@ -2470,9 +2469,6 @@ OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
s3c2440_early_console_setup);
OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c2412, s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c2440, s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c6400, s3c2440_early_console_setup);
/* S5PV210, EXYNOS */
static struct samsung_early_console_data s5pv210_early_console_data = {
@@ -2489,8 +2485,6 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
s5pv210_early_console_setup);
-EARLYCON_DECLARE(s5pv210, s5pv210_early_console_setup);
-EARLYCON_DECLARE(exynos4210, s5pv210_early_console_setup);
#endif
MODULE_ALIAS("platform:samsung-uart");
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 9dbae01d41ce..9ae182a54784 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -624,8 +624,6 @@ static int __init sprd_early_console_setup(
device->con->write = sprd_early_write;
return 0;
}
-
-EARLYCON_DECLARE(sprd_serial, sprd_early_console_setup);
OF_EARLYCON_DECLARE(sprd_serial, "sprd,sc9836-uart",
sprd_early_console_setup);
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 0ac5ef4f750c..e0dd3f5d5635 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -42,43 +42,6 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* uA units */
-static char edid_buf1[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x22, 0xf0, 0x52, 0x29, 0x01, 0x01, 0x01, 0x01,
- 0x16, 0x16, 0x01, 0x03, 0x80, 0x30, 0x1b, 0x78,
- 0x2e, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26,
- 0x0f, 0x50, 0x54, 0xa1, 0x08, 0x00, 0xd1, 0xc0,
- 0x81, 0xc0, 0xa9, 0xc0, 0xb3, 0x00, 0x95, 0x00,
- 0x81, 0x40, 0x81, 0x80, 0x01, 0x01, 0x02, 0x3a,
- 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
- 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e,
- 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 0x4c, 0x18,
- 0x5e, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
- 0x50, 0x20, 0x5a, 0x52, 0x32, 0x32, 0x34, 0x30,
- 0x77, 0x0a, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x43, 0x4e, 0x34, 0x32, 0x32, 0x32, 0x30,
- 0x30, 0x33, 0x46, 0x0a, 0x20, 0x20, 0x01, 0xb1,
-
- 0x02, 0x03, 0x17, 0xb1, 0x4c, 0x90, 0x1f, 0x05,
- 0x14, 0x04, 0x13, 0x03, 0x02, 0x07, 0x06, 0x12,
- 0x01, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x02,
- 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58,
- 0x2c, 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00,
- 0x1e, 0x02, 0x3a, 0x80, 0xd0, 0x72, 0x38, 0x2d,
- 0x40, 0x10, 0x2c, 0x45, 0x80, 0xdb, 0x0b, 0x11,
- 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0x72, 0x51,
- 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xdb,
- 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00,
- 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28, 0x55,
- 0x40, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x8c,
- 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10,
- 0x3e, 0x96, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b
-};
-
-
static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -945,9 +908,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
pr_err("Unabled to start core clocks\n");
return ret;
}
- mdss_dp_phy_reset(&dp_drv->ctrl_io);
- mdss_dp_aux_reset(&dp_drv->ctrl_io);
- mdss_dp_aux_ctrl(&dp_drv->ctrl_io, true);
mdss_dp_hpd_configure(&dp_drv->ctrl_io, true);
orientation = usbpd_get_plug_orientation(dp_drv->pd);
@@ -971,11 +931,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
dp_init_panel_info(dp_drv, dp_drv->new_vic);
- mdss_dp_phy_aux_setup(&dp_drv->phy_io);
-
- mdss_dp_irq_enable(dp_drv);
- pr_debug("irq enabled\n");
- mdss_dp_dpcd_cap_read(dp_drv);
dp_drv->link_rate =
mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info,
dp_drv->dpcd.max_lane_count);
@@ -1143,9 +1098,10 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
return -ENODEV;
}
- /* Use the existing EDID buffer for 1080p */
- memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1));
dp_drv->panel_data.panel_info.edid_data = edid_data;
+ /* initialize EDID buffer pointers */
+ dp_drv->edid_buf = edid_init_data.buf;
+ dp_drv->edid_buf_size = edid_init_data.buf_size;
return 0;
}
@@ -1189,17 +1145,30 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io),
mdss_dp_get_phy_hw_version(&dp_drv->phy_io));
+ mdss_dp_phy_aux_setup(&dp_drv->phy_io);
+
+ mdss_dp_irq_enable(dp_drv);
+ pr_debug("irq enabled\n");
+ mdss_dp_dpcd_cap_read(dp_drv);
+
+ ret = mdss_dp_edid_read(dp_drv);
+ if (ret)
+ goto edid_error;
+
+ pr_debug("edid_read success. buf_size=%d\n",
+ dp_drv->edid_buf_size);
+
ret = hdmi_edid_parser(dp_drv->panel_data.panel_info.edid_data);
if (ret) {
DEV_ERR("%s: edid parse failed\n", __func__);
- goto edid_parser_error;
+ goto edid_error;
}
mdss_dp_send_cable_notification(dp_drv, true);
return ret;
-edid_parser_error:
+edid_error:
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
clk_error:
mdss_dp_regulator_ctrl(dp_drv, false);
@@ -1422,7 +1391,7 @@ static void mdss_dp_event_work(struct work_struct *work)
switch (todo) {
case EV_EDID_READ:
- mdss_dp_edid_read(dp, 0);
+ mdss_dp_edid_read(dp);
break;
case EV_DPCD_CAP_READ:
mdss_dp_dpcd_cap_read(dp);
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 03646cd7cc65..a8bb2ab5d343 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -378,6 +378,8 @@ struct mdss_dp_drv_pdata {
char train_link_rate; /* X 27000000 for real rate */
char train_lane_cnt;
+ u8 *edid_buf;
+ u32 edid_buf_size;
struct edp_edid edid;
struct dpcd_cap dpcd;
@@ -464,7 +466,7 @@ void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *dp);
-void mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp, int block);
+int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp);
int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp);
void dp_aux_i2c_handler(struct mdss_dp_drv_pdata *dp, u32 isr);
void dp_aux_native_handler(struct mdss_dp_drv_pdata *dp, u32 isr);
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index 7b14a7efb9dc..dfba02871649 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -665,7 +665,7 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
char data = 0;
for (cnt = 5; cnt; cnt--) {
- ret = dp_aux_write_buf(ep, 0x50, &data, 1, 1);
+ ret = dp_aux_write_buf(ep, EDID_START_ADDRESS, &data, 1, 1);
pr_debug("ret=%d\n", ret);
if (ret >= 0)
break;
@@ -680,43 +680,85 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
return 0;
}
-static int dp_sink_edid_read(struct mdss_dp_drv_pdata *ep, int block)
+int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp)
{
struct edp_buf *rp;
int cnt, rlen;
int ret = 0;
+ int blk_num = 0;
- ret = dp_aux_chan_ready(ep);
+ ret = dp_aux_chan_ready(dp);
if (ret) {
pr_err("aux chan NOT ready\n");
return ret;
}
for (cnt = 5; cnt; cnt--) {
- rlen = dp_aux_read_buf(ep, 0x50, 128, 1);
+ rlen = dp_aux_read_buf
+ (dp, EDID_START_ADDRESS, EDID_BLOCK_SIZE, 1);
if (rlen > 0) {
- pr_debug("rlen=%d\n", rlen);
+ pr_debug("cnt=%d, block=%d, rlen=%d\n",
+ cnt, blk_num, rlen);
- rp = &ep->rxp;
+ rp = &dp->rxp;
if (!dp_edid_buf_error(rp->data, rp->len))
break;
}
}
- if (cnt <= 0) {
- pr_err("Failed\n");
+ if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) {
+ pr_err("Read failed. rlen=%d\n", rlen);
return -EINVAL;
}
- dp_extract_edid_manufacturer(&ep->edid, rp->data);
- dp_extract_edid_product(&ep->edid, rp->data);
- dp_extract_edid_version(&ep->edid, rp->data);
- dp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
- dp_extract_edid_video_support(&ep->edid, rp->data);
- dp_extract_edid_feature(&ep->edid, rp->data);
- dp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
+ rp = &dp->rxp;
+
+ dp_extract_edid_manufacturer(&dp->edid, rp->data);
+ dp_extract_edid_product(&dp->edid, rp->data);
+ dp_extract_edid_version(&dp->edid, rp->data);
+ dp_extract_edid_ext_block_cnt(&dp->edid, rp->data);
+ dp_extract_edid_video_support(&dp->edid, rp->data);
+ dp_extract_edid_feature(&dp->edid, rp->data);
+ dp_extract_edid_detailed_timing_description(&dp->edid, rp->data);
+ /* for the first block initialize the edid buffer size */
+ dp->edid_buf_size = 0;
+
+ pr_debug("edid extension = %d\n",
+ dp->edid.ext_block_cnt);
+
+ memcpy(dp->edid_buf, rp->data, EDID_BLOCK_SIZE);
+ dp->edid_buf_size += EDID_BLOCK_SIZE;
+
+ if (!dp->edid.ext_block_cnt)
+ return 0;
- return 128;
+ for (blk_num = 1; blk_num <= dp->edid.ext_block_cnt;
+ blk_num++) {
+ for (cnt = 5; cnt; cnt--) {
+ rlen = dp_aux_read_buf
+ (dp, EDID_START_ADDRESS +
+ (blk_num * EDID_BLOCK_SIZE),
+ EDID_BLOCK_SIZE, 1);
+ if (rlen > 0) {
+ pr_debug("cnt=%d, blk_num=%d, rlen=%d\n",
+ cnt, blk_num, rlen);
+ rp = &dp->rxp;
+ if (!dp_edid_buf_error(rp->data, rp->len))
+ break;
+ }
+ }
+
+ if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) {
+ pr_err("Read failed. rlen=%d\n", rlen);
+ return -EINVAL;
+ }
+
+ memcpy(dp->edid_buf + (blk_num * EDID_BLOCK_SIZE),
+ rp->data, EDID_BLOCK_SIZE);
+ dp->edid_buf_size += EDID_BLOCK_SIZE;
+ }
+
+ return 0;
}
static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
@@ -1357,11 +1399,6 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep)
}
-void mdss_dp_edid_read(struct mdss_dp_drv_pdata *ep, int block)
-{
- dp_sink_edid_read(ep, block);
-}
-
int mdss_dp_link_train(struct mdss_dp_drv_pdata *ep)
{
int ret;
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index 8ef00dd7248e..2079dba2a357 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -86,6 +86,7 @@
#define TXn_TX_DRV_LVL 0x001C
#define TCSR_USB3_DP_PHYMODE 0x48
+#define EDID_START_ADDRESS 0x50
struct lane_mapping {
char lane0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 518b84fbad51..73af16ca6ed4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1947,7 +1947,6 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
mdss_mdp_init_default_prefill_factors(mdata);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT);
- mdss_set_quirk(mdata, MDSS_QUIRK_SRC_SPLIT_ALWAYS);
mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 3a39d4fdc895..600701041309 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -347,10 +347,7 @@ static void __update_avr_info(struct mdss_mdp_ctl *ctl,
*/
static bool __layer_needs_src_split(struct mdp_input_layer *layer)
{
- struct mdss_data_type *mdata = mdss_mdp_get_mdata();
-
- return (layer->flags & MDP_LAYER_ASYNC) ||
- mdss_has_quirk(mdata, MDSS_QUIRK_SRC_SPLIT_ALWAYS);
+ return (layer->flags & MDP_LAYER_ASYNC);
}
static int __async_update_position_check(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index bcb4867b4ffd..8cfb8e46777c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2690,6 +2690,16 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (pipe->scaler.enable)
mdss_mdp_pipe_program_pixel_extn(pipe);
+
+ ret = mdss_mdp_pipe_pp_setup(pipe, &opmode);
+ if (ret) {
+ pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
+
+ MDSS_XLOG(pipe->num, pipe->mixer_left->num,
+ pipe->play_cnt, 0xbad);
+
+ goto done;
+ }
}
if ((!(pipe->flags & MDP_VPU_PIPE) && (src_data == NULL)) ||
@@ -2708,12 +2718,6 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (params_changed) {
pipe->params_changed = 0;
- ret = mdss_mdp_pipe_pp_setup(pipe, &opmode);
- if (ret) {
- pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
- goto done;
- }
-
ret = mdss_mdp_image_setup(pipe, src_data);
if (ret) {
pr_err("image setup error for pnum=%d\n", pipe->num);
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index 5474df66eefb..a21242870a35 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -360,10 +360,13 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
ext_disp->current_disp = data->type;
} else if ((state == EXT_DISPLAY_CABLE_DISCONNECT) &&
!ext_disp->ack_enabled) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
+ if (ext_disp->ops) {
+ ext_disp->ops->audio_info_setup = NULL;
+ ext_disp->ops->get_audio_edid_blk = NULL;
+ ext_disp->ops->cable_status = NULL;
+ ext_disp->ops->get_intf_id = NULL;
+ }
+
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
@@ -451,7 +454,7 @@ static int msm_ext_disp_notify(struct platform_device *pdev,
if (ret)
goto end;
- if (new_state == EXT_DISPLAY_CABLE_CONNECT) {
+ if (new_state == EXT_DISPLAY_CABLE_CONNECT && ext_disp->ops) {
ext_disp->ops->audio_info_setup =
data->codec_ops.audio_info_setup;
ext_disp->ops->get_audio_edid_blk =
@@ -524,10 +527,13 @@ static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
* empty.
*/
if (!ack_hpd) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
+ if (ext_disp->ops) {
+ ext_disp->ops->audio_info_setup = NULL;
+ ext_disp->ops->get_audio_edid_blk = NULL;
+ ext_disp->ops->cable_status = NULL;
+ ext_disp->ops->get_intf_id = NULL;
+ }
+
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 772c784ba763..8f5a12ab2f2b 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -157,7 +157,7 @@
#define EARLYCON_TABLE() STRUCT_ALIGN(); \
VMLINUX_SYMBOL(__earlycon_table) = .; \
*(__earlycon_table) \
- *(__earlycon_table_end)
+ VMLINUX_SYMBOL(__earlycon_table_end) = .;
#else
#define EARLYCON_TABLE()
#endif
@@ -179,7 +179,6 @@
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
#define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
-#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
#ifdef CONFIG_ACPI
#define ACPI_PROBE_TABLE(name) \
@@ -527,8 +526,7 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(clksrc) \
- EARLYCON_TABLE() \
- EARLYCON_OF_TABLES()
+ EARLYCON_TABLE()
#define INIT_TEXT \
*(.init.text) \
diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h
index 28efd55ea8f6..85e28a9edc03 100644
--- a/include/dt-bindings/clock/msm-clocks-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-cobalt.h
@@ -484,10 +484,6 @@
#define clk_gpu_pll0_pll_out_even 0xb0ed5009
#define clk_gpu_pll0_pll_out_odd 0x08c5a8a5
#define clk_gpu_pll0_postdiv_clk 0x76c19f3c
-#define clk_gpu_pll1_pll 0x09ac81ef
-#define clk_gpu_pll1_pll_out_even 0xa503de04
-#define clk_gpu_pll1_pll_out_odd 0x1c205dfb
-#define clk_gpu_pll1_postdiv_clk 0xdf546700
#define clk_gpucc_mx_clk 0x1edbb879
#define clk_gpucc_gcc_dbg_clk 0x9ae8cd3c
#define clk_gfxcc_dbg_clk 0x3ed47625
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
index 7ef57256d8f0..6f0e35511cc9 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
@@ -235,8 +235,6 @@
#define GPUCC_GPU_PLL0_PLL_MODE 0x00000
#define GPUCC_GPU_PLL0_USER_CTL_MODE 0x0000C
-#define GPUCC_GPU_PLL1_PLL_MODE 0x00040
-#define GPUCC_GPU_PLL1_USER_CTL_MODE 0x0004C
#define GPUCC_GFX3D_CMD_RCGR 0x01070
#define GPUCC_RBBMTIMER_CMD_RCGR 0x010B0
#define GPUCC_GFX3D_ISENSE_CMD_RCGR 0x01100
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 0afc11f8f300..b2c1ea2a4739 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -342,22 +342,26 @@ struct earlycon_device {
struct earlycon_id {
char name[16];
+ char compatible[128];
int (*setup)(struct earlycon_device *, const char *options);
} __aligned(32);
+extern const struct earlycon_id __earlycon_table[];
+extern const struct earlycon_id __earlycon_table_end[];
+
+#define OF_EARLYCON_DECLARE(_name, compat, fn) \
+ static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
+ __used __section(__earlycon_table) \
+ = { .name = __stringify(_name), \
+ .compatible = compat, \
+ .setup = fn }
+
+#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
+
extern int setup_earlycon(char *buf);
extern int of_setup_earlycon(unsigned long addr,
int (*setup)(struct earlycon_device *, const char *));
-#define EARLYCON_DECLARE(_name, func) \
- static const struct earlycon_id __earlycon_##_name \
- __used __section(__earlycon_table) \
- = { .name = __stringify(_name), \
- .setup = func }
-
-#define OF_EARLYCON_DECLARE(name, compat, fn) \
- _OF_DECLARE(earlycon, name, compat, fn, void *)
-
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c);
int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 6275e4536bc0..62f1ff65f273 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -106,5 +106,8 @@ extern int icnss_set_fw_debug_mode(bool enable_fw_log);
extern int icnss_get_irq(int ce_id);
extern int icnss_power_on(struct device *dev);
extern int icnss_power_off(struct device *dev);
+extern struct dma_iommu_mapping *icnss_smmu_get_mapping(struct device *dev);
+extern int icnss_smmu_map(struct device *dev, phys_addr_t paddr,
+ uint32_t *iova_addr, size_t size);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/soc/qcom/service-locator.h b/include/soc/qcom/service-locator.h
index 6bf8ac0be15f..7fa25b90fc12 100644
--- a/include/soc/qcom/service-locator.h
+++ b/include/soc/qcom/service-locator.h
@@ -80,7 +80,7 @@ int find_subsys(const char *pd_path, char *subsys);
#else
static inline int get_service_location(char *client_name,
- char *service_name, struct notifier_block *locator_nb);
+ char *service_name, struct notifier_block *locator_nb)
{
return -ENODEV;
}
diff --git a/include/soc/qcom/service-notifier.h b/include/soc/qcom/service-notifier.h
index be3f134eebe3..90fceba091b9 100644
--- a/include/soc/qcom/service-notifier.h
+++ b/include/soc/qcom/service-notifier.h
@@ -53,7 +53,7 @@ static void *service_notif_register_notifier(const char *service_path,
int instance_id, struct notifier_block *nb,
int *curr_state)
{
- return -ENODEV;
+ return PTR_ERR(-ENODEV);
}
static int service_notif_unregister_notifier(void *service_notif_handle,
diff --git a/include/soc/qcom/smem.h b/include/soc/qcom/smem.h
index 79bcc1b31cf8..c3e9c474ea8b 100644
--- a/include/soc/qcom/smem.h
+++ b/include/soc/qcom/smem.h
@@ -92,15 +92,8 @@ enum {
SMEM_KEYPAD_STATE_UPDATED,
SMEM_KEYPAD_STATE_IDX,
SMEM_GPIO_INT,
- SMEM_MDDI_LCD_IDX,
- SMEM_MDDI_HOST_DRIVER_STATE,
- SMEM_MDDI_LCD_DISP_STATE,
- SMEM_LCD_CUR_PANEL,
- SMEM_MARM_BOOT_SEGMENT_INFO,
- SMEM_AARM_BOOT_SEGMENT_INFO,
- SMEM_SLEEP_STATIC,
- SMEM_SCORPION_FREQUENCY,
- SMEM_SMD_PROFILES,
+ SMEM_SMP2P_CDSP_BASE,
+ SMEM_SMD_PROFILES = SMEM_SMP2P_CDSP_BASE + 8,
SMEM_TSSC_BUSY,
SMEM_HS_SUSPEND_FILTER_INFO,
SMEM_BATT_INFO,
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index a80278954a77..aac11dbe5984 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -121,6 +121,11 @@
#define KGSL_MEMFLAGS_GPUWRITEONLY 0x02000000U
#define KGSL_MEMFLAGS_FORCE_32BIT 0x100000000ULL
+/* Flag for binding all the virt range to single phys data */
+#define KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS 0x400000000ULL
+#define KGSL_SPARSE_BIND 0x1ULL
+#define KGSL_SPARSE_UNBIND 0x2ULL
+
/* Memory caching hints */
#define KGSL_CACHEMODE_MASK 0x0C000000U
#define KGSL_CACHEMODE_SHIFT 26
@@ -131,6 +136,8 @@
#define KGSL_CACHEMODE_WRITEBACK 3
#define KGSL_MEMFLAGS_USE_CPU_MAP 0x10000000ULL
+#define KGSL_MEMFLAGS_SPARSE_PHYS 0x20000000ULL
+#define KGSL_MEMFLAGS_SPARSE_VIRT 0x40000000ULL
/* Memory types for which allocations are made */
#define KGSL_MEMTYPE_MASK 0x0000FF00
@@ -1457,4 +1464,96 @@ struct kgsl_gpuobj_set_info {
#define IOCTL_KGSL_GPUOBJ_SET_INFO \
_IOW(KGSL_IOC_TYPE, 0x4C, struct kgsl_gpuobj_set_info)
+/**
+ * struct kgsl_sparse_phys_alloc - Argument for IOCTL_KGSL_SPARSE_PHYS_ALLOC
+ * @size: Size in bytes to back
+ * @pagesize: Pagesize alignment required
+ * @flags: Flags for this allocation
+ * @id: Returned ID for this allocation
+ */
+struct kgsl_sparse_phys_alloc {
+ uint64_t size;
+ uint64_t pagesize;
+ uint64_t flags;
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_PHYS_ALLOC \
+ _IOWR(KGSL_IOC_TYPE, 0x50, struct kgsl_sparse_phys_alloc)
+
+/**
+ * struct kgsl_sparse_phys_free - Argument for IOCTL_KGSL_SPARSE_PHYS_FREE
+ * @id: ID to free
+ */
+struct kgsl_sparse_phys_free {
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_PHYS_FREE \
+ _IOW(KGSL_IOC_TYPE, 0x51, struct kgsl_sparse_phys_free)
+
+/**
+ * struct kgsl_sparse_virt_alloc - Argument for IOCTL_KGSL_SPARSE_VIRT_ALLOC
+ * @size: Size in bytes to reserve
+ * @pagesize: Pagesize alignment required
+ * @flags: Flags for this allocation
+ * @id: Returned ID for this allocation
+ * @gpuaddr: Returned GPU address for this allocation
+ */
+struct kgsl_sparse_virt_alloc {
+ uint64_t size;
+ uint64_t pagesize;
+ uint64_t flags;
+ uint64_t gpuaddr;
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_VIRT_ALLOC \
+ _IOWR(KGSL_IOC_TYPE, 0x52, struct kgsl_sparse_virt_alloc)
+
+/**
+ * struct kgsl_sparse_virt_free - Argument for IOCTL_KGSL_SPARSE_VIRT_FREE
+ * @id: ID to free
+ */
+struct kgsl_sparse_virt_free {
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_VIRT_FREE \
+ _IOW(KGSL_IOC_TYPE, 0x53, struct kgsl_sparse_virt_free)
+
+/**
+ * struct kgsl_sparse_binding_object - Argument for kgsl_sparse_bind
+ * @virtoffset: Offset into the virtual ID
+ * @physoffset: Offset into the physical ID (bind only)
+ * @size: Size in bytes to reserve
+ * @flags: Flags for this kgsl_sparse_binding_object
+ * @id: Physical ID to bind (bind only)
+ */
+struct kgsl_sparse_binding_object {
+ uint64_t virtoffset;
+ uint64_t physoffset;
+ uint64_t size;
+ uint64_t flags;
+ unsigned int id;
+};
+
+/**
+ * struct kgsl_sparse_bind - Argument for IOCTL_KGSL_SPARSE_BIND
+ * @list: List of kgsl_sparse_bind_objects to bind/unbind
+ * @id: Virtual ID to bind/unbind
+ * @size: Size of kgsl_sparse_bind_object
+ * @count: Number of elements in list
+ *
+ */
+struct kgsl_sparse_bind {
+ uint64_t __user list;
+ unsigned int id;
+ unsigned int size;
+ unsigned int count;
+};
+
+#define IOCTL_KGSL_SPARSE_BIND \
+ _IOW(KGSL_IOC_TYPE, 0x54, struct kgsl_sparse_bind)
+
#endif /* _UAPI_MSM_KGSL_H */
diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h
index 5d340b9a2523..540a96c57e5b 100644
--- a/include/uapi/media/msm_cam_sensor.h
+++ b/include/uapi/media/msm_cam_sensor.h
@@ -35,6 +35,7 @@
#define MAX_REGULATOR 5
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
+#define MSM_V4L2_PIX_FMT_META10 v4l2_fourcc('M', 'E', '1', '0') /* META10 */
#define MSM_V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4')
/* 14 BGBG.. GRGR.. */
#define MSM_V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4')
diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h
index 93613855228e..9f933dc7e84f 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -802,6 +802,7 @@ struct msm_isp_ahb_clk_cfg {
#define V4L2_PIX_FMT_NV14 v4l2_fourcc('N', 'V', '1', '4')
#define V4L2_PIX_FMT_NV41 v4l2_fourcc('N', 'V', '4', '1')
#define V4L2_PIX_FMT_META v4l2_fourcc('Q', 'M', 'E', 'T')
+#define V4L2_PIX_FMT_META10 v4l2_fourcc('Q', 'M', '1', '0')
#define V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4') /* 14 BGBG.GRGR.*/
#define V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4') /* 14 GBGB.RGRG.*/
#define V4L2_PIX_FMT_SGRBG14 v4l2_fourcc('B', 'A', '1', '4') /* 14 GRGR.BGBG.*/
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 958d79e1933c..584cd048c24b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4096,7 +4096,8 @@ static inline int migration_needed(struct task_struct *p, int cpu)
int nice;
struct related_thread_group *grp;
- if (!sched_enable_hmp || p->state != TASK_RUNNING)
+ if (!sched_enable_hmp || p->state != TASK_RUNNING ||
+ p->nr_cpus_allowed == 1)
return 0;
/* No need to migrate task that is about to be throttled */
diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c
index 16a23aa9770c..a8d6e0fa4732 100644
--- a/sound/soc/codecs/wcd9330.c
+++ b/sound/soc/codecs/wcd9330.c
@@ -8956,8 +8956,11 @@ static int tomtom_codec_probe(struct snd_soc_codec *codec)
err_pdata:
kfree(ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err_hwdep:
kfree(tomtom->fw_data);
+ tomtom->fw_data = NULL;
err_nomem_slimch:
devm_kfree(codec->dev, tomtom);
return ret;
@@ -8965,12 +8968,17 @@ err_nomem_slimch:
static int tomtom_codec_remove(struct snd_soc_codec *codec)
{
struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx *control;
WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
atomic_set(&kp_tomtom_priv, 0);
WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
+ control = dev_get_drvdata(codec->dev->parent);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
+
if (tomtom->wcd_ext_clk)
clk_put(tomtom->wcd_ext_clk);
tomtom_cleanup_irqs(tomtom);
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index e922a5a0e262..5a52b25764a4 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -13357,8 +13357,11 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
err_pdata:
devm_kfree(codec->dev, ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err_hwdep:
devm_kfree(codec->dev, tasha->fw_data);
+ tasha->fw_data = NULL;
err:
return ret;
}
@@ -13366,6 +13369,11 @@ err:
static int tasha_codec_remove(struct snd_soc_codec *codec)
{
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx *control;
+
+ control = dev_get_drvdata(codec->dev->parent);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
tasha_cleanup_irqs(tasha);
/* Cleanup MBHC */
diff --git a/sound/soc/codecs/wcd934x/wcd934x-routing.h b/sound/soc/codecs/wcd934x/wcd934x-routing.h
index 4735ef9722ed..72976a9ec0fe 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-routing.h
+++ b/sound/soc/codecs/wcd934x/wcd934x-routing.h
@@ -114,6 +114,11 @@ const struct snd_soc_dapm_route tavil_slim_audio_map[] = {
const struct snd_soc_dapm_route tavil_audio_map[] = {
+ /* VI Feedback */
+ {"AIF4_VI Mixer", "SPKR_VI_1", "VIINPUT"},
+ {"AIF4_VI Mixer", "SPKR_VI_2", "VIINPUT"},
+ {"AIF4 VI", NULL, "AIF4_VI Mixer"},
+
/* CDC Tx interface with SLIMBUS */
{"SLIM TX0", NULL, "CDC_IF TX0 MUX"},
{"SLIM TX1", NULL, "CDC_IF TX1 MUX"},
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index d7103f1ff00f..8c2387dc194b 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -122,6 +122,8 @@ static const struct snd_kcontrol_new name##_mux = \
#define CF_MIN_3DB_150HZ 0x2
enum {
+ VI_SENSE_1,
+ VI_SENSE_2,
AUDIO_NOMINAL,
HPH_PA_DELAY,
};
@@ -148,6 +150,7 @@ enum {
AIF3_PB,
AIF3_CAP,
AIF4_PB,
+ AIF4_VIFEED,
NUM_CODEC_DAIS,
};
@@ -474,6 +477,8 @@ struct tavil_priv {
struct work_struct tavil_add_child_devices_work;
struct hpf_work tx_hpf_work[WCD934X_NUM_DECIMATORS];
struct tx_mute_work tx_mute_dwork[WCD934X_NUM_DECIMATORS];
+
+ unsigned int vi_feed_value;
};
static const struct tavil_reg_mask_val tavil_spkr_default[] = {
@@ -700,6 +705,72 @@ void *tavil_get_afe_config(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL(tavil_get_afe_config);
+static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist =
+ dapm_kcontrol_get_wlist(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
+ struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = tavil_p->vi_feed_value;
+
+ return 0;
+}
+
+static int tavil_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist =
+ dapm_kcontrol_get_wlist(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
+ struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+ struct soc_multi_mixer_control *mixer =
+ ((struct soc_multi_mixer_control *)kcontrol->private_value);
+ u32 dai_id = widget->shift;
+ u32 port_id = mixer->shift;
+ u32 enable = ucontrol->value.integer.value[0];
+
+ dev_dbg(codec->dev, "%s: enable: %d, port_id:%d, dai_id: %d\n",
+ __func__, enable, port_id, dai_id);
+
+ tavil_p->vi_feed_value = ucontrol->value.integer.value[0];
+
+ mutex_lock(&tavil_p->codec_mutex);
+ if (enable) {
+ if (port_id == WCD934X_TX14 && !test_bit(VI_SENSE_1,
+ &tavil_p->status_mask)) {
+ list_add_tail(&core->tx_chs[WCD934X_TX14].list,
+ &tavil_p->dai[dai_id].wcd9xxx_ch_list);
+ set_bit(VI_SENSE_1, &tavil_p->status_mask);
+ }
+ if (port_id == WCD934X_TX15 && !test_bit(VI_SENSE_2,
+ &tavil_p->status_mask)) {
+ list_add_tail(&core->tx_chs[WCD934X_TX15].list,
+ &tavil_p->dai[dai_id].wcd9xxx_ch_list);
+ set_bit(VI_SENSE_2, &tavil_p->status_mask);
+ }
+ } else {
+ if (port_id == WCD934X_TX14 && test_bit(VI_SENSE_1,
+ &tavil_p->status_mask)) {
+ list_del_init(&core->tx_chs[WCD934X_TX14].list);
+ clear_bit(VI_SENSE_1, &tavil_p->status_mask);
+ }
+ if (port_id == WCD934X_TX15 && test_bit(VI_SENSE_2,
+ &tavil_p->status_mask)) {
+ list_del_init(&core->tx_chs[WCD934X_TX15].list);
+ clear_bit(VI_SENSE_2, &tavil_p->status_mask);
+ }
+ }
+ mutex_unlock(&tavil_p->codec_mutex);
+ snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+ return 0;
+}
+
static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1060,6 +1131,143 @@ static int tavil_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
return ret;
}
+static int tavil_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct wcd9xxx *core = NULL;
+ struct snd_soc_codec *codec = NULL;
+ struct tavil_priv *tavil_p = NULL;
+ int ret = 0;
+ struct wcd9xxx_codec_dai_data *dai = NULL;
+
+ codec = snd_soc_dapm_to_codec(w->dapm);
+ tavil_p = snd_soc_codec_get_drvdata(codec);
+ core = dev_get_drvdata(codec->dev->parent);
+
+ dev_dbg(codec->dev,
+ "%s: num_dai %d stream name %s w->name %s event %d shift %d\n",
+ __func__, codec->component.num_dai, w->sname,
+ w->name, event, w->shift);
+
+ if (w->shift != AIF4_VIFEED) {
+ pr_err("%s Error in enabling the tx path\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ dai = &tavil_p->dai[w->shift];
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
+ dev_dbg(codec->dev, "%s: spkr1 enabled\n", __func__);
+ /* Enable V&I sensing */
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x0F,
+ 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x10);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
+ 0x10);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
+ 0x00);
+ }
+ if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
+ pr_debug("%s: spkr2 enabled\n", __func__);
+ /* Enable V&I sensing */
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x0F,
+ 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x0F,
+ 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
+ 0x10);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
+ 0x10);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
+ 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
+ 0x00);
+ }
+ dai->bus_down_in_recovery = false;
+ tavil_codec_enable_slim_port_intr(dai, codec);
+ (void) tavil_codec_enable_slim_chmask(dai, true);
+ ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+ dai->rate, dai->bit_width,
+ &dai->grph);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+ dai->grph);
+ if (ret)
+ dev_err(codec->dev, "%s error in close_slim_sch_tx %d\n",
+ __func__, ret);
+ if (!dai->bus_down_in_recovery)
+ ret = tavil_codec_enable_slim_chmask(dai, false);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(core,
+ &dai->wcd9xxx_ch_list,
+ dai->grph);
+ dev_dbg(codec->dev, "%s: Disconnect TX port, ret = %d\n",
+ __func__, ret);
+ }
+ if (test_bit(VI_SENSE_1, &tavil_p->status_mask)) {
+ /* Disable V&I sensing */
+ dev_dbg(codec->dev, "%s: spkr1 disabled\n", __func__);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX10_SPKR_PROT_PATH_CTL, 0x10,
+ 0x00);
+ }
+ if (test_bit(VI_SENSE_2, &tavil_p->status_mask)) {
+ /* Disable V&I sensing */
+ dev_dbg(codec->dev, "%s: spkr2 disabled\n", __func__);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x20,
+ 0x20);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX11_SPKR_PROT_PATH_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec,
+ WCD934X_CDC_TX12_SPKR_PROT_PATH_CTL, 0x10,
+ 0x00);
+ }
+ break;
+ }
+done:
+ return ret;
+}
+
static int tavil_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -3406,6 +3614,13 @@ static const char *const cdc_if_rx7_mux_text[] = {
"SLIM RX7", "I2S_0 RX7"
};
+static const struct snd_kcontrol_new aif4_vi_mixer[] = {
+ SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
+ tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
+ SOC_SINGLE_EXT("SPKR_VI_2", SND_SOC_NOPM, WCD934X_TX15, 1, 0,
+ tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
+};
+
static const struct snd_kcontrol_new aif1_cap_mixer[] = {
SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
slim_tx_mixer_get, slim_tx_mixer_put),
@@ -4094,6 +4309,13 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
aif3_cap_mixer, ARRAY_SIZE(aif3_cap_mixer)),
+ SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
+ AIF4_VIFEED, 0, tavil_codec_enable_slimvi_feedback,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("AIF4_VI Mixer", SND_SOC_NOPM, AIF4_VIFEED, 0,
+ aif4_vi_mixer, ARRAY_SIZE(aif4_vi_mixer)),
+ SND_SOC_DAPM_INPUT("VIINPUT"),
+
SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -4297,6 +4519,7 @@ static int tavil_get_channel_map(struct snd_soc_dai *dai,
case AIF1_CAP:
case AIF2_CAP:
case AIF3_CAP:
+ case AIF4_VIFEED:
if (!tx_slot || !tx_num) {
dev_err(tavil->dev, "%s: Invalid tx_slot 0x%pK or tx_num 0x%pK\n",
__func__, tx_slot, tx_num);
@@ -4653,6 +4876,22 @@ static int tavil_prepare(struct snd_pcm_substream *substream,
return 0;
}
+static int tavil_vi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(dai->codec);
+
+ dev_dbg(tavil->dev, "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n",
+ __func__, dai->name, dai->id, params_rate(params),
+ params_channels(params));
+
+ tavil->dai[dai->id].rate = params_rate(params);
+ tavil->dai[dai->id].bit_width = 32;
+
+ return 0;
+}
+
static int tavil_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -4726,6 +4965,12 @@ static struct snd_soc_dai_ops tavil_dai_ops = {
.get_channel_map = tavil_get_channel_map,
};
+static struct snd_soc_dai_ops tavil_vi_dai_ops = {
+ .hw_params = tavil_vi_hw_params,
+ .set_channel_map = tavil_set_channel_map,
+ .get_channel_map = tavil_get_channel_map,
+};
+
static struct snd_soc_dai_driver tavil_dai[] = {
{
.name = "tavil_rx1",
@@ -4825,6 +5070,20 @@ static struct snd_soc_dai_driver tavil_dai[] = {
},
.ops = &tavil_dai_ops,
},
+ {
+ .name = "tavil_vifeedback",
+ .id = AIF4_VIFEED,
+ .capture = {
+ .stream_name = "VIfeed",
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_48000,
+ .formats = WCD934X_FORMATS_S16_S24_S32_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &tavil_vi_dai_ops,
+ },
};
static int tavil_cdc_req_mclk_enable(struct tavil_priv *tavil,
@@ -5297,6 +5556,8 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
err_pdata:
devm_kfree(codec->dev, ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err:
return ret;
}
@@ -5308,6 +5569,8 @@ static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
control = dev_get_drvdata(codec->dev->parent);
devm_kfree(codec->dev, control->rx_chs);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
tavil_cleanup_irqs(tavil);
return 0;
diff --git a/sound/soc/msm/msm-audio-pinctrl.c b/sound/soc/msm/msm-audio-pinctrl.c
index d30b0c40f993..2b30271500eb 100644
--- a/sound/soc/msm/msm-audio-pinctrl.c
+++ b/sound/soc/msm/msm-audio-pinctrl.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -200,28 +200,40 @@ int msm_gpioset_initialize(enum pinctrl_client client,
err:
/* Free up memory allocated for gpio set combinations */
for (i = 0; i < gpioset_info[client].gpiosets_max; i++) {
- if (NULL != gpioset_info[client].gpiosets[i])
+ if (gpioset_info[client].gpiosets[i] != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets[i]);
+ gpioset_info[client].gpiosets[i] = NULL;
+ }
}
- if (NULL != gpioset_info[client].gpiosets)
+ if (gpioset_info[client].gpiosets != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets);
+ gpioset_info[client].gpiosets = NULL;
+ }
/* Free up memory allocated for gpio set combinations */
for (i = 0; i < gpioset_info[client].gpiosets_comb_max; i++) {
- if (NULL != gpioset_info[client].gpiosets_comb_names[i])
+ if (gpioset_info[client].gpiosets_comb_names[i] != NULL) {
devm_kfree(dev,
gpioset_info[client].gpiosets_comb_names[i]);
+ gpioset_info[client].gpiosets_comb_names[i] = NULL;
+ }
}
- if (NULL != gpioset_info[client].gpiosets_comb_names)
+ if (gpioset_info[client].gpiosets_comb_names != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets_comb_names);
+ gpioset_info[client].gpiosets_comb_names = NULL;
+ }
/* Free up memory allocated for handles to pinctrl states */
- if (NULL != pinctrl_info[client].cdc_lines)
+ if (pinctrl_info[client].cdc_lines != NULL) {
devm_kfree(dev, pinctrl_info[client].cdc_lines);
+ pinctrl_info[client].cdc_lines = NULL;
+ }
/* Free up memory allocated for counter of gpio sets */
- if (NULL != gpioset_info[client].gpioset_state)
+ if (gpioset_info[client].gpioset_state != NULL) {
devm_kfree(dev, gpioset_info[client].gpioset_state);
+ gpioset_info[client].gpioset_state = NULL;
+ }
success:
return ret;
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index 763854061966..4d2347aabb25 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -2042,32 +2042,6 @@ static struct snd_soc_ops msm_wcn_ops = {
.hw_params = msm_wcn_hw_params,
};
-static int msm_get_ll_qos_val(struct snd_pcm_runtime *runtime)
-{
- int usecs;
-
- /* take 10% of period time as the deadline */
- usecs = (100000 / runtime->rate) * runtime->period_size;
- usecs += ((100000 % runtime->rate) * runtime->period_size) /
- runtime->rate;
-
- return usecs;
-}
-
-static int msm_mm5_prepare(struct snd_pcm_substream *substream)
-{
- if (pm_qos_request_active(&substream->latency_pm_qos_req))
- pm_qos_remove_request(&substream->latency_pm_qos_req);
- pm_qos_add_request(&substream->latency_pm_qos_req,
- PM_QOS_CPU_DMA_LATENCY,
- msm_get_ll_qos_val(substream->runtime));
- return 0;
-}
-
-static struct snd_soc_ops msm_mm5_ops = {
- .prepare = msm_mm5_prepare,
-};
-
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm_common_dai_links[] = {
/* FrontEnd DAI Links */
@@ -2300,7 +2274,6 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
- .ops = &msm_mm5_ops,
},
{
.name = "Listen 1 Audio Service",
@@ -2717,6 +2690,19 @@ static struct snd_soc_dai_link msm_tasha_fe_dai_links[] = {
};
static struct snd_soc_dai_link msm_tavil_fe_dai_links[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_vifeedback",
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ops = &msm_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
/* Ultrasound RX DAI Link */
{
.name = "SLIMBUS_2 Hostless Playback",